drivers/tpm: Add tpm failure handling

Add additional failure mode logic for the TPM to enable an
automated recovery mode for GSC hangs.

BUG=b:296439237
TEST=Force the error by hard coding the return code and observe the
device entering hibernate.
BRANCH=None

Change-Id: Ieec7e9227d538130354dea8b772d0306cdda1237
Signed-off-by: Jon Murphy <jpmurphy@google.com>
Reviewed-on: https://review.coreboot.org/c/coreboot/+/77667
Reviewed-by: Eric Lai <eric_lai@quanta.corp-partner.google.com>
Reviewed-by: Julius Werner <jwerner@chromium.org>
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
This commit is contained in:
Jon Murphy 2023-09-05 11:43:14 -06:00 committed by Raul Rangel
parent db4e93ba1a
commit a2f08aa5c4
2 changed files with 25 additions and 1 deletions

View File

@ -172,3 +172,12 @@ config PCR_RUNTIME_DATA
default 3 default 3
endmenu # Trusted Platform Module (tpm) 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.

View File

@ -4,6 +4,7 @@
#include <assert.h> #include <assert.h>
#include <console/console.h> #include <console/console.h>
#include <bootmode.h> #include <bootmode.h>
#include <ec/google/chromeec/ec.h>
#include <fmap.h> #include <fmap.h>
#include <security/tpm/tspi/crtm.h> #include <security/tpm/tspi/crtm.h>
#include <security/tpm/tss/vendor/cr50/cr50.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 * check the return value here because vb2api_fw_phase1 will catch
* invalid secdata and tell us what to do (=reboot). */ * invalid secdata and tell us what to do (=reboot). */
timestamp_add_now(TS_TPMINIT_START); 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_firmware(ctx);
antirollback_read_space_kernel(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); timestamp_add_now(TS_TPMINIT_END);