On 01/21/2018 02:46 AM, Stefan Berger wrote: > On 01/20/2018 07:54 AM, Philippe Mathieu-Daudé wrote: >> On 01/19/2018 11:11 AM, Marc-André Lureau wrote: >>> tpm_crb is a device for TPM 2.0 Command Response Buffer (CRB) >>> Interface as defined in TCG PC Client Platform TPM Profile (PTP) >>> Specification Family “2.0” Level 00 Revision 01.03 v22. >>> >>> The PTP allows device implementation to switch between TIS and CRB >>> model at run time, but given that CRB is a simpler device to >>> implement, I chose to implement it as a different device. >>> >>> The device doesn't implement other locality than 0 for now (my laptop >>> TPM doesn't either, so I assume this isn't so bad) >>> >>> The command/reply memory region is statically allocated after the CRB >>> registers address TPM_CRB_ADDR_BASE + sizeof(struct crb_regs) (I >>> wonder if the BIOS could or should allocate it instead, or what size >>> to use, again this seems to fit well expectations) >>> >>> The PTP doesn't specify a particular bus to put the device. So I added >>> it on the system bus directly, so it could hopefully be used easily on >>> a different platform than x86. Currently, it fails to init on piix, >>> because error_on_sysbus_device() check. The check may be changed in a >>> near future, see discussion on the qemu-devel ML. >>> >>> Tested with some success with Linux upstream and Windows 10, seabios & >>> modified ovmf. The device is recognized and correctly transmit >>> command/response with passthrough & emu. However, we are missing PPI >>> ACPI part atm. >>> >>> Signed-off-by: Marc-André Lureau <marcandre.lur...@redhat.com> >>> Signed-off-by: Stefan Berger <stef...@linux.vnet.ibm.com> >>> --- >>> qapi/tpm.json | 5 +- >>> include/hw/acpi/tpm.h | 72 ++++++++ >>> include/sysemu/tpm.h | 3 + >>> hw/i386/acpi-build.c | 34 +++- >>> hw/tpm/tpm_crb.c | 327 >>> +++++++++++++++++++++++++++++++++++++ >>> default-configs/i386-softmmu.mak | 1 + >>> default-configs/x86_64-softmmu.mak | 1 + >>> hw/tpm/Makefile.objs | 1 + >>> 8 files changed, 434 insertions(+), 10 deletions(-) >>> create mode 100644 hw/tpm/tpm_crb.c >>> >>> diff --git a/qapi/tpm.json b/qapi/tpm.json >>> index 7093f268fb..d50deef5e9 100644 >>> --- a/qapi/tpm.json >>> +++ b/qapi/tpm.json >>> @@ -11,10 +11,11 @@ >>> # An enumeration of TPM models >>> # >>> # @tpm-tis: TPM TIS model >>> +# @tpm-crb: TPM CRB model (since 2.12) >>> # >>> # Since: 1.5 >>> ## >>> -{ 'enum': 'TpmModel', 'data': [ 'tpm-tis' ] } >>> +{ 'enum': 'TpmModel', 'data': [ 'tpm-tis', 'tpm-crb' ] } >>> ## >>> # @query-tpm-models: >>> @@ -28,7 +29,7 @@ >>> # Example: >>> # >>> # -> { "execute": "query-tpm-models" } >>> -# <- { "return": [ "tpm-tis" ] } >>> +# <- { "return": [ "tpm-tis", "tpm-crb" ] } >>> # >>> ## >>> { 'command': 'query-tpm-models', 'returns': ['TpmModel'] } >>> diff --git a/include/hw/acpi/tpm.h b/include/hw/acpi/tpm.h >>> index 6d516c6a7f..b0048515fa 100644 >>> --- a/include/hw/acpi/tpm.h >>> +++ b/include/hw/acpi/tpm.h >>> @@ -16,11 +16,82 @@ >>> #ifndef HW_ACPI_TPM_H >>> #define HW_ACPI_TPM_H >>> +#include "qemu/osdep.h" >>> + >>> #define TPM_TIS_ADDR_BASE 0xFED40000 >>> #define TPM_TIS_ADDR_SIZE 0x5000 >>> #define TPM_TIS_IRQ 5 >>> +struct crb_regs { >>> + union { >>> + uint32_t reg; >>> + struct { >>> + unsigned tpm_established:1; >>> + unsigned loc_assigned:1; >>> + unsigned active_locality:3; >>> + unsigned reserved:2; >>> + unsigned tpm_reg_valid_sts:1; >>> + } bits; >> I suppose this is little-endian layout, so this won't work on big-endian >> hosts. >> >> Can you add a qtest? >> >>> + } loc_state; >>> + uint32_t reserved1; >>> + uint32_t loc_ctrl; >>> + union { >>> + uint32_t reg; >>> + struct { >>> + unsigned granted:1; >>> + unsigned been_seized:1; >>> + } bits; >> >> This is unclear where you expect those bits (right/left aligned). >> >> Can you add an unnamed field to be more explicit? >> >> i.e. without using struct if left alignment expected: >> >> unsigned granted:1, been_seized:1, :30; > > > I got rid of all the bitfields and this patch here makes it work on a > ppc64 big endian and also x86_64 host: > > https://github.com/stefanberger/qemu-tpm/commit/28fc07f0d9314168986190effd6d72d9fd3972dd
Thanks! Looking at your tree, I recommend you to have a look at the "hw/registerfields.h" API, you might find it simpler when it comes to add bitfields #defines and checks, moreover when you have specs available in a parsable form, since you can easily script and auto-generate. Alistair, thinking about it I'm not sure you already have a such template available, but if you do we might add it in the scripts/modules/ directory, then I can add doc and examples. > > > Regards, > Stefan > > >> >>> + } loc_sts; >>> + uint8_t reserved2[32]; >>> + union { >>> + uint64_t reg; >>> + struct { >>> + unsigned type:4; >>> + unsigned version:4; >>> + unsigned cap_locality:1; >>> + unsigned cap_crb_idle_bypass:1; >>> + unsigned reserved1:1; >>> + unsigned cap_data_xfer_size_support:2; >>> + unsigned cap_fifo:1; >>> + unsigned cap_crb:1; >>> + unsigned cap_if_res:2; >>> + unsigned if_selector:2; >>> + unsigned if_selector_lock:1; >>> + unsigned reserved2:4; >>> + unsigned rid:8; >>> + unsigned vid:16; >>> + unsigned did:16; >>> + } bits; >>> + } intf_id; >>> + uint64_t ctrl_ext; >>> + >>> + uint32_t ctrl_req; >>> + union { >>> + uint32_t reg; >>> + struct { >>> + unsigned tpm_sts:1; >>> + unsigned tpm_idle:1; >>> + unsigned reserved:30; >> Oh here you use 'reserved' to left align. >> >>> + } bits; >>> + } ctrl_sts; >>> + uint32_t ctrl_cancel; >>> + uint32_t ctrl_start; >>> + uint32_t ctrl_int_enable; >>> + uint32_t ctrl_int_sts; >>> + uint32_t ctrl_cmd_size; >>> + uint32_t ctrl_cmd_pa_low; >>> + uint32_t ctrl_cmd_pa_high; >>> + uint32_t ctrl_rsp_size; >>> + uint64_t ctrl_rsp_pa; >>> + uint8_t reserved3[0x10]; >>> +} QEMU_PACKED; >>> + >>> +#define TPM_CRB_ADDR_BASE 0xFED40000 >>> +#define TPM_CRB_ADDR_SIZE 0x1000 >>> +#define TPM_CRB_ADDR_CTRL \ >>> + (TPM_CRB_ADDR_BASE + offsetof(struct crb_regs, ctrl_req)) >>> + >>> #define TPM_LOG_AREA_MINIMUM_SIZE (64 * 1024) >>> #define TPM_TCPA_ACPI_CLASS_CLIENT 0 >>> @@ -30,5 +101,6 @@ >>> #define TPM2_ACPI_CLASS_SERVER 1 >>> #define TPM2_START_METHOD_MMIO 6 >>> +#define TPM2_START_METHOD_CRB 7 >>> #endif /* HW_ACPI_TPM_H */ >>> diff --git a/include/sysemu/tpm.h b/include/sysemu/tpm.h >>> index ac04a9d4a2..233b1a3fc3 100644 >>> --- a/include/sysemu/tpm.h >>> +++ b/include/sysemu/tpm.h >>> @@ -46,9 +46,12 @@ typedef struct TPMIfClass { >>> } TPMIfClass; >>> #define TYPE_TPM_TIS "tpm-tis" >>> +#define TYPE_TPM_CRB "tpm-crb" >>> #define TPM_IS_TIS(chr) \ >>> object_dynamic_cast(OBJECT(chr), TYPE_TPM_TIS) >>> +#define TPM_IS_CRB(chr) \ >>> + object_dynamic_cast(OBJECT(chr), TYPE_TPM_CRB) >>> /* returns NULL unless there is exactly one TPM device */ >>> static inline TPMIf *tpm_find(void) >>> diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c >>> index dc4b2b9ffe..ed78c4ed9f 100644 >>> --- a/hw/i386/acpi-build.c >>> +++ b/hw/i386/acpi-build.c >>> @@ -2224,6 +2224,22 @@ build_dsdt(GArray *table_data, BIOSLinker >>> *linker, >>> aml_append(sb_scope, scope); >>> } >>> } >>> + >>> + if (TPM_IS_CRB(tpm_find())) { >>> + dev = aml_device("TPM"); >>> + aml_append(dev, aml_name_decl("_HID", aml_string("MSFT0101"))); >>> + crs = aml_resource_template(); >>> + aml_append(crs, aml_memory32_fixed(TPM_CRB_ADDR_BASE, >>> + TPM_CRB_ADDR_SIZE, >>> AML_READ_WRITE)); >>> + aml_append(dev, aml_name_decl("_CRS", crs)); >>> + >>> + method = aml_method("_STA", 0, AML_NOTSERIALIZED); >>> + aml_append(method, aml_return(aml_int(0x0f))); >>> + aml_append(dev, method); >>> + >>> + aml_append(sb_scope, dev); >>> + } >>> + >>> aml_append(dsdt, sb_scope); >>> /* copy AML table into ACPI tables blob and patch header >>> there */ >>> @@ -2285,18 +2301,20 @@ build_tpm2(GArray *table_data, BIOSLinker >>> *linker, GArray *tcpalog) >>> if (TPM_IS_TIS(tpm_find())) { >>> tpm2_ptr->control_area_address = cpu_to_le64(0); >>> tpm2_ptr->start_method = cpu_to_le32(TPM2_START_METHOD_MMIO); >>> - >>> - tpm2_ptr->log_area_minimum_length = >>> - cpu_to_le32(TPM_LOG_AREA_MINIMUM_SIZE); >>> - >>> - /* log area start address to be filled by Guest linker */ >>> - bios_linker_loader_add_pointer(linker, >>> - ACPI_BUILD_TABLE_FILE, log_addr_offset, log_addr_size, >>> - ACPI_BUILD_TPMLOG_FILE, 0); >>> + } else if (TPM_IS_CRB(tpm_find())) { >>> + tpm2_ptr->control_area_address = >>> cpu_to_le64(TPM_CRB_ADDR_CTRL); >>> + tpm2_ptr->start_method = cpu_to_le32(TPM2_START_METHOD_CRB); >>> } else { >>> g_warn_if_reached(); >>> } >>> + tpm2_ptr->log_area_minimum_length = >>> + cpu_to_le32(TPM_LOG_AREA_MINIMUM_SIZE); >>> + >>> + /* log area start address to be filled by Guest linker */ >>> + bios_linker_loader_add_pointer(linker, ACPI_BUILD_TABLE_FILE, >>> + log_addr_offset, log_addr_size, >>> + ACPI_BUILD_TPMLOG_FILE, 0); >>> build_header(linker, table_data, >>> (void *)tpm2_ptr, "TPM2", sizeof(*tpm2_ptr), 4, >>> NULL, NULL); >>> } >>> diff --git a/hw/tpm/tpm_crb.c b/hw/tpm/tpm_crb.c >>> new file mode 100644 >>> index 0000000000..908ca18d92 >>> --- /dev/null >>> +++ b/hw/tpm/tpm_crb.c >>> @@ -0,0 +1,327 @@ >>> +/* >>> + * tpm_crb.c - QEMU's TPM CRB interface emulator >>> + * >>> + * Copyright (c) 2017 Red Hat, Inc. >>> + * >>> + * Authors: >>> + * Marc-André Lureau <marcandre.lur...@redhat.com> >>> + * >>> + * This work is licensed under the terms of the GNU GPL, version 2 >>> or later. >>> + * See the COPYING file in the top-level directory. >>> + * >>> + * tpm_crb is a device for TPM 2.0 Command Response Buffer (CRB) >>> Interface >>> + * as defined in TCG PC Client Platform TPM Profile (PTP) Specification >>> + * Family “2.0” Level 00 Revision 01.03 v22 >>> + */ >>> + >>> +#include "qemu/osdep.h" >>> + >>> +#include "qemu-common.h" >>> +#include "qapi/error.h" >>> +#include "hw/sysbus.h" >>> +#include "exec/address-spaces.h" >>> + >>> +#include "hw/pci/pci_ids.h" >>> +#include "hw/acpi/tpm.h" >>> +#include "sysemu/tpm_backend.h" >>> +#include "tpm_int.h" >>> +#include "tpm_util.h" >>> + >>> +typedef struct CRBState { >>> + SysBusDevice parent_obj; >>> + >>> + TPMBackend *tpmbe; >>> + TPMBackendCmd cmd; >>> + struct crb_regs regs; >>> + MemoryRegion mmio; >>> + MemoryRegion cmdmem; >>> + >>> + size_t be_buffer_size; >>> +} CRBState; >>> + >>> +#define CRB(obj) OBJECT_CHECK(CRBState, (obj), TYPE_TPM_CRB) >>> + >>> +#define DEBUG_CRB 0 >>> + >>> +#define DPRINTF(fmt, ...) do { \ >>> + if (DEBUG_CRB) { \ >>> + printf(fmt, ## __VA_ARGS__); \ >>> + } \ >>> + } while (0) >>> + >>> +#define CRB_ADDR_LOC_STATE offsetof(struct crb_regs, loc_state) >>> +#define CRB_ADDR_LOC_CTRL offsetof(struct crb_regs, loc_ctrl) >>> +#define CRB_ADDR_CTRL_REQ offsetof(struct crb_regs, ctrl_req) >>> +#define CRB_ADDR_CTRL_CANCEL offsetof(struct crb_regs, ctrl_cancel) >>> +#define CRB_ADDR_CTRL_START offsetof(struct crb_regs, ctrl_start) >>> + >>> +#define CRB_INTF_TYPE_CRB_ACTIVE 0b1 >>> +#define CRB_INTF_VERSION_CRB 0b1 >>> +#define CRB_INTF_CAP_LOCALITY_0_ONLY 0b0 >>> +#define CRB_INTF_CAP_IDLE_FAST 0b0 >>> +#define CRB_INTF_CAP_XFER_SIZE_64 0b11 >>> +#define CRB_INTF_CAP_FIFO_NOT_SUPPORTED 0b0 >>> +#define CRB_INTF_CAP_CRB_SUPPORTED 0b1 >>> +#define CRB_INTF_IF_SELECTOR_CRB 0b1 >>> +#define CRB_INTF_IF_SELECTOR_UNLOCKED 0b0 >>> + >>> +#define CRB_CTRL_CMD_SIZE (TPM_CRB_ADDR_SIZE - sizeof(struct crb_regs)) >>> + >>> +enum crb_loc_ctrl { >>> + CRB_LOC_CTRL_REQUEST_ACCESS = BIT(0), >>> + CRB_LOC_CTRL_RELINQUISH = BIT(1), >>> + CRB_LOC_CTRL_SEIZE = BIT(2), >>> + CRB_LOC_CTRL_RESET_ESTABLISHMENT_BIT = BIT(3), >>> +}; >>> + >>> +enum crb_ctrl_req { >>> + CRB_CTRL_REQ_CMD_READY = BIT(0), >>> + CRB_CTRL_REQ_GO_IDLE = BIT(1), >>> +}; >>> + >>> +enum crb_start { >>> + CRB_START_INVOKE = BIT(0), >>> +}; >>> + >>> +enum crb_cancel { >>> + CRB_CANCEL_INVOKE = BIT(0), >>> +}; >>> + >>> +static const char *addr_desc(unsigned off) >>> +{ >>> + struct crb_regs crb; >>> + >>> + switch (off) { >>> +#define CASE(field) \ >>> + case offsetof(struct crb_regs, field) ... \ >>> + offsetof(struct crb_regs, field) + sizeof(crb.field) - 1: \ >>> + return G_STRINGIFY(field); >>> + CASE(loc_state); >>> + CASE(reserved1); >>> + CASE(loc_ctrl); >>> + CASE(loc_sts); >>> + CASE(reserved2); >>> + CASE(intf_id); >>> + CASE(ctrl_ext); >>> + CASE(ctrl_req); >>> + CASE(ctrl_sts); >>> + CASE(ctrl_cancel); >>> + CASE(ctrl_start); >>> + CASE(ctrl_int_enable); >>> + CASE(ctrl_int_sts); >>> + CASE(ctrl_cmd_size); >>> + CASE(ctrl_cmd_pa_low); >>> + CASE(ctrl_cmd_pa_high); >>> + CASE(ctrl_rsp_size); >>> + CASE(ctrl_rsp_pa); >>> +#undef CASE >>> + } >>> + return NULL; >>> +} >>> + >>> +static uint64_t tpm_crb_mmio_read(void *opaque, hwaddr addr, >>> + unsigned size) >>> +{ >>> + CRBState *s = CRB(opaque); >>> + DPRINTF("CRB read 0x%lx:%s len:%u\n", >>> + addr, addr_desc(addr), size); >>> + void *regs = (void *)&s->regs + addr; >>> + >>> + switch (size) { >>> + case 1: >>> + return *(uint8_t *)regs; >>> + case 2: >>> + return *(uint16_t *)regs; >>> + case 4: >>> + return *(uint32_t *)regs; >>> + default: >>> + g_return_val_if_reached(-1); >>> + } >>> +} >>> + >>> +static void tpm_crb_mmio_write(void *opaque, hwaddr addr, >>> + uint64_t val, unsigned size) >>> +{ >>> + CRBState *s = CRB(opaque); >>> + DPRINTF("CRB write 0x%lx:%s len:%u val:%lu\n", >>> + addr, addr_desc(addr), size, val); >>> + >>> + switch (addr) { >>> + case CRB_ADDR_CTRL_REQ: >>> + switch (val) { >>> + case CRB_CTRL_REQ_CMD_READY: >>> + s->regs.ctrl_sts.bits.tpm_idle = 0; >>> + break; >>> + case CRB_CTRL_REQ_GO_IDLE: >>> + s->regs.ctrl_sts.bits.tpm_idle = 1; >>> + break; >>> + } >>> + break; >>> + case CRB_ADDR_CTRL_CANCEL: >>> + if (val == CRB_CANCEL_INVOKE && s->regs.ctrl_start & >>> CRB_START_INVOKE) { >>> + tpm_backend_cancel_cmd(s->tpmbe); >>> + } >>> + break; >>> + case CRB_ADDR_CTRL_START: >>> + if (val == CRB_START_INVOKE && >>> + !(s->regs.ctrl_start & CRB_START_INVOKE)) { >>> + void *mem = memory_region_get_ram_ptr(&s->cmdmem); >>> + >>> + s->regs.ctrl_start |= CRB_START_INVOKE; >>> + s->cmd = (TPMBackendCmd) { >>> + .in = mem, >>> + .in_len = MIN(tpm_cmd_get_size(mem), >>> s->be_buffer_size), >>> + .out = mem, >>> + .out_len = s->be_buffer_size, >>> + }; >>> + >>> + tpm_backend_deliver_request(s->tpmbe, &s->cmd); >>> + } >>> + break; >>> + case CRB_ADDR_LOC_CTRL: >>> + switch (val) { >>> + case CRB_LOC_CTRL_RESET_ESTABLISHMENT_BIT: >>> + /* not loc 3 or 4 */ >>> + break; >>> + case CRB_LOC_CTRL_RELINQUISH: >>> + break; >>> + case CRB_LOC_CTRL_REQUEST_ACCESS: >>> + s->regs.loc_sts.bits.granted = 1; >>> + s->regs.loc_sts.bits.been_seized = 0; >>> + s->regs.loc_state.bits.loc_assigned = 1; >>> + s->regs.loc_state.bits.tpm_reg_valid_sts = 1; >>> + break; >>> + } >>> + break; >>> + } >>> +} >>> + >>> +static const MemoryRegionOps tpm_crb_memory_ops = { >>> + .read = tpm_crb_mmio_read, >>> + .write = tpm_crb_mmio_write, >>> + .endianness = DEVICE_LITTLE_ENDIAN, >>> + .valid = { >>> + .min_access_size = 1, >>> + .max_access_size = 4, >>> + }, >>> +}; >>> + >>> +static void tpm_crb_reset(DeviceState *dev) >>> +{ >>> + CRBState *s = CRB(dev); >>> + >>> + tpm_backend_reset(s->tpmbe); >>> + >>> + s->be_buffer_size = MIN(tpm_backend_get_buffer_size(s->tpmbe), >>> + CRB_CTRL_CMD_SIZE); >>> + >>> + s->regs = (struct crb_regs) { >>> + .intf_id.bits = { >>> + .type = CRB_INTF_TYPE_CRB_ACTIVE, >>> + .version = CRB_INTF_VERSION_CRB, >>> + .cap_locality = CRB_INTF_CAP_LOCALITY_0_ONLY, >>> + .cap_crb_idle_bypass = CRB_INTF_CAP_IDLE_FAST, >>> + .cap_data_xfer_size_support = CRB_INTF_CAP_XFER_SIZE_64, >>> + .cap_fifo = CRB_INTF_CAP_FIFO_NOT_SUPPORTED, >>> + .cap_crb = CRB_INTF_CAP_CRB_SUPPORTED, >>> + .cap_if_res = 0b0, >>> + .if_selector = CRB_INTF_IF_SELECTOR_CRB, >>> + .if_selector_lock = CRB_INTF_IF_SELECTOR_UNLOCKED, >>> + .rid = 0b0001, >>> + .vid = PCI_VENDOR_ID_IBM, >>> + .did = 0b0001, >>> + }, >>> + .ctrl_cmd_size = CRB_CTRL_CMD_SIZE, >>> + .ctrl_cmd_pa_low = TPM_CRB_ADDR_BASE + sizeof(struct crb_regs), >>> + .ctrl_rsp_size = CRB_CTRL_CMD_SIZE, >>> + .ctrl_rsp_pa = TPM_CRB_ADDR_BASE + sizeof(struct crb_regs), >>> + }; >>> + >>> + tpm_backend_startup_tpm(s->tpmbe, s->be_buffer_size); >>> +} >>> + >>> +static void tpm_crb_request_completed(TPMIf *ti, int ret) >>> +{ >>> + CRBState *s = CRB(ti); >>> + >>> + s->regs.ctrl_start &= ~CRB_START_INVOKE; >>> + if (ret != 0) { >>> + s->regs.ctrl_sts.bits.tpm_sts = 1; /* fatal error */ >>> + } >>> +} >>> + >>> +static enum TPMVersion tpm_crb_get_version(TPMIf *ti) >>> +{ >>> + CRBState *s = CRB(ti); >>> + >>> + return tpm_backend_get_tpm_version(s->tpmbe); >>> +} >>> + >>> +static const VMStateDescription vmstate_tpm_crb = { >>> + .name = "tpm-crb", >>> + .unmigratable = 1, >>> +}; >>> + >>> +static Property tpm_crb_properties[] = { >>> + DEFINE_PROP_TPMBE("tpmdev", CRBState, tpmbe), >>> + DEFINE_PROP_END_OF_LIST(), >>> +}; >>> + >>> +static void tpm_crb_realizefn(DeviceState *dev, Error **errp) >>> +{ >>> + CRBState *s = CRB(dev); >>> + SysBusDevice *sbd = SYS_BUS_DEVICE(dev); >>> + >>> + if (!tpm_find()) { >>> + error_setg(errp, "at most one TPM device is permitted"); >>> + return; >>> + } >>> + if (!s->tpmbe) { >>> + error_setg(errp, "'tpmdev' property is required"); >>> + return; >>> + } >>> + >>> + memory_region_init_io(&s->mmio, OBJECT(s), &tpm_crb_memory_ops, s, >>> + "tpm-crb-mmio", sizeof(struct crb_regs)); >>> + memory_region_init_ram(&s->cmdmem, OBJECT(s), >>> + "tpm-crb-cmd", CRB_CTRL_CMD_SIZE, errp); >>> + >>> + sysbus_init_mmio(sbd, &s->mmio); >>> + sysbus_mmio_map(sbd, 0, TPM_CRB_ADDR_BASE); >>> + /* allocate ram in bios instead? */ >>> + memory_region_add_subregion(get_system_memory(), >>> + TPM_CRB_ADDR_BASE + sizeof(struct crb_regs), &s->cmdmem); >>> +} >>> + >>> +static void tpm_crb_class_init(ObjectClass *klass, void *data) >>> +{ >>> + DeviceClass *dc = DEVICE_CLASS(klass); >>> + TPMIfClass *tc = TPM_IF_CLASS(klass); >>> + >>> + dc->realize = tpm_crb_realizefn; >>> + dc->props = tpm_crb_properties; >>> + dc->reset = tpm_crb_reset; >>> + dc->vmsd = &vmstate_tpm_crb; >>> + dc->user_creatable = true; >>> + tc->model = TPM_MODEL_TPM_CRB; >>> + tc->get_version = tpm_crb_get_version; >>> + tc->request_completed = tpm_crb_request_completed; >>> +} >>> + >>> +static const TypeInfo tpm_crb_info = { >>> + .name = TYPE_TPM_CRB, >>> + .parent = TYPE_SYS_BUS_DEVICE, >>> + .instance_size = sizeof(CRBState), >>> + .class_init = tpm_crb_class_init, >>> + .interfaces = (InterfaceInfo[]) { >>> + { TYPE_TPM_IF }, >>> + { } >>> + } >>> +}; >>> + >>> +static void tpm_crb_register(void) >>> +{ >>> + type_register_static(&tpm_crb_info); >>> +} >>> + >>> +type_init(tpm_crb_register) >>> diff --git a/default-configs/i386-softmmu.mak >>> b/default-configs/i386-softmmu.mak >>> index 95ac4b464a..ac27700e79 100644 >>> --- a/default-configs/i386-softmmu.mak >>> +++ b/default-configs/i386-softmmu.mak >>> @@ -37,6 +37,7 @@ CONFIG_APPLESMC=y >>> CONFIG_I8259=y >>> CONFIG_PFLASH_CFI01=y >>> CONFIG_TPM_TIS=$(CONFIG_TPM) >>> +CONFIG_TPM_CRB=$(CONFIG_TPM) >>> CONFIG_MC146818RTC=y >>> CONFIG_PCI_PIIX=y >>> CONFIG_WDT_IB700=y >>> diff --git a/default-configs/x86_64-softmmu.mak >>> b/default-configs/x86_64-softmmu.mak >>> index 0221236825..b2104ade19 100644 >>> --- a/default-configs/x86_64-softmmu.mak >>> +++ b/default-configs/x86_64-softmmu.mak >>> @@ -37,6 +37,7 @@ CONFIG_APPLESMC=y >>> CONFIG_I8259=y >>> CONFIG_PFLASH_CFI01=y >>> CONFIG_TPM_TIS=$(CONFIG_TPM) >>> +CONFIG_TPM_CRB=$(CONFIG_TPM) >>> CONFIG_MC146818RTC=y >>> CONFIG_PCI_PIIX=y >>> CONFIG_WDT_IB700=y >>> diff --git a/hw/tpm/Makefile.objs b/hw/tpm/Makefile.objs >>> index 7a93b24636..1dc9f8bf2c 100644 >>> --- a/hw/tpm/Makefile.objs >>> +++ b/hw/tpm/Makefile.objs >>> @@ -1,4 +1,5 @@ >>> common-obj-y += tpm_util.o >>> common-obj-$(CONFIG_TPM_TIS) += tpm_tis.o >>> +common-obj-$(CONFIG_TPM_CRB) += tpm_crb.o >>> common-obj-$(CONFIG_TPM_PASSTHROUGH) += tpm_passthrough.o >>> common-obj-$(CONFIG_TPM_EMULATOR) += tpm_emulator.o >>> >
signature.asc
Description: OpenPGP digital signature