From dd46eef2f6e0b7dce2e6bcd85ed8caca5a6b606c Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Mon, 7 Nov 2016 08:47:10 -0700 Subject: [PATCH] efi: arm: Add EFI app support 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 [agraf: Remove whitespace change, add kconfig dep] Signed-off-by: Alexander Graf --- arch/arm/config.mk | 7 +++ arch/arm/lib/Makefile | 10 ++++ arch/arm/lib/crt0_arm_efi.S | 138 +++++++++++++++++++++++++++++++++++++++++++ arch/arm/lib/elf_arm_efi.lds | 70 ++++++++++++++++++++++ arch/arm/lib/reloc_arm_efi.c | 66 +++++++++++++++++++++ cmd/Kconfig | 2 +- 6 files changed, 292 insertions(+), 1 deletion(-) create mode 100644 arch/arm/lib/crt0_arm_efi.S create mode 100644 arch/arm/lib/elf_arm_efi.lds create mode 100644 arch/arm/lib/reloc_arm_efi.c diff --git a/arch/arm/config.mk b/arch/arm/config.mk index 542b897..27914a9 100644 --- a/arch/arm/config.mk +++ b/arch/arm/config.mk @@ -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 diff --git a/arch/arm/lib/Makefile b/arch/arm/lib/Makefile index caa62c6..a812306 100644 --- a/arch/arm/lib/Makefile +++ b/arch/arm/lib/Makefile @@ -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 index 0000000..967c885 --- /dev/null +++ b/arch/arm/lib/crt0_arm_efi.S @@ -0,0 +1,138 @@ +/* + * crt0-efi-arm.S - PE/COFF header for ARM EFI applications + * + * Copright (C) 2014 Linaro Ltd. + * + * 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 index 0000000..59f66a1 --- /dev/null +++ b/arch/arm/lib/elf_arm_efi.lds @@ -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 index 0000000..d2f96ee --- /dev/null +++ b/arch/arm/lib/reloc_arm_efi.c @@ -0,0 +1,66 @@ +/* + * reloc_arm.c - position-independent ARM ELF shared object relocator + * + * Copyright (C) 2014 Linaro Ltd. + * Copyright (C) 1999 Hewlett-Packard Co. + * Contributed by David Mosberger . + * + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + * This file is taken and modified from the gnu-efi project. + */ + +#include +#include + +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; +} diff --git a/cmd/Kconfig b/cmd/Kconfig index ebcfd6d..a1ce4b7 100644 --- a/cmd/Kconfig +++ b/cmd/Kconfig @@ -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 -- 2.7.4