From 635d320abfa6dc3c0e1d00e3ceae567dd0e55a5b Mon Sep 17 00:00:00 2001 From: Tudor Florea Date: Thu, 8 Oct 2015 22:42:49 +0200 Subject: initial commit for Enea Linux 5.0 arm Signed-off-by: Tudor Florea --- .../01-arm64-boot-BE-kernels-from-UEFI.patch | 995 +++++++++++++++++++++ 1 file changed, 995 insertions(+) create mode 100644 recipes-kernel/linux/linux-hierofalcon/01-arm64-boot-BE-kernels-from-UEFI.patch (limited to 'recipes-kernel/linux/linux-hierofalcon/01-arm64-boot-BE-kernels-from-UEFI.patch') 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 @@ +From c55fa726d3e67da11a7ccd16ca367e9094265e4e Mon Sep 17 00:00:00 2001 +From: Adrian Calianu +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. + +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 + +Signed-off-by: Adrian Calianu +--- + 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 ++ ++ .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 ++#include ++#include ++#include ++#include ++ ++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 + #include +-#include + + 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 ++ ++ .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 ++#include ++ ++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 + -- cgit v1.2.3-54-g00ecf