Extend TPM TIS interface to support TPM 2
Following the recent upgrade to version 1.3, extend the TPM TIS interface with capabilities introduced for support of a TPM 2. TPM TIS for TPM 2 introduced the following extensions beyond the TPM TIS 1.3 (used for TPM 1.2): - A new 32bit interface Id register was introduced. - New flags for the status (STS) register were defined. - New flags for the capability flags were defined. Support the above if a TPM TIS 1.3 for TPM 2 is used with a TPM 2 on the backend side. Support the old TPM TIS 1.3 configuration if a TPM 1.2 is being used. A subsequent patch will then determine which TPM version is being used in the backend. Signed-off-by: Stefan Berger <stefanb@linux.vnet.ibm.com> Reviewed-by: Michael S. Tsirkin <mst@redhat.com> Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
This commit is contained in:
parent
38d40ff10f
commit
116694c34a
@ -96,6 +96,20 @@ bool tpm_backend_get_tpm_established_flag(TPMBackend *s)
|
||||
return k->ops->get_tpm_established_flag(s);
|
||||
}
|
||||
|
||||
int tpm_backend_reset_tpm_established_flag(TPMBackend *s, uint8_t locty)
|
||||
{
|
||||
TPMBackendClass *k = TPM_BACKEND_GET_CLASS(s);
|
||||
|
||||
return k->ops->reset_tpm_established_flag(s, locty);
|
||||
}
|
||||
|
||||
TPMVersion tpm_backend_get_tpm_version(TPMBackend *s)
|
||||
{
|
||||
TPMBackendClass *k = TPM_BACKEND_GET_CLASS(s);
|
||||
|
||||
return k->ops->get_tpm_version(s);
|
||||
}
|
||||
|
||||
static bool tpm_backend_prop_get_opened(Object *obj, Error **errp)
|
||||
{
|
||||
TPMBackend *s = TPM_BACKEND(obj);
|
||||
|
@ -29,6 +29,7 @@ struct TPMState {
|
||||
|
||||
char *backend;
|
||||
TPMBackend *be_driver;
|
||||
TPMVersion be_tpm_version;
|
||||
};
|
||||
|
||||
#define TPM(obj) OBJECT_CHECK(TPMState, (obj), TYPE_TPM_TIS)
|
||||
|
@ -267,6 +267,13 @@ static bool tpm_passthrough_get_tpm_established_flag(TPMBackend *tb)
|
||||
return false;
|
||||
}
|
||||
|
||||
static int tpm_passthrough_reset_tpm_established_flag(TPMBackend *tb,
|
||||
uint8_t locty)
|
||||
{
|
||||
/* only a TPM 2.0 will support this */
|
||||
return 0;
|
||||
}
|
||||
|
||||
static bool tpm_passthrough_get_startup_error(TPMBackend *tb)
|
||||
{
|
||||
TPMPassthruState *tpm_pt = TPM_PASSTHROUGH(tb);
|
||||
@ -324,6 +331,11 @@ static const char *tpm_passthrough_create_desc(void)
|
||||
return "Passthrough TPM backend driver";
|
||||
}
|
||||
|
||||
static TPMVersion tpm_passthrough_get_tpm_version(TPMBackend *tb)
|
||||
{
|
||||
return TPM_VERSION_1_2;
|
||||
}
|
||||
|
||||
/*
|
||||
* A basic test of a TPM device. We expect a well formatted response header
|
||||
* (error response is fine) within one second.
|
||||
@ -540,6 +552,8 @@ static const TPMDriverOps tpm_passthrough_driver = {
|
||||
.deliver_request = tpm_passthrough_deliver_request,
|
||||
.cancel_cmd = tpm_passthrough_cancel_cmd,
|
||||
.get_tpm_established_flag = tpm_passthrough_get_tpm_established_flag,
|
||||
.reset_tpm_established_flag = tpm_passthrough_reset_tpm_established_flag,
|
||||
.get_tpm_version = tpm_passthrough_get_tpm_version,
|
||||
};
|
||||
|
||||
static void tpm_passthrough_inst_init(Object *obj)
|
||||
|
108
hw/tpm/tpm_tis.c
108
hw/tpm/tpm_tis.c
@ -17,6 +17,9 @@
|
||||
* supports version 1.3, 21 March 2013
|
||||
* In the developers menu choose the PC Client section then find the TIS
|
||||
* specification.
|
||||
*
|
||||
* TPM TIS for TPM 2 implementation following TCG PC Client Platform
|
||||
* TPM Profile (PTP) Specification, Familiy 2.0, Revision 00.43
|
||||
*/
|
||||
|
||||
#include "sysemu/tpm_backend.h"
|
||||
@ -49,6 +52,7 @@
|
||||
#define TPM_TIS_REG_INTF_CAPABILITY 0x14
|
||||
#define TPM_TIS_REG_STS 0x18
|
||||
#define TPM_TIS_REG_DATA_FIFO 0x24
|
||||
#define TPM_TIS_REG_INTERFACE_ID 0x30
|
||||
#define TPM_TIS_REG_DATA_XFIFO 0x80
|
||||
#define TPM_TIS_REG_DATA_XFIFO_END 0xbc
|
||||
#define TPM_TIS_REG_DID_VID 0xf00
|
||||
@ -57,6 +61,12 @@
|
||||
/* vendor-specific registers */
|
||||
#define TPM_TIS_REG_DEBUG 0xf90
|
||||
|
||||
#define TPM_TIS_STS_TPM_FAMILY_MASK (0x3 << 26)/* TPM 2.0 */
|
||||
#define TPM_TIS_STS_TPM_FAMILY1_2 (0 << 26) /* TPM 2.0 */
|
||||
#define TPM_TIS_STS_TPM_FAMILY2_0 (1 << 26) /* TPM 2.0 */
|
||||
#define TPM_TIS_STS_RESET_ESTABLISHMENT_BIT (1 << 25) /* TPM 2.0 */
|
||||
#define TPM_TIS_STS_COMMAND_CANCEL (1 << 24) /* TPM 2.0 */
|
||||
|
||||
#define TPM_TIS_STS_VALID (1 << 7)
|
||||
#define TPM_TIS_STS_COMMAND_READY (1 << 6)
|
||||
#define TPM_TIS_STS_TPM_GO (1 << 5)
|
||||
@ -102,15 +112,42 @@
|
||||
#endif
|
||||
|
||||
#define TPM_TIS_CAP_INTERFACE_VERSION1_3 (2 << 28)
|
||||
#define TPM_TIS_CAP_INTERFACE_VERSION1_3_FOR_TPM2_0 (3 << 28)
|
||||
#define TPM_TIS_CAP_DATA_TRANSFER_64B (3 << 9)
|
||||
#define TPM_TIS_CAP_DATA_TRANSFER_LEGACY (0 << 9)
|
||||
#define TPM_TIS_CAP_BURST_COUNT_DYNAMIC (0 << 8)
|
||||
#define TPM_TIS_CAP_INTERRUPT_LOW_LEVEL (1 << 4) /* support is mandatory */
|
||||
#define TPM_TIS_CAPABILITIES_SUPPORTED (TPM_TIS_CAP_INTERRUPT_LOW_LEVEL | \
|
||||
TPM_TIS_CAP_BURST_COUNT_DYNAMIC | \
|
||||
TPM_TIS_CAP_DATA_TRANSFER_64B | \
|
||||
TPM_TIS_CAP_INTERFACE_VERSION1_3 | \
|
||||
TPM_TIS_INTERRUPTS_SUPPORTED)
|
||||
#define TPM_TIS_CAPABILITIES_SUPPORTED1_3 \
|
||||
(TPM_TIS_CAP_INTERRUPT_LOW_LEVEL | \
|
||||
TPM_TIS_CAP_BURST_COUNT_DYNAMIC | \
|
||||
TPM_TIS_CAP_DATA_TRANSFER_64B | \
|
||||
TPM_TIS_CAP_INTERFACE_VERSION1_3 | \
|
||||
TPM_TIS_INTERRUPTS_SUPPORTED)
|
||||
|
||||
#define TPM_TIS_CAPABILITIES_SUPPORTED2_0 \
|
||||
(TPM_TIS_CAP_INTERRUPT_LOW_LEVEL | \
|
||||
TPM_TIS_CAP_BURST_COUNT_DYNAMIC | \
|
||||
TPM_TIS_CAP_DATA_TRANSFER_64B | \
|
||||
TPM_TIS_CAP_INTERFACE_VERSION1_3_FOR_TPM2_0 | \
|
||||
TPM_TIS_INTERRUPTS_SUPPORTED)
|
||||
|
||||
#define TPM_TIS_IFACE_ID_INTERFACE_TIS1_3 (0xf) /* TPM 2.0 */
|
||||
#define TPM_TIS_IFACE_ID_INTERFACE_FIFO (0x0) /* TPM 2.0 */
|
||||
#define TPM_TIS_IFACE_ID_INTERFACE_VER_FIFO (0 << 4) /* TPM 2.0 */
|
||||
#define TPM_TIS_IFACE_ID_CAP_5_LOCALITIES (1 << 8) /* TPM 2.0 */
|
||||
#define TPM_TIS_IFACE_ID_CAP_TIS_SUPPORTED (1 << 13) /* TPM 2.0 */
|
||||
#define TPM_TIS_IFACE_ID_INT_SEL_LOCK (1 << 19) /* TPM 2.0 */
|
||||
|
||||
#define TPM_TIS_IFACE_ID_SUPPORTED_FLAGS1_3 \
|
||||
(TPM_TIS_IFACE_ID_INTERFACE_TIS1_3 | \
|
||||
(~0 << 4)/* all of it is don't care */)
|
||||
|
||||
/* if backend was a TPM 2.0: */
|
||||
#define TPM_TIS_IFACE_ID_SUPPORTED_FLAGS2_0 \
|
||||
(TPM_TIS_IFACE_ID_INTERFACE_FIFO | \
|
||||
TPM_TIS_IFACE_ID_INTERFACE_VER_FIFO | \
|
||||
TPM_TIS_IFACE_ID_CAP_5_LOCALITIES | \
|
||||
TPM_TIS_IFACE_ID_CAP_TIS_SUPPORTED)
|
||||
|
||||
#define TPM_TIS_TPM_DID 0x0001
|
||||
#define TPM_TIS_TPM_VID PCI_VENDOR_ID_IBM
|
||||
@ -154,7 +191,8 @@ static void tpm_tis_show_buffer(const TPMSizedBuffer *sb, const char *string)
|
||||
|
||||
/*
|
||||
* Set the given flags in the STS register by clearing the register but
|
||||
* preserving the SELFTEST_DONE flag and then setting the new flags.
|
||||
* preserving the SELFTEST_DONE and TPM_FAMILY_MASK flags and then setting
|
||||
* the new flags.
|
||||
*
|
||||
* The SELFTEST_DONE flag is acquired from the backend that determines it by
|
||||
* peeking into TPM commands.
|
||||
@ -166,7 +204,7 @@ static void tpm_tis_show_buffer(const TPMSizedBuffer *sb, const char *string)
|
||||
*/
|
||||
static void tpm_tis_sts_set(TPMLocality *l, uint32_t flags)
|
||||
{
|
||||
l->sts &= TPM_TIS_STS_SELFTEST_DONE;
|
||||
l->sts &= TPM_TIS_STS_SELFTEST_DONE | TPM_TIS_STS_TPM_FAMILY_MASK;
|
||||
l->sts |= flags;
|
||||
}
|
||||
|
||||
@ -489,7 +527,17 @@ static uint64_t tpm_tis_mmio_read(void *opaque, hwaddr addr,
|
||||
val = tis->loc[locty].ints;
|
||||
break;
|
||||
case TPM_TIS_REG_INTF_CAPABILITY:
|
||||
val = TPM_TIS_CAPABILITIES_SUPPORTED;
|
||||
switch (s->be_tpm_version) {
|
||||
case TPM_VERSION_UNSPEC:
|
||||
val = 0;
|
||||
break;
|
||||
case TPM_VERSION_1_2:
|
||||
val = TPM_TIS_CAPABILITIES_SUPPORTED1_3;
|
||||
break;
|
||||
case TPM_VERSION_2_0:
|
||||
val = TPM_TIS_CAPABILITIES_SUPPORTED2_0;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case TPM_TIS_REG_STS:
|
||||
if (tis->active_locty == locty) {
|
||||
@ -536,6 +584,9 @@ static uint64_t tpm_tis_mmio_read(void *opaque, hwaddr addr,
|
||||
shift = 0; /* no more adjustments */
|
||||
}
|
||||
break;
|
||||
case TPM_TIS_REG_INTERFACE_ID:
|
||||
val = tis->loc[locty].iface_id;
|
||||
break;
|
||||
case TPM_TIS_REG_DID_VID:
|
||||
val = (TPM_TIS_TPM_DID << 16) | TPM_TIS_TPM_VID;
|
||||
break;
|
||||
@ -736,6 +787,25 @@ static void tpm_tis_mmio_write_intern(void *opaque, hwaddr addr,
|
||||
break;
|
||||
}
|
||||
|
||||
if (s->be_tpm_version == TPM_VERSION_2_0) {
|
||||
/* some flags that are only supported for TPM 2 */
|
||||
if (val & TPM_TIS_STS_COMMAND_CANCEL) {
|
||||
if (tis->loc[locty].state == TPM_TIS_STATE_EXECUTION) {
|
||||
/*
|
||||
* request the backend to cancel. Some backends may not
|
||||
* support it
|
||||
*/
|
||||
tpm_backend_cancel_cmd(s->be_driver);
|
||||
}
|
||||
}
|
||||
|
||||
if (val & TPM_TIS_STS_RESET_ESTABLISHMENT_BIT) {
|
||||
if (locty == 3 || locty == 4) {
|
||||
tpm_backend_reset_tpm_established_flag(s->be_driver, locty);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
val &= (TPM_TIS_STS_COMMAND_READY | TPM_TIS_STS_TPM_GO |
|
||||
TPM_TIS_STS_RESPONSE_RETRY);
|
||||
|
||||
@ -860,6 +930,13 @@ static void tpm_tis_mmio_write_intern(void *opaque, hwaddr addr,
|
||||
}
|
||||
}
|
||||
break;
|
||||
case TPM_TIS_REG_INTERFACE_ID:
|
||||
if (val & TPM_TIS_IFACE_ID_INT_SEL_LOCK) {
|
||||
for (l = 0; l < TPM_TIS_NUM_LOCALITIES; l++) {
|
||||
tis->loc[l].iface_id |= TPM_TIS_IFACE_ID_INT_SEL_LOCK;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@ -894,6 +971,8 @@ static void tpm_tis_reset(DeviceState *dev)
|
||||
TPMTISEmuState *tis = &s->s.tis;
|
||||
int c;
|
||||
|
||||
s->be_tpm_version = tpm_backend_get_tpm_version(s->be_driver);
|
||||
|
||||
tpm_backend_reset(s->be_driver);
|
||||
|
||||
tis->active_locty = TPM_TIS_NO_LOCALITY;
|
||||
@ -902,7 +981,18 @@ static void tpm_tis_reset(DeviceState *dev)
|
||||
|
||||
for (c = 0; c < TPM_TIS_NUM_LOCALITIES; c++) {
|
||||
tis->loc[c].access = TPM_TIS_ACCESS_TPM_REG_VALID_STS;
|
||||
tis->loc[c].sts = 0;
|
||||
switch (s->be_tpm_version) {
|
||||
case TPM_VERSION_UNSPEC:
|
||||
break;
|
||||
case TPM_VERSION_1_2:
|
||||
tis->loc[c].sts = TPM_TIS_STS_TPM_FAMILY1_2;
|
||||
tis->loc[c].iface_id = TPM_TIS_IFACE_ID_SUPPORTED_FLAGS1_3;
|
||||
break;
|
||||
case TPM_VERSION_2_0:
|
||||
tis->loc[c].sts = TPM_TIS_STS_TPM_FAMILY2_0;
|
||||
tis->loc[c].iface_id = TPM_TIS_IFACE_ID_SUPPORTED_FLAGS2_0;
|
||||
break;
|
||||
}
|
||||
tis->loc[c].inte = TPM_TIS_INT_POLARITY_LOW_LEVEL;
|
||||
tis->loc[c].ints = 0;
|
||||
tis->loc[c].state = TPM_TIS_STATE_IDLE;
|
||||
|
@ -42,6 +42,7 @@ typedef struct TPMLocality {
|
||||
TPMTISState state;
|
||||
uint8_t access;
|
||||
uint32_t sts;
|
||||
uint32_t iface_id;
|
||||
uint32_t inte;
|
||||
uint32_t ints;
|
||||
|
||||
|
@ -20,6 +20,12 @@ int tpm_config_parse(QemuOptsList *opts_list, const char *optarg);
|
||||
int tpm_init(void);
|
||||
void tpm_cleanup(void);
|
||||
|
||||
typedef enum TPMVersion {
|
||||
TPM_VERSION_UNSPEC = 0,
|
||||
TPM_VERSION_1_2 = 1,
|
||||
TPM_VERSION_2_0 = 2,
|
||||
} TPMVersion;
|
||||
|
||||
#define TYPE_TPM_TIS "tpm-tis"
|
||||
|
||||
static inline bool tpm_find(void)
|
||||
|
@ -88,6 +88,10 @@ struct TPMDriverOps {
|
||||
void (*cancel_cmd)(TPMBackend *t);
|
||||
|
||||
bool (*get_tpm_established_flag)(TPMBackend *t);
|
||||
|
||||
int (*reset_tpm_established_flag)(TPMBackend *t, uint8_t locty);
|
||||
|
||||
TPMVersion (*get_tpm_version)(TPMBackend *t);
|
||||
};
|
||||
|
||||
|
||||
@ -191,6 +195,15 @@ void tpm_backend_cancel_cmd(TPMBackend *s);
|
||||
*/
|
||||
bool tpm_backend_get_tpm_established_flag(TPMBackend *s);
|
||||
|
||||
/**
|
||||
* tpm_backend_reset_tpm_established_flag:
|
||||
* @s: the backend
|
||||
* @locty: the locality number
|
||||
*
|
||||
* Reset the TPM establishment flag.
|
||||
*/
|
||||
int tpm_backend_reset_tpm_established_flag(TPMBackend *s, uint8_t locty);
|
||||
|
||||
/**
|
||||
* tpm_backend_open:
|
||||
* @s: the backend to open
|
||||
@ -201,6 +214,16 @@ bool tpm_backend_get_tpm_established_flag(TPMBackend *s);
|
||||
*/
|
||||
void tpm_backend_open(TPMBackend *s, Error **errp);
|
||||
|
||||
/**
|
||||
* tpm_backend_get_tpm_version:
|
||||
* @s: the backend to call into
|
||||
*
|
||||
* Get the TPM Version that is emulated at the backend.
|
||||
*
|
||||
* Returns TPMVersion.
|
||||
*/
|
||||
TPMVersion tpm_backend_get_tpm_version(TPMBackend *s);
|
||||
|
||||
TPMBackend *qemu_find_tpm(const char *id);
|
||||
|
||||
const TPMDriverOps *tpm_get_backend_driver(const char *type);
|
||||
|
Loading…
Reference in New Issue
Block a user