diff options
Diffstat (limited to 'src/cpu/intel/microcode')
-rw-r--r-- | src/cpu/intel/microcode/Kconfig | 77 | ||||
-rw-r--r-- | src/cpu/intel/microcode/Makefile.inc | 20 | ||||
-rw-r--r-- | src/cpu/intel/microcode/microcode.c | 15 |
3 files changed, 108 insertions, 4 deletions
diff --git a/src/cpu/intel/microcode/Kconfig b/src/cpu/intel/microcode/Kconfig index f5f9c761e8..4640c16991 100644 --- a/src/cpu/intel/microcode/Kconfig +++ b/src/cpu/intel/microcode/Kconfig @@ -16,3 +16,80 @@ config RELOAD_MICROCODE_PATCH This feature is mostly required with Intel latest generation processors starting with Alder Lake (with modified MCHECK init flow). + +config CPU_INTEL_MICROCODE_CBFS_SPLIT_BINS + bool "For Intel CPU, include microcode per CPUID into CBFS" + depends on CBFS_VERIFICATION && !MICROCODE_UPDATE_PRE_RAM + default n + help + This option controls whether to include external microcode binaries per + CPUID in CBFS. + + The current approach of loading microcode blobs post CPU reset is to search + the unified blob in the CBFS and then perform the CBFS verification. The bigger + the unified microcode blob in size the longer it takes to perform the verification. + + Select this option to store the split microcode blobs per CPUID in the CBFS. + As the microcode blobs will be divided into smaller chunks per CPUID, which will + reduce the overall search, verify and load time. + + The microcode file may be removed from the ROM image at a later + time with cbfstool, if desired. + + If unsure, and applicable, select "Generate from tree" + +config CPU_INTEL_UCODE_SPLIT_BINARIES + string "Specify the split microcode blob directory path" + depends on CPU_INTEL_MICROCODE_CBFS_SPLIT_BINS + default "" + help + Provide the split microcode blob directory path if + CPU_INTEL_MICROCODE_CBFS_SPLIT_BINS config is enabled. + + CPU_INTEL_MICROCODE_CBFS_SPLIT_BINS config is allowed to pack the individual microcode + patch file per CPUID inside the CBFS. + + Intel distributes CPU microcode updates based on CPUID as part of the github repository + in INC format and expects it also getting used in binary form. + + For example: Intel CPU microcode `m506e3.inc` is getting converted into F-MO-S + (06-5e-03) binary file for Linux kernel. + + `MicrocodeConverter` is an Intel-provided tool for converting binary form MCU into + several other common formats for integration. + + Implementation logic behind CPU_INTEL_MICROCODE_CBFS_SPLIT_BINS config relies on + converting Intel CPU microcode INC file into the binary file as per format specified + here `cpu_microcode_$(CPUID).bin`. For example: Intel CPU microcode `m506e3.inc` to + convert into `cpu_microcode_506e3.bin` binary file for coreboot to integrate if + CPU_INTEL_MICROCODE_CBFS_SPLIT_BINS config is enabled. + + This config provides the directory name (including path) that holds the split microcode + binary files per CPUID as mentioned above for each coreboot variants. For example: if + google/kunimitsu had built with Intel SkyLake processor with CPUID `506e3` and `506e4` + then CPU_INTEL_UCODE_SPLIT_BINARIES refers to the directory path that holds the split + microcode binary files aka `cpu_microcode_506e3.bin` and `cpu_microcode_506e4.bin`. + + CONFIG_CPU_UCODE_SPLIT_BINARIES="3rdparty/blobs/mainboard/google/kunimitsu/microcode_inputs/kunimitsu" + Refer to the file representation below: + |---3rdparty + | |--- blobs + | | |--- mainboard + | | | |--- google + | | | | |--- kunimitsu + | | | | | |--- microcode_inputs + | | | | | | |--- kunimitsu + | | | | | | | |--- cpu_microcode_506e3.bin + | | | | | | | |--- cpu_microcode_506e4.bin + + Users of this config option requires to manually place the microcode binary files per + CPUIDs as per the given format (`cpu_microcode_$(CPUID).bin`) in a directory. + Finally specify the microcode binary directory path using CPU_UCODE_SPLIT_BINARIES + config. + + At runtime (either from romstage/ramstage), coreboot read the CPUID and search for the + `cpu_microcode_$(CPUID).bin` file (in this example: cpu_microcode_506e3.bin) inside RW + CBFS. Eventually able to locate the appropriate `cpu_microcode_$(CPUID).bin` file and + perform the verification prior loading into the CPUs (BSP and APs). + + If unsure, leave this blank. diff --git a/src/cpu/intel/microcode/Makefile.inc b/src/cpu/intel/microcode/Makefile.inc index 119c38fac2..4ea8227e13 100644 --- a/src/cpu/intel/microcode/Makefile.inc +++ b/src/cpu/intel/microcode/Makefile.inc @@ -3,3 +3,23 @@ bootblock-$(CONFIG_MICROCODE_UPDATE_PRE_RAM) += microcode_asm.S bootblock-$(CONFIG_SUPPORT_CPU_UCODE_IN_CBFS) += microcode.c ramstage-$(CONFIG_SUPPORT_CPU_UCODE_IN_CBFS) += microcode.c romstage-$(CONFIG_SUPPORT_CPU_UCODE_IN_CBFS) += microcode.c + +# Pack individual microcodes per CPUID from CONFIG_CPU_INTEL_UCODE_SPLIT_BINARIES directory into the CBFS. +ifeq ($(CONFIG_CPU_INTEL_MICROCODE_CBFS_SPLIT_BINS),y) +microcode-params-dir := $(call strip_quotes,$(CONFIG_CPU_INTEL_UCODE_SPLIT_BINARIES))/ +microcode-params := $(shell find "$(microcode-params-dir)" -type f -exec basename {} \;) + +# Make "cpu_microcode_$(CPUID).bin" file entry into the FIT table +$(call add_intermediate, add_mcu_fit, set_fit_ptr $(IFITTOOL)) + $(foreach params, $(microcode-params), $(shell $(IFITTOOL) -f $< -a -n $(params) -t 1 \ + -s $(CONFIG_CPU_INTEL_NUM_FIT_ENTRIES) -r COREBOOT)) true + +# Add "cpu_microcode_$(CPUID).bin" file into the CBFS +$(foreach params,$(microcode-params), \ + $(eval cbfs-files-y += $(params)) \ + $(eval $(params)-file := $(microcode-params-dir)/$(params)) \ + $(eval $(params)-type := microcode) \ + $(eval $(params)-align := $(if $(filter y,$(CONFIG_SOC_AMD_COMMON_BLOCK_LPC_SPI_DMA)),64,16)) \ +) + +endif diff --git a/src/cpu/intel/microcode/microcode.c b/src/cpu/intel/microcode/microcode.c index 6f6e2f12d0..0d52bafb31 100644 --- a/src/cpu/intel/microcode/microcode.c +++ b/src/cpu/intel/microcode/microcode.c @@ -8,6 +8,7 @@ #include <cpu/intel/microcode.h> #include <cpu/x86/msr.h> #include <smp/spinlock.h> +#include <stdio.h> #include <types.h> DECLARE_SPIN_LOCK(microcode_lock) @@ -170,10 +171,6 @@ static const void *find_cbfs_microcode(void) msr_t msr; struct cpuinfo_x86 c; - ucode_updates = cbfs_map(MICROCODE_CBFS_FILE, µcode_len); - if (ucode_updates == NULL) - return NULL; - rev = read_microcode_rev(); eax = cpuid_eax(1); get_fms(&c, eax); @@ -188,6 +185,16 @@ static const void *find_cbfs_microcode(void) printk(BIOS_DEBUG, "microcode: sig=0x%x pf=0x%x revision=0x%x\n", sig, pf, rev); + if (CONFIG(CPU_INTEL_MICROCODE_CBFS_SPLIT_BINS)) { + char cbfs_filename[25]; + snprintf(cbfs_filename, sizeof(cbfs_filename), "cpu_microcode_%x.bin", sig); + ucode_updates = cbfs_map(cbfs_filename, µcode_len); + } else { + ucode_updates = cbfs_map(MICROCODE_CBFS_FILE, µcode_len); + } + if (ucode_updates == NULL) + return NULL; + while (microcode_len >= sizeof(*ucode_updates)) { /* Newer microcode updates include a size field, whereas older * containers set it at 0 and are exactly 2048 bytes long */ |