qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Qemu-devel] [PATCH] TPM: add CRB device


From: Stefan Berger
Subject: Re: [Qemu-devel] [PATCH] TPM: add CRB device
Date: Thu, 4 Jan 2018 10:58:33 -0500
User-agent: Mozilla/5.0 (X11; Linux x86_64; rv:45.0) Gecko/20100101 Thunderbird/45.4.0

On 12/22/2017 09:55 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.

When you say 'some success', you mean that a test suite wasn't passing all tests, right? I didn't run the test suite so far, but what I tested looks good to me so far.

We have one ACPI part missing in the implementation and that's this mailbox thing that allows one to send a code to the firmware that the firmware then reads and acts upon and reconfigures the TPM during the next warm-boot.

https://trustedcomputinggroup.org/wp-content/uploads/Physical-Presence-Interface_1-30_0-52.pdf

It was challenging to implement this interface 'back then' using ACPI's AML, but now it's even more low level with the programming interface.

I know we have to wait for that other patch. Nevertheless ...


Signed-off-by: Marc-André Lureau <address@hidden>
Signed-off-by: Stefan Berger <address@hidden>

---
  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                   | 325 +++++++++++++++++++++++++++++++++++++
  default-configs/i386-softmmu.mak   |   1 +
  default-configs/x86_64-softmmu.mak |   1 +
  hw/tpm/Makefile.objs               |   1 +
  8 files changed, 432 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;
+    } loc_state;
+    uint32_t reserved1;
+    uint32_t loc_ctrl;
+    union {
+        uint32_t reg;
+        struct {
+            unsigned granted:1;
+            unsigned been_seized:1;
+        } bits;
+    } 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;
+        } 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 852e02687c..4bc7b09f49 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 18b939e469..86a1aa86ba 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..d70de79459
--- /dev/null
+++ b/hw/tpm/tpm_crb.c
@@ -0,0 +1,325 @@
+/*
+ * tpm_crb.c - QEMU's TPM CRB interface emulator
+ *
+ * Copyright (c) 2017 Red Hat, Inc.
+ *
+ * Authors:
+ *   Marc-André Lureau <address@hidden>
+ *
+ * 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;
+} 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_ctrl_sts {
+    CRB_CTRL_STS_ERROR = BIT(0),
+    CRB_CTRL_STS_TPM_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), CRB_CTRL_CMD_SIZE),
+                .out = mem,
+                .out_len = CRB_CTRL_CMD_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->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, CRB_CTRL_CMD_SIZE);
+}
+
+static void tpm_crb_request_completed(TPMIf *ti)
+{
+    CRBState *s = CRB(ti);
+
+    s->regs.ctrl_start &= ~CRB_START_INVOKE;
+    /* TODO, in case of error: s->regs.ctrl_sts = CRB_CTRL_STS_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





reply via email to

[Prev in Thread] Current Thread [Next in Thread]