@@ -46,6 +46,7 @@ operating system.
QEMU files related to TPM CRB interface:
- ``hw/tpm/tpm_crb.c``
- ``hw/tpm/tpm_crb_common.c``
+ - ``hw/tpm/tpm_crb_sysbus.c``
SPAPR interface
---------------
@@ -49,6 +49,7 @@ struct TPMIfClass {
#define TYPE_TPM_TIS_ISA "tpm-tis"
#define TYPE_TPM_TIS_SYSBUS "tpm-tis-device"
#define TYPE_TPM_CRB "tpm-crb"
+#define TYPE_TPM_CRB_SYSBUS "tpm-crb-device"
#define TYPE_TPM_SPAPR "tpm-spapr"
#define TYPE_TPM_TIS_I2C "tpm-tis-i2c"
@@ -58,6 +59,8 @@ struct TPMIfClass {
object_dynamic_cast(OBJECT(chr), TYPE_TPM_TIS_SYSBUS)
#define TPM_IS_CRB(chr) \
object_dynamic_cast(OBJECT(chr), TYPE_TPM_CRB)
+#define TPM_IS_CRB_SYSBUS(chr) \
+ object_dynamic_cast(OBJECT(chr), TYPE_TPM_CRB_SYSBUS)
#define TPM_IS_SPAPR(chr) \
object_dynamic_cast(OBJECT(chr), TYPE_TPM_SPAPR)
#define TPM_IS_TIS_I2C(chr) \
@@ -31,6 +31,7 @@
#include "hw/pci/pci_bus.h"
#include "hw/pci/pci_bridge.h"
#include "qemu/cutils.h"
+#include "qom/object.h"
static GArray *build_alloc_array(void)
{
@@ -2218,7 +2219,7 @@ void build_tpm2(GArray *table_data, BIOSLinker *linker, GArray *tcpalog,
{
uint8_t start_method_params[12] = {};
unsigned log_addr_offset;
- uint64_t control_area_start_address;
+ uint64_t baseaddr, control_area_start_address;
TPMIf *tpmif = tpm_find();
uint32_t start_method;
AcpiTable table = { .sig = "TPM2", .rev = 4,
@@ -2236,6 +2237,10 @@ void build_tpm2(GArray *table_data, BIOSLinker *linker, GArray *tcpalog,
} else if (TPM_IS_CRB(tpmif)) {
control_area_start_address = TPM_CRB_ADDR_CTRL;
start_method = TPM2_START_METHOD_CRB;
+ } else if (TPM_IS_CRB_SYSBUS(tpmif)) {
+ baseaddr = object_property_get_uint(OBJECT(tpmif), "x-baseaddr", NULL);
+ control_area_start_address = baseaddr + A_CRB_CTRL_REQ;
+ start_method = TPM2_START_METHOD_CRB;
} else {
g_assert_not_reached();
}
@@ -2955,6 +2955,7 @@ static void virt_machine_class_init(ObjectClass *oc, void *data)
machine_class_allow_dynamic_sysbus_dev(mc, TYPE_VFIO_PLATFORM);
#ifdef CONFIG_TPM
machine_class_allow_dynamic_sysbus_dev(mc, TYPE_TPM_TIS_SYSBUS);
+ machine_class_allow_dynamic_sysbus_dev(mc, TYPE_TPM_CRB_SYSBUS);
#endif
mc->block_default_type = IF_VIRTIO;
mc->no_cdrom = 1;
@@ -493,6 +493,7 @@ static const BindingEntry bindings[] = {
#endif
#ifdef CONFIG_TPM
TYPE_BINDING(TYPE_TPM_TIS_SYSBUS, add_tpm_tis_fdt_node),
+ TYPE_BINDING(TYPE_TPM_CRB_SYSBUS, no_fdt_node),
#endif
TYPE_BINDING(TYPE_RAMFB_DEVICE, no_fdt_node),
TYPE_BINDING("", NULL), /* last element */
@@ -1114,6 +1114,7 @@ static void loongarch_class_init(ObjectClass *oc, void *data)
machine_class_allow_dynamic_sysbus_dev(mc, TYPE_RAMFB_DEVICE);
#ifdef CONFIG_TPM
machine_class_allow_dynamic_sysbus_dev(mc, TYPE_TPM_TIS_SYSBUS);
+ machine_class_allow_dynamic_sysbus_dev(mc, TYPE_TPM_CRB_SYSBUS);
#endif
}
@@ -1702,6 +1702,7 @@ static void virt_machine_class_init(ObjectClass *oc, void *data)
machine_class_allow_dynamic_sysbus_dev(mc, TYPE_RAMFB_DEVICE);
#ifdef CONFIG_TPM
machine_class_allow_dynamic_sysbus_dev(mc, TYPE_TPM_TIS_SYSBUS);
+ machine_class_allow_dynamic_sysbus_dev(mc, TYPE_TPM_CRB_SYSBUS);
#endif
new file mode 100644
@@ -0,0 +1,162 @@
+/*
+ * tpm_crb_sysbus.c - QEMU's TPM CRB interface emulator
+ *
+ * Copyright (c) 2018 Red Hat, Inc.
+ *
+ * Authors:
+ * Marc-André Lureau <marcandre.lureau@redhat.com>
+ * Joelle van Dyne <j@getutm.app>
+ *
+ * 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 "hw/acpi/acpi_aml_interface.h"
+#include "hw/acpi/tpm.h"
+#include "hw/qdev-properties.h"
+#include "migration/vmstate.h"
+#include "tpm_prop.h"
+#include "hw/sysbus.h"
+#include "qapi/visitor.h"
+#include "qom/object.h"
+#include "sysemu/tpm_util.h"
+#include "trace.h"
+#include "tpm_crb.h"
+
+struct TPMCRBStateSysBus {
+ /*< private >*/
+ SysBusDevice parent_obj;
+
+ /*< public >*/
+ TPMCRBState state;
+ uint64_t baseaddr;
+ uint64_t size;
+};
+
+OBJECT_DECLARE_SIMPLE_TYPE(TPMCRBStateSysBus, TPM_CRB_SYSBUS)
+
+static void tpm_crb_sysbus_request_completed(TPMIf *ti, int ret)
+{
+ TPMCRBStateSysBus *s = TPM_CRB_SYSBUS(ti);
+
+ return tpm_crb_request_completed(&s->state, ret);
+}
+
+static enum TPMVersion tpm_crb_sysbus_get_tpm_version(TPMIf *ti)
+{
+ TPMCRBStateSysBus *s = TPM_CRB_SYSBUS(ti);
+
+ return tpm_crb_get_version(&s->state);
+}
+
+static int tpm_crb_sysbus_pre_save(void *opaque)
+{
+ TPMCRBStateSysBus *s = opaque;
+
+ return tpm_crb_pre_save(&s->state);
+}
+
+static const VMStateDescription vmstate_tpm_crb_sysbus = {
+ .name = "tpm-crb-sysbus",
+ .pre_save = tpm_crb_sysbus_pre_save,
+ .fields = (VMStateField[]) {
+ VMSTATE_END_OF_LIST(),
+ }
+};
+
+static Property tpm_crb_sysbus_properties[] = {
+ DEFINE_PROP_TPMBE("tpmdev", TPMCRBStateSysBus, state.tpmbe),
+ DEFINE_PROP_UINT64("x-baseaddr", TPMCRBStateSysBus,
+ baseaddr, TPM_CRB_ADDR_BASE),
+ DEFINE_PROP_UINT64("x-size", TPMCRBStateSysBus,
+ size, TPM_CRB_ADDR_SIZE),
+ DEFINE_PROP_END_OF_LIST(),
+};
+
+static void tpm_crb_sysbus_initfn(Object *obj)
+{
+ TPMCRBStateSysBus *s = TPM_CRB_SYSBUS(obj);
+
+ tpm_crb_init_memory(obj, &s->state, NULL);
+
+ vmstate_register_ram(&s->state.mmio, DEVICE(obj));
+
+ sysbus_init_mmio(SYS_BUS_DEVICE(obj), &s->state.mmio);
+}
+
+static void tpm_crb_sysbus_reset(DeviceState *dev)
+{
+ TPMCRBStateSysBus *s = TPM_CRB_SYSBUS(dev);
+
+ return tpm_crb_reset(&s->state, s->baseaddr);
+}
+
+static void tpm_crb_sysbus_realizefn(DeviceState *dev, Error **errp)
+{
+ TPMCRBStateSysBus *s = TPM_CRB_SYSBUS(dev);
+
+ if (!tpm_find()) {
+ error_setg(errp, "at most one TPM device is permitted");
+ return;
+ }
+
+ if (!s->state.tpmbe) {
+ error_setg(errp, "'tpmdev' property is required");
+ return;
+ }
+
+ if (tpm_crb_sysbus_get_tpm_version(TPM_IF(s)) != TPM_VERSION_2_0) {
+ error_setg(errp, "TPM CRB only supports TPM 2.0 backends");
+ return;
+ }
+}
+
+static void build_tpm_crb_sysbus_aml(AcpiDevAmlIf *adev, Aml *scope)
+{
+ TPMCRBStateSysBus *s = TPM_CRB_SYSBUS(adev);
+
+ tpm_crb_build_aml(TPM_IF(adev), scope, s->baseaddr, s->size, false);
+}
+
+static void tpm_crb_sysbus_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ TPMIfClass *tc = TPM_IF_CLASS(klass);
+ AcpiDevAmlIfClass *adevc = ACPI_DEV_AML_IF_CLASS(klass);
+
+ device_class_set_props(dc, tpm_crb_sysbus_properties);
+ dc->vmsd = &vmstate_tpm_crb_sysbus;
+ tc->model = TPM_MODEL_TPM_CRB;
+ dc->realize = tpm_crb_sysbus_realizefn;
+ dc->user_creatable = true;
+ dc->reset = tpm_crb_sysbus_reset;
+ tc->request_completed = tpm_crb_sysbus_request_completed;
+ tc->get_version = tpm_crb_sysbus_get_tpm_version;
+ set_bit(DEVICE_CATEGORY_MISC, dc->categories);
+ adevc->build_dev_aml = build_tpm_crb_sysbus_aml;
+}
+
+static const TypeInfo tpm_crb_sysbus_info = {
+ .name = TYPE_TPM_CRB_SYSBUS,
+ .parent = TYPE_SYS_BUS_DEVICE,
+ .instance_size = sizeof(TPMCRBStateSysBus),
+ .instance_init = tpm_crb_sysbus_initfn,
+ .class_init = tpm_crb_sysbus_class_init,
+ .interfaces = (InterfaceInfo[]) {
+ { TYPE_TPM_IF },
+ { TYPE_ACPI_DEV_AML_IF },
+ { }
+ }
+};
+
+static void tpm_crb_sysbus_register(void)
+{
+ type_register_static(&tpm_crb_sysbus_info);
+}
+
+type_init(tpm_crb_sysbus_register)
@@ -5,6 +5,7 @@ config ARM_VIRT
imply VFIO_AMD_XGBE
imply VFIO_PLATFORM
imply VFIO_XGMAC
+ imply TPM_CRB_SYSBUS
imply TPM_TIS_SYSBUS
imply TPM_TIS_I2C
imply NVDIMM
@@ -6,6 +6,7 @@ config LOONGARCH_VIRT
imply PCI_DEVICES
imply NVDIMM
imply TPM_TIS_SYSBUS
+ imply TPM_CRB_SYSBUS
select SERIAL
select VIRTIO_PCI
select PLATFORM_BUS
@@ -29,6 +29,7 @@ config RISCV_VIRT
imply PCI_DEVICES
imply VIRTIO_VGA
imply TEST_DEVICES
+ imply TPM_CRB_SYSBUS
imply TPM_TIS_SYSBUS
select RISCV_NUMA
select GOLDFISH_RTC
@@ -25,6 +25,11 @@ config TPM_CRB
depends on TPM && PC
select TPM_BACKEND
+config TPM_CRB_SYSBUS
+ bool
+ depends on TPM
+ select TPM_BACKEND
+
config TPM_SPAPR
bool
default y
@@ -5,6 +5,9 @@ system_ss.add(when: 'CONFIG_TPM_TIS_SYSBUS', if_true: files('tpm-sysbus.c'))
system_ss.add(when: 'CONFIG_TPM_TIS_I2C', if_true: files('tpm_tis_i2c.c'))
system_ss.add(when: 'CONFIG_TPM_CRB', if_true: files('tpm_crb.c'))
system_ss.add(when: 'CONFIG_TPM_CRB', if_true: files('tpm_crb_common.c'))
+system_ss.add(when: 'CONFIG_TPM_CRB_SYSBUS', if_true: files('tpm_crb_sysbus.c'))
+system_ss.add(when: 'CONFIG_TPM_CRB_SYSBUS', if_true: files('tpm_crb_common.c'))
+system_ss.add(when: 'CONFIG_TPM_CRB_SYSBUS', if_true: files('tpm-sysbus.c'))
system_ss.add(when: 'CONFIG_TPM_TIS', if_true: files('tpm_ppi.c'))
system_ss.add(when: 'CONFIG_TPM_CRB', if_true: files('tpm_ppi.c'))