Commit 5c3a85f3 authored by Ard Biesheuvel's avatar Ard Biesheuvel Committed by Borislav Petkov
Browse files

x86/boot/compressed: Move bootargs parsing out of 32-bit startup code



Move the logic that chooses between the different EFI entrypoints out of
the 32-bit boot path, and into a 64-bit helper that can perform the same
task much more cleanly. While at it, document the mixed mode boot flow
in a code comment.

Signed-off-by: default avatarArd Biesheuvel <ardb@kernel.org>
Signed-off-by: default avatarBorislav Petkov <bp@suse.de>
Link: https://lore.kernel.org/r/20221122161017.2426828-4-ardb@kernel.org
parent e2ab9eab
Loading
Loading
Loading
Loading
+43 −0
Original line number Diff line number Diff line
@@ -22,6 +22,49 @@

	.code64
	.text
/*
 * 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
 * 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.
 *
 *                                                             +--------------+
 *  +------------------+     +------------+            +------>| efi_pe_entry |
 *  | efi32_pe_entry   |---->|            |            |       +-----------+--+
 *  +------------------+     |            |     +------+----------------+  |
 *                           | startup_32 |---->| startup_64_mixed_mode |  |
 *  +------------------+     |            |     +------+----------------+  V
 *  | efi32_stub_entry |---->|            |            |     +------------------+
 *  +------------------+     +------------+            +---->| efi64_stub_entry |
 *                                                           +-------------+----+
 *                           +------------+     +----------+               |
 *                           | startup_64 |<----| efi_main |<--------------+
 *                           +------------+     +----------+
 */
SYM_FUNC_START(startup_64_mixed_mode)
	lea	efi32_boot_args(%rip), %rdx
	mov	0(%rdx), %edi
	mov	4(%rdx), %esi
	mov	8(%rdx), %edx		// saved bootparams pointer
	test	%edx, %edx
	jnz	efi64_stub_entry
	/*
	 * efi_pe_entry uses MS calling convention, which requires 32 bytes of
	 * shadow space on the stack even if all arguments are passed in
	 * registers. We also need an additional 8 bytes for the space that
	 * would be occupied by the return address, and this also results in
	 * the correct stack alignment for entry.
	 */
	sub	$40, %rsp
	mov	%rdi, %rcx		// MS calling convention
	mov	%rsi, %rdx
	jmp	efi_pe_entry
SYM_FUNC_END(startup_64_mixed_mode)

SYM_FUNC_START(__efi64_thunk)
	push	%rbp
	push	%rbx
+4 −20
Original line number Diff line number Diff line
@@ -261,25 +261,9 @@ SYM_FUNC_START(startup_32)
	 */
	leal	rva(startup_64)(%ebp), %eax
#ifdef CONFIG_EFI_MIXED
	movl	rva(efi32_boot_args)(%ebp), %edi
	testl	%edi, %edi
	jz	1f
	leal	rva(efi64_stub_entry)(%ebp), %eax
	movl	rva(efi32_boot_args+4)(%ebp), %esi
	movl	rva(efi32_boot_args+8)(%ebp), %edx	// saved bootparams pointer
	testl	%edx, %edx
	jnz	1f
	/*
	 * efi_pe_entry uses MS calling convention, which requires 32 bytes of
	 * shadow space on the stack even if all arguments are passed in
	 * registers. We also need an additional 8 bytes for the space that
	 * would be occupied by the return address, and this also results in
	 * the correct stack alignment for entry.
	 */
	subl	$40, %esp
	leal	rva(efi_pe_entry)(%ebp), %eax
	movl	%edi, %ecx			// MS calling convention
	movl	%esi, %edx
	cmpb	$1, rva(efi_is64)(%ebp)
	je	1f
	leal	rva(startup_64_mixed_mode)(%ebp), %eax
1:
#endif
	/* Check if the C-bit position is correct when SEV is active */
@@ -779,7 +763,7 @@ SYM_DATA_END_LABEL(boot32_idt, SYM_L_GLOBAL, boot32_idt_end)
SYM_DATA(image_offset, .long 0)
#endif
#ifdef CONFIG_EFI_MIXED
SYM_DATA_LOCAL(efi32_boot_args, .long 0, 0, 0)
SYM_DATA(efi32_boot_args, .long 0, 0, 0)
SYM_DATA(efi_is64, .byte 1)

#define ST32_boottime		60 // offsetof(efi_system_table_32_t, boottime)