History

arm64/efi: do not assume DRAM base is aligned to 2 MB

The current arm64 Image relocation code in the UEFI stub assumes that the dram_base argument it receives is always a multiple of 2 MB. In reality, it is simply the lowest start address of all RAM entries in the UEFI memory map, which means it could be any multiple of 4 KB. Since the arm64 kernel Image needs to reside TEXT_OFFSET bytes beyond a 2 MB aligned base, or it will fail to boot, make sure we round dram_base to 2 MB before using it to calculate the relocation address.

Ard Biesheuvel committed 11 years ago

Commit 73effcc1 parent 97029701 file · +12 −2Browse files

Unified · Split

arch/arm64/kernel/efi-stub.c+12−2
@@ -25,10 +25,20 @@ efi_status_t __init handle_kernel_image(efi_system_table_t *sys_table_arg, · 24 unmodified lines
25 unsigned long kernel_size, kernel_memsize = 0;25 unsigned long kernel_size, kernel_memsize = 0;
26 unsigned long nr_pages;26 unsigned long nr_pages;
27 void *old_image_addr = (void *)*image_addr;27 void *old_image_addr = (void *)*image_addr;
28 unsigned long preferred_offset;
29
30 /*
31 * The preferred offset of the kernel Image is TEXT_OFFSET bytes beyond
32 * a 2 MB aligned base, which itself may be lower than dram_base, as
33 * long as the resulting offset equals or exceeds it.
34 */
35 preferred_offset = round_down(dram_base, SZ_2M) + TEXT_OFFSET;
36 if (preferred_offset < dram_base)
37 preferred_offset += SZ_2M;
28 38
29 /* Relocate the image, if required. */39 /* Relocate the image, if required. */
30 kernel_size = _edata - _text;40 kernel_size = _edata - _text;
31 if (*image_addr != (dram_base + TEXT_OFFSET)) {41 if (*image_addr != preferred_offset) {
32 kernel_memsize = kernel_size + (_end - _edata);42 kernel_memsize = kernel_size + (_end - _edata);
33 43
34 /*44 /*
@@ -42,7 +52,7 @@ efi_status_t __init handle_kernel_image(efi_system_table_t *sys_table_arg, · 7 unmodified lines
42 * Mustang), we can still place the kernel at the address52 * Mustang), we can still place the kernel at the address
43 * 'dram_base + TEXT_OFFSET'.53 * 'dram_base + TEXT_OFFSET'.
44 */54 */
45 *image_addr = *reserve_addr = dram_base + TEXT_OFFSET;55 *image_addr = *reserve_addr = preferred_offset;
46 nr_pages = round_up(kernel_memsize, EFI_ALLOC_ALIGN) /56 nr_pages = round_up(kernel_memsize, EFI_ALLOC_ALIGN) /
47 EFI_PAGE_SIZE;57 EFI_PAGE_SIZE;
48 status = efi_call_early(allocate_pages, EFI_ALLOCATE_ADDRESS,58 status = efi_call_early(allocate_pages, EFI_ALLOCATE_ADDRESS,