[RFC PATCH 02/10] arm64/efi: efistub: cover entire static mem footprint in PE/COFF .text

2014-07-21 Thread Ard Biesheuvel
The static memory footprint of a kernel Image at boot is larger than the
Image file itself. Things like .bss data and initial page tables are allocated
statically but populated dynamically so their content is not contained in the
Image file.

However, if EFI has loaded the Image at precisely the desired offset of
base of DRAM + TEXT_OFFSET, the Image will be booted in place, and we have
to make sure that the allocation done by the EFI loader is large enough.

Fix this by growing the PE/COFF .text section to cover the entire static
memory footprint. The part of the section that is not covered by the payload
will be zero initialised by the EFI loader.

Signed-off-by: Ard Biesheuvel ard.biesheu...@linaro.org
---
 arch/arm64/kernel/head.S | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/arch/arm64/kernel/head.S b/arch/arm64/kernel/head.S
index 5cd1f3491df5..c63f44f20ae3 100644
--- a/arch/arm64/kernel/head.S
+++ b/arch/arm64/kernel/head.S
@@ -150,7 +150,7 @@ optional_header:
.short  0x20b   // PE32+ format
.byte   0x02// MajorLinkerVersion
.byte   0x14// MinorLinkerVersion
-   .long   _edata - stext  // SizeOfCode
+   .long   _end - stext// SizeOfCode
.long   0   // SizeOfInitializedData
.long   0   // SizeOfUninitializedData
.long   efi_stub_entry - efi_head   // AddressOfEntryPoint
@@ -168,7 +168,7 @@ extra_header_fields:
.short  0   // MinorSubsystemVersion
.long   0   // Win32VersionValue
 
-   .long   _edata - efi_head   // SizeOfImage
+   .long   _end - efi_head // SizeOfImage
 
// Everything before the kernel image is considered part of the header
.long   stext_offset// SizeOfHeaders
@@ -215,7 +215,7 @@ section_table:
.byte   0
.byte   0
.byte   0   // end of 0 padding of section name
-   .long   _edata - stext  // VirtualSize
+   .long   _end - stext// VirtualSize
.long   stext_offset// VirtualAddress
.long   _edata - stext  // SizeOfRawData
.long   stext_offset// PointerToRawData
-- 
1.8.3.2

--
To unsubscribe from this list: send the line unsubscribe linux-efi in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[RFC PATCH 04/10] arm64: add EFI little endian constants to linker script

2014-07-21 Thread Ard Biesheuvel
Similar to how text offset and kernel size are mangled to produce little
endian constants for the Image header regardless of the endianness of the
kernel, this adds a number of constants used in the EFI PE/COFF header which
can only be calculated (and byte swapped) by the linker.

Signed-off-by: Ard Biesheuvel ard.biesheu...@linaro.org
---
 arch/arm64/kernel/image.h | 16 +++-
 1 file changed, 15 insertions(+), 1 deletion(-)

diff --git a/arch/arm64/kernel/image.h b/arch/arm64/kernel/image.h
index 8fae0756e175..f5a2f298810d 100644
--- a/arch/arm64/kernel/image.h
+++ b/arch/arm64/kernel/image.h
@@ -37,8 +37,10 @@
 (((data)  0xff00)  24) |\
 (((data)  0x00ff)  40) |\
 (((data)  0xff00)  56))
+#define DATA_LE32(data) (DATA_LE64(data)  32)
 #else
 #define DATA_LE64(data) ((data)  0x)
+#define DATA_LE32(data) ((data)  0x)
 #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 */
-- 
1.8.3.2

--
To unsubscribe from this list: send the line unsubscribe linux-efi in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[RFC PATCH 03/10] arm64: add macros to emit little endian ASM constants

2014-07-21 Thread Ard Biesheuvel
The Image header contains many constants that should be emitted in little
endian regardless of the endianness of the kernel. Add helper macros le16,
le32 and le64 to asm/assembler.h to aid with this.

Signed-off-by: Ard Biesheuvel ard.biesheu...@linaro.org
---
 arch/arm64/include/asm/assembler.h | 18 ++
 1 file changed, 18 insertions(+)

diff --git a/arch/arm64/include/asm/assembler.h 
b/arch/arm64/include/asm/assembler.h
index 5901480bfdca..7db7c946f73f 100644
--- a/arch/arm64/include/asm/assembler.h
+++ b/arch/arm64/include/asm/assembler.h
@@ -155,3 +155,21 @@ lr .reqx30 // 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
-- 
1.8.3.2

