tpm_crb_common.c 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264
  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/qdev-properties.h"
  21. #include "hw/pci/pci_ids.h"
  22. #include "hw/acpi/tpm.h"
  23. #include "migration/vmstate.h"
  24. #include "system/tpm_backend.h"
  25. #include "system/tpm_util.h"
  26. #include "tpm_prop.h"
  27. #include "tpm_ppi.h"
  28. #include "trace.h"
  29. #include "qom/object.h"
  30. #include "tpm_crb.h"
  31. static uint8_t tpm_crb_get_active_locty(TPMCRBState *s, uint32_t *regs)
  32. {
  33. if (!ARRAY_FIELD_EX32(regs, CRB_LOC_STATE, locAssigned)) {
  34. return TPM_CRB_NO_LOCALITY;
  35. }
  36. return ARRAY_FIELD_EX32(regs, CRB_LOC_STATE, activeLocality);
  37. }
  38. static void tpm_crb_mmio_write(void *opaque, hwaddr addr,
  39. uint64_t val, unsigned size)
  40. {
  41. TPMCRBState *s = opaque;
  42. uint8_t locty = addr >> 12;
  43. uint32_t *regs;
  44. void *mem;
  45. trace_tpm_crb_mmio_write(addr, size, val);
  46. regs = memory_region_get_ram_ptr(&s->mmio);
  47. mem = &regs[R_CRB_DATA_BUFFER];
  48. assert(regs);
  49. /* receive TPM command bytes in DATA_BUFFER */
  50. if (addr >= A_CRB_DATA_BUFFER) {
  51. assert(addr + size <= TPM_CRB_ADDR_SIZE);
  52. assert(size <= sizeof(val));
  53. memcpy(mem + addr - A_CRB_DATA_BUFFER, &val, size);
  54. memory_region_set_dirty(&s->mmio, addr, size);
  55. return;
  56. }
  57. /* otherwise we are doing MMIO writes */
  58. switch (addr) {
  59. case A_CRB_CTRL_REQ:
  60. switch (val) {
  61. case CRB_CTRL_REQ_CMD_READY:
  62. ARRAY_FIELD_DP32(regs, CRB_CTRL_STS,
  63. tpmIdle, 0);
  64. break;
  65. case CRB_CTRL_REQ_GO_IDLE:
  66. ARRAY_FIELD_DP32(regs, CRB_CTRL_STS,
  67. tpmIdle, 1);
  68. break;
  69. }
  70. break;
  71. case A_CRB_CTRL_CANCEL:
  72. if (val == CRB_CANCEL_INVOKE &&
  73. regs[R_CRB_CTRL_START] & CRB_START_INVOKE) {
  74. tpm_backend_cancel_cmd(s->tpmbe);
  75. }
  76. break;
  77. case A_CRB_CTRL_START:
  78. if (val == CRB_START_INVOKE &&
  79. !(regs[R_CRB_CTRL_START] & CRB_START_INVOKE) &&
  80. tpm_crb_get_active_locty(s, regs) == locty) {
  81. regs[R_CRB_CTRL_START] |= CRB_START_INVOKE;
  82. s->cmd = (TPMBackendCmd) {
  83. .in = mem,
  84. .in_len = MIN(tpm_cmd_get_size(mem), s->be_buffer_size),
  85. .out = mem,
  86. .out_len = s->be_buffer_size,
  87. };
  88. tpm_backend_deliver_request(s->tpmbe, &s->cmd);
  89. }
  90. break;
  91. case A_CRB_LOC_CTRL:
  92. switch (val) {
  93. case CRB_LOC_CTRL_RESET_ESTABLISHMENT_BIT:
  94. /* not loc 3 or 4 */
  95. break;
  96. case CRB_LOC_CTRL_RELINQUISH:
  97. ARRAY_FIELD_DP32(regs, CRB_LOC_STATE,
  98. locAssigned, 0);
  99. ARRAY_FIELD_DP32(regs, CRB_LOC_STS,
  100. Granted, 0);
  101. break;
  102. case CRB_LOC_CTRL_REQUEST_ACCESS:
  103. ARRAY_FIELD_DP32(regs, CRB_LOC_STS,
  104. Granted, 1);
  105. ARRAY_FIELD_DP32(regs, CRB_LOC_STS,
  106. beenSeized, 0);
  107. ARRAY_FIELD_DP32(regs, CRB_LOC_STATE,
  108. locAssigned, 1);
  109. break;
  110. }
  111. break;
  112. }
  113. memory_region_set_dirty(&s->mmio, 0, A_CRB_DATA_BUFFER);
  114. }
  115. const MemoryRegionOps tpm_crb_memory_ops = {
  116. .write = tpm_crb_mmio_write,
  117. .endianness = DEVICE_LITTLE_ENDIAN,
  118. .valid = {
  119. .min_access_size = 1,
  120. .max_access_size = 4,
  121. },
  122. };
  123. void tpm_crb_request_completed(TPMCRBState *s, int ret)
  124. {
  125. uint32_t *regs = memory_region_get_ram_ptr(&s->mmio);
  126. assert(regs);
  127. regs[R_CRB_CTRL_START] &= ~CRB_START_INVOKE;
  128. if (ret != 0) {
  129. ARRAY_FIELD_DP32(regs, CRB_CTRL_STS,
  130. tpmSts, 1); /* fatal error */
  131. }
  132. memory_region_set_dirty(&s->mmio, 0, TPM_CRB_ADDR_SIZE);
  133. }
  134. enum TPMVersion tpm_crb_get_version(TPMCRBState *s)
  135. {
  136. return tpm_backend_get_tpm_version(s->tpmbe);
  137. }
  138. int tpm_crb_pre_save(TPMCRBState *s)
  139. {
  140. tpm_backend_finish_sync(s->tpmbe);
  141. return 0;
  142. }
  143. void tpm_crb_reset(TPMCRBState *s, uint64_t baseaddr)
  144. {
  145. uint32_t *regs = memory_region_get_ram_ptr(&s->mmio);
  146. assert(regs);
  147. if (s->ppi_enabled) {
  148. tpm_ppi_reset(&s->ppi);
  149. }
  150. tpm_backend_reset(s->tpmbe);
  151. memset(regs, 0, TPM_CRB_ADDR_SIZE);
  152. ARRAY_FIELD_DP32(regs, CRB_LOC_STATE,
  153. tpmRegValidSts, 1);
  154. ARRAY_FIELD_DP32(regs, CRB_LOC_STATE,
  155. tpmEstablished, 1);
  156. ARRAY_FIELD_DP32(regs, CRB_CTRL_STS,
  157. tpmIdle, 1);
  158. ARRAY_FIELD_DP32(regs, CRB_INTF_ID,
  159. InterfaceType, CRB_INTF_TYPE_CRB_ACTIVE);
  160. ARRAY_FIELD_DP32(regs, CRB_INTF_ID,
  161. InterfaceVersion, CRB_INTF_VERSION_CRB);
  162. ARRAY_FIELD_DP32(regs, CRB_INTF_ID,
  163. CapLocality, CRB_INTF_CAP_LOCALITY_0_ONLY);
  164. ARRAY_FIELD_DP32(regs, CRB_INTF_ID,
  165. CapCRBIdleBypass, CRB_INTF_CAP_IDLE_FAST);
  166. ARRAY_FIELD_DP32(regs, CRB_INTF_ID,
  167. CapDataXferSizeSupport, CRB_INTF_CAP_XFER_SIZE_64);
  168. ARRAY_FIELD_DP32(regs, CRB_INTF_ID,
  169. CapFIFO, CRB_INTF_CAP_FIFO_NOT_SUPPORTED);
  170. ARRAY_FIELD_DP32(regs, CRB_INTF_ID,
  171. CapCRB, CRB_INTF_CAP_CRB_SUPPORTED);
  172. ARRAY_FIELD_DP32(regs, CRB_INTF_ID,
  173. InterfaceSelector, CRB_INTF_IF_SELECTOR_CRB);
  174. ARRAY_FIELD_DP32(regs, CRB_INTF_ID,
  175. RID, 0b0000);
  176. ARRAY_FIELD_DP32(regs, CRB_INTF_ID2,
  177. VID, PCI_VENDOR_ID_IBM);
  178. baseaddr += A_CRB_DATA_BUFFER;
  179. regs[R_CRB_CTRL_CMD_SIZE] = CRB_CTRL_CMD_SIZE;
  180. regs[R_CRB_CTRL_CMD_LADDR] = (uint32_t)baseaddr;
  181. regs[R_CRB_CTRL_CMD_HADDR] = (uint32_t)(baseaddr >> 32);
  182. regs[R_CRB_CTRL_RSP_SIZE] = CRB_CTRL_CMD_SIZE;
  183. regs[R_CRB_CTRL_RSP_LADDR] = (uint32_t)baseaddr;
  184. regs[R_CRB_CTRL_RSP_HADDR] = (uint32_t)(baseaddr >> 32);
  185. s->be_buffer_size = MIN(tpm_backend_get_buffer_size(s->tpmbe),
  186. CRB_CTRL_CMD_SIZE);
  187. if (tpm_backend_startup_tpm(s->tpmbe, s->be_buffer_size) < 0) {
  188. exit(1);
  189. }
  190. memory_region_rom_device_set_romd(&s->mmio, true);
  191. memory_region_set_dirty(&s->mmio, 0, TPM_CRB_ADDR_SIZE);
  192. }
  193. void tpm_crb_init_memory(Object *obj, TPMCRBState *s, Error **errp)
  194. {
  195. uint64_t page_size = qemu_real_host_page_size();
  196. memory_region_init_rom_device_nomigrate(&s->mmio, obj, &tpm_crb_memory_ops,
  197. s, "tpm-crb-mem", ROUND_UP(TPM_CRB_ADDR_SIZE, page_size), errp);
  198. if (s->ppi_enabled) {
  199. tpm_ppi_init_memory(&s->ppi, obj);
  200. }
  201. }
  202. void tpm_crb_mem_save(TPMCRBState *s, uint32_t *saved_regs, void *saved_cmdmem)
  203. {
  204. uint32_t *regs = memory_region_get_ram_ptr(&s->mmio);
  205. memcpy(saved_regs, regs, A_CRB_DATA_BUFFER);
  206. memcpy(saved_cmdmem, &regs[R_CRB_DATA_BUFFER], CRB_CTRL_CMD_SIZE);
  207. }
  208. void tpm_crb_mem_load(TPMCRBState *s, const uint32_t *saved_regs,
  209. const void *saved_cmdmem)
  210. {
  211. uint32_t *regs = memory_region_get_ram_ptr(&s->mmio);
  212. memcpy(regs, saved_regs, A_CRB_DATA_BUFFER);
  213. memcpy(&regs[R_CRB_DATA_BUFFER], saved_cmdmem, CRB_CTRL_CMD_SIZE);
  214. }
  215. void tpm_crb_build_aml(TPMIf *ti, Aml *scope, uint32_t baseaddr, uint32_t size,
  216. bool build_ppi)
  217. {
  218. Aml *dev, *crs;
  219. dev = aml_device("TPM");
  220. aml_append(dev, aml_name_decl("_HID", aml_string("MSFT0101")));
  221. aml_append(dev, aml_name_decl("_STR", aml_string("TPM 2.0 Device")));
  222. aml_append(dev, aml_name_decl("_UID", aml_int(1)));
  223. aml_append(dev, aml_name_decl("_STA", aml_int(0xF)));
  224. crs = aml_resource_template();
  225. aml_append(crs, aml_memory32_fixed(baseaddr, size, AML_READ_WRITE));
  226. aml_append(dev, aml_name_decl("_CRS", crs));
  227. if (build_ppi) {
  228. tpm_build_ppi_acpi(ti, dev);
  229. }
  230. aml_append(scope, dev);
  231. }