efi: arm: Add EFI app support
authorSimon Glass <sjg@chromium.org>
Mon, 7 Nov 2016 15:47:10 +0000 (08:47 -0700)
committerAlexander Graf <agraf@suse.de>
Mon, 14 Nov 2016 22:24:04 +0000 (23:24 +0100)
Add support for EFI apps on ARM. This includes start-up and relocation
code, plus a link script and some compiler setting changes.

Signed-off-by: Simon Glass <sjg@chromium.org>
[agraf: Remove whitespace change, add kconfig dep]
Signed-off-by: Alexander Graf <agraf@suse.de>
arch/arm/config.mk
arch/arm/lib/Makefile
arch/arm/lib/crt0_arm_efi.S [new file with mode: 0644]
arch/arm/lib/elf_arm_efi.lds [new file with mode: 0644]
arch/arm/lib/reloc_arm_efi.c [new file with mode: 0644]
cmd/Kconfig

index 542b897..27914a9 100644 (file)
@@ -13,6 +13,9 @@ CONFIG_STANDALONE_LOAD_ADDR = 0xc100000
 endif
 endif
 
+CFLAGS_NON_EFI := -fno-pic -ffixed-r9 -ffunction-sections -fdata-sections
+CFLAGS_EFI := -fpic -fshort-wchar
+
 LDFLAGS_FINAL += --gc-sections
 PLATFORM_RELFLAGS += -ffunction-sections -fdata-sections \
                     -fno-common -ffixed-r9
@@ -148,3 +151,7 @@ ifneq ($(CONFIG_VF610),)
 ALL-y += u-boot.vyb
 endif
 endif
+
+EFI_LDS := elf_arm_efi.lds
+EFI_CRT0 := crt0_arm_efi.o
+EFI_RELOC := reloc_arm_efi.o
index caa62c6..a812306 100644 (file)
@@ -92,3 +92,13 @@ AFLAGS_memset.o := -DMEMSET_NO_THUMB_BUILD
 AFLAGS_memcpy.o := -DMEMCPY_NO_THUMB_BUILD
 endif
 endif
