summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/soc/amd/common/psp_verstage/include/psp_verstage.h2
-rw-r--r--src/soc/amd/common/psp_verstage/psp_verstage.c6
-rw-r--r--src/soc/amd/mendocino/psp_verstage/chipset.c58
3 files changed, 66 insertions, 0 deletions
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 3b524c310c..e740332862 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 @@ int platform_set_sha_op(enum vb2_hash_algorithm hash_alg,
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 b928a27e27..0dc3314ca5 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 @@ static uint32_t update_boot_region(struct vb2_context *ctx)
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 @@ static uint32_t update_boot_region(struct vb2_context *ctx)
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 @@ static uint32_t update_boot_region(struct vb2_context *ctx)
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 d4a33f0832..b89627981c 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);