diff options
author | Karthikeyan Ramasubramanian <kramasub@google.com> | 2023-07-14 16:56:04 -0600 |
---|---|---|
committer | Martin L Roth <gaumless@gmail.com> | 2023-08-04 20:52:20 +0000 |
commit | 2c828436a7ac491cc97294b5c94d319ef822b7a3 (patch) | |
tree | cd0d8b79567691d43dc5bca6c86ad2e058d7cb1c /src/soc/amd | |
parent | 97e57cfd51578dee7d3e29d5e39f31855294ed4e (diff) |
soc/amd/phoenix: Add SVC call to inject v2 hash tables
On mainboards using Phoenix SoC with PSP verstage enabled, to
accommodate growing number of PSP binaries, multiple smaller hash tables
are introduced. Also some hash tables are in V2 format identifying the
concerned PSP binaries using UUID. Add SVC calls to support multiple
hash tables with different versions.
BUG=b:277292697
TEST=Build and boot to OS in Myst with PSP verstage enabled. Ensure that
all the hash tables are injected successfully. Ensure that PSP validated
all the signed PSP binaries using the injected hash tables successfully.
Change-Id: I64e1b1af55cb95067403e89da4fb31bec704cd4f
Signed-off-by: Karthikeyan Ramasubramanian <kramasub@google.com>
Reviewed-on: https://review.coreboot.org/c/coreboot/+/76588
Reviewed-by: Martin Roth <martin.roth@amd.corp-partner.google.com>
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Diffstat (limited to 'src/soc/amd')
-rw-r--r-- | src/soc/amd/phoenix/psp_verstage/chipset.c | 121 | ||||
-rw-r--r-- | src/soc/amd/phoenix/psp_verstage/svc.c | 7 | ||||
-rw-r--r-- | src/soc/amd/phoenix/psp_verstage/svc.h | 2 |
3 files changed, 103 insertions, 27 deletions
diff --git a/src/soc/amd/phoenix/psp_verstage/chipset.c b/src/soc/amd/phoenix/psp_verstage/chipset.c index acbd55954f..cf03272b96 100644 --- a/src/soc/amd/phoenix/psp_verstage/chipset.c +++ b/src/soc/amd/phoenix/psp_verstage/chipset.c @@ -11,51 +11,40 @@ #include <security/vboot/misc.h> #include <security/vboot/vbnv.h> +#define PSP_FW_HASH_FILE_NAME(slot, id) "apu/amdfw_" slot "_hash" id /* * We can't pass pointer to hash table in the SPI. * The AMD PSP team specifically required that whole hash table * should be copied into memory before passing them to the PSP * to reduce window of TOCTOU. */ -#define MAX_NUM_HASH_ENTRIES 128 +#define MAX_NUM_HASH_ENTRIES 64 static struct psp_fw_hash_table hash_table; static struct psp_fw_entry_hash_256 hash_256[MAX_NUM_HASH_ENTRIES]; static struct psp_fw_entry_hash_384 hash_384[MAX_NUM_HASH_ENTRIES]; -void update_psp_fw_hash_table(const char *fname) +static struct psp_fw_hash_table_v2 hash_table_v2; +static struct psp_fw_entry_hash_256_v2 hash_256_v2[MAX_NUM_HASH_ENTRIES]; +static struct psp_fw_entry_hash_384_v2 hash_384_v2[MAX_NUM_HASH_ENTRIES]; + +static void update_one_psp_fw_hash_table_v1(enum verstage_cmd_id cmd, uint8_t *spi_ptr) { - void *hash_file = cbfs_map(fname, NULL); - uint8_t *spi_ptr = (uint8_t *)hash_file; uint32_t len; - if (!spi_ptr) { - printk(BIOS_ERR, "AMD Firmware hash table %s not found\n", fname); - /* - * If we don't supply hash table, the PSP will refuse to boot. - * So returning here is safe to do. - */ - return; - } - memcpy(&hash_table, spi_ptr, offsetof(struct psp_fw_hash_table, fw_hash_256)); if (hash_table.no_of_entries_256 > MAX_NUM_HASH_ENTRIES || hash_table.no_of_entries_384 > MAX_NUM_HASH_ENTRIES) { printk(BIOS_ERR, "Too many entries in AMD Firmware hash table" - " (SHA256:%d, SHA384:%d)\n", - hash_table.no_of_entries_256, hash_table.no_of_entries_384); - cbfs_unmap(hash_file); - rdev_munmap(boot_device_ro(), hash_file); + " (SHA256:%d, SHA384:%d)\n", hash_table.no_of_entries_256, + hash_table.no_of_entries_384); return; } - if (hash_table.no_of_entries_256 == 0 && - hash_table.no_of_entries_384 == 0) { + if (hash_table.no_of_entries_256 == 0 && hash_table.no_of_entries_384 == 0) { printk(BIOS_ERR, "No entries in AMD Firmware hash table" - " (SHA256:%d, SHA384:%d)\n", - hash_table.no_of_entries_256, hash_table.no_of_entries_384); - cbfs_unmap(hash_file); - rdev_munmap(boot_device_ro(), hash_file); + " (SHA256:%d, SHA384:%d)\n", hash_table.no_of_entries_256, + hash_table.no_of_entries_384); return; } @@ -70,11 +59,95 @@ void update_psp_fw_hash_table(const char *fname) len = sizeof(struct psp_fw_entry_hash_384) * hash_table.no_of_entries_384; memcpy(hash_384, spi_ptr, len); - svc_set_fw_hash_table(&hash_table); + svc_set_fw_hash_table(cmd, &hash_table); +} + +static void update_one_psp_fw_hash_table_v2(enum verstage_cmd_id cmd, uint8_t *spi_ptr) +{ + uint32_t len; + + memcpy(&hash_table_v2, spi_ptr, offsetof(struct psp_fw_hash_table_v2, fw_hash_256)); + + if (hash_table_v2.no_of_entries_256 > MAX_NUM_HASH_ENTRIES || + hash_table_v2.no_of_entries_384 > MAX_NUM_HASH_ENTRIES) { + printk(BIOS_ERR, "Too many entries in AMD Firmware hash table" + " (SHA256:%d, SHA384:%d)\n", hash_table_v2.no_of_entries_256, + hash_table_v2.no_of_entries_384); + return; + } + + if (hash_table_v2.no_of_entries_256 == 0 && hash_table_v2.no_of_entries_384 == 0) { + printk(BIOS_ERR, "No entries in AMD Firmware hash table" + " (SHA256:%d, SHA384:%d)\n", hash_table_v2.no_of_entries_256, + hash_table_v2.no_of_entries_384); + return; + } + + spi_ptr += offsetof(struct psp_fw_hash_table_v2, fw_hash_256); + + hash_table_v2.fw_hash_256 = hash_256_v2; + hash_table_v2.fw_hash_384 = hash_384_v2; + len = sizeof(struct psp_fw_entry_hash_256_v2) * hash_table_v2.no_of_entries_256; + memcpy(hash_256_v2, spi_ptr, len); + + spi_ptr += len; + len = sizeof(struct psp_fw_entry_hash_384_v2) * hash_table_v2.no_of_entries_384; + memcpy(hash_384_v2, spi_ptr, len); + + svc_set_fw_hash_table(cmd, &hash_table_v2); +} + +static void update_one_psp_fw_hash_table(enum verstage_cmd_id cmd, const char *fname) +{ + void *hash_file = cbfs_map(fname, NULL); + uint16_t version; + + if (!hash_file) { + printk(BIOS_ERR, "AMD Firmware hash table %s not found\n", fname); + /* + * If we don't supply hash table, the PSP will refuse to boot. + * So returning here is safe to do. + */ + return; + } + + memcpy(&version, hash_file, sizeof(version)); + assert(version <= 2); + switch (version) { + case 1: + update_one_psp_fw_hash_table_v1(cmd, hash_file); + break; + case 2: + update_one_psp_fw_hash_table_v2(cmd, hash_file); + break; + default: + printk(BIOS_ERR, "%s: Unexpected version %d\n", __func__, version); + } cbfs_unmap(hash_file); rdev_munmap(boot_device_ro(), hash_file); } +void update_psp_fw_hash_tables(void) +{ + struct vb2_context *ctx = vboot_get_context(); + + if (vboot_is_firmware_slot_a(ctx)) { + update_one_psp_fw_hash_table(CMD_SET_FW_HASH_TABLE_STAGE1, + PSP_FW_HASH_FILE_NAME("a", "")); + update_one_psp_fw_hash_table(CMD_SET_FW_HASH_TABLE_STAGE2, + PSP_FW_HASH_FILE_NAME("a", "1")); + update_one_psp_fw_hash_table(CMD_SET_FW_HASH_TABLE_TOS, + PSP_FW_HASH_FILE_NAME("a", "2")); + } else { + update_one_psp_fw_hash_table(CMD_SET_FW_HASH_TABLE_STAGE1, + PSP_FW_HASH_FILE_NAME("a", "")); + update_one_psp_fw_hash_table(CMD_SET_FW_HASH_TABLE_STAGE2, + PSP_FW_HASH_FILE_NAME("a", "1")); + update_one_psp_fw_hash_table(CMD_SET_FW_HASH_TABLE_TOS, + PSP_FW_HASH_FILE_NAME("a", "2")); + } +} + uint32_t update_psp_bios_dir(uint32_t *psp_dir_offset, uint32_t *bios_dir_offset) { return svc_update_psp_bios_dir(psp_dir_offset, bios_dir_offset); diff --git a/src/soc/amd/phoenix/psp_verstage/svc.c b/src/soc/amd/phoenix/psp_verstage/svc.c index c88f7598f7..45d18c1456 100644 --- a/src/soc/amd/phoenix/psp_verstage/svc.c +++ b/src/soc/amd/phoenix/psp_verstage/svc.c @@ -206,13 +206,16 @@ uint32_t svc_set_platform_boot_mode(enum chrome_platform_boot_mode boot_mode) return retval; } -uint32_t svc_set_fw_hash_table(struct psp_fw_hash_table *hash_table) +uint32_t svc_set_fw_hash_table(enum verstage_cmd_id cmd, void *hash_table) { uint32_t retval = 0; struct cmd_param_set_fw_hash_table param = { .ptr_psp_fw_hash_table = hash_table, }; - SVC_CALL2(SVC_VERSTAGE_CMD, CMD_SET_FW_HASH_TABLE, (void *)¶m, retval); + assert(cmd == CMD_SET_FW_HASH_TABLE_STAGE1 || + cmd == CMD_SET_FW_HASH_TABLE_STAGE2 || + cmd == CMD_SET_FW_HASH_TABLE_TOS); + SVC_CALL2(SVC_VERSTAGE_CMD, cmd, (void *)¶m, retval); return retval; } diff --git a/src/soc/amd/phoenix/psp_verstage/svc.h b/src/soc/amd/phoenix/psp_verstage/svc.h index c3e6475ca9..43b560a8a9 100644 --- a/src/soc/amd/phoenix/psp_verstage/svc.h +++ b/src/soc/amd/phoenix/psp_verstage/svc.h @@ -92,7 +92,7 @@ struct cmd_param_set_platform_boot_mode { }; struct cmd_param_set_fw_hash_table { - struct psp_fw_hash_table *ptr_psp_fw_hash_table; + void *ptr_psp_fw_hash_table; }; struct cmd_param_get_prev_boot_status { |