arm64/efi: efistub: don't abort if base of DRAM is occupied
authorArd Biesheuvel <ard.biesheuvel@linaro.org>
Wed, 30 Jul 2014 10:59:04 +0000 (11:59 +0100)
committerWill Deacon <will.deacon@arm.com>
Mon, 8 Sep 2014 13:39:18 +0000 (14:39 +0100)
If we cannot relocate the kernel Image to its preferred offset of base of DRAM
plus TEXT_OFFSET, instead relocate it to the lowest available 2 MB boundary plus
TEXT_OFFSET. We may lose a bit of memory at the low end, but we can still
proceed normally otherwise.

Acked-by: Mark Salter <msalter@redhat.com>
Acked-by: Mark Rutland <mark.rutland@arm.com>
Acked-by: Leif Lindholm <leif.lindholm@linaro.org>
Tested-by: Leif Lindholm <leif.lindholm@linaro.org>
Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Signed-off-by: Will Deacon <will.deacon@arm.com>
arch/arm64/kernel/efi-stub.c

index 1317fef8dde9688308791097b497ecb63370ec44..d27dd982ff267df105d8f8b75d8039719b3aaec9 100644 (file)
@@ -28,20 +28,16 @@ efi_status_t handle_kernel_image(efi_system_table_t *sys_table,
        kernel_size = _edata - _text;
        if (*image_addr != (dram_base + TEXT_OFFSET)) {
                kernel_memsize = kernel_size + (_end - _edata);
-               status = efi_relocate_kernel(sys_table, image_addr,
-                                            kernel_size, kernel_memsize,
-                                            dram_base + TEXT_OFFSET,
-                                            PAGE_SIZE);
+               status = efi_low_alloc(sys_table, kernel_memsize + TEXT_OFFSET,
+                                      SZ_2M, reserve_addr);
                if (status != EFI_SUCCESS) {
                        pr_efi_err(sys_table, "Failed to relocate kernel\n");
                        return status;
                }
-               if (*image_addr != (dram_base + TEXT_OFFSET)) {
-                       pr_efi_err(sys_table, "Failed to alloc kernel memory\n");
-                       efi_free(sys_table, kernel_memsize, *image_addr);
-                       return EFI_LOAD_ERROR;
-               }
-               *image_size = kernel_memsize;
+               memcpy((void *)*reserve_addr + TEXT_OFFSET, (void *)*image_addr,
+                      kernel_size);
+               *image_addr = *reserve_addr + TEXT_OFFSET;
+               *reserve_size = kernel_memsize + TEXT_OFFSET;
        }