aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorArd Biesheuvel <ardb@kernel.org>2023-08-07 18:27:00 +0200
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2024-03-06 14:45:14 +0000
commit51a0710218cea5c7d5528b92ba19e964423c7f5a (patch)
tree34c2a68c575d71b27fc286f9d6dbb82d7248979f
parent4f3077c3eae7e68e2c0ba6d1bd3f5afeb61eb269 (diff)
downloadlinux-51a0710218cea5c7d5528b92ba19e964423c7f5a.tar.gz
x86/efistub: Branch straight to kernel entry point from C code
commit d2d7a54f69b67cd0a30e0ebb5307cb2de625baac upstream. Instead of returning to the calling code in assembler that does nothing more than perform an indirect call with the boot_params pointer in register ESI/RSI, perform the jump directly from the EFI stub C code. This will allow the asm entrypoint code to be dropped entirely in subsequent patches. Signed-off-by: Ard Biesheuvel <ardb@kernel.org> Signed-off-by: Borislav Petkov (AMD) <bp@alien8.de> Link: https://lore.kernel.org/r/20230807162720.545787-4-ardb@kernel.org Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r--drivers/firmware/efi/libstub/x86-stub.c22
1 files changed, 17 insertions, 5 deletions
diff --git a/drivers/firmware/efi/libstub/x86-stub.c b/drivers/firmware/efi/libstub/x86-stub.c
index 9ae0d6d0c285f8..9422fddfbc8f1d 100644
--- a/drivers/firmware/efi/libstub/x86-stub.c
+++ b/drivers/firmware/efi/libstub/x86-stub.c
@@ -279,7 +279,7 @@ adjust_memory_range_protection(unsigned long start, unsigned long size)
#define TRAMPOLINE_PLACEMENT_BASE ((128 - 8)*1024)
#define TRAMPOLINE_PLACEMENT_SIZE (640*1024 - (128 - 8)*1024)
-void startup_32(struct boot_params *boot_params);
+extern const u8 startup_32[], startup_64[];
static void
setup_memory_protection(unsigned long image_base, unsigned long image_size)
@@ -760,10 +760,19 @@ static efi_status_t exit_boot(struct boot_params *boot_params, void *handle)
return EFI_SUCCESS;
}
+static void __noreturn enter_kernel(unsigned long kernel_addr,
+ struct boot_params *boot_params)
+{
+ /* enter decompressed kernel with boot_params pointer in RSI/ESI */
+ asm("jmp *%0"::"r"(kernel_addr), "S"(boot_params));
+
+ unreachable();
+}
+
/*
- * On success, we return the address of startup_32, which has potentially been
- * relocated by efi_relocate_kernel.
- * On failure, we exit to the firmware via efi_exit instead of returning.
+ * On success, this routine will jump to the relocated image directly and never
+ * return. On failure, it will exit to the firmware via efi_exit() instead of
+ * returning.
*/
asmlinkage unsigned long efi_main(efi_handle_t handle,
efi_system_table_t *sys_table_arg,
@@ -905,7 +914,10 @@ asmlinkage unsigned long efi_main(efi_handle_t handle,
goto fail;
}
- return bzimage_addr;
+ if (IS_ENABLED(CONFIG_X86_64))
+ bzimage_addr += startup_64 - startup_32;
+
+ enter_kernel(bzimage_addr, boot_params);
fail:
efi_err("efi_main() failed!\n");