aboutsummaryrefslogtreecommitdiff
path: root/src/soc/amd/common
diff options
context:
space:
mode:
authorRob Barnes <robbarnes@google.com>2021-11-02 17:47:47 -0600
committerKarthik Ramasubramanian <kramasub@google.com>2021-11-22 16:30:08 +0000
commitb35acf9210ffdd458a806ddbbf7deef7aac20fcd (patch)
treeae50e227433bc5563e231339a99c1d692c619c8b /src/soc/amd/common
parent2c89d08d7eff7007b4ef48aa333085d20cd74bb9 (diff)
soc/amd/psp_verstage: Init TPM on S0i3 resume
Add option to initialize the TPM in PSP verstage during s0i3 resume. This is needed if the TPM is reset in s0i3. FSDL is handling restoring everything else, so only the minimum TPM initialization is done. Move aoac and i2c init before psp_verstrage_s0i3_resume becasue i2c needs to be ready before attempting to restore tpm. BUG=b:200578885,b:197965075 TEST=Multiple cycles of S0i3 suspend resume. ~66ms of additional delay. BRANCH=None Change-Id: Ie511928da6a8b4be62621fd2c4c31a8d1e724d48 Signed-off-by: Rob Barnes <robbarnes@google.com> Reviewed-on: https://review.coreboot.org/c/coreboot/+/58870 Tested-by: build bot (Jenkins) <no-reply@coreboot.org> Reviewed-by: Karthik Ramasubramanian <kramasub@google.com>
Diffstat (limited to 'src/soc/amd/common')
-rw-r--r--src/soc/amd/common/psp_verstage/Kconfig9
-rw-r--r--src/soc/amd/common/psp_verstage/include/psp_verstage.h3
-rw-r--r--src/soc/amd/common/psp_verstage/psp_verstage.c56
3 files changed, 62 insertions, 6 deletions
diff --git a/src/soc/amd/common/psp_verstage/Kconfig b/src/soc/amd/common/psp_verstage/Kconfig
index 834abaaa5f..6cac8b70ed 100644
--- a/src/soc/amd/common/psp_verstage/Kconfig
+++ b/src/soc/amd/common/psp_verstage/Kconfig
@@ -5,3 +5,12 @@ config PSP_VERSTAGE_CCP_DMA
Configure PSP Verstage to use Crypto Co-processor (CCP) DMA while
accessing the boot device. Select it on platforms which supports
using CCP DMA to access the boot device.
+
+config PSP_INIT_TPM_ON_S0I3_RESUME
+ bool
+ depends on TPM2 && VBOOT_STARTS_BEFORE_BOOTBLOCK
+ default VBOOT_STARTS_BEFORE_BOOTBLOCK
+ help
+ If the TPM is reset while in S0i3, it must be reinitialized
+ during s0i3 resume. This must be performed in PSP verstage since
+ coreboot is otherwise not involved with s0i3 resume.
diff --git a/src/soc/amd/common/psp_verstage/include/psp_verstage.h b/src/soc/amd/common/psp_verstage/include/psp_verstage.h
index ef8a9da951..606b6a69cd 100644
--- a/src/soc/amd/common/psp_verstage/include/psp_verstage.h
+++ b/src/soc/amd/common/psp_verstage/include/psp_verstage.h
@@ -20,6 +20,7 @@
#define POSTCODE_EARLY_INIT 0x02
#define POSTCODE_LATE_INIT 0x03
#define POSTCODE_VERSTAGE_MAIN 0x04
+#define POSTCODE_VERSTAGE_S0I3_RESUME 0x05
#define POSTCODE_SAVE_BUFFERS 0x0E
#define POSTCODE_UPDATE_BOOT_REGION 0x0F
@@ -36,6 +37,8 @@
#define POSTCODE_AMD_FW_MISSING 0xC9
#define POSTCODE_CMOS_RECOVERY 0xCA
#define POSTCODE_EARLY_INIT_ERROR 0xCB
+#define POSTCODE_INIT_TPM_FAILED 0xCC
+
#define POSTCODE_UNMAP_SPI_ROM 0xF0
#define POSTCODE_UNMAP_FCH_DEVICES 0xF1
diff --git a/src/soc/amd/common/psp_verstage/psp_verstage.c b/src/soc/amd/common/psp_verstage/psp_verstage.c
index 71f07c0417..2e3d09d3a2 100644
--- a/src/soc/amd/common/psp_verstage/psp_verstage.c
+++ b/src/soc/amd/common/psp_verstage/psp_verstage.c
@@ -12,6 +12,8 @@
#include <pc80/mc146818rtc.h>
#include <soc/iomap.h>
#include <soc/psp_transfer.h>
+#include <security/tpm/tspi.h>
+#include <security/tpm/tss.h>
#include <security/vboot/vbnv.h>
#include <security/vboot/misc.h>
#include <security/vboot/symbols.h>
@@ -206,11 +208,42 @@ static uint32_t save_buffers(struct vb2_context **ctx)
return 0;
}
+/*
+ * S0i3 resume in PSP verstage is a special case. The FSDL is restoring mostly
+ * everything, so do the minimum necessary here. Unlike normal boot, subsequent
+ * coreboot stages are not run after s0i3 verstage.
+ * If the TPM is reset in S0i3, it must be re-initialized here.
+ */
+static void psp_verstage_s0i3_resume(void)
+{
+ uint32_t rv;
+
+ post_code(POSTCODE_VERSTAGE_S0I3_RESUME);
+
+ printk(BIOS_DEBUG, "Entering PSP verstage S0i3 resume\n");
+
+ if (!CONFIG(PSP_INIT_TPM_ON_S0I3_RESUME))
+ return;
+
+ rv = tpm_setup(true);
+ if (rv != TPM_SUCCESS) {
+ printk(BIOS_ERR, "tpm_setup failed rv:%d\n", rv);
+ reboot_into_recovery(vboot_get_context(), POSTCODE_INIT_TPM_FAILED);
+ }
+
+ rv = tlcl_disable_platform_hierarchy();
+ if (rv != TPM_SUCCESS) {
+ printk(BIOS_ERR, "tlcl_disable_platform_hierarchy failed rv:%d\n", rv);
+ reboot_into_recovery(vboot_get_context(), POSTCODE_INIT_TPM_FAILED);
+ }
+}
+
void Main(void)
{
uint32_t retval;
struct vb2_context *ctx = NULL;
void *boot_dev_base;
+ uint32_t bootmode;
/*
* Do not use printk() before console_init()
@@ -247,18 +280,29 @@ void Main(void)
/* mainboard_tpm_init may check board_id, so make sure espi is ready first */
verstage_mainboard_tpm_init();
- printk(BIOS_DEBUG, "calling verstage_mainboard_early_init\n");
- verstage_mainboard_early_init();
-
- svc_write_postcode(POSTCODE_LATE_INIT);
- fch_io_enable_legacy_io();
-
printk(BIOS_DEBUG, "calling verstage_soc_aoac_init\n");
verstage_soc_aoac_init();
printk(BIOS_DEBUG, "calling verstage_soc_i2c_init\n");
verstage_soc_i2c_init();
+ /*
+ * S0i3 resume in PSP verstage is a special case, handle it separately.
+ * Make sure TPM i2c is ready first.
+ */
+ svc_get_boot_mode(&bootmode);
+ if (bootmode == PSP_BOOT_MODE_S0i3_RESUME) {
+ psp_verstage_s0i3_resume();
+ unmap_fch_devices();
+ svc_exit(0);
+ }
+
+ printk(BIOS_DEBUG, "calling verstage_mainboard_early_init\n");
+ verstage_mainboard_early_init();
+
+ svc_write_postcode(POSTCODE_LATE_INIT);
+ fch_io_enable_legacy_io();
+
printk(BIOS_DEBUG, "calling verstage_soc_spi_init\n");
verstage_soc_spi_init();