Revision 8f0605cc tpm/tpm_passthrough.c
b/tpm/tpm_passthrough.c | ||
---|---|---|
27 | 27 |
#include "qemu-common.h" |
28 | 28 |
#include "qapi/error.h" |
29 | 29 |
#include "qemu/sockets.h" |
30 |
#include "backends/tpm.h" |
|
30 | 31 |
#include "tpm_int.h" |
31 | 32 |
#include "hw/hw.h" |
32 | 33 |
#include "hw/pc.h" |
... | ... | |
43 | 44 |
do { } while (0) |
44 | 45 |
#endif |
45 | 46 |
|
46 |
/* data structures */ |
|
47 |
#define TYPE_TPM_PASSTHROUGH "tpm-passthrough" |
|
48 |
#define TPM_PASSTHROUGH(obj) \ |
|
49 |
OBJECT_CHECK(TPMPassthruState, (obj), TYPE_TPM_PASSTHROUGH) |
|
47 | 50 |
|
51 |
/* data structures */ |
|
48 | 52 |
typedef struct TPMPassthruThreadParams { |
49 | 53 |
TPMState *tpm_state; |
50 | 54 |
|
... | ... | |
53 | 57 |
} TPMPassthruThreadParams; |
54 | 58 |
|
55 | 59 |
struct TPMPassthruState { |
60 |
TPMBackend parent; |
|
61 |
|
|
56 | 62 |
TPMBackendThread tbt; |
57 | 63 |
|
58 | 64 |
TPMPassthruThreadParams tpm_thread_params; |
... | ... | |
65 | 71 |
bool had_startup_error; |
66 | 72 |
}; |
67 | 73 |
|
74 |
typedef struct TPMPassthruState TPMPassthruState; |
|
75 |
|
|
68 | 76 |
#define TPM_PASSTHROUGH_DEFAULT_DEVICE "/dev/tpm0" |
69 | 77 |
|
70 | 78 |
/* functions */ |
... | ... | |
149 | 157 |
gpointer user_data) |
150 | 158 |
{ |
151 | 159 |
TPMPassthruThreadParams *thr_parms = user_data; |
152 |
TPMPassthruState *tpm_pt = thr_parms->tb->s.tpm_pt;
|
|
160 |
TPMPassthruState *tpm_pt = TPM_PASSTHROUGH(thr_parms->tb);
|
|
153 | 161 |
TPMBackendCmd cmd = (TPMBackendCmd)data; |
154 | 162 |
|
155 | 163 |
DPRINTF("tpm_passthrough: processing command type %d\n", cmd); |
... | ... | |
176 | 184 |
*/ |
177 | 185 |
static int tpm_passthrough_startup_tpm(TPMBackend *tb) |
178 | 186 |
{ |
179 |
TPMPassthruState *tpm_pt = tb->s.tpm_pt;
|
|
187 |
TPMPassthruState *tpm_pt = TPM_PASSTHROUGH(tb);
|
|
180 | 188 |
|
181 | 189 |
/* terminate a running TPM */ |
182 | 190 |
tpm_backend_thread_end(&tpm_pt->tbt); |
183 | 191 |
|
184 | 192 |
tpm_backend_thread_create(&tpm_pt->tbt, |
185 | 193 |
tpm_passthrough_worker_thread, |
186 |
&tb->s.tpm_pt->tpm_thread_params);
|
|
194 |
&tpm_pt->tpm_thread_params); |
|
187 | 195 |
|
188 | 196 |
return 0; |
189 | 197 |
} |
190 | 198 |
|
191 | 199 |
static void tpm_passthrough_reset(TPMBackend *tb) |
192 | 200 |
{ |
193 |
TPMPassthruState *tpm_pt = tb->s.tpm_pt;
|
|
201 |
TPMPassthruState *tpm_pt = TPM_PASSTHROUGH(tb);
|
|
194 | 202 |
|
195 | 203 |
DPRINTF("tpm_passthrough: CALL TO TPM_RESET!\n"); |
196 | 204 |
|
... | ... | |
204 | 212 |
static int tpm_passthrough_init(TPMBackend *tb, TPMState *s, |
205 | 213 |
TPMRecvDataCB *recv_data_cb) |
206 | 214 |
{ |
207 |
TPMPassthruState *tpm_pt = tb->s.tpm_pt;
|
|
215 |
TPMPassthruState *tpm_pt = TPM_PASSTHROUGH(tb);
|
|
208 | 216 |
|
209 | 217 |
tpm_pt->tpm_thread_params.tpm_state = s; |
210 | 218 |
tpm_pt->tpm_thread_params.recv_data_callback = recv_data_cb; |
... | ... | |
220 | 228 |
|
221 | 229 |
static bool tpm_passthrough_get_startup_error(TPMBackend *tb) |
222 | 230 |
{ |
223 |
TPMPassthruState *tpm_pt = tb->s.tpm_pt;
|
|
231 |
TPMPassthruState *tpm_pt = TPM_PASSTHROUGH(tb);
|
|
224 | 232 |
|
225 | 233 |
return tpm_pt->had_startup_error; |
226 | 234 |
} |
... | ... | |
238 | 246 |
|
239 | 247 |
static void tpm_passthrough_deliver_request(TPMBackend *tb) |
240 | 248 |
{ |
241 |
TPMPassthruState *tpm_pt = tb->s.tpm_pt;
|
|
249 |
TPMPassthruState *tpm_pt = TPM_PASSTHROUGH(tb);
|
|
242 | 250 |
|
243 | 251 |
tpm_backend_thread_deliver_request(&tpm_pt->tbt); |
244 | 252 |
} |
245 | 253 |
|
246 | 254 |
static void tpm_passthrough_cancel_cmd(TPMBackend *tb) |
247 | 255 |
{ |
248 |
TPMPassthruState *tpm_pt = tb->s.tpm_pt;
|
|
256 |
TPMPassthruState *tpm_pt = TPM_PASSTHROUGH(tb);
|
|
249 | 257 |
int n; |
250 | 258 |
|
251 | 259 |
/* |
... | ... | |
412 | 420 |
|
413 | 421 |
static int tpm_passthrough_handle_device_opts(QemuOpts *opts, TPMBackend *tb) |
414 | 422 |
{ |
423 |
TPMPassthruState *tpm_pt = TPM_PASSTHROUGH(tb); |
|
415 | 424 |
const char *value; |
416 | 425 |
|
417 | 426 |
value = qemu_opt_get(opts, "cancel-path"); |
... | ... | |
424 | 433 |
value = TPM_PASSTHROUGH_DEFAULT_DEVICE; |
425 | 434 |
} |
426 | 435 |
|
427 |
tb->s.tpm_pt->tpm_dev = g_strdup(value);
|
|
436 |
tpm_pt->tpm_dev = g_strdup(value); |
|
428 | 437 |
|
429 |
tb->path = g_strdup(tb->s.tpm_pt->tpm_dev);
|
|
438 |
tb->path = g_strdup(tpm_pt->tpm_dev); |
|
430 | 439 |
|
431 |
tb->s.tpm_pt->tpm_fd = qemu_open(tb->s.tpm_pt->tpm_dev, O_RDWR);
|
|
432 |
if (tb->s.tpm_pt->tpm_fd < 0) {
|
|
440 |
tpm_pt->tpm_fd = qemu_open(tpm_pt->tpm_dev, O_RDWR);
|
|
441 |
if (tpm_pt->tpm_fd < 0) { |
|
433 | 442 |
error_report("Cannot access TPM device using '%s': %s\n", |
434 |
tb->s.tpm_pt->tpm_dev, strerror(errno));
|
|
443 |
tpm_pt->tpm_dev, strerror(errno)); |
|
435 | 444 |
goto err_free_parameters; |
436 | 445 |
} |
437 | 446 |
|
438 |
if (tpm_passthrough_test_tpmdev(tb->s.tpm_pt->tpm_fd)) {
|
|
447 |
if (tpm_passthrough_test_tpmdev(tpm_pt->tpm_fd)) { |
|
439 | 448 |
error_report("'%s' is not a TPM device.\n", |
440 |
tb->s.tpm_pt->tpm_dev);
|
|
449 |
tpm_pt->tpm_dev); |
|
441 | 450 |
goto err_close_tpmdev; |
442 | 451 |
} |
443 | 452 |
|
444 | 453 |
return 0; |
445 | 454 |
|
446 | 455 |
err_close_tpmdev: |
447 |
qemu_close(tb->s.tpm_pt->tpm_fd);
|
|
448 |
tb->s.tpm_pt->tpm_fd = -1;
|
|
456 |
qemu_close(tpm_pt->tpm_fd); |
|
457 |
tpm_pt->tpm_fd = -1; |
|
449 | 458 |
|
450 | 459 |
err_free_parameters: |
451 | 460 |
g_free(tb->path); |
452 | 461 |
tb->path = NULL; |
453 | 462 |
|
454 |
g_free(tb->s.tpm_pt->tpm_dev);
|
|
455 |
tb->s.tpm_pt->tpm_dev = NULL;
|
|
463 |
g_free(tpm_pt->tpm_dev); |
|
464 |
tpm_pt->tpm_dev = NULL; |
|
456 | 465 |
|
457 | 466 |
return 1; |
458 | 467 |
} |
459 | 468 |
|
460 | 469 |
static TPMBackend *tpm_passthrough_create(QemuOpts *opts, const char *id) |
461 | 470 |
{ |
462 |
TPMBackend *tb; |
|
471 |
Object *obj = object_new(TYPE_TPM_PASSTHROUGH); |
|
472 |
TPMBackend *tb = TPM_BACKEND(obj); |
|
473 |
TPMPassthruState *tpm_pt = TPM_PASSTHROUGH(tb); |
|
463 | 474 |
|
464 |
tb = g_new0(TPMBackend, 1); |
|
465 |
tb->s.tpm_pt = g_new0(TPMPassthruState, 1); |
|
466 | 475 |
tb->id = g_strdup(id); |
467 | 476 |
/* let frontend set the fe_model to proper value */ |
468 | 477 |
tb->fe_model = -1; |
... | ... | |
473 | 482 |
goto err_exit; |
474 | 483 |
} |
475 | 484 |
|
476 |
tb->s.tpm_pt->cancel_fd = tpm_passthrough_open_sysfs_cancel(tb);
|
|
477 |
if (tb->s.tpm_pt->cancel_fd < 0) {
|
|
485 |
tpm_pt->cancel_fd = tpm_passthrough_open_sysfs_cancel(tb); |
|
486 |
if (tpm_pt->cancel_fd < 0) { |
|
478 | 487 |
goto err_exit; |
479 | 488 |
} |
480 | 489 |
|
... | ... | |
482 | 491 |
|
483 | 492 |
err_exit: |
484 | 493 |
g_free(tb->id); |
485 |
g_free(tb->s.tpm_pt); |
|
486 |
g_free(tb); |
|
487 | 494 |
|
488 | 495 |
return NULL; |
489 | 496 |
} |
490 | 497 |
|
491 | 498 |
static void tpm_passthrough_destroy(TPMBackend *tb) |
492 | 499 |
{ |
493 |
TPMPassthruState *tpm_pt = tb->s.tpm_pt;
|
|
500 |
TPMPassthruState *tpm_pt = TPM_PASSTHROUGH(tb);
|
|
494 | 501 |
|
495 | 502 |
tpm_passthrough_cancel_cmd(tb); |
496 | 503 |
|
497 | 504 |
tpm_backend_thread_end(&tpm_pt->tbt); |
498 | 505 |
|
499 | 506 |
qemu_close(tpm_pt->tpm_fd); |
500 |
qemu_close(tb->s.tpm_pt->cancel_fd);
|
|
507 |
qemu_close(tpm_pt->cancel_fd); |
|
501 | 508 |
|
502 | 509 |
g_free(tb->id); |
503 | 510 |
g_free(tb->path); |
504 | 511 |
g_free(tb->cancel_path); |
505 |
g_free(tb->s.tpm_pt->tpm_dev); |
|
506 |
g_free(tb->s.tpm_pt); |
|
507 |
g_free(tb); |
|
512 |
g_free(tpm_pt->tpm_dev); |
|
508 | 513 |
} |
509 | 514 |
|
510 | 515 |
const TPMDriverOps tpm_passthrough_driver = { |
... | ... | |
522 | 527 |
.get_tpm_established_flag = tpm_passthrough_get_tpm_established_flag, |
523 | 528 |
}; |
524 | 529 |
|
530 |
static void tpm_passthrough_inst_init(Object *obj) |
|
531 |
{ |
|
532 |
} |
|
533 |
|
|
534 |
static void tpm_passthrough_inst_finalize(Object *obj) |
|
535 |
{ |
|
536 |
} |
|
537 |
|
|
538 |
static void tpm_passthrough_class_init(ObjectClass *klass, void *data) |
|
539 |
{ |
|
540 |
TPMBackendClass *tbc = TPM_BACKEND_CLASS(klass); |
|
541 |
|
|
542 |
tbc->ops = &tpm_passthrough_driver; |
|
543 |
} |
|
544 |
|
|
545 |
static const TypeInfo tpm_passthrough_info = { |
|
546 |
.name = TYPE_TPM_PASSTHROUGH, |
|
547 |
.parent = TYPE_TPM_BACKEND, |
|
548 |
.instance_size = sizeof(TPMPassthruState), |
|
549 |
.class_init = tpm_passthrough_class_init, |
|
550 |
.instance_init = tpm_passthrough_inst_init, |
|
551 |
.instance_finalize = tpm_passthrough_inst_finalize, |
|
552 |
}; |
|
553 |
|
|
525 | 554 |
static void tpm_passthrough_register(void) |
526 | 555 |
{ |
556 |
type_register_static(&tpm_passthrough_info); |
|
527 | 557 |
tpm_register_driver(&tpm_passthrough_driver); |
528 | 558 |
} |
529 | 559 |
|
Also available in: Unified diff