Commit 9f922377 authored by Ard Biesheuvel's avatar Ard Biesheuvel
Browse files

efi/libstub/arm: Make efi_entry() an ordinary PE/COFF entrypoint



Expose efi_entry() as the PE/COFF entrypoint directly, instead of
jumping into a wrapper that fiddles with stack buffers and other
stuff that the compiler is much better at. The only reason this
code exists is to obtain a pointer to the base of the image, but
we can get the same value from the loaded_image protocol, which
we already need for other reasons anyway.

Update the return type as well, to make it consistent with what
is required for a PE/COFF executable entrypoint.

Signed-off-by: default avatarArd Biesheuvel <ardb@kernel.org>
parent e951a1f4
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -60,7 +60,7 @@ optional_header:
		.long	__pecoff_code_size		@ SizeOfCode
		.long	__pecoff_data_size		@ SizeOfInitializedData
		.long	0				@ SizeOfUninitializedData
		.long	efi_stub_entry - start		@ AddressOfEntryPoint
		.long	efi_entry - start		@ AddressOfEntryPoint
		.long	start_offset			@ BaseOfCode
		.long	__pecoff_data_start - start	@ BaseOfData

+9 −33
Original line number Diff line number Diff line
@@ -1437,33 +1437,15 @@ __enter_kernel:
reloc_code_end:

#ifdef CONFIG_EFI_STUB
		.align	2
_start:		.long	start - .

ENTRY(efi_stub_entry)
		@ allocate space on stack for passing current zImage address
		@ and for the EFI stub to return of new entry point of
		@ zImage, as EFI stub may copy the kernel. Pointer address
		@ is passed in r2. r0 and r1 are passed through from the
		@ EFI firmware to efi_entry
		adr	ip, _start
		ldr	r3, [ip]
		add	r3, r3, ip
		stmfd	sp!, {r3, lr}
		mov	r2, sp			@ pass zImage address in r2
		bl	efi_entry

		@ Check for error return from EFI stub. r0 has FDT address
		@ or error code.
		cmn	r0, #1
		beq	efi_load_fail

		@ Preserve return value of efi_entry() in r4
		mov	r4, r0
		add	r1, r4, #SZ_2M			@ DT end
ENTRY(efi_enter_kernel)
		mov	r7, r0				@ preserve image base
		mov	r4, r1				@ preserve DT pointer

		mov	r0, r4				@ DT start
		add	r1, r4, r2			@ DT end
		bl	cache_clean_flush

		ldr	r0, [sp]			@ relocated zImage
		mov	r0, r7				@ relocated zImage
		ldr	r1, =_edata			@ size of zImage
		add	r1, r1, r0			@ end of zImage
		bl	cache_clean_flush
@@ -1473,9 +1455,8 @@ ENTRY(efi_stub_entry)
		@ inside the PE/COFF loader allocated region is unsafe. Let's
		@ assume our own zImage relocation code did a better job, and
		@ jump into its version of this routine before proceeding.
		ldr	r0, [sp]			@ relocated zImage
		ldr	r1, .Ljmp
		sub	r1, r0, r1
		sub	r1, r7, r1
		mov	pc, r1				@ no mode switch
0:
		bl	cache_off
@@ -1487,12 +1468,7 @@ ENTRY(efi_stub_entry)
		mov	r1, #0xFFFFFFFF
		mov	r2, r4
		b	__efi_start

efi_load_fail:
		@ Return EFI_LOAD_ERROR to EFI firmware on error.
		ldr	r0, =0x80000001
		ldmfd	sp!, {ip, pc}
ENDPROC(efi_stub_entry)
ENDPROC(efi_enter_kernel)
		.align	2
.Ljmp:		.long	start - 0b
#endif
+17 −69
Original line number Diff line number Diff line
@@ -10,81 +10,35 @@

#include <asm/assembler.h>

#define EFI_LOAD_ERROR 0x8000000000000001

	__INIT

	/*
	 * We arrive here from the EFI boot manager with:
	 *
	 *    * CPU in little-endian mode
	 *    * MMU on with identity-mapped RAM
	 *    * Icache and Dcache on
	 *
	 * We will most likely be running from some place other than where
	 * we want to be. The kernel image wants to be placed at TEXT_OFFSET
	 * from start of RAM.
	 */
