diff options
Diffstat (limited to 'meta-seattle/recipes-kernel/linux/files/01-arm64-boot-BE-kernels-from-UEFI.patch')
-rw-r--r-- | meta-seattle/recipes-kernel/linux/files/01-arm64-boot-BE-kernels-from-UEFI.patch | 999 |
1 files changed, 0 insertions, 999 deletions
diff --git a/meta-seattle/recipes-kernel/linux/files/01-arm64-boot-BE-kernels-from-UEFI.patch b/meta-seattle/recipes-kernel/linux/files/01-arm64-boot-BE-kernels-from-UEFI.patch deleted file mode 100644 index 35b25249..00000000 --- a/meta-seattle/recipes-kernel/linux/files/01-arm64-boot-BE-kernels-from-UEFI.patch +++ /dev/null @@ -1,999 +0,0 @@ -From c55fa726d3e67da11a7ccd16ca367e9094265e4e Mon Sep 17 00:00:00 2001 -From: Adrian Calianu <adrian.calianu@enea.com> -Date: Mon, 16 Feb 2015 13:56:36 +0100 -Subject: [PATCH 1/1] arm64: boot BE kernels from UEFI - -Adds support for booting BE kernels from UEFI. As UEFI is defined to -be strictly little endian, some workarounds are required to combine a little -endian EFI stub with a big endian kernel. Also, runtime services need to be -wrapped so they can be executed in little endian mode. - -Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org> - -This patch is the resulting of porting on 3.19 kernel of a patch set -([RFC PATCH 00/10] arm64: boot BE kernels from UEFI) provided by -Ard Biesheuvel ard.biesheuvel at linaro.org for 3.17 kernel. - -http://lists.infradead.org/pipermail/linux-arm-kernel/2014-July/274208.html - -Upstream-Status: Pending - -Signed-off-by: Adrian Calianu <adrian.calianu@enea.com> ---- - arch/arm64/Kconfig | 10 ++- - arch/arm64/include/asm/assembler.h | 18 +++++ - arch/arm64/include/asm/efi.h | 2 + - arch/arm64/kernel/Makefile | 7 +- - arch/arm64/kernel/efi-be-call.S | 55 +++++++++++++++ - arch/arm64/kernel/efi-be-runtime.c | 104 ++++++++++++++++++++++++++++ - arch/arm64/kernel/efi-entry.S | 43 +++++++++--- - arch/arm64/kernel/efi-stub.c | 10 +-- - arch/arm64/kernel/efi.c | 64 ++++++++++------- - arch/arm64/kernel/efistub-le/Makefile | 52 ++++++++++++++ - arch/arm64/kernel/efistub-le/efi-le-entry.S | 12 ++++ - arch/arm64/kernel/efistub-le/efistub-le.lds | 35 ++++++++++ - arch/arm64/kernel/efistub-le/le.h | 12 ++++ - arch/arm64/kernel/efistub-le/strstr.c | 20 ++++++ - arch/arm64/kernel/head.S | 48 +++++++------ - arch/arm64/kernel/image.h | 16 ++++- - drivers/firmware/efi/efi.c | 26 ++++--- - drivers/firmware/efi/efivars.c | 2 +- - drivers/firmware/efi/libstub/fdt.c | 4 ++ - 19 files changed, 459 insertions(+), 81 deletions(-) - create mode 100644 arch/arm64/kernel/efi-be-call.S - create mode 100644 arch/arm64/kernel/efi-be-runtime.c - create mode 100644 arch/arm64/kernel/efistub-le/Makefile - create mode 100644 arch/arm64/kernel/efistub-le/efi-le-entry.S - create mode 100644 arch/arm64/kernel/efistub-le/efistub-le.lds - create mode 100644 arch/arm64/kernel/efistub-le/le.h - create mode 100644 arch/arm64/kernel/efistub-le/strstr.c - -diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig -index 3f08727..d35a06c 100644 ---- a/arch/arm64/Kconfig -+++ b/arch/arm64/Kconfig -@@ -573,16 +573,20 @@ config CMDLINE_FORCE - config EFI_STUB - bool - -+config EFI_LE_STUB -+ bool -+ - config EFI - bool "UEFI runtime support" -- depends on OF && !CPU_BIG_ENDIAN -+ depends on OF - select LIBFDT - select UCS2_STRING - select EFI_PARAMS_FROM_FDT - select EFI_RUNTIME_WRAPPERS -- select EFI_STUB -+ select EFI_STUB if !CPU_BIG_ENDIAN -+ select EFI_LE_STUB if CPU_BIG_ENDIAN - select EFI_ARMSTUB -- default y -+ default y if !CPU_BIG_ENDIAN - help - This option provides support for runtime services provided - by UEFI firmware (such as non-volatile variables, realtime -diff --git a/arch/arm64/include/asm/assembler.h b/arch/arm64/include/asm/assembler.h -index 5901480..ad3aa92 100644 ---- a/arch/arm64/include/asm/assembler.h -+++ b/arch/arm64/include/asm/assembler.h -@@ -155,3 +155,21 @@ lr .req x30 // link register - #endif - orr \rd, \lbits, \hbits, lsl #32 - .endm -+ -+ /* -+ * Define LE constants -+ */ -+ .macro le16, x -+ .byte \x & 0xff -+ .byte (\x >> 8) & 0xff -+ .endm -+ -+ .macro le32, x -+ le16 \x -+ le16 \x >> 16 -+ .endm -+ -+ .macro le64, x -+ le32 \x -+ le32 \x >> 32 -+ .endm -diff --git a/arch/arm64/include/asm/efi.h b/arch/arm64/include/asm/efi.h -index a34fd3b..44e642b 100644 ---- a/arch/arm64/include/asm/efi.h -+++ b/arch/arm64/include/asm/efi.h -@@ -44,4 +44,6 @@ extern void efi_idmap_init(void); - - #define efi_call_early(f, ...) sys_table_arg->boottime->f(__VA_ARGS__) - -+extern void efi_be_runtime_setup(void); -+ - #endif /* _ASM_EFI_H */ -diff --git a/arch/arm64/kernel/Makefile b/arch/arm64/kernel/Makefile -index 79bdd3b..1ab3ff4 100644 ---- a/arch/arm64/kernel/Makefile -+++ b/arch/arm64/kernel/Makefile -@@ -32,7 +32,12 @@ arm64-obj-$(CONFIG_ARM64_CPU_SUSPEND) += sleep.o suspend.o - arm64-obj-$(CONFIG_CPU_IDLE) += cpuidle.o - arm64-obj-$(CONFIG_JUMP_LABEL) += jump_label.o - arm64-obj-$(CONFIG_KGDB) += kgdb.o --arm64-obj-$(CONFIG_EFI) += efi.o efi-stub.o efi-entry.o -+arm64-efi-obj-y := efi.o -+arm64-efi-obj-$(CONFIG_EFI_STUB) += efi-stub.o efi-entry.o -+arm64-efi-obj-$(CONFIG_EFI_LE_STUB) += efistub-le/ -+arm64-efi-obj-$(CONFIG_CPU_BIG_ENDIAN) += efi-be-runtime.o efi-be-call.o -+arm64-obj-$(CONFIG_EFI) += $(arm64-efi-obj-y) -+ - arm64-obj-$(CONFIG_PCI) += pci.o - arm64-obj-$(CONFIG_ARMV8_DEPRECATED) += armv8_deprecated.o - arm64-obj-$(CONFIG_ACPI) += acpi.o -diff --git a/arch/arm64/kernel/efi-be-call.S b/arch/arm64/kernel/efi-be-call.S -new file mode 100644 -index 0000000..b395c8c ---- /dev/null -+++ b/arch/arm64/kernel/efi-be-call.S -@@ -0,0 +1,55 @@ -+ -+#include <linux/linkage.h> -+ -+ .text -+ .align 3 -+ENTRY(efi_be_phys_call) -+ /* -+ * Entered at physical address with 1:1 mapping enabled. -+ */ -+ stp x29, x30, [sp, #-96]! -+ mov x29, sp -+ str x27, [sp, #16] -+ -+ ldr x8, =efi_be_phys_call // virt address of this function -+ adr x9, efi_be_phys_call // phys address of this function -+ sub x9, x8, x9 // calculate virt to phys offset in x9 -+ -+ /* preserve all inputs */ -+ stp x0, x1, [sp, #32] -+ stp x2, x3, [sp, #48] -+ stp x4, x5, [sp, #64] -+ stp x6, x7, [sp, #80] -+ -+ /* get phys address of stack */ -+ sub sp, sp, x9 -+ -+ /* switch to LE, disable MMU and D-cache but leave I-cache enabled */ -+ mrs x27, sctlr_el1 -+ bic x8, x27, #1 << 2 // clear SCTLR.C -+ msr sctlr_el1, x8 -+ -+ bl flush_cache_all -+ -+ /* restore inputs but rotated by 1 register */ -+ ldp x7, x0, [sp, #32] -+ ldp x1, x2, [sp, #48] -+ ldp x3, x4, [sp, #64] -+ ldp x5, x6, [sp, #80] -+ -+ bic x8, x27, #1 << 2 // clear SCTLR.C -+ bic x8, x8, #1 << 0 // clear SCTLR.M -+ bic x8, x8, #1 << 25 // clear SCTLR.EE -+ msr sctlr_el1, x8 -+ isb -+ -+ blr x7 -+ -+ /* switch back to BE and reenable MMU and D-cache */ -+ msr sctlr_el1, x27 -+ -+ mov sp, x29 -+ ldr x27, [sp, #16] -+ ldp x29, x30, [sp], #96 -+ ret -+ENDPROC(efi_be_phys_call) -diff --git a/arch/arm64/kernel/efi-be-runtime.c b/arch/arm64/kernel/efi-be-runtime.c -new file mode 100644 -index 0000000..28d7406 ---- /dev/null -+++ b/arch/arm64/kernel/efi-be-runtime.c -@@ -0,0 +1,104 @@ -+ -+#include <linux/efi.h> -+#include <linux/spinlock.h> -+#include <asm/efi.h> -+#include <asm/neon.h> -+#include <asm/tlbflush.h> -+ -+static efi_runtime_services_t *runtime; -+static efi_status_t (*efi_be_call)(phys_addr_t func, ...); -+ -+static DEFINE_SPINLOCK(efi_be_rt_lock); -+ -+static unsigned long efi_be_call_pre(void) -+{ -+ unsigned long flags; -+ -+ kernel_neon_begin(); -+ spin_lock_irqsave(&efi_be_rt_lock, flags); -+ cpu_switch_mm(idmap_pg_dir, &init_mm); -+ flush_tlb_all(); -+ return flags; -+} -+ -+static void efi_be_call_post(unsigned long flags) -+{ -+ cpu_switch_mm(current, current->active_mm); -+ flush_tlb_all(); -+ spin_unlock_irqrestore(&efi_be_rt_lock, flags); -+ kernel_neon_end(); -+} -+ -+static efi_status_t efi_be_get_variable(efi_char16_t *name, -+ efi_guid_t *vendor, -+ u32 *attr, -+ unsigned long *data_size, -+ void *data) -+{ -+ unsigned long flags; -+ efi_status_t status; -+ -+ *data_size = cpu_to_le64(*data_size); -+ flags = efi_be_call_pre(); -+ status = efi_be_call(le64_to_cpu(runtime->get_variable), -+ virt_to_phys(name), virt_to_phys(vendor), -+ virt_to_phys(attr), virt_to_phys(data_size), -+ virt_to_phys(data)); -+ efi_be_call_post(flags); -+ *attr = le32_to_cpu(*attr); -+ *data_size = le64_to_cpu(*data_size); -+ return status; -+} -+ -+static efi_status_t efi_be_get_next_variable(unsigned long *name_size, -+ efi_char16_t *name, -+ efi_guid_t *vendor) -+{ -+ unsigned long flags; -+ efi_status_t status; -+ -+ *name_size = cpu_to_le64(*name_size); -+ flags = efi_be_call_pre(); -+ status = efi_be_call(le64_to_cpu(runtime->get_next_variable), -+ virt_to_phys(name_size), virt_to_phys(name), -+ virt_to_phys(vendor)); -+ efi_be_call_post(flags); -+ *name_size = le64_to_cpu(*name_size); -+ return status; -+} -+ -+static efi_status_t efi_be_set_variable(efi_char16_t *name, -+ efi_guid_t *vendor, -+ u32 attr, -+ unsigned long data_size, -+ void *data) -+{ -+ unsigned long flags; -+ efi_status_t status; -+ -+ flags = efi_be_call_pre(); -+ status = efi_be_call(le64_to_cpu(runtime->set_variable), -+ virt_to_phys(name), virt_to_phys(vendor), -+ cpu_to_le32(attr), cpu_to_le64(data_size), -+ virt_to_phys(data)); -+ efi_be_call_post(flags); -+ return status; -+} -+ -+void efi_be_runtime_setup(void) -+{ -+ extern u8 efi_be_phys_call[]; -+ -+ runtime = ioremap_cache(le64_to_cpu(efi.systab->runtime), -+ sizeof(efi_runtime_services_t)); -+ if (!runtime) { -+ pr_err("Failed to set up BE wrappers for UEFI Runtime Services!\n"); -+ return; -+ } -+ -+ efi_be_call = (void *)virt_to_phys(efi_be_phys_call); -+ -+ efi.get_variable = efi_be_get_variable; -+ efi.get_next_variable = efi_be_get_next_variable; -+ efi.set_variable = efi_be_set_variable; -+} -diff --git a/arch/arm64/kernel/efi-entry.S b/arch/arm64/kernel/efi-entry.S -index 8ce9b05..760fbb5 100644 ---- a/arch/arm64/kernel/efi-entry.S -+++ b/arch/arm64/kernel/efi-entry.S -@@ -34,7 +34,34 @@ ENTRY(efi_stub_entry) - * Create a stack frame to save FP/LR with extra space - * for image_addr variable passed to efi_entry(). - */ -- stp x29, x30, [sp, #-32]! -+ stp x29, x30, [sp, #-48]! -+ stp x22, x23, [sp, #32] -+ -+#ifdef CONFIG_EFI_LE_STUB -+ adr x4, efi_stub_entry -+ ldp w8, w9, [x4, #-32] -+STUB_BE(rev w8, w8 ) -+STUB_BE(rev w9, w9 ) -+ add x8, x4, w8, sxtw // x8: base of Image -+ add x9, x4, w9, sxtw // x9: offset of linux_banner -+ -+ ldp x22, x23, [x4, #-24] // x22: size of Image -+STUB_BE(rev x23, x23 ) // x23: stext offset -+ -+ /* -+ * Get a pointer to linux_banner in the outer image and store it -+ * in this image. -+ */ -+ adrp x4, le_linux_banner -+ str x9, [x4, #:lo12:le_linux_banner] -+#else -+ adrp x8, _text -+ add x8, x8, #:lo12:_text // x8: base of Image -+ adrp x9, _edata -+ add x9, x9, #:lo12:_edata -+ sub x22, x9, x8 // x22: size of Image -+ ldr x23, =stext_offset // x23: stext offset -+#endif - - /* - * Call efi_entry to do the real work. -@@ -45,8 +72,6 @@ ENTRY(efi_stub_entry) - * efi_system_table_t *sys_table, - * unsigned long *image_addr) ; - */ -- adrp x8, _text -- add x8, x8, #:lo12:_text - add x2, sp, 16 - str x8, [x2] - bl efi_entry -@@ -61,17 +86,12 @@ ENTRY(efi_stub_entry) - */ - mov x20, x0 // DTB address - ldr x0, [sp, #16] // relocated _text address -- ldr x21, =stext_offset -- add x21, x0, x21 -+ add x21, x0, x23 - - /* - * Calculate size of the kernel Image (same for original and copy). - */ -- adrp x1, _text -- add x1, x1, #:lo12:_text -- adrp x2, _edata -- add x2, x2, #:lo12:_edata -- sub x1, x2, x1 -+ mov x1, x22 - - /* - * Flush the copied Image to the PoC, and ensure it is not shadowed by -@@ -117,7 +137,8 @@ ENTRY(efi_stub_entry) - - efi_load_fail: - mov x0, #EFI_LOAD_ERROR -- ldp x29, x30, [sp], #32 -+ ldp x22, x23, [sp, #32] -+ ldp x29, x30, [sp], #48 - ret - - efi_stub_entry_end: -diff --git a/arch/arm64/kernel/efi-stub.c b/arch/arm64/kernel/efi-stub.c -index d27dd98..dd6d6bc 100644 ---- a/arch/arm64/kernel/efi-stub.c -+++ b/arch/arm64/kernel/efi-stub.c -@@ -11,7 +11,6 @@ - */ - #include <linux/efi.h> - #include <asm/efi.h> --#include <asm/sections.h> - - efi_status_t handle_kernel_image(efi_system_table_t *sys_table, - unsigned long *image_addr, -@@ -22,22 +21,19 @@ efi_status_t handle_kernel_image(efi_system_table_t *sys_table, - efi_loaded_image_t *image) - { - efi_status_t status; -- unsigned long kernel_size, kernel_memsize = 0; - - /* Relocate the image, if required. */ -- kernel_size = _edata - _text; - if (*image_addr != (dram_base + TEXT_OFFSET)) { -- kernel_memsize = kernel_size + (_end - _edata); -- status = efi_low_alloc(sys_table, kernel_memsize + TEXT_OFFSET, -+ status = efi_low_alloc(sys_table, image->image_size + TEXT_OFFSET, - SZ_2M, reserve_addr); - if (status != EFI_SUCCESS) { - pr_efi_err(sys_table, "Failed to relocate kernel\n"); - return status; - } - memcpy((void *)*reserve_addr + TEXT_OFFSET, (void *)*image_addr, -- kernel_size); -+ image->image_size); - *image_addr = *reserve_addr + TEXT_OFFSET; -- *reserve_size = kernel_memsize + TEXT_OFFSET; -+ *reserve_size = image->image_size + TEXT_OFFSET; - } - - -diff --git a/arch/arm64/kernel/efi.c b/arch/arm64/kernel/efi.c -index 4178e9e..133c599 100644 ---- a/arch/arm64/kernel/efi.c -+++ b/arch/arm64/kernel/efi.c -@@ -43,7 +43,7 @@ early_param("uefi_debug", uefi_debug_setup); - - static int __init is_normal_ram(efi_memory_desc_t *md) - { -- if (md->attribute & EFI_MEMORY_WB) -+ if (le64_to_cpu(md->attribute) & EFI_MEMORY_WB) - return 1; - return 0; - } -@@ -59,10 +59,10 @@ static void __init efi_setup_idmap(void) - - /* map runtime io spaces */ - for_each_efi_memory_desc(&memmap, md) { -- if (!(md->attribute & EFI_MEMORY_RUNTIME) || is_normal_ram(md)) -+ if (!(le64_to_cpu(md->attribute) & EFI_MEMORY_RUNTIME) || is_normal_ram(md)) - continue; -- paddr = md->phys_addr; -- npages = md->num_pages; -+ paddr = le64_to_cpu(md->phys_addr); -+ npages = le64_to_cpu(md->num_pages); - memrange_efi_to_native(&paddr, &npages); - size = npages << PAGE_SHIFT; - create_id_mapping(paddr, size, 1); -@@ -88,29 +88,29 @@ static int __init uefi_init(void) - /* - * Verify the EFI Table - */ -- if (efi.systab->hdr.signature != EFI_SYSTEM_TABLE_SIGNATURE) { -+ if (le64_to_cpu(efi.systab->hdr.signature) != EFI_SYSTEM_TABLE_SIGNATURE) { - pr_err("System table signature incorrect\n"); - retval = -EINVAL; - goto out; - } -- if ((efi.systab->hdr.revision >> 16) < 2) -+ if ((le32_to_cpu(efi.systab->hdr.revision) >> 16) < 2) - pr_warn("Warning: EFI system table version %d.%02d, expected 2.00 or greater\n", - efi.systab->hdr.revision >> 16, - efi.systab->hdr.revision & 0xffff); - - /* Show what we know for posterity */ -- c16 = early_memremap(efi.systab->fw_vendor, -+ c16 = early_memremap(le64_to_cpu(efi.systab->fw_vendor), - sizeof(vendor)); - if (c16) { - for (i = 0; i < (int) sizeof(vendor) - 1 && *c16; ++i) -- vendor[i] = c16[i]; -+ vendor[i] = le16_to_cpu(c16[i]); - vendor[i] = '\0'; - early_memunmap(c16, sizeof(vendor)); - } - - pr_info("EFI v%u.%.02u by %s\n", -- efi.systab->hdr.revision >> 16, -- efi.systab->hdr.revision & 0xffff, vendor); -+ le32_to_cpu(efi.systab->hdr.revision) >> 16, -+ le32_to_cpu(efi.systab->hdr.revision) & 0xffff, vendor); - - retval = efi_config_init(NULL); - -@@ -124,7 +124,7 @@ out: - */ - static __init int is_reserve_region(efi_memory_desc_t *md) - { -- switch (md->type) { -+ switch (le32_to_cpu(md->type)) { - case EFI_LOADER_CODE: - case EFI_LOADER_DATA: - case EFI_BOOT_SERVICES_CODE: -@@ -146,8 +146,9 @@ static __init void reserve_regions(void) - pr_info("Processing EFI memory map:\n"); - - for_each_efi_memory_desc(&memmap, md) { -- paddr = md->phys_addr; -- npages = md->num_pages; -+ u32 md_type = le32_to_cpu(md->type); -+ paddr = le64_to_cpu(md->phys_addr); -+ npages = le64_to_cpu(md->num_pages); - - if (uefi_debug) { - char buf[64]; -@@ -164,8 +165,8 @@ static __init void reserve_regions(void) - early_init_dt_add_memory_arch(paddr, size); - - if (is_reserve_region(md) || -- md->type == EFI_BOOT_SERVICES_CODE || -- md->type == EFI_BOOT_SERVICES_DATA) { -+ md_type == EFI_BOOT_SERVICES_CODE || -+ md_type == EFI_BOOT_SERVICES_DATA) { - memblock_reserve(paddr, size); - if (uefi_debug) - pr_cont("*"); -@@ -246,17 +247,17 @@ static void __init free_boot_services(void) - */ - if (free_start) { - /* adjust free_end then free region */ -- if (free_end > md->phys_addr) -+ if (free_end > le64_to_cpu(md->phys_addr)) - free_end -= PAGE_SIZE; - total_freed += free_region(free_start, free_end); - free_start = 0; - } -- keep_end = md->phys_addr + (md->num_pages << EFI_PAGE_SHIFT); -+ keep_end = le64_to_cpu(md->phys_addr) + (le64_to_cpu(md->num_pages) << EFI_PAGE_SHIFT); - continue; - } - -- if (md->type != EFI_BOOT_SERVICES_CODE && -- md->type != EFI_BOOT_SERVICES_DATA) { -+ if (le32_to_cpu(md->type) != EFI_BOOT_SERVICES_CODE && -+ le32_to_cpu(md->type) != EFI_BOOT_SERVICES_DATA) { - /* no need to free this region */ - continue; - } -@@ -264,8 +265,8 @@ static void __init free_boot_services(void) - /* - * We want to free memory from this region. - */ -- paddr = md->phys_addr; -- npages = md->num_pages; -+ paddr = le64_to_cpu(md->phys_addr); -+ npages = le64_to_cpu(md->num_pages); - memrange_efi_to_native(&paddr, &npages); - size = npages << PAGE_SHIFT; - -@@ -333,8 +334,8 @@ static int __init remap_region(efi_memory_desc_t *md, void **new) - { - u64 paddr, vaddr, npages, size; - -- paddr = md->phys_addr; -- npages = md->num_pages; -+ paddr = le64_to_cpu(md->phys_addr); -+ npages = le64_to_cpu(md->num_pages); - memrange_efi_to_native(&paddr, &npages); - size = npages << PAGE_SHIFT; - -@@ -350,7 +351,7 @@ static int __init remap_region(efi_memory_desc_t *md, void **new) - } - - /* adjust for any rounding when EFI and system pagesize differs */ -- md->virt_addr = vaddr + (md->phys_addr - paddr); -+ md->virt_addr = vaddr + (le64_to_cpu(md->phys_addr) - paddr); - - if (uefi_debug) - pr_info(" EFI remap 0x%012llx => %p\n", -@@ -395,6 +396,21 @@ static int __init arm64_enter_virtual_mode(void) - - efi.memmap = &memmap; - -+ if (IS_ENABLED(CONFIG_CPU_BIG_ENDIAN)) { -+ efi.systab = ioremap_cache(efi_system_table, -+ sizeof(efi_system_table_t)); -+ if (!efi.systab) { -+ pr_err("Failed to remap EFI system table!\n"); -+ return -1; -+ } -+ free_boot_services(); -+ efi_be_runtime_setup(); -+ -+ set_bit(EFI_SYSTEM_TABLES, &efi.flags); -+ set_bit(EFI_RUNTIME_SERVICES, &efi.flags); -+ return 0; -+ } -+ - /* Map the runtime regions */ - virtmap = kmalloc(mapsize, GFP_KERNEL); - if (!virtmap) { -diff --git a/arch/arm64/kernel/efistub-le/Makefile b/arch/arm64/kernel/efistub-le/Makefile -new file mode 100644 -index 0000000..8a1c2a8 ---- /dev/null -+++ b/arch/arm64/kernel/efistub-le/Makefile -@@ -0,0 +1,52 @@ -+ -+# -+# Build a little endian EFI stub and wrap it into a single .o -+# -+ -+# the LE objects making up the LE efi stub -+le-objs := efi-entry.o efi-stub.o strstr.o cache.o \ -+ lib-memchr.o lib-memcmp.o lib-memcpy.o lib-memmove.o \ -+ lib-memset.o lib-strchr.o lib-strlen.o lib-strncmp.o \ -+ fdt-fdt.o fdt-fdt_ro.o fdt-fdt_rw.o fdt-fdt_sw.o \ -+ fdt-fdt_wip.o fdt-fdt_empty_tree.o \ -+ libstub-fdt.o libstub-arm-stub.o libstub-efi-stub-helper.o -+ -+extra-y := efi-le-stub.bin efi-le-stub.elf $(le-objs) -+ -+KBUILD_CFLAGS := $(subst -pg,,$(KBUILD_CFLAGS)) -fno-stack-protector \ -+ -mlittle-endian -I$(srctree)/scripts/dtc/libfdt -+ -+le-targets := $(addprefix $(obj)/, $(le-objs)) -+$(le-targets): KBUILD_AFLAGS += -mlittle-endian -include $(srctree)/$(src)/le.h -+ -+$(obj)/efi-entry.o: $(obj)/../efi-entry.S FORCE -+ $(call if_changed_dep,as_o_S) -+ -+CFLAGS_efi-stub.o += -DTEXT_OFFSET=$(TEXT_OFFSET) -+$(obj)/efi-stub.o: $(obj)/../efi-stub.c FORCE -+ $(call if_changed_dep,cc_o_c) -+ -+$(obj)/cache.o: $(src)/../../mm/cache.S FORCE -+ $(call if_changed_dep,as_o_S) -+ -+$(obj)/lib-%.o: $(src)/../../lib/%.S FORCE -+ $(call if_changed_dep,as_o_S) -+ -+$(obj)/fdt-%.o: $(srctree)/lib/%.c FORCE -+ $(call if_changed_dep,cc_o_c) -+ -+$(obj)/libstub-%.o: $(srctree)/drivers/firmware/efi/libstub/%.c FORCE -+ $(call if_changed_dep,cc_o_c) -+ -+$(obj)/efi-le-stub.elf: LDFLAGS=-EL -Map $@.map -T -+$(obj)/efi-le-stub.elf: $(src)/efistub-le.lds $(le-targets) FORCE -+ $(call if_changed,ld) -+ -+$(obj)/efi-le-stub.bin: OBJCOPYFLAGS=-O binary -+$(obj)/efi-le-stub.bin: $(obj)/efi-le-stub.elf FORCE -+ $(call if_changed,objcopy) -+ -+# the BE object containing the entire LE stub -+obj-y := efi-le-entry.o -+ -+$(obj)/efi-le-entry.o: $(obj)/efi-le-stub.bin -diff --git a/arch/arm64/kernel/efistub-le/efi-le-entry.S b/arch/arm64/kernel/efistub-le/efi-le-entry.S -new file mode 100644 -index 0000000..755364c ---- /dev/null -+++ b/arch/arm64/kernel/efistub-le/efi-le-entry.S -@@ -0,0 +1,12 @@ -+#include <linux/linkage.h> -+ -+ .text -+ .align 12 -+ .long _text - efi_stub_entry -+ .long linux_banner - efi_stub_entry -+ .quad _kernel_size_le -+ .quad stext_offset -+ .quad 0 -+ENTRY(efi_stub_entry) -+ .incbin "arch/arm64/kernel/efistub-le/efi-le-stub.bin" -+ENDPROC(efi_stub_entry) -diff --git a/arch/arm64/kernel/efistub-le/efistub-le.lds b/arch/arm64/kernel/efistub-le/efistub-le.lds -new file mode 100644 -index 0000000..f64d542 ---- /dev/null -+++ b/arch/arm64/kernel/efistub-le/efistub-le.lds -@@ -0,0 +1,35 @@ -+ -+ENTRY(efi_stub_entry) -+ -+SECTIONS { -+ /* -+ * The inner and outer alignment of this chunk of code need to be the -+ * same so that PC relative references using adrp/add or adrp/ldr pairs -+ * will work correctly. -+ * Skip 32 bytes here, so we can put the binary blob at an offset of -+ * 4k + 0x20 in the outer image, and use the gap to share constants -+ * emitted by the outer linker but required in the stub. -+ */ -+ .text 0x20 : { -+ arch/arm64/kernel/efistub-le/efi-entry.o(.init.text) -+ *(.init.text) -+ *(.text) -+ *(.text*) -+ } -+ .rodata : { -+ . = ALIGN(16); -+ *(.rodata) -+ *(.rodata*) -+ *(.init.rodata) -+ } -+ .data : { -+ . = ALIGN(16); -+ *(.data) -+ *(.data*) -+ le_linux_banner = .; -+ . += 8; -+ } -+ /DISCARD/ : { -+ *(__ex_table) -+ } -+} -diff --git a/arch/arm64/kernel/efistub-le/le.h b/arch/arm64/kernel/efistub-le/le.h -new file mode 100644 -index 0000000..a9f6dfc ---- /dev/null -+++ b/arch/arm64/kernel/efistub-le/le.h -@@ -0,0 +1,12 @@ -+ -+/* -+ * This is a bit of a hack, but it is necessary to correctly compile .S files -+ * that contain CPU_LE()/CPU_BE() statements, as these are defined to depend on -+ * CONFIG_ symbols and not on the endianness of the compiler. -+ */ -+#ifdef CONFIG_CPU_BIG_ENDIAN -+#define STUB_BE(code...) code -+#else -+#define STUB_BE(code...) -+#endif -+#undef CONFIG_CPU_BIG_ENDIAN -diff --git a/arch/arm64/kernel/efistub-le/strstr.c b/arch/arm64/kernel/efistub-le/strstr.c -new file mode 100644 -index 0000000..bd16094 ---- /dev/null -+++ b/arch/arm64/kernel/efistub-le/strstr.c -@@ -0,0 +1,20 @@ -+ -+#include <linux/types.h> -+#include <linux/string.h> -+ -+char *strstr(const char *s1, const char *s2) -+{ -+ size_t l1, l2; -+ -+ l2 = strlen(s2); -+ if (!l2) -+ return (char *)s1; -+ l1 = strlen(s1); -+ while (l1 >= l2) { -+ l1--; -+ if (!memcmp(s1, s2, l2)) -+ return (char *)s1; -+ s1++; -+ } -+ return NULL; -+} -diff --git a/arch/arm64/kernel/head.S b/arch/arm64/kernel/head.S -index 8ce88e0..8b1eba5 100644 ---- a/arch/arm64/kernel/head.S -+++ b/arch/arm64/kernel/head.S -@@ -126,7 +126,10 @@ efi_head: - .byte 0x4d - .byte 0x64 - #ifdef CONFIG_EFI -- .long pe_header - efi_head // Offset to the PE header. -+ .byte pe_header - efi_head // Offset to the PE header. -+ .byte 0 -+ .byte 0 -+ .byte 0 - #else - .word 0 // reserved - #endif -@@ -139,30 +142,31 @@ pe_header: - .ascii "PE" - .short 0 - coff_header: -- .short 0xaa64 // AArch64 -- .short 2 // nr_sections -+ le16 0xaa64 // AArch64 -+ le16 2 // nr_sections - .long 0 // TimeDateStamp - .long 0 // PointerToSymbolTable -- .long 1 // NumberOfSymbols -- .short section_table - optional_header // SizeOfOptionalHeader -- .short 0x206 // Characteristics. -+ le32 1 // NumberOfSymbols -+ .byte section_table - optional_header // SizeOfOptionalHeader -+ .byte 0 -+ le16 0x206 // Characteristics. - // IMAGE_FILE_DEBUG_STRIPPED | - // IMAGE_FILE_EXECUTABLE_IMAGE | - // IMAGE_FILE_LINE_NUMS_STRIPPED - optional_header: -- .short 0x20b // PE32+ format -+ le16 0x20b // PE32+ format - .byte 0x02 // MajorLinkerVersion - .byte 0x14 // MinorLinkerVersion -- .long _end - stext // SizeOfCode -+ .long _efi_code_virtsize_le // SizeOfCode - .long 0 // SizeOfInitializedData - .long 0 // SizeOfUninitializedData -- .long efi_stub_entry - efi_head // AddressOfEntryPoint -- .long stext_offset // BaseOfCode -+ .long _efi_entry_point_le // AddressOfEntryPoint -+ .long _efi_stext_offset_le // BaseOfCode - - extra_header_fields: - .quad 0 // ImageBase -- .long 0x1000 // SectionAlignment -- .long PECOFF_FILE_ALIGNMENT // FileAlignment -+ le32 0x1000 // SectionAlignment -+ le32 0x200 // FileAlignment - .short 0 // MajorOperatingSystemVersion - .short 0 // MinorOperatingSystemVersion - .short 0 // MajorImageVersion -@@ -171,19 +175,19 @@ extra_header_fields: - .short 0 // MinorSubsystemVersion - .long 0 // Win32VersionValue - -- .long _end - efi_head // SizeOfImage -+ .long _efi_image_size_le // SizeOfImage - - // Everything before the kernel image is considered part of the header -- .long stext_offset // SizeOfHeaders -+ .long _efi_stext_offset_le // SizeOfHeaders - .long 0 // CheckSum -- .short 0xa // Subsystem (EFI application) -+ le16 0xa // Subsystem (EFI application) - .short 0 // DllCharacteristics - .quad 0 // SizeOfStackReserve - .quad 0 // SizeOfStackCommit - .quad 0 // SizeOfHeapReserve - .quad 0 // SizeOfHeapCommit - .long 0 // LoaderFlags -- .long 0x6 // NumberOfRvaAndSizes -+ le32 0x6 // NumberOfRvaAndSizes - - .quad 0 // ExportTable - .quad 0 // ImportTable -@@ -211,23 +215,23 @@ section_table: - .long 0 // PointerToLineNumbers - .short 0 // NumberOfRelocations - .short 0 // NumberOfLineNumbers -- .long 0x42100040 // Characteristics (section flags) -+ le32 0x42100040 // Characteristics (section flags) - - - .ascii ".text" - .byte 0 - .byte 0 - .byte 0 // end of 0 padding of section name -- .long _end - stext // VirtualSize -- .long stext_offset // VirtualAddress -- .long _edata - stext // SizeOfRawData -- .long stext_offset // PointerToRawData -+ .long _efi_code_virtsize_le // VirtualSize -+ .long _efi_stext_offset_le // VirtualAddress -+ .long _efi_code_rawsize_le // SizeOfRawData -+ .long _efi_stext_offset_le // PointerToRawData - - .long 0 // PointerToRelocations (0 for executables) - .long 0 // PointerToLineNumbers (0 for executables) - .short 0 // NumberOfRelocations (0 for executables) - .short 0 // NumberOfLineNumbers (0 for executables) -- .long 0xe0500020 // Characteristics (section flags) -+ le32 0xe0500020 // Characteristics (section flags) - - /* - * EFI will load stext onwards at the 4k section alignment -diff --git a/arch/arm64/kernel/image.h b/arch/arm64/kernel/image.h -index 8fae075..d08ce56 100644 ---- a/arch/arm64/kernel/image.h -+++ b/arch/arm64/kernel/image.h -@@ -37,8 +37,10 @@ - (((data) & 0x0000ff0000000000) >> 24) | \ - (((data) & 0x00ff000000000000) >> 40) | \ - (((data) & 0xff00000000000000) >> 56)) -+#define DATA_LE32(data) (DATA_LE64(data) >> 32) - #else - #define DATA_LE64(data) ((data) & 0xffffffffffffffff) -+#define DATA_LE32(data) ((data) & 0xffffffff) - #endif - - #ifdef CONFIG_CPU_BIG_ENDIAN -@@ -57,6 +59,18 @@ - #define HEAD_SYMBOLS \ - _kernel_size_le = DATA_LE64(_end - _text); \ - _kernel_offset_le = DATA_LE64(TEXT_OFFSET); \ -- _kernel_flags_le = DATA_LE64(__HEAD_FLAGS); -+ _kernel_flags_le = DATA_LE64(__HEAD_FLAGS); \ -+ EFI_HEAD_SYMBOLS -+ -+#ifdef CONFIG_EFI -+#define EFI_HEAD_SYMBOLS \ -+ _efi_stext_offset_le = DATA_LE32(stext_offset); \ -+ _efi_code_virtsize_le = DATA_LE32(_end - _text - stext_offset); \ -+ _efi_code_rawsize_le = DATA_LE32(_edata - _text - stext_offset); \ -+ _efi_image_size_le = DATA_LE32(_end - _text); \ -+ _efi_entry_point_le = DATA_LE32(efi_stub_entry - _text); -+#else -+#define EFI_HEAD_SYMBOLS -+#endif - - #endif /* __ASM_IMAGE_H */ -diff --git a/drivers/firmware/efi/efi.c b/drivers/firmware/efi/efi.c -index 9035c1b..4e98daa 100644 ---- a/drivers/firmware/efi/efi.c -+++ b/drivers/firmware/efi/efi.c -@@ -296,18 +296,23 @@ static __init int match_config_table(efi_guid_t *guid, - int __init efi_config_init(efi_config_table_type_t *arch_tables) - { - void *config_tables, *tablep; -- int i, sz; -+ unsigned long __tables; -+ int i, sz, nr_tables; - -- if (efi_enabled(EFI_64BIT)) -+ if (efi_enabled(EFI_64BIT)) { - sz = sizeof(efi_config_table_64_t); -- else -+ nr_tables = le64_to_cpu((__force __le64)efi.systab->nr_tables); -+ __tables = le64_to_cpu((__force __le64)efi.systab->tables); -+ } else { - sz = sizeof(efi_config_table_32_t); -+ nr_tables = le32_to_cpu((__force __le32)efi.systab->nr_tables); -+ __tables = le32_to_cpu((__force __le32)efi.systab->tables); -+ } - - /* - * Let's see what config tables the firmware passed to us. - */ -- config_tables = early_memremap(efi.systab->tables, -- efi.systab->nr_tables * sz); -+ config_tables = early_memremap(__tables, nr_tables * sz); - if (config_tables == NULL) { - pr_err("Could not map Configuration table!\n"); - return -ENOMEM; -@@ -315,21 +320,20 @@ int __init efi_config_init(efi_config_table_type_t *arch_tables) - - tablep = config_tables; - pr_info(""); -- for (i = 0; i < efi.systab->nr_tables; i++) { -+ for (i = 0; i < nr_tables; i++) { - efi_guid_t guid; - unsigned long table; - - if (efi_enabled(EFI_64BIT)) { - u64 table64; - guid = ((efi_config_table_64_t *)tablep)->guid; -- table64 = ((efi_config_table_64_t *)tablep)->table; -- table = table64; -+ table = table64 = le64_to_cpu((__force __le64) -+ ((efi_config_table_64_t *)tablep)->table); - #ifndef CONFIG_64BIT - if (table64 >> 32) { - pr_cont("\n"); - pr_err("Table located above 4GB, disabling EFI.\n"); -- early_memunmap(config_tables, -- efi.systab->nr_tables * sz); -+ early_memunmap(config_tables, nr_tables * sz); - return -EINVAL; - } - #endif -@@ -344,7 +348,7 @@ int __init efi_config_init(efi_config_table_type_t *arch_tables) - tablep += sz; - } - pr_cont("\n"); -- early_memunmap(config_tables, efi.systab->nr_tables * sz); -+ early_memunmap(config_tables, nr_tables * sz); - - set_bit(EFI_CONFIG_TABLES, &efi.flags); - -diff --git a/drivers/firmware/efi/efivars.c b/drivers/firmware/efi/efivars.c -index f256ecd..2b1c8be 100644 ---- a/drivers/firmware/efi/efivars.c -+++ b/drivers/firmware/efi/efivars.c -@@ -563,7 +563,7 @@ efivar_create_sysfs_entry(struct efivar_entry *new_var) - /* Convert Unicode to normal chars (assume top bits are 0), - ala UTF-8 */ - for (i=0; i < (int)(variable_name_size / sizeof(efi_char16_t)); i++) { -- short_name[i] = variable_name[i] & 0xFF; -+ short_name[i] = le16_to_cpu((__force __le16)variable_name[i]); - } - /* This is ugly, but necessary to separate one vendor's - private variables from another's. */ -diff --git a/drivers/firmware/efi/libstub/fdt.c b/drivers/firmware/efi/libstub/fdt.c -index c846a96..f0f9d54 100644 ---- a/drivers/firmware/efi/libstub/fdt.c -+++ b/drivers/firmware/efi/libstub/fdt.c -@@ -22,6 +22,10 @@ efi_status_t update_fdt(efi_system_table_t *sys_table, void *orig_fdt, - unsigned long map_size, unsigned long desc_size, - u32 desc_ver) - { -+#ifdef CONFIG_EFI_LE_STUB -+ extern char const *le_linux_banner; -+ char const *linux_banner = le_linux_banner; -+#endif - int node, prev, num_rsv; - int status; - u32 fdt_val32; --- -1.9.1 - |