[SeaBIOS] [PATCH v8 7/8] Add a menu item for displaying TPM diagnostics

Stefan Berger stefanb at us.ibm.com
Wed Jul 2 17:38:51 CEST 2014


This patch adds a menu item for displaying TPM diagnostics such
as timeouts and durations, and device, vendor, and revision IDs
and the display of some physical presence flags of the TPM.

Signed-off-by: Stefan Berger <stefanb at linux.vnet.ibm.com>
---
 src/Kconfig          |   8 +++
 src/hw/tpm_drivers.c |  11 ++++
 src/hw/tpm_drivers.h |   1 +
 src/tcgbios.c        | 174 ++++++++++++++++++++++++++++++++++++++++++++++++++-
 src/tcgbios.h        |   5 ++
 5 files changed, 198 insertions(+), 1 deletion(-)

diff --git a/src/Kconfig b/src/Kconfig
index 9e65449..a6e1096 100644
--- a/src/Kconfig
+++ b/src/Kconfig
@@ -418,6 +418,14 @@ menu "BIOS interfaces"
         help
             Provide TPM support along with TCG BIOS extensions
 
+    config TPM_DIAGNOSTICS
+       depends on TCGBIOS
+       bool "TPM Diagnostics menu item"
+       default n
+       help
+           Add a menu item for displaying of TPM diagnostics in case
+           of certain issues with the TPM hardware.
+
 endmenu
 
 menu "BIOS Tables"
diff --git a/src/hw/tpm_drivers.c b/src/hw/tpm_drivers.c
index 1d5a779..f7cb669 100644
--- a/src/hw/tpm_drivers.c
+++ b/src/hw/tpm_drivers.c
@@ -241,6 +241,16 @@ static u32 tis_waitrespready(enum tpmDurationType to_t)
 }
 
 
+static void tis_version_data(u16 *did, u16 *vid, u16 *rid)
+{
+    u8 locty = tis_find_active_locality();
+
+    *did = readw(TIS_REG(locty, TIS_REG_DID_VID + 2));
+    *vid = readw(TIS_REG(locty, TIS_REG_DID_VID));
+    *rid = readw(TIS_REG(locty, TIS_REG_RID));
+}
+
+
 struct tpm_driver tpm_drivers[TPM_NUM_DRIVERS] = {
     [TIS_DRIVER_IDX] =
         {
@@ -256,6 +266,7 @@ struct tpm_driver tpm_drivers[TPM_NUM_DRIVERS] = {
             .waitdatavalid = tis_waitdatavalid,
             .waitrespready = tis_waitrespready,
             .sha1threshold = 100 * 1024,
+            .get_vers_data = tis_version_data,
         },
 };
 
diff --git a/src/hw/tpm_drivers.h b/src/hw/tpm_drivers.h
index 34bb12d..f13f198 100644
--- a/src/hw/tpm_drivers.h
+++ b/src/hw/tpm_drivers.h
@@ -26,6 +26,7 @@ struct tpm_driver {
     /* the TPM will be used for buffers of sizes below the sha1threshold
        for calculating the hash */
     u32 sha1threshold;
+    void (*get_vers_data)(u16 *did, u16 *vid, u16 *rid);
 };
 
 extern struct tpm_driver tpm_drivers[];
diff --git a/src/tcgbios.c b/src/tcgbios.c
index 5be9bcd..bdeedb8 100644
--- a/src/tcgbios.c
+++ b/src/tcgbios.c
@@ -87,6 +87,15 @@ typedef struct {
     u8            tpm_working:1;
     u8            if_shutdown:1;
     u8            tpm_driver_to_use:4;
+#ifdef CONFIG_TPM_DIAGNOSTICS
+    u32           startup_error;
+    u32           selftest_error;
+    u32           physpresence_enable_error;
+    u32           physpresence_lock_error;
+    u32           get_timeouts_error;
+    u32           get_durations_error;
+    u32           sha1_error;
+#endif
 } tcpa_state_t;
 
 
@@ -403,6 +412,10 @@ determine_timeouts(void)
     dprintf(DEBUG_tcg, "TCGBIOS: Return code from TPM_GetCapability(Timeouts)"
             " = 0x%08x\n", returnCode);
 
+#ifdef CONFIG_TPM_DIAGNOSTICS
+    tcpa_state.get_timeouts_error = rc ? rc : returnCode;
+#endif
+
     if (rc || returnCode)
         goto err_exit;
 
@@ -416,6 +429,10 @@ determine_timeouts(void)
     dprintf(DEBUG_tcg, "TCGBIOS: Return code from TPM_GetCapability(Durations)"
             " = 0x%08x\n", returnCode);
 
+#ifdef CONFIG_TPM_DIAGNOSTICS
+    tcpa_state.get_durations_error = rc ? rc : returnCode;
+#endif
+
     if (rc || returnCode)
         goto err_exit;
 
@@ -471,6 +488,10 @@ tcpa_startup(void)
     dprintf(DEBUG_tcg, "Return code from TPM_Startup = 0x%08x\n",
             returnCode);
 
+#ifdef CONFIG_TPM_DIAGNOSTICS
+    tcpa_state.startup_error = rc ? rc : returnCode;
+#endif
+
     if (rc || returnCode)
         goto err_exit;
 
@@ -480,6 +501,10 @@ tcpa_startup(void)
     dprintf(DEBUG_tcg, "Return code from TPM_SelfTestFull = 0x%08x\n",
             returnCode);
 
+#ifdef CONFIG_TPM_DIAGNOSTICS
+    tcpa_state.selftest_error = rc ? rc : returnCode;
+#endif
+
     if (rc || returnCode)
         goto err_exit;
 
@@ -515,6 +540,11 @@ tcpa_leave_bios(void)
                             PhysicalPresence_CMD_ENABLE,
                             sizeof(PhysicalPresence_CMD_ENABLE),
                             NULL, 10, &returnCode, TPM_DURATION_TYPE_SHORT);
