Commit df9215f1 authored by Ard Biesheuvel's avatar Ard Biesheuvel Committed by Borislav Petkov (AMD)
Browse files

x86/efistub: Simplify and clean up handover entry code



Now that the EFI entry code in assembler is only used by the optional
and deprecated EFI handover protocol, and given that the EFI stub C code
no longer returns to it, most of it can simply be dropped.

While at it, clarify the symbol naming, by merging efi_main() and
efi_stub_entry(), making the latter the shared entry point for all
different boot modes that enter via the EFI stub.

The efi32_stub_entry() and efi64_stub_entry() names are referenced
explicitly by the tooling that populates the setup header, so these must
be retained, but can be emitted as aliases of efi_stub_entry() where
appropriate.

Signed-off-by: default avatarArd Biesheuvel <ardb@kernel.org>
Signed-off-by: default avatarBorislav Petkov (AMD) <bp@alien8.de>
Link: https://lore.kernel.org/r/20230807162720.545787-5-ardb@kernel.org
parent d2d7a54f
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -1417,7 +1417,7 @@ execution context provided by the EFI firmware.

The function prototype for the handover entry point looks like this::

    efi_main(void *handle, efi_system_table_t *table, struct boot_params *bp)
    efi_stub_entry(void *handle, efi_system_table_t *table, struct boot_params *bp)

'handle' is the EFI image handle passed to the boot loader by the EFI
firmware, 'table' is the EFI system table - these are the first two
+12 −10
Original line number Diff line number Diff line
@@ -26,8 +26,8 @@
 * When booting in 64-bit mode on 32-bit EFI firmware, startup_64_mixed_mode()
 * is the first thing that runs after switching to long mode. Depending on
 * whether the EFI handover protocol or the compat entry point was used to
 * enter the kernel, it will either branch to the 64-bit EFI handover
 * entrypoint at offset 0x390 in the image, or to the 64-bit EFI PE/COFF
 * enter the kernel, it will either branch to the common 64-bit EFI stub
 * entrypoint efi_stub_entry() directly, or via the 64-bit EFI PE/COFF
 * entrypoint efi_pe_entry(). In the former case, the bootloader must provide a
 * struct bootparams pointer as the third argument, so the presence of such a
 * pointer is used to disambiguate.
@@ -37,21 +37,23 @@
 *  | efi32_pe_entry   |---->|            |            |       +-----------+--+
 *  +------------------+     |            |     +------+----------------+  |
 *                           | startup_32 |---->| startup_64_mixed_mode |  |
 *  +------------------+     |            |     +------+----------------+  V
 *  | efi32_stub_entry |---->|            |            |     +------------------+
 *  +------------------+     +------------+            +---->| efi64_stub_entry |
 *                                                           +-------------+----+
 *                           +------------+     +----------+               |
 *                           | startup_64 |<----| efi_main |<--------------+
 *                           +------------+     +----------+
 *  +------------------+     |            |     +------+----------------+  |
 *  | efi32_stub_entry |---->|            |            |                   |
 *  +------------------+     +------------+            |                   |
 *                                                     V                   |
 *                           +------------+     +----------------+         |
 *                           | startup_64 |<----| efi_stub_entry |<--------+
 *                           +------------+     +----------------+
 */
SYM_FUNC_START(startup_64_mixed_mode)
	lea	efi32_boot_args(%rip), %rdx
	mov	0(%rdx), %edi
	mov	4(%rdx), %esi
#ifdef CONFIG_EFI_HANDOVER_PROTOCOL
	mov	8(%rdx), %edx		// saved bootparams pointer
	test	%edx, %edx
	jnz	efi64_stub_entry
	jnz	efi_stub_entry
#endif
	/*
	 * efi_pe_entry uses MS calling convention, which requires 32 bytes of
	 * shadow space on the stack even if all arguments are passed in
+0 −11
Original line number Diff line number Diff line
@@ -150,17 +150,6 @@ SYM_FUNC_START(startup_32)
	jmp	*%eax
SYM_FUNC_END(startup_32)

#ifdef CONFIG_EFI_STUB
SYM_FUNC_START(efi32_stub_entry)
	add	$0x4, %esp
	movl	8(%esp), %esi	/* save boot_params pointer */
	call	efi_main
	/* efi_main returns the possibly relocated address of startup_32 */
	jmp	*%eax
SYM_FUNC_END(efi32_stub_entry)
SYM_FUNC_ALIAS(efi_stub_entry, efi32_stub_entry)
#endif

	.text
SYM_FUNC_START_LOCAL_NOALIGN(.Lrelocated)

+2 −10
Original line number Diff line number Diff line
@@ -542,19 +542,11 @@ trampoline_return:
	jmp	*%rax
SYM_CODE_END(startup_64)

#ifdef CONFIG_EFI_STUB
#ifdef CONFIG_EFI_HANDOVER_PROTOCOL
#if IS_ENABLED(CONFIG_EFI_MIXED) && IS_ENABLED(CONFIG_EFI_HANDOVER_PROTOCOL)
	.org 0x390
#endif
SYM_FUNC_START(efi64_stub_entry)
	and	$~0xf, %rsp			/* realign the stack */
	movq	%rdx, %rbx			/* save boot_params pointer */
	call	efi_main
	movq	%rbx,%rsi
	leaq	rva(startup_64)(%rax), %rax
	jmp	*%rax
	jmp	efi_stub_entry
SYM_FUNC_END(efi64_stub_entry)
SYM_FUNC_ALIAS(efi_stub_entry, efi64_stub_entry)
#endif

	.text
+16 −4
Original line number Diff line number Diff line
@@ -817,7 +817,7 @@ static void __noreturn enter_kernel(unsigned long kernel_addr,
 * return.  On failure, it will exit to the firmware via efi_exit() instead of
 * returning.
 */
asmlinkage unsigned long efi_main(efi_handle_t handle,
void __noreturn efi_stub_entry(efi_handle_t handle,
			       efi_system_table_t *sys_table_arg,
			       struct boot_params *boot_params)
{
@@ -964,7 +964,19 @@ asmlinkage unsigned long efi_main(efi_handle_t handle,

	enter_kernel(bzimage_addr, boot_params);
fail:
	efi_err("efi_main() failed!\n");
	efi_err("efi_stub_entry() failed!\n");

	efi_exit(handle, status);
}

#ifdef CONFIG_EFI_HANDOVER_PROTOCOL
#ifndef CONFIG_EFI_MIXED
extern __alias(efi_stub_entry)
void efi32_stub_entry(efi_handle_t handle, efi_system_table_t *sys_table_arg,
		      struct boot_params *boot_params);

extern __alias(efi_stub_entry)
void efi64_stub_entry(efi_handle_t handle, efi_system_table_t *sys_table_arg,
		      struct boot_params *boot_params);
#endif
#endif