2014-01-10 16:30:28

by Roy Franz

[permalink] [raw]
Subject: [PATCH V6 0/8] Add ARM EFI stub

This patch series adds EFI stub support for the ARM architecture. The
stub for ARM is implemented in a similar manner to x86 in that it is a
shim layer between EFI and the normal zImage/bzImage boot process, and
that an image with the stub configured is bootable as both a zImage and
EFI application. This patchset adds common code that is shared with
the ARM64 EFI stub.

This patch depends on Leif Lindholm's ARM v7 runtime services patchset, which
in turn depends on Mark Salter's early_io_remap() patchset. This EFI stub
patchset can be tested without those by simply modifying the Kconfig for
EFI_STUB to not depend on EFI. The kernel will boot using the stub,
however no EFI support will be available in the kernel.

I have addressed all the feedback I have recieved to date, and I am hoping
that this patchset is acceptable for merging into 3.14. It has been
functionally stable for some time, and provides useful functionality.
Further consolidation of the ARM/ARM64 stubs planned as part of the
ongoing development of the stubs and supporting tools for both
architectures (getting the FDT from a UEFI configuration table, using UEFI
memory map instead of FDT for memory description.)



Changes since v5:
* Move more code dealing with the Device tree to common code shared by
ARM and ARM64.
* move formatting of informative and error messaging to common code to
harmonize formatting between ARM/ARM64 stubs.

Changes since v4:
* Common and x86 EFI stub changes that this patch depends on were merged
in 3.13.
* Updated FDT bindings to match agreed upon bindings in Leif's runtime
services patchset. This includes adding the kernel_banner version string,
and changing how the EFI memory map is passed. The EFI memory map is now
allocated as EFI_RUNTIME_SERVICES_DATA since it may be passed to the kernel.
The FDT bindings for arm/arm64 are identical.
* Added space in PE/COFF header for signature to allow signing of the image
for EFI secure boot.
* Moved shared FDT function to drivers/firmware/efi/fdt.c. This will be shared
with arm64. (Mark Salter has a patchset for the arm64 stub.)


Changes since v3:
* Common and x86 EFI stub changes have been broken out and submitted separately.
This patch series depends on the "[PATCH V5 00/18] ARM EFI stub common code"
series as merged by Matt Fleming. (Patch 10 of that series omitted)
* Re-added -fno-stack-protector. Needed for compilation with
CONFIG_CC_STACKPROTECTOR option. Cannot easily add support for stack
protection since there are no functions in stub that never return, which
is a requirement for use. (x86 stub also disables stack protector.)
Note that even in the absense of -fno-stack-protector, stack protection
was never present in the decompressor, as the required functions are not
implemented.
* Fixed long summaries in commit messages.
* Further cleanups of assembly in head.S


Changes since v2:
* Now depends on "arm: Add [U]EFI runtime services support" patches by [email protected].
The EFI memory map is the only memory map passed to the kernel, so EFI support
is now required.
* remove "-fno-stack-protector" from decompressor Makefile. The current code doesn't
trigger the stack protection, so the decompressor now compiles with it still
on. Note that there has never been any stack protection in the decompressor
since the stack usage doesn't trigger the heuristic in GCC, so right now
the "-fno-stack-protector" is a noop.
* Changed EFI command line handling to not have a fixed limit.
* Change FDT memory allocation to retry with a larger allocation if
first educated guess is inadequate.
* Correctly set 'SizeOfCode' in PE/COFF header.
* Reviewed ".setup" section that is in x86 PE/COFF header. This is used for x86
to account for code that is not in the .text section. We don't need this
for ARM, as all of our code is in the .text section, or in the PE/COFF header
itself.
* Moved EFI_STUB_ERROR #define to header file to share between stub C and ASM.
* Variety of cleanups and fixes in head.S.
* Changed update_fdt_and_exit_boot() to just update the device tree, and
renamed appropriately. Memory allocations moved out of this function as
well, which enables the retries if the initial FDT size is too small.
Note that in order to do the retried allocations, the original FDT and
command line memory regions are left allocated. This is OK since the kernel
has the memory map and will free these allocations along with the initrd
and new fdt allocations.
* Added prefix to all prints, reduced number of prints, and reviewed all
messages.
* Change mixed usage of dtb/fdt to all be fdt or "device tree" in efi-stub.c
* remove unnecessary zimage_size variable from relocate_kernel()
* correct return types on EFI functions - should be efi_status_t, not int.
Roy Franz (8):
efi-stub.txt updates for ARM
Add shared printk wrapper for consistent prefixing
Add helper function to get and convert EFI command line
Add shared FDT related functions for ARM/ARM64
Add strstr to compressed string.c for ARM.
Add EFI stub for ARM
Disable stack protection for decompressor/stub
Add config EFI_STUB for ARM to Kconfig

Documentation/efi-stub.txt | 27 +++-
arch/arm/Kconfig | 11 ++
arch/arm/boot/compressed/Makefile | 17 ++-
arch/arm/boot/compressed/efi-header.S | 117 +++++++++++++++++
arch/arm/boot/compressed/efi-stub.c | 214 ++++++++++++++++++++++++++++++
arch/arm/boot/compressed/efi-stub.h | 5 +
arch/arm/boot/compressed/head.S | 83 +++++++++++-
arch/arm/boot/compressed/string.c | 21 +++
drivers/firmware/efi/efi-stub-helper.c | 55 ++++++--
drivers/firmware/efi/fdt.c | 225 ++++++++++++++++++++++++++++++++
10 files changed, 748 insertions(+), 27 deletions(-)
create mode 100644 arch/arm/boot/compressed/efi-header.S
create mode 100644 arch/arm/boot/compressed/efi-stub.c
create mode 100644 arch/arm/boot/compressed/efi-stub.h
create mode 100644 drivers/firmware/efi/fdt.c

--
1.7.10.4


2014-01-10 16:30:36

by Roy Franz

[permalink] [raw]
Subject: [PATCH V6 2/8] Add shared printk wrapper for consistent prefixing

Add a wrapper for printk to standardize the prefix for informational and
error messages from the EFI stub.

Signed-off-by: Roy Franz <[email protected]>
---
drivers/firmware/efi/efi-stub-helper.c | 25 ++++++++++++++-----------
1 file changed, 14 insertions(+), 11 deletions(-)

diff --git a/drivers/firmware/efi/efi-stub-helper.c b/drivers/firmware/efi/efi-stub-helper.c
index b6bffbf..eb5d2eb 100644
--- a/drivers/firmware/efi/efi-stub-helper.c
+++ b/drivers/firmware/efi/efi-stub-helper.c
@@ -45,6 +45,9 @@ static void efi_printk(efi_system_table_t *sys_table_arg, char *str)
}
}

+#define pr_efi(sys_table, msg) efi_printk(sys_table, "EFI stub: "msg)
+#define pr_efi_err(sys_table, msg) efi_printk(sys_table, "EFI stub: ERROR: "msg)
+

static efi_status_t efi_get_memory_map(efi_system_table_t *sys_table_arg,
efi_memory_desc_t **map,
@@ -324,7 +327,7 @@ static efi_status_t handle_cmdline_files(efi_system_table_t *sys_table_arg,
nr_files * sizeof(*files),
(void **)&files);
if (status != EFI_SUCCESS) {
- efi_printk(sys_table_arg, "Failed to alloc mem for file handle list\n");
+ pr_efi_err(sys_table_arg, "Failed to alloc mem for file handle list\n");
goto fail;
}

@@ -376,13 +379,13 @@ static efi_status_t handle_cmdline_files(efi_system_table_t *sys_table_arg,
image->device_handle, &fs_proto,
(void **)&io);
if (status != EFI_SUCCESS) {
- efi_printk(sys_table_arg, "Failed to handle fs_proto\n");
+ pr_efi_err(sys_table_arg, "Failed to handle fs_proto\n");
goto free_files;
}

status = efi_call_phys2(io->open_volume, io, &fh);
if (status != EFI_SUCCESS) {
- efi_printk(sys_table_arg, "Failed to open volume\n");
+ pr_efi_err(sys_table_arg, "Failed to open volume\n");
goto free_files;
}
}
@@ -390,7 +393,7 @@ static efi_status_t handle_cmdline_files(efi_system_table_t *sys_table_arg,
status = efi_call_phys5(fh->open, fh, &h, filename_16,
EFI_FILE_MODE_READ, (u64)0);
if (status != EFI_SUCCESS) {
- efi_printk(sys_table_arg, "Failed to open file: ");
+ pr_efi_err(sys_table_arg, "Failed to open file: ");
efi_char16_printk(sys_table_arg, filename_16);
efi_printk(sys_table_arg, "\n");
goto close_handles;
@@ -402,7 +405,7 @@ static efi_status_t handle_cmdline_files(efi_system_table_t *sys_table_arg,
status = efi_call_phys4(h->get_info, h, &info_guid,
&info_sz, NULL);
if (status != EFI_BUFFER_TOO_SMALL) {
- efi_printk(sys_table_arg, "Failed to get file info size\n");
+ pr_efi_err(sys_table_arg, "Failed to get file info size\n");
goto close_handles;
}

@@ -411,7 +414,7 @@ grow:
EFI_LOADER_DATA, info_sz,
(void **)&info);
if (status != EFI_SUCCESS) {
- efi_printk(sys_table_arg, "Failed to alloc mem for file info\n");
+ pr_efi_err(sys_table_arg, "Failed to alloc mem for file info\n");
goto close_handles;
}

@@ -427,7 +430,7 @@ grow:
efi_call_phys1(sys_table_arg->boottime->free_pool, info);

if (status != EFI_SUCCESS) {
- efi_printk(sys_table_arg, "Failed to get file info\n");
+ pr_efi_err(sys_table_arg, "Failed to get file info\n");
goto close_handles;
}

@@ -446,13 +449,13 @@ grow:
status = efi_high_alloc(sys_table_arg, file_size_total, 0x1000,
&file_addr, max_addr);
if (status != EFI_SUCCESS) {
- efi_printk(sys_table_arg, "Failed to alloc highmem for files\n");
+ pr_efi_err(sys_table_arg, "Failed to alloc highmem for files\n");
goto close_handles;
}

/* We've run out of free low memory. */
if (file_addr > max_addr) {
- efi_printk(sys_table_arg, "We've run out of free low memory\n");
+ pr_efi_err(sys_table_arg, "We've run out of free low memory\n");
status = EFI_INVALID_PARAMETER;
goto free_file_total;
}
@@ -473,7 +476,7 @@ grow:
&chunksize,
(void *)addr);
if (status != EFI_SUCCESS) {
- efi_printk(sys_table_arg, "Failed to read file\n");
+ pr_efi_err(sys_table_arg, "Failed to read file\n");
goto free_file_total;
}
addr += chunksize;
@@ -558,7 +561,7 @@ static efi_status_t efi_relocate_kernel(efi_system_table_t *sys_table_arg,
&new_addr);
}
if (status != EFI_SUCCESS) {
- efi_printk(sys_table_arg, "ERROR: Failed to allocate usable memory for kernel.\n");
+ pr_efi_err(sys_table_arg, "ERROR: Failed to allocate usable memory for kernel.\n");
return status;
}