+
+#ifdef CONFIG_TPM_DIAGNOSTICS
+    tcpa_state.physpresence_enable_error = rc ? rc : returnCode;
+#endif
+
     if (rc || returnCode)
         goto err_exit;
 
@@ -522,6 +552,11 @@ tcpa_leave_bios(void)
                             PhysicalPresence_NOT_PRESENT_LOCK,
                             sizeof(PhysicalPresence_NOT_PRESENT_LOCK),
                             NULL, 10, &returnCode, TPM_DURATION_TYPE_SHORT);
+
+#ifdef CONFIG_TPM_DIAGNOSTICS
+    tcpa_state.physpresence_lock_error = rc ? rc : returnCode;
+#endif
+
     if (rc || returnCode)
         goto err_exit;
 
@@ -628,6 +663,10 @@ tpm_sha1_calc(const u8 *data, u32 length, u8 *hash)
                               &returnCode,
                               &data[offset], rest, TPM_DURATION_TYPE_SHORT);
 
+#ifdef CONFIG_TPM_DIAGNOSTICS
+    tcpa_state.sha1_error = rc ? rc : returnCode;
+#endif
+
     if (rc || returnCode)
         goto err_exit;
 
@@ -1929,6 +1968,131 @@ tcpa_process_cfg(const tpm_bios_cfg_t *cfg, int verbose)
     return rc;
 }
 