+
+# For building EFI apps
+CFLAGS_$(EFI_CRT0) := $(CFLAGS_EFI)
+CFLAGS_REMOVE_$(EFI_CRT0) := $(CFLAGS_NON_EFI)
+
+CFLAGS_$(EFI_RELOC) := $(CFLAGS_EFI)
+CFLAGS_REMOVE_$(EFI_RELOC) := $(CFLAGS_NON_EFI)
+
+extra-$(CONFIG_CMD_BOOTEFI_HELLO) += $(EFI_CRT0) $(EFI_RELOC)
+extra-$(CONFIG_EFI) += $(EFI_CRT0) $(EFI_RELOC)
diff --git a/arch/arm/lib/crt0_arm_efi.S b/arch/arm/lib/crt0_arm_efi.S
new file mode 100644 (file)
index 0000000..967c885
--- /dev/null
@@ -0,0 +1,138 @@
+/*
+ * crt0-efi-arm.S - PE/COFF header for ARM EFI applications
+ *
+ * Copright (C) 2014 Linaro Ltd. <ard.biesheuvel@linaro.org>
+ *
+ * SPDX-License-Identifier:     GPL-2.0+     BSD-2-Clause
+ *
+ * This file is taken and modified from the gnu-efi project.
+ */
+
+       .section        .text.head
+
+       /*
+        * Magic "MZ" signature for PE/COFF
+        */
+       .globl  image_base
+image_base:
+       .ascii  "MZ"
+       .skip   58                              /* 'MZ' + pad + offset == 64 */
+       .long   pe_header - image_base          /* Offset to the PE header */
+pe_header:
+       .ascii  "PE"
+       .short  0
+coff_header:
+       .short  0x1c2                           /* Mixed ARM/Thumb */
+       .short  2                               /* nr_sections */
+       .long   0                               /* TimeDateStamp */
+       .long   0                               /* PointerToSymbolTable */
+       .long   1                               /* NumberOfSymbols */
+       .short  section_table - optional_header /* SizeOfOptionalHeader */
+       /*
+        * Characteristics: IMAGE_FILE_32BIT_MACHINE |
+        * IMAGE_FILE_DEBUG_STRIPPED | IMAGE_FILE_EXECUTABLE_IMAGE |
+        * IMAGE_FILE_LINE_NUMS_STRIPPED
+        */
+       .short  0x306
+optional_header:
+       .short  0x10b                           /* PE32+ format */
+       .byte   0x02                            /* MajorLinkerVersion */
+       .byte   0x14                            /* MinorLinkerVersion */
+       .long   _edata - _start                 /* SizeOfCode */
+       .long   0                               /* SizeOfInitializedData */
+       .long   0                               /* SizeOfUninitializedData */
+       .long   _start - image_base             /* AddressOfEntryPoint */
+       .long   _start - image_base             /* BaseOfCode */
+       .long   0                               /* BaseOfData */
+
+extra_header_fields:
+       .long   0                               /* image_base */
+       .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 - image_base             /* SizeOfImage */
+
+       /*
+        * Everything before the kernel image is considered part of the header
+        */
+       .long   _start - image_base             /* SizeOfHeaders */
+       .long   0                               /* CheckSum */
+       .short  EFI_SUBSYSTEM                   /* Subsystem */
+       .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:
+
+       /*
+        * 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 - _start         /* VirtualSize */
+       .long   _start - image_base     /* VirtualAddress */
+       .long   _edata - _start         /* SizeOfRawData */
+       .long   _start - image_base     /* 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) */
+
+_start:
+       stmfd           sp!, {r0-r2, lr}
+
+       mov             r2, r0
+       mov             r3, r1
+       adr             r1, .L_DYNAMIC
+       ldr             r0, [r1]
+       add             r1, r0, r1
+       adr             r0, image_base
+       bl              _relocate
+       teq             r0, #0
+       bne             0f
+
+       ldmfd           sp, {r0-r1}
+       bl              efi_main
+
+0:     add             sp, sp, #12
+       ldr             pc, [sp], #4
+
+.L_DYNAMIC:
+       .word           _DYNAMIC - .
diff --git a/arch/arm/lib/elf_arm_efi.lds b/arch/arm/lib/elf_arm_efi.lds
new file mode 100644 (file)
index 0000000..59f66a1
--- /dev/null
@@ -0,0 +1,70 @@
+/*
+ * U-Boot ARM EFI linker script
+ *
+ * SPDX-License-Identifier:    BSD-2-Clause
+ *
+ * Modified from elf_arm_efi.lds in gnu-efi
+ */
+
+OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm")
+OUTPUT_ARCH(arm)
+ENTRY(_start)
+SECTIONS
+{
+       .text 0x0 : {
+               _text = .;
+               *(.text.head)
+               *(.text)
+               *(.text.*)
+               *(.gnu.linkonce.t.*)
+               *(.srodata)
+               *(.rodata*)
+               . = ALIGN(16);
+       }
+       _etext = .;
+       _text_size = . - _text;
+       .dynamic  : { *(.dynamic) }
+       .data : {
+               _data = .;
+               *(.sdata)
+               *(.data)
+               *(.data1)
+               *(.data.*)
+               *(.got.plt)
+               *(.got)
+
+               /*
+                * The EFI loader doesn't seem to like a .bss section, so we
+                * stick it all into .data:
+                */
+               . = ALIGN(16);
+               _bss = .;
+               *(.sbss)
+               *(.scommon)
+               *(.dynbss)
+               *(.bss)
+               *(.bss.*)
+               *(COMMON)
+               . = ALIGN(16);
+               _bss_end = .;
+               _edata = .;
+       }
+       .rel.dyn : { *(.rel.dyn) }
+       .rel.plt : { *(.rel.plt) }
+       .rel.got : { *(.rel.got) }
+       .rel.data : { *(.rel.data) *(.rel.data*) }
+       _data_size = . - _etext;
+
+       . = ALIGN(4096);
+       .dynsym   : { *(.dynsym) }
+       . = ALIGN(4096);
+       .dynstr   : { *(.dynstr) }
+       . = ALIGN(4096);
+       .note.gnu.build-id : { *(.note.gnu.build-id) }
+       /DISCARD/ : {
+               *(.rel.reloc)
+               *(.eh_frame)
+               *(.note.GNU-stack)
+       }
+       .comment 0 : { *(.comment) }
+}
diff --git a/arch/arm/lib/reloc_arm_efi.c b/arch/arm/lib/reloc_arm_efi.c
new file mode 100644 (file)
index 0000000..d2f96ee
--- /dev/null
@@ -0,0 +1,66 @@
+/*
+ * reloc_arm.c - position-independent ARM ELF shared object relocator
+ *
+ * Copyright (C) 2014 Linaro Ltd. <ard.biesheuvel@linaro.org>
+ * Copyright (C) 1999 Hewlett-Packard Co.
+ * Contributed by David Mosberger <davidm@hpl.hp.com>.
+ *
+ * All rights reserved.
+ *
+ * SPDX-License-Identifier:    BSD-3-Clause
+ *
+ * This file is taken and modified from the gnu-efi project.
+ */
+
+#include <efi.h>
+#include <elf.h>
+
+efi_status_t _relocate(long ldbase, Elf32_Dyn *dyn, efi_handle_t image,
+                      struct efi_system_table *systab)
+{
+       long relsz = 0, relent = 0;
+       Elf32_Rel *rel = 0;
+       ulong *addr;
+       int i;
+
+       for (i = 0; dyn[i].d_tag != DT_NULL; ++i) {
+               switch (dyn[i].d_tag) {
+               case DT_REL:
+                       rel = (Elf32_Rel *)((ulong)dyn[i].d_un.d_ptr
+                                       + ldbase);
+                       break;
+               case DT_RELSZ:
+                       relsz = dyn[i].d_un.d_val;
+                       break;
+               case DT_RELENT:
+                       relent = dyn[i].d_un.d_val;
+                       break;
+               default:
+                       break;
+               }
+       }
+
+       if (!rel && relent == 0)
+               return EFI_SUCCESS;
+
+       if (!rel || relent == 0)
+               return EFI_LOAD_ERROR;
+
+       while (relsz > 0) {
+               /* apply the relocs */
+               switch (ELF32_R_TYPE(rel->r_info)) {
+               case R_ARM_NONE:
+                       break;
+               case R_ARM_RELATIVE:
+                       addr = (ulong *)(ldbase + rel->r_offset);
+                       *addr += ldbase;
+                       break;
+               default:
+                       break;
+               }
+               rel = (Elf32_Rel *)((char *)rel + relent);
+               relsz -= relent;
+       }
+
+       return EFI_SUCCESS;
+}
index ebcfd6d..a1ce4b7 100644 (file)
@@ -183,7 +183,7 @@ config CMD_BOOTEFI
 
 config CMD_BOOTEFI_HELLO
        bool "Allow booting a standard EFI hello world for testing"
-       depends on CMD_BOOTEFI && NEED_CRT0_ENABLEMENT
+       depends on CMD_BOOTEFI && ARM && !ARM64
        help
          This adds a standard EFI hello world application to U-Boot so that
          it can be used with the 'bootefi hello' command. This is useful