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 #include +#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) -{ - void *hash_file = cbfs_map(fname, NULL); - uint8_t *spi_ptr = (uint8_t *)hash_file; - uint32_t len; +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]; - 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; - } +static void update_one_psp_fw_hash_table_v1(enum verstage_cmd_id cmd, uint8_t *spi_ptr) +{ + uint32_t len; 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 { diff --git a/src/vendorcode/amd/fsp/phoenix/include/bl_uapp/bl_syscall_public.h b/src/vendorcode/amd/fsp/phoenix/include/bl_uapp/bl_syscall_public.h index 623762ad0e..b3e41404e8 100644 --- a/src/vendorcode/amd/fsp/phoenix/include/bl_uapp/bl_syscall_public.h +++ b/src/vendorcode/amd/fsp/phoenix/include/bl_uapp/bl_syscall_public.h @@ -60,6 +60,9 @@ enum verstage_cmd_id { CMD_GET_PREV_BOOT_STATUS, CMD_GET_HSP_SECURE_STATE, CMD_WRITE_POSTCODE, + CMD_SET_FW_HASH_TABLE_STAGE1, + CMD_SET_FW_HASH_TABLE_STAGE2, + CMD_SET_FW_HASH_TABLE_TOS, }; struct mod_exp_params { @@ -178,13 +181,32 @@ struct psp_fw_entry_hash_384 { } __packed; struct psp_fw_hash_table { - uint16_t version; // Version of psp_fw_hash_table, Start with 0. + uint16_t version; // Version 1 of psp_fw_hash_table. uint16_t no_of_entries_256; uint16_t no_of_entries_384; struct psp_fw_entry_hash_256 *fw_hash_256; struct psp_fw_entry_hash_384 *fw_hash_384; } __packed; +struct psp_fw_entry_hash_256_v2 { + uint8_t uuid[16]; + uint8_t sha[32]; +} __packed; + +struct psp_fw_entry_hash_384_v2 { + uint8_t uuid[16]; + uint8_t sha[48]; +} __packed; + +struct psp_fw_hash_table_v2 { + uint16_t version; // Version 2 of psp_fw_hash_table. + uint16_t no_of_entries_256; + uint16_t no_of_entries_384; + uint16_t reserved; // For alignment purposes. + struct psp_fw_entry_hash_256_v2 *fw_hash_256; + struct psp_fw_entry_hash_384_v2 *fw_hash_384; +} __packed; + /* * Exit to the main Boot Loader. This does not return back to user application. * @@ -372,14 +394,15 @@ uint32_t svc_ccp_dma(uint32_t spi_rom_offset, void *dest, uint32_t size); uint32_t svc_set_platform_boot_mode(enum chrome_platform_boot_mode boot_mode); /* - * Set the PSP FW hash table. + * Set PSP FW hash table. * * Parameters: * - hash_table - Table of hash for each PSP binary signed against SoC chain of trust + * - cmd - Cmd to indicate the PSP stage using the hash table * * Return value: BL_OK or error code */ -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); /* Get the previous boot status. *