x86/microcode: Parse built-in microcode early
Apparently, people do build microcode into the kernel image, i.e. CONFIG_FIRMWARE_IN_KERNEL=y. Make that work in the early loader which is where microcode should be preferably loaded anyway. Note that you need to specify the microcode filename with the path relative to the toplevel firmware directory (the same like the late loading method) in CONFIG_EXTRA_FIRMWARE=y so that early loader can find it. I.e., something like this (Intel variant): CONFIG_FIRMWARE_IN_KERNEL=y CONFIG_EXTRA_FIRMWARE="intel-ucode/06-3a-09" CONFIG_EXTRA_FIRMWARE_DIR="/lib/firmware/" While at it, add me to the loader copyright boilerplate. Signed-off-by: Borislav Petkov <bp@suse.de> Cc: Borislav Petkov <bp@alien8.de> Cc: Daniel J Blueman <daniel@numascale.com> Cc: H. Peter Anvin <hpa@zytor.com> Cc: Thomas Gleixner <tglx@linutronix.de> Signed-off-by: Ingo Molnar <mingo@kernel.org>
This commit is contained in:

committed by
Ingo Molnar

parent
da9b50765e
commit
760d765b2b
@@ -228,7 +228,18 @@ static void apply_ucode_in_initrd(void *ucode, size_t size, bool save_patch)
|
||||
}
|
||||
}
|
||||
|
||||
void __init load_ucode_amd_bsp(void)
|
||||
static bool __init load_builtin_amd_microcode(struct cpio_data *cp, int family)
|
||||
{
|
||||
char fw_name[36] = "amd-ucode/microcode_amd.bin";
|
||||
|
||||
if (family >= 0x15)
|
||||
snprintf(fw_name, sizeof(fw_name),
|
||||
"amd-ucode/microcode_amd_fam%.2xh.bin", family);
|
||||
|
||||
return get_builtin_firmware(cp, fw_name);
|
||||
}
|
||||
|
||||
void __init load_ucode_amd_bsp(int family)
|
||||
{
|
||||
struct cpio_data cp;
|
||||
void **data;
|
||||
@@ -243,8 +254,10 @@ void __init load_ucode_amd_bsp(void)
|
||||
#endif
|
||||
|
||||
cp = find_ucode_in_initrd();
|
||||
if (!cp.data)
|
||||
return;
|
||||
if (!cp.data) {
|
||||
if (!load_builtin_amd_microcode(&cp, family))
|
||||
return;
|
||||
}
|
||||
|
||||
*data = cp.data;
|
||||
*size = cp.size;
|
||||
|
@@ -3,6 +3,7 @@
|
||||
*
|
||||
* Copyright (C) 2012 Fenghua Yu <fenghua.yu@intel.com>
|
||||
* H Peter Anvin" <hpa@zytor.com>
|
||||
* (C) 2015 Borislav Petkov <bp@alien8.de>
|
||||
*
|
||||
* This driver allows to early upgrade microcode on Intel processors
|
||||
* belonging to IA-32 family - PentiumPro, Pentium II,
|
||||
@@ -17,6 +18,7 @@
|
||||
* 2 of the License, or (at your option) any later version.
|
||||
*/
|
||||
#include <linux/module.h>
|
||||
#include <linux/firmware.h>
|
||||
#include <asm/microcode.h>
|
||||
#include <asm/microcode_intel.h>
|
||||
#include <asm/microcode_amd.h>
|
||||
@@ -43,6 +45,25 @@ static bool __init check_loader_disabled_bsp(void)
|
||||
return *res;
|
||||
}
|
||||
|
||||
extern struct builtin_fw __start_builtin_fw[];
|
||||
extern struct builtin_fw __end_builtin_fw[];
|
||||
|
||||
bool get_builtin_firmware(struct cpio_data *cd, const char *name)
|
||||
{
|
||||
#ifdef CONFIG_FW_LOADER
|
||||
struct builtin_fw *b_fw;
|
||||
|
||||
for (b_fw = __start_builtin_fw; b_fw != __end_builtin_fw; b_fw++) {
|
||||
if (!strcmp(name, b_fw->name)) {
|
||||
cd->size = b_fw->size;
|
||||
cd->data = b_fw->data;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
||||
void __init load_ucode_bsp(void)
|
||||
{
|
||||
int vendor, family;
|
||||
@@ -63,7 +84,7 @@ void __init load_ucode_bsp(void)
|
||||
break;
|
||||
case X86_VENDOR_AMD:
|
||||
if (family >= 0x10)
|
||||
load_ucode_amd_bsp();
|
||||
load_ucode_amd_bsp(family);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
@@ -521,6 +521,23 @@ out:
|
||||
EXPORT_SYMBOL_GPL(save_mc_for_early);
|
||||
#endif
|
||||
|
||||
static bool __init load_builtin_intel_microcode(struct cpio_data *cp)
|
||||
{
|
||||
u32 eax = 0x00000001, ebx, ecx = 0, edx;
|
||||
int family, model, stepping;
|
||||
char name[30];
|
||||
|
||||
native_cpuid(&eax, &ebx, &ecx, &edx);
|
||||
|
||||
family = __x86_family(eax);
|
||||
model = x86_model(eax);
|
||||
stepping = eax & 0xf;
|
||||
|
||||
sprintf(name, "intel-ucode/%02x-%02x-%02x", family, model, stepping);
|
||||
|
||||
return get_builtin_firmware(cp, name);
|
||||
}
|
||||
|
||||
static __initdata char ucode_name[] = "kernel/x86/microcode/GenuineIntel.bin";
|
||||
static __init enum ucode_state
|
||||
scan_microcode(struct mc_saved_data *mc_saved_data, unsigned long *initrd,
|
||||
@@ -539,8 +556,10 @@ scan_microcode(struct mc_saved_data *mc_saved_data, unsigned long *initrd,
|
||||
cd.size = 0;
|
||||
|
||||
cd = find_cpio_data(p, (void *)start, size, &offset);
|
||||
if (!cd.data)
|
||||
return UCODE_ERROR;
|
||||
if (!cd.data) {
|
||||
if (!load_builtin_intel_microcode(&cd))
|
||||
return UCODE_ERROR;
|
||||
}
|
||||
|
||||
return get_matching_model_microcode(0, start, cd.data, cd.size,
|
||||
mc_saved_data, initrd, uci);
|
||||
|
Reference in New Issue
Block a user