summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--arch/x86/boot/compressed/Makefile2
-rw-r--r--arch/x86/boot/compressed/eboot.c3
-rw-r--r--arch/x86/boot/compressed/efi_stub_32.S87
-rw-r--r--arch/x86/boot/compressed/efi_stub_64.S5
-rw-r--r--arch/x86/boot/compressed/head_32.S6
-rw-r--r--arch/x86/boot/compressed/head_64.S23
-rw-r--r--arch/x86/include/asm/efi.h34
-rw-r--r--arch/x86/platform/efi/efi_64.c2
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) \