From 11f8b65a797d8bb721a0223542f5f6ce42fc3474 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Duval?= Date: Thu, 20 Feb 2020 17:20:54 +0100 Subject: [PATCH] boot_loader: load intel microcode update data file MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Previous version of the patch was broken by the EFI refactoring. Change-Id: I6dd125100b22b2461c531bfd8f81b3dd28e2b751 Reviewed-on: https://review.haiku-os.org/c/haiku/+/2409 Reviewed-by: Jérôme Duval --- .../private/kernel/boot/arch/x86/arch_cpu.h | 5 ++ headers/private/kernel/boot/platform.h | 1 + src/system/boot/arch/x86/cpu.cpp | 57 +++++++++++++++++++ src/system/boot/loader/loader.cpp | 2 +- src/system/boot/loader/main.cpp | 1 + src/system/boot/platform/bios_ia32/cpu.cpp | 7 +++ src/system/boot/platform/bios_ia32/long.cpp | 1 + src/system/boot/platform/efi/cpu.cpp | 13 +++++ src/system/boot/platform/efi/start.cpp | 1 + 9 files changed, 87 insertions(+), 1 deletion(-) diff --git a/headers/private/kernel/boot/arch/x86/arch_cpu.h b/headers/private/kernel/boot/arch/x86/arch_cpu.h index 9c697ce3b5..59608e3e25 100644 --- a/headers/private/kernel/boot/arch/x86/arch_cpu.h +++ b/headers/private/kernel/boot/arch/x86/arch_cpu.h @@ -21,4 +21,9 @@ void calculate_cpu_conversion_factor(uint8 channel); } #endif +#include + +void ucode_load(BootVolume& volume); + + #endif /* BOOT_ARCH_CPU_H */ diff --git a/headers/private/kernel/boot/platform.h b/headers/private/kernel/boot/platform.h index 8cbae602a1..3c28b73bff 100644 --- a/headers/private/kernel/boot/platform.h +++ b/headers/private/kernel/boot/platform.h @@ -43,6 +43,7 @@ extern void platform_switch_to_logo(void); extern void platform_switch_to_text_mode(void); extern void platform_start_kernel(void); extern void platform_exit(void); +extern void platform_load_ucode(BootVolume& volume); #ifdef __cplusplus } diff --git a/src/system/boot/arch/x86/cpu.cpp b/src/system/boot/arch/x86/cpu.cpp index 1890f81138..664baec29b 100644 --- a/src/system/boot/arch/x86/cpu.cpp +++ b/src/system/boot/arch/x86/cpu.cpp @@ -17,6 +17,7 @@ #include #include +#include #include #include @@ -311,6 +312,62 @@ slower_sample: } } +extern int open_maybe_packaged(BootVolume& volume, const char* path, + int openMode); + +void +ucode_load(BootVolume& volume) +{ + cpuid_info info; + if (get_current_cpuid(&info, 0, 0) != B_OK + || strncmp(info.eax_0.vendor_id, "GenuineIntel", 12) != 0) + return; + + if (get_current_cpuid(&info, 1, 0) != B_OK) + return; + + char path[128]; + int family = info.eax_1.family; + int model = info.eax_1.model; + if (family == 0x6 || family == 0xf) { + family += info.eax_1.extended_family; + model += (info.eax_1.extended_model << 4); + } + snprintf(path, sizeof(path), "system/data/firmware/intel-ucode/" + "%02x-%02x-%02x", family, model, info.eax_1.stepping); + dprintf("ucode_load: %s\n", path); + + int fd = open_maybe_packaged(volume, path, O_RDONLY); + if (fd < B_OK) { + dprintf("ucode_load: couldn't find microcode\n"); + return; + } + struct stat stat; + if (fstat(fd, &stat) < 0) { + dprintf("ucode_load: couldn't stat microcode file\n"); + close(fd); + return; + } + + ssize_t length = stat.st_size; + const uint32 alignment = 16; +#define ALIGN(size, align) (((size) + align - 1) & ~(align - 1)) + void *buffer = kernel_args_malloc(length + alignment - 1); + if (buffer != NULL) { + buffer = (void*)ALIGN((addr_t)buffer, alignment); + if (read(fd, buffer, length) != length) { + dprintf("ucode_load: couldn't read microcode file\n"); + kernel_args_free(buffer); + } else { + gKernelArgs.ucode_data = buffer; + gKernelArgs.ucode_data_size = length; + dprintf("ucode_load: microcode file read in memory\n"); + } + } + + close(fd); +} + extern "C" bigtime_t system_time() diff --git a/src/system/boot/loader/loader.cpp b/src/system/boot/loader/loader.cpp index e19234402b..32e1a064df 100644 --- a/src/system/boot/loader/loader.cpp +++ b/src/system/boot/loader/loader.cpp @@ -55,7 +55,7 @@ static const char *sAddonPaths[] = { }; -static int +int open_maybe_packaged(BootVolume& volume, const char* path, int openMode) { if (strncmp(path, kSystemDirectoryPrefix, strlen(kSystemDirectoryPrefix)) diff --git a/src/system/boot/loader/main.cpp b/src/system/boot/loader/main.cpp index 73b66da682..d4a41c54e3 100644 --- a/src/system/boot/loader/main.cpp +++ b/src/system/boot/loader/main.cpp @@ -128,6 +128,7 @@ main(stage2_args *args) gKernelArgs.ucode_data = NULL; gKernelArgs.ucode_data_size = 0; + platform_load_ucode(bootVolume); // apply boot settings apply_boot_settings(); diff --git a/src/system/boot/platform/bios_ia32/cpu.cpp b/src/system/boot/platform/bios_ia32/cpu.cpp index 2d177f7bf7..93a782ffbb 100644 --- a/src/system/boot/platform/bios_ia32/cpu.cpp +++ b/src/system/boot/platform/bios_ia32/cpu.cpp @@ -70,3 +70,10 @@ cpu_init() gKernelArgs.num_cpus = 1; // this will eventually be corrected later on } + + +extern "C" void +platform_load_ucode(BootVolume& volume) +{ + ucode_load(volume); +} diff --git a/src/system/boot/platform/bios_ia32/long.cpp b/src/system/boot/platform/bios_ia32/long.cpp index 2152f99213..c784422d4d 100644 --- a/src/system/boot/platform/bios_ia32/long.cpp +++ b/src/system/boot/platform/bios_ia32/long.cpp @@ -244,6 +244,7 @@ convert_kernel_args() fix_address(gKernelArgs.debug_output); fix_address(gKernelArgs.previous_debug_output); fix_address(gKernelArgs.boot_splash); + fix_address(gKernelArgs.ucode_data); fix_address(gKernelArgs.arch_args.apic); fix_address(gKernelArgs.arch_args.hpet); diff --git a/src/system/boot/platform/efi/cpu.cpp b/src/system/boot/platform/efi/cpu.cpp index 88a3fc5758..aab6ad0102 100644 --- a/src/system/boot/platform/efi/cpu.cpp +++ b/src/system/boot/platform/efi/cpu.cpp @@ -6,8 +6,12 @@ #include +#include #include #include +#ifdef __x86_64__ +# include +#endif void @@ -16,3 +20,12 @@ cpu_init() gKernelArgs.num_cpus = 1; // this will eventually be corrected later on } + + +extern "C" void +platform_load_ucode(BootVolume& volume) +{ +#ifdef __x86_64__ + ucode_load(volume); +#endif +} diff --git a/src/system/boot/platform/efi/start.cpp b/src/system/boot/platform/efi/start.cpp index 9d485b87d7..c0e535c66e 100644 --- a/src/system/boot/platform/efi/start.cpp +++ b/src/system/boot/platform/efi/start.cpp @@ -90,6 +90,7 @@ convert_kernel_args() fix_address(gKernelArgs.debug_output); fix_address(gKernelArgs.boot_splash); #if defined(__x86_64__) || defined(__x86__) + fix_address(gKernelArgs.ucode_data); fix_address(gKernelArgs.arch_args.apic); fix_address(gKernelArgs.arch_args.hpet); #endif