]> xenbits.xensource.com Git - seabios.git/commitdiff
tpm: Extend TPM TIS with TPM 2 support.
authorStefan Berger <stefanb@linux.vnet.ibm.com>
Tue, 2 Feb 2016 18:09:09 +0000 (13:09 -0500)
committerKevin O'Connor <kevin@koconnor.net>
Sat, 6 Feb 2016 01:47:37 +0000 (20:47 -0500)
Extend the probing of the interface with TPM 2 specifics.

Use the new interface ID register of the TIS to check whether
a TPM 1.2 or a TPM 2 is underneath.

We select the TIS if possible and lock it so we can issue commands
during S3 for example and prevent the OS from changing to CRB type
of interface.

The register is described in table 13 here:

http://www.trustedcomputinggroup.org/resources/pc_client_platform_tpm_profile_ptp_specification

Signed-off-by: Stefan Berger <stefanb@linux.vnet.ibm.com>
src/hw/tpm_drivers.c
src/hw/tpm_drivers.h
src/tcgbios.c

index 08fd1010df26ef1f025874e6a8cbf6a24c1492a7..a137e62a11107f8f97e46ef85d8f7887fe7b8a15 100644 (file)
@@ -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
index 15a60af27dc9cb3c50d1d7df1f1199f278960eb5..52c7a158630cdf5ce959b2b40a09d313502bdbd8 100644 (file)
@@ -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
 
index 707742649b75c5868ac01feb7235ca9fd338f55c..0559083f5abf450de5bddcaf32aeb6e67203ac02 100644 (file)
@@ -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;