diff options
-rw-r--r-- | src/hw/tpm_drivers.c | 38 | ||||
-rw-r--r-- | src/hw/tpm_drivers.h | 9 | ||||
-rw-r--r-- | src/tcgbios.c | 12 |
3 files changed, 51 insertions, 8 deletions
diff --git a/src/hw/tpm_drivers.c b/src/hw/tpm_drivers.c index 08fd101..a137e62 100644 --- a/src/hw/tpm_drivers.c +++ b/src/hw/tpm_drivers.c @@ -23,6 +23,7 @@ struct tpm_driver { u32 *durations; void (*set_timeouts)(u32 timeouts[4], u32 durations[3]); u32 (*probe)(void); + TPMVersion (*get_tpm_version)(void); u32 (*init)(void); u32 (*activate)(u8 locty); u32 (*ready)(void); @@ -56,7 +57,6 @@ static const u32 tpm_default_durations[3] = { static u32 tpm_default_dur[3]; static u32 tpm_default_to[4]; - /* if device is not there, return '0', '1' otherwise */ static u32 tis_probe(void) { @@ -69,9 +69,39 @@ static u32 tis_probe(void) if ((didvid != 0) && (didvid != 0xffffffff)) rc = 1; + /* TPM 2 has an interface register */ + u32 ifaceid = readl(TIS_REG(0, TIS_REG_IFACE_ID)); + + if ((ifaceid & 0xf) != 0xf) { + if ((ifaceid & 0xf) == 1) { + /* CRB is active; no TIS */ + return 0; + } + if ((ifaceid & (1 << 13)) == 0) { + /* TIS cannot be selected */ + return 0; + } + /* write of 0 to bits 17-18 selects TIS */ + writel(TIS_REG(0, TIS_REG_IFACE_ID), 0); + /* since we only support TIS, we lock it */ + writel(TIS_REG(0, TIS_REG_IFACE_ID), (1 << 19)); + } + return rc; } +static TPMVersion tis_get_tpm_version(void) +{ + /* TPM 2 has an interface register */ + u32 ifaceid = readl(TIS_REG(0, TIS_REG_IFACE_ID)); + + if ((ifaceid & 0xf) == 0) { + /* TPM 2 */ + return TPM_VERSION_2; + } + return TPM_VERSION_1_2; +} + static u32 tis_init(void) { if (!CONFIG_TCGBIOS) @@ -323,7 +353,7 @@ struct tpm_driver tpm_drivers[TPM_NUM_DRIVERS] = { static u8 TPMHW_driver_to_use = TPM_INVALID_DRIVER; -int +TPMVersion tpmhw_probe(void) { unsigned int i; @@ -332,10 +362,10 @@ tpmhw_probe(void) if (td->probe() != 0) { td->init(); TPMHW_driver_to_use = i; - return 0; + return tis_get_tpm_version(); } } - return -1; + return TPM_VERSION_NONE; } int diff --git a/src/hw/tpm_drivers.h b/src/hw/tpm_drivers.h index 15a60af..52c7a15 100644 --- a/src/hw/tpm_drivers.h +++ b/src/hw/tpm_drivers.h @@ -10,7 +10,13 @@ enum tpmDurationType { TPM_DURATION_TYPE_LONG, }; -int tpmhw_probe(void); +typedef u8 TPMVersion; + +#define TPM_VERSION_NONE 0 +#define TPM_VERSION_1_2 1 +#define TPM_VERSION_2 2 + +TPMVersion tpmhw_probe(void); int tpmhw_is_present(void); struct tpm_req_header; int tpmhw_transmit(u8 locty, struct tpm_req_header *req, @@ -33,6 +39,7 @@ void tpmhw_set_timeouts(u32 timeouts[4], u32 durations[3]); #define TIS_REG_INTF_CAPABILITY 0x14 #define TIS_REG_STS 0x18 #define TIS_REG_DATA_FIFO 0x24 +#define TIS_REG_IFACE_ID 0x30 #define TIS_REG_DID_VID 0xf00 #define TIS_REG_RID 0xf04 diff --git a/src/tcgbios.c b/src/tcgbios.c index 7077426..0559083 100644 --- a/src/tcgbios.c +++ b/src/tcgbios.c @@ -62,6 +62,8 @@ struct { static int TPM_has_physical_presence; +static TPMVersion TPM_version; + static struct tcpa_descriptor_rev2 * find_tcpa_by_rsdp(struct rsdp_descriptor *rsdp) { @@ -498,11 +500,15 @@ tpm_setup(void) if (!CONFIG_TCGBIOS) return; - int ret = tpmhw_probe(); - if (ret) + TPM_version = tpmhw_probe(); + if (TPM_version == TPM_VERSION_NONE) return; - ret = tpm_tcpa_probe(); + dprintf(DEBUG_tcg, + "TCGBIOS: Detected a TPM %s.\n", + (TPM_version == TPM_VERSION_1_2) ? "1.2" : "2"); + + int ret = tpm_tcpa_probe(); if (ret) return; |