efi: more fixes and general cleanups for v5.6
Ard Biesheuvel
maintainercover efi: more fixes and general cleanups for v5.6
In addition to two other series that are in flight, regarding the EFI runtime call assembly wrappers [0], and the use of restricted memory permissions for mapping EFI runtime service memory regions [1], here's another batch of fixes and cleanups for the early EFI code.
Patches #1 .. #3 are fixes for the code that is currently queued in tip/efi/core.
Patch #4 fixes an ancient issue in the EFI boot code where it doesn't map the memory containing the EFI vendor name string correctly.
Patch #5 redefines the macro __efiapi to __attribute__((regparm(0))) on 32-bit x86 so we no longer have to cast every function pointer that requires that annotation.
Patch #6 refactors efi_runtime_init() so we no longer have two mostly identical copies of the same code for 32-bit and 64-bit.
Patch #7 cleans up efi_systab_init() and also gets rid of the 'efi_phys' data structure that exists for no good reason.
Branch can be found here:
https://git.kernel.org/pub/scm/linux/kernel/git/ardb/linux.git/log/?h=efi-more-cleanup-for-v5.6
[0] https://lore.kernel.org/linux-efi/[email protected]/
[1] https://lore.kernel.org/linux-efi/[email protected]/
Ard Biesheuvel (7):
efi/libstub: fix boot argument handling in mixed mode entry code efi/libstub: use correct system table pointer in mixed mode efi_free() efi/x86: re-disable RT services for 32-bit kernels running on 64-bit
EFI
efi/x86: map the entire EFI vendor string before copying it efi/x86: avoid redundant cast of EFI firmware service pointer efi/x86: merge two near identical versions of efi_runtime_init() efi/x86: clean up efi_systab_init() routine for legibility
arch/x86/boot/compressed/eboot.c | 3 +- arch/x86/boot/compressed/head_64.S | 17 +- arch/x86/include/asm/efi.h | 25 +- arch/x86/platform/efi/efi.c | 262 +++++++++----------- arch/x86/platform/efi/efi_64.c | 5 + include/linux/efi.h | 23 +- 6 files changed, 135 insertions(+), 200 deletions(-)
Signature · 1 line
2.17.1
Ard Biesheuvel
maintainerPATCH 1/7 efi/libstub: fix boot argument handling in mixed mode entry code
The mixed mode refactor actually broke mixed mode by failing to pass the bootparam structure to startup_32(). This went unnoticed because it apparently has a high tolerance for being passed random junk, and still boots fine in some cases. So let's fix this by populating %esi as required when entering via efi32_stub_entry, and while at it, preserve the arguments themselves instead of their address in memory (via the stack pointer) since that memory could be clobbered before we get to it.
--- arch/x86/boot/compressed/head_64.S | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-)
arch/x86/boot/compressed/head_64.S +10 -7
@@ -208,13 +208,12 @@ SYM_FUNC_START(startup_32) pushl $__KERNEL_CS leal startup_64(%ebp), %eax #ifdef CONFIG_EFI_MIXED - movl efi32_boot_args(%ebp), %ebx - cmp $0, %ebx + movl efi32_boot_args(%ebp), %edi + cmp $0, %edi jz 1f leal handover_entry(%ebp), %eax - movl 0(%ebx), %edi - movl 4(%ebx), %esi - movl 8(%ebx), %edx + movl %esi, %edx + movl efi32_boot_args+4(%ebp), %esi movl $0x0, %ecx 1: #endif
@@ -232,12 +231,16 @@ SYM_FUNC_END(startup_32) .org 0x190 SYM_FUNC_START(efi32_stub_entry) add $0x4, %esp /* Discard return address */ + popl %ecx + popl %edx + popl %esi call 1f 1: pop %ebp subl $1b, %ebp - movl %esp, efi32_boot_args(%ebp) + movl %ecx, efi32_boot_args(%ebp) + movl %edx, efi32_boot_args+4(%ebp) sgdtl efi32_boot_gdt(%ebp) /* Disable paging */
@@ -628,7 +631,7 @@ SYM_DATA_START_LOCAL(gdt) SYM_DATA_END_LABEL(gdt, SYM_L_LOCAL, gdt_end) #ifdef CONFIG_EFI_MIXED -SYM_DATA_LOCAL(efi32_boot_args, .long 0) +SYM_DATA_LOCAL(efi32_boot_args, .long 0, 0) #endif /*
Signature · 1 line
2.17.1
Ard Biesheuvel
maintainerPATCH 2/7 efi/libstub: use correct system table pointer in mixed mode efi_free()
In reply to Ard BiesheuvelThere is a special implementation for mixed mode of the efi_free() function, to work around the incompatibility of the mixed mode plumbing with the prototype of the EFI FreePages boot service, which takes a 64-bit physical address as its first argument.
Calling FreePages in mixed mode involves passing the mixed mode address of the FreePages code from the mixed mode version of the EFI system table, and the current code dereferences the ordinary system table instead, producing the wrong results. So fix this by using the efi_table_attr() macro.
--- arch/x86/boot/compressed/eboot.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
arch/x86/boot/compressed/eboot.c +2 -1
@@ -901,7 +901,8 @@ void efi_free(unsigned long size, unsigned long addr)if (efi_is_native ())efi_free_native (size, addr);else -efi64_thunk (efi_system_table ()->boottime->mixed_mode.free_pages, +efi64_thunk (efi_table_attr (efi_system_table (), + boottime)->mixed_mode.free_pages, addr, 0, DIV_ROUND_UP(size, EFI_PAGE_SIZE)); }#endif
Signature · 1 line
2.17.1
Ard Biesheuvel
maintainerPATCH 3/7 efi/x86: re-disable RT services for 32-bit kernels running on 64-bit EFI
In reply to Ard BiesheuvelCommit a8147dba75b1 ("efi/x86: Rename efi_is_native() to efi_is_mixed()") renamed and refactored efi_is_native() into efi_is_mixed(), but failed to take into account that these are not diametrical opposites.
Mixed mode is a construct that permits 64-bit kernels to boot on 32-bit firmware, but there is another non-native combination which is supported, i.e., 32-bit kernels booting on 64-bit firmware, but only for boot and not for runtime services.
Due to this oversight, efi_runtime_supported() now incorrectly returns true for such configurations, resulting in crashes at boot. So fix this by making efi_runtime_supported() aware of this.
As a side effect, some efi_thunk_xxx() stubs have become obsolete, so remove them as well.
--- arch/x86/include/asm/efi.h | 17 +++-------------- 1 file changed, 3 insertions(+), 14 deletions(-)
arch/x86/include/asm/efi.h +3 -14
@@ -163,6 +163,9 @@ static inline bool efi_is_mixed(void)static inline bool efi_runtime_supported (void ) { +if (IS_ENABLED (CONFIG_X86_32 )) +return !efi_enabled (EFI_64BIT ); +if (!efi_is_mixed ())return true;
@@ -176,7 +179,6 @@ extern void parse_efi_setup(u64 phys_addr, u32 data_len);extern void efifb_setup_from_dmi (struct screen_info *si,const char *opt); -#ifdef CONFIG_EFI_MIXED extern void efi_thunk_runtime_setup (void ); extern efi_status_t efi_thunk_set_virtual_address_map( void *phys_set_virtual_address_map,
@@ -184,19 +186,6 @@ extern efi_status_t efi_thunk_set_virtual_address_map(unsigned long descriptor_size, u32 descriptor_version, efi_memory_desc_t *virtual_map); -#else -static inline void efi_thunk_runtime_setup (void ) {} -static inline efi_status_t efi_thunk_set_virtual_address_map ( -void *phys_set_virtual_address_map, -unsigned long memory_map_size, -unsigned long descriptor_size, -u32 descriptor_version, -efi_memory_desc_t *virtual_map) -{ -return EFI_SUCCESS ; -} -#endif /* CONFIG_EFI_MIXED */ -/* arch specific definitions used by the stub code */
Signature · 1 line
2.17.1
Ard Biesheuvel
maintainerPATCH 4/7 efi/x86: map the entire EFI vendor string before copying it
In reply to Ard BiesheuvelFix a couple of issues with the way we map and copy the vendor string:
- we map only 2 bytes, which usually works since you get at least a page, but if the vendor string happens to cross a page boundary, a crash will result
- only call early_memunmap() if early_memremap() succeeded, or we will call it with a NULL address which it doesn't like,
- while at it, switch to early_memremap_ro(), and array indexing rather than pointer dereferencing to read the CHAR16 characters.
--- arch/x86/platform/efi/efi.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-)
arch/x86/platform/efi/efi.c +7 -6
@@ -541,7 +541,6 @@ void __init efi_init(void)efi_char16_t *c16;char vendor[100 ] ="unknown" ;int i =0 ; -void *tmp;#ifdef CONFIG_X86_32 if (boot_params.efi_info.efi_systab_hi ||
@@ -566,14 +565,16 @@ void __init efi_init(void)/* * Show what we know for posterity */ - c16 = tmp =early_memremap (efi.systab->fw_vendor,2 ); + c16 =early_memremap_ro (efi.systab->fw_vendor, +sizeof (vendor) *sizeof (efi_char16_t));if (c16) { -for (i =0 ; i <sizeof (vendor) -1 && *c16; ++i) - vendor[i] = *c16++; +for (i =0 ; i <sizeof (vendor) -1 && c16[i]; ++i) + vendor[i] = c16[i]; vendor[i] ='\0' ; - }else +early_memunmap (c16,sizeof (vendor) *sizeof (efi_char16_t)); + }else {pr_err ("Could not map the firmware vendor!\n" ); -early_memunmap (tmp,2 ); + } pr_info("EFI v%u.%.02u by %s\n", efi.systab->hdr.revision >> 16,
Signature · 1 line
2.17.1
Ard Biesheuvel
maintainerPATCH 5/7 efi/x86: avoid redundant cast of EFI firmware service pointer
In reply to Ard BiesheuvelAll EFI firmware call prototypes have been annotated as __efiapi, permitting us to attach attributes regarding the calling convention by overriding __efiapi to an architecture specific value.
On 32-bit x86, EFI firmware calls use the plain calling convention where all arguments are passed via the stack, and cleaned up by the caller. Let's add this to the __efiapi definition so we no longer need to cast the function pointers before invoking them.
--- arch/x86/include/asm/efi.h | 8 +------- include/linux/efi.h | 4 +++- 2 files changed, 4 insertions(+), 8 deletions(-)
arch/x86/include/asm/efi.h +1 -7
@@ -51,13 +51,7 @@ extern asmlinkage unsigned long efi_call_phys(void *, ...); }) -/* -* Wrap all the virtual calls in a way that forces the parameters on the stack. -*/ -#define arch_efi_call_virt(p, f, args...) \ -({ \ - ((efi_##f##_t __attribute__((regparm(0)))*) p->f)(args); \ -}) +#define arch_efi_call_virt(p, f, args...) p->f(args)#define efi_ioremap (addr, size, type, attr) ioremap_cache(addr, size)
include/linux/efi.h +3 -1
@@ -48,8 +48,10 @@ typedef u16 efi_char16_t; /* UNICODE character */typedef u64 efi_physical_addr_t ;typedef void *efi_handle_t ; -#ifdef CONFIG_X86_64 +#if defined(CONFIG_X86_64 )#define __efiapi __attribute__((ms_abi)) +#elif defined(CONFIG_X86_32 ) +#define __efiapi __attribute__((regparm(0)))#else #define __efiapi#endif
Signature · 1 line
2.17.1
Ard Biesheuvel
maintainerPATCH 6/7 efi/x86: merge two near identical versions of efi_runtime_init()
In reply to Ard BiesheuvelThe routines efi_runtime_init32() and efi_runtime_init64() are almost indistinguishable, and the only relevant difference is the offset in the runtime struct from where to obtain the address of the SetVirtualAddressMap() routine. Let's collapse them into one, and get rid of some unnecessary casts by switching to a native vs mixed distinction instead, reusing the helper from the EFI stub.
While at it, move the variable where we keep the physical address of the SetVirtualAddressMap() EFI runtime service out of struct efi, where it doesn't belong given that we only call it once (if ever) during early boot.
--- arch/x86/platform/efi/efi.c | 83 ++++++-------------- arch/x86/platform/efi/efi_64.c | 5 ++ include/linux/efi.h | 19 ----- 3 files changed, 27 insertions(+), 80 deletions(-)
arch/x86/platform/efi/efi.c +22 -61
@@ -56,6 +56,7 @@static struct efi efi_phys__initdata ;static efi_system_table_t efi_systab__initdata ; +static efi_set_virtual_address_map_t __efiapi *set_virtual_address_map __initdata;static efi_config_table_type_t arch_tables[]__initdata = { #ifdef CONFIG_X86_UV
@@ -113,7 +114,7 @@ static efi_status_t __init phys_efi_set_virtual_address_map(/* Disable interrupts around EFI calls: */ local_irq_save (flags); - status =efi_call_phys (efi_phys.set_virtual_address_map, + status =efi_call_phys (set_virtual_address_map, memory_map_size, descriptor_size, descriptor_version, virtual_map);local_irq_restore (flags);
@@ -455,57 +456,9 @@ static int __init efi_systab_init(void *phys)return 0 ; } -static int __init efi_runtime_init32 (void ) -{ -efi_runtime_services_32_t *runtime; - - runtime =early_memremap ((unsigned long )efi.systab->runtime, -sizeof (efi_runtime_services_32_t)); -if (!runtime) { -pr_err ("Could not map the runtime service table!\n" ); -return -ENOMEM ; - } - -/* -* We will only need *early* access to the SetVirtualAddressMap -* EFI runtime service. All other runtime services will be called -* via the virtual mapping. -*/ - efi_phys.set_virtual_address_map = - (efi_set_virtual_address_map_t *) - (unsigned long )runtime->set_virtual_address_map; -early_memunmap (runtime,sizeof (efi_runtime_services_32_t)); - -return 0 ; -} - -static int __init efi_runtime_init64 (void ) -{ -efi_runtime_services_64_t *runtime; - - runtime =early_memremap ((unsigned long )efi.systab->runtime, -sizeof (efi_runtime_services_64_t)); -if (!runtime) { -pr_err ("Could not map the runtime service table!\n" ); -return -ENOMEM ; - } - -/* -* We will only need *early* access to the SetVirtualAddressMap -* EFI runtime service. All other runtime services will be called -* via the virtual mapping. -*/ - efi_phys.set_virtual_address_map = - (efi_set_virtual_address_map_t *) - (unsigned long )runtime->set_virtual_address_map; -early_memunmap (runtime,sizeof (efi_runtime_services_64_t)); - -return 0 ; -} -static int __init efi_runtime_init (void ) { -int rv; +efi_runtime_services_t *runtime;/* * Check out the runtime services table. We need to map
@@ -522,13 +475,25 @@ static int __init efi_runtime_init(void)*/ if (!efi_enabled (EFI_PARAVIRT )) { -if (efi_enabled (EFI_64BIT )) - rv =efi_runtime_init64 (); -else - rv =efi_runtime_init32 (); +int size = !efi_is_mixed () ?sizeof (efi_runtime_services_t) + :sizeof (efi_runtime_services_32_t); + + runtime =early_memremap_ro ((unsigned long )efi.systab->runtime, + size); +if (!runtime) { +pr_err ("Could not map the runtime service table!\n" ); +return -ENOMEM ; + } -if (rv) -return rv; +/* +* We will only need *early* access to the SetVirtualAddressMap +* EFI runtime service. All other runtime services will be +* called via the virtual mapping. +*/ + set_virtual_address_map =efi_table_attr (runtime, + set_virtual_address_map); + +early_memunmap (runtime, size); }set_bit (EFI_RUNTIME_SERVICES , &efi.flags);
@@ -960,8 +925,6 @@ static void __init kexec_enter_virtual_mode(void)efi_native_runtime_setup (); - efi.set_virtual_address_map =NULL ; -if (efi_enabled (EFI_OLD_MEMMAP ) && (__supported_pte_mask & _PAGE_NX))runtime_code_page_mkexec ();#endif
@@ -1049,7 +1012,7 @@ static void __init __efi_enter_virtual_mode(void) (efi_memory_desc_t *)pa); }else { status = efi_thunk_set_virtual_address_map( - efi_phys.set_virtual_address_map, + set_virtual_address_map, efi.memmap.desc_size * count, efi.memmap.desc_size, efi.memmap.desc_version,
@@ -1077,8 +1040,6 @@ static void __init __efi_enter_virtual_mode(void)else efi_thunk_runtime_setup (); - efi.set_virtual_address_map =NULL ; -/* * Apply more restrictive page table mapping attributes now that * SVAM() has been called and the firmware has performed all
arch/x86/platform/efi/efi_64.c +5 -0
@@ -57,6 +57,11 @@ static u64 efi_va = EFI_VA_START;struct efi_scratch efi_scratch; +__pure bool efi_is_64bit (void ) +{ +return efi_enabled (EFI_64BIT ); +} +static void __init early_code_mapping_set_exec (int executable) {efi_memory_desc_t *md;
include/linux/efi.h +0 -19
@@ -539,24 +539,6 @@ typedef struct {u32 query_variable_info; } efi_runtime_services_32_t; -typedef struct { -efi_table_hdr_t hdr; -u64 get_time; -u64 set_time; -u64 get_wakeup_time; -u64 set_wakeup_time; -u64 set_virtual_address_map; -u64 convert_pointer; -u64 get_variable; -u64 get_next_variable; -u64 set_variable; -u64 get_next_high_mono_count; -u64 reset_system; -u64 update_capsule; -u64 query_capsule_caps; -u64 query_variable_info; -}efi_runtime_services_64_t ; -typedef efi_status_t efi_get_time_t (efi_time_t *tm,efi_time_cap_t *tc);typedef efi_status_t efi_set_time_t (efi_time_t *tm); typedef efi_status_t efi_get_wakeup_time_t (efi_bool_t *enabled, efi_bool_t *pending,
@@ -946,7 +928,6 @@ extern struct efi {efi_query_capsule_caps_t *query_capsule_caps;efi_get_next_high_mono_count_t *get_next_high_mono_count;efi_reset_system_t *reset_system; -efi_set_virtual_address_map_t *set_virtual_address_map;struct efi_memory_map memmap;unsigned long flags; } efi;
Signature · 1 line
2.17.1
Ard Biesheuvel
maintainerPATCH 7/7 efi/x86: clean up efi_systab_init() routine for legibility
In reply to Ard BiesheuvelClean up the efi_systab_init() routine which maps the EFI system table and copies the relevant pieces of data out of it.
The current routine is very difficult to read, so let's clean that up. Also, switch to a R/O mapping of the system table since that is all we need.
Finally, use a plain u64 variable to record the physical address of the system table instead of pointlessly stashing it in a struct efi that is never used for anything else.
--- arch/x86/platform/efi/efi.c | 166 ++++++++++---------- 1 file changed, 82 insertions(+), 84 deletions(-)
arch/x86/platform/efi/efi.c +82 -84
@@ -54,7 +54,7 @@#include <asm/x86_init.h> #include <asm/uv/uv.h> -static struct efi efi_phys__initdata ; +static u64 efi_systab_phys__initdata ;static efi_system_table_t efi_systab__initdata ; static efi_set_virtual_address_map_t __efiapi *set_virtual_address_map __initdata;
@@ -354,89 +354,90 @@ void __init efi_print_memmap(void) } } -static int __init efi_systab_init (void *phys) +static int __init efi_systab_init (u64 phys) { +int size =efi_enabled (EFI_64BIT ) ?sizeof (efi_system_table_64_t) + :sizeof (efi_system_table_32_t); +bool over4g = false; +void *p; + + p =early_memremap_ro (phys, size); +if (p ==NULL ) { +pr_err ("Couldn't map the system table!\n" ); +return -ENOMEM ; + } +if (efi_enabled (EFI_64BIT )) { -efi_system_table_64_t *systab64; -struct efi_setup_data *data =NULL ; -u64 tmp =0 ; +const efi_system_table_64_t *systab64 = p; + + efi_systab.hdr = systab64->hdr; + efi_systab.fw_vendor = systab64->fw_vendor; + efi_systab.fw_revision = systab64->fw_revision; + efi_systab.con_in_handle = systab64->con_in_handle; + efi_systab.con_in = systab64->con_in; + efi_systab.con_out_handle = systab64->con_out_handle; + efi_systab.con_out = (void *)(unsigned long )systab64->con_out; + efi_systab.stderr_handle = systab64->stderr_handle; + efi_systab.stderr = systab64->stderr; + efi_systab.runtime = (void *)(unsigned long )systab64->runtime; + efi_systab.boottime = (void *)(unsigned long )systab64->boottime; + efi_systab.nr_tables = systab64->nr_tables; + efi_systab.tables = systab64->tables; + + over4g = systab64->con_in_handle >U32_MAX || + systab64->con_in >U32_MAX || + systab64->con_out_handle >U32_MAX || + systab64->con_out >U32_MAX || + systab64->stderr_handle >U32_MAX || + systab64->stderr >U32_MAX || + systab64->boottime >U32_MAX ;if (efi_setup) { - data =early_memremap (efi_setup,sizeof (*data)); -if (!data) +struct efi_setup_data *data; + + data =early_memremap_ro (efi_setup,sizeof (*data)); +if (!data) { +early_memunmap (p, size);return -ENOMEM ; - } - systab64 =early_memremap ((unsigned long )phys, -sizeof (*systab64)); -if (systab64 ==NULL ) { -pr_err ("Couldn't map the system table!\n" ); -if (data) -early_memunmap (data,sizeof (*data)); -return -ENOMEM ; - } + } + + efi_systab.fw_vendor = (unsigned long )data->fw_vendor; + efi_systab.runtime = (void *)(unsigned long )data->runtime; + efi_systab.tables = (unsigned long )data->tables; + + over4g |= data->fw_vendor >U32_MAX || + data->runtime >U32_MAX || + data->tables >U32_MAX ; - efi_systab.hdr = systab64->hdr; - efi_systab.fw_vendor = data ? (unsigned long )data->fw_vendor : - systab64->fw_vendor; - tmp |= data ? data->fw_vendor : systab64->fw_vendor; - efi_systab.fw_revision = systab64->fw_revision; - efi_systab.con_in_handle = systab64->con_in_handle; - tmp |= systab64->con_in_handle; - efi_systab.con_in = systab64->con_in; - tmp |= systab64->con_in; - efi_systab.con_out_handle = systab64->con_out_handle; - tmp |= systab64->con_out_handle; - efi_systab.con_out = (void *)(unsigned long )systab64->con_out; - tmp |= systab64->con_out; - efi_systab.stderr_handle = systab64->stderr_handle; - tmp |= systab64->stderr_handle; - efi_systab.stderr = systab64->stderr; - tmp |= systab64->stderr; - efi_systab.runtime = data ? - (void *)(unsigned long )data->runtime : - (void *)(unsigned long )systab64->runtime; - tmp |= data ? data->runtime : systab64->runtime; - efi_systab.boottime = (void *)(unsigned long )systab64->boottime; - tmp |= systab64->boottime; - efi_systab.nr_tables = systab64->nr_tables; - efi_systab.tables = data ? (unsigned long )data->tables : - systab64->tables; - tmp |= data ? data->tables : systab64->tables; - -early_memunmap (systab64,sizeof (*systab64)); -if (data)early_memunmap (data,sizeof (*data)); -#ifdef CONFIG_X86_32 -if (tmp >>32 ) { -pr_err ("EFI data located above 4GB, disabling EFI.\n" ); -return -EINVAL ; + }else { + over4g |= systab64->fw_vendor >U32_MAX || + systab64->runtime >U32_MAX || + systab64->tables >U32_MAX ; } -#endif }else { -efi_system_table_32_t *systab32; +const efi_system_table_32_t *systab32 = p; + + efi_systab.hdr = systab32->hdr; + efi_systab.fw_vendor = systab32->fw_vendor; + efi_systab.fw_revision = systab32->fw_revision; + efi_systab.con_in_handle = systab32->con_in_handle; + efi_systab.con_in = systab32->con_in; + efi_systab.con_out_handle = systab32->con_out_handle; + efi_systab.con_out = (void *)(unsigned long )systab32->con_out; + efi_systab.stderr_handle = systab32->stderr_handle; + efi_systab.stderr = systab32->stderr; + efi_systab.runtime = (void *)(unsigned long )systab32->runtime; + efi_systab.boottime = (void *)(unsigned long )systab32->boottime; + efi_systab.nr_tables = systab32->nr_tables; + efi_systab.tables = systab32->tables; + } - systab32 =early_memremap ((unsigned long )phys, -sizeof (*systab32)); -if (systab32 ==NULL ) { -pr_err ("Couldn't map the system table!\n" ); -return -ENOMEM ; - } +early_memunmap (p, size); - efi_systab.hdr = systab32->hdr; - efi_systab.fw_vendor = systab32->fw_vendor; - efi_systab.fw_revision = systab32->fw_revision; - efi_systab.con_in_handle = systab32->con_in_handle; - efi_systab.con_in = systab32->con_in; - efi_systab.con_out_handle = systab32->con_out_handle; - efi_systab.con_out = (void *)(unsigned long )systab32->con_out; - efi_systab.stderr_handle = systab32->stderr_handle; - efi_systab.stderr = systab32->stderr; - efi_systab.runtime = (void *)(unsigned long )systab32->runtime; - efi_systab.boottime = (void *)(unsigned long )systab32->boottime; - efi_systab.nr_tables = systab32->nr_tables; - efi_systab.tables = systab32->tables; - -early_memunmap (systab32,sizeof (*systab32)); +if (IS_ENABLED (CONFIG_X86_32 ) && over4g) { +pr_err ("EFI data located above 4GB, disabling EFI.\n" ); +return -EINVAL ; } efi.systab = &efi_systab;
@@ -507,20 +508,17 @@ void __init efi_init(void)char vendor[100 ] ="unknown" ;int i =0 ; -#ifdef CONFIG_X86_32 -if (boot_params.efi_info.efi_systab_hi || - boot_params.efi_info.efi_memmap_hi) { +if (IS_ENABLED (CONFIG_X86_32 ) && + (boot_params.efi_info.efi_systab_hi || + boot_params.efi_info.efi_memmap_hi)) {pr_info ("Table located above 4GB, disabling EFI.\n" );return ; } - efi_phys.systab = (efi_system_table_t *)boot_params.efi_info.efi_systab; -#else - efi_phys.systab = (efi_system_table_t *) - (boot_params.efi_info.efi_systab | - ((__u64 )boot_params.efi_info.efi_systab_hi<<32 )); -#endif -if (efi_systab_init (efi_phys.systab)) + efi_systab_phys = boot_params.efi_info.efi_systab | + ((__u64 )boot_params.efi_info.efi_systab_hi <<32 ); + +if (efi_systab_init (efi_systab_phys))return ; efi.config_table = (unsigned long )efi.systab->tables;
@@ -673,7 +671,7 @@ static void __init get_systab_virt_addr(efi_memory_desc_t *md) size = md->num_pages <<EFI_PAGE_SHIFT ; end = md->phys_addr + size; - systab = (u64 )(unsigned long )efi_phys.systab; + systab = efi_systab_phys;if (md->phys_addr <= systab && systab < end) { systab += md->virt_addr - md->phys_addr; efi.systab = (efi_system_table_t *)(unsigned long )systab;
Signature · 1 line
2.17.1