summaryrefslogtreecommitdiffstats
path: root/recipes-kernel/linux/linux-hierofalcon/01-arm64-boot-BE-kernels-from-UEFI.patch
diff options
context:
space:
mode:
authorTudor Florea <tudor.florea@enea.com>2015-10-08 22:42:49 +0200
committerTudor Florea <tudor.florea@enea.com>2015-10-08 22:42:49 +0200
commit635d320abfa6dc3c0e1d00e3ceae567dd0e55a5b (patch)
treedcd42fafb9189d3be13ef3d95f9ce6f4f5cfa267 /recipes-kernel/linux/linux-hierofalcon/01-arm64-boot-BE-kernels-from-UEFI.patch
downloadmeta-hierofalcon-635d320abfa6dc3c0e1d00e3ceae567dd0e55a5b.tar.gz
initial commit for Enea Linux 5.0 arm
Signed-off-by: Tudor Florea <tudor.florea@enea.com>
Diffstat (limited to 'recipes-kernel/linux/linux-hierofalcon/01-arm64-boot-BE-kernels-from-UEFI.patch')
-rw-r--r--recipes-kernel/linux/linux-hierofalcon/01-arm64-boot-BE-kernels-from-UEFI.patch995
1 files changed, 995 insertions, 0 deletions
diff --git a/recipes-kernel/linux/linux-hierofalcon/01-arm64-boot-BE-kernels-from-UEFI.patch b/recipes-kernel/linux/linux-hierofalcon/01-arm64-boot-BE-kernels-from-UEFI.patch
new file mode 100644
index 0000000..6790315
--- /dev/null
+++ b/recipes-kernel/linux/linux-hierofalcon/01-arm64-boot-BE-kernels-from-UEFI.patch
@@ -0,0 +1,995 @@
1From c55fa726d3e67da11a7ccd16ca367e9094265e4e Mon Sep 17 00:00:00 2001
2From: Adrian Calianu <adrian.calianu@enea.com>
3Date: Mon, 16 Feb 2015 13:56:36 +0100
4Subject: [PATCH 1/1] arm64: boot BE kernels from UEFI
5
6Adds support for booting BE kernels from UEFI. As UEFI is defined to
7be strictly little endian, some workarounds are required to combine a little
8endian EFI stub with a big endian kernel. Also, runtime services need to be
9wrapped so they can be executed in little endian mode.
10
11This patch is the resulting of porting on 3.19 kernel of a patch set
12([RFC PATCH 00/10] arm64: boot BE kernels from UEFI) provided by
13Ard Biesheuvel ard.biesheuvel at linaro.org for 3.17 kernel.
14
15http://lists.infradead.org/pipermail/linux-arm-kernel/2014-July/274208.html
16
17Signed-off-by: Adrian Calianu <adrian.calianu@enea.com>
18---
19 arch/arm64/Kconfig | 10 ++-
20 arch/arm64/include/asm/assembler.h | 18 +++++
21 arch/arm64/include/asm/efi.h | 2 +
22 arch/arm64/kernel/Makefile | 7 +-
23 arch/arm64/kernel/efi-be-call.S | 55 +++++++++++++++
24 arch/arm64/kernel/efi-be-runtime.c | 104 ++++++++++++++++++++++++++++
25 arch/arm64/kernel/efi-entry.S | 43 +++++++++---
26 arch/arm64/kernel/efi-stub.c | 10 +--
27 arch/arm64/kernel/efi.c | 64 ++++++++++-------
28 arch/arm64/kernel/efistub-le/Makefile | 52 ++++++++++++++
29 arch/arm64/kernel/efistub-le/efi-le-entry.S | 12 ++++
30 arch/arm64/kernel/efistub-le/efistub-le.lds | 35 ++++++++++
31 arch/arm64/kernel/efistub-le/le.h | 12 ++++
32 arch/arm64/kernel/efistub-le/strstr.c | 20 ++++++
33 arch/arm64/kernel/head.S | 48 +++++++------
34 arch/arm64/kernel/image.h | 16 ++++-
35 drivers/firmware/efi/efi.c | 26 ++++---
36 drivers/firmware/efi/efivars.c | 2 +-
37 drivers/firmware/efi/libstub/fdt.c | 4 ++
38 19 files changed, 459 insertions(+), 81 deletions(-)
39 create mode 100644 arch/arm64/kernel/efi-be-call.S
40 create mode 100644 arch/arm64/kernel/efi-be-runtime.c
41 create mode 100644 arch/arm64/kernel/efistub-le/Makefile
42 create mode 100644 arch/arm64/kernel/efistub-le/efi-le-entry.S
43 create mode 100644 arch/arm64/kernel/efistub-le/efistub-le.lds
44 create mode 100644 arch/arm64/kernel/efistub-le/le.h
45 create mode 100644 arch/arm64/kernel/efistub-le/strstr.c
46
47diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
48index 3f08727..d35a06c 100644
49--- a/arch/arm64/Kconfig
50+++ b/arch/arm64/Kconfig
51@@ -573,16 +573,20 @@ config CMDLINE_FORCE
52 config EFI_STUB
53 bool
54
55+config EFI_LE_STUB
56+ bool
57+
58 config EFI
59 bool "UEFI runtime support"
60- depends on OF && !CPU_BIG_ENDIAN
61+ depends on OF
62 select LIBFDT
63 select UCS2_STRING
64 select EFI_PARAMS_FROM_FDT
65 select EFI_RUNTIME_WRAPPERS
66- select EFI_STUB
67+ select EFI_STUB if !CPU_BIG_ENDIAN
68+ select EFI_LE_STUB if CPU_BIG_ENDIAN
69 select EFI_ARMSTUB
70- default y
71+ default y if !CPU_BIG_ENDIAN
72 help
73 This option provides support for runtime services provided
74 by UEFI firmware (such as non-volatile variables, realtime
75diff --git a/arch/arm64/include/asm/assembler.h b/arch/arm64/include/asm/assembler.h
76index 5901480..ad3aa92 100644
77--- a/arch/arm64/include/asm/assembler.h
78+++ b/arch/arm64/include/asm/assembler.h
79@@ -155,3 +155,21 @@ lr .req x30 // link register
80 #endif
81 orr \rd, \lbits, \hbits, lsl #32
82 .endm
83+
84+ /*
85+ * Define LE constants
86+ */
87+ .macro le16, x
88+ .byte \x & 0xff
89+ .byte (\x >> 8) & 0xff
90+ .endm
91+
92+ .macro le32, x
93+ le16 \x
94+ le16 \x >> 16
95+ .endm
96+
97+ .macro le64, x
98+ le32 \x
99+ le32 \x >> 32
100+ .endm
101diff --git a/arch/arm64/include/asm/efi.h b/arch/arm64/include/asm/efi.h
102index a34fd3b..44e642b 100644
103--- a/arch/arm64/include/asm/efi.h
104+++ b/arch/arm64/include/asm/efi.h
105@@ -44,4 +44,6 @@ extern void efi_idmap_init(void);
106
107 #define efi_call_early(f, ...) sys_table_arg->boottime->f(__VA_ARGS__)
108
109+extern void efi_be_runtime_setup(void);
110+
111 #endif /* _ASM_EFI_H */
112diff --git a/arch/arm64/kernel/Makefile b/arch/arm64/kernel/Makefile
113index 79bdd3b..1ab3ff4 100644
114--- a/arch/arm64/kernel/Makefile
115+++ b/arch/arm64/kernel/Makefile
116@@ -32,7 +32,12 @@ arm64-obj-$(CONFIG_ARM64_CPU_SUSPEND) += sleep.o suspend.o
117 arm64-obj-$(CONFIG_CPU_IDLE) += cpuidle.o
118 arm64-obj-$(CONFIG_JUMP_LABEL) += jump_label.o
119 arm64-obj-$(CONFIG_KGDB) += kgdb.o
120-arm64-obj-$(CONFIG_EFI) += efi.o efi-stub.o efi-entry.o
121+arm64-efi-obj-y := efi.o
122+arm64-efi-obj-$(CONFIG_EFI_STUB) += efi-stub.o efi-entry.o
123+arm64-efi-obj-$(CONFIG_EFI_LE_STUB) += efistub-le/
124+arm64-efi-obj-$(CONFIG_CPU_BIG_ENDIAN) += efi-be-runtime.o efi-be-call.o
125+arm64-obj-$(CONFIG_EFI) += $(arm64-efi-obj-y)
126+
127 arm64-obj-$(CONFIG_PCI) += pci.o
128 arm64-obj-$(CONFIG_ARMV8_DEPRECATED) += armv8_deprecated.o
129 arm64-obj-$(CONFIG_ACPI) += acpi.o
130diff --git a/arch/arm64/kernel/efi-be-call.S b/arch/arm64/kernel/efi-be-call.S
131new file mode 100644
132index 0000000..b395c8c
133--- /dev/null
134+++ b/arch/arm64/kernel/efi-be-call.S
135@@ -0,0 +1,55 @@
136+
137+#include <linux/linkage.h>
138+
139+ .text
140+ .align 3
141+ENTRY(efi_be_phys_call)
142+ /*
143+ * Entered at physical address with 1:1 mapping enabled.
144+ */
145+ stp x29, x30, [sp, #-96]!
146+ mov x29, sp
147+ str x27, [sp, #16]
148+
149+ ldr x8, =efi_be_phys_call // virt address of this function
150+ adr x9, efi_be_phys_call // phys address of this function
151+ sub x9, x8, x9 // calculate virt to phys offset in x9
152+
153+ /* preserve all inputs */
154+ stp x0, x1, [sp, #32]
155+ stp x2, x3, [sp, #48]
156+ stp x4, x5, [sp, #64]
157+ stp x6, x7, [sp, #80]
158+
159+ /* get phys address of stack */
160+ sub sp, sp, x9
161+
162+ /* switch to LE, disable MMU and D-cache but leave I-cache enabled */
163+ mrs x27, sctlr_el1
164+ bic x8, x27, #1 << 2 // clear SCTLR.C
165+ msr sctlr_el1, x8
166+
167+ bl flush_cache_all
168+
169+ /* restore inputs but rotated by 1 register */
170+ ldp x7, x0, [sp, #32]
171+ ldp x1, x2, [sp, #48]
172+ ldp x3, x4, [sp, #64]
173+ ldp x5, x6, [sp, #80]
174+
175+ bic x8, x27, #1 << 2 // clear SCTLR.C
176+ bic x8, x8, #1 << 0 // clear SCTLR.M
177+ bic x8, x8, #1 << 25 // clear SCTLR.EE
178+ msr sctlr_el1, x8
179+ isb
180+
181+ blr x7
182+
183+ /* switch back to BE and reenable MMU and D-cache */
184+ msr sctlr_el1, x27
185+
186+ mov sp, x29
187+ ldr x27, [sp, #16]
188+ ldp x29, x30, [sp], #96
189+ ret
190+ENDPROC(efi_be_phys_call)
191diff --git a/arch/arm64/kernel/efi-be-runtime.c b/arch/arm64/kernel/efi-be-runtime.c
192new file mode 100644
193index 0000000..28d7406
194--- /dev/null
195+++ b/arch/arm64/kernel/efi-be-runtime.c
196@@ -0,0 +1,104 @@
197+
198+#include <linux/efi.h>
199+#include <linux/spinlock.h>
200+#include <asm/efi.h>
201+#include <asm/neon.h>
202+#include <asm/tlbflush.h>
203+
204+static efi_runtime_services_t *runtime;
205+static efi_status_t (*efi_be_call)(phys_addr_t func, ...);
206+
207+static DEFINE_SPINLOCK(efi_be_rt_lock);
208+
209+static unsigned long efi_be_call_pre(void)
210+{
211+ unsigned long flags;
212+
213+ kernel_neon_begin();
214+ spin_lock_irqsave(&efi_be_rt_lock, flags);
215+ cpu_switch_mm(idmap_pg_dir, &init_mm);
216+ flush_tlb_all();
217+ return flags;
218+}
219+
220+static void efi_be_call_post(unsigned long flags)
221+{
222+ cpu_switch_mm(current, current->active_mm);
223+ flush_tlb_all();
224+ spin_unlock_irqrestore(&efi_be_rt_lock, flags);
225+ kernel_neon_end();
226+}
227+
228+static efi_status_t efi_be_get_variable(efi_char16_t *name,
229+ efi_guid_t *vendor,
230+ u32 *attr,
231+ unsigned long *data_size,
232+ void *data)
233+{
234+ unsigned long flags;
235+ efi_status_t status;
236+
237+ *data_size = cpu_to_le64(*data_size);
238+ flags = efi_be_call_pre();
239+ status = efi_be_call(le64_to_cpu(runtime->get_variable),
240+ virt_to_phys(name), virt_to_phys(vendor),
241+ virt_to_phys(attr), virt_to_phys(data_size),
242+ virt_to_phys(data));
243+ efi_be_call_post(flags);
244+ *attr = le32_to_cpu(*attr);
245+ *data_size = le64_to_cpu(*data_size);
246+ return status;
247+}
248+
249+static efi_status_t efi_be_get_next_variable(unsigned long *name_size,
250+ efi_char16_t *name,
251+ efi_guid_t *vendor)
252+{
253+ unsigned long flags;
254+ efi_status_t status;
255+
256+ *name_size = cpu_to_le64(*name_size);
257+ flags = efi_be_call_pre();
258+ status = efi_be_call(le64_to_cpu(runtime->get_next_variable),
259+ virt_to_phys(name_size), virt_to_phys(name),
260+ virt_to_phys(vendor));
261+ efi_be_call_post(flags);
262+ *name_size = le64_to_cpu(*name_size);
263+ return status;
264+}
265+
266+static efi_status_t efi_be_set_variable(efi_char16_t *name,
267+ efi_guid_t *vendor,
268+ u32 attr,
269+ unsigned long data_size,
270+ void *data)
271+{
272+ unsigned long flags;
273+ efi_status_t status;
274+
275+ flags = efi_be_call_pre();
276+ status = efi_be_call(le64_to_cpu(runtime->set_variable),
277+ virt_to_phys(name), virt_to_phys(vendor),
278+ cpu_to_le32(attr), cpu_to_le64(data_size),
279+ virt_to_phys(data));
280+ efi_be_call_post(flags);
281+ return status;
282+}
283+
284+void efi_be_runtime_setup(void)
285+{
286+ extern u8 efi_be_phys_call[];
287+
288+ runtime = ioremap_cache(le64_to_cpu(efi.systab->runtime),
289+ sizeof(efi_runtime_services_t));
290+ if (!runtime) {
291+ pr_err("Failed to set up BE wrappers for UEFI Runtime Services!\n");
292+ return;
293+ }
294+
295+ efi_be_call = (void *)virt_to_phys(efi_be_phys_call);
296+
297+ efi.get_variable = efi_be_get_variable;
298+ efi.get_next_variable = efi_be_get_next_variable;
299+ efi.set_variable = efi_be_set_variable;
300+}
301diff --git a/arch/arm64/kernel/efi-entry.S b/arch/arm64/kernel/efi-entry.S
302index 8ce9b05..760fbb5 100644
303--- a/arch/arm64/kernel/efi-entry.S
304+++ b/arch/arm64/kernel/efi-entry.S
305@@ -34,7 +34,34 @@ ENTRY(efi_stub_entry)
306 * Create a stack frame to save FP/LR with extra space
307 * for image_addr variable passed to efi_entry().
308 */
309- stp x29, x30, [sp, #-32]!
310+ stp x29, x30, [sp, #-48]!
311+ stp x22, x23, [sp, #32]
312+
313+#ifdef CONFIG_EFI_LE_STUB
314+ adr x4, efi_stub_entry
315+ ldp w8, w9, [x4, #-32]
316+STUB_BE(rev w8, w8 )
317+STUB_BE(rev w9, w9 )
318+ add x8, x4, w8, sxtw // x8: base of Image
319+ add x9, x4, w9, sxtw // x9: offset of linux_banner
320+
321+ ldp x22, x23, [x4, #-24] // x22: size of Image
322+STUB_BE(rev x23, x23 ) // x23: stext offset
323+
324+ /*
325+ * Get a pointer to linux_banner in the outer image and store it
326+ * in this image.
327+ */
328+ adrp x4, le_linux_banner
329+ str x9, [x4, #:lo12:le_linux_banner]
330+#else
331+ adrp x8, _text
332+ add x8, x8, #:lo12:_text // x8: base of Image
333+ adrp x9, _edata
334+ add x9, x9, #:lo12:_edata
335+ sub x22, x9, x8 // x22: size of Image
336+ ldr x23, =stext_offset // x23: stext offset
337+#endif
338
339 /*
340 * Call efi_entry to do the real work.
341@@ -45,8 +72,6 @@ ENTRY(efi_stub_entry)
342 * efi_system_table_t *sys_table,
343 * unsigned long *image_addr) ;
344 */
345- adrp x8, _text
346- add x8, x8, #:lo12:_text
347 add x2, sp, 16
348 str x8, [x2]
349 bl efi_entry
350@@ -61,17 +86,12 @@ ENTRY(efi_stub_entry)
351 */
352 mov x20, x0 // DTB address
353 ldr x0, [sp, #16] // relocated _text address
354- ldr x21, =stext_offset
355- add x21, x0, x21
356+ add x21, x0, x23
357
358 /*
359 * Calculate size of the kernel Image (same for original and copy).
360 */
361- adrp x1, _text
362- add x1, x1, #:lo12:_text
363- adrp x2, _edata
364- add x2, x2, #:lo12:_edata
365- sub x1, x2, x1
366+ mov x1, x22
367
368 /*
369 * Flush the copied Image to the PoC, and ensure it is not shadowed by
370@@ -117,7 +137,8 @@ ENTRY(efi_stub_entry)
371
372 efi_load_fail:
373 mov x0, #EFI_LOAD_ERROR
374- ldp x29, x30, [sp], #32
375+ ldp x22, x23, [sp, #32]
376+ ldp x29, x30, [sp], #48
377 ret
378
379 efi_stub_entry_end:
380diff --git a/arch/arm64/kernel/efi-stub.c b/arch/arm64/kernel/efi-stub.c
381index d27dd98..dd6d6bc 100644
382--- a/arch/arm64/kernel/efi-stub.c
383+++ b/arch/arm64/kernel/efi-stub.c
384@@ -11,7 +11,6 @@
385 */
386 #include <linux/efi.h>
387 #include <asm/efi.h>
388-#include <asm/sections.h>
389
390 efi_status_t handle_kernel_image(efi_system_table_t *sys_table,
391 unsigned long *image_addr,
392@@ -22,22 +21,19 @@ efi_status_t handle_kernel_image(efi_system_table_t *sys_table,
393 efi_loaded_image_t *image)
394 {
395 efi_status_t status;
396- unsigned long kernel_size, kernel_memsize = 0;
397
398 /* Relocate the image, if required. */
399- kernel_size = _edata - _text;
400 if (*image_addr != (dram_base + TEXT_OFFSET)) {
401- kernel_memsize = kernel_size + (_end - _edata);
402- status = efi_low_alloc(sys_table, kernel_memsize + TEXT_OFFSET,
403+ status = efi_low_alloc(sys_table, image->image_size + TEXT_OFFSET,
404 SZ_2M, reserve_addr);
405 if (status != EFI_SUCCESS) {
406 pr_efi_err(sys_table, "Failed to relocate kernel\n");
407 return status;
408 }
409 memcpy((void *)*reserve_addr + TEXT_OFFSET, (void *)*image_addr,
410- kernel_size);
411+ image->image_size);
412 *image_addr = *reserve_addr + TEXT_OFFSET;
413- *reserve_size = kernel_memsize + TEXT_OFFSET;
414+ *reserve_size = image->image_size + TEXT_OFFSET;
415 }
416
417
418diff --git a/arch/arm64/kernel/efi.c b/arch/arm64/kernel/efi.c
419index 4178e9e..133c599 100644
420--- a/arch/arm64/kernel/efi.c
421+++ b/arch/arm64/kernel/efi.c
422@@ -43,7 +43,7 @@ early_param("uefi_debug", uefi_debug_setup);
423
424 static int __init is_normal_ram(efi_memory_desc_t *md)
425 {
426- if (md->attribute & EFI_MEMORY_WB)
427+ if (le64_to_cpu(md->attribute) & EFI_MEMORY_WB)
428 return 1;
429 return 0;
430 }
431@@ -59,10 +59,10 @@ static void __init efi_setup_idmap(void)
432
433 /* map runtime io spaces */
434 for_each_efi_memory_desc(&memmap, md) {
435- if (!(md->attribute & EFI_MEMORY_RUNTIME) || is_normal_ram(md))
436+ if (!(le64_to_cpu(md->attribute) & EFI_MEMORY_RUNTIME) || is_normal_ram(md))
437 continue;
438- paddr = md->phys_addr;
439- npages = md->num_pages;
440+ paddr = le64_to_cpu(md->phys_addr);
441+ npages = le64_to_cpu(md->num_pages);
442 memrange_efi_to_native(&paddr, &npages);
443 size = npages << PAGE_SHIFT;
444 create_id_mapping(paddr, size, 1);
445@@ -88,29 +88,29 @@ static int __init uefi_init(void)
446 /*
447 * Verify the EFI Table
448 */
449- if (efi.systab->hdr.signature != EFI_SYSTEM_TABLE_SIGNATURE) {
450+ if (le64_to_cpu(efi.systab->hdr.signature) != EFI_SYSTEM_TABLE_SIGNATURE) {
451 pr_err("System table signature incorrect\n");
452 retval = -EINVAL;
453 goto out;
454 }
455- if ((efi.systab->hdr.revision >> 16) < 2)
456+ if ((le32_to_cpu(efi.systab->hdr.revision) >> 16) < 2)
457 pr_warn("Warning: EFI system table version %d.%02d, expected 2.00 or greater\n",
458 efi.systab->hdr.revision >> 16,
459 efi.systab->hdr.revision & 0xffff);
460
461 /* Show what we know for posterity */
462- c16 = early_memremap(efi.systab->fw_vendor,
463+ c16 = early_memremap(le64_to_cpu(efi.systab->fw_vendor),
464 sizeof(vendor));
465 if (c16) {
466 for (i = 0; i < (int) sizeof(vendor) - 1 && *c16; ++i)
467- vendor[i] = c16[i];
468+ vendor[i] = le16_to_cpu(c16[i]);
469 vendor[i] = '\0';
470 early_memunmap(c16, sizeof(vendor));
471 }
472
473 pr_info("EFI v%u.%.02u by %s\n",
474- efi.systab->hdr.revision >> 16,
475- efi.systab->hdr.revision & 0xffff, vendor);
476+ le32_to_cpu(efi.systab->hdr.revision) >> 16,
477+ le32_to_cpu(efi.systab->hdr.revision) & 0xffff, vendor);
478
479 retval = efi_config_init(NULL);
480
481@@ -124,7 +124,7 @@ out:
482 */
483 static __init int is_reserve_region(efi_memory_desc_t *md)
484 {
485- switch (md->type) {
486+ switch (le32_to_cpu(md->type)) {
487 case EFI_LOADER_CODE:
488 case EFI_LOADER_DATA:
489 case EFI_BOOT_SERVICES_CODE:
490@@ -146,8 +146,9 @@ static __init void reserve_regions(void)
491 pr_info("Processing EFI memory map:\n");
492
493 for_each_efi_memory_desc(&memmap, md) {
494- paddr = md->phys_addr;
495- npages = md->num_pages;
496+ u32 md_type = le32_to_cpu(md->type);
497+ paddr = le64_to_cpu(md->phys_addr);
498+ npages = le64_to_cpu(md->num_pages);
499
500 if (uefi_debug) {
501 char buf[64];
502@@ -164,8 +165,8 @@ static __init void reserve_regions(void)
503 early_init_dt_add_memory_arch(paddr, size);
504
505 if (is_reserve_region(md) ||
506- md->type == EFI_BOOT_SERVICES_CODE ||
507- md->type == EFI_BOOT_SERVICES_DATA) {
508+ md_type == EFI_BOOT_SERVICES_CODE ||
509+ md_type == EFI_BOOT_SERVICES_DATA) {
510 memblock_reserve(paddr, size);
511 if (uefi_debug)
512 pr_cont("*");
513@@ -246,17 +247,17 @@ static void __init free_boot_services(void)
514 */
515 if (free_start) {
516 /* adjust free_end then free region */
517- if (free_end > md->phys_addr)
518+ if (free_end > le64_to_cpu(md->phys_addr))
519 free_end -= PAGE_SIZE;
520 total_freed += free_region(free_start, free_end);
521 free_start = 0;
522 }
523- keep_end = md->phys_addr + (md->num_pages << EFI_PAGE_SHIFT);
524+ keep_end = le64_to_cpu(md->phys_addr) + (le64_to_cpu(md->num_pages) << EFI_PAGE_SHIFT);
525 continue;
526 }
527
528- if (md->type != EFI_BOOT_SERVICES_CODE &&
529- md->type != EFI_BOOT_SERVICES_DATA) {
530+ if (le32_to_cpu(md->type) != EFI_BOOT_SERVICES_CODE &&
531+ le32_to_cpu(md->type) != EFI_BOOT_SERVICES_DATA) {
532 /* no need to free this region */
533 continue;
534 }
535@@ -264,8 +265,8 @@ static void __init free_boot_services(void)
536 /*
537 * We want to free memory from this region.
538 */
539- paddr = md->phys_addr;
540- npages = md->num_pages;
541+ paddr = le64_to_cpu(md->phys_addr);
542+ npages = le64_to_cpu(md->num_pages);
543 memrange_efi_to_native(&paddr, &npages);
544 size = npages << PAGE_SHIFT;
545
546@@ -333,8 +334,8 @@ static int __init remap_region(efi_memory_desc_t *md, void **new)
547 {
548 u64 paddr, vaddr, npages, size;
549
550- paddr = md->phys_addr;
551- npages = md->num_pages;
552+ paddr = le64_to_cpu(md->phys_addr);
553+ npages = le64_to_cpu(md->num_pages);
554 memrange_efi_to_native(&paddr, &npages);
555 size = npages << PAGE_SHIFT;
556
557@@ -350,7 +351,7 @@ static int __init remap_region(efi_memory_desc_t *md, void **new)
558 }
559
560 /* adjust for any rounding when EFI and system pagesize differs */
561- md->virt_addr = vaddr + (md->phys_addr - paddr);
562+ md->virt_addr = vaddr + (le64_to_cpu(md->phys_addr) - paddr);
563
564 if (uefi_debug)
565 pr_info(" EFI remap 0x%012llx => %p\n",
566@@ -395,6 +396,21 @@ static int __init arm64_enter_virtual_mode(void)
567
568 efi.memmap = &memmap;
569
570+ if (IS_ENABLED(CONFIG_CPU_BIG_ENDIAN)) {
571+ efi.systab = ioremap_cache(efi_system_table,
572+ sizeof(efi_system_table_t));
573+ if (!efi.systab) {
574+ pr_err("Failed to remap EFI system table!\n");
575+ return -1;
576+ }
577+ free_boot_services();
578+ efi_be_runtime_setup();
579+
580+ set_bit(EFI_SYSTEM_TABLES, &efi.flags);
581+ set_bit(EFI_RUNTIME_SERVICES, &efi.flags);
582+ return 0;
583+ }
584+
585 /* Map the runtime regions */
586 virtmap = kmalloc(mapsize, GFP_KERNEL);
587 if (!virtmap) {
588diff --git a/arch/arm64/kernel/efistub-le/Makefile b/arch/arm64/kernel/efistub-le/Makefile
589new file mode 100644
590index 0000000..8a1c2a8
591--- /dev/null
592+++ b/arch/arm64/kernel/efistub-le/Makefile
593@@ -0,0 +1,52 @@
594+
595+#
596+# Build a little endian EFI stub and wrap it into a single .o
597+#
598+
599+# the LE objects making up the LE efi stub
600+le-objs := efi-entry.o efi-stub.o strstr.o cache.o \
601+ lib-memchr.o lib-memcmp.o lib-memcpy.o lib-memmove.o \
602+ lib-memset.o lib-strchr.o lib-strlen.o lib-strncmp.o \
603+ fdt-fdt.o fdt-fdt_ro.o fdt-fdt_rw.o fdt-fdt_sw.o \
604+ fdt-fdt_wip.o fdt-fdt_empty_tree.o \
605+ libstub-fdt.o libstub-arm-stub.o libstub-efi-stub-helper.o
606+
607+extra-y := efi-le-stub.bin efi-le-stub.elf $(le-objs)
608+
609+KBUILD_CFLAGS := $(subst -pg,,$(KBUILD_CFLAGS)) -fno-stack-protector \
610+ -mlittle-endian -I$(srctree)/scripts/dtc/libfdt
611+
612+le-targets := $(addprefix $(obj)/, $(le-objs))
613+$(le-targets): KBUILD_AFLAGS += -mlittle-endian -include $(srctree)/$(src)/le.h
614+
615+$(obj)/efi-entry.o: $(obj)/../efi-entry.S FORCE
616+ $(call if_changed_dep,as_o_S)
617+
618+CFLAGS_efi-stub.o += -DTEXT_OFFSET=$(TEXT_OFFSET)
619+$(obj)/efi-stub.o: $(obj)/../efi-stub.c FORCE
620+ $(call if_changed_dep,cc_o_c)
621+
622+$(obj)/cache.o: $(src)/../../mm/cache.S FORCE
623+ $(call if_changed_dep,as_o_S)
624+
625+$(obj)/lib-%.o: $(src)/../../lib/%.S FORCE
626+ $(call if_changed_dep,as_o_S)
627+
628+$(obj)/fdt-%.o: $(srctree)/lib/%.c FORCE
629+ $(call if_changed_dep,cc_o_c)
630+
631+$(obj)/libstub-%.o: $(srctree)/drivers/firmware/efi/libstub/%.c FORCE
632+ $(call if_changed_dep,cc_o_c)
633+
634+$(obj)/efi-le-stub.elf: LDFLAGS=-EL -Map $@.map -T
635+$(obj)/efi-le-stub.elf: $(src)/efistub-le.lds $(le-targets) FORCE
636+ $(call if_changed,ld)
637+
638+$(obj)/efi-le-stub.bin: OBJCOPYFLAGS=-O binary
639+$(obj)/efi-le-stub.bin: $(obj)/efi-le-stub.elf FORCE
640+ $(call if_changed,objcopy)
641+
642+# the BE object containing the entire LE stub
643+obj-y := efi-le-entry.o
644+
645+$(obj)/efi-le-entry.o: $(obj)/efi-le-stub.bin
646diff --git a/arch/arm64/kernel/efistub-le/efi-le-entry.S b/arch/arm64/kernel/efistub-le/efi-le-entry.S
647new file mode 100644
648index 0000000..755364c
649--- /dev/null
650+++ b/arch/arm64/kernel/efistub-le/efi-le-entry.S
651@@ -0,0 +1,12 @@
652+#include <linux/linkage.h>
653+
654+ .text
655+ .align 12
656+ .long _text - efi_stub_entry
657+ .long linux_banner - efi_stub_entry
658+ .quad _kernel_size_le
659+ .quad stext_offset
660+ .quad 0
661+ENTRY(efi_stub_entry)
662+ .incbin "arch/arm64/kernel/efistub-le/efi-le-stub.bin"
663+ENDPROC(efi_stub_entry)
664diff --git a/arch/arm64/kernel/efistub-le/efistub-le.lds b/arch/arm64/kernel/efistub-le/efistub-le.lds
665new file mode 100644
666index 0000000..f64d542
667--- /dev/null
668+++ b/arch/arm64/kernel/efistub-le/efistub-le.lds
669@@ -0,0 +1,35 @@
670+
671+ENTRY(efi_stub_entry)
672+
673+SECTIONS {
674+ /*
675+ * The inner and outer alignment of this chunk of code need to be the
676+ * same so that PC relative references using adrp/add or adrp/ldr pairs
677+ * will work correctly.
678+ * Skip 32 bytes here, so we can put the binary blob at an offset of
679+ * 4k + 0x20 in the outer image, and use the gap to share constants
680+ * emitted by the outer linker but required in the stub.
681+ */
682+ .text 0x20 : {
683+ arch/arm64/kernel/efistub-le/efi-entry.o(.init.text)
684+ *(.init.text)
685+ *(.text)
686+ *(.text*)
687+ }
688+ .rodata : {
689+ . = ALIGN(16);
690+ *(.rodata)
691+ *(.rodata*)
692+ *(.init.rodata)
693+ }
694+ .data : {
695+ . = ALIGN(16);
696+ *(.data)
697+ *(.data*)
698+ le_linux_banner = .;
699+ . += 8;
700+ }
701+ /DISCARD/ : {
702+ *(__ex_table)
703+ }
704+}
705diff --git a/arch/arm64/kernel/efistub-le/le.h b/arch/arm64/kernel/efistub-le/le.h
706new file mode 100644
707index 0000000..a9f6dfc
708--- /dev/null
709+++ b/arch/arm64/kernel/efistub-le/le.h
710@@ -0,0 +1,12 @@
711+
712+/*
713+ * This is a bit of a hack, but it is necessary to correctly compile .S files
714+ * that contain CPU_LE()/CPU_BE() statements, as these are defined to depend on
715+ * CONFIG_ symbols and not on the endianness of the compiler.
716+ */
717+#ifdef CONFIG_CPU_BIG_ENDIAN
718+#define STUB_BE(code...) code
719+#else
720+#define STUB_BE(code...)
721+#endif
722+#undef CONFIG_CPU_BIG_ENDIAN
723diff --git a/arch/arm64/kernel/efistub-le/strstr.c b/arch/arm64/kernel/efistub-le/strstr.c
724new file mode 100644
725index 0000000..bd16094
726--- /dev/null
727+++ b/arch/arm64/kernel/efistub-le/strstr.c
728@@ -0,0 +1,20 @@
729+
730+#include <linux/types.h>
731+#include <linux/string.h>
732+
733+char *strstr(const char *s1, const char *s2)
734+{
735+ size_t l1, l2;
736+
737+ l2 = strlen(s2);
738+ if (!l2)
739+ return (char *)s1;
740+ l1 = strlen(s1);
741+ while (l1 >= l2) {
742+ l1--;
743+ if (!memcmp(s1, s2, l2))
744+ return (char *)s1;
745+ s1++;
746+ }
747+ return NULL;
748+}
749diff --git a/arch/arm64/kernel/head.S b/arch/arm64/kernel/head.S
750index 8ce88e0..8b1eba5 100644
751--- a/arch/arm64/kernel/head.S
752+++ b/arch/arm64/kernel/head.S
753@@ -126,7 +126,10 @@ efi_head:
754 .byte 0x4d
755 .byte 0x64
756 #ifdef CONFIG_EFI
757- .long pe_header - efi_head // Offset to the PE header.
758+ .byte pe_header - efi_head // Offset to the PE header.
759+ .byte 0
760+ .byte 0
761+ .byte 0
762 #else
763 .word 0 // reserved
764 #endif
765@@ -139,30 +142,31 @@ pe_header:
766 .ascii "PE"
767 .short 0
768 coff_header:
769- .short 0xaa64 // AArch64
770- .short 2 // nr_sections
771+ le16 0xaa64 // AArch64
772+ le16 2 // nr_sections
773 .long 0 // TimeDateStamp
774 .long 0 // PointerToSymbolTable
775- .long 1 // NumberOfSymbols
776- .short section_table - optional_header // SizeOfOptionalHeader
777- .short 0x206 // Characteristics.
778+ le32 1 // NumberOfSymbols
779+ .byte section_table - optional_header // SizeOfOptionalHeader
780+ .byte 0
781+ le16 0x206 // Characteristics.
782 // IMAGE_FILE_DEBUG_STRIPPED |
783 // IMAGE_FILE_EXECUTABLE_IMAGE |
784 // IMAGE_FILE_LINE_NUMS_STRIPPED
785 optional_header:
786- .short 0x20b // PE32+ format
787+ le16 0x20b // PE32+ format
788 .byte 0x02 // MajorLinkerVersion
789 .byte 0x14 // MinorLinkerVersion
790- .long _end - stext // SizeOfCode
791+ .long _efi_code_virtsize_le // SizeOfCode
792 .long 0 // SizeOfInitializedData
793 .long 0 // SizeOfUninitializedData
794- .long efi_stub_entry - efi_head // AddressOfEntryPoint
795- .long stext_offset // BaseOfCode
796+ .long _efi_entry_point_le // AddressOfEntryPoint
797+ .long _efi_stext_offset_le // BaseOfCode
798
799 extra_header_fields:
800 .quad 0 // ImageBase
801- .long 0x1000 // SectionAlignment
802- .long PECOFF_FILE_ALIGNMENT // FileAlignment
803+ le32 0x1000 // SectionAlignment
804+ le32 0x200 // FileAlignment
805 .short 0 // MajorOperatingSystemVersion
806 .short 0 // MinorOperatingSystemVersion
807 .short 0 // MajorImageVersion
808@@ -171,19 +175,19 @@ extra_header_fields:
809 .short 0 // MinorSubsystemVersion
810 .long 0 // Win32VersionValue
811
812- .long _end - efi_head // SizeOfImage
813+ .long _efi_image_size_le // SizeOfImage
814
815 // Everything before the kernel image is considered part of the header
816- .long stext_offset // SizeOfHeaders
817+ .long _efi_stext_offset_le // SizeOfHeaders
818 .long 0 // CheckSum
819- .short 0xa // Subsystem (EFI application)
820+ le16 0xa // Subsystem (EFI application)
821 .short 0 // DllCharacteristics
822 .quad 0 // SizeOfStackReserve
823 .quad 0 // SizeOfStackCommit
824 .quad 0 // SizeOfHeapReserve
825 .quad 0 // SizeOfHeapCommit
826 .long 0 // LoaderFlags
827- .long 0x6 // NumberOfRvaAndSizes
828+ le32 0x6 // NumberOfRvaAndSizes
829
830 .quad 0 // ExportTable
831 .quad 0 // ImportTable
832@@ -211,23 +215,23 @@ section_table:
833 .long 0 // PointerToLineNumbers
834 .short 0 // NumberOfRelocations
835 .short 0 // NumberOfLineNumbers
836- .long 0x42100040 // Characteristics (section flags)
837+ le32 0x42100040 // Characteristics (section flags)
838
839
840 .ascii ".text"
841 .byte 0
842 .byte 0
843 .byte 0 // end of 0 padding of section name
844- .long _end - stext // VirtualSize
845- .long stext_offset // VirtualAddress
846- .long _edata - stext // SizeOfRawData
847- .long stext_offset // PointerToRawData
848+ .long _efi_code_virtsize_le // VirtualSize
849+ .long _efi_stext_offset_le // VirtualAddress
850+ .long _efi_code_rawsize_le // SizeOfRawData
851+ .long _efi_stext_offset_le // PointerToRawData
852
853 .long 0 // PointerToRelocations (0 for executables)
854 .long 0 // PointerToLineNumbers (0 for executables)
855 .short 0 // NumberOfRelocations (0 for executables)
856 .short 0 // NumberOfLineNumbers (0 for executables)
857- .long 0xe0500020 // Characteristics (section flags)
858+ le32 0xe0500020 // Characteristics (section flags)
859
860 /*
861 * EFI will load stext onwards at the 4k section alignment
862diff --git a/arch/arm64/kernel/image.h b/arch/arm64/kernel/image.h
863index 8fae075..d08ce56 100644
864--- a/arch/arm64/kernel/image.h
865+++ b/arch/arm64/kernel/image.h
866@@ -37,8 +37,10 @@
867 (((data) & 0x0000ff0000000000) >> 24) | \
868 (((data) & 0x00ff000000000000) >> 40) | \
869 (((data) & 0xff00000000000000) >> 56))
870+#define DATA_LE32(data) (DATA_LE64(data) >> 32)
871 #else
872 #define DATA_LE64(data) ((data) & 0xffffffffffffffff)
873+#define DATA_LE32(data) ((data) & 0xffffffff)
874 #endif
875
876 #ifdef CONFIG_CPU_BIG_ENDIAN
877@@ -57,6 +59,18 @@
878 #define HEAD_SYMBOLS \
879 _kernel_size_le = DATA_LE64(_end - _text); \
880 _kernel_offset_le = DATA_LE64(TEXT_OFFSET); \
881- _kernel_flags_le = DATA_LE64(__HEAD_FLAGS);
882+ _kernel_flags_le = DATA_LE64(__HEAD_FLAGS); \
883+ EFI_HEAD_SYMBOLS
884+
885+#ifdef CONFIG_EFI
886+#define EFI_HEAD_SYMBOLS \
887+ _efi_stext_offset_le = DATA_LE32(stext_offset); \
888+ _efi_code_virtsize_le = DATA_LE32(_end - _text - stext_offset); \
889+ _efi_code_rawsize_le = DATA_LE32(_edata - _text - stext_offset); \
890+ _efi_image_size_le = DATA_LE32(_end - _text); \
891+ _efi_entry_point_le = DATA_LE32(efi_stub_entry - _text);
892+#else
893+#define EFI_HEAD_SYMBOLS
894+#endif
895
896 #endif /* __ASM_IMAGE_H */
897diff --git a/drivers/firmware/efi/efi.c b/drivers/firmware/efi/efi.c
898index 9035c1b..4e98daa 100644
899--- a/drivers/firmware/efi/efi.c
900+++ b/drivers/firmware/efi/efi.c
901@@ -296,18 +296,23 @@ static __init int match_config_table(efi_guid_t *guid,
902 int __init efi_config_init(efi_config_table_type_t *arch_tables)
903 {
904 void *config_tables, *tablep;
905- int i, sz;
906+ unsigned long __tables;
907+ int i, sz, nr_tables;
908
909- if (efi_enabled(EFI_64BIT))
910+ if (efi_enabled(EFI_64BIT)) {
911 sz = sizeof(efi_config_table_64_t);
912- else
913+ nr_tables = le64_to_cpu((__force __le64)efi.systab->nr_tables);
914+ __tables = le64_to_cpu((__force __le64)efi.systab->tables);
915+ } else {
916 sz = sizeof(efi_config_table_32_t);
917+ nr_tables = le32_to_cpu((__force __le32)efi.systab->nr_tables);
918+ __tables = le32_to_cpu((__force __le32)efi.systab->tables);
919+ }
920
921 /*
922 * Let's see what config tables the firmware passed to us.
923 */
924- config_tables = early_memremap(efi.systab->tables,
925- efi.systab->nr_tables * sz);
926+ config_tables = early_memremap(__tables, nr_tables * sz);
927 if (config_tables == NULL) {
928 pr_err("Could not map Configuration table!\n");
929 return -ENOMEM;
930@@ -315,21 +320,20 @@ int __init efi_config_init(efi_config_table_type_t *arch_tables)
931
932 tablep = config_tables;
933 pr_info("");
934- for (i = 0; i < efi.systab->nr_tables; i++) {
935+ for (i = 0; i < nr_tables; i++) {
936 efi_guid_t guid;
937 unsigned long table;
938
939 if (efi_enabled(EFI_64BIT)) {
940 u64 table64;
941 guid = ((efi_config_table_64_t *)tablep)->guid;
942- table64 = ((efi_config_table_64_t *)tablep)->table;
943- table = table64;
944+ table = table64 = le64_to_cpu((__force __le64)
945+ ((efi_config_table_64_t *)tablep)->table);
946 #ifndef CONFIG_64BIT
947 if (table64 >> 32) {
948 pr_cont("\n");
949 pr_err("Table located above 4GB, disabling EFI.\n");
950- early_memunmap(config_tables,
951- efi.systab->nr_tables * sz);
952+ early_memunmap(config_tables, nr_tables * sz);
953 return -EINVAL;
954 }
955 #endif
956@@ -344,7 +348,7 @@ int __init efi_config_init(efi_config_table_type_t *arch_tables)
957 tablep += sz;
958 }
959 pr_cont("\n");
960- early_memunmap(config_tables, efi.systab->nr_tables * sz);
961+ early_memunmap(config_tables, nr_tables * sz);
962
963 set_bit(EFI_CONFIG_TABLES, &efi.flags);
964
965diff --git a/drivers/firmware/efi/efivars.c b/drivers/firmware/efi/efivars.c
966index f256ecd..2b1c8be 100644
967--- a/drivers/firmware/efi/efivars.c
968+++ b/drivers/firmware/efi/efivars.c
969@@ -563,7 +563,7 @@ efivar_create_sysfs_entry(struct efivar_entry *new_var)
970 /* Convert Unicode to normal chars (assume top bits are 0),
971 ala UTF-8 */
972 for (i=0; i < (int)(variable_name_size / sizeof(efi_char16_t)); i++) {
973- short_name[i] = variable_name[i] & 0xFF;
974+ short_name[i] = le16_to_cpu((__force __le16)variable_name[i]);
975 }
976 /* This is ugly, but necessary to separate one vendor's
977 private variables from another's. */
978diff --git a/drivers/firmware/efi/libstub/fdt.c b/drivers/firmware/efi/libstub/fdt.c
979index c846a96..f0f9d54 100644
980--- a/drivers/firmware/efi/libstub/fdt.c
981+++ b/drivers/firmware/efi/libstub/fdt.c
982@@ -22,6 +22,10 @@ efi_status_t update_fdt(efi_system_table_t *sys_table, void *orig_fdt,
983 unsigned long map_size, unsigned long desc_size,
984 u32 desc_ver)
985 {
986+#ifdef CONFIG_EFI_LE_STUB
987+ extern char const *le_linux_banner;
988+ char const *linux_banner = le_linux_banner;
989+#endif
990 int node, prev, num_rsv;
991 int status;
992 u32 fdt_val32;
993--
9941.9.1
995