diff options
author | Ard Biesheuvel <ard.biesheuvel@linaro.org> | 2015-10-23 10:48:14 -0400 |
---|---|---|
committer | Catalin Marinas <catalin.marinas@arm.com> | 2015-10-30 12:02:52 -0400 |
commit | bf457786f569cc480629d7855cac1fd1173ac009 (patch) | |
tree | f4f2eea9505db363050ae55eb80b2317b2446eb9 /drivers/firmware | |
parent | cb083816ab5ac3d10a9417527f07fc5962cc3808 (diff) |
arm64/efi: move arm64 specific stub C code to libstub
Now that we added special handling to the C files in libstub, move
the one remaining arm64 specific EFI stub C file to libstub as
well, so that it gets the same treatment. This should prevent future
changes from resulting in binaries that may execute incorrectly in
UEFI context.
With efi-entry.S the only remaining EFI stub source file under
arch/arm64, we can also simplify the Makefile logic somewhat.
Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Reviewed-by: Matt Fleming <matt@codeblueprint.co.uk>
Tested-by: Jeremy Linton <jeremy.linton@arm.com>
Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
Diffstat (limited to 'drivers/firmware')
-rw-r--r-- | drivers/firmware/efi/libstub/Makefile | 3 | ||||
-rw-r--r-- | drivers/firmware/efi/libstub/arm64-stub.c | 68 |
2 files changed, 71 insertions, 0 deletions
diff --git a/drivers/firmware/efi/libstub/Makefile b/drivers/firmware/efi/libstub/Makefile index bca9a76cbd33..92ae557abbbc 100644 --- a/drivers/firmware/efi/libstub/Makefile +++ b/drivers/firmware/efi/libstub/Makefile | |||
@@ -34,6 +34,9 @@ $(obj)/lib-%.o: $(srctree)/lib/%.c FORCE | |||
34 | lib-$(CONFIG_EFI_ARMSTUB) += arm-stub.o fdt.o string.o \ | 34 | lib-$(CONFIG_EFI_ARMSTUB) += arm-stub.o fdt.o string.o \ |
35 | $(patsubst %.c,lib-%.o,$(arm-deps)) | 35 | $(patsubst %.c,lib-%.o,$(arm-deps)) |
36 | 36 | ||
37 | lib-$(CONFIG_ARM64) += arm64-stub.o | ||
38 | CFLAGS_arm64-stub.o := -DTEXT_OFFSET=$(TEXT_OFFSET) | ||
39 | |||
37 | # | 40 | # |
38 | # arm64 puts the stub in the kernel proper, which will unnecessarily retain all | 41 | # arm64 puts the stub in the kernel proper, which will unnecessarily retain all |
39 | # code indefinitely unless it is annotated as __init/__initdata/__initconst etc. | 42 | # code indefinitely unless it is annotated as __init/__initdata/__initconst etc. |
diff --git a/drivers/firmware/efi/libstub/arm64-stub.c b/drivers/firmware/efi/libstub/arm64-stub.c new file mode 100644 index 000000000000..816120ece6bc --- /dev/null +++ b/drivers/firmware/efi/libstub/arm64-stub.c | |||
@@ -0,0 +1,68 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2013, 2014 Linaro Ltd; <roy.franz@linaro.org> | ||
3 | * | ||
4 | * This file implements the EFI boot stub for the arm64 kernel. | ||
5 | * Adapted from ARM version by Mark Salter <msalter@redhat.com> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License version 2 as | ||
9 | * published by the Free Software Foundation. | ||
10 | * | ||
11 | */ | ||
12 | #include <linux/efi.h> | ||
13 | #include <asm/efi.h> | ||
14 | #include <asm/sections.h> | ||
15 | |||
16 | efi_status_t __init handle_kernel_image(efi_system_table_t *sys_table_arg, | ||
17 | unsigned long *image_addr, | ||
18 | unsigned long *image_size, | ||
19 | unsigned long *reserve_addr, | ||
20 | unsigned long *reserve_size, | ||
21 | unsigned long dram_base, | ||
22 | efi_loaded_image_t *image) | ||
23 | { | ||
24 | efi_status_t status; | ||
25 | unsigned long kernel_size, kernel_memsize = 0; | ||
26 | unsigned long nr_pages; | ||
27 | void *old_image_addr = (void *)*image_addr; | ||
28 | |||
29 | /* Relocate the image, if required. */ | ||
30 | kernel_size = _edata - _text; | ||
31 | if (*image_addr != (dram_base + TEXT_OFFSET)) { | ||
32 | kernel_memsize = kernel_size + (_end - _edata); | ||
33 | |||
34 | /* | ||
35 | * First, try a straight allocation at the preferred offset. | ||
36 | * This will work around the issue where, if dram_base == 0x0, | ||
37 | * efi_low_alloc() refuses to allocate at 0x0 (to prevent the | ||
38 | * address of the allocation to be mistaken for a FAIL return | ||
39 | * value or a NULL pointer). It will also ensure that, on | ||
40 | * platforms where the [dram_base, dram_base + TEXT_OFFSET) | ||
41 | * interval is partially occupied by the firmware (like on APM | ||
42 | * Mustang), we can still place the kernel at the address | ||
43 | * 'dram_base + TEXT_OFFSET'. | ||
44 | */ | ||
45 | *image_addr = *reserve_addr = dram_base + TEXT_OFFSET; | ||
46 | nr_pages = round_up(kernel_memsize, EFI_ALLOC_ALIGN) / | ||
47 | EFI_PAGE_SIZE; | ||
48 | status = efi_call_early(allocate_pages, EFI_ALLOCATE_ADDRESS, | ||
49 | EFI_LOADER_DATA, nr_pages, | ||
50 | (efi_physical_addr_t *)reserve_addr); | ||
51 | if (status != EFI_SUCCESS) { | ||
52 | kernel_memsize += TEXT_OFFSET; | ||
53 | status = efi_low_alloc(sys_table_arg, kernel_memsize, | ||
54 | SZ_2M, reserve_addr); | ||
55 | |||
56 | if (status != EFI_SUCCESS) { | ||
57 | pr_efi_err(sys_table_arg, "Failed to relocate kernel\n"); | ||
58 | return status; | ||
59 | } | ||
60 | *image_addr = *reserve_addr + TEXT_OFFSET; | ||
61 | } | ||
62 | memcpy((void *)*image_addr, old_image_addr, kernel_size); | ||
63 | *reserve_size = kernel_memsize; | ||
64 | } | ||
65 | |||
66 | |||
67 | return EFI_SUCCESS; | ||
68 | } | ||