+#ifdef CONFIG_TPM_DIAGNOSTICS
+static void
+wait_for_any_key(void)
+{
+    printf("Press any key to continue.\n");
+    while (get_keystroke(1000) < 0)
+         ;
+}
+
+static void
+tcpa_display_timeouts(void)
+{
+    struct tpm_driver *td;
+    int i;
+
+    td = &tpm_drivers[tcpa_state.tpm_driver_to_use];
+
+    printf("\nTIS Timeouts : ");
+
+    if (td->timeouts == NULL) {
+        printf("not known");
+    } else {
+        for (i = 0; i < 4 ; i++)
+            printf("%d ", td->timeouts[i]);
+    }
+
+    printf("\nTPM Durations: ");
+
+    if (td->durations == NULL) {
+        printf("not known");
+    } else {
+        for (i = 0; i < 3 ; i++)
+            printf("%d ", td->durations[i]);
+    }
+    printf("\n\n");
+
+    wait_for_any_key();
+}
+
+static void
+tcpa_display_tpm_version(void)
+{
+    struct tpm_driver *td;
+    u16 did, vid, rid;
+
+    td = &tpm_drivers[tcpa_state.tpm_driver_to_use];
+
+    td->get_vers_data(&did, &vid, &rid);
+
+    printf("\nDevice ID   : 0x%x\n", did);
+    printf("Vendor ID   : 0x%x\n", vid);
+    printf("Revision ID : 0x%x\n\n", rid);
+    wait_for_any_key();
+}
+
+static void
+tcpa_display_errors(void)
+{
+    printf("\ntpm probed:  %d\n", tcpa_state.tpm_probed);
+    printf("tpm working: %d\n", tcpa_state.tpm_working);
+    printf("tpm found:   %d\n", tcpa_state.tpm_found);
+    printf("startup  error: 0x%x\n", tcpa_state.startup_error);
+    printf("selftest error: 0x%x\n", tcpa_state.selftest_error);
+    printf("get timeouts error : 0x%x\n",
+           tcpa_state.get_timeouts_error);
+    printf("get durations error: 0x%x\n",
+           tcpa_state.get_durations_error);
+    printf("get sha1 error: 0x%x\n",
+           tcpa_state.sha1_error);
+    printf("phys. presence enable error: 0x%x\n",
+           tcpa_state.physpresence_enable_error);
+    printf("phys. presence lock error  : 0x%x\n\n",
+           tcpa_state.physpresence_lock_error);
+    wait_for_any_key();
+}
+
+static void
+tcpa_display_perm_flags(void)
+{
+    struct tpm_permanent_flags pf;
+    int rc;
+
+    rc = read_permanent_flags((char *)&pf, sizeof(pf));
+    if (rc)
+        return;
+
+    printf("phys. presence lifetime lock: %d\n",
+           pf.flags[PERM_FLAG_IDX_PHYSICAL_PRESENCE_LIFETIME_LOCK]);
+    printf("phys. presence hw enable: %d\n",
+           pf.flags[PERM_FLAG_IDX_PHYSICAL_PRESENCE_HW_ENABLE]);
+    printf("phys. presence cmd enable: %d\n\n",
+           pf.flags[PERM_FLAG_IDX_PHYSICAL_PRESENCE_CMD_ENABLE]);
+    wait_for_any_key();
+}
+
+static void
+tcpa_display_stclear_flags(void)
+{
+    struct tpm_stclear_flags stcf;
+    int rc;
+
+    rc = read_stclear_flags((char *)&stcf, sizeof(stcf));
+    if (rc)
+        return;
+
+    printf("phys. presence: %d\n",
+           stcf.flags[STCLEAR_FLAG_IDX_PHYSICAL_PRESENCE]);
+    printf("phys. presence lock: %d\n",
+           stcf.flags[STCLEAR_FLAG_IDX_PHYSICAL_PRESENCE_LOCK]);
+    printf("global lock: %d\n\n",
+           stcf.flags[STCLEAR_FLAG_IDX_GLOBAL_LOCK]);
+    wait_for_any_key();
+}
+
+static void
+tcpa_display_diagnostics(void)
+{
+    tcpa_display_tpm_version();
+    tcpa_display_errors();
+    tcpa_display_timeouts();
+    tcpa_display_perm_flags();
+    tcpa_display_stclear_flags();
+}
+#endif
+
 void
 tcpa_menu(void)
 {
@@ -1955,9 +2119,12 @@ tcpa_menu(void)
                    "6. Allow installation of owner\n"
                    "7. Prevent installation of owner\n");
         } else {
-            printf("TPM is not working correctly.\n");
+            printf("TPM is not working correctly.\n\n");
         }
 
+#ifdef CONFIG_TPM_DIAGNOSTICS
+        printf("d. TPM Diagnostics\n");
+#endif
         printf("Escape for previous menu.\n");
 
         if (has_working_tpm()) {
@@ -1976,6 +2143,11 @@ tcpa_menu(void)
         case 2 ... 8:
             cfg.op = scan_code - 1;
             break;
+#ifdef CONFIG_TPM_DIAGNOSTICS
+        case 32:
+            tcpa_display_diagnostics();
+            continue;
+#endif
         default:
             continue;
         }
diff --git a/src/tcgbios.h b/src/tcgbios.h
index b01300a..3807b2f 100644
--- a/src/tcgbios.h
+++ b/src/tcgbios.h
@@ -87,6 +87,10 @@
 #define TPM_ST_DEACTIVATED               0x3
 
 
+/* TPM command error codes */
+#define TPM_INVALID_POSTINIT             0x26
+
+
 /* interrupt identifiers (al register) */
 enum irq_ids {
     TCG_StatusCheck = 0,
@@ -313,6 +317,7 @@ enum permFlagsIndex {
     PERM_FLAG_IDX_ALLOW_MAINTENANCE,
     PERM_FLAG_IDX_PHYSICAL_PRESENCE_LIFETIME_LOCK,
     PERM_FLAG_IDX_PHYSICAL_PRESENCE_HW_ENABLE,
+    PERM_FLAG_IDX_PHYSICAL_PRESENCE_CMD_ENABLE,
 };
 
 
-- 
1.8.1.4




More information about the SeaBIOS mailing list