summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/security/tpm/Kconfig9
-rw-r--r--src/security/vboot/vboot_logic.c17
2 files changed, 25 insertions, 1 deletions
diff --git a/src/security/tpm/Kconfig b/src/security/tpm/Kconfig
index 39134c1c71..c06150dacd 100644
--- a/src/security/tpm/Kconfig
+++ b/src/security/tpm/Kconfig
@@ -172,3 +172,12 @@ config PCR_RUNTIME_DATA
default 3
endmenu # Trusted Platform Module (tpm)
+
+config TPM_SETUP_HIBERNATE_ON_ERR
+ bool
+ depends on EC_GOOGLE_CHROMEEC
+ help
+ Select this to force a device to hibernate on the next AP shutdown when a TPM
+ setup error occurs. This will cause a cold boot of the system and offer an
+ opportunity to recover the TPM should it be hung. This is only effective if
+ the Z-State brings the power rail down.
diff --git a/src/security/vboot/vboot_logic.c b/src/security/vboot/vboot_logic.c
index ab38085f48..11983b9e1e 100644
--- a/src/security/vboot/vboot_logic.c
+++ b/src/security/vboot/vboot_logic.c
@@ -4,6 +4,7 @@
#include <assert.h>
#include <console/console.h>
#include <bootmode.h>
+#include <ec/google/chromeec/ec.h>
#include <fmap.h>
#include <security/tpm/tspi/crtm.h>
#include <security/tpm/tss/vendor/cr50/cr50.h>
@@ -271,9 +272,23 @@ void verstage_main(void)
* check the return value here because vb2api_fw_phase1 will catch
* invalid secdata and tell us what to do (=reboot). */
timestamp_add_now(TS_TPMINIT_START);
- if (vboot_setup_tpm(ctx) == TPM_SUCCESS) {
+ rv = vboot_setup_tpm(ctx);
+ if (rv == TPM_SUCCESS) {
antirollback_read_space_firmware(ctx);
antirollback_read_space_kernel(ctx);
+ } else {
+ vb2api_fail(ctx, VB2_RECOVERY_RO_TPM_S_ERROR, rv);
+ if (CONFIG(TPM_SETUP_HIBERNATE_ON_ERR) &&
+ rv == TPM_CB_COMMUNICATION_ERROR) {
+ printk(BIOS_ERR, "Failed to communicate with TPM\n"
+ "Next reboot will hibernate to reset TPM");
+ /* Command the EC to hibernate on next AP shutdown */
+ if (google_chromeec_reboot(
+ EC_REBOOT_HIBERNATE,
+ EC_REBOOT_FLAG_ON_AP_SHUTDOWN)) {
+ printk(BIOS_ERR, "Failed to get EC to schedule hibernate");
+ }
+ }
}
timestamp_add_now(TS_TPMINIT_END);