Commit 41cd96fa authored by Ard Biesheuvel's avatar Ard Biesheuvel Committed by Ingo Molnar

efi: libstub/arm: Account for firmware reserved memory at the base of RAM

The EFI stubloader for ARM starts out by allocating a 32 MB window
at the base of RAM, in order to ensure that the decompressor (which
blindly copies the uncompressed kernel into that window) does not
overwrite other allocations that are made while running in the context
of the EFI firmware.

In some cases, (e.g., U-Boot running on the Raspberry Pi 2), this is
causing boot failures because this initial allocation conflicts with
a page of reserved memory at the base of RAM that contains the SMP spin
tables and other pieces of firmware data and which was put there by
the bootloader under the assumption that the TEXT_OFFSET window right
below the kernel is only used partially during early boot, and will be
left alone once the memory reservations are processed and taken into
account.

So let's permit reserved memory regions to exist in the region starting
at the base of RAM, and ending at TEXT_OFFSET - 5 * PAGE_SIZE, which is
the window below the kernel that is not touched by the early boot code.
Tested-by: default avatarGuillaume Gardet <Guillaume.Gardet@arm.com>
Signed-off-by: default avatarArd Biesheuvel <ard.biesheuvel@linaro.org>
Acked-by: default avatarChester Lin <clin@suse.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: linux-efi@vger.kernel.org
Link: https://lkml.kernel.org/r/20191029173755.27149-5-ardb@kernel.orgSigned-off-by: default avatarIngo Molnar <mingo@kernel.org>
parent 18b915ac
...@@ -52,6 +52,7 @@ lib-$(CONFIG_EFI_ARMSTUB) += arm-stub.o fdt.o string.o random.o \ ...@@ -52,6 +52,7 @@ lib-$(CONFIG_EFI_ARMSTUB) += arm-stub.o fdt.o string.o random.o \
lib-$(CONFIG_ARM) += arm32-stub.o lib-$(CONFIG_ARM) += arm32-stub.o
lib-$(CONFIG_ARM64) += arm64-stub.o lib-$(CONFIG_ARM64) += arm64-stub.o
CFLAGS_arm32-stub.o := -DTEXT_OFFSET=$(TEXT_OFFSET)
CFLAGS_arm64-stub.o := -DTEXT_OFFSET=$(TEXT_OFFSET) CFLAGS_arm64-stub.o := -DTEXT_OFFSET=$(TEXT_OFFSET)
# #
......
...@@ -195,6 +195,7 @@ efi_status_t handle_kernel_image(efi_system_table_t *sys_table, ...@@ -195,6 +195,7 @@ efi_status_t handle_kernel_image(efi_system_table_t *sys_table,
unsigned long dram_base, unsigned long dram_base,
efi_loaded_image_t *image) efi_loaded_image_t *image)
{ {
unsigned long kernel_base;
efi_status_t status; efi_status_t status;
/* /*
...@@ -204,9 +205,18 @@ efi_status_t handle_kernel_image(efi_system_table_t *sys_table, ...@@ -204,9 +205,18 @@ efi_status_t handle_kernel_image(efi_system_table_t *sys_table,
* loaded. These assumptions are made by the decompressor, * loaded. These assumptions are made by the decompressor,
* before any memory map is available. * before any memory map is available.
*/ */
dram_base = round_up(dram_base, SZ_128M); kernel_base = round_up(dram_base, SZ_128M);
status = reserve_kernel_base(sys_table, dram_base, reserve_addr, /*
* Note that some platforms (notably, the Raspberry Pi 2) put
* spin-tables and other pieces of firmware at the base of RAM,
* abusing the fact that the window of TEXT_OFFSET bytes at the
* base of the kernel image is only partially used at the moment.
* (Up to 5 pages are used for the swapper page tables)
*/
kernel_base += TEXT_OFFSET - 5 * PAGE_SIZE;
status = reserve_kernel_base(sys_table, kernel_base, reserve_addr,
reserve_size); reserve_size);
if (status != EFI_SUCCESS) { if (status != EFI_SUCCESS) {
pr_efi_err(sys_table, "Unable to allocate memory for uncompressed kernel.\n"); pr_efi_err(sys_table, "Unable to allocate memory for uncompressed kernel.\n");
...@@ -220,7 +230,7 @@ efi_status_t handle_kernel_image(efi_system_table_t *sys_table, ...@@ -220,7 +230,7 @@ efi_status_t handle_kernel_image(efi_system_table_t *sys_table,
*image_size = image->image_size; *image_size = image->image_size;
status = efi_relocate_kernel(sys_table, image_addr, *image_size, status = efi_relocate_kernel(sys_table, image_addr, *image_size,
*image_size, *image_size,
dram_base + MAX_UNCOMP_KERNEL_SIZE, 0); kernel_base + MAX_UNCOMP_KERNEL_SIZE, 0);
if (status != EFI_SUCCESS) { if (status != EFI_SUCCESS) {
pr_efi_err(sys_table, "Failed to relocate kernel.\n"); pr_efi_err(sys_table, "Failed to relocate kernel.\n");
efi_free(sys_table, *reserve_size, *reserve_addr); efi_free(sys_table, *reserve_size, *reserve_addr);
......
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