aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/hw/tpm_drivers.c38
-rw-r--r--src/hw/tpm_drivers.h9
-rw-r--r--src/tcgbios.c12
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;