Martin Roth has submitted this change. ( https://review.coreboot.org/c/coreboot/+/60291 )
(
14 is the latest approved patch-set. No files were changed between the latest approved patch-set and the submitted one. )Change subject: soc/amd/(common,mendocino)/psp_verstage: Pass PSP FW hash table ......................................................................
soc/amd/(common,mendocino)/psp_verstage: Pass PSP FW hash table
Copy AMD PSP fw hash table into memory, then pass it to the PSP. The PSP will use this hash to verify it's the correct firmware bundled with coreboot build and not replaced.
BUG=b:203597980 TEST=Build Skyrim BIOS image with the hash table and boot to OS after PSP verified the binaries against the hash table.
Change-Id: I84bea97c89620d0388b27891a898ffde77052239 Signed-off-by: Kangheui Won khwon@chromium.org Signed-off-by: Karthikeyan Ramasubramanian kramasub@google.com Reviewed-on: https://review.coreboot.org/c/coreboot/+/60291 Reviewed-by: Tim Van Patten timvp@google.com Reviewed-by: Jon Murphy jpmurphy@google.com Tested-by: build bot (Jenkins) no-reply@coreboot.org --- M src/soc/amd/common/psp_verstage/include/psp_verstage.h M src/soc/amd/common/psp_verstage/psp_verstage.c M src/soc/amd/mendocino/psp_verstage/chipset.c 3 files changed, 89 insertions(+), 0 deletions(-)
Approvals: build bot (Jenkins): Verified Jon Murphy: Looks good to me, approved Tim Van Patten: Looks good to me, but someone else must approve
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 3b524c3..e740332 100644 --- a/src/soc/amd/common/psp_verstage/include/psp_verstage.h +++ b/src/soc/amd/common/psp_verstage/include/psp_verstage.h @@ -66,4 +66,6 @@ struct sha_generic_data *sha_op); void platform_report_mode(int developer_mode_enabled);
+void update_psp_fw_hash_table(const char *fname); + #endif /* PSP_VERSTAGE_H */ diff --git a/src/soc/amd/common/psp_verstage/psp_verstage.c b/src/soc/amd/common/psp_verstage/psp_verstage.c index b928a27..0dc3314 100644 --- a/src/soc/amd/common/psp_verstage/psp_verstage.c +++ b/src/soc/amd/common/psp_verstage/psp_verstage.c @@ -74,6 +74,7 @@ uint32_t psp_dir_addr, bios_dir_addr; uint32_t *psp_dir_in_spi, *bios_dir_in_spi; const char *fname; + const char *hash_fname; void *amdfw_location; void *boot_dev_base = rdev_mmap_full(boot_device_ro());
@@ -85,8 +86,10 @@
if (vboot_is_firmware_slot_a(ctx)) { fname = "apu/amdfw_a"; + hash_fname = "apu/amdfw_a_hash"; } else { fname = "apu/amdfw_b"; + hash_fname = "apu/amdfw_b_hash"; }
amdfw_location = cbfs_map(fname, NULL); @@ -130,6 +133,9 @@ return POSTCODE_UPDATE_PSP_BIOS_DIR_ERROR; }
+ if (CONFIG(SEPARATE_SIGNED_PSPFW)) + update_psp_fw_hash_table(hash_fname); + return 0; }
diff --git a/src/soc/amd/mendocino/psp_verstage/chipset.c b/src/soc/amd/mendocino/psp_verstage/chipset.c index d4a33f0..b896279 100644 --- a/src/soc/amd/mendocino/psp_verstage/chipset.c +++ b/src/soc/amd/mendocino/psp_verstage/chipset.c @@ -3,9 +3,67 @@ /* TODO: Check if this is still correct */
#include <bl_uapp/bl_syscall_public.h> +#include <cbfs.h> #include <console/console.h> #include <psp_verstage.h>
+/* + * 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 +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) +{ + uint8_t *spi_ptr = (uint8_t *)cbfs_map(fname, NULL); + uint32_t len; + + if (!spi_ptr) { + printk(BIOS_ERR, "Error: 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, "Error: 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); + return; + } + + if (hash_table.no_of_entries_256 == 0 && + hash_table.no_of_entries_384 == 0) { + printk(BIOS_ERR, "Error: No entries in AMD Firmware hash table" + " (SHA256:%d, SHA384:%d)\n", + hash_table.no_of_entries_256, hash_table.no_of_entries_384); + return; + } + + spi_ptr += offsetof(struct psp_fw_hash_table, fw_hash_256); + + hash_table.fw_hash_256 = hash_256; + hash_table.fw_hash_384 = hash_384; + len = sizeof(struct psp_fw_entry_hash_256) * hash_table.no_of_entries_256; + memcpy(hash_256, spi_ptr, len); + + spi_ptr += len; + 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); +} + 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);