diff mbox

[U-Boot,v4,09/14] efi: arm: Add aarch64 EFI app support

Message ID 1478533636-17577-10-git-send-email-sjg@chromium.org
State Accepted
Delegated to: Alexander Graf
Headers show

Commit Message

Simon Glass Nov. 7, 2016, 3:47 p.m. UTC
Add support for EFI apps on aarch64. This includes start-up and relocation
code plus a link script.

Signed-off-by: Simon Glass <sjg@chromium.org>
---

Changes in v4:
- Add new patch to add EFI app support on aarch64

Changes in v3: None
Changes in v2: None

 arch/arm/cpu/armv8/config.mk     |   4 ++
 arch/arm/lib/crt0_aarch64_efi.S  | 135 +++++++++++++++++++++++++++++++++++++++
 arch/arm/lib/elf_aarch64_efi.lds |  70 ++++++++++++++++++++
 arch/arm/lib/reloc_aarch64_efi.c |  87 +++++++++++++++++++++++++
 4 files changed, 296 insertions(+)
 create mode 100644 arch/arm/lib/crt0_aarch64_efi.S
 create mode 100644 arch/arm/lib/elf_aarch64_efi.lds
 create mode 100644 arch/arm/lib/reloc_aarch64_efi.c

Comments

Alexander Graf Nov. 14, 2016, 11:06 p.m. UTC | #1
> Add support for EFI apps on aarch64. This includes start-up and relocation
> code plus a link script.
> 
> Signed-off-by: Simon Glass <sjg@chromium.org>

Thanks, applied to efi-next

Alex
diff mbox

Patch

diff --git a/arch/arm/cpu/armv8/config.mk b/arch/arm/cpu/armv8/config.mk
index 6850258..27b66d4 100644
--- a/arch/arm/cpu/armv8/config.mk
+++ b/arch/arm/cpu/armv8/config.mk
@@ -8,3 +8,7 @@  PLATFORM_RELFLAGS += -fno-common -ffixed-x18
 
 PF_NO_UNALIGNED := $(call cc-option, -mstrict-align)
 PLATFORM_CPPFLAGS += $(PF_NO_UNALIGNED)