--
1.7.10.4

2014-01-10 16:30:47

by Roy Franz

[permalink] [raw]
Subject: [PATCH V6 6/8] Add EFI stub for ARM

This patch adds EFI stub support for the ARM Linux kernel. The EFI stub
operates similarly to the x86 stub: it is a shim between the EFI firmware
and the normal zImage entry point, and sets up the environment that the
zImage is expecting. This includes loading the initrd (optionaly) and
device tree from the system partition based on the kernel command line.
The stub updates the device tree as necessary, adding entries for EFI
runtime services. The PE/COFF "MZ" header at offset 0 results in the
first instruction being an add that corrupts r5, which is not used by
the zImage interface.

Signed-off-by: Roy Franz <[email protected]>
Acked-by: Grant Likely <[email protected]>
---
arch/arm/boot/compressed/Makefile | 15 ++-
arch/arm/boot/compressed/efi-header.S | 117 ++++++++++++++++++
arch/arm/boot/compressed/efi-stub.c | 214 +++++++++++++++++++++++++++++++++
arch/arm/boot/compressed/efi-stub.h | 5 +
arch/arm/boot/compressed/head.S | 83 ++++++++++++-
5 files changed, 426 insertions(+), 8 deletions(-)
create mode 100644 arch/arm/boot/compressed/efi-header.S
create mode 100644 arch/arm/boot/compressed/efi-stub.c
create mode 100644 arch/arm/boot/compressed/efi-stub.h

diff --git a/arch/arm/boot/compressed/Makefile b/arch/arm/boot/compressed/Makefile
index e7190bb..c0c7fee 100644
--- a/arch/arm/boot/compressed/Makefile
+++ b/arch/arm/boot/compressed/Makefile
@@ -99,11 +99,22 @@ libfdt_objs := $(addsuffix .o, $(basename $(libfdt)))
$(addprefix $(obj)/,$(libfdt) $(libfdt_hdrs)): $(obj)/%: $(srctree)/scripts/dtc/libfdt/%
$(call cmd,shipped)

-$(addprefix $(obj)/,$(libfdt_objs) atags_to_fdt.o): \
+$(addprefix $(obj)/,$(libfdt_objs) atags_to_fdt.o efi-stub.o): \
$(addprefix $(obj)/,$(libfdt_hdrs))

ifeq ($(CONFIG_ARM_ATAG_DTB_COMPAT),y)
-OBJS += $(libfdt_objs) atags_to_fdt.o
+OBJS += atags_to_fdt.o
+USE_LIBFDT = y
+endif
+
+ifeq ($(CONFIG_EFI_STUB),y)
+CFLAGS_efi-stub.o += -DTEXT_OFFSET=$(TEXT_OFFSET)
+OBJS += efi-stub.o
+USE_LIBFDT = y
+endif
+
+ifeq ($(USE_LIBFDT),y)
+OBJS += $(libfdt_objs)
endif

