summaryrefslogtreecommitdiff
path: root/src/cpu
diff options
context:
space:
mode:
authorRizwan Qureshi <rizwan.qureshi@intel.com>2021-05-20 21:05:03 +0530
committerWerner Zeh <werner.zeh@siemens.com>2021-05-27 06:35:33 +0000
commit1aa60a95bd8363d215fae11663229c976338ef6e (patch)
tree3150eba65f840cb358c5ff8d9ba5d9cb6c4e9058 /src/cpu
parent078448296c863926ff4c65cad7d602e96026bf14 (diff)
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 <rizwan.qureshi@intel.com> Change-Id: I1466caf4a4ba1f9a0214bdde19cce57dd65dacbd Reviewed-on: https://review.coreboot.org/c/coreboot/+/54734 Tested-by: build bot (Jenkins) <no-reply@coreboot.org> Reviewed-by: Arthur Heymans <arthur@aheymans.xyz> Reviewed-by: Tim Wawrzynczak <twawrzynczak@chromium.org> Reviewed-by: Furquan Shaikh <furquan@google.com>
Diffstat (limited to 'src/cpu')
-rw-r--r--src/cpu/intel/microcode/microcode.c50
1 files changed, 50 insertions, 0 deletions
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;
}