1 /*
2  * Copyright (C) 2016      SUSE Linux GmbH
3  * Author Juergen Gross <jgross@suse.com>
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU Lesser General Public License as published
7  * by the Free Software Foundation; version 2.1 only. with the special
8  * exception on linking described in file LICENSE.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU Lesser General Public License for more details.
14  */
15 
16 #include "libxl_osdeps.h"
17 
18 #include "libxl_internal.h"
19 
libxl__device_vtpm_setdefault(libxl__gc * gc,uint32_t domid,libxl_device_vtpm * vtpm,bool hotplug)20 static int libxl__device_vtpm_setdefault(libxl__gc *gc, uint32_t domid,
21                                          libxl_device_vtpm *vtpm, bool hotplug)
22 {
23     int rc;
24     if (libxl_uuid_is_nil(&vtpm->uuid)) {
25         libxl_uuid_generate(&vtpm->uuid);
26     }
27     rc = libxl__resolve_domid(gc, vtpm->backend_domname, &vtpm->backend_domid);
28     return rc;
29 }
30 
libxl__update_config_vtpm(libxl__gc * gc,libxl_device_vtpm * dst,libxl_device_vtpm * src)31 static void libxl__update_config_vtpm(libxl__gc *gc, libxl_device_vtpm *dst,
32                                       libxl_device_vtpm *src)
33 {
34     dst->devid = src->devid;
35     libxl_uuid_copy(CTX, &dst->uuid, &src->uuid);
36 }
37 
libxl__set_xenstore_vtpm(libxl__gc * gc,uint32_t domid,libxl_device_vtpm * vtpm,flexarray_t * back,flexarray_t * front,flexarray_t * ro_front)38 static int libxl__set_xenstore_vtpm(libxl__gc *gc, uint32_t domid,
39                                     libxl_device_vtpm *vtpm,
40                                     flexarray_t *back, flexarray_t *front,
41                                     flexarray_t *ro_front)
42 {
43     flexarray_append_pair(back, "handle", GCSPRINTF("%d", vtpm->devid));
44     flexarray_append_pair(back, "uuid",
45                           GCSPRINTF(LIBXL_UUID_FMT,
46                                     LIBXL_UUID_BYTES(vtpm->uuid)));
47     flexarray_append_pair(back, "resume", "False");
48 
49     flexarray_append_pair(front, "handle", GCSPRINTF("%d", vtpm->devid));
50 
51     return 0;
52 }
53 
libxl__device_vtpm_add(libxl__egc * egc,uint32_t domid,libxl_device_vtpm * vtpm,libxl__ao_device * aodev)54 static void libxl__device_vtpm_add(libxl__egc *egc, uint32_t domid,
55                                    libxl_device_vtpm *vtpm,
56                                    libxl__ao_device *aodev)
57 {
58     libxl__device_add_async(egc, domid, &libxl__vtpm_devtype, vtpm, aodev);
59 }
60 
libxl__vtpm_from_xenstore(libxl__gc * gc,const char * libxl_path,libxl_devid devid,libxl_device_vtpm * vtpm)61 static int libxl__vtpm_from_xenstore(libxl__gc *gc, const char *libxl_path,
62                                      libxl_devid devid,
63                                      libxl_device_vtpm *vtpm)
64 {
65     int rc;
66     const char *be_path;
67     char *uuid;
68 
69     vtpm->devid = devid;
70 
71     rc = libxl__xs_read_mandatory(gc, XBT_NULL,
72                                   GCSPRINTF("%s/backend", libxl_path),
73                                   &be_path);
74     if (rc) return rc;
75 
76     rc = libxl__backendpath_parse_domid(gc, be_path, &vtpm->backend_domid);
77     if (rc) return rc;
78 
79     uuid = libxl__xs_read(gc, XBT_NULL, GCSPRINTF("%s/uuid", be_path));
80     if (uuid) {
81         if(libxl_uuid_from_string(&(vtpm->uuid), uuid)) {
82             LOGD(ERROR, vtpm->backend_domid, "%s/uuid is a malformed uuid?? "
83                                "(%s) Probably a bug!!\n", be_path, uuid);
84             return ERROR_FAIL;
85         }
86     }
87 
88     return 0;
89 }
90 
libxl_device_vtpm_getinfo(libxl_ctx * ctx,uint32_t domid,const libxl_device_vtpm * vtpm,libxl_vtpminfo * vtpminfo)91 int libxl_device_vtpm_getinfo(libxl_ctx *ctx,
92                               uint32_t domid,
93                               const libxl_device_vtpm *vtpm,
94                               libxl_vtpminfo *vtpminfo)
95 {
96     GC_INIT(ctx);
97     char *libxl_path, *vtpmpath;
98     char *val;
99     int rc = 0;
100 
101     libxl_vtpminfo_init(vtpminfo);
102     vtpminfo->devid = vtpm->devid;
103 
104     vtpmpath = libxl__domain_device_frontend_path(gc, domid, vtpminfo->devid,
105                                                   LIBXL__DEVICE_KIND_VTPM);
106     libxl_path = libxl__domain_device_libxl_path(gc, domid, vtpminfo->devid,
107                                                  LIBXL__DEVICE_KIND_VTPM);
108     vtpminfo->backend = xs_read(ctx->xsh, XBT_NULL,
109           GCSPRINTF("%s/backend", libxl_path), NULL);
110     if (!vtpminfo->backend) {
111         goto err;
112     }
113 
114     rc = libxl__backendpath_parse_domid(gc, vtpminfo->backend,
115                                         &vtpminfo->backend_id);
116     if (rc) goto exit;
117 
118     val = libxl__xs_read(gc, XBT_NULL,
119           GCSPRINTF("%s/state", vtpmpath));
120     vtpminfo->state = val ? strtoul(val, NULL, 10) : -1;
121 
122     val = libxl__xs_read(gc, XBT_NULL,
123           GCSPRINTF("%s/event-channel", vtpmpath));
124     vtpminfo->evtch = val ? strtoul(val, NULL, 10) : -1;
125 
126     val = libxl__xs_read(gc, XBT_NULL,
127           GCSPRINTF("%s/ring-ref", vtpmpath));
128     vtpminfo->rref = val ? strtoul(val, NULL, 10) : -1;
129 
130     vtpminfo->frontend = xs_read(ctx->xsh, XBT_NULL,
131           GCSPRINTF("%s/frontend", libxl_path), NULL);
132     vtpminfo->frontend_id = domid;
133 
134     val = libxl__xs_read(gc, XBT_NULL,
135           GCSPRINTF("%s/uuid", libxl_path));
136     if(val == NULL) {
137        LOGD(ERROR, domid, "%s/uuid does not exist!", vtpminfo->backend);
138        goto err;
139     }
140     if(libxl_uuid_from_string(&(vtpminfo->uuid), val)) {
141        LOGD(ERROR, domid,
142              "%s/uuid is a malformed uuid?? (%s) Probably a bug!\n",
143              vtpminfo->backend, val);
144        goto err;
145     }
146 
147     goto exit;
148 err:
149     rc = ERROR_FAIL;
150 exit:
151     GC_FREE;
152     return rc;
153 }
154 
libxl_devid_to_device_vtpm(libxl_ctx * ctx,uint32_t domid,int devid,libxl_device_vtpm * vtpm)155 int libxl_devid_to_device_vtpm(libxl_ctx *ctx,
156                                uint32_t domid,
157                                int devid,
158                                libxl_device_vtpm *vtpm)
159 {
160     GC_INIT(ctx);
161     libxl_device_vtpm *vtpms;
162     int nb, i;
163     int rc;
164 
165     vtpms = libxl__device_list(gc, &libxl__vtpm_devtype, domid, &nb);
166     if (!vtpms)
167         return ERROR_FAIL;
168 
169     libxl_device_vtpm_init(vtpm);
170     rc = 1;
171     for (i = 0; i < nb; ++i) {
172         if(devid == vtpms[i].devid) {
173             vtpm->backend_domid = vtpms[i].backend_domid;
174             vtpm->devid = vtpms[i].devid;
175             libxl_uuid_copy(ctx, &vtpm->uuid, &vtpms[i].uuid);
176             rc = 0;
177             break;
178         }
179     }
180 
181     libxl__device_list_free(&libxl__vtpm_devtype, vtpms, nb);
182     GC_FREE;
183     return rc;
184 }
185 
libxl_device_vtpm_compare(const libxl_device_vtpm * d1,const libxl_device_vtpm * d2)186 static int libxl_device_vtpm_compare(const libxl_device_vtpm *d1,
187                                      const libxl_device_vtpm *d2)
188 {
189     return COMPARE_DEVID(d1, d2);
190 }
191 
libxl_uuid_to_device_vtpm(libxl_ctx * ctx,uint32_t domid,libxl_uuid * uuid,libxl_device_vtpm * vtpm)192 int libxl_uuid_to_device_vtpm(libxl_ctx *ctx, uint32_t domid,
193                             libxl_uuid* uuid, libxl_device_vtpm *vtpm)
194 {
195     GC_INIT(ctx);
196     libxl_device_vtpm *vtpms;
197     int nb, i;
198     int rc;
199 
200     vtpms = libxl__device_list(gc, &libxl__vtpm_devtype, domid, &nb);
201     if (!vtpms)
202         return ERROR_FAIL;
203 
204     memset(vtpm, 0, sizeof (libxl_device_vtpm));
205     rc = 1;
206     for (i = 0; i < nb; ++i) {
207         if(!libxl_uuid_compare(uuid, &vtpms[i].uuid)) {
208             vtpm->backend_domid = vtpms[i].backend_domid;
209             vtpm->devid = vtpms[i].devid;
210             libxl_uuid_copy(ctx, &vtpm->uuid, &vtpms[i].uuid);
211             rc = 0;
212             break;
213         }
214     }
215 
216     libxl__device_list_free(&libxl__vtpm_devtype, vtpms, nb);
217     GC_FREE;
218     return rc;
219 }
220 
libxl_device_vtpm_update_config(libxl__gc * gc,void * d,void * s)221 static void libxl_device_vtpm_update_config(libxl__gc *gc, void *d, void *s)
222 {
223     libxl__update_config_vtpm(gc, d, s);
224 }
225 
226 static LIBXL_DEFINE_UPDATE_DEVID(vtpm)
227 static LIBXL_DEFINE_DEVICE_FROM_TYPE(vtpm)
228 static LIBXL_DEFINE_DEVICES_ADD(vtpm)
229 
230 LIBXL_DEFINE_DEVICE_ADD(vtpm)
231 LIBXL_DEFINE_DEVICE_REMOVE(vtpm)
232 LIBXL_DEFINE_DEVICE_LIST(vtpm)
233 
234 DEFINE_DEVICE_TYPE_STRUCT(vtpm, VTPM,
235     .update_config = libxl_device_vtpm_update_config,
236     .from_xenstore = (device_from_xenstore_fn_t)libxl__vtpm_from_xenstore,
237     .set_xenstore_config = (device_set_xenstore_config_fn_t)
238                            libxl__set_xenstore_vtpm,
239 );
240 
241 /*
242  * Local variables:
243  * mode: C
244  * c-basic-offset: 4
245  * indent-tabs-mode: nil
246  * End:
247  */
248 
249