diff options
author | Audrey Pearson <apearson@raptorengineeringinc.com> | 2015-10-08 12:47:24 -0500 |
---|---|---|
committer | Alexandru Gagniuc <mr.nuke.me@gmail.com> | 2015-10-14 21:22:52 +0000 |
commit | 83e4c5613eecc5283d9a66997dc90e26384f9284 (patch) | |
tree | 9893e5caf603bd8eea5d975137626c6eb0c04441 | |
parent | aa1b6b06ef506eeb4cc73139b473a0aeb9ee26ba (diff) |
cpu/amd/microcode: Update parser to use stock microcode blobs
The existing microcode update system used custom, manually generated microcode
blob files. This made updates very difficult. Update parser to use stock
microcode update files as provided by AMD.
Change-Id: I772b264ad167f2a5d629dab5d64d9b0ccab3a053
Signed-off-by: Audrey Pearson <apearson@raptorengineeringinc.com>
Reviewed-on: http://review.coreboot.org/11829
Tested-by: Raptor Engineering Automated Test Stand <noreply@raptorengineeringinc.com>
Reviewed-by: Alexandru Gagniuc <mr.nuke.me@gmail.com>
Tested-by: build bot (Jenkins)
-rw-r--r-- | src/cpu/amd/microcode/microcode.c | 166 |
1 files changed, 132 insertions, 34 deletions
diff --git a/src/cpu/amd/microcode/microcode.c b/src/cpu/amd/microcode/microcode.c index 45e4bf0a52..badd3b797b 100644 --- a/src/cpu/amd/microcode/microcode.c +++ b/src/cpu/amd/microcode/microcode.c @@ -2,6 +2,7 @@ * This file is part of the coreboot project. * * Copyright (C) 2007 Advanced Micro Devices, Inc. + * Copyright (C) 2015 Raptor Engineering * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -22,37 +23,96 @@ #include <cpu/x86/msr.h> #include <cpu/amd/microcode.h> #include <cbfs.h> +#include <arch/io.h> #define UCODE_DEBUG(fmt, args...) \ do { printk(BIOS_DEBUG, "[microcode] "fmt, ##args); } while(0) +#define UCODE_MAGIC 0x00414d44 +#define UCODE_EQUIV_CPU_TABLE_TYPE 0x00000000 +#define UCODE_SECTION_START_ID 0x00000001 +#define UCODE_MAGIC 0x00414d44 + +#define F1XH_MPB_MAX_SIZE 2048 +#define F15H_MPB_MAX_SIZE 4096 +#define CONT_HDR 12 +#define SECT_HDR 8 + +/* + * STRUCTURE OF A MICROCODE (UCODE) FILE + * Container Header + * Section Header + * Microcode Header + * Microcode "Blob" + * Section Header + * Microcode Header + * Microcode "Blob" + * ... + * ... + * (end of file) + * + * + * CONTAINER HEADER (offset 0 bytes from start of file) + * Total size = fixed size (12 bytes) + variable size + * [0:3] 32-bit unique ID + * [4:7] don't-care + * [8-11] Size (n) in bytes of variable portion of container header + * [12-n] don't-care + * + * SECTION HEADER (offset += 12+n) + * Total size = 8 bytes + * [0:3] Unique identifier signaling start of section (0x00000001) + * [4:7] Total size (m) of following microcode section, including microcode header + * + * MICROCODE HEADER (offset += 8) + * Total size = 64 bytes + * [0:3] Data code (32 bits) + * [4:7] Patch ID (32 bits) + * [8:9] Microcode patch data ID (16 bits) + * [10] c patch data length (8 bits) + * [11] init flag (8 bits) + * [12:15] ucode patch data cksum (32 bits) + * [16:19] nb dev ID (32 bits) + * [20:23] sb dev ID (32 bits) + * [24:25] Processor rev ID (16 bits) + * [26] nb revision ID (8 bits) + * [27] sb revision ID (8 bits) + * [28] BIOS API revision (8 bits) + * [29-31] Reserved 1 (array of three 8-bit values) + * [32-63] Match reg (array of eight 32-bit values) + * + * MICROCODE BLOB (offset += 64) + * Total size = m bytes + * + */ + struct microcode { - u32 date_code; - u32 patch_id; + uint32_t data_code; + uint32_t patch_id; - u16 m_patch_data_id; - u8 m_patch_data_len; - u8 init_flag; + uint16_t mc_patch_data_id; + uint8_t mc_patch_data_len; + uint8_t init_flag; - u32 m_patch_data_cksum; + uint32_t mc_patch_data_checksum; - u32 nb_dev_id; - u32 ht_io_hub_dev_id; + uint32_t nb_dev_id; + uint32_t sb_dev_id; - u16 processor_rev_id; - u8 ht_io_hub_rev_id; - u8 nb_rev_id; + uint16_t processor_rev_id; + uint8_t nb_rev_id; + uint8_t sb_rev_id; - u8 bios_api_rev; - u8 resv1[3]; + uint8_t bios_api_rev; + uint8_t reserved1[3]; - u32 match_reg[8]; + uint32_t match_reg[8]; - u8 m_patch_data[896]; - u8 resv2[896]; + uint8_t m_patch_data[896]; + uint8_t resv2[896]; - u8 x86_code_present; - u8 x86_code_entry[191]; + uint8_t x86_code_present; + uint8_t x86_code_entry[191]; }; static void apply_microcode_patch(const struct microcode *m) @@ -82,35 +142,73 @@ static void amd_update_microcode(const void *ucode, size_t ucode_len, const struct microcode *m; const uint8_t *c = ucode; const uint8_t *ucode_end = (uint8_t*)ucode + ucode_len; + const uint8_t *cur_section_hdr; + + uint32_t container_hdr_id; + uint32_t container_hdr_size; + uint32_t blob_size; + uint32_t sec_hdr_id; + + /* Container Header */ + container_hdr_id = read32(c); + if (container_hdr_id != UCODE_MAGIC) { + UCODE_DEBUG("Invalid container header ID\n"); + return; + } + + container_hdr_size = read32(c + 8); + cur_section_hdr = c + CONT_HDR + container_hdr_size; + + /* Read in first section header ID */ + sec_hdr_id = read32(cur_section_hdr); + c = cur_section_hdr + 4; + + /* Loop through sections */ + while (sec_hdr_id == UCODE_SECTION_START_ID && + c <= (ucode_end - F15H_MPB_MAX_SIZE)) { + + blob_size = read32(c); + + m = (struct microcode *)(c + 4); - while (c <= (ucode_end - 2048)) { - m = (struct microcode *)c; if (m->processor_rev_id == equivalent_processor_rev_id) { apply_microcode_patch(m); break; } - c += 2048; + + cur_section_hdr = c + 4 + blob_size; + sec_hdr_id = read32(cur_section_hdr); + c = cur_section_hdr + 4; } } -#define MICROCODE_CBFS_FILE "cpu_microcode_blob.bin" +static const char *microcode_cbfs_file[] = { + "microcode_amd.bin", + "microcode_amd_fam15h.bin", +}; -void amd_update_microcode_from_cbfs(u32 equivalent_processor_rev_id) +void amd_update_microcode_from_cbfs(uint32_t equivalent_processor_rev_id) { const void *ucode; size_t ucode_len; - if (equivalent_processor_rev_id == 0) { - UCODE_DEBUG("rev id not found. Skipping microcode patch!\n"); - return; - } + uint32_t i; - ucode = cbfs_boot_map_with_leak(MICROCODE_CBFS_FILE, - CBFS_TYPE_MICROCODE, &ucode_len); - if (!ucode) { - UCODE_DEBUG("microcode file not found. Skipping updates.\n"); - return; - } + for (i = 0; i < ARRAY_SIZE(microcode_cbfs_file); i++) + { + if (equivalent_processor_rev_id == 0) { + UCODE_DEBUG("rev id not found. Skipping microcode patch!\n"); + return; + } + + ucode = cbfs_boot_map_with_leak(microcode_cbfs_file[i], + CBFS_TYPE_MICROCODE, &ucode_len); + if (!ucode) { + UCODE_DEBUG("microcode file not found. Skipping updates.\n"); - amd_update_microcode(ucode, ucode_len, equivalent_processor_rev_id); + return; + } + + amd_update_microcode(ucode, ucode_len, equivalent_processor_rev_id); + } } |