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__device_from_vtpm(libxl__gc * gc,uint32_t domid,libxl_device_vtpm * vtpm,libxl__device * device)31 static int libxl__device_from_vtpm(libxl__gc *gc, uint32_t domid,
32                                    libxl_device_vtpm *vtpm,
33                                    libxl__device *device)
34 {
35    device->backend_devid   = vtpm->devid;
36    device->backend_domid   = vtpm->backend_domid;
37    device->backend_kind    = LIBXL__DEVICE_KIND_VTPM;
38    device->devid           = vtpm->devid;
39    device->domid           = domid;
40    device->kind            = LIBXL__DEVICE_KIND_VTPM;
41 
42    return 0;
43 }
44 
libxl__update_config_vtpm(libxl__gc * gc,libxl_device_vtpm * dst,libxl_device_vtpm * src)45 static void libxl__update_config_vtpm(libxl__gc *gc, libxl_device_vtpm *dst,
46                                       libxl_device_vtpm *src)
47 {
48     dst->devid = src->devid;
49     libxl_uuid_copy(CTX, &dst->uuid, &src->uuid);
50 }
51 
52 static LIBXL_DEFINE_UPDATE_DEVID(vtpm, "vtpm")
53 
libxl__set_xenstore_vtpm(libxl__gc * gc,uint32_t domid,libxl_device_vtpm * vtpm,flexarray_t * back,flexarray_t * front,flexarray_t * ro_front)54 static int libxl__set_xenstore_vtpm(libxl__gc *gc, uint32_t domid,
55                                     libxl_device_vtpm *vtpm,
56                                     flexarray_t *back, flexarray_t *front,
57                                     flexarray_t *ro_front)
58 {
59     flexarray_append_pair(back, "handle", GCSPRINTF("%d", vtpm->devid));
60     flexarray_append_pair(back, "uuid",
61                           GCSPRINTF(LIBXL_UUID_FMT,
62                                     LIBXL_UUID_BYTES(vtpm->uuid)));
63     flexarray_append_pair(back, "resume", "False");
64 
65     flexarray_append_pair(front, "handle", GCSPRINTF("%d", vtpm->devid));
66 
67     return 0;
68 }
69 
libxl__device_vtpm_add(libxl__egc * egc,uint32_t domid,libxl_device_vtpm * vtpm,libxl__ao_device * aodev)70 static void libxl__device_vtpm_add(libxl__egc *egc, uint32_t domid,
71                                    libxl_device_vtpm *vtpm,
72                                    libxl__ao_device *aodev)
73 {
74     libxl__device_add_async(egc, domid, &libxl__vtpm_devtype, vtpm, aodev);
75 }
76 
libxl__vtpm_from_xenstore(libxl__gc * gc,const char * libxl_path,libxl_devid devid,libxl_device_vtpm * vtpm)77 static int libxl__vtpm_from_xenstore(libxl__gc *gc, const char *libxl_path,
78                                      libxl_devid devid,
79                                      libxl_device_vtpm *vtpm)
80 {
81     int rc;
82     const char *be_path;
83     char *uuid;
84 
85     vtpm->devid = devid;
86 
87     rc = libxl__xs_read_mandatory(gc, XBT_NULL,
88                                   GCSPRINTF("%s/backend", libxl_path),
89                                   &be_path);
90     if (rc) return rc;
91 
92     rc = libxl__backendpath_parse_domid(gc, be_path, &vtpm->backend_domid);
93     if (rc) return rc;
94 
95     uuid = libxl__xs_read(gc, XBT_NULL, GCSPRINTF("%s/uuid", be_path));
96     if (uuid) {
97         if(libxl_uuid_from_string(&(vtpm->uuid), uuid)) {
98             LOGD(ERROR, vtpm->backend_domid, "%s/uuid is a malformed uuid?? "
99                                "(%s) Probably a bug!!\n", be_path, uuid);
100             return ERROR_FAIL;
101         }
102     }
103 
104     return 0;
105 }
106 
libxl_device_vtpm_getinfo(libxl_ctx * ctx,uint32_t domid,libxl_device_vtpm * vtpm,libxl_vtpminfo * vtpminfo)107 int libxl_device_vtpm_getinfo(libxl_ctx *ctx,
108                               uint32_t domid,
109                               libxl_device_vtpm *vtpm,
110                               libxl_vtpminfo *vtpminfo)
111 {
112     GC_INIT(ctx);
113     char *libxl_path, *dompath, *vtpmpath;
114     char *val;
115     int rc = 0;
116 
117     libxl_vtpminfo_init(vtpminfo);
118     dompath = libxl__xs_get_dompath(gc, domid);
119     vtpminfo->devid = vtpm->devid;
120 
121     vtpmpath = GCSPRINTF("%s/device/vtpm/%d", dompath, vtpminfo->devid);
122     libxl_path = GCSPRINTF("%s/device/vtpm/%d",
123                            libxl__xs_libxl_path(gc, domid), vtpminfo->devid);
124     vtpminfo->backend = xs_read(ctx->xsh, XBT_NULL,
125           GCSPRINTF("%s/backend", libxl_path), NULL);
126     if (!vtpminfo->backend) {
127         goto err;
128     }
129 
130     rc = libxl__backendpath_parse_domid(gc, vtpminfo->backend,
131                                         &vtpminfo->backend_id);
132     if (rc) goto exit;
133 
134     val = libxl__xs_read(gc, XBT_NULL,
135           GCSPRINTF("%s/state", vtpmpath));
136     vtpminfo->state = val ? strtoul(val, NULL, 10) : -1;
137 
138     val = libxl__xs_read(gc, XBT_NULL,
139           GCSPRINTF("%s/event-channel", vtpmpath));
140     vtpminfo->evtch = val ? strtoul(val, NULL, 10) : -1;
141 
142     val = libxl__xs_read(gc, XBT_NULL,
143           GCSPRINTF("%s/ring-ref", vtpmpath));
144     vtpminfo->rref = val ? strtoul(val, NULL, 10) : -1;
145 
146     vtpminfo->frontend = xs_read(ctx->xsh, XBT_NULL,
147           GCSPRINTF("%s/frontend", libxl_path), NULL);
148     vtpminfo->frontend_id = domid;
149 
150     val = libxl__xs_read(gc, XBT_NULL,
151           GCSPRINTF("%s/uuid", libxl_path));
152     if(val == NULL) {
153        LOGD(ERROR, domid, "%s/uuid does not exist!", vtpminfo->backend);
154        goto err;
155     }
156     if(libxl_uuid_from_string(&(vtpminfo->uuid), val)) {
157        LOGD(ERROR, domid,
158              "%s/uuid is a malformed uuid?? (%s) Probably a bug!\n",
159              vtpminfo->backend, val);
160        goto err;
161     }
162 
163     goto exit;
164 err:
165     rc = ERROR_FAIL;
166 exit:
167     GC_FREE;
168     return rc;
169 }
170 
libxl_devid_to_device_vtpm(libxl_ctx * ctx,uint32_t domid,int devid,libxl_device_vtpm * vtpm)171 int libxl_devid_to_device_vtpm(libxl_ctx *ctx,
172                                uint32_t domid,
173                                int devid,
174                                libxl_device_vtpm *vtpm)
175 {
176     GC_INIT(ctx);
177     libxl_device_vtpm *vtpms;
178     int nb, i;
179     int rc;
180 
181     vtpms = libxl__device_list(gc, &libxl__vtpm_devtype, domid, &nb);
182     if (!vtpms)
183         return ERROR_FAIL;
184 
185     libxl_device_vtpm_init(vtpm);
186     rc = 1;
187     for (i = 0; i < nb; ++i) {
188         if(devid == vtpms[i].devid) {
189             vtpm->backend_domid = vtpms[i].backend_domid;
190             vtpm->devid = vtpms[i].devid;
191             libxl_uuid_copy(ctx, &vtpm->uuid, &vtpms[i].uuid);
192             rc = 0;
193             break;
194         }
195     }
196 
197     libxl__device_list_free(&libxl__vtpm_devtype, vtpms, nb);
198     GC_FREE;
199     return rc;
200 }
201 
libxl_device_vtpm_compare(libxl_device_vtpm * d1,libxl_device_vtpm * d2)202 static int libxl_device_vtpm_compare(libxl_device_vtpm *d1,
203                                      libxl_device_vtpm *d2)
204 {
205     return COMPARE_DEVID(d1, d2);
206 }
207 
libxl_uuid_to_device_vtpm(libxl_ctx * ctx,uint32_t domid,libxl_uuid * uuid,libxl_device_vtpm * vtpm)208 int libxl_uuid_to_device_vtpm(libxl_ctx *ctx, uint32_t domid,
209                             libxl_uuid* uuid, libxl_device_vtpm *vtpm)
210 {
211     GC_INIT(ctx);
212     libxl_device_vtpm *vtpms;
213     int nb, i;
214     int rc;
215 
216     vtpms = libxl__device_list(gc, &libxl__vtpm_devtype, domid, &nb);
217     if (!vtpms)
218         return ERROR_FAIL;
219 
220     memset(vtpm, 0, sizeof (libxl_device_vtpm));
221     rc = 1;
222     for (i = 0; i < nb; ++i) {
223         if(!libxl_uuid_compare(uuid, &vtpms[i].uuid)) {
224             vtpm->backend_domid = vtpms[i].backend_domid;
225             vtpm->devid = vtpms[i].devid;
226             libxl_uuid_copy(ctx, &vtpm->uuid, &vtpms[i].uuid);
227             rc = 0;
228             break;
229         }
230     }
231 
232     libxl__device_list_free(&libxl__vtpm_devtype, vtpms, nb);
233     GC_FREE;
234     return rc;
235 }
236 
libxl_device_vtpm_update_config(libxl__gc * gc,void * d,void * s)237 static void libxl_device_vtpm_update_config(libxl__gc *gc, void *d, void *s)
238 {
239     libxl__update_config_vtpm(gc, d, s);
240 }
241 
242 LIBXL_DEFINE_DEVICE_ADD(vtpm)
243 static LIBXL_DEFINE_DEVICES_ADD(vtpm)
244 LIBXL_DEFINE_DEVICE_REMOVE(vtpm)
245 LIBXL_DEFINE_DEVICE_LIST(vtpm)
246 
247 DEFINE_DEVICE_TYPE_STRUCT(vtpm,
248     .update_config = libxl_device_vtpm_update_config,
249     .from_xenstore = (device_from_xenstore_fn_t)libxl__vtpm_from_xenstore,
250     .set_xenstore_config = (device_set_xenstore_config_fn_t)
251                            libxl__set_xenstore_vtpm,
252 );
253 
254 /*
255  * Local variables:
256  * mode: C
257  * c-basic-offset: 4
258  * indent-tabs-mode: nil
259  * End:
260  */
261 
262