+
+EFI_LDS := elf_aarch64_efi.lds
+EFI_CRT0 := crt0_aarch64_efi.o
+EFI_RELOC := reloc_aarch64_efi.o
diff --git a/arch/arm/lib/crt0_aarch64_efi.S b/arch/arm/lib/crt0_aarch64_efi.S
new file mode 100644
index 0000000..5205646
--- /dev/null
+++ b/arch/arm/lib/crt0_aarch64_efi.S
@@ -0,0 +1,135 @@ 
+/*
+ * crt0-efi-aarch64.S - PE/COFF header for aarch64 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	ImageBase
+ImageBase:
+	.ascii	"MZ"
+	.skip	58				/* 'MZ' + pad + offset == 64 */
+	.long	pe_header - ImageBase		/* Offset to the PE header */
+pe_header:
+	.ascii	"PE"
+	.short	0
+coff_header:
+	.short	0xaa64				/* AArch64 */
+	.short	2				/* nr_sections */
+	.long	0				/* TimeDateStamp */
+	.long	0				/* PointerToSymbolTable */
+	.long	1				/* NumberOfSymbols */
+	.short	section_table - optional_header	/* SizeOfOptionalHeader */
+	/*
+	 * Characteristics: IMAGE_FILE_DEBUG_STRIPPED |
+	 * IMAGE_FILE_EXECUTABLE_IMAGE | IMAGE_FILE_LINE_NUMS_STRIPPED
+	 */
+	.short	0x206
+optional_header:
+	.short	0x20b				/* PE32+ format */
+	.byte	0x02				/* MajorLinkerVersion */
+	.byte	0x14				/* MinorLinkerVersion */
+	.long	_edata - _start			/* SizeOfCode */
+	.long	0				/* SizeOfInitializedData */
+	.long	0				/* SizeOfUninitializedData */
+	.long	_start - ImageBase		/* AddressOfEntryPoint */
+	.long	_start - ImageBase		/* BaseOfCode */
+
+extra_header_fields:
+	.quad	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 - ImageBase		/* SizeOfImage */
+
+	/*
+	 * Everything before the kernel image is considered part of the header
+	 */
+	.long	_start - ImageBase		/* SizeOfHeaders */
+	.long	0				/* CheckSum */
+	.short	EFI_SUBSYSTEM			/* Subsystem */
+	.short	0				/* DllCharacteristics */
+	.quad	0				/* SizeOfStackReserve */
+	.quad	0				/* SizeOfStackCommit */
+	.quad	0				/* SizeOfHeapReserve */
+	.quad	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 - _start		/* VirtualSize */
+	.long	_start - ImageBase	/* VirtualAddress */
+	.long	_edata - _start		/* SizeOfRawData */
+	.long	_start - ImageBase	/* 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:
+	stp		x29, x30, [sp, #-32]!
+	mov		x29, sp
+
+	stp		x0, x1, [sp, #16]
+	mov		x2, x0
+	mov		x3, x1
+	adr		x0, ImageBase
+	adrp		x1, _DYNAMIC
+	add		x1, x1, #:lo12:_DYNAMIC
+	bl		_relocate
+	cbnz		x0, 0f
+
+	ldp		x0, x1, [sp, #16]
+	bl		efi_main
+
+0:	ldp		x29, x30, [sp], #32
+	ret
diff --git a/arch/arm/lib/elf_aarch64_efi.lds b/arch/arm/lib/elf_aarch64_efi.lds
new file mode 100644
index 0000000..47cce1d
--- /dev/null
+++ b/arch/arm/lib/elf_aarch64_efi.lds
@@ -0,0 +1,70 @@ 
+/*
+ * U-Boot aarch64 EFI linker script
+ *
+ * SPDX-License-Identifier:	BSD-2-Clause
+ *
+ * Modified from elf_aarch64_efi.lds in gnu-efi
+ */
+
+OUTPUT_FORMAT("elf64-littleaarch64", "elf64-littleaarch64", "elf64-littleaarch64")
+OUTPUT_ARCH(aarch64)
+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 = .;
+	}
+	.rela.dyn : { *(.rela.dyn) }
+	.rela.plt : { *(.rela.plt) }
+	.rela.got : { *(.rela.got) }
+	.rela.data : { *(.rela.data) *(.rela.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_aarch64_efi.c b/arch/arm/lib/reloc_aarch64_efi.c
new file mode 100644
index 0000000..38c13d3
--- /dev/null
+++ b/arch/arm/lib/reloc_aarch64_efi.c
@@ -0,0 +1,87 @@ 
+/* reloc_aarch64.c - position independent x86 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.
+
+    Redistribution and use in source and binary forms, with or without
+    modification, are permitted provided that the following conditions
+    are met:
+
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+    * Redistributions in binary form must reproduce the above
+      copyright notice, this list of conditions and the following
+      disclaimer in the documentation and/or other materials
+      provided with the distribution.
+    * Neither the name of Hewlett-Packard Co. nor the names of its
+      contributors may be used to endorse or promote products derived
+      from this software without specific prior written permission.
+
+    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+    CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+    INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+    MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+    DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+    BE LIABLE FOR ANYDIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+    OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+    PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+    PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+    THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
+    TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
+    THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+    SUCH DAMAGE.
+*/
+
+#include <efi.h>
+
+#include <elf.h>
+
+efi_status_t _relocate(long ldbase, Elf64_Dyn *dyn, efi_handle_t image,
+		       struct efi_system_table *systab)
+{
+	long relsz = 0, relent = 0;
+	Elf64_Rela *rel = 0;
+	unsigned long *addr;
+	int i;
+
+	for (i = 0; dyn[i].d_tag != DT_NULL; ++i) {
+		switch (dyn[i].d_tag) {
+		case DT_RELA:
+			rel = (Elf64_Rela *)((ulong)dyn[i].d_un.d_ptr + ldbase);
+			break;
+		case DT_RELASZ:
+			relsz = dyn[i].d_un.d_val;
+			break;
+		case DT_RELAENT:
+			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 (ELF64_R_TYPE(rel->r_info)) {
+		case R_AARCH64_NONE:
+			break;
+		case R_AARCH64_RELATIVE:
+			addr = (ulong *)(ldbase + rel->r_offset);
+			*addr = ldbase + rel->r_addend;
+			break;
+		default:
+			break;
+		}
+		rel = (Elf64_Rela *)((char *)rel + relent);
+		relsz -= relent;
+	}
+	return EFI_SUCCESS;
+}