tpm_crb.c 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193
  1. /*
  2. * tpm_crb.c - QEMU's TPM CRB interface emulator
  3. *
  4. * Copyright (c) 2018 Red Hat, Inc.
  5. *
  6. * Authors:
  7. * Marc-André Lureau <marcandre.lureau@redhat.com>
  8. *
  9. * This work is licensed under the terms of the GNU GPL, version 2 or later.
  10. * See the COPYING file in the top-level directory.
  11. *
  12. * tpm_crb is a device for TPM 2.0 Command Response Buffer (CRB) Interface
  13. * as defined in TCG PC Client Platform TPM Profile (PTP) Specification
  14. * Family “2.0” Level 00 Revision 01.03 v22
  15. */
  16. #include "qemu/osdep.h"
  17. #include "qemu/module.h"
  18. #include "qapi/error.h"
  19. #include "exec/address-spaces.h"
  20. #include "hw/acpi/acpi_aml_interface.h"
  21. #include "hw/acpi/tpm.h"
  22. #include "hw/qdev-properties.h"
  23. #include "hw/pci/pci_ids.h"
  24. #include "hw/acpi/tpm.h"
  25. #include "migration/vmstate.h"
  26. #include "system/tpm_backend.h"
  27. #include "system/tpm_util.h"
  28. #include "system/reset.h"
  29. #include "system/xen.h"
  30. #include "tpm_prop.h"
  31. #include "tpm_ppi.h"
  32. #include "trace.h"
  33. #include "qom/object.h"
  34. #include "tpm_crb.h"
  35. struct CRBState {
  36. DeviceState parent_obj;
  37. TPMCRBState state;
  38. /* These states are only for migration */
  39. uint32_t saved_regs[TPM_CRB_R_MAX];
  40. MemoryRegion saved_cmdmem;
  41. };
  42. typedef struct CRBState CRBState;
  43. DECLARE_INSTANCE_CHECKER(CRBState, CRB,
  44. TYPE_TPM_CRB)
  45. static void tpm_crb_none_request_completed(TPMIf *ti, int ret)
  46. {
  47. CRBState *s = CRB(ti);
  48. tpm_crb_request_completed(&s->state, ret);
  49. }
  50. static enum TPMVersion tpm_crb_none_get_version(TPMIf *ti)
  51. {
  52. CRBState *s = CRB(ti);
  53. return tpm_crb_get_version(&s->state);
  54. }
  55. /**
  56. * For migrating to an older version of QEMU
  57. */
  58. static int tpm_crb_none_pre_save(void *opaque)
  59. {
  60. CRBState *s = opaque;
  61. void *saved_cmdmem = memory_region_get_ram_ptr(&s->saved_cmdmem);
  62. tpm_crb_mem_save(&s->state, s->saved_regs, saved_cmdmem);
  63. return tpm_crb_pre_save(&s->state);
  64. }
  65. /**
  66. * For migrating from an older version of QEMU
  67. */
  68. static int tpm_crb_none_post_load(void *opaque, int version_id)
  69. {
  70. CRBState *s = opaque;
  71. void *saved_cmdmem = memory_region_get_ram_ptr(&s->saved_cmdmem);
  72. tpm_crb_mem_load(&s->state, s->saved_regs, saved_cmdmem);
  73. return 0;
  74. }
  75. static const VMStateDescription vmstate_tpm_crb_none = {
  76. .name = "tpm-crb",
  77. .pre_save = tpm_crb_none_pre_save,
  78. .post_load = tpm_crb_none_post_load,
  79. .fields = (const VMStateField[]) {
  80. VMSTATE_UINT32_ARRAY(saved_regs, CRBState, TPM_CRB_R_MAX),
  81. VMSTATE_END_OF_LIST(),
  82. }
  83. };
  84. static const Property tpm_crb_none_properties[] = {
  85. DEFINE_PROP_TPMBE("tpmdev", CRBState, state.tpmbe),
  86. DEFINE_PROP_BOOL("ppi", CRBState, state.ppi_enabled, true),
  87. };
  88. static void tpm_crb_none_reset(void *dev)
  89. {
  90. CRBState *s = CRB(dev);
  91. return tpm_crb_reset(&s->state, TPM_CRB_ADDR_BASE);
  92. }
  93. static void tpm_crb_none_realize(DeviceState *dev, Error **errp)
  94. {
  95. CRBState *s = CRB(dev);
  96. if (!tpm_find()) {
  97. error_setg(errp, "at most one TPM device is permitted");
  98. return;
  99. }
  100. if (!s->state.tpmbe) {
  101. error_setg(errp, "'tpmdev' property is required");
  102. return;
  103. }
  104. if (tpm_crb_none_get_version(TPM_IF(s)) != TPM_VERSION_2_0) {
  105. error_setg(errp, "TPM CRB only supports TPM 2.0 backends");
  106. return;
  107. }
  108. tpm_crb_init_memory(OBJECT(s), &s->state, errp);
  109. /* only used for migration */
  110. memory_region_init_ram(&s->saved_cmdmem, OBJECT(s),
  111. "tpm-crb-cmd", CRB_CTRL_CMD_SIZE, errp);
  112. memory_region_add_subregion(get_system_memory(),
  113. TPM_CRB_ADDR_BASE, &s->state.mmio);
  114. if (s->state.ppi_enabled) {
  115. memory_region_add_subregion(get_system_memory(),
  116. TPM_PPI_ADDR_BASE, &s->state.ppi.ram);
  117. }
  118. if (xen_enabled()) {
  119. tpm_crb_none_reset(dev);
  120. } else {
  121. qemu_register_reset(tpm_crb_none_reset, dev);
  122. }
  123. }
  124. static void build_tpm_crb_none_aml(AcpiDevAmlIf *adev, Aml *scope)
  125. {
  126. tpm_crb_build_aml(TPM_IF(adev), scope, TPM_CRB_ADDR_BASE, TPM_CRB_ADDR_SIZE,
  127. true);
  128. }
  129. static void tpm_crb_none_class_init(ObjectClass *klass, void *data)
  130. {
  131. DeviceClass *dc = DEVICE_CLASS(klass);
  132. TPMIfClass *tc = TPM_IF_CLASS(klass);
  133. AcpiDevAmlIfClass *adevc = ACPI_DEV_AML_IF_CLASS(klass);
  134. dc->realize = tpm_crb_none_realize;
  135. device_class_set_props(dc, tpm_crb_none_properties);
  136. dc->vmsd = &vmstate_tpm_crb_none;
  137. dc->user_creatable = true;
  138. tc->model = TPM_MODEL_TPM_CRB;
  139. tc->get_version = tpm_crb_none_get_version;
  140. tc->request_completed = tpm_crb_none_request_completed;
  141. adevc->build_dev_aml = build_tpm_crb_none_aml;
  142. set_bit(DEVICE_CATEGORY_MISC, dc->categories);
  143. }
  144. static const TypeInfo tpm_crb_none_info = {
  145. .name = TYPE_TPM_CRB,
  146. /* could be TYPE_SYS_BUS_DEVICE (or LPC etc) */
  147. .parent = TYPE_DEVICE,
  148. .instance_size = sizeof(CRBState),
  149. .class_init = tpm_crb_none_class_init,
  150. .interfaces = (InterfaceInfo[]) {
  151. { TYPE_TPM_IF },
  152. { TYPE_ACPI_DEV_AML_IF },
  153. { }
  154. }
  155. };
  156. static void tpm_crb_none_register(void)
  157. {
  158. type_register_static(&tpm_crb_none_info);
  159. }
  160. type_init(tpm_crb_none_register)