targets := vmlinux vmlinux.lds \
diff --git a/arch/arm/boot/compressed/efi-header.S b/arch/arm/boot/compressed/efi-header.S
new file mode 100644
index 0000000..dbb7101
--- /dev/null
+++ b/arch/arm/boot/compressed/efi-header.S
@@ -0,0 +1,117 @@
+@ Copyright (C) 2013 Linaro Ltd; <[email protected]>
+@
+@ This file contains the PE/COFF header that is part of the
+@ EFI stub.
+@
+
+ .org 0x3c
+ @
+ @ The PE header can be anywhere in the file, but for
+ @ simplicity we keep it together with the MSDOS header
+ @ The offset to the PE/COFF header needs to be at offset
+ @ 0x3C in the MSDOS header.
+ @ The only 2 fields of the MSDOS header that are used are this
+ @ PE/COFF offset, and the "MZ" bytes at offset 0x0.
+ @
+ .long pe_header @ Offset to the PE header.
+
+ .align 3
+pe_header:
+ .ascii "PE"
+ .short 0
+
+coff_header:
+ .short 0x01c2 @ ARM or Thumb
+ .short 2 @ nr_sections
+ .long 0 @ TimeDateStamp
+ .long 0 @ PointerToSymbolTable
+ .long 1 @ NumberOfSymbols
+ .short section_table - optional_header @ SizeOfOptionalHeader
+ .short 0x306 @ Characteristics.
+ @ IMAGE_FILE_32BIT_MACHINE |
+ @ IMAGE_FILE_DEBUG_STRIPPED |
+ @ IMAGE_FILE_EXECUTABLE_IMAGE |
+ @ IMAGE_FILE_LINE_NUMS_STRIPPED
+
+optional_header:
+ .short 0x10b @ PE32 format
+ .byte 0x02 @ MajorLinkerVersion
+ .byte 0x14 @ MinorLinkerVersion
+
+ .long _edata - efi_stub_entry @ SizeOfCode
+
+ .long 0 @ SizeOfInitializedData
+ .long 0 @ SizeOfUninitializedData
+
+ .long efi_stub_entry @ AddressOfEntryPoint
+ .long efi_stub_entry @ BaseOfCode
+ .long 0 @ data
+
+extra_header_fields:
+ .long 0 @ ImageBase
+ .long 0x20 @ SectionAlignment
+ .long 0x8 @ FileAlignment
+ .short 0 @ MajorOperatingSystemVersion
+ .short 0 @ MinorOperatingSystemVersion
+ .short 0 @ MajorImageVersion
+ .short 0 @ MinorImageVersion
+ .short 0 @ MajorSubsystemVersion
+ .short 0 @ MinorSubsystemVersion
+ .long 0 @ Win32VersionValue
+
+ .long _edata @ SizeOfImage
+
+ @ Everything before the entry point is considered part of the header
+ .long efi_stub_entry @ SizeOfHeaders
+ .long 0 @ CheckSum
+ .short 0xa @ Subsystem (EFI application)
+ .short 0 @ DllCharacteristics
+ .long 0 @ SizeOfStackReserve
+ .long 0 @ SizeOfStackCommit
+ .long 0 @ SizeOfHeapReserve
+ .long 0 @ SizeOfHeapCommit
+ .long 0 @ LoaderFlags
+ .long 0x6 @ NumberOfRvaAndSizes
+
+ .quad 0 @ ExportTable
+ .quad 0 @ ImportTable
+ .quad 0 @ ResourceTable
+ .quad 0 @ ExceptionTable
+ .quad 0 @ CertificationTable
+ .quad 0 @ BaseRelocationTable
+ # Section table
+section_table:
+
+ #
+ # The EFI application loader requires a relocation section
+ # because EFI applications must be relocatable. This is a
+ # dummy section as far as we are concerned.
+ #
+ .ascii ".reloc"
+ .byte 0
+ .byte 0 @ end of 0 padding of section name
+ .long 0
+ .long 0
+ .long 0 @ SizeOfRawData
+ .long 0 @ PointerToRawData
+ .long 0 @ PointerToRelocations
+ .long 0 @ PointerToLineNumbers
+ .short 0 @ NumberOfRelocations
+ .short 0 @ NumberOfLineNumbers
+ .long 0x42100040 @ Characteristics (section flags)
+
+
+ .ascii ".text"
+ .byte 0
+ .byte 0
+ .byte 0 @ end of 0 padding of section name
+ .long _edata - efi_stub_entry @ VirtualSize
+ .long efi_stub_entry @ VirtualAddress
+ .long _edata - efi_stub_entry @ SizeOfRawData
+ .long efi_stub_entry @ 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)
diff --git a/arch/arm/boot/compressed/efi-stub.c b/arch/arm/boot/compressed/efi-stub.c
new file mode 100644
index 0000000..7d5feb3
--- /dev/null
+++ b/arch/arm/boot/compressed/efi-stub.c
@@ -0,0 +1,214 @@
+/*
+ * linux/arch/arm/boot/compressed/efi-stub.c
+ *
+ * Copyright (C) 2013 Linaro Ltd; <[email protected]>
+ *
+ * This file implements the EFI boot stub for the ARM kernel
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+#include <linux/efi.h>
+#include <libfdt.h>
+#include "efi-stub.h"
+
+/* EFI function call wrappers. These are not required for
+ * ARM, but wrappers are required for X86 to convert between
+ * ABIs. These wrappers are provided to allow code sharing
+ * between X86 and ARM. Since these wrappers directly invoke the
+ * EFI function pointer, the function pointer type must be properly
+ * defined, which is not the case for X86 One advantage of this is
+ * it allows for type checking of arguments, which is not
+ * possible with the X86 wrappers.
+ */
+#define efi_call_phys0(f) f()
+#define efi_call_phys1(f, a1) f(a1)
+#define efi_call_phys2(f, a1, a2) f(a1, a2)
+#define efi_call_phys3(f, a1, a2, a3) f(a1, a2, a3)
+#define efi_call_phys4(f, a1, a2, a3, a4) f(a1, a2, a3, a4)
+#define efi_call_phys5(f, a1, a2, a3, a4, a5) f(a1, a2, a3, a4, a5)
+
+/* The maximum uncompressed kernel size is 32 MBytes, so we will reserve
+ * that for the decompressed kernel. We have no easy way to tell what
+ * the actuall size of code + data the uncompressed kernel will use.
+ */
+#define MAX_UNCOMP_KERNEL_SIZE 0x02000000
+
+/* The kernel zImage should be located between 32 Mbytes
+ * and 128 MBytes from the base of DRAM. The min
+ * address leaves space for a maximal size uncompressed image,
+ * and the max address is due to how the zImage decompressor
+ * picks a destination address.
+ */
+#define ZIMAGE_OFFSET_LIMIT 0x08000000
+#define MIN_ZIMAGE_OFFSET MAX_UNCOMP_KERNEL_SIZE
+
+/* Include shared EFI stub code, and required headers. */
+#include "../../../../include/generated/compile.h"
+#include "../../../../include/generated/utsrelease.h"
+#include "../../../../drivers/firmware/efi/efi-stub-helper.c"
+#include "../../../../drivers/firmware/efi/fdt.c"
+
+
+int efi_entry(void *handle, efi_system_table_t *sys_table,
+ unsigned long *zimage_addr)
+{
+ efi_loaded_image_t *image;
+ int status;
+ unsigned long nr_pages;
+ const struct fdt_region *region;
+
+ void *fdt;
+ int err;
+ int node;
+ unsigned long zimage_size = 0;
+ unsigned long dram_base;
+ /* addr/point and size pairs for memory management*/
+ unsigned long initrd_addr;
+ unsigned long initrd_size = 0;
+ unsigned long fdt_addr;
+ unsigned long fdt_size = 0;
+ efi_physical_addr_t kernel_reserve_addr;
+ unsigned long kernel_reserve_size = 0;
+ char *cmdline_ptr;
+ int cmdline_size = 0;
+
+
+ unsigned long new_fdt_addr;
+
+ /* Check if we were booted by the EFI firmware */
+ if (sys_table->hdr.signature != EFI_SYSTEM_TABLE_SIGNATURE)
+ goto fail;
+
+ pr_efi(sys_table, "Booting Linux using EFI stub.\n");
+
+ /* Get the command line from EFI, using the LOADED_IMAGE
+ * protocol. We are going to copy the command line into the
+ * device tree, so this memory just needs to not conflict with
+ * boot protocol requirements.
+ */
+ efi_get_cmdline(sys_table, &image, handle, &cmdline_ptr);
+ if (!cmdline_ptr) {
+ pr_efi_err(sys_table, "Unable to allocate memory for command line.\n");
+ goto fail;
+ }
+
+ /* We first load the device tree, as we need to get the base address of
+ * DRAM from the device tree. The zImage, device tree, and initrd
+ * have address restrictions that are relative to the base of DRAM.
+ */
+ status = handle_cmdline_files(sys_table, image, cmdline_ptr, "dtb=",
+ 0xffffffff, &fdt_addr, &fdt_size);
+ if (status != EFI_SUCCESS) {
+ pr_efi_err(sys_table, "Unable to load device tree blob.\n");
+ goto fail_free_cmdline;
+ }
+
+ err = fdt_check_header((void *)fdt_addr);
+ if (err != 0) {
+ pr_efi_err(sys_table, "Device tree header not valid.\n");
+ goto fail_free_fdt;
+ }
+ if (fdt_totalsize((void *)fdt_addr) > fdt_size) {
+ pr_efi_err(sys_table, "Incomplete device tree.\n");
+ goto fail_free_fdt;
+
+ }
+
+
+ /* Look up the base of DRAM from the device tree. */
+ fdt = (void *)fdt_addr;
+ node = fdt_subnode_offset(fdt, 0, "memory");
+ region = fdt_getprop(fdt, node, "reg", NULL);
+ if (region) {
+ dram_base = fdt64_to_cpu(region->base);
+ } else {
+ /* There is no way to get amount or addresses of physical
+ * memory installed using EFI calls. If the device tree
+ * we read from disk doesn't have this, there is no way
+ * for us to construct this informaion.
+ */
+ pr_efi_err(sys_table, "No 'memory' node in device tree.\n");
+ goto fail_free_fdt;
+ }
+
+ /* Reserve memory for the uncompressed kernel image. This is
+ * all that prevents any future allocations from conflicting
+ * with the kernel. Since we can't tell from the compressed
+ * image how much DRAM the kernel actually uses (due to BSS
+ * size uncertainty) we allocate the maximum possible size.
+ */
+ kernel_reserve_addr = dram_base;
+ kernel_reserve_size = MAX_UNCOMP_KERNEL_SIZE;
+ nr_pages = round_up(kernel_reserve_size, EFI_PAGE_SIZE) / EFI_PAGE_SIZE;
+ status = efi_call_phys4(sys_table->boottime->allocate_pages,
+ EFI_ALLOCATE_ADDRESS, EFI_LOADER_DATA,
+ nr_pages, &kernel_reserve_addr);
+ if (status != EFI_SUCCESS) {
+ pr_efi_err(sys_table, "Unable to allocate memory for uncompressed kernel.\n");
+ goto fail_free_fdt;
+ }
+
+ /* Relocate the zImage, if required. ARM doesn't have a
+ * preferred address, so we set it to 0, as we want to allocate
+ * as low in memory as possible.
+ */
+ zimage_size = image->image_size;
+ status = efi_relocate_kernel(sys_table, zimage_addr, zimage_size,
+ zimage_size, 0, 0);
+ if (status != EFI_SUCCESS) {
+ pr_efi_err(sys_table, "Failed to relocate kernel.\n");
+ goto fail_free_kernel_reserve;
+ }
+
+ /* Check to see if we were able to allocate memory low enough
+ * in memory.
+ */
+ if (*zimage_addr + zimage_size > dram_base + ZIMAGE_OFFSET_LIMIT) {
+ pr_efi_err(sys_table, "Failed to relocate kernel, no low memory available.\n");
+ goto fail_free_zimage;
+ }
+ status = handle_cmdline_files(sys_table, image, cmdline_ptr, "initrd=",
+ dram_base + ZIMAGE_OFFSET_LIMIT,
+ &initrd_addr, &initrd_size);
+ if (status != EFI_SUCCESS) {
+ pr_efi_err(sys_table, "Unable to load initrd.\n");
+ goto fail_free_zimage;
+ }
+
+
+ /*
+ * Now we need to allocate new memory for the final FDT so that
+ * we can add EFI and command line related fields to it.
+ * This function will allocate the new FDT and update it,
+ * retrying memory allocations if they are too small.
+ * It also call
+ */
+ status = allocate_new_fdt_and_exit_boot(sys_table, handle,
+ &new_fdt_addr,
+ dram_base + ZIMAGE_OFFSET_LIMIT,
+ initrd_addr, initrd_size,
+ cmdline_ptr, fdt_addr,
+ fdt_size);
+ if (status == EFI_SUCCESS)
+ return new_fdt_addr;
+
+ efi_free(sys_table, initrd_size, initrd_addr);
+
+fail_free_zimage:
+ efi_free(sys_table, zimage_size, *zimage_addr);
+
+fail_free_kernel_reserve:
+ efi_free(sys_table, kernel_reserve_size, kernel_reserve_addr);
+
+fail_free_fdt:
+ efi_free(sys_table, fdt_size, fdt_addr);
+
+fail_free_cmdline:
+ efi_free(sys_table, cmdline_size, (u32)cmdline_ptr);
+
+fail:
+ return EFI_STUB_ERROR;
+}
diff --git a/arch/arm/boot/compressed/efi-stub.h b/arch/arm/boot/compressed/efi-stub.h
new file mode 100644
index 0000000..0fe9376
--- /dev/null
+++ b/arch/arm/boot/compressed/efi-stub.h
@@ -0,0 +1,5 @@
+#ifndef _ARM_EFI_STUB_H
+#define _ARM_EFI_STUB_H
+/* Error code returned to ASM code instead of valid FDT address. */
+#define EFI_STUB_ERROR (~0)
+#endif
diff --git a/arch/arm/boot/compressed/head.S b/arch/arm/boot/compressed/head.S
index 066b034..eeb394c 100644
--- a/arch/arm/boot/compressed/head.S
+++ b/arch/arm/boot/compressed/head.S
@@ -10,6 +10,7 @@
*/
#include <linux/linkage.h>
#include <asm/assembler.h>
+#include "efi-stub.h"

