Commit d0f9ca9b authored by Ard Biesheuvel's avatar Ard Biesheuvel

ARM: decompressor: run decompressor in place if loaded via UEFI

The decompressor can load from anywhere in memory, and the only reason
the EFI stub code relocates it is to ensure it appears within the first
128 MiB of memory, so that the uncompressed kernel ends up at the right
offset in memory.

We can short circuit this, and simply jump into the decompressor startup
code at the point where it knows where the base of memory lives. This
also means there is no need to disable the MMU and caches, create new
page tables and re-enable them.
Signed-off-by: default avatarArd Biesheuvel <ardb@kernel.org>
Reviewed-by: default avatarNicolas Pitre <nico@fluxnic.net>
parent 35d57d12
...@@ -1430,37 +1430,26 @@ reloc_code_end: ...@@ -1430,37 +1430,26 @@ reloc_code_end:
#ifdef CONFIG_EFI_STUB #ifdef CONFIG_EFI_STUB
ENTRY(efi_enter_kernel) ENTRY(efi_enter_kernel)
mov r7, r0 @ preserve image base mov r4, r0 @ preserve image base
mov r4, r1 @ preserve DT pointer mov r8, r1 @ preserve DT pointer
mov r0, r4 @ DT start mrc p15, 0, r0, c1, c0, 0 @ read SCTLR
add r1, r4, r2 @ DT end tst r0, #0x1 @ MMU enabled?
bl cache_clean_flush orreq r4, r4, #1 @ set LSB if not
mov r0, r7 @ relocated zImage mov r0, r8 @ DT start
ldr r1, =_edata @ size of zImage add r1, r8, r2 @ DT end
add r1, r1, r0 @ end of zImage
bl cache_clean_flush bl cache_clean_flush
@ The PE/COFF loader might not have cleaned the code we are adr r0, 0f @ switch to our stack
@ running beyond the PoU, and so calling cache_off below from ldr sp, [r0]
@ inside the PE/COFF loader allocated region is unsafe unless add sp, sp, r0
@ we explicitly clean it to the PoC.
adr r0, call_cache_fn @ region of code we will
adr r1, 0f @ run with MMU off
bl cache_clean_flush
bl cache_off
@ Set parameters for booting zImage according to boot protocol mov r5, #0 @ appended DTB size
@ put FDT address in r2, it was returned by efi_entry() mov r7, #0xFFFFFFFF @ machine ID
@ r1 is the machine type, and r0 needs to be 0 b wont_overwrite
mov r0, #0
mov r1, #0xFFFFFFFF
mov r2, r4
add r7, r7, #(__efi_start - start)
mov pc, r7 @ no mode switch
ENDPROC(efi_enter_kernel) ENDPROC(efi_enter_kernel)
0: 0: .long .L_user_stack_end - .
#endif #endif
.align .align
......
...@@ -199,14 +199,8 @@ efi_status_t handle_kernel_image(unsigned long *image_addr, ...@@ -199,14 +199,8 @@ efi_status_t handle_kernel_image(unsigned long *image_addr,
unsigned long kernel_base; unsigned long kernel_base;
efi_status_t status; efi_status_t status;
/* /* use a 16 MiB aligned base for the decompressed kernel */
* Verify that the DRAM base address is compatible with the ARM kernel_base = round_up(dram_base, SZ_16M) + TEXT_OFFSET;
* boot protocol, which determines the base of DRAM by masking
* off the low 27 bits of the address at which the zImage is
* loaded. These assumptions are made by the decompressor,
* before any memory map is available.
*/
kernel_base = round_up(dram_base, SZ_128M);
/* /*
* Note that some platforms (notably, the Raspberry Pi 2) put * Note that some platforms (notably, the Raspberry Pi 2) put
...@@ -215,41 +209,14 @@ efi_status_t handle_kernel_image(unsigned long *image_addr, ...@@ -215,41 +209,14 @@ efi_status_t handle_kernel_image(unsigned long *image_addr,
* base of the kernel image is only partially used at the moment. * base of the kernel image is only partially used at the moment.
* (Up to 5 pages are used for the swapper page tables) * (Up to 5 pages are used for the swapper page tables)
*/ */
kernel_base += TEXT_OFFSET - 5 * PAGE_SIZE; status = reserve_kernel_base(kernel_base - 5 * PAGE_SIZE, reserve_addr,
reserve_size);
status = reserve_kernel_base(kernel_base, reserve_addr, reserve_size);
if (status != EFI_SUCCESS) { if (status != EFI_SUCCESS) {
pr_efi_err("Unable to allocate memory for uncompressed kernel.\n"); pr_efi_err("Unable to allocate memory for uncompressed kernel.\n");
return status; return status;
} }
/* *image_addr = kernel_base;
* Relocate the zImage, so that it appears in the lowest 128 MB
* memory window.
*/
*image_addr = (unsigned long)image->image_base;
*image_size = image->image_size;
status = efi_relocate_kernel(image_addr, *image_size, *image_size,
kernel_base + MAX_UNCOMP_KERNEL_SIZE, 0, 0);
if (status != EFI_SUCCESS) {
pr_efi_err("Failed to relocate kernel.\n");
efi_free(*reserve_size, *reserve_addr);
*reserve_size = 0;
return status;
}
/*
* Check to see if we were able to allocate memory low enough
* in memory. The kernel determines the base of DRAM from the
* address at which the zImage is loaded.
*/
if (*image_addr + *image_size > dram_base + ZIMAGE_OFFSET_LIMIT) {
pr_efi_err("Failed to relocate kernel, no low memory available.\n");
efi_free(*reserve_size, *reserve_addr);
*reserve_size = 0;
efi_free(*image_size, *image_addr);
*image_size = 0; *image_size = 0;
return EFI_LOAD_ERROR;
}
return EFI_SUCCESS; return EFI_SUCCESS;
} }
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment