From 1aa60a95bd8363d215fae11663229c976338ef6e Mon Sep 17 00:00:00 2001 From: Rizwan Qureshi Date: Thu, 20 May 2021 21:05:03 +0530 Subject: [PATCH] src/intel/microcode: Add support for extended signature table Microcode header supports advertising support for only one CPU signature and processor flags. If there are multiple processor families supported by this microcode blob, they are mentioned in the extended signature table. Add support to parse the extended processor signature table to determine if the microcode blob supports the currently running CPU. BUG=b:182234962 TEST=Booted ADL brya system with a processor whose signature/pf are in the extended signature table of a microcode patch. Was able to match and load the patch appropriately. Signed-off-by: Rizwan Qureshi Change-Id: I1466caf4a4ba1f9a0214bdde19cce57dd65dacbd Reviewed-on: https://review.coreboot.org/c/coreboot/+/54734 Tested-by: build bot (Jenkins) Reviewed-by: Arthur Heymans Reviewed-by: Tim Wawrzynczak Reviewed-by: Furquan Shaikh --- src/cpu/intel/microcode/microcode.c | 50 +++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) diff --git a/src/cpu/intel/microcode/microcode.c b/src/cpu/intel/microcode/microcode.c index 51823ca6de..45996dfdc3 100644 --- a/src/cpu/intel/microcode/microcode.c +++ b/src/cpu/intel/microcode/microcode.c @@ -29,6 +29,18 @@ struct microcode { u32 reserved[3]; }; +struct ext_sig_table { + u32 ext_sig_cnt; + u32 ext_tbl_chksm; + u32 res[3]; +}; + +struct ext_sig_entry { + u32 sig; + u32 pf; + u32 chksm; +}; + static inline u32 read_microcode_rev(void) { /* Some Intel CPUs can be very finicky about the @@ -117,9 +129,31 @@ uint32_t get_microcode_checksum(const void *microcode) return ((struct microcode *)microcode)->cksum; } + +static struct ext_sig_table *ucode_get_ext_sig_table(const struct microcode *ucode) +{ + struct ext_sig_table *ext_tbl; + /* header + ucode data blob size */ + u32 size = ucode->data_size + sizeof(struct microcode); + + size_t ext_tbl_len = ucode->total_size - size; + + if (ext_tbl_len < sizeof(struct ext_sig_table)) + return NULL; + + ext_tbl = (struct ext_sig_table *)((uintptr_t)ucode + size); + + if (ext_tbl_len < (sizeof(struct ext_sig_table) + + ext_tbl->ext_sig_cnt * sizeof(struct ext_sig_entry))) + return NULL; + + return ext_tbl; +} + static const void *find_cbfs_microcode(void) { const struct microcode *ucode_updates; + struct ext_sig_table *ext_tbl; size_t microcode_len; u32 eax; u32 pf, rev, sig, update_size; @@ -163,6 +197,22 @@ static const void *find_cbfs_microcode(void) if ((ucode_updates->sig == sig) && (ucode_updates->pf & pf)) return ucode_updates; + + /* Check if there is extended signature table */ + ext_tbl = ucode_get_ext_sig_table(ucode_updates); + + if (ext_tbl != NULL) { + int i; + struct ext_sig_entry *entry = (struct ext_sig_entry *)(ext_tbl + 1); + + for (i = 0; i < ext_tbl->ext_sig_cnt; i++, entry++) { + + if ((sig == entry->sig) && (pf & entry->pf)) { + return ucode_updates; + } + } + } + ucode_updates = (void *)((char *)ucode_updates + update_size); microcode_len -= update_size; }