.arch armv7-a
/*
@@ -120,22 +121,93 @@
*/
.align
.arm @ Always enter in ARM state
+ .text
start:
.type start,#function
- .rept 7
+#ifdef CONFIG_EFI_STUB
+ @ Magic MSDOS signature for PE/COFF + ADD opcode
+ @ the EFI stub only supports little endian, as the EFI functions
+ @ it invokes are little endian.
+ .word 0x62805a4d
+#else
+ mov r0, r0
+#endif
+ .rept 5
mov r0, r0
.endr
- ARM( mov r0, r0 )
- ARM( b 1f )
- THUMB( adr r12, BSYM(1f) )
- THUMB( bx r12 )
+
+ adrl r12, BSYM(zimage_continue)
+ ARM( mov pc, r12 )
+ THUMB( bx r12 )
+ @ zimage_continue will be in ARM or thumb mode as configured

.word 0x016f2818 @ Magic numbers to help the loader
.word start @ absolute load/run zImage address
.word _edata @ zImage end address
+
+#ifdef CONFIG_EFI_STUB
+ @ Portions of the MSDOS file header must be at offset
+ @ 0x3c from the start of the file. All PE/COFF headers
+ @ are kept contiguous for simplicity.
+#include "efi-header.S"
+
+efi_stub_entry:
+ @ The EFI stub entry point is not at a fixed address, however
+ @ this address must be set in the PE/COFF header.
+ @ EFI entry point is in A32 mode, switch to T32 if configured.
+ THUMB( adr r12, BSYM(1f) )
+ THUMB( bx r12 )
THUMB( .thumb )
1:
ARM_BE8( setend be ) @ go BE8 if compiled for BE8
+ @ Save lr on stack for possible return to EFI firmware.
+ @ Don't care about fp, but need 64 bit alignment....
+ stmfd sp!, {fp, lr}
+
+ @ allocate space on stack for passing current zImage address
+ @ and for the EFI stub to return of new entry point of
+ @ zImage, as EFI stub may copy the kernel. Pointer address
+ @ is passed in r2. r0 and r1 are passed through from the
+ @ EFI firmware to efi_entry
+ adr r3, start
+ str r3, [sp, #-8]!
+ mov r2, sp @ pass pointer in r2
+ bl efi_entry
+ ldr r3, [sp], #8 @ get new zImage address from stack
+
+ @ Check for error return from EFI stub. r0 has FDT address
+ @ or EFI_STUB_ERROR error code.
+ cmp r0, #EFI_STUB_ERROR
+ beq efi_load_fail
+
+ @ Save return values of efi_entry
+ stmfd sp!, {r0, r3}
+ bl cache_clean_flush
+ bl cache_off
+ ldmfd sp!, {r0, r3}
+
+ @ Set parameters for booting zImage according to boot protocol
+ @ put FDT address in r2, it was returned by efi_entry()
+ @ r1 is FDT machine type, and r0 needs to be 0
+ mov r2, r0
+ mov r1, #0xFFFFFFFF
+ mov r0, #0
+
+ @ Branch to (possibly) relocated zImage that is in r3
+ @ Make sure we are in A32 mode, as zImage requires
+ THUMB( bx r3 )
+ ARM( mov pc, r3 )
+
+efi_load_fail:
+ @ Return EFI_LOAD_ERROR to EFI firmware on error.
+ @ Switch back to ARM mode for EFI is done based on
+ @ return address on stack in case we are in THUMB mode
+ ldr r0, =0x80000001
+ ldmfd sp!, {fp, pc} @ put lr from stack into pc
+#endif
+
+ THUMB( .thumb )
+zimage_continue:
mrs r9, cpsr
#ifdef CONFIG_ARM_VIRT_EXT
bl __hyp_stub_install @ get into SVC mode, reversibly
@@ -168,7 +240,6 @@ not_angel:
* by the linker here, but it should preserve r7, r8, and r9.
*/

- .text

#ifdef CONFIG_AUTO_ZRELADDR
@ determine final kernel image address
--
1.7.10.4

2014-01-10 16:30:40

by Roy Franz

[permalink] [raw]
Subject: [PATCH V6 5/8] Add strstr to compressed string.c for ARM.

The shared efi-stub-helper.c functions require a strstr implementation.
The EFI stub is part of the decompressor, so it does not use the kernel
strstr() implementation. This patch adds a strstr() implementation to
the string.c file for the decompressor, with the implementation copied
from the arch/x86/boot/string.c file used by the x86 decompressor.

Signed-off-by: Roy Franz <[email protected]>
Reviewed-by: Grant Likely <[email protected]>
---
arch/arm/boot/compressed/string.c | 21 +++++++++++++++++++++
1 file changed, 21 insertions(+)

diff --git a/arch/arm/boot/compressed/string.c b/arch/arm/boot/compressed/string.c
index 36e53ef..5397792 100644
--- a/arch/arm/boot/compressed/string.c
+++ b/arch/arm/boot/compressed/string.c
@@ -111,6 +111,27 @@ char *strchr(const char *s, int c)
return (char *)s;
}

+/**
+ * strstr - Find the first substring in a %NUL terminated string
+ * @s1: The string to be searched
+ * @s2: The string to search for
+ */
+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;
+}
#undef memset

void *memset(void *s, int c, size_t count)
--
1.7.10.4

2014-01-10 16:30:52

by Roy Franz

[permalink] [raw]
Subject: [PATCH V6 7/8] Disable stack protection for decompressor/stub

The ARM decompressor/EFI stub do not implement the functions
(__stack_chk_guard_setup, etc) that are required for support of
stack protection. The actual enablement of stack protection is
controlled by heuristics in GCC, which the code added for the EFI
stub triggers when CONFIG_STACKPROTECTOR is set. Even with
CONFIG_STACKPROTECTOR set, the decompressor was never compiled
with stack protection actually enabled. Adding -fno-stack-protector
to the decompressor/stub build keeps it building without stack
protection as it has always been built.
The x86 decompressor/stub is also built with -fno-stack-protector.

Signed-off-by: Roy Franz <[email protected]>
---
arch/arm/boot/compressed/Makefile | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/arm/boot/compressed/Makefile b/arch/arm/boot/compressed/Makefile
index c0c7fee..7974791 100644
--- a/arch/arm/boot/compressed/Makefile
+++ b/arch/arm/boot/compressed/Makefile
@@ -132,7 +132,7 @@ ORIG_CFLAGS := $(KBUILD_CFLAGS)
KBUILD_CFLAGS = $(subst -pg, , $(ORIG_CFLAGS))
endif

-ccflags-y := -fpic -mno-single-pic-base -fno-builtin -I$(obj)
+ccflags-y := -fpic -mno-single-pic-base -fno-builtin -fno-stack-protector -I$(obj)
asflags-y := -DZIMAGE

# Supply kernel BSS size to the decompressor via a linker symbol.
--
1.7.10.4

2014-01-10 16:31:15

by Roy Franz

[permalink] [raw]
Subject: [PATCH V6 8/8] Add config EFI_STUB for ARM to Kconfig

The previous patches have added the implementation of the EFI stub
functionality to the kernel, so now the Kconfig support is added
to enable it.

Signed-off-by: Roy Franz <[email protected]>
---
arch/arm/Kconfig | 11 +++++++++++
1 file changed, 11 insertions(+)

diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 1ab24cc..b650a38 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -1867,6 +1867,17 @@ config EFI
However, even with this option, the resultant kernel will
continue to boot on non-UEFI platforms.

+config EFI_STUB
+ bool "EFI stub support"
+ depends on EFI && !CPU_BIG_ENDIAN
+ ---help---
+ This kernel feature allows a zImage to be loaded directly by EFI
+ firmware without the use of a bootloader. A PE/COFF header is
+ added to the zImage in a way that makes the binary both a Linux
+ zImage and an PE/COFF executable that can be executed directly by
+ EFI firmware.
+ See Documentation/efi-stub.txt for more information.
+
config SECCOMP
bool
prompt "Enable seccomp to safely compute untrusted bytecode"
--
1.7.10.4

2014-01-10 16:32:16

by Roy Franz

[permalink] [raw]
Subject: [PATCH V6 3/8] Add helper function to get and convert EFI command line

Add an EFI stub helper function to retrieve the EFI command line using
the LOADED_IMAGE_PROTOCOL, and convert it to ASCII. This function will
be shared by the various EFI stub implementations.

Signed-off-by: Roy Franz <[email protected]>
---
drivers/firmware/efi/efi-stub-helper.c | 30 ++++++++++++++++++++++++++++++
1 file changed, 30 insertions(+)

diff --git a/drivers/firmware/efi/efi-stub-helper.c b/drivers/firmware/efi/efi-stub-helper.c
index eb5d2eb..f657456 100644
--- a/drivers/firmware/efi/efi-stub-helper.c
+++ b/drivers/firmware/efi/efi-stub-helper.c
@@ -637,3 +637,33 @@ static char *efi_convert_cmdline_to_ascii(efi_system_table_t *sys_table_arg,
*cmd_line_len = options_size;
return (char *)cmdline_addr;
}
+
+/*
+ * get the command line from EFI, using the LOADED_IMAGE
+ * protocol, and convert to ASCII.
+ *
+ */
+static void efi_get_cmdline(efi_system_table_t *sys_table,
+ efi_loaded_image_t **image,
+ void *handle, char **cmdline_ptr)
+{
+ efi_guid_t proto = LOADED_IMAGE_PROTOCOL_GUID;
+ efi_status_t status;
+ int cmdline_size;
+
+ status = efi_call_phys3(sys_table->boottime->handle_protocol,
+ handle, &proto, (void *)image);
+ if (status != EFI_SUCCESS) {
+ pr_efi_err(sys_table, "Failed to get handle for LOADED_IMAGE_PROTOCOL\n");
+ *cmdline_ptr = NULL;
+ return;
+ }
+
+ /*
+ * We are going to copy this into device tree, so we don't care where
+ * in memory it is.
+ */
+ *cmdline_ptr = efi_convert_cmdline_to_ascii(sys_table, *image,
+ &cmdline_size);
+
+}
--
1.7.10.4

2014-01-10 16:32:13

by Roy Franz

[permalink] [raw]
Subject: [PATCH V6 4/8] Add shared FDT related functions for ARM/ARM64

Both ARM and ARM64 stubs will update the device tree that they pass to
the kernel. In both cases they primarily need to add the same UEFI
related information, so the function can be shared. Create a new FDT
related file for this to avoid use of architecture #ifdefs in
efi-stub-helper.c.

Signed-off-by: Roy Franz <[email protected]>
Acked-by: Grant Likely <[email protected]>
---
drivers/firmware/efi/fdt.c | 225 ++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 225 insertions(+)
create mode 100644 drivers/firmware/efi/fdt.c

diff --git a/drivers/firmware/efi/fdt.c b/drivers/firmware/efi/fdt.c
new file mode 100644
index 0000000..e38f330
--- /dev/null
+++ b/drivers/firmware/efi/fdt.c
@@ -0,0 +1,225 @@
+/*
+ * FDT related Helper functions used by the EFI stub on multiple
+ * architectures. This should be #included by the EFI stub
+ * implementation files.
+ *
+ * Copyright 2013 Linaro Limited; author Roy Franz
+ *
+ * This file is part of the Linux kernel, and is made available
+ * under the terms of the GNU General Public License version 2.
+ *
+ */
+
+struct fdt_region {
+ u64 base;
+ u64 size;
+};
+
+static efi_status_t update_fdt(efi_system_table_t *sys_table, void *orig_fdt,
+ void *fdt, int new_fdt_size, char *cmdline_ptr,
+ u64 initrd_addr, u64 initrd_size,
+ efi_memory_desc_t *memory_map,
+ unsigned long map_size, unsigned long desc_size,
+ u32 desc_ver)
+{
+ int node;
+ int status;
+ u32 fdt_val32;
+ u64 fdt_val64;
+
+ /*
+ * Copy definition of linux_banner here. Since this code is
+ * built as part of the decompressor for ARM v7, pulling
+ * in version.c where linux_banner is defined for the
+ * kernel brings other kernel dependencies with it.
+ */
+ const char linux_banner[] =
+ "Linux version " UTS_RELEASE " (" LINUX_COMPILE_BY "@"
+ LINUX_COMPILE_HOST ") (" LINUX_COMPILER ") " UTS_VERSION "\n";
+
+ status = fdt_open_into(orig_fdt, fdt, new_fdt_size);
+ if (status != 0)
+ goto fdt_set_fail;
+
+ node = fdt_subnode_offset(fdt, 0, "chosen");
+ if (node < 0) {
+ node = fdt_add_subnode(fdt, 0, "chosen");
+ if (node < 0) {
+ status = node; /* node is error code when negative */
+ goto fdt_set_fail;
+ }
+ }
+
+ if ((cmdline_ptr != NULL) && (strlen(cmdline_ptr) > 0)) {
+ status = fdt_setprop(fdt, node, "bootargs", cmdline_ptr,
+ strlen(cmdline_ptr) + 1);
+ if (status)
+ goto fdt_set_fail;
+ }
+
+ /* Set initrd address/end in device tree, if present */
+ if (initrd_size != 0) {
+ u64 initrd_image_end;
+ u64 initrd_image_start = cpu_to_fdt64(initrd_addr);
+ status = fdt_setprop(fdt, node, "linux,initrd-start",
+ &initrd_image_start, sizeof(u64));
+ if (status)
+ goto fdt_set_fail;
+ initrd_image_end = cpu_to_fdt64(initrd_addr + initrd_size);
+ status = fdt_setprop(fdt, node, "linux,initrd-end",
+ &initrd_image_end, sizeof(u64));
+ if (status)
+ goto fdt_set_fail;
+ }
+
+ /* Add FDT entries for EFI runtime services in chosen node. */
+ node = fdt_subnode_offset(fdt, 0, "chosen");
+ fdt_val64 = cpu_to_fdt64((u64)(unsigned long)sys_table);
+ status = fdt_setprop(fdt, node, "linux,uefi-system-table",
+ &fdt_val64, sizeof(fdt_val64));
+ if (status)
+ goto fdt_set_fail;
+
+ fdt_val64 = cpu_to_fdt64((u64)(unsigned long)memory_map);
+ status = fdt_setprop(fdt, node, "linux,uefi-mmap-start",
+ &fdt_val64, sizeof(fdt_val64));
+ if (status)
+ goto fdt_set_fail;
+
+ fdt_val32 = cpu_to_fdt32(map_size);
+ status = fdt_setprop(fdt, node, "linux,uefi-mmap-size",
+ &fdt_val32, sizeof(fdt_val32));
+ if (status)
+ goto fdt_set_fail;
+
+ fdt_val32 = cpu_to_fdt32(desc_size);
+ status = fdt_setprop(fdt, node, "linux,uefi-mmap-desc-size",
+ &fdt_val32, sizeof(fdt_val32));
+ if (status)
+ goto fdt_set_fail;
+
+ fdt_val32 = cpu_to_fdt32(desc_ver);
+ status = fdt_setprop(fdt, node, "linux,uefi-mmap-desc-ver",
+ &fdt_val32, sizeof(fdt_val32));
+ if (status)
+ goto fdt_set_fail;
+
+ /*
+ * Add kernel version banner so stub/kernel match can be
+ * verified.
+ */
+ status = fdt_setprop_string(fdt, node, "linux,uefi-stub-kern-ver",
+ linux_banner);
+ if (status)
+ goto fdt_set_fail;
+
+ return EFI_SUCCESS;
+
+fdt_set_fail:
+ if (status == -FDT_ERR_NOSPACE)
+ return EFI_BUFFER_TOO_SMALL;
+
+ return EFI_LOAD_ERROR;
+}
+
+#ifndef EFI_FDT_ALIGN
+#define EFI_FDT_ALIGN EFI_PAGE_SIZE
+#endif
+
+/*
+ * Allocate memory for a new FDT, then add EFI, commandline, and
+ * initrd related fields to the FDT. This routine increases the
+ * FDT allocation size until the allocated memory is large
+ * enough. EFI allocations are in EFI_PAGE_SIZE granules,
+ * which are fixed at 4K bytes, so in most cases the first
+ * allocation should succeed.
+ * EFI boot services are exited at the end of this function.
+ * There must be no allocations between the get_memory_map()
+ * call and the exit_boot_services() call, so the exiting of
+ * boot services is very tightly tied to the creation of the FDT
+ * with the final memory map in it.
+ */
+
+efi_status_t allocate_new_fdt_and_exit_boot(efi_system_table_t *sys_table,
+ void *handle,
+ unsigned long *new_fdt_addr,
+ unsigned long max_addr,
+ u64 initrd_addr, u64 initrd_size,
+ char *cmdline_ptr,
+ unsigned long fdt_addr,
+ unsigned long fdt_size)
+{
+ unsigned long map_size, desc_size;
+ u32 desc_ver;
+ unsigned long mmap_key;
+ efi_memory_desc_t *memory_map;
+ unsigned long new_fdt_size;
+ efi_status_t status;
+
+ /* Estimate size of new FDT, and allocate memory for it. We
+ * will allocate a bigger buffer if this ends up being too
+ * small, so a rough guess is OK here.*/
+ new_fdt_size = fdt_size + EFI_PAGE_SIZE;
+ while (1) {
+ status = efi_high_alloc(sys_table, new_fdt_size, EFI_FDT_ALIGN,
+ new_fdt_addr, max_addr);
+ if (status != EFI_SUCCESS) {
+ pr_efi_err(sys_table, "Unable to allocate memory for new device tree.\n");
+ goto fail;
+ }
+
+ /* Now that we have done our final memory allocation (and free)
+ * we can get the memory map key needed for
+ * exit_boot_services().
+ */
+ status = efi_get_memory_map(sys_table, &memory_map, &map_size,
+ &desc_size, &desc_ver, &mmap_key);
+ if (status != EFI_SUCCESS)
+ goto fail_free_new_fdt;
+
+ status = update_fdt(sys_table,
+ (void *)fdt_addr, (void *)*new_fdt_addr,
+ new_fdt_size, cmdline_ptr, initrd_addr,
+ initrd_size, memory_map, map_size,
+ desc_size, desc_ver);
+
+ /* Succeeding the first time is the expected case. */
+ if (status == EFI_SUCCESS)
+ break;
+
+ if (status == EFI_BUFFER_TOO_SMALL) {
+ /* We need to allocate more space for the new
+ * device tree, so free existing buffer that is
+ * too small. Also free memory map, as we will need
+ * to get new one that reflects the free/alloc we do
+ * on the device tree buffer. */
+ efi_free(sys_table, new_fdt_size, *new_fdt_addr);
+ efi_call_phys1(sys_table->boottime->free_pool,
+ memory_map);
+ new_fdt_size += EFI_PAGE_SIZE;
+ } else {
+ pr_efi_err(sys_table, "Unable to constuct new device tree.\n");
+ goto fail_free_mmap;
+ }
+ }
+
+ /* Now we are ready to exit_boot_services.*/
+ status = efi_call_phys2(sys_table->boottime->exit_boot_services,
+ handle, mmap_key);
+
+
+ if (status == EFI_SUCCESS)
+ return status;
+
+ pr_efi_err(sys_table, "Exit boot services failed.\n");
+
+fail_free_mmap:
+ efi_call_phys1(sys_table->boottime->free_pool, memory_map);
+
+fail_free_new_fdt:
+ efi_free(sys_table, new_fdt_size, *new_fdt_addr);
+
+fail:
+ return EFI_LOAD_ERROR;
+}
+
--
1.7.10.4

2014-01-10 16:32:54

by Roy Franz

[permalink] [raw]
Subject: [PATCH V6 1/8] efi-stub.txt updates for ARM

Update efi-stub.txt documentation to be more general
and not x86 specific. Add ARM only "dtb=" command
line option description.

Signed-off-by: Roy Franz <[email protected]>
Acked-by: Grant Likely <[email protected]>
---
Documentation/efi-stub.txt | 27 ++++++++++++++++++++-------
1 file changed, 20 insertions(+), 7 deletions(-)

diff --git a/Documentation/efi-stub.txt b/Documentation/efi-stub.txt
index 44e6bb6..a55a0cd 100644
--- a/Documentation/efi-stub.txt
+++ b/Documentation/efi-stub.txt
@@ -1,13 +1,16 @@
The EFI Boot Stub
---------------------------

-On the x86 platform, a bzImage can masquerade as a PE/COFF image,
-thereby convincing EFI firmware loaders to load it as an EFI
-executable. The code that modifies the bzImage header, along with the
-EFI-specific entry point that the firmware loader jumps to are
-collectively known as the "EFI boot stub", and live in
+On the x86 and ARM platforms, a kernel zImage/bzImage can masquerade
+as a PE/COFF image, thereby convincing EFI firmware loaders to load
+it as an EFI executable. The code that modifies the bzImage header,
+along with the EFI-specific entry point that the firmware loader
+jumps to are collectively known as the "EFI boot stub", and live in
arch/x86/boot/header.S and arch/x86/boot/compressed/eboot.c,
-respectively.
+respectively. For ARM the EFI stub is implemented in
+arch/arm/boot/compressed/efi-header.S and
+arch/arm/boot/compressed/efi-stub.c. EFI stub code that is shared
+between architectures is in drivers/firmware/efi/efi-stub-helper.c.

By using the EFI boot stub it's possible to boot a Linux kernel
without the use of a conventional EFI boot loader, such as grub or
@@ -23,7 +26,9 @@ The bzImage located in arch/x86/boot/bzImage must be copied to the EFI
System Partiion (ESP) and renamed with the extension ".efi". Without
the extension the EFI firmware loader will refuse to execute it. It's
not possible to execute bzImage.efi from the usual Linux file systems
-because EFI firmware doesn't have support for them.
+because EFI firmware doesn't have support for them. For ARM the
+arch/arm/boot/zImage should be copied to the system partition, and it
+may not need to be renamed.


**** Passing kernel parameters from the EFI shell
@@ -63,3 +68,11 @@ Notice how bzImage.efi can be specified with a relative path. That's
because the image we're executing is interpreted by the EFI shell,
which understands relative paths, whereas the rest of the command line
is passed to bzImage.efi.
+
+
+**** The "dtb=" option
+
+For the ARM architecture, we also need to be able to provide a device
+tree to the kernel. This is done with the "dtb=" command line option,
+and is processed in the same manner as the "initrd=" option that is
+described above.
--
1.7.10.4

2014-01-13 15:04:16

by Matt Fleming

[permalink] [raw]
Subject: Re: [PATCH V6 3/8] Add helper function to get and convert EFI command line

On Fri, 10 Jan, at 08:30:12AM, Roy Franz wrote:
> Add an EFI stub helper function to retrieve the EFI command line using
> the LOADED_IMAGE_PROTOCOL, and convert it to ASCII. This function will
> be shared by the various EFI stub implementations.
>
> Signed-off-by: Roy Franz <[email protected]>
> ---
> drivers/firmware/efi/efi-stub-helper.c | 30 ++++++++++++++++++++++++++++++
> 1 file changed, 30 insertions(+)
>
> diff --git a/drivers/firmware/efi/efi-stub-helper.c b/drivers/firmware/efi/efi-stub-helper.c
> index eb5d2eb..f657456 100644
> --- a/drivers/firmware/efi/efi-stub-helper.c
> +++ b/drivers/firmware/efi/efi-stub-helper.c
> @@ -637,3 +637,33 @@ static char *efi_convert_cmdline_to_ascii(efi_system_table_t *sys_table_arg,
> *cmd_line_len = options_size;
> return (char *)cmdline_addr;
> }
> +
> +/*
> + * get the command line from EFI, using the LOADED_IMAGE
> + * protocol, and convert to ASCII.
> + *
> + */
> +static void efi_get_cmdline(efi_system_table_t *sys_table,
> + efi_loaded_image_t **image,
> + void *handle, char **cmdline_ptr)
> +{

Wouldn't this prototype make more sense?

static char *efi_get_cmdline(efi_system_table_t *sys_table,
efi_loaded_image_t **image,
void *handle);

Is this function really worth implementing at all? Certainly on x86, we
lookup the loaded image protocol for reasons other than parsing the
command line, and so would need to do it in the caller anyway.

--
Matt Fleming, Intel Open Source Technology Center

2014-01-13 15:07:40

by Matt Fleming

[permalink] [raw]
Subject: Re: [PATCH V6 0/8] Add ARM EFI stub

On Fri, 10 Jan, at 08:30:09AM, Roy Franz wrote:
> This patch series adds EFI stub support for the ARM architecture. The
> stub for ARM is implemented in a similar manner to x86 in that it is a
> shim layer between EFI and the normal zImage/bzImage boot process, and
> that an image with the stub configured is bootable as both a zImage and
> EFI application. This patchset adds common code that is shared with
> the ARM64 EFI stub.
>
> This patch depends on Leif Lindholm's ARM v7 runtime services patchset, which
> in turn depends on Mark Salter's early_io_remap() patchset. This EFI stub
> patchset can be tested without those by simply modifying the Kconfig for
> EFI_STUB to not depend on EFI. The kernel will boot using the stub,
> however no EFI support will be available in the kernel.
>
> I have addressed all the feedback I have recieved to date, and I am hoping
> that this patchset is acceptable for merging into 3.14. It has been
> functionally stable for some time, and provides useful functionality.
> Further consolidation of the ARM/ARM64 stubs planned as part of the
> ongoing development of the stubs and supporting tools for both
> architectures (getting the FDT from a UEFI configuration table, using UEFI
> memory map instead of FDT for memory description.)

Is this going to Linus via one of the ARM maintainer trees?

--
Matt Fleming, Intel Open Source Technology Center

2014-01-14 09:06:08

by Ard Biesheuvel

[permalink] [raw]
Subject: Re: [PATCH V6 6/8] Add EFI stub for ARM

On 10 January 2014 17:30, Roy Franz <[email protected]> wrote:
> This patch adds EFI stub support for the ARM Linux kernel. The EFI stub
> operates similarly to the x86 stub: it is a shim between the EFI firmware
> and the normal zImage entry point, and sets up the environment that the
> zImage is expecting. This includes loading the initrd (optionaly) and
> device tree from the system partition based on the kernel command line.
> The stub updates the device tree as necessary, adding entries for EFI
> runtime services. The PE/COFF "MZ" header at offset 0 results in the
> first instruction being an add that corrupts r5, which is not used by
> the zImage interface.
>
> Signed-off-by: Roy Franz <[email protected]>
> Acked-by: Grant Likely <[email protected]>
> ---

[...]

> diff --git a/arch/arm/boot/compressed/efi-header.S b/arch/arm/boot/compressed/efi-header.S
> new file mode 100644
> index 0000000..dbb7101
> --- /dev/null
> +++ b/arch/arm/boot/compressed/efi-header.S
> @@ -0,0 +1,117 @@
> +@ Copyright (C) 2013 Linaro Ltd; <[email protected]>
> +@
> +@ This file contains the PE/COFF header that is part of the
> +@ EFI stub.
> +@
> +
> + .org 0x3c
> + @
> + @ The PE header can be anywhere in the file, but for
> + @ simplicity we keep it together with the MSDOS header
> + @ The offset to the PE/COFF header needs to be at offset
> + @ 0x3C in the MSDOS header.
> + @ The only 2 fields of the MSDOS header that are used are this
> + @ PE/COFF offset, and the "MZ" bytes at offset 0x0.
> + @
> + .long pe_header @ Offset to the PE header.
> +
> + .align 3
> +pe_header:
> + .ascii "PE"
> + .short 0
> +
> +coff_header:
> + .short 0x01c2 @ ARM or Thumb

Could you explain why you are using 0x1c2 (Thumb) here and not 0x1c0 (ARM) ?

Cheers,
Ard.

2014-01-14 19:29:22

by Rob Herring

[permalink] [raw]
Subject: Re: [PATCH V6 6/8] Add EFI stub for ARM

On Fri, Jan 10, 2014 at 10:30 AM, Roy Franz <[email protected]> wrote:
> This patch adds EFI stub support for the ARM Linux kernel. The EFI stub
> operates similarly to the x86 stub: it is a shim between the EFI firmware
> and the normal zImage entry point, and sets up the environment that the
> zImage is expecting. This includes loading the initrd (optionaly) and
> device tree from the system partition based on the kernel command line.
> The stub updates the device tree as necessary, adding entries for EFI
> runtime services. The PE/COFF "MZ" header at offset 0 results in the
> first instruction being an add that corrupts r5, which is not used by
> the zImage interface.
>
> Signed-off-by: Roy Franz <[email protected]>
> Acked-by: Grant Likely <[email protected]>
> ---

[snip]

> + /* Look up the base of DRAM from the device tree. */
> + fdt = (void *)fdt_addr;
> + node = fdt_subnode_offset(fdt, 0, "memory");
> + region = fdt_getprop(fdt, node, "reg", NULL);
> + if (region) {
> + dram_base = fdt64_to_cpu(region->base);

This will not work if the address is 32-bit size.

> + } else {
> + /* There is no way to get amount or addresses of physical
> + * memory installed using EFI calls. If the device tree
> + * we read from disk doesn't have this, there is no way
> + * for us to construct this informaion.
> + */
> + pr_efi_err(sys_table, "No 'memory' node in device tree.\n");
> + goto fail_free_fdt;

The current pc can't be used to determine the DRAM base like AUTO_ZRELADDR?

Rob

2014-01-14 19:35:29

by Roy Franz

[permalink] [raw]
Subject: Re: [PATCH V6 6/8] Add EFI stub for ARM

On Tue, Jan 14, 2014 at 11:29 AM, Rob Herring <[email protected]> wrote:
> On Fri, Jan 10, 2014 at 10:30 AM, Roy Franz <[email protected]> wrote:
>> This patch adds EFI stub support for the ARM Linux kernel. The EFI stub
>> operates similarly to the x86 stub: it is a shim between the EFI firmware
>> and the normal zImage entry point, and sets up the environment that the
>> zImage is expecting. This includes loading the initrd (optionaly) and
>> device tree from the system partition based on the kernel command line.
>> The stub updates the device tree as necessary, adding entries for EFI
>> runtime services. The PE/COFF "MZ" header at offset 0 results in the
>> first instruction being an add that corrupts r5, which is not used by
>> the zImage interface.
>>
>> Signed-off-by: Roy Franz <[email protected]>
>> Acked-by: Grant Likely <[email protected]>
>> ---
>
> [snip]
>
>> + /* Look up the base of DRAM from the device tree. */
>> + fdt = (void *)fdt_addr;
>> + node = fdt_subnode_offset(fdt, 0, "memory");
>> + region = fdt_getprop(fdt, node, "reg", NULL);
>> + if (region) {
>> + dram_base = fdt64_to_cpu(region->base);
>
> This will not work if the address is 32-bit size.
>
>> + } else {
>> + /* There is no way to get amount or addresses of physical
>> + * memory installed using EFI calls. If the device tree
>> + * we read from disk doesn't have this, there is no way
>> + * for us to construct this informaion.
>> + */
>> + pr_efi_err(sys_table, "No 'memory' node in device tree.\n");
>> + goto fail_free_fdt;
>
> The current pc can't be used to determine the DRAM base like AUTO_ZRELADDR?
>
> Rob

Hi Rob,

UEFI may load the stub based kernel anywhere, so we don't get any
useful information from where we were loaded.
I am currently working on getting the base address from the EFI memory
map, so all of the above code will go away, the only FDT
operations that the stub will perform is to add the EFI related fields.

Roy

2014-01-14 19:39:45

by Roy Franz

[permalink] [raw]
Subject: Re: [PATCH V6 0/8] Add ARM EFI stub

On Mon, Jan 13, 2014 at 7:07 AM, Matt Fleming <[email protected]> wrote:
> On Fri, 10 Jan, at 08:30:09AM, Roy Franz wrote:
>> This patch series adds EFI stub support for the ARM architecture. The
>> stub for ARM is implemented in a similar manner to x86 in that it is a
>> shim layer between EFI and the normal zImage/bzImage boot process, and
>> that an image with the stub configured is bootable as both a zImage and
>> EFI application. This patchset adds common code that is shared with
>> the ARM64 EFI stub.
>>
>> This patch depends on Leif Lindholm's ARM v7 runtime services patchset, which
>> in turn depends on Mark Salter's early_io_remap() patchset. This EFI stub
>> patchset can be tested without those by simply modifying the Kconfig for
>> EFI_STUB to not depend on EFI. The kernel will boot using the stub,
>> however no EFI support will be available in the kernel.
>>
>> I have addressed all the feedback I have recieved to date, and I am hoping
>> that this patchset is acceptable for merging into 3.14. It has been
>> functionally stable for some time, and provides useful functionality.
>> Further consolidation of the ARM/ARM64 stubs planned as part of the
>> ongoing development of the stubs and supporting tools for both
>> architectures (getting the FDT from a UEFI configuration table, using UEFI
>> memory map instead of FDT for memory description.)
>
> Is this going to Linus via one of the ARM maintainer trees?
>
> --
> Matt Fleming, Intel Open Source Technology Center

Hi Matt,

Yes, this is planned to go through one of the ARM trees. Given
that this relies on the early_io_remap
patchsets that have not been accepted yet, I don't see this being
accepted for 3.14.

Roy

2014-01-14 19:41:28

by Roy Franz

[permalink] [raw]
Subject: Re: [PATCH V6 3/8] Add helper function to get and convert EFI command line

On Mon, Jan 13, 2014 at 7:04 AM, Matt Fleming <[email protected]> wrote:
> On Fri, 10 Jan, at 08:30:12AM, Roy Franz wrote:
>> Add an EFI stub helper function to retrieve the EFI command line using
>> the LOADED_IMAGE_PROTOCOL, and convert it to ASCII. This function will
>> be shared by the various EFI stub implementations.
>>
>> Signed-off-by: Roy Franz <[email protected]>
>> ---
>> drivers/firmware/efi/efi-stub-helper.c | 30 ++++++++++++++++++++++++++++++
>> 1 file changed, 30 insertions(+)
>>
>> diff --git a/drivers/firmware/efi/efi-stub-helper.c b/drivers/firmware/efi/efi-stub-helper.c
>> index eb5d2eb..f657456 100644
>> --- a/drivers/firmware/efi/efi-stub-helper.c
>> +++ b/drivers/firmware/efi/efi-stub-helper.c
>> @@ -637,3 +637,33 @@ static char *efi_convert_cmdline_to_ascii(efi_system_table_t *sys_table_arg,
>> *cmd_line_len = options_size;
>> return (char *)cmdline_addr;
>> }
>> +
>> +/*
>> + * get the command line from EFI, using the LOADED_IMAGE
>> + * protocol, and convert to ASCII.
>> + *
>> + */
>> +static void efi_get_cmdline(efi_system_table_t *sys_table,
>> + efi_loaded_image_t **image,
>> + void *handle, char **cmdline_ptr)
>> +{
>
> Wouldn't this prototype make more sense?
>
> static char *efi_get_cmdline(efi_system_table_t *sys_table,
> efi_loaded_image_t **image,
> void *handle);
>
> Is this function really worth implementing at all? Certainly on x86, we
> lookup the loaded image protocol for reasons other than parsing the
> command line, and so would need to do it in the caller anyway.
>
> --
> Matt Fleming, Intel Open Source Technology Center

Yeah, this should just go away. This was the result of some
over-zealous moving code from arm/arm64 to shared code.

Roy

2014-01-15 01:47:31

by Roy Franz

[permalink] [raw]
Subject: Re: [PATCH V6 6/8] Add EFI stub for ARM

On Tue, Jan 14, 2014 at 1:05 AM, Ard Biesheuvel
<[email protected]> wrote:
> On 10 January 2014 17:30, Roy Franz <[email protected]> wrote:
>> This patch adds EFI stub support for the ARM Linux kernel. The EFI stub
>> operates similarly to the x86 stub: it is a shim between the EFI firmware
>> and the normal zImage entry point, and sets up the environment that the
>> zImage is expecting. This includes loading the initrd (optionaly) and
>> device tree from the system partition based on the kernel command line.
>> The stub updates the device tree as necessary, adding entries for EFI
>> runtime services. The PE/COFF "MZ" header at offset 0 results in the
>> first instruction being an add that corrupts r5, which is not used by
>> the zImage interface.
>>
>> Signed-off-by: Roy Franz <[email protected]>
>> Acked-by: Grant Likely <[email protected]>
>> ---
>
> [...]
>
>> diff --git a/arch/arm/boot/compressed/efi-header.S b/arch/arm/boot/compressed/efi-header.S
>> new file mode 100644
>> index 0000000..dbb7101
>> --- /dev/null
>> +++ b/arch/arm/boot/compressed/efi-header.S
>> @@ -0,0 +1,117 @@
>> +@ Copyright (C) 2013 Linaro Ltd; <[email protected]>
>> +@
>> +@ This file contains the PE/COFF header that is part of the
>> +@ EFI stub.
>> +@
>> +
>> + .org 0x3c
>> + @
>> + @ The PE header can be anywhere in the file, but for
>> + @ simplicity we keep it together with the MSDOS header
>> + @ The offset to the PE/COFF header needs to be at offset
>> + @ 0x3C in the MSDOS header.
>> + @ The only 2 fields of the MSDOS header that are used are this
>> + @ PE/COFF offset, and the "MZ" bytes at offset 0x0.
>> + @
>> + .long pe_header @ Offset to the PE header.
>> +
>> + .align 3
>> +pe_header:
>> + .ascii "PE"
>> + .short 0
>> +
>> +coff_header:
>> + .short 0x01c2 @ ARM or Thumb
>
> Could you explain why you are using 0x1c2 (Thumb) here and not 0x1c0 (ARM) ?
>
> Cheers,
> Ard.

Nope. It should be 0x1c0.

Roy

2014-01-15 02:17:01

by Roy Franz

[permalink] [raw]
Subject: Re: [PATCH V6 6/8] Add EFI stub for ARM

On Tue, Jan 14, 2014 at 5:47 PM, Roy Franz <[email protected]> wrote:
> On Tue, Jan 14, 2014 at 1:05 AM, Ard Biesheuvel
> <[email protected]> wrote:
>> On 10 January 2014 17:30, Roy Franz <[email protected]> wrote:
>>> This patch adds EFI stub support for the ARM Linux kernel. The EFI stub
>>> operates similarly to the x86 stub: it is a shim between the EFI firmware
>>> and the normal zImage entry point, and sets up the environment that the
>>> zImage is expecting. This includes loading the initrd (optionaly) and
>>> device tree from the system partition based on the kernel command line.
>>> The stub updates the device tree as necessary, adding entries for EFI
>>> runtime services. The PE/COFF "MZ" header at offset 0 results in the
>>> first instruction being an add that corrupts r5, which is not used by
>>> the zImage interface.
>>>
>>> Signed-off-by: Roy Franz <[email protected]>
>>> Acked-by: Grant Likely <[email protected]>
>>> ---
>>
>> [...]
>>
>>> diff --git a/arch/arm/boot/compressed/efi-header.S b/arch/arm/boot/compressed/efi-header.S
>>> new file mode 100644
>>> index 0000000..dbb7101
>>> --- /dev/null
>>> +++ b/arch/arm/boot/compressed/efi-header.S
>>> @@ -0,0 +1,117 @@
>>> +@ Copyright (C) 2013 Linaro Ltd; <[email protected]>
>>> +@
>>> +@ This file contains the PE/COFF header that is part of the
>>> +@ EFI stub.
>>> +@
>>> +
>>> + .org 0x3c
>>> + @
>>> + @ The PE header can be anywhere in the file, but for
>>> + @ simplicity we keep it together with the MSDOS header
>>> + @ The offset to the PE/COFF header needs to be at offset
>>> + @ 0x3C in the MSDOS header.
>>> + @ The only 2 fields of the MSDOS header that are used are this
>>> + @ PE/COFF offset, and the "MZ" bytes at offset 0x0.
>>> + @
>>> + .long pe_header @ Offset to the PE header.
>>> +
>>> + .align 3
>>> +pe_header:
>>> + .ascii "PE"
>>> + .short 0
>>> +
>>> +coff_header:
>>> + .short 0x01c2 @ ARM or Thumb
>>
>> Could you explain why you are using 0x1c2 (Thumb) here and not 0x1c0 (ARM) ?
>>
>> Cheers,
>> Ard.
>
> Nope. It should be 0x1c0.
>
> Roy

OK, now I resolved the nagging feeling that I had already fixed
this... Right now, the EDK2 UEFI implementation
requires the machine type for ARM to be "0x1c2". I don't think that
this is correct, but correcting this in EDK2 slipped through
the cracks, but is now back on my todo list.

I think that for now we should leave this as 0x1c2 so that the
unpatched EDK2 builds will boot it, and some time after EDK2 is
updated
this can be changed. I'll work on a patch for EDK2 and get the
discussion going on that list to resolve this in EDK2.


Roy

2014-01-15 09:46:25

by Ard Biesheuvel

[permalink] [raw]
Subject: Re: [PATCH V6 6/8] Add EFI stub for ARM

On 15 January 2014 03:16, Roy Franz <[email protected]> wrote:
> On Tue, Jan 14, 2014 at 5:47 PM, Roy Franz <[email protected]> wrote:
>> On Tue, Jan 14, 2014 at 1:05 AM, Ard Biesheuvel
>> <[email protected]> wrote:
>>> On 10 January 2014 17:30, Roy Franz <[email protected]> wrote:
>>>> This patch adds EFI stub support for the ARM Linux kernel. The EFI stub
>>>> operates similarly to the x86 stub: it is a shim between the EFI firmware
>>>> and the normal zImage entry point, and sets up the environment that the
>>>> zImage is expecting. This includes loading the initrd (optionaly) and
>>>> device tree from the system partition based on the kernel command line.
>>>> The stub updates the device tree as necessary, adding entries for EFI
>>>> runtime services. The PE/COFF "MZ" header at offset 0 results in the
>>>> first instruction being an add that corrupts r5, which is not used by
>>>> the zImage interface.
>>>>
>>>> Signed-off-by: Roy Franz <[email protected]>
>>>> Acked-by: Grant Likely <[email protected]>
>>>> ---
>>>
>>> [...]
>>>
>>>> diff --git a/arch/arm/boot/compressed/efi-header.S b/arch/arm/boot/compressed/efi-header.S
>>>> new file mode 100644
>>>> index 0000000..dbb7101
>>>> --- /dev/null
>>>> +++ b/arch/arm/boot/compressed/efi-header.S
>>>> @@ -0,0 +1,117 @@
>>>> +@ Copyright (C) 2013 Linaro Ltd; <[email protected]>
>>>> +@
>>>> +@ This file contains the PE/COFF header that is part of the
>>>> +@ EFI stub.
>>>> +@
>>>> +
>>>> + .org 0x3c
>>>> + @
>>>> + @ The PE header can be anywhere in the file, but for
>>>> + @ simplicity we keep it together with the MSDOS header
>>>> + @ The offset to the PE/COFF header needs to be at offset
>>>> + @ 0x3C in the MSDOS header.
>>>> + @ The only 2 fields of the MSDOS header that are used are this
>>>> + @ PE/COFF offset, and the "MZ" bytes at offset 0x0.
>>>> + @
>>>> + .long pe_header @ Offset to the PE header.
>>>> +
>>>> + .align 3

Btw you also have a whitespace error here.

>>>> +pe_header:
>>>> + .ascii "PE"
>>>> + .short 0
>>>> +
>>>> +coff_header:
>>>> + .short 0x01c2 @ ARM or Thumb
>>>
>>> Could you explain why you are using 0x1c2 (Thumb) here and not 0x1c0 (ARM) ?
>>>
>>> Cheers,
>>> Ard.
>>
>> Nope. It should be 0x1c0.
>>
>> Roy
>
> OK, now I resolved the nagging feeling that I had already fixed
> this... Right now, the EDK2 UEFI implementation
> requires the machine type for ARM to be "0x1c2". I don't think that
> this is correct, but correcting this in EDK2 slipped through
> the cracks, but is now back on my todo list.
>
> I think that for now we should leave this as 0x1c2 so that the
> unpatched EDK2 builds will boot it, and some time after EDK2 is
> updated
> this can be changed. I'll work on a patch for EDK2 and get the
> discussion going on that list to resolve this in EDK2.
>

OK. I have updated sbsigntool (Linaro's version) so it supports
either, but I agree that using the ARM constant is the correct way.

--
Ard.

2014-01-15 11:46:32

by Leif Lindholm

[permalink] [raw]
Subject: Re: [PATCH V6 6/8] Add EFI stub for ARM

On Tue, Jan 14, 2014 at 06:16:58PM -0800, Roy Franz wrote:
> >>> + .align 3
> >>> +pe_header:
> >>> + .ascii "PE"
> >>> + .short 0
> >>> +
> >>> +coff_header:
> >>> + .short 0x01c2 @ ARM or Thumb
> >>
> >> Could you explain why you are using 0x1c2 (Thumb) here and not 0x1c0 (ARM) ?
> >
> > Nope. It should be 0x1c0.
>
> OK, now I resolved the nagging feeling that I had already fixed
> this... Right now, the EDK2 UEFI implementation
> requires the machine type for ARM to be "0x1c2". I don't think that
> this is correct, but correcting this in EDK2 slipped through
> the cracks, but is now back on my todo list.

Nope, it should be 0x1c2.

0x1c0 is the COFF code for ARM only, which corresponds roughly with
OABI - which is not supported (and never will be) by the UEFI
specification.
0x1c2 means ARM or Thumb (Interworking), which is what we have.

The UEFI specification (correctly) neglects to even mention 0x1c0
and 0x1c4.

Do also note that the COFF information relates to the executable,
the stub. The rest of the kernel image is just a blob as far as UEFI
is concerned.

> I think that for now we should leave this as 0x1c2 so that the
> unpatched EDK2 builds will boot it, and some time after EDK2 is
> updated
> this can be changed. I'll work on a patch for EDK2 and get the
> discussion going on that list to resolve this in EDK2.

No need.

/
Leif