ENTRY(entry)
	/*
	 * Create a stack frame to save FP/LR with extra space
	 * for image_addr variable passed to efi_entry().
	 */
	stp	x29, x30, [sp, #-32]!
	mov	x29, sp

	/*
	 * Call efi_entry to do the real work.
	 * x0 and x1 are already set up by firmware. Current runtime
	 * address of image is calculated and passed via *image_addr.
	 *
	 * unsigned long efi_entry(void *handle,
	 *                         efi_system_table_t *sys_table,
	 *                         unsigned long *image_addr) ;
	 */
	adr_l	x8, _text
	add	x2, sp, 16
	str	x8, [x2]
	bl	efi_entry
	cmn	x0, #1
	b.eq	efi_load_fail

ENTRY(efi_enter_kernel)
	/*
	 * efi_entry() will have copied the kernel image if necessary and we
	 * return here with device tree address in x0 and the kernel entry
	 * point stored at *image_addr. Save those values in registers which
	 * are callee preserved.
	 */
	mov	x20, x0		// DTB address
	ldr	x0, [sp, #16]	// relocated _text address
	ldr	w21, =stext_offset
	add	x21, x0, x21

	/*
	 * Calculate size of the kernel Image (same for original and copy).
	 * end up here with device tree address in x1 and the kernel entry
	 * point stored in x0. Save those values in registers which are
	 * callee preserved.
	 */
	adr_l	x1, _text
	adr_l	x2, _edata
	sub	x1, x2, x1
	mov	x19, x0			// relocated Image address
	mov	x20, x1			// DTB address

	/*
	 * Flush the copied Image to the PoC, and ensure it is not shadowed by
	 * stale icache entries from before relocation.
	 */
	ldr	w1, =kernel_size
	bl	__flush_dcache_area
	ic	ialluis
	dsb	sy

	/*
	 * Ensure that the rest of this function (in the original Image) is
	 * visible when the caches are disabled. The I-cache can't have stale
	 * entries for the VA range of the current image, so no maintenance is
	 * necessary.
	 * Jump across, into the copy of the image that we just cleaned
	 * to the PoC, so that we can safely disable the MMU and caches.
	 */
	adr	x0, entry
	adr	x1, entry_end
	sub	x1, x1, x0
	bl	__flush_dcache_area

	ldr	w0, .Ljmp
	sub	x0, x19, w0, sxtw
	br	x0
0:
	/* Turn off Dcache and MMU */
	mrs	x0, CurrentEL
	cmp	x0, #CurrentEL_EL2
@@ -109,12 +63,6 @@ ENTRY(entry)
	mov	x1, xzr
	mov	x2, xzr
	mov	x3, xzr
	br	x21

efi_load_fail:
	mov	x0, #EFI_LOAD_ERROR
	ldp	x29, x30, [sp], #32
	ret

entry_end:
ENDPROC(entry)
	b	stext
ENDPROC(efi_enter_kernel)
.Ljmp:	.long	_text - 0b
+1 −1
Original line number Diff line number Diff line
@@ -27,7 +27,7 @@ optional_header:
	.long	__initdata_begin - efi_header_end	// SizeOfCode
	.long	__pecoff_data_size			// SizeOfInitializedData
	.long	0					// SizeOfUninitializedData
	.long	__efistub_entry - _head			// AddressOfEntryPoint
	.long	__efistub_efi_entry - _head		// AddressOfEntryPoint
	.long	efi_header_end - _head			// BaseOfCode

extra_header_fields:
+3 −1
Original line number Diff line number Diff line
@@ -12,7 +12,8 @@

#ifdef CONFIG_EFI

__efistub_stext_offset = stext - _text;
__efistub_kernel_size		= _edata - _text;


/*
 * The EFI stub has its own symbol namespace prefixed by __efistub_, to
@@ -42,6 +43,7 @@ __efistub___memset = __pi_memset;
#endif

__efistub__text			= _text;
__efistub_stext			= stext;
__efistub__end			= _end;
__efistub__edata		= _edata;
__efistub_screen_info		= screen_info;
Loading