diff options
-rw-r--r-- | arch/arm/Kconfig | 19 | ||||
-rw-r--r-- | arch/arm/boot/compressed/Makefile | 4 | ||||
-rw-r--r-- | arch/arm/boot/compressed/efi-header.S | 130 | ||||
-rw-r--r-- | arch/arm/boot/compressed/head.S | 54 | ||||
-rw-r--r-- | arch/arm/boot/compressed/vmlinux.lds.S | 7 | ||||
-rw-r--r-- | arch/arm/include/asm/efi.h | 23 | ||||
-rw-r--r-- | drivers/firmware/efi/libstub/Makefile | 9 | ||||
-rw-r--r-- | drivers/firmware/efi/libstub/arm-stub.c | 4 | ||||
-rw-r--r-- | drivers/firmware/efi/libstub/arm32-stub.c | 85 |
9 files changed, 331 insertions, 4 deletions
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 446e49b56e6a..67f8303d513d 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig | |||
@@ -2041,6 +2041,25 @@ config AUTO_ZRELADDR | |||
2041 | 0xf8000000. This assumes the zImage being placed in the first 128MB | 2041 | 0xf8000000. This assumes the zImage being placed in the first 128MB |
2042 | from start of memory. | 2042 | from start of memory. |
2043 | 2043 | ||
2044 | config EFI_STUB | ||
2045 | bool | ||
2046 | |||
2047 | config EFI | ||
2048 | bool "UEFI runtime support" | ||
2049 | depends on OF && !CPU_BIG_ENDIAN && MMU && AUTO_ZRELADDR && !XIP_KERNEL | ||
2050 | select UCS2_STRING | ||
2051 | select EFI_PARAMS_FROM_FDT | ||
2052 | select EFI_STUB | ||
2053 | select EFI_ARMSTUB | ||
2054 | select EFI_RUNTIME_WRAPPERS | ||
2055 | ---help--- | ||
2056 | This option provides support for runtime services provided | ||
2057 | by UEFI firmware (such as non-volatile variables, realtime | ||
2058 | clock, and platform reset). A UEFI stub is also provided to | ||
2059 | allow the kernel to be booted as an EFI application. This | ||
2060 | is only useful for kernels that may run on systems that have | ||
2061 | UEFI firmware. | ||
2062 | |||
2044 | endmenu | 2063 | endmenu |
2045 | 2064 | ||
2046 | menu "CPU Power Management" | 2065 | menu "CPU Power Management" |
diff --git a/arch/arm/boot/compressed/Makefile b/arch/arm/boot/compressed/Makefile index 3f9a9ebc77c3..4c23a68a0917 100644 --- a/arch/arm/boot/compressed/Makefile +++ b/arch/arm/boot/compressed/Makefile | |||
@@ -167,9 +167,11 @@ if [ $(words $(ZRELADDR)) -gt 1 -a "$(CONFIG_AUTO_ZRELADDR)" = "" ]; then \ | |||
167 | false; \ | 167 | false; \ |
168 | fi | 168 | fi |
169 | 169 | ||
170 | efi-obj-$(CONFIG_EFI_STUB) := $(objtree)/drivers/firmware/efi/libstub/lib.a | ||
171 | |||
170 | $(obj)/vmlinux: $(obj)/vmlinux.lds $(obj)/$(HEAD) $(obj)/piggy.$(suffix_y).o \ | 172 | $(obj)/vmlinux: $(obj)/vmlinux.lds $(obj)/$(HEAD) $(obj)/piggy.$(suffix_y).o \ |
171 | $(addprefix $(obj)/, $(OBJS)) $(lib1funcs) $(ashldi3) \ | 173 | $(addprefix $(obj)/, $(OBJS)) $(lib1funcs) $(ashldi3) \ |
172 | $(bswapsdi2) FORCE | 174 | $(bswapsdi2) $(efi-obj-y) FORCE |
173 | @$(check_for_multiple_zreladdr) | 175 | @$(check_for_multiple_zreladdr) |
174 | $(call if_changed,ld) | 176 | $(call if_changed,ld) |
175 | @$(check_for_bad_syms) | 177 | @$(check_for_bad_syms) |
diff --git a/arch/arm/boot/compressed/efi-header.S b/arch/arm/boot/compressed/efi-header.S new file mode 100644 index 000000000000..9d5dc4fda3c1 --- /dev/null +++ b/arch/arm/boot/compressed/efi-header.S | |||
@@ -0,0 +1,130 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2013-2015 Linaro Ltd | ||
3 | * Authors: Roy Franz <roy.franz@linaro.org> | ||
4 | * Ard Biesheuvel <ard.biesheuvel@linaro.org> | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License version 2 as | ||
8 | * published by the Free Software Foundation. | ||
9 | */ | ||
10 | |||
11 | .macro __nop | ||
12 | #ifdef CONFIG_EFI_STUB | ||
13 | @ This is almost but not quite a NOP, since it does clobber the | ||
14 | @ condition flags. But it is the best we can do for EFI, since | ||
15 | @ PE/COFF expects the magic string "MZ" at offset 0, while the | ||
16 | @ ARM/Linux boot protocol expects an executable instruction | ||
17 | @ there. | ||
18 | .inst 'M' | ('Z' << 8) | (0x1310 << 16) @ tstne r0, #0x4d000 | ||
19 | #else | ||
20 | mov r0, r0 | ||
21 | #endif | ||
22 | .endm | ||
23 | |||
24 | .macro __EFI_HEADER | ||
25 | #ifdef CONFIG_EFI_STUB | ||
26 | b __efi_start | ||
27 | |||
28 | .set start_offset, __efi_start - start | ||
29 | .org start + 0x3c | ||
30 | @ | ||
31 | @ The PE header can be anywhere in the file, but for | ||
32 | @ simplicity we keep it together with the MSDOS header | ||
33 | @ The offset to the PE/COFF header needs to be at offset | ||
34 | @ 0x3C in the MSDOS header. | ||
35 | @ The only 2 fields of the MSDOS header that are used are this | ||
36 | @ PE/COFF offset, and the "MZ" bytes at offset 0x0. | ||
37 | @ | ||
38 | .long pe_header - start @ Offset to the PE header. | ||
39 | |||
40 | pe_header: | ||
41 | .ascii "PE\0\0" | ||
42 | |||
43 | coff_header: | ||
44 | .short 0x01c2 @ ARM or Thumb | ||
45 | .short 2 @ nr_sections | ||
46 | .long 0 @ TimeDateStamp | ||
47 | .long 0 @ PointerToSymbolTable | ||
48 | .long 1 @ NumberOfSymbols | ||
49 | .short section_table - optional_header | ||
50 | @ SizeOfOptionalHeader | ||
51 | .short 0x306 @ Characteristics. | ||
52 | @ IMAGE_FILE_32BIT_MACHINE | | ||
53 | @ IMAGE_FILE_DEBUG_STRIPPED | | ||
54 | @ IMAGE_FILE_EXECUTABLE_IMAGE | | ||
55 | @ IMAGE_FILE_LINE_NUMS_STRIPPED | ||
56 | |||
57 | optional_header: | ||
58 | .short 0x10b @ PE32 format | ||
59 | .byte 0x02 @ MajorLinkerVersion | ||
60 | .byte 0x14 @ MinorLinkerVersion | ||
61 | .long _end - __efi_start @ SizeOfCode | ||
62 | .long 0 @ SizeOfInitializedData | ||
63 | .long 0 @ SizeOfUninitializedData | ||
64 | .long efi_stub_entry - start @ AddressOfEntryPoint | ||
65 | .long start_offset @ BaseOfCode | ||
66 | .long 0 @ data | ||
67 | |||
68 | extra_header_fields: | ||
69 | .long 0 @ ImageBase | ||
70 | .long 0x200 @ SectionAlignment | ||
71 | .long 0x200 @ FileAlignment | ||
72 | .short 0 @ MajorOperatingSystemVersion | ||
73 | .short 0 @ MinorOperatingSystemVersion | ||
74 | .short 0 @ MajorImageVersion | ||
75 | .short 0 @ MinorImageVersion | ||
76 | .short 0 @ MajorSubsystemVersion | ||
77 | .short 0 @ MinorSubsystemVersion | ||
78 | .long 0 @ Win32VersionValue | ||
79 | |||
80 | .long _end - start @ SizeOfImage | ||
81 | .long start_offset @ SizeOfHeaders | ||
82 | .long 0 @ CheckSum | ||
83 | .short 0xa @ Subsystem (EFI application) | ||
84 | .short 0 @ DllCharacteristics | ||
85 | .long 0 @ SizeOfStackReserve | ||
86 | .long 0 @ SizeOfStackCommit | ||
87 | .long 0 @ SizeOfHeapReserve | ||
88 | .long 0 @ SizeOfHeapCommit | ||
89 | .long 0 @ LoaderFlags | ||
90 | .long 0x6 @ NumberOfRvaAndSizes | ||
91 | |||
92 | .quad 0 @ ExportTable | ||
93 | .quad 0 @ ImportTable | ||
94 | .quad 0 @ ResourceTable | ||
95 | .quad 0 @ ExceptionTable | ||
96 | .quad 0 @ CertificationTable | ||
97 | .quad 0 @ BaseRelocationTable | ||
98 | |||
99 | section_table: | ||
100 | @ | ||
101 | @ The EFI application loader requires a relocation section | ||
102 | @ because EFI applications must be relocatable. This is a | ||
103 | @ dummy section as far as we are concerned. | ||
104 | @ | ||
105 | .ascii ".reloc\0\0" | ||
106 | .long 0 @ VirtualSize | ||
107 | .long 0 @ VirtualAddress | ||
108 | .long 0 @ SizeOfRawData | ||
109 | .long 0 @ PointerToRawData | ||
110 | .long 0 @ PointerToRelocations | ||
111 | .long 0 @ PointerToLineNumbers | ||
112 | .short 0 @ NumberOfRelocations | ||
113 | .short 0 @ NumberOfLineNumbers | ||
114 | .long 0x42100040 @ Characteristics | ||
115 | |||
116 | .ascii ".text\0\0\0" | ||
117 | .long _end - __efi_start @ VirtualSize | ||
118 | .long __efi_start @ VirtualAddress | ||
119 | .long _edata - __efi_start @ SizeOfRawData | ||
120 | .long __efi_start @ PointerToRawData | ||
121 | .long 0 @ PointerToRelocations | ||
122 | .long 0 @ PointerToLineNumbers | ||
123 | .short 0 @ NumberOfRelocations | ||
124 | .short 0 @ NumberOfLineNumbers | ||
125 | .long 0xe0500020 @ Characteristics | ||
126 | |||
127 | .align 9 | ||
128 | __efi_start: | ||
129 | #endif | ||
130 | .endm | ||
diff --git a/arch/arm/boot/compressed/head.S b/arch/arm/boot/compressed/head.S index 06e983f59980..af11c2f8f3b7 100644 --- a/arch/arm/boot/compressed/head.S +++ b/arch/arm/boot/compressed/head.S | |||
@@ -12,6 +12,8 @@ | |||
12 | #include <asm/assembler.h> | 12 | #include <asm/assembler.h> |
13 | #include <asm/v7m.h> | 13 | #include <asm/v7m.h> |
14 | 14 | ||
15 | #include "efi-header.S" | ||
16 | |||
15 | AR_CLASS( .arch armv7-a ) | 17 | AR_CLASS( .arch armv7-a ) |
16 | M_CLASS( .arch armv7-m ) | 18 | M_CLASS( .arch armv7-m ) |
17 | 19 | ||
@@ -126,7 +128,7 @@ | |||
126 | start: | 128 | start: |
127 | .type start,#function | 129 | .type start,#function |
128 | .rept 7 | 130 | .rept 7 |
129 | mov r0, r0 | 131 | __nop |
130 | .endr | 132 | .endr |
131 | ARM( mov r0, r0 ) | 133 | ARM( mov r0, r0 ) |
132 | ARM( b 1f ) | 134 | ARM( b 1f ) |
@@ -139,7 +141,8 @@ start: | |||
139 | .word 0x04030201 @ endianness flag | 141 | .word 0x04030201 @ endianness flag |
140 | 142 | ||
141 | THUMB( .thumb ) | 143 | THUMB( .thumb ) |
142 | 1: | 144 | 1: __EFI_HEADER |
145 | |||
143 | ARM_BE8( setend be ) @ go BE8 if compiled for BE8 | 146 | ARM_BE8( setend be ) @ go BE8 if compiled for BE8 |
144 | AR_CLASS( mrs r9, cpsr ) | 147 | AR_CLASS( mrs r9, cpsr ) |
145 | #ifdef CONFIG_ARM_VIRT_EXT | 148 | #ifdef CONFIG_ARM_VIRT_EXT |
@@ -1353,6 +1356,53 @@ __enter_kernel: | |||
1353 | 1356 | ||
1354 | reloc_code_end: | 1357 | reloc_code_end: |
1355 | 1358 | ||
1359 | #ifdef CONFIG_EFI_STUB | ||
1360 | .align 2 | ||
1361 | _start: .long start - . | ||
1362 | |||
1363 | ENTRY(efi_stub_entry) | ||
1364 | @ allocate space on stack for passing current zImage address | ||
1365 | @ and for the EFI stub to return of new entry point of | ||
1366 | @ zImage, as EFI stub may copy the kernel. Pointer address | ||
1367 | @ is passed in r2. r0 and r1 are passed through from the | ||
1368 | @ EFI firmware to efi_entry | ||
1369 | adr ip, _start | ||
1370 | ldr r3, [ip] | ||
1371 | add r3, r3, ip | ||
1372 | stmfd sp!, {r3, lr} | ||
1373 | mov r2, sp @ pass zImage address in r2 | ||
1374 | bl efi_entry | ||
1375 | |||
1376 | @ Check for error return from EFI stub. r0 has FDT address | ||
1377 | @ or error code. | ||
1378 | cmn r0, #1 | ||
1379 | beq efi_load_fail | ||
1380 | |||
1381 | @ Preserve return value of efi_entry() in r4 | ||
1382 | mov r4, r0 | ||
1383 | bl cache_clean_flush | ||
1384 | bl cache_off | ||
1385 | |||
1386 | @ Set parameters for booting zImage according to boot protocol | ||
1387 | @ put FDT address in r2, it was returned by efi_entry() | ||
1388 | @ r1 is the machine type, and r0 needs to be 0 | ||
1389 | mov r0, #0 | ||
1390 | mov r1, #0xFFFFFFFF | ||
1391 | mov r2, r4 | ||
1392 | |||
1393 | @ Branch to (possibly) relocated zImage that is in [sp] | ||
1394 | ldr lr, [sp] | ||
1395 | ldr ip, =start_offset | ||
1396 | add lr, lr, ip | ||
1397 | mov pc, lr @ no mode switch | ||
1398 | |||
1399 | efi_load_fail: | ||
1400 | @ Return EFI_LOAD_ERROR to EFI firmware on error. | ||
1401 | ldr r0, =0x80000001 | ||
1402 | ldmfd sp!, {ip, pc} | ||
1403 | ENDPROC(efi_stub_entry) | ||
1404 | #endif | ||
1405 | |||
1356 | .align | 1406 | .align |
1357 | .section ".stack", "aw", %nobits | 1407 | .section ".stack", "aw", %nobits |
1358 | .L_user_stack: .space 4096 | 1408 | .L_user_stack: .space 4096 |
diff --git a/arch/arm/boot/compressed/vmlinux.lds.S b/arch/arm/boot/compressed/vmlinux.lds.S index 2b60b843ac5e..81c493156ce8 100644 --- a/arch/arm/boot/compressed/vmlinux.lds.S +++ b/arch/arm/boot/compressed/vmlinux.lds.S | |||
@@ -48,6 +48,13 @@ SECTIONS | |||
48 | *(.rodata) | 48 | *(.rodata) |
49 | *(.rodata.*) | 49 | *(.rodata.*) |
50 | } | 50 | } |
51 | .data : { | ||
52 | /* | ||
53 | * The EFI stub always executes from RAM, and runs strictly before the | ||
54 | * decompressor, so we can make an exception for its r/w data, and keep it | ||
55 | */ | ||
56 | *(.data.efistub) | ||
57 | } | ||
51 | .piggydata : { | 58 | .piggydata : { |
52 | *(.piggydata) | 59 | *(.piggydata) |
53 | } | 60 | } |
diff --git a/arch/arm/include/asm/efi.h b/arch/arm/include/asm/efi.h index c91e330616ad..e0eea72deb87 100644 --- a/arch/arm/include/asm/efi.h +++ b/arch/arm/include/asm/efi.h | |||
@@ -57,4 +57,27 @@ void efi_virtmap_unload(void); | |||
57 | #define efi_init() | 57 | #define efi_init() |
58 | #endif /* CONFIG_EFI */ | 58 | #endif /* CONFIG_EFI */ |
59 | 59 | ||
60 | /* arch specific definitions used by the stub code */ | ||
61 | |||
62 | #define efi_call_early(f, ...) sys_table_arg->boottime->f(__VA_ARGS__) | ||
63 | |||
64 | /* | ||
65 | * A reasonable upper bound for the uncompressed kernel size is 32 MBytes, | ||
66 | * so we will reserve that amount of memory. We have no easy way to tell what | ||
67 | * the actuall size of code + data the uncompressed kernel will use. | ||
68 | * If this is insufficient, the decompressor will relocate itself out of the | ||
69 | * way before performing the decompression. | ||
70 | */ | ||
71 | #define MAX_UNCOMP_KERNEL_SIZE SZ_32M | ||
72 | |||
73 | /* | ||
74 | * The kernel zImage should preferably be located between 32 MB and 128 MB | ||
75 | * from the base of DRAM. The min address leaves space for a maximal size | ||
76 | * uncompressed image, and the max address is due to how the zImage decompressor | ||
77 | * picks a destination address. | ||
78 | */ | ||
79 | #define ZIMAGE_OFFSET_LIMIT SZ_128M | ||
80 | #define MIN_ZIMAGE_OFFSET MAX_UNCOMP_KERNEL_SIZE | ||
81 | #define MAX_FDT_OFFSET ZIMAGE_OFFSET_LIMIT | ||
82 | |||
60 | #endif /* _ASM_ARM_EFI_H */ | 83 | #endif /* _ASM_ARM_EFI_H */ |
diff --git a/drivers/firmware/efi/libstub/Makefile b/drivers/firmware/efi/libstub/Makefile index 3c0467d3688c..8cf9ccbf42d5 100644 --- a/drivers/firmware/efi/libstub/Makefile +++ b/drivers/firmware/efi/libstub/Makefile | |||
@@ -34,6 +34,7 @@ $(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_ARM) += arm32-stub.o | ||
37 | lib-$(CONFIG_ARM64) += arm64-stub.o | 38 | lib-$(CONFIG_ARM64) += arm64-stub.o |
38 | CFLAGS_arm64-stub.o := -DTEXT_OFFSET=$(TEXT_OFFSET) | 39 | CFLAGS_arm64-stub.o := -DTEXT_OFFSET=$(TEXT_OFFSET) |
39 | 40 | ||
@@ -67,3 +68,11 @@ quiet_cmd_stubcopy = STUBCPY $@ | |||
67 | $(OBJDUMP) -r $@ | grep $(STUBCOPY_RELOC-y) \ | 68 | $(OBJDUMP) -r $@ | grep $(STUBCOPY_RELOC-y) \ |
68 | && (echo >&2 "$@: absolute symbol references not allowed in the EFI stub"; \ | 69 | && (echo >&2 "$@: absolute symbol references not allowed in the EFI stub"; \ |
69 | rm -f $@; /bin/false); else /bin/false; fi | 70 | rm -f $@; /bin/false); else /bin/false; fi |
71 | |||
72 | # | ||
73 | # ARM discards the .data section because it disallows r/w data in the | ||
74 | # decompressor. So move our .data to .data.efistub, which is preserved | ||
75 | # explicitly by the decompressor linker script. | ||
76 | # | ||
77 | STUBCOPY_FLAGS-$(CONFIG_ARM) += --rename-section .data=.data.efistub | ||
78 | STUBCOPY_RELOC-$(CONFIG_ARM) := R_ARM_ABS | ||
diff --git a/drivers/firmware/efi/libstub/arm-stub.c b/drivers/firmware/efi/libstub/arm-stub.c index 950c87f5d279..3397902e4040 100644 --- a/drivers/firmware/efi/libstub/arm-stub.c +++ b/drivers/firmware/efi/libstub/arm-stub.c | |||
@@ -303,8 +303,10 @@ fail: | |||
303 | * The value chosen is the largest non-zero power of 2 suitable for this purpose | 303 | * The value chosen is the largest non-zero power of 2 suitable for this purpose |
304 | * both on 32-bit and 64-bit ARM CPUs, to maximize the likelihood that it can | 304 | * both on 32-bit and 64-bit ARM CPUs, to maximize the likelihood that it can |
305 | * be mapped efficiently. | 305 | * be mapped efficiently. |
306 | * Since 32-bit ARM could potentially execute with a 1G/3G user/kernel split, | ||
307 | * map everything below 1 GB. | ||
306 | */ | 308 | */ |
307 | #define EFI_RT_VIRTUAL_BASE 0x40000000 | 309 | #define EFI_RT_VIRTUAL_BASE SZ_512M |
308 | 310 | ||
309 | static int cmp_mem_desc(const void *l, const void *r) | 311 | static int cmp_mem_desc(const void *l, const void *r) |
310 | { | 312 | { |
diff --git a/drivers/firmware/efi/libstub/arm32-stub.c b/drivers/firmware/efi/libstub/arm32-stub.c new file mode 100644 index 000000000000..495ebd657e38 --- /dev/null +++ b/drivers/firmware/efi/libstub/arm32-stub.c | |||
@@ -0,0 +1,85 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2013 Linaro Ltd; <roy.franz@linaro.org> | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License version 2 as | ||
6 | * published by the Free Software Foundation. | ||
7 | * | ||
8 | */ | ||
9 | #include <linux/efi.h> | ||
10 | #include <asm/efi.h> | ||
11 | |||
12 | efi_status_t handle_kernel_image(efi_system_table_t *sys_table, | ||
13 | unsigned long *image_addr, | ||
14 | unsigned long *image_size, | ||
15 | unsigned long *reserve_addr, | ||
16 | unsigned long *reserve_size, | ||
17 | unsigned long dram_base, | ||
18 | efi_loaded_image_t *image) | ||
19 | { | ||
20 | unsigned long nr_pages; | ||
21 | efi_status_t status; | ||
22 | /* Use alloc_addr to tranlsate between types */ | ||
23 | efi_physical_addr_t alloc_addr; | ||
24 | |||
25 | /* | ||
26 | * Verify that the DRAM base address is compatible with the ARM | ||
27 | * boot protocol, which determines the base of DRAM by masking | ||
28 | * off the low 27 bits of the address at which the zImage is | ||
29 | * loaded. These assumptions are made by the decompressor, | ||
30 | * before any memory map is available. | ||
31 | */ | ||
32 | dram_base = round_up(dram_base, SZ_128M); | ||
33 | |||
34 | /* | ||
35 | * Reserve memory for the uncompressed kernel image. This is | ||
36 | * all that prevents any future allocations from conflicting | ||
37 | * with the kernel. Since we can't tell from the compressed | ||
38 | * image how much DRAM the kernel actually uses (due to BSS | ||
39 | * size uncertainty) we allocate the maximum possible size. | ||
40 | * Do this very early, as prints can cause memory allocations | ||
41 | * that may conflict with this. | ||
42 | */ | ||
43 | alloc_addr = dram_base; | ||
44 | *reserve_size = MAX_UNCOMP_KERNEL_SIZE; | ||
45 | nr_pages = round_up(*reserve_size, EFI_PAGE_SIZE) / EFI_PAGE_SIZE; | ||
46 | status = sys_table->boottime->allocate_pages(EFI_ALLOCATE_ADDRESS, | ||
47 | EFI_LOADER_DATA, | ||
48 | nr_pages, &alloc_addr); | ||
49 | if (status != EFI_SUCCESS) { | ||
50 | *reserve_size = 0; | ||
51 | pr_efi_err(sys_table, "Unable to allocate memory for uncompressed kernel.\n"); | ||
52 | return status; | ||
53 | } | ||
54 | *reserve_addr = alloc_addr; | ||
55 | |||
56 | /* | ||
57 | * Relocate the zImage, so that it appears in the lowest 128 MB | ||
58 | * memory window. | ||
59 | */ | ||
60 | *image_size = image->image_size; | ||
61 | status = efi_relocate_kernel(sys_table, image_addr, *image_size, | ||
62 | *image_size, | ||
63 | dram_base + MAX_UNCOMP_KERNEL_SIZE, 0); | ||
64 | if (status != EFI_SUCCESS) { | ||
65 | pr_efi_err(sys_table, "Failed to relocate kernel.\n"); | ||
66 | efi_free(sys_table, *reserve_size, *reserve_addr); | ||
67 | *reserve_size = 0; | ||
68 | return status; | ||
69 | } | ||
70 | |||
71 | /* | ||
72 | * Check to see if we were able to allocate memory low enough | ||
73 | * in memory. The kernel determines the base of DRAM from the | ||
74 | * address at which the zImage is loaded. | ||
75 | */ | ||
76 | if (*image_addr + *image_size > dram_base + ZIMAGE_OFFSET_LIMIT) { | ||
77 | pr_efi_err(sys_table, "Failed to relocate kernel, no low memory available.\n"); | ||
78 | efi_free(sys_table, *reserve_size, *reserve_addr); | ||
79 | *reserve_size = 0; | ||
80 | efi_free(sys_table, *image_size, *image_addr); | ||
81 | *image_size = 0; | ||
82 | return EFI_LOAD_ERROR; | ||
83 | } | ||
84 | return EFI_SUCCESS; | ||
85 | } | ||