[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