Commit 6208857b authored by Ard Biesheuvel's avatar Ard Biesheuvel

efi/libstub: arm32: Base FDT and initrd placement on image address

The way we use the base of DRAM in the EFI stub is problematic as it
is ill defined what the base of DRAM actually means. There are some
restrictions on the placement of FDT and initrd which are defined in
terms of dram_base, but given that the placement of the kernel in
memory is what defines these boundaries (as on ARM, this is where the
linear region starts), it is better to use the image address in these
cases, and disregard dram_base altogether.
Reviewed-by: default avatarMaxim Uvarov <maxim.uvarov@linaro.org>
Tested-by: default avatarMaxim Uvarov <maxim.uvarov@linaro.org>
Signed-off-by: default avatarArd Biesheuvel <ardb@kernel.org>
parent f30f242f
......@@ -66,25 +66,24 @@ static inline void efifb_setup_from_dmi(struct screen_info *si, const char *opt)
#define MAX_UNCOMP_KERNEL_SIZE SZ_32M
/*
* The kernel zImage should preferably be located between 32 MB and 128 MB
* from the base of DRAM. The min address leaves space for a maximal size
* uncompressed image, and the max address is due to how the zImage decompressor
* picks a destination address.
* phys-to-virt patching requires that the physical to virtual offset fits
* into the immediate field of an add/sub instruction, which comes down to the
* 24 least significant bits being zero, and so the offset should be a multiple
* of 16 MB. Since PAGE_OFFSET itself is a multiple of 16 MB, the physical
* base should be aligned to 16 MB as well.
*/
#define ZIMAGE_OFFSET_LIMIT SZ_128M
#define MIN_ZIMAGE_OFFSET MAX_UNCOMP_KERNEL_SIZE
#define EFI_PHYS_ALIGN SZ_16M
/* on ARM, the FDT should be located in the first 128 MB of RAM */
static inline unsigned long efi_get_max_fdt_addr(unsigned long dram_base)
/* on ARM, the FDT should be located in a lowmem region */
static inline unsigned long efi_get_max_fdt_addr(unsigned long image_addr)
{
return dram_base + ZIMAGE_OFFSET_LIMIT;
return round_down(image_addr, EFI_PHYS_ALIGN) + SZ_512M;
}
/* on ARM, the initrd should be loaded in a lowmem region */
static inline unsigned long efi_get_max_initrd_addr(unsigned long dram_base,
unsigned long image_addr)
static inline unsigned long efi_get_max_initrd_addr(unsigned long image_addr)
{
return dram_base + SZ_512M;
return round_down(image_addr, EFI_PHYS_ALIGN) + SZ_512M;
}
struct efi_arm_entry_state {
......
......@@ -65,7 +65,7 @@ efi_status_t __efi_rt_asm_wrapper(void *, const char *, ...);
(SEGMENT_ALIGN > THREAD_ALIGN ? SEGMENT_ALIGN : THREAD_ALIGN)
/* on arm64, the FDT may be located anywhere in system RAM */
static inline unsigned long efi_get_max_fdt_addr(unsigned long dram_base)
static inline unsigned long efi_get_max_fdt_addr(unsigned long image_addr)
{
return ULONG_MAX;
}
......@@ -80,8 +80,7 @@ static inline unsigned long efi_get_max_fdt_addr(unsigned long dram_base)
* apply to other bootloaders, and are required for some kernel
* configurations.
*/
static inline unsigned long efi_get_max_initrd_addr(unsigned long dram_base,
unsigned long image_addr)
static inline unsigned long efi_get_max_initrd_addr(unsigned long image_addr)
{
return (image_addr & ~(SZ_1G - 1UL)) + (1UL << (VA_BITS_MIN - 1));
}
......
......@@ -252,7 +252,7 @@ efi_status_t handle_kernel_image(unsigned long *image_addr,
efi_status_t status;
/* use a 16 MiB aligned base for the decompressed kernel */
kernel_base = round_up(dram_base, SZ_16M) + TEXT_OFFSET;
kernel_base = round_up(dram_base, EFI_PHYS_ALIGN) + TEXT_OFFSET;
/*
* Note that some platforms (notably, the Raspberry Pi 2) put
......
......@@ -262,7 +262,7 @@ efi_status_t __efiapi efi_pe_entry(efi_handle_t handle,
efi_info("Generating empty DTB\n");
if (!efi_noinitrd) {
max_addr = efi_get_max_initrd_addr(dram_base, image_addr);
max_addr = efi_get_max_initrd_addr(image_addr);
status = efi_load_initrd(image, &initrd_addr, &initrd_size,
ULONG_MAX, max_addr);
if (status != EFI_SUCCESS)
......@@ -306,7 +306,7 @@ efi_status_t __efiapi efi_pe_entry(efi_handle_t handle,
install_memreserve_table();
status = allocate_new_fdt_and_exit_boot(handle, &fdt_addr,
efi_get_max_fdt_addr(dram_base),
efi_get_max_fdt_addr(image_addr),
initrd_addr, initrd_size,
cmdline_ptr, fdt_addr, fdt_size);
if (status != 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