--
To unsubscribe from this list: send the line unsubscribe linux-efi in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[RFC PATCH 00/10] arm64: boot BE kernels from UEFI

2014-07-21 Thread Ard Biesheuvel
This series 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.

Patches #1 and #2 have been sent to the list before, but are included for
completeness.

Patch #3, #4 and #5 modify the PE/COFF header definition so it is always
emitted in little endian, regardless of the endianness of the kernel.

Patch #6 removes references to linker defined symbols like _text and _edata
from the stub, as the stub is now a standalone little endian binary that is
wrapped in a big endian object file, and _text and _edata are unavailable
or meaningless in that context.

Patch #7 adds the Makefile changes and some code to build the standalone stub
and wrap it.

Patch #8 updates the kernel code that references data in UEFI memory to byte
reverse it if required.

Patch #9 adds runtime services wrappers for the variable store services so they
can be called from the big endian kernel. Other runtime services are not
implemented for now.

Patch #10 enables everything by adding the Kconfig logic.

This is tested on Foundation model and FVP Base model. Booting works fine on
both, however, enumerating the variable store works only on FVP Base, and is
not debuggable on Foundation Model, so I would really appreciate any insights
into the code in patch #9 that may be causing this. There is some trickery
regarding en-/disabling caches and MMU and surely I have gotten something
wrong there.

Ard Biesheuvel (10):
  arm64/efi: efistub: jump to 'stext' directly, not through the header
  arm64/efi: efistub: cover entire static mem footprint in PE/COFF .text
  arm64: add macros to emit little endian ASM constants
  arm64: add EFI little endian constants to linker script
  arm64/efi: update the PE/COFF header to be endian agnostic
  arm64/efi: efistub: avoid using linker defined constants
  arm64/efi: efistub: add support for booting a BE kernel
  arm64/efi: use LE accessors to access UEFI data
  arm64/efi: enable minimal UEFI Runtime Services for big endian
  arm64: Kconfig: enable UEFI on BE kernels

 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   |  41 ---
 arch/arm64/kernel/efi-stub.c|  11 ++-
 arch/arm64/kernel/efi.c |  68 +++---
 arch/arm64/kernel/efistub-le/Makefile   |  52 ++
 arch/arm64/kernel/efistub-le/efi-le-entry.S |  13 
 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|  50 +++--
 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, 466 insertions(+), 80 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

-- 
1.8.3.2

--
To unsubscribe from this list: send the line unsubscribe linux-efi in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[RFC PATCH 01/10] arm64/efi: efistub: jump to 'stext' directly, not through the header

2014-07-21 Thread Ard Biesheuvel
After the EFI stub has done its business, it jumps into the kernel by branching
to offset #0 of the loaded Image, which is where it expects to find the header
containing a 'branch to stext' instruction.

However, the header is not covered by any PE/COFF section, so the header may
not actually be loaded at the expected offset. So instead, jump to 'stext'
directly, which is at the base of the PE/COFF .text section, by supplying a
symbol 'stext_offset' to efi-entry.o which contains the relative offset of
stext into the Image. Also replace other open coded calculations of the same
value with a reference to 'stext_offset'

Signed-off-by: Ard Biesheuvel ard.biesheu...@linaro.org
---
 arch/arm64/kernel/efi-entry.S |  3 ++-
 arch/arm64/kernel/head.S  | 10 ++
 2 files changed, 8 insertions(+), 5 deletions(-)

diff --git a/arch/arm64/kernel/efi-entry.S b/arch/arm64/kernel/efi-entry.S
index 619b1dd7bcde..a0016d3a17da 100644
--- a/arch/arm64/kernel/efi-entry.S
+++ b/arch/arm64/kernel/efi-entry.S
@@ -61,7 +61,8 @@ ENTRY(efi_stub_entry)
 */
