aboutsummaryrefslogtreecommitdiff
path: root/src/cpu/amd/pi/00730F01/update_microcode.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/cpu/amd/pi/00730F01/update_microcode.c')
-rw-r--r--src/cpu/amd/pi/00730F01/update_microcode.c141
1 files changed, 115 insertions, 26 deletions
diff --git a/src/cpu/amd/pi/00730F01/update_microcode.c b/src/cpu/amd/pi/00730F01/update_microcode.c
index e3f0c3bdae..11e2531e2b 100644
--- a/src/cpu/amd/pi/00730F01/update_microcode.c
+++ b/src/cpu/amd/pi/00730F01/update_microcode.c
@@ -2,42 +2,131 @@
#include <stdint.h>
#include <cpu/amd/microcode.h>
+#include <commonlib/helpers.h>
+#include <console/console.h>
+#include <cpu/x86/msr.h>
+#include <cpu/amd/msr.h>
+#include <cbfs.h>
-struct id_mapping {
- uint32_t orig_id;
- uint16_t new_id;
-};
+/*
+ * Values and header structure from:
+ * BKDG for AMD Family 16h Models 30h-3Fh Processors
+ * 52740 Rev 3.06 - March 18, 2016
+ */
-static u16 get_equivalent_processor_rev_id(u32 orig_id)
+#define F16H_MPB_MAX_SIZE 3458
+#define F16H_MPB_DATA_OFFSET 32
+
+ /*
+ * STRUCTURE OF A MICROCODE (UCODE) FILE FOR FAM16h
+ * Microcode Patch Block
+ * Microcode Header
+ * Microcode "Blob"
+ * ...
+ * ...
+ * (end of file)
+ *
+ *
+ * MICROCODE HEADER (offset 0 bytes from start of file)
+ * Total size = 32 bytes
+ * [0:3] Date code (32 bits)
+ * [4:7] Patch level (32 bits)
+ * [8:9] Microcode patch data ID (16 bits)
+ * [10:15] Reserved (48 bits)
+ * [16:19] Chipset 1 device ID (32 bits)
+ * [20:23] Chipset 2 device ID (32 bits)
+ * [24:25] Processor Revisions ID (16 bits)
+ * [26] Chipset 1 revision ID (8 bits)
+ * [27] Chipset 2 revision ID (8 bits)
+ * [28:31] Reserved (32 bits)
+ *
+ * MICROCODE BLOB (offset += 32)
+ * Total size = m bytes
+ *
+ */
+
+struct microcode {
+ uint32_t date_code;
+ uint32_t patch_id;
+
+ uint16_t mc_patch_data_id;
+ uint8_t reserved1[6];
+
+ uint32_t chipset1_dev_id;
+ uint32_t chipset2_dev_id;
+
+ uint16_t processor_rev_id;
+
+ uint8_t chipset1_rev_id;
+ uint8_t chipset2_rev_id;
+
+ uint8_t reserved2[4];
+
+ uint8_t m_patch_data[F16H_MPB_MAX_SIZE-F16H_MPB_DATA_OFFSET];
+} __packed;
+
+static void apply_microcode_patch(const struct microcode *m)
{
- static const struct id_mapping id_mapping_table[] = {
- /* Family 16h */
+ uint32_t new_patch_id;
+ msr_t msr;
- /* TODO This equivalent processor revisions ID needs verification */
- { 0x730f01, 0x7301 },
+ msr.hi = (uint64_t)(uintptr_t)m >> 32;
+ msr.lo = (uintptr_t)m & 0xffffffff;
- /* Array terminator */
- { 0xffffff, 0x0000 },
- };
+ wrmsr(MSR_PATCH_LOADER, msr);
- u32 new_id;
- int i;
+ printk(BIOS_DEBUG, "microcode: patch id to apply = 0x%08x\n",
+ m->patch_id);
- new_id = 0;
+ msr = rdmsr(MSR_PATCH_LEVEL);
+ new_patch_id = msr.lo;
- for (i = 0; id_mapping_table[i].orig_id != 0xffffff; i++) {
- if (id_mapping_table[i].orig_id == orig_id) {
- new_id = id_mapping_table[i].new_id;
- break;
- }
- }
+ if (new_patch_id == m->patch_id)
+ printk(BIOS_INFO, "microcode: being updated to patch id = 0x%08x succeeded\n",
+ new_patch_id);
+ else
+ printk(BIOS_ERR, "microcode: being updated to patch id = 0x%08x failed\n",
+ new_patch_id);
+}
- return new_id;
+static uint16_t get_equivalent_processor_rev_id(void)
+{
+ uint32_t cpuid_family = cpuid_eax(1);
+
+ return (uint16_t)((cpuid_family & 0xff0000) >> 8 | (cpuid_family & 0xff));
+}
+
+static void amd_update_microcode(const void *ucode, size_t ucode_len,
+ uint16_t equivalent_processor_rev_id)
+{
+ const struct microcode *m;
+ const uint8_t *c = ucode;
+
+ m = (struct microcode *)c;
+
+ /* Assume cpu_microcode_blob only contains one microcode. */
+ if (m->processor_rev_id == equivalent_processor_rev_id)
+ apply_microcode_patch(m);
}
-void update_microcode(u32 cpu_deviceid)
+void amd_update_microcode_from_cbfs(void)
{
- u16 equivalent_processor_rev_id =
- get_equivalent_processor_rev_id(cpu_deviceid);
- amd_update_microcode_from_cbfs(equivalent_processor_rev_id);
+ const void *ucode;
+ size_t ucode_len;
+ uint16_t equivalent_processor_rev_id = get_equivalent_processor_rev_id();
+
+ ucode = cbfs_boot_map_with_leak("cpu_microcode_blob.bin",
+ CBFS_TYPE_MICROCODE, &ucode_len);
+ if (!ucode) {
+ printk(BIOS_WARNING, "cpu_microcode_blob.bin not found. Skipping updates.\n");
+ return;
+ }
+
+ if (ucode_len > F16H_MPB_MAX_SIZE ||
+ ucode_len < F16H_MPB_DATA_OFFSET) {
+ printk(BIOS_DEBUG, "microcode file invalid. Skipping updates.\n");
+ return;
+ }
+
+ amd_update_microcode(ucode, ucode_len, equivalent_processor_rev_id);
}