diff options
author | Linus Torvalds | 2024-07-16 12:22:07 -0700 |
---|---|---|
committer | Linus Torvalds | 2024-07-16 12:22:07 -0700 |
commit | e55037c879a087a57d775e848a58430ab3380fc1 (patch) | |
tree | f12f19aba55d8cc305f6b6bad1c166685ed37b45 /drivers/firmware | |
parent | d80f2996b8502779c39221a9e7c9ea7e361c0ae4 (diff) | |
parent | 4a2ebb082297f41803742729642961532e54079e (diff) |
Merge tag 'efi-next-for-v6.11' of git://git.kernel.org/pub/scm/linux/kernel/git/efi/efi
Pull EFI updates from Ard Biesheuvel:
"Note the removal of the EFI fake memory map support - this is believed
to be unused and no longer worth supporting. However, we could easily
bring it back if needed.
With recent developments regarding confidential VMs and unaccepted
memory, combined with kexec, creating a known inaccurate view of the
firmware's memory map and handing it to the OS is a feature we can
live without, hence the removal. Alternatively, I could imagine making
this feature mutually exclusive with those confidential VM related
features, but let's try simply removing it first.
Summary:
- Drop support for the 'fake' EFI memory map on x86
- Add an SMBIOS based tweak to the EFI stub instructing the firmware
on x86 Macbook Pros to keep both GPUs enabled
- Replace 0-sized array with flexible array in EFI memory attributes
table handling
- Drop redundant BSS clearing when booting via the native PE
entrypoint on x86
- Avoid returning EFI_SUCCESS when aborting on an out-of-memory
condition
- Cosmetic tweak for arm64 KASLR loading logic"
* tag 'efi-next-for-v6.11' of git://git.kernel.org/pub/scm/linux/kernel/git/efi/efi:
efi: Replace efi_memory_attributes_table_t 0-sized array with flexible array
efi: Rename efi_early_memdesc_ptr() to efi_memdesc_ptr()
arm64/efistub: Clean up KASLR logic
x86/efistub: Drop redundant clearing of BSS
x86/efistub: Avoid returning EFI_SUCCESS on error
x86/efistub: Call Apple set_os protocol on dual GPU Intel Macs
x86/efistub: Enable SMBIOS protocol handling for x86
efistub/smbios: Simplify SMBIOS enumeration API
x86/efi: Drop support for fake EFI memory maps
Diffstat (limited to 'drivers/firmware')
-rw-r--r-- | drivers/firmware/efi/libstub/Makefile | 2 | ||||
-rw-r--r-- | drivers/firmware/efi/libstub/arm64-stub.c | 13 | ||||
-rw-r--r-- | drivers/firmware/efi/libstub/arm64.c | 3 | ||||
-rw-r--r-- | drivers/firmware/efi/libstub/efistub.h | 9 | ||||
-rw-r--r-- | drivers/firmware/efi/libstub/kaslr.c | 20 | ||||
-rw-r--r-- | drivers/firmware/efi/libstub/relocate.c | 2 | ||||
-rw-r--r-- | drivers/firmware/efi/libstub/smbios.c | 43 | ||||
-rw-r--r-- | drivers/firmware/efi/libstub/unaccepted_memory.c | 2 | ||||
-rw-r--r-- | drivers/firmware/efi/libstub/x86-stub.c | 83 | ||||
-rw-r--r-- | drivers/firmware/efi/memattr.c | 2 |
10 files changed, 120 insertions, 59 deletions
diff --git a/drivers/firmware/efi/libstub/Makefile b/drivers/firmware/efi/libstub/Makefile index 06f0428a723c..1f32d6cf98d6 100644 --- a/drivers/firmware/efi/libstub/Makefile +++ b/drivers/firmware/efi/libstub/Makefile @@ -76,7 +76,7 @@ lib-$(CONFIG_EFI_GENERIC_STUB) += efi-stub.o string.o intrinsics.o systable.o \ lib-$(CONFIG_ARM) += arm32-stub.o lib-$(CONFIG_ARM64) += kaslr.o arm64.o arm64-stub.o smbios.o -lib-$(CONFIG_X86) += x86-stub.o +lib-$(CONFIG_X86) += x86-stub.o smbios.o lib-$(CONFIG_X86_64) += x86-5lvl.o lib-$(CONFIG_RISCV) += kaslr.o riscv.o riscv-stub.o lib-$(CONFIG_LOONGARCH) += loongarch.o loongarch-stub.o diff --git a/drivers/firmware/efi/libstub/arm64-stub.c b/drivers/firmware/efi/libstub/arm64-stub.c index 452b7ccd330e..2c3869356147 100644 --- a/drivers/firmware/efi/libstub/arm64-stub.c +++ b/drivers/firmware/efi/libstub/arm64-stub.c @@ -21,7 +21,6 @@ efi_status_t handle_kernel_image(unsigned long *image_addr, efi_loaded_image_t *image, efi_handle_t image_handle) { - efi_status_t status; unsigned long kernel_size, kernel_codesize, kernel_memsize; if (image->image_base != _text) { @@ -39,15 +38,9 @@ efi_status_t handle_kernel_image(unsigned long *image_addr, *reserve_size = kernel_memsize; *image_addr = (unsigned long)_text; - status = efi_kaslr_relocate_kernel(image_addr, - reserve_addr, reserve_size, - kernel_size, kernel_codesize, - kernel_memsize, - efi_kaslr_get_phys_seed(image_handle)); - if (status != EFI_SUCCESS) - return status; - - return EFI_SUCCESS; + return efi_kaslr_relocate_kernel(image_addr, reserve_addr, reserve_size, + kernel_size, kernel_codesize, kernel_memsize, + efi_kaslr_get_phys_seed(image_handle)); } asmlinkage void primary_entry(void); diff --git a/drivers/firmware/efi/libstub/arm64.c b/drivers/firmware/efi/libstub/arm64.c index 446e35eaf3d9..e57cd3de0a00 100644 --- a/drivers/firmware/efi/libstub/arm64.c +++ b/drivers/firmware/efi/libstub/arm64.c @@ -39,8 +39,7 @@ static bool system_needs_vamap(void) static char const emag[] = "eMAG"; default: - version = efi_get_smbios_string(&record->header, 4, - processor_version); + version = efi_get_smbios_string(record, processor_version); if (!version || (strncmp(version, altra, sizeof(altra) - 1) && strncmp(version, emag, sizeof(emag) - 1))) break; diff --git a/drivers/firmware/efi/libstub/efistub.h b/drivers/firmware/efi/libstub/efistub.h index 27abb4ce0291..d33ccbc4a2c6 100644 --- a/drivers/firmware/efi/libstub/efistub.h +++ b/drivers/firmware/efi/libstub/efistub.h @@ -1204,14 +1204,13 @@ struct efi_smbios_type4_record { u16 thread_enabled; }; -#define efi_get_smbios_string(__record, __type, __name) ({ \ - int off = offsetof(struct efi_smbios_type ## __type ## _record, \ - __name); \ - __efi_get_smbios_string((__record), __type, off); \ +#define efi_get_smbios_string(__record, __field) ({ \ + __typeof__(__record) __rec = __record; \ + __efi_get_smbios_string(&__rec->header, &__rec->__field); \ }) const u8 *__efi_get_smbios_string(const struct efi_smbios_record *record, - u8 type, int offset); + const u8 *offset); void efi_remap_image(unsigned long image_base, unsigned alloc_size, unsigned long code_size); diff --git a/drivers/firmware/efi/libstub/kaslr.c b/drivers/firmware/efi/libstub/kaslr.c index 1a9808012abd..6318c40bda38 100644 --- a/drivers/firmware/efi/libstub/kaslr.c +++ b/drivers/firmware/efi/libstub/kaslr.c @@ -18,8 +18,6 @@ */ u32 efi_kaslr_get_phys_seed(efi_handle_t image_handle) { - efi_status_t status; - u32 phys_seed; efi_guid_t li_fixed_proto = LINUX_EFI_LOADED_IMAGE_FIXED_GUID; void *p; @@ -32,18 +30,20 @@ u32 efi_kaslr_get_phys_seed(efi_handle_t image_handle) &li_fixed_proto, &p) == EFI_SUCCESS) { efi_info("Image placement fixed by loader\n"); } else { + efi_status_t status; + u32 phys_seed; + status = efi_get_random_bytes(sizeof(phys_seed), (u8 *)&phys_seed); - if (status == EFI_SUCCESS) { + if (status == EFI_SUCCESS) return phys_seed; - } else if (status == EFI_NOT_FOUND) { + + if (status == EFI_NOT_FOUND) efi_info("EFI_RNG_PROTOCOL unavailable\n"); - efi_nokaslr = true; - } else if (status != EFI_SUCCESS) { - efi_err("efi_get_random_bytes() failed (0x%lx)\n", - status); - efi_nokaslr = true; - } + else + efi_err("efi_get_random_bytes() failed (0x%lx)\n", status); + + efi_nokaslr = true; } return 0; diff --git a/drivers/firmware/efi/libstub/relocate.c b/drivers/firmware/efi/libstub/relocate.c index bf6fbd5d22a1..d694bcfa1074 100644 --- a/drivers/firmware/efi/libstub/relocate.c +++ b/drivers/firmware/efi/libstub/relocate.c @@ -48,7 +48,7 @@ efi_status_t efi_low_alloc_above(unsigned long size, unsigned long align, unsigned long m = (unsigned long)map->map; u64 start, end; - desc = efi_early_memdesc_ptr(m, map->desc_size, i); + desc = efi_memdesc_ptr(m, map->desc_size, i); if (desc->type != EFI_CONVENTIONAL_MEMORY) continue; diff --git a/drivers/firmware/efi/libstub/smbios.c b/drivers/firmware/efi/libstub/smbios.c index c217de2cc8d5..f31410d7e7e1 100644 --- a/drivers/firmware/efi/libstub/smbios.c +++ b/drivers/firmware/efi/libstub/smbios.c @@ -6,20 +6,31 @@ #include "efistub.h" -typedef struct efi_smbios_protocol efi_smbios_protocol_t; - -struct efi_smbios_protocol { - efi_status_t (__efiapi *add)(efi_smbios_protocol_t *, efi_handle_t, - u16 *, struct efi_smbios_record *); - efi_status_t (__efiapi *update_string)(efi_smbios_protocol_t *, u16 *, - unsigned long *, u8 *); - efi_status_t (__efiapi *remove)(efi_smbios_protocol_t *, u16); - efi_status_t (__efiapi *get_next)(efi_smbios_protocol_t *, u16 *, u8 *, - struct efi_smbios_record **, - efi_handle_t *); - - u8 major_version; - u8 minor_version; +typedef union efi_smbios_protocol efi_smbios_protocol_t; + +union efi_smbios_protocol { + struct { + efi_status_t (__efiapi *add)(efi_smbios_protocol_t *, efi_handle_t, + u16 *, struct efi_smbios_record *); + efi_status_t (__efiapi *update_string)(efi_smbios_protocol_t *, u16 *, + unsigned long *, u8 *); + efi_status_t (__efiapi *remove)(efi_smbios_protocol_t *, u16); + efi_status_t (__efiapi *get_next)(efi_smbios_protocol_t *, u16 *, u8 *, + struct efi_smbios_record **, + efi_handle_t *); + + u8 major_version; + u8 minor_version; + }; + struct { + u32 add; + u32 update_string; + u32 remove; + u32 get_next; + + u8 major_version; + u8 minor_version; + } mixed_mode; }; const struct efi_smbios_record *efi_get_smbios_record(u8 type) @@ -38,7 +49,7 @@ const struct efi_smbios_record *efi_get_smbios_record(u8 type) } const u8 *__efi_get_smbios_string(const struct efi_smbios_record *record, - u8 type, int offset) + const u8 *offset) { const u8 *strtable; @@ -46,7 +57,7 @@ const u8 *__efi_get_smbios_string(const struct efi_smbios_record *record, return NULL; strtable = (u8 *)record + record->length; - for (int i = 1; i < ((u8 *)record)[offset]; i++) { + for (int i = 1; i < *offset; i++) { int len = strlen(strtable); if (!len) diff --git a/drivers/firmware/efi/libstub/unaccepted_memory.c b/drivers/firmware/efi/libstub/unaccepted_memory.c index 9a655f30ba47..c295ea3a6efc 100644 --- a/drivers/firmware/efi/libstub/unaccepted_memory.c +++ b/drivers/firmware/efi/libstub/unaccepted_memory.c @@ -29,7 +29,7 @@ efi_status_t allocate_unaccepted_bitmap(__u32 nr_desc, efi_memory_desc_t *d; unsigned long m = (unsigned long)map->map; - d = efi_early_memdesc_ptr(m, map->desc_size, i); + d = efi_memdesc_ptr(m, map->desc_size, i); if (d->type != EFI_UNACCEPTED_MEMORY) continue; diff --git a/drivers/firmware/efi/libstub/x86-stub.c b/drivers/firmware/efi/libstub/x86-stub.c index 1983fd3bf392..078055b054e3 100644 --- a/drivers/firmware/efi/libstub/x86-stub.c +++ b/drivers/firmware/efi/libstub/x86-stub.c @@ -225,6 +225,68 @@ static void retrieve_apple_device_properties(struct boot_params *boot_params) } } +static bool apple_match_product_name(void) +{ + static const char type1_product_matches[][15] = { + "MacBookPro11,3", + "MacBookPro11,5", + "MacBookPro13,3", + "MacBookPro14,3", + "MacBookPro15,1", + "MacBookPro15,3", + "MacBookPro16,1", + "MacBookPro16,4", + }; + const struct efi_smbios_type1_record *record; + const u8 *product; + + record = (struct efi_smbios_type1_record *)efi_get_smbios_record(1); + if (!record) + return false; + + product = efi_get_smbios_string(record, product_name); + if (!product) + return false; + + for (int i = 0; i < ARRAY_SIZE(type1_product_matches); i++) { + if (!strcmp(product, type1_product_matches[i])) + return true; + } + + return false; +} + +static void apple_set_os(void) +{ + struct { + unsigned long version; + efi_status_t (__efiapi *set_os_version)(const char *); + efi_status_t (__efiapi *set_os_vendor)(const char *); + } *set_os; + efi_status_t status; + + if (!efi_is_64bit() || !apple_match_product_name()) + return; + + status = efi_bs_call(locate_protocol, &APPLE_SET_OS_PROTOCOL_GUID, NULL, + (void **)&set_os); + if (status != EFI_SUCCESS) + return; + + if (set_os->version >= 2) { + status = set_os->set_os_vendor("Apple Inc."); + if (status != EFI_SUCCESS) + efi_err("Failed to set OS vendor via apple_set_os\n"); + } + + if (set_os->version > 0) { + /* The version being set doesn't seem to matter */ + status = set_os->set_os_version("Mac OS X 10.9"); + if (status != EFI_SUCCESS) + efi_err("Failed to set OS version via apple_set_os\n"); + } +} + efi_status_t efi_adjust_memory_range_protection(unsigned long start, unsigned long size) { @@ -335,9 +397,12 @@ static const efi_char16_t apple[] = L"Apple"; static void setup_quirks(struct boot_params *boot_params) { - if (IS_ENABLED(CONFIG_APPLE_PROPERTIES) && - !memcmp(efistub_fw_vendor(), apple, sizeof(apple))) - retrieve_apple_device_properties(boot_params); + if (!memcmp(efistub_fw_vendor(), apple, sizeof(apple))) { + if (IS_ENABLED(CONFIG_APPLE_PROPERTIES)) + retrieve_apple_device_properties(boot_params); + + apple_set_os(); + } } /* @@ -476,9 +541,6 @@ efi_status_t __efiapi efi_pe_entry(efi_handle_t handle, efi_status_t status; char *cmdline_ptr; - if (efi_is_native()) - memset(_bss, 0, _ebss - _bss); - efi_system_table = sys_table_arg; /* Check if we were booted by the EFI firmware */ @@ -501,16 +563,13 @@ efi_status_t __efiapi efi_pe_entry(efi_handle_t handle, /* Convert unicode cmdline to ascii */ cmdline_ptr = efi_convert_cmdline(image, &options_size); if (!cmdline_ptr) - goto fail; + efi_exit(handle, EFI_OUT_OF_RESOURCES); efi_set_u64_split((unsigned long)cmdline_ptr, &hdr->cmd_line_ptr, &boot_params.ext_cmd_line_ptr); efi_stub_entry(handle, sys_table_arg, &boot_params); /* not reached */ - -fail: - efi_exit(handle, status); } static void add_e820ext(struct boot_params *params, @@ -555,7 +614,7 @@ setup_e820(struct boot_params *params, struct setup_data *e820ext, u32 e820ext_s m |= (u64)efi->efi_memmap_hi << 32; #endif - d = efi_early_memdesc_ptr(m, efi->efi_memdesc_size, i); + d = efi_memdesc_ptr(m, efi->efi_memdesc_size, i); switch (d->type) { case EFI_RESERVED_TYPE: case EFI_RUNTIME_SERVICES_CODE: @@ -781,7 +840,7 @@ static const char *cmdline_memmap_override; static efi_status_t parse_options(const char *cmdline) { static const char opts[][14] = { - "mem=", "memmap=", "efi_fake_mem=", "hugepages=" + "mem=", "memmap=", "hugepages=" }; for (int i = 0; i < ARRAY_SIZE(opts); i++) { diff --git a/drivers/firmware/efi/memattr.c b/drivers/firmware/efi/memattr.c index ab85bf8e165a..164203429fa7 100644 --- a/drivers/firmware/efi/memattr.c +++ b/drivers/firmware/efi/memattr.c @@ -164,7 +164,7 @@ int __init efi_memattr_apply_permissions(struct mm_struct *mm, bool valid; char buf[64]; - valid = entry_is_valid((void *)tbl->entry + i * tbl->desc_size, + valid = entry_is_valid(efi_memdesc_ptr(tbl->entry, tbl->desc_size, i), &md); size = md.num_pages << EFI_PAGE_SHIFT; if (efi_enabled(EFI_DBG) || !valid) |