aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/firmware
diff options
context:
space:
mode:
authorArd Biesheuvel <ard.biesheuvel@linaro.org>2015-10-23 10:48:14 -0400
committerCatalin Marinas <catalin.marinas@arm.com>2015-10-30 12:02:52 -0400
commitbf457786f569cc480629d7855cac1fd1173ac009 (patch)
treef4f2eea9505db363050ae55eb80b2317b2446eb9 /drivers/firmware
parentcb083816ab5ac3d10a9417527f07fc5962cc3808 (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/Makefile3
-rw-r--r--drivers/firmware/efi/libstub/arm64-stub.c68
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
34lib-$(CONFIG_EFI_ARMSTUB) += arm-stub.o fdt.o string.o \ 34lib-$(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
37lib-$(CONFIG_ARM64) += arm64-stub.o
38CFLAGS_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
16efi_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}