mov x20, x0 // DTB address
ldr x0, [sp, #16]   // relocated _text address
-   mov x21, x0
+   ldr x21, =stext_offset
+   add x21, x0, x21
 
/*
 * Flush dcache covering current runtime addresses
diff --git a/arch/arm64/kernel/head.S b/arch/arm64/kernel/head.S
index 69dafe9621fd..5cd1f3491df5 100644
--- a/arch/arm64/kernel/head.S
+++ b/arch/arm64/kernel/head.S
@@ -129,6 +129,8 @@ efi_head:
 #endif
 
 #ifdef CONFIG_EFI
+   .globl  stext_offset
+   .setstext_offset, stext - efi_head
.align 3
 pe_header:
.ascii  PE
@@ -152,7 +154,7 @@ optional_header:
.long   0   // SizeOfInitializedData
.long   0   // SizeOfUninitializedData
.long   efi_stub_entry - efi_head   // AddressOfEntryPoint
-   .long   stext - efi_head// BaseOfCode
+   .long   stext_offset// BaseOfCode
 
 extra_header_fields:
.quad   0   // ImageBase
@@ -169,7 +171,7 @@ extra_header_fields:
.long   _edata - efi_head   // SizeOfImage
 
// Everything before the kernel image is considered part of the header
-   .long   stext - efi_head// SizeOfHeaders
+   .long   stext_offset// SizeOfHeaders
.long   0   // CheckSum
.short  0xa // Subsystem (EFI application)
.short  0   // DllCharacteristics
@@ -214,9 +216,9 @@ section_table:
.byte   0
.byte   0   // end of 0 padding of section name
.long   _edata - stext  // VirtualSize
-   .long   stext - efi_head// VirtualAddress
+   .long   stext_offset// VirtualAddress
.long   _edata - stext  // SizeOfRawData
-   .long   stext - efi_head// PointerToRawData
+   .long   stext_offset// PointerToRawData
 
.long   0   // PointerToRelocations (0 for executables)
.long   0   // PointerToLineNumbers (0 for executables)
-- 
1.8.3.2

--
To unsubscribe from this list: send the line unsubscribe linux-efi in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[RFC PATCH 09/10] arm64/efi: enable minimal UEFI Runtime Services for big endian

2014-07-21 Thread Ard Biesheuvel
This enables the UEFI Runtime Services needed to manipulate the
non-volatile variable store when running under a BE kernel.

Signed-off-by: Ard Biesheuvel ard.biesheu...@linaro.org
---
 arch/arm64/include/asm/efi.h   |   2 +
 arch/arm64/kernel/efi-be-call.S|  55 
 arch/arm64/kernel/efi-be-runtime.c | 104 +
 arch/arm64/kernel/efi.c|  15 ++
 4 files changed, 176 insertions(+)
 create mode 100644 arch/arm64/kernel/efi-be-call.S
 create mode 100644 arch/arm64/kernel/efi-be-runtime.c

diff --git a/arch/arm64/include/asm/efi.h b/arch/arm64/include/asm/efi.h
index a34fd3b12e2b..44e642b6ab61 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/efi-be-call.S b/arch/arm64/kernel/efi-be-call.S
new file mode 100644
index ..24c92a4c352b
--- /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 ..62e6c441b77b
--- /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),
+

[RFC PATCH 05/10] arm64/efi: update the PE/COFF header to be endian agnostic

2014-07-21 Thread Ard Biesheuvel
Update the PE/COFF header to use explicit little endian constants and use
explicit little endian linker symbols so that the PE/COFF header is always
emitted in little endian regardless of the endiannes of the kernel.

Signed-off-by: Ard Biesheuvel ard.biesheu...@linaro.org
---
 arch/arm64/kernel/head.S | 48 ++--
 1 file changed, 26 insertions(+), 22 deletions(-)

diff --git a/arch/arm64/kernel/head.S b/arch/arm64/kernel/head.S
index c63f44f20ae3..5179d3df1024 100644
--- a/arch/arm64/kernel/head.S
+++ b/arch/arm64/kernel/head.S
@@ -123,7 +123,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
@@ -136,30 +139,31 @@ pe_header:
.ascii  PE
.short  0
 coff_header:
-   .short  0xaa64  // AArch64
-   .short  2   // nr_sections
+   le160xaa64  // AArch64
+   le162   // nr_sections
.long   0   // TimeDateStamp
.long   0   // PointerToSymbolTable
-   .long   1   // NumberOfSymbols
-   .short  section_table - optional_header // SizeOfOptionalHeader
-   .short  0x206   // Characteristics.
+   le321   // NumberOfSymbols
+   .byte   section_table - optional_header // SizeOfOptionalHeader
+   .byte   0
+   le160x206   // Characteristics.
// IMAGE_FILE_DEBUG_STRIPPED |
// IMAGE_FILE_EXECUTABLE_IMAGE |
// IMAGE_FILE_LINE_NUMS_STRIPPED
 optional_header:
-   .short  0x20b   // PE32+ format
+   le160x20b   // 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   0x20// SectionAlignment
-   .long   0x8 // FileAlignment
+   le320x20// SectionAlignment
+   le320x8 // FileAlignment
.short  0   // MajorOperatingSystemVersion
.short  0   // MinorOperatingSystemVersion
.short  0   // MajorImageVersion
@@ -168,19 +172,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)
+   le160xa // Subsystem (EFI application)
.short  0   // DllCharacteristics
.quad   0   // SizeOfStackReserve
.quad   0   // SizeOfStackCommit
.quad   0   // SizeOfHeapReserve
.quad   0   // SizeOfHeapCommit
.long   0   // LoaderFlags
-   .long   0x6 // NumberOfRvaAndSizes
+   le320x6 // NumberOfRvaAndSizes
 
.quad   0   // ExportTable
.quad   0   // ImportTable
@@ -208,23 +212,23 @@ section_table:
.long   0   // 

[RFC PATCH 10/10] arm64: Kconfig: enable UEFI on BE kernels

2014-07-21 Thread Ard Biesheuvel
This changes the Kconfig logic to allow EFI to be enabled on a BE kernel build.

Signed-off-by: Ard Biesheuvel ard.biesheu...@linaro.org
---
 arch/arm64/Kconfig | 10 +++---
 1 file changed, 7 insertions(+), 3 deletions(-)

diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index e9d8af2fc389..9fa1383acbd3 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -301,16 +301,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
-- 
1.8.3.2

--
To unsubscribe from this list: send the line unsubscribe linux-efi in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[RFC PATCH 07/10] arm64/efi: efistub: add support for booting a BE kernel

2014-07-21 Thread Ard Biesheuvel
This adds support to boot a big endian kernel from UEFI firmware, which is
always little endian. The EFI stub itself is built as little endian, and
embedded into a big endian kernel image.

To enable this, we need to build all the stub's dependencies as little endian,
including FDT parsing code and string functions. This is accomplished by
building little endian versions of those support files and link them into
a static library which is used by the inner stub build.

Signed-off-by: Ard Biesheuvel ard.biesheu...@linaro.org
---
 arch/arm64/kernel/Makefile  |  7 +++-
 arch/arm64/kernel/efi-entry.S   | 42 +--
 arch/arm64/kernel/efistub-le/Makefile   | 52 +
 arch/arm64/kernel/efistub-le/efi-le-entry.S | 13 
 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 +++
 drivers/firmware/efi/libstub/fdt.c  |  4 +++
 8 files changed, 173 insertions(+), 12 deletions(-)
 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/kernel/Makefile b/arch/arm64/kernel/Makefile
index afaeb734295a..942cd042e93e 100644
--- a/arch/arm64/kernel/Makefile
+++ b/arch/arm64/kernel/Makefile
@@ -27,7 +27,12 @@ arm64-obj-$(CONFIG_HAVE_HW_BREAKPOINT)   += 
hw_breakpoint.o
 arm64-obj-$(CONFIG_ARM64_CPU_SUSPEND)  += sleep.o suspend.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)
 
 obj-y  += $(arm64-obj-y) vdso/
 obj-m  += $(arm64-obj-m)
diff --git a/arch/arm64/kernel/efi-entry.S b/arch/arm64/kernel/efi-entry.S
index a0016d3a17da..89f34bb86cfd 100644
--- a/arch/arm64/kernel/efi-entry.S
+++ b/arch/arm64/kernel/efi-entry.S
@@ -34,8 +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(revw8, w8  )
+STUB_BE(revw9, 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(revx23, x23)   // x23: stext offset
+
+   /*
+* Get a pointer to linux_banner in the outer image and store it
+* in this image.
+*/
+   adrpx4, le_linux_banner
+   str x9, [x4, #:lo12:le_linux_banner]
+#else
+   adrpx8, _text
+   add x8, x8, #:lo12:_text// x8: base of Image
+   adrpx9, _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.
 * x0 and x1 are already set up by firmware. Current runtime
@@ -45,8 +71,6 @@ ENTRY(efi_stub_entry)
 * efi_system_table_t *sys_table,
 * unsigned long *image_addr) ;
 */
-   adrpx8, _text
-   add x8, x8, #:lo12:_text
add x2, sp, 16
str x8, [x2]
bl  efi_entry
@@ -61,18 +85,13 @@ 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
 
/*
 * Flush dcache covering current runtime addresses
 * of kernel text/data. Then flush all of icache.
 */
-   adrpx1, _text
-   add x1, x1, #:lo12:_text
-   adrpx2, _edata
-   add x2, x2, #:lo12:_edata
-   sub x1, x2, x1
+   mov x1, x22
 
bl  __flush_dcache_area
ic  ialluis
@@ -103,7 +122,8 @@ ENTRY(efi_stub_entry)
 
 efi_load_fail:
mov x0, #EFI_LOAD_ERROR
-   ldp

Re: [PATCH v2] arm64/efi: efistub: jump to 'stext' directly, not through the header

2014-07-21 Thread Ard Biesheuvel
On 17 July 2014 16:09, Mark Salter msal...@redhat.com wrote:
 On Wed, 2014-07-16 at 23:13 +0200, Ard Biesheuvel wrote:
 On 16 July 2014 23:03, Mark Salter msal...@redhat.com wrote:
  On Wed, 2014-07-16 at 22:38 +0200, Ard Biesheuvel wrote:
  On 16 July 2014 21:45, Mark Salter msal...@redhat.com wrote:
   On Wed, 2014-07-16 at 16:53 +0100, Mark Rutland wrote:
   On Wed, Jul 16, 2014 at 03:51:37PM +0100, Mark Salter wrote:
On Tue, 2014-07-15 at 12:58 +0200, Ard Biesheuvel wrote:
 After the EFI stub has done its business, it jumps into the kernel 
 by branching
 to offset #0 of the loaded Image, which is where it expects to 
 find the header
 containing a 'branch to stext' instruction.

 However, the header is not covered by any PE/COFF section, so the 
 header may
 not actually be loaded at the expected offset. So instead, jump to 
 'stext'
 directly, which is at the base of the PE/COFF .text section, by 
 supplying a
 symbol 'stext_offset' to efi-entry.o which contains the relative 
 offset of
 stext into the Image. Also replace other open coded calculations 
 of the same
 value with a reference to 'stext_offset'
   
Have you actually seen a situation where the header isn't there?
Isn't the kernel header actually part of the pe/coff file and
firmware loads the whole file into RAM?
  
   From my understanding of Ard's earlier comments, this part isn't
   guaranteed per the UEFI spec.
  
   I would rather we weren't relying on implementation details.
  
  
   Could be. I didn't see anything about it in the UEFI spec, but I
   probably wasn't exhaustive in my search. In any case, there's at
   least one other place broken if the kernel header isn't included
   in the loaded image.
  
 
  I have not been able to find anything in the PE/COFF documents that
  tells you what to put in memory areas that are not covered by a
  section. Expecting the header to be there is indeed relying on an
  implementation detail, which seems risky.
  And indeed, if there are any other (non EFI related) uses of header
  fields in the kernel, it would be good to have a look at those well,
 
  I think we need to come up with a loader which does load an image
  without kernel header so that we can test. Otherwise, we'll probably
  end up with buggy code anyway. The stub code assumes the the loaded
  image pointed to by the system table is the whole image. Seems like
  we'd need to add code to determine if it is whole kernel image or
  image without initial header. Stub would have to handle both cases.
  For instance, one case would want image placed at 2MiB+TEXT_OFFSET,
  other case would want 2MiB+TEXT_OFFSET+sizeof(kernel header).
 

 No, this has nothing to do with misaligned data.

 The PE/COFF .text section does not start at virtual offset #0 but at
 virtual offset 'stext - efi_head'.
 In other words, there is a hole in the virtual image where the header
 is supposed to be.
 So if there is no PE/COFF section describing what data should be put
 at offset #0 by the loader, we can't assume the header is there, even
 if ImageBase does start at #0

 I get that. You're supposing UEFI will always allocate memory for the
 full image, but only sometimes copy the PE/COFF headers. I can see your
 point from a PE/COFF perspective, but not so much from the UEFI spec
 perspective where the language leads me to think it treats the PE/COFF
 images as one unit wrt loading. In any case, it really isn't worth
 arguing about. I don't have any objection to the patch since it won't
 break anything from my perspective and it'll protect against breakage
 which could possibly occur with some firmware implementations.


OK, thanks.

-- 
Ard.
--
To unsubscribe from this list: send the line unsubscribe linux-efi in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html