While the EFI stub code does not generally require a GOT, it is very easy to write code that would require a GOT with an old toolchain, but that modern toolchains optimize to eliminate the GOT references. This can lead to unexpected crashes if the kernel is built with an older toolchain. To avoid potential issues, move the efi_pe_entry back to assembler, and relocate the GOT if present before calling any C code. Signed-off-by: Arvind Sankar <nivedita@xxxxxxxxxxxx> --- arch/x86/boot/compressed/eboot.c | 4 ++-- arch/x86/boot/compressed/head_32.S | 23 ++++++++++++++++++++++- arch/x86/boot/compressed/head_64.S | 18 ++++++++++++++++++ 3 files changed, 42 insertions(+), 3 deletions(-) diff --git a/arch/x86/boot/compressed/eboot.c b/arch/x86/boot/compressed/eboot.c index ab3a40283db7..b62f957274aa 100644 --- a/arch/x86/boot/compressed/eboot.c +++ b/arch/x86/boot/compressed/eboot.c @@ -356,8 +356,8 @@ void __noreturn efi_stub_entry(efi_handle_t handle, * need to create one ourselves (usually the bootloader would create * one for us). */ -efi_status_t __efiapi efi_pe_entry(efi_handle_t handle, - efi_system_table_t *sys_table_arg) +efi_status_t efi_entry(efi_handle_t handle, + efi_system_table_t *sys_table_arg) { struct boot_params *boot_params; struct apm_bios_info *bi; diff --git a/arch/x86/boot/compressed/head_32.S b/arch/x86/boot/compressed/head_32.S index 973ac0b51af5..171947ae5b8c 100644 --- a/arch/x86/boot/compressed/head_32.S +++ b/arch/x86/boot/compressed/head_32.S @@ -145,9 +145,29 @@ SYM_FUNC_START(startup_32) SYM_FUNC_END(startup_32) #ifdef CONFIG_EFI_STUB + +SYM_FUNC_START(efi_pe_entry) + /* Adjust the GOT */ + /* Don't clobber EBX as we may return to firmware in case of error */ + pushl %ebx + call 1f +1: popl %ebx + subl $1b, %ebx + call .Ladjust_got + popl %ebx + /* Transfer control to C entry */ + jmp efi_entry +SYM_FUNC_END(efi_pe_entry) + SYM_FUNC_START(efi32_stub_entry) SYM_FUNC_START_ALIAS(efi_stub_entry) - add $0x4, %esp + /* We cannot return from here */ + addl $0x4, %esp + /* Adjust the GOT */ + call 1f +1: popl %ebx + subl $1b, %ebx + call .Ladjust_got call efi_main movl %eax, %esi movl BP_code32_start(%esi), %eax @@ -155,6 +175,7 @@ SYM_FUNC_START_ALIAS(efi_stub_entry) jmp *%eax SYM_FUNC_END(efi32_stub_entry) SYM_FUNC_END_ALIAS(efi_stub_entry) + #endif .text diff --git a/arch/x86/boot/compressed/head_64.S b/arch/x86/boot/compressed/head_64.S index 1464d8d0ec66..5a295d41a7a8 100644 --- a/arch/x86/boot/compressed/head_64.S +++ b/arch/x86/boot/compressed/head_64.S @@ -421,9 +421,26 @@ trampoline_return: SYM_CODE_END(startup_64) #ifdef CONFIG_EFI_STUB + +SYM_FUNC_START(efi_pe_entry) + /* Convert arguments to SysV ABI */ + movq %rcx, %rdi + movq %rdx, %rsi + /* Adjust the GOT */ + call .Ladjust_got + /* Transfer control to C entry */ + jmp efi_entry +SYM_FUNC_END(efi_pe_entry) + .org 0x390 SYM_FUNC_START(efi64_stub_entry) SYM_FUNC_START_ALIAS(efi_stub_entry) + /* We cannot return from here */ + addq $8, %rsp + /* Adjust the GOT */ + pushq %rdx + call .Ladjust_got + popq %rdx and $~0xf, %rsp /* realign the stack */ call efi_main movq %rax,%rsi @@ -432,6 +449,7 @@ SYM_FUNC_START_ALIAS(efi_stub_entry) jmp *%rax SYM_FUNC_END(efi64_stub_entry) SYM_FUNC_END_ALIAS(efi_stub_entry) + #endif .text -- 2.24.1