Skip to content

Commit

Permalink
x86/efistub: Branch straight to kernel entry point from C code
Browse files Browse the repository at this point in the history
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
  • Loading branch information
Ard Biesheuvel authored and Borislav Petkov (AMD) committed Aug 7, 2023
1 parent 2f69a81 commit d2d7a54
Showing 1 changed file with 17 additions and 5 deletions.
22 changes: 17 additions & 5 deletions drivers/firmware/efi/libstub/x86-stub.c
Original file line number Diff line number Diff line change
Expand Up @@ -290,7 +290,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)
Expand Down Expand Up @@ -803,10 +803,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,
Expand Down Expand Up @@ -950,7 +959,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");

Expand Down

0 comments on commit d2d7a54

Please sign in to comment.