diff options
-rw-r--r-- | arch/x86/boot/compressed/Makefile | 2 | ||||
-rw-r--r-- | arch/x86/boot/compressed/eboot.c | 3 | ||||
-rw-r--r-- | arch/x86/boot/compressed/efi_stub_32.S | 87 | ||||
-rw-r--r-- | arch/x86/boot/compressed/efi_stub_64.S | 5 | ||||
-rw-r--r-- | arch/x86/boot/compressed/head_32.S | 6 | ||||
-rw-r--r-- | arch/x86/boot/compressed/head_64.S | 23 | ||||
-rw-r--r-- | arch/x86/include/asm/efi.h | 34 | ||||
-rw-r--r-- | arch/x86/platform/efi/efi_64.c | 2 |
8 files changed, 24 insertions, 138 deletions
diff --git a/arch/x86/boot/compressed/Makefile b/arch/x86/boot/compressed/Makefile index 1dac210f7d44..56aa5fa0a66b 100644 --- a/arch/x86/boot/compressed/Makefile +++ b/arch/x86/boot/compressed/Makefile @@ -89,7 +89,7 @@ vmlinux-objs-$(CONFIG_ACPI) += $(obj)/acpi.o $(obj)/eboot.o: KBUILD_CFLAGS += -fshort-wchar -mno-red-zone -vmlinux-objs-$(CONFIG_EFI_STUB) += $(obj)/eboot.o $(obj)/efi_stub_$(BITS).o \ +vmlinux-objs-$(CONFIG_EFI_STUB) += $(obj)/eboot.o \ $(objtree)/drivers/firmware/efi/libstub/lib.a vmlinux-objs-$(CONFIG_EFI_MIXED) += $(obj)/efi_thunk_$(BITS).o diff --git a/arch/x86/boot/compressed/eboot.c b/arch/x86/boot/compressed/eboot.c index 2733bc263c04..36a26d6e2af0 100644 --- a/arch/x86/boot/compressed/eboot.c +++ b/arch/x86/boot/compressed/eboot.c @@ -44,7 +44,8 @@ BOOT_SERVICES(64); void efi_char16_printk(efi_system_table_t *table, efi_char16_t *str) { efi_call_proto(efi_simple_text_output_protocol, output_string, - efi_early->text_output, str); + ((efi_simple_text_output_protocol_t *)(unsigned long) + efi_early->text_output), str); } static efi_status_t diff --git a/arch/x86/boot/compressed/efi_stub_32.S b/arch/x86/boot/compressed/efi_stub_32.S deleted file mode 100644 index ed6c351d34ed..000000000000 --- a/arch/x86/boot/compressed/efi_stub_32.S +++ /dev/null @@ -1,87 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* - * EFI call stub for IA32. - * - * This stub allows us to make EFI calls in physical mode with interrupts - * turned off. Note that this implementation is different from the one in - * arch/x86/platform/efi/efi_stub_32.S because we're _already_ in physical - * mode at this point. - */ - -#include <linux/linkage.h> -#include <asm/page_types.h> - -/* - * efi_call_phys(void *, ...) is a function with variable parameters. - * All the callers of this function assure that all the parameters are 4-bytes. - */ - -/* - * In gcc calling convention, EBX, ESP, EBP, ESI and EDI are all callee save. - * So we'd better save all of them at the beginning of this function and restore - * at the end no matter how many we use, because we can not assure EFI runtime - * service functions will comply with gcc calling convention, too. - */ - -.text -SYM_FUNC_START(efi_call_phys) - /* - * 0. The function can only be called in Linux kernel. So CS has been - * set to 0x0010, DS and SS have been set to 0x0018. In EFI, I found - * the values of these registers are the same. And, the corresponding - * GDT entries are identical. So I will do nothing about segment reg - * and GDT, but change GDT base register in prelog and epilog. - */ - - /* - * 1. Because we haven't been relocated by this point we need to - * use relative addressing. - */ - call 1f -1: popl %edx - subl $1b, %edx - - /* - * 2. Now on the top of stack is the return - * address in the caller of efi_call_phys(), then parameter 1, - * parameter 2, ..., param n. To make things easy, we save the return - * address of efi_call_phys in a global variable. - */ - popl %ecx - movl %ecx, saved_return_addr(%edx) - /* get the function pointer into ECX*/ - popl %ecx - movl %ecx, efi_rt_function_ptr(%edx) - - /* - * 3. Call the physical function. - */ - call *%ecx - - /* - * 4. Balance the stack. And because EAX contain the return value, - * we'd better not clobber it. We need to calculate our address - * again because %ecx and %edx are not preserved across EFI function - * calls. - */ - call 1f -1: popl %edx - subl $1b, %edx - - movl efi_rt_function_ptr(%edx), %ecx - pushl %ecx - - /* - * 10. Push the saved return address onto the stack and return. - */ - movl saved_return_addr(%edx), %ecx - pushl %ecx - ret -SYM_FUNC_END(efi_call_phys) -.previous - -.data -saved_return_addr: - .long 0 -efi_rt_function_ptr: - .long 0 diff --git a/arch/x86/boot/compressed/efi_stub_64.S b/arch/x86/boot/compressed/efi_stub_64.S deleted file mode 100644 index 99494dff2113..000000000000 --- a/arch/x86/boot/compressed/efi_stub_64.S +++ /dev/null @@ -1,5 +0,0 @@ -#include <asm/segment.h> -#include <asm/msr.h> -#include <asm/processor-flags.h> - -#include "../../platform/efi/efi_stub_64.S" diff --git a/arch/x86/boot/compressed/head_32.S b/arch/x86/boot/compressed/head_32.S index f2dfd6d083ef..0b03dc7bba12 100644 --- a/arch/x86/boot/compressed/head_32.S +++ b/arch/x86/boot/compressed/head_32.S @@ -161,9 +161,7 @@ SYM_FUNC_START(efi_pe_entry) popl %ecx movl %ecx, efi32_config+8(%esi) /* EFI System table pointer */ - /* Relocate efi_config->call() */ leal efi32_config(%esi), %eax - add %esi, 40(%eax) pushl %eax call make_boot_params @@ -188,9 +186,7 @@ SYM_FUNC_START(efi32_stub_entry) movl %ecx, efi32_config(%esi) /* Handle */ movl %edx, efi32_config+8(%esi) /* EFI System table pointer */ - /* Relocate efi_config->call() */ leal efi32_config(%esi), %eax - add %esi, 40(%eax) pushl %eax 2: call efi_main @@ -266,8 +262,6 @@ SYM_FUNC_END(.Lrelocated) .data efi32_config: .fill 5,8,0 - .long efi_call_phys - .long 0 .byte 0 #endif diff --git a/arch/x86/boot/compressed/head_64.S b/arch/x86/boot/compressed/head_64.S index ee60b81944a7..ad57edeaeeb3 100644 --- a/arch/x86/boot/compressed/head_64.S +++ b/arch/x86/boot/compressed/head_64.S @@ -459,15 +459,6 @@ SYM_FUNC_START(efi_pe_entry) leaq efi64_config(%rip), %rax movq %rax, efi_config(%rip) - call 1f -1: popq %rbp - subq $1b, %rbp - - /* - * Relocate efi_config->call(). - */ - addq %rbp, efi64_config+40(%rip) - movq %rax, %rdi call make_boot_params cmpq $0,%rax @@ -475,20 +466,10 @@ SYM_FUNC_START(efi_pe_entry) mov %rax, %rsi leaq startup_32(%rip), %rax movl %eax, BP_code32_start(%rsi) - jmp 2f /* Skip the relocation */ handover_entry: - call 1f -1: popq %rbp - subq $1b, %rbp - - /* - * Relocate efi_config->call(). - */ - movq efi_config(%rip), %rax - addq %rbp, 40(%rax) -2: movq efi_config(%rip), %rdi + and $~0xf, %rsp /* realign the stack */ call efi_main movq %rax,%rsi cmpq $0,%rax @@ -688,14 +669,12 @@ SYM_DATA_LOCAL(efi_config, .quad 0) #ifdef CONFIG_EFI_MIXED SYM_DATA_START(efi32_config) .fill 5,8,0 - .quad efi64_thunk .byte 0 SYM_DATA_END(efi32_config) #endif SYM_DATA_START(efi64_config) .fill 5,8,0 - .quad efi_call .byte 1 SYM_DATA_END(efi64_config) #endif /* CONFIG_EFI_STUB */ diff --git a/arch/x86/include/asm/efi.h b/arch/x86/include/asm/efi.h index c27323cb49e5..001905daa110 100644 --- a/arch/x86/include/asm/efi.h +++ b/arch/x86/include/asm/efi.h @@ -152,6 +152,7 @@ struct efi_setup_data { extern u64 efi_setup; #ifdef CONFIG_EFI +extern efi_status_t efi64_thunk(u32, ...); static inline bool efi_is_mixed(void) { @@ -205,7 +206,6 @@ struct efi_config { u64 runtime_services; u64 boot_services; u64 text_output; - efi_status_t (*call)(unsigned long, ...); bool is64; } __packed; @@ -235,30 +235,36 @@ static inline bool efi_is_native(void) (unsigned long)(attr), (attr)) #define efi_table_attr(table, attr, instance) ({ \ - __typeof__(((table##_t *)0)->attr) __ret; \ + __typeof__(instance->attr) __ret; \ if (efi_is_native()) { \ - __ret = ((table##_t *)(unsigned long)instance)->attr; \ + __ret = instance->attr; \ } else { \ - __ret = (__typeof__(__ret))efi_mixed_mode_cast( \ - ((table##_t *)(unsigned long)instance)->mixed_mode.attr);\ + __ret = (__typeof__(__ret)) \ + efi_mixed_mode_cast(instance->mixed_mode.attr); \ } \ __ret; \ }) #define efi_call_proto(protocol, f, instance, ...) \ - __efi_early()->call((unsigned long) \ - efi_table_attr(protocol, f, instance), \ - instance, ##__VA_ARGS__) + (efi_is_native() \ + ? instance->f(instance, ##__VA_ARGS__) \ + : efi64_thunk(instance->mixed_mode.f, instance, ##__VA_ARGS__)) #define efi_call_early(f, ...) \ - __efi_early()->call((unsigned long) \ - efi_table_attr(efi_boot_services, f, \ - __efi_early()->boot_services), __VA_ARGS__) + (efi_is_native() \ + ? ((efi_boot_services_t *)(unsigned long) \ + __efi_early()->boot_services)->f(__VA_ARGS__) \ + : efi64_thunk(((efi_boot_services_t *)(unsigned long) \ + __efi_early()->boot_services)->mixed_mode.f, \ + __VA_ARGS__)) #define efi_call_runtime(f, ...) \ - __efi_early()->call((unsigned long) \ - efi_table_attr(efi_runtime_services, f, \ - __efi_early()->runtime_services), __VA_ARGS__) + (efi_is_native() \ + ? ((efi_runtime_services_t *)(unsigned long) \ + __efi_early()->runtime_services)->f(__VA_ARGS__)\ + : efi64_thunk(((efi_runtime_services_t *)(unsigned long)\ + __efi_early()->runtime_services)->mixed_mode.f, \ + __VA_ARGS__)) extern bool efi_reboot_required(void); extern bool efi_is_table_address(unsigned long phys_addr); diff --git a/arch/x86/platform/efi/efi_64.c b/arch/x86/platform/efi/efi_64.c index 885e50a707a6..03c2ed3c645c 100644 --- a/arch/x86/platform/efi/efi_64.c +++ b/arch/x86/platform/efi/efi_64.c @@ -635,8 +635,6 @@ void efi_switch_mm(struct mm_struct *mm) } #ifdef CONFIG_EFI_MIXED -extern efi_status_t efi64_thunk(u32, ...); - static DEFINE_SPINLOCK(efi_runtime_lock); #define runtime_service32(func) \ |