Skip to content

Commit 138728d

Browse files
Ard BiesheuvelIngo Molnar
authored andcommitted
efi/arm-stub: Correct FDT and initrd allocation rules for arm64
On arm64, we have made some changes over the past year to the way the kernel itself is allocated and to how it deals with the initrd and FDT. This patch brings the allocation logic in the EFI stub in line with that, which is necessary because the introduction of KASLR has created the possibility for the initrd to be allocated in a place where the kernel may not be able to map it. (This is mostly a theoretical scenario, since it only affects systems where the physical memory footprint exceeds the size of the linear mapping.) Since we know the kernel itself will be covered by the linear mapping, choose a suitably sized window (i.e., based on the size of the linear region) covering the kernel when allocating memory for the initrd. The FDT may be anywhere in memory on arm64 now that we map it via the fixmap, so we can lift the address restriction there completely. Tested-by: Richard Ruigrok <rruigrok@codeaurora.org> Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org> Reviewed-by: Jeffrey Hugo <jhugo@codeaurora.org> Cc: Linus Torvalds <torvalds@linux-foundation.org> Cc: Matt Fleming <matt@codeblueprint.co.uk> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Thomas Gleixner <tglx@linutronix.de> Cc: linux-efi@vger.kernel.org Link: http://lkml.kernel.org/r/20170404160245.27812-4-ard.biesheuvel@linaro.org Signed-off-by: Ingo Molnar <mingo@kernel.org>
1 parent 55d728a commit 138728d

File tree

3 files changed

+39
-5
lines changed

3 files changed

+39
-5
lines changed

arch/arm/include/asm/efi.h

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,18 @@ static inline void efifb_setup_from_dmi(struct screen_info *si, const char *opt)
8585
*/
8686
#define ZIMAGE_OFFSET_LIMIT SZ_128M
8787
#define MIN_ZIMAGE_OFFSET MAX_UNCOMP_KERNEL_SIZE
88-
#define MAX_FDT_OFFSET ZIMAGE_OFFSET_LIMIT
88+
89+
/* on ARM, the FDT should be located in the first 128 MB of RAM */
90+
static inline unsigned long efi_get_max_fdt_addr(unsigned long dram_base)
91+
{
92+
return dram_base + ZIMAGE_OFFSET_LIMIT;
93+
}
94+
95+
/* on ARM, the initrd should be loaded in a lowmem region */
96+
static inline unsigned long efi_get_max_initrd_addr(unsigned long dram_base,
97+
unsigned long image_addr)
98+
{
99+
return dram_base + SZ_512M;
100+
}
89101

90102
#endif /* _ASM_ARM_EFI_H */

arch/arm64/include/asm/efi.h

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,28 @@ int efi_set_mapping_permissions(struct mm_struct *mm, efi_memory_desc_t *md);
4646
* 2MiB so we know it won't cross a 2MiB boundary.
4747
*/
4848
#define EFI_FDT_ALIGN SZ_2M /* used by allocate_new_fdt_and_exit_boot() */
49-
#define MAX_FDT_OFFSET SZ_512M
49+
50+
/* on arm64, the FDT may be located anywhere in system RAM */
51+
static inline unsigned long efi_get_max_fdt_addr(unsigned long dram_base)
52+
{
53+
return ULONG_MAX;
54+
}
55+
56+
/*
57+
* On arm64, we have to ensure that the initrd ends up in the linear region,
58+
* which is a 1 GB aligned region of size '1UL << (VA_BITS - 1)' that is
59+
* guaranteed to cover the kernel Image.
60+
*
61+
* Since the EFI stub is part of the kernel Image, we can relax the
62+
* usual requirements in Documentation/arm64/booting.txt, which still
63+
* apply to other bootloaders, and are required for some kernel
64+
* configurations.
65+
*/
66+
static inline unsigned long efi_get_max_initrd_addr(unsigned long dram_base,
67+
unsigned long image_addr)
68+
{
69+
return (image_addr & ~(SZ_1G - 1UL)) + (1UL << (VA_BITS - 1));
70+
}
5071

5172
#define efi_call_early(f, ...) sys_table_arg->boottime->f(__VA_ARGS__)
5273
#define __efi_call_early(f, ...) f(__VA_ARGS__)

drivers/firmware/efi/libstub/arm-stub.c

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -213,8 +213,9 @@ unsigned long efi_entry(void *handle, efi_system_table_t *sys_table,
213213
if (!fdt_addr)
214214
pr_efi(sys_table, "Generating empty DTB\n");
215215

216-
status = handle_cmdline_files(sys_table, image, cmdline_ptr,
217-
"initrd=", dram_base + SZ_512M,
216+
status = handle_cmdline_files(sys_table, image, cmdline_ptr, "initrd=",
217+
efi_get_max_initrd_addr(dram_base,
218+
*image_addr),
218219
(unsigned long *)&initrd_addr,
219220
(unsigned long *)&initrd_size);
220221
if (status != EFI_SUCCESS)
@@ -224,7 +225,7 @@ unsigned long efi_entry(void *handle, efi_system_table_t *sys_table,
224225

225226
new_fdt_addr = fdt_addr;
226227
status = allocate_new_fdt_and_exit_boot(sys_table, handle,
227-
&new_fdt_addr, dram_base + MAX_FDT_OFFSET,
228+
&new_fdt_addr, efi_get_max_fdt_addr(dram_base),
228229
initrd_addr, initrd_size, cmdline_ptr,
229230
fdt_addr, fdt_size);
230231

0 commit comments

Comments
 (0)