Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge tag 'efi-fixes-for-v6.1-3' of git://git.kernel.org/pub/scm/linux/kernel/git/efi/efi

Pull EFI fixes from Ard Biesheuvel:

- Force the use of SetVirtualAddressMap() on Ampera Altra arm64
machines, which crash in SetTime() if no virtual remapping is used

This is the first time we've added an SMBIOS based quirk on arm64,
but fortunately, we can just call a EFI protocol to grab the type #1
SMBIOS record when running in the stub, so we don't need all the
machinery we have in the kernel proper to parse SMBIOS data.

- Drop a spurious warning on misaligned runtime regions when using 16k
or 64k pages on arm64

* tag 'efi-fixes-for-v6.1-3' of git://git.kernel.org/pub/scm/linux/kernel/git/efi/efi:
arm64: efi: Fix handling of misaligned runtime regions and drop warning
arm64: efi: Force the use of SetVirtualAddressMap() on Altra machines

+128 -20
+34 -18
arch/arm64/kernel/efi.c
··· 13 13 14 14 #include <asm/efi.h> 15 15 16 + static bool region_is_misaligned(const efi_memory_desc_t *md) 17 + { 18 + if (PAGE_SIZE == EFI_PAGE_SIZE) 19 + return false; 20 + return !PAGE_ALIGNED(md->phys_addr) || 21 + !PAGE_ALIGNED(md->num_pages << EFI_PAGE_SHIFT); 22 + } 23 + 16 24 /* 17 25 * Only regions of type EFI_RUNTIME_SERVICES_CODE need to be 18 26 * executable, everything else can be mapped with the XN bits ··· 34 26 if (type == EFI_MEMORY_MAPPED_IO) 35 27 return PROT_DEVICE_nGnRE; 36 28 37 - if (WARN_ONCE(!PAGE_ALIGNED(md->phys_addr), 38 - "UEFI Runtime regions are not aligned to 64 KB -- buggy firmware?")) 29 + if (region_is_misaligned(md)) { 30 + static bool __initdata code_is_misaligned; 31 + 39 32 /* 40 - * If the region is not aligned to the page size of the OS, we 41 - * can not use strict permissions, since that would also affect 42 - * the mapping attributes of the adjacent regions. 33 + * Regions that are not aligned to the OS page size cannot be 34 + * mapped with strict permissions, as those might interfere 35 + * with the permissions that are needed by the adjacent 36 + * region's mapping. However, if we haven't encountered any 37 + * misaligned runtime code regions so far, we can safely use 38 + * non-executable permissions for non-code regions. 43 39 */ 44 - return pgprot_val(PAGE_KERNEL_EXEC); 40 + code_is_misaligned |= (type == EFI_RUNTIME_SERVICES_CODE); 41 + 42 + return code_is_misaligned ? pgprot_val(PAGE_KERNEL_EXEC) 43 + : pgprot_val(PAGE_KERNEL); 44 + } 45 45 46 46 /* R-- */ 47 47 if ((attr & (EFI_MEMORY_XP | EFI_MEMORY_RO)) == ··· 80 64 bool page_mappings_only = (md->type == EFI_RUNTIME_SERVICES_CODE || 81 65 md->type == EFI_RUNTIME_SERVICES_DATA); 82 66 83 - if (!PAGE_ALIGNED(md->phys_addr) || 84 - !PAGE_ALIGNED(md->num_pages << EFI_PAGE_SHIFT)) { 85 - /* 86 - * If the end address of this region is not aligned to page 87 - * size, the mapping is rounded up, and may end up sharing a 88 - * page frame with the next UEFI memory region. If we create 89 - * a block entry now, we may need to split it again when mapping 90 - * the next region, and support for that is going to be removed 91 - * from the MMU routines. So avoid block mappings altogether in 92 - * that case. 93 - */ 67 + /* 68 + * If this region is not aligned to the page size used by the OS, the 69 + * mapping will be rounded outwards, and may end up sharing a page 70 + * frame with an adjacent runtime memory region. Given that the page 71 + * table descriptor covering the shared page will be rewritten when the 72 + * adjacent region gets mapped, we must avoid block mappings here so we 73 + * don't have to worry about splitting them when that happens. 74 + */ 75 + if (region_is_misaligned(md)) 94 76 page_mappings_only = true; 95 - } 96 77 97 78 create_pgd_mapping(mm, md->phys_addr, md->virt_addr, 98 79 md->num_pages << EFI_PAGE_SHIFT, ··· 115 102 { 116 103 BUG_ON(md->type != EFI_RUNTIME_SERVICES_CODE && 117 104 md->type != EFI_RUNTIME_SERVICES_DATA); 105 + 106 + if (region_is_misaligned(md)) 107 + return 0; 118 108 119 109 /* 120 110 * Calling apply_to_page_range() is only safe on regions that are
+1 -1
drivers/firmware/efi/libstub/Makefile
··· 82 82 lib-$(CONFIG_EFI_GENERIC_STUB) += efi-stub.o string.o intrinsics.o systable.o 83 83 84 84 lib-$(CONFIG_ARM) += arm32-stub.o 85 - lib-$(CONFIG_ARM64) += arm64-stub.o 85 + lib-$(CONFIG_ARM64) += arm64-stub.o smbios.o 86 86 lib-$(CONFIG_X86) += x86-stub.o 87 87 lib-$(CONFIG_RISCV) += riscv-stub.o 88 88 lib-$(CONFIG_LOONGARCH) += loongarch-stub.o
+16 -1
drivers/firmware/efi/libstub/arm64-stub.c
··· 15 15 16 16 #include "efistub.h" 17 17 18 + static bool system_needs_vamap(void) 19 + { 20 + const u8 *type1_family = efi_get_smbios_string(1, family); 21 + 22 + /* 23 + * Ampere Altra machines crash in SetTime() if SetVirtualAddressMap() 24 + * has not been called prior. 25 + */ 26 + if (!type1_family || strcmp(type1_family, "Altra")) 27 + return false; 28 + 29 + efi_warn("Working around broken SetVirtualAddressMap()\n"); 30 + return true; 31 + } 32 + 18 33 efi_status_t check_platform_features(void) 19 34 { 20 35 u64 tg; ··· 39 24 * UEFI runtime regions 1:1 and so calling SetVirtualAddressMap() is 40 25 * unnecessary. 41 26 */ 42 - if (VA_BITS_MIN >= 48) 27 + if (VA_BITS_MIN >= 48 && !system_needs_vamap()) 43 28 efi_novamap = true; 44 29 45 30 /* UEFI mandates support for 4 KB granularity, no need to check */
+28
drivers/firmware/efi/libstub/efistub.h
··· 975 975 976 976 void efi_retrieve_tpm2_eventlog(void); 977 977 978 + struct efi_smbios_record { 979 + u8 type; 980 + u8 length; 981 + u16 handle; 982 + }; 983 + 984 + struct efi_smbios_type1_record { 985 + struct efi_smbios_record header; 986 + 987 + u8 manufacturer; 988 + u8 product_name; 989 + u8 version; 990 + u8 serial_number; 991 + efi_guid_t uuid; 992 + u8 wakeup_type; 993 + u8 sku_number; 994 + u8 family; 995 + }; 996 + 997 + #define efi_get_smbios_string(__type, __name) ({ \ 998 + int size = sizeof(struct efi_smbios_type ## __type ## _record); \ 999 + int off = offsetof(struct efi_smbios_type ## __type ## _record, \ 1000 + __name); \ 1001 + __efi_get_smbios_string(__type, off, size); \ 1002 + }) 1003 + 1004 + const u8 *__efi_get_smbios_string(u8 type, int offset, int recsize); 1005 + 978 1006 #endif
+48
drivers/firmware/efi/libstub/smbios.c
··· 1 + // SPDX-License-Identifier: GPL-2.0-only 2 + // Copyright 2022 Google LLC 3 + // Author: Ard Biesheuvel <ardb@google.com> 4 + 5 + #include <linux/efi.h> 6 + 7 + #include "efistub.h" 8 + 9 + typedef struct efi_smbios_protocol efi_smbios_protocol_t; 10 + 11 + struct efi_smbios_protocol { 12 + efi_status_t (__efiapi *add)(efi_smbios_protocol_t *, efi_handle_t, 13 + u16 *, struct efi_smbios_record *); 14 + efi_status_t (__efiapi *update_string)(efi_smbios_protocol_t *, u16 *, 15 + unsigned long *, u8 *); 16 + efi_status_t (__efiapi *remove)(efi_smbios_protocol_t *, u16); 17 + efi_status_t (__efiapi *get_next)(efi_smbios_protocol_t *, u16 *, u8 *, 18 + struct efi_smbios_record **, 19 + efi_handle_t *); 20 + 21 + u8 major_version; 22 + u8 minor_version; 23 + }; 24 + 25 + const u8 *__efi_get_smbios_string(u8 type, int offset, int recsize) 26 + { 27 + struct efi_smbios_record *record; 28 + efi_smbios_protocol_t *smbios; 29 + efi_status_t status; 30 + u16 handle = 0xfffe; 31 + const u8 *strtable; 32 + 33 + status = efi_bs_call(locate_protocol, &EFI_SMBIOS_PROTOCOL_GUID, NULL, 34 + (void **)&smbios) ?: 35 + efi_call_proto(smbios, get_next, &handle, &type, &record, NULL); 36 + if (status != EFI_SUCCESS) 37 + return NULL; 38 + 39 + strtable = (u8 *)record + recsize; 40 + for (int i = 1; i < ((u8 *)record)[offset]; i++) { 41 + int len = strlen(strtable); 42 + 43 + if (!len) 44 + return NULL; 45 + strtable += len + 1; 46 + } 47 + return strtable; 48 + }
+1
include/linux/efi.h
··· 389 389 #define EFI_LOAD_FILE2_PROTOCOL_GUID EFI_GUID(0x4006c0c1, 0xfcb3, 0x403e, 0x99, 0x6d, 0x4a, 0x6c, 0x87, 0x24, 0xe0, 0x6d) 390 390 #define EFI_RT_PROPERTIES_TABLE_GUID EFI_GUID(0xeb66918a, 0x7eef, 0x402a, 0x84, 0x2e, 0x93, 0x1d, 0x21, 0xc3, 0x8a, 0xe9) 391 391 #define EFI_DXE_SERVICES_TABLE_GUID EFI_GUID(0x05ad34ba, 0x6f02, 0x4214, 0x95, 0x2e, 0x4d, 0xa0, 0x39, 0x8e, 0x2b, 0xb9) 392 + #define EFI_SMBIOS_PROTOCOL_GUID EFI_GUID(0x03583ff6, 0xcb36, 0x4940, 0x94, 0x7e, 0xb9, 0xb3, 0x9f, 0x4a, 0xfa, 0xf7) 392 393 393 394 #define EFI_IMAGE_SECURITY_DATABASE_GUID EFI_GUID(0xd719b2cb, 0x3d3a, 0x4596, 0xa3, 0xbc, 0xda, 0xd0, 0x0e, 0x67, 0x65, 0x6f) 394 395 #define EFI_SHIM_LOCK_GUID EFI_GUID(0x605dab50, 0xe046, 0x4300, 0xab, 0xb6, 0x3d, 0xd8, 0x10, 0xdd, 0x8b, 0x23)