summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorandrew <andrew@FreeBSD.org>2015-04-06 15:50:20 +0000
committerandrew <andrew@FreeBSD.org>2015-04-06 15:50:20 +0000
commit1b7f9d2b451da796fa328eaf44d7483ebd82c027 (patch)
tree6dea3e5f774b16e4cfd91d174934942ee4372c05
parent42eded17aa6c8b6fa27c7f83e5326e6b006396dd (diff)
downloadFreeBSD-src-1b7f9d2b451da796fa328eaf44d7483ebd82c027.zip
FreeBSD-src-1b7f9d2b451da796fa328eaf44d7483ebd82c027.tar.gz
Add support to the efi boot1 and loader for 32-bit ARM. This will be used
by the future qemu virt support. Differential Revision: https://reviews.freebsd.org/D2238 Reviewed by: emaste
-rw-r--r--sys/arm/include/metadata.h7
-rw-r--r--sys/boot/efi/Makefile2
-rw-r--r--sys/boot/efi/boot1/Makefile16
-rw-r--r--sys/boot/efi/boot1/fat-amd64.tmpl.bz2.uu (renamed from sys/boot/efi/boot1/fat.tmpl.bz2.uu)2
-rw-r--r--sys/boot/efi/boot1/fat-arm.tmpl.bz2.uu26
-rwxr-xr-xsys/boot/efi/boot1/generate-fat.sh14
-rw-r--r--sys/boot/efi/include/arm/efibind.h165
-rw-r--r--sys/boot/efi/loader/Makefile4
-rw-r--r--sys/boot/efi/loader/arch/arm/Makefile.inc5
-rw-r--r--sys/boot/efi/loader/arch/arm/exec.c107
-rw-r--r--sys/boot/efi/loader/arch/arm/ldscript.arm86
-rw-r--r--sys/boot/efi/loader/arch/arm/reloc.c83
-rw-r--r--sys/boot/efi/loader/arch/arm/start.S190
-rw-r--r--sys/boot/efi/loader/bootinfo.c34
-rw-r--r--sys/boot/efi/loader/copy.c12
15 files changed, 741 insertions, 12 deletions
diff --git a/sys/arm/include/metadata.h b/sys/arm/include/metadata.h
index 0ef3f41..cf4c9bb 100644
--- a/sys/arm/include/metadata.h
+++ b/sys/arm/include/metadata.h
@@ -31,5 +31,12 @@
#define MODINFOMD_BOOTINFO 0x1001
#define MODINFOMD_DTBP 0x1002
+#define MODINFOMD_EFI_MAP 0x1003
+
+struct efi_map_header {
+ uint64_t memory_size;
+ uint64_t descriptor_size;
+ uint32_t descriptor_version;
+};
#endif /* !_MACHINE_METADATA_H_ */
diff --git a/sys/boot/efi/Makefile b/sys/boot/efi/Makefile
index d729733..e92e03e 100644
--- a/sys/boot/efi/Makefile
+++ b/sys/boot/efi/Makefile
@@ -10,7 +10,7 @@ SUBDIR+= fdt
.endif
.endif
-.if ${MACHINE_CPUARCH} == "amd64"
+.if ${MACHINE_CPUARCH} == "amd64" || ${MACHINE_CPUARCH} == "arm"
SUBDIR+= loader boot1
.endif
diff --git a/sys/boot/efi/boot1/Makefile b/sys/boot/efi/boot1/Makefile
index 4be85f4..72537eb 100644
--- a/sys/boot/efi/boot1/Makefile
+++ b/sys/boot/efi/boot1/Makefile
@@ -36,6 +36,14 @@ LDFLAGS= -Wl,-T${LDSCRIPT} -Wl,-Bsymbolic -shared
LDFLAGS+= -Wl,-znocombreloc
.endif
+.if ${MACHINE_CPUARCH} == "arm"
+#
+# Add libstand for the __aeabi_* functions used by the compiler
+#
+DPADD+= ${LIBSTAND}
+LDADD+= -lstand
+.endif
+
${PROG}: ${LDSCRIPT}
OBJCOPY?= objcopy
@@ -45,6 +53,8 @@ OBJDUMP?= objdump
EFI_TARGET= efi-app-x86_64
.elif ${MACHINE_CPUARCH} == "i386"
EFI_TARGET= efi-app-ia32
+.else
+EFI_TARGET= binary
.endif
boot1.efi: loader.sym
@@ -52,7 +62,7 @@ boot1.efi: loader.sym
${OBJDUMP} -t ${.ALLSRC} | fgrep '*UND*'; \
exit 1; \
fi
- ${OBJCOPY} -j .text -j .sdata -j .data \
+ ${OBJCOPY} -j .peheader -j .text -j .sdata -j .data \
-j .dynamic -j .dynsym -j .rel.dyn \
-j .rela.dyn -j .reloc -j .eh_frame -j set_Xcommand_set \
--output-target=${EFI_TARGET} ${.ALLSRC} ${.TARGET}
@@ -66,8 +76,8 @@ boot1.o: ${.CURDIR}/../../common/ufsread.c
boot1.efifat: boot1.efi
echo ${.OBJDIR}
- uudecode ${.CURDIR}/fat.tmpl.bz2.uu
- mv fat.tmpl.bz2 ${.TARGET}.bz2
+ uudecode ${.CURDIR}/fat-${MACHINE_CPUARCH}.tmpl.bz2.uu
+ mv fat-${MACHINE_CPUARCH}.tmpl.bz2 ${.TARGET}.bz2
bzip2 -f -d ${.TARGET}.bz2
dd if=boot1.efi of=${.TARGET} seek=${BOOT1_OFFSET} conv=notrunc
diff --git a/sys/boot/efi/boot1/fat.tmpl.bz2.uu b/sys/boot/efi/boot1/fat-amd64.tmpl.bz2.uu
index c9044ee..d8a44b7 100644
--- a/sys/boot/efi/boot1/fat.tmpl.bz2.uu
+++ b/sys/boot/efi/boot1/fat-amd64.tmpl.bz2.uu
@@ -1,7 +1,7 @@
FAT template boot filesystem created by generate-fat.sh
DO NOT EDIT
$FreeBSD$
-begin 644 fat.tmpl.bz2
+begin 644 fat-amd64.tmpl.bz2
M0EIH.3%!629362AK*D(`&I+____[ZZKJZ_^N_ZO^Z_Z_OJ[L`4`!7I0$#&$"
M0$!$3&(<P`(;J*C:0E0E#30&AH`T````9#0```9````#)ZF0:,-3U/409,`)
M@`"8`C3",````$R:8F@P`C`````"24U,D>I-DTU,)ZAZ0VA-!M0T'J`>H#"9
diff --git a/sys/boot/efi/boot1/fat-arm.tmpl.bz2.uu b/sys/boot/efi/boot1/fat-arm.tmpl.bz2.uu
new file mode 100644
index 0000000..15b59d8
--- /dev/null
+++ b/sys/boot/efi/boot1/fat-arm.tmpl.bz2.uu
@@ -0,0 +1,26 @@
+FAT template boot filesystem created by generate-fat.sh
+DO NOT EDIT
+$FreeBSD$
+begin 644 fat-arm.tmpl.bz2
+M0EIH.3%!629365NH-?4`&T!_____ZZ[J[_ZN_ZO^J_Z[OJ_^J^J[^KZNKNNJ
+MZNKNZOJ^P`+\#$``0`&AD:,@TTTT-&C30#$R&FF1H:!B&)D&F@```-&AB::#
+M1HP0-,AD`T8F(TTP2JII&?^I5/]4`@TTT-&(T8FAB:&@T:8F(Q!@!`9,1DR9
+M`-,$:,FC)B&FC"8"#3"#(-,0`&AD:,@TTTT-&C30#$R&FF1H:!B&)D&F@```
+M-&AB::#1HP0-,AD`T8F(TTP*HI)D\DFDVC0AIIH]3(:-``80>HTTR!IH::#$
+M-`Q`:`/2:::&)IDP"/0$T:>IFD]$R8---3HUK2<PNK%<6\J]BA",-*(A%:0B
+M(B#G5%F8B$$(68C_:!`A#OL<HAB+JZ6UHRRU>*K9].C:!IWS-2UK9M<WC]W[
+M+]QW,9%V2,?<"ZEO9B("$,I.0ZFE66K/,<N6+8ITS$J3))F2I4HJ5*E2I74J
+M:$J5*E2I4JE5*I*I-2I4J5.;84I4J5*E2I6ZU4Q*E2I4J5+X<SOK,65E965D
+MT:($(0A"$(0A"$(0C>.3@8,&#!@P8(0A"$(0@0A"$(0[;_L-&C1HT:-&B+YP
+M,&#!@P8,$"$(0A"-?NW$*YY:V9IQ,:B93+AX^A7B),5HN_4JV=2\Y,:-+W'Q
+MKQKVU7KA+YR'.:*V#48N-"7<`%:TT4D`/;N;SZM9X,V(@!D'=P==+O)9*\H8
+MI8W<L9:.AU[N;G"QEHLZBWB/2B.SKCGRM):%ZK3-2U3ZV1;%MUZX:^?X_Y@N
+MM=0SN1R7Z\&PN,I8VVWKMS$1-X41%"V)-;+V9:MI5;.+M*TMZ]K7HQ-ALY1\
+M4LG)\#5/I7#7-D_1<KUPE\OW)<YEW=.GMJ%$MUF)TE9N)8[M[6LIEXF@H6?S
+MW%U89M5M+:LW6(\?7Z6I:U4F>IM*Q<2E)KFG;%M&U;INV]<)Q%^P'*<]T6R;
+M^7`P.+I+N(HA%=#(^Q0WVV0]=$2=5)>-XWKW7!95E7$<5QW)<IS6"PF@7&+H
+M&<ETI.`9F48V7/E&??ROG%<9FU^Y#E.8W+GL%]#L7+U=^CY91Q\+`K'-WPF4
+M.2S[EM@S38.8YKG.@P6_83I,-<G1DPY84N-)VMWK,/!;AIJ&3E%&7B`0A,`&
+3'65I7J6`B^?^+N2*<*$@MU!KZ@``
+`
+end
diff --git a/sys/boot/efi/boot1/generate-fat.sh b/sys/boot/efi/boot1/generate-fat.sh
index 2688da3..de42339 100755
--- a/sys/boot/efi/boot1/generate-fat.sh
+++ b/sys/boot/efi/boot1/generate-fat.sh
@@ -17,18 +17,20 @@ BOOT1_SIZE=128k
#
# Known filenames
-# amd64: BOOTx64.efi
-# arm64: BOOTaa64.efi
+# amd64: BOOTx64.efi
+# aarch64: BOOTaa64.efi
+# arm: BOOTarm.efi
#
-if [ -z "$1" ]; then
- echo "Usage: $0 filename"
+if [ -z "$2" ]; then
+ echo "Usage: $0 arch boot-filename"
exit 1
fi
-FILENAME=$1
+ARCH=$1
+FILENAME=$2
# Generate 800K FAT image
-OUTPUT_FILE=fat.tmpl
+OUTPUT_FILE=fat-${ARCH}.tmpl
dd if=/dev/zero of=$OUTPUT_FILE bs=512 count=$FAT_SIZE
DEVICE=`mdconfig -a -f $OUTPUT_FILE`
diff --git a/sys/boot/efi/include/arm/efibind.h b/sys/boot/efi/include/arm/efibind.h
new file mode 100644
index 0000000..85537ad
--- /dev/null
+++ b/sys/boot/efi/include/arm/efibind.h
@@ -0,0 +1,165 @@
+/* $FreeBSD$ */
+/*++
+
+Copyright (c) 2004 - 2012, Intel Corporation. All rights reserved.
+
+This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+
+ EfiBind.h
+
+Abstract:
+
+ Processor or Compiler specific defines and types for IA-32.
+ We are using the ANSI C 2000 _t type definitions for basic types.
+ This it technically a violation of the coding standard, but they
+ are used to make EfiTypes.h portable. Code other than EfiTypes.h
+ should never use any ANSI C 2000 _t integer types.
+
+--*/
+
+#ifndef _EFI_BIND_H_
+#define _EFI_BIND_H_
+
+
+#define EFI_DRIVER_ENTRY_POINT(InitFunction)
+#define EFI_APPLICATION_ENTRY_POINT EFI_DRIVER_ENTRY_POINT
+
+
+//
+// Make sure we are useing the correct packing rules per EFI specification
+//
+#ifndef __GNUC__
+#pragma pack()
+#endif
+
+
+#ifdef __FreeBSD__
+#include <sys/stdint.h>
+#else
+//
+// Assume standard IA-32 alignment.
+// BugBug: Need to check portability of long long
+//
+typedef unsigned long long uint64_t;
+typedef long long int64_t;
+typedef unsigned int uint32_t;
+typedef int int32_t;
+typedef unsigned short uint16_t;
+typedef short int16_t;
+typedef unsigned char uint8_t;
+typedef signed char int8_t;
+#endif
+
+typedef uint64_t UINT64;
+typedef int64_t INT64;
+typedef uint32_t UINT32;
+typedef int32_t INT32;
+typedef uint16_t UINT16;
+typedef int16_t INT16;
+typedef uint8_t UINT8;
+typedef int8_t INT8;
+
+#undef VOID
+#define VOID void
+
+//
+// Native integer size in stdint.h
+//
+typedef uint32_t UINTN;
+typedef int32_t INTN;
+
+#define EFIERR(a) (0x80000000 | a)
+#define EFI_ERROR_MASK 0x80000000
+#define EFIERR_OEM(a) (0xc0000000 | a)
+
+//
+// Processor specific defines
+//
+#define EFI_MAX_BIT 0x80000000
+#define MAX_2_BITS 0xC0000000
+
+//
+// Maximum legal IA-32 address
+//
+#define EFI_MAX_ADDRESS 0xFFFFFFFF
+
+//
+// Bad pointer value to use in check builds.
+// if you see this value you are using uninitialized or free'ed data
+//
+#define EFI_BAD_POINTER 0xAFAFAFAF
+#define EFI_BAD_POINTER_AS_BYTE 0xAF
+
+#define EFI_DEADLOOP() { volatile UINTN __iii; __iii = 1; while (__iii); }
+
+//
+// Inject a break point in the code to assist debugging for NT Emulation Environment
+// For real hardware, just put in a halt loop. Don't do a while(1) because the
+// compiler will optimize away the rest of the function following, so that you run out in
+// the weeds if you skip over it with a debugger.
+//
+#define EFI_BREAKPOINT EFI_DEADLOOP()
+
+
+//
+// Memory Fence forces serialization, and is needed to support out of order
+// memory transactions. The Memory Fence is mainly used to make sure IO
+// transactions complete in a deterministic sequence, and to syncronize locks
+// an other MP code. Currently no memory fencing is required.
+//
+#define MEMORY_FENCE()
+
+//
+// Some compilers don't support the forward reference construct:
+// typedef struct XXXXX. The forward reference is required for
+// ANSI compatibility.
+//
+// The following macro provide a workaround for such cases.
+//
+
+
+#ifdef EFI_NO_INTERFACE_DECL
+ #define EFI_FORWARD_DECLARATION(x)
+#else
+ #define EFI_FORWARD_DECLARATION(x) typedef struct _##x x
+#endif
+
+
+//
+// Some C compilers optimize the calling conventions to increase performance.
+// EFIAPI is used to make all public APIs follow the standard C calling
+// convention.
+//
+#define EFIAPI
+
+
+
+//
+// For symbol name in GNU assembly code, an extra "_" is necessary
+//
+#if defined(__GNUC__)
+ ///
+ /// Private worker functions for ASM_PFX()
+ ///
+ #define _CONCATENATE(a, b) __CONCATENATE(a, b)
+ #define __CONCATENATE(a, b) a ## b
+
+ ///
+ /// The __USER_LABEL_PREFIX__ macro predefined by GNUC represents the prefix
+ /// on symbols in assembly language.
+ ///
+ #define ASM_PFX(name) _CONCATENATE (__USER_LABEL_PREFIX__, name)
+
+#endif
+
+#define INTERFACE_DECL(x) struct x
+
+#endif
diff --git a/sys/boot/efi/loader/Makefile b/sys/boot/efi/loader/Makefile
index 8cbbaf3..3f536c8 100644
--- a/sys/boot/efi/loader/Makefile
+++ b/sys/boot/efi/loader/Makefile
@@ -87,6 +87,8 @@ OBJDUMP?= objdump
EFI_TARGET= efi-app-x86_64
.elif ${MACHINE_CPUARCH} == "i386"
EFI_TARGET= efi-app-ia32
+.else
+EFI_TARGET= binary
.endif
loader.efi: loader.sym
@@ -94,7 +96,7 @@ loader.efi: loader.sym
${OBJDUMP} -t ${.ALLSRC} | fgrep '*UND*'; \
exit 1; \
fi
- ${OBJCOPY} -j .text -j .sdata -j .data \
+ ${OBJCOPY} -j .peheader -j .text -j .sdata -j .data \
-j .dynamic -j .dynsym -j .rel.dyn \
-j .rela.dyn -j .reloc -j .eh_frame -j set_Xcommand_set \
--output-target=${EFI_TARGET} ${.ALLSRC} ${.TARGET}
diff --git a/sys/boot/efi/loader/arch/arm/Makefile.inc b/sys/boot/efi/loader/arch/arm/Makefile.inc
new file mode 100644
index 0000000..853c957
--- /dev/null
+++ b/sys/boot/efi/loader/arch/arm/Makefile.inc
@@ -0,0 +1,5 @@
+# $FreeBSD$
+
+SRCS+= exec.c \
+ start.S \
+ reloc.c
diff --git a/sys/boot/efi/loader/arch/arm/exec.c b/sys/boot/efi/loader/arch/arm/exec.c
new file mode 100644
index 0000000..1cbbce5
--- /dev/null
+++ b/sys/boot/efi/loader/arch/arm/exec.c
@@ -0,0 +1,107 @@
+/*-
+ * Copyright (c) 2001 Benno Rice <benno@FreeBSD.org>
+ * Copyright (c) 2007 Semihalf, Rafal Jaworowski <raj@semihalf.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:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, 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 <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/linker.h>
+
+#include <machine/md_var.h>
+#include <machine/metadata.h>
+#include <machine/elf.h>
+
+#include <stand.h>
+
+#include <efi.h>
+#include <efilib.h>
+
+#include "bootstrap.h"
+#include "loader_efi.h"
+
+extern vm_offset_t md_load(char *, vm_offset_t *);
+
+int
+__elfN(arm_load)(char *filename, u_int64_t dest,
+ struct preloaded_file **result)
+{
+ int r;
+
+ r = __elfN(loadfile)(filename, dest, result);
+ if (r != 0)
+ return (r);
+
+ return (0);
+}
+
+int
+__elfN(arm_exec)(struct preloaded_file *fp)
+{
+ struct file_metadata *fmp;
+ vm_offset_t modulep, kernend;
+ Elf_Ehdr *e;
+ int error;
+ void (*entry)(void *);
+ EFI_STATUS status;
+
+ if ((fmp = file_findmetadata(fp, MODINFOMD_ELFHDR)) == NULL)
+ return (EFTYPE);
+
+ e = (Elf_Ehdr *)&fmp->md_data;
+
+ if ((error = bi_load(fp->f_args, &modulep, &kernend)) != 0)
+ return (error);
+
+ entry = efi_translate(e->e_entry);
+ printf("Kernel entry at 0x%x...\n", (unsigned)entry);
+ printf("Kernel args: %s\n", fp->f_args);
+ printf("modulep: %#x\n", modulep);
+ printf("relocation_offset %llx\n", __elfN(relocation_offset));
+
+ status = BS->ExitBootServices(IH, efi_mapkey);
+ if (EFI_ERROR(status)) {
+ printf("%s: ExitBootServices() returned 0x%lx\n", __func__,
+ (long)status);
+ return (EINVAL);
+ }
+
+ dev_cleanup();
+
+ (*entry)((void *)modulep);
+ panic("exec returned");
+}
+
+static struct file_format arm_elf = {
+ __elfN(arm_load),
+ __elfN(arm_exec)
+};
+
+struct file_format *file_formats[] = {
+ &arm_elf,
+ NULL
+};
+
diff --git a/sys/boot/efi/loader/arch/arm/ldscript.arm b/sys/boot/efi/loader/arch/arm/ldscript.arm
new file mode 100644
index 0000000..0b747aa
--- /dev/null
+++ b/sys/boot/efi/loader/arch/arm/ldscript.arm
@@ -0,0 +1,86 @@
+/* $FreeBSD$ */
+OUTPUT_FORMAT("elf32-littlearm", "elf32-bigarm",
+ "elf32-littlearm")
+OUTPUT_ARCH(arm)
+ENTRY(_start)
+SECTIONS
+{
+ /* Read-only sections, merged into text segment: */
+ . = 0;
+ ImageBase = .;
+ .peheader : {
+ *(.peheader)
+ }
+ .text : {
+ *(.text .stub .text.* .gnu.linkonce.t.*)
+ /* .gnu.warning sections are handled specially by elf32.em. */
+ *(.gnu.warning)
+ *(.gnu.linkonce.t*)
+ } =0
+ _etext = .;
+ PROVIDE (etext = .);
+ . = ALIGN(4096);
+ .data :
+ {
+ *(.data)
+ *(.gnu.linkonce.d*)
+ *(.rodata)
+ *(.rodata.*)
+ CONSTRUCTORS
+ }
+ .data1 : { *(.data1) }
+ .got1 : { *(.got1) }
+ .dynamic : { *(.dynamic) }
+ /* Put .ctors and .dtors next to the .got2 section, so that the pointers
+ get relocated with -mrelocatable. Also put in the .fixup pointers.
+ The current compiler no longer needs this, but keep it around for 2.7.2 */
+ PROVIDE (_GOT2_START_ = .);
+ .got2 : { *(.got2) }
+ PROVIDE (__CTOR_LIST__ = .);
+ .ctors : { *(.ctors) }
+ PROVIDE (__CTOR_END__ = .);
+ PROVIDE (__DTOR_LIST__ = .);
+ .dtors : { *(.dtors) }
+ PROVIDE (__DTOR_END__ = .);
+ PROVIDE (_FIXUP_START_ = .);
+ .fixup : { *(.fixup) }
+ PROVIDE (_FIXUP_END_ = .);
+ PROVIDE (_GOT2_END_ = .);
+ PROVIDE (_GOT_START_ = .);
+ .got : { *(.got) }
+ .got.plt : { *(.got.plt) }
+ PROVIDE (_GOT_END_ = .);
+ /* We want the small data sections together, so single-instruction offsets
+ can access them all, and initialized data all before uninitialized, so
+ we can shorten the on-disk segment size. */
+ .sdata : { *(.sdata) }
+ _edata = .;
+ PROVIDE (edata = .);
+ set_Xcommand_set : {
+ __start_set_Xcommand_set = .;
+ *(set_Xcommand_set)
+ __stop_set_Xcommand_set = .;
+ }
+ __gp = .;
+ PROVIDE (__bss_start = .);
+ .sbss :
+ {
+ *(.sbss)
+ *(.scommon)
+ *(.dynsbss)
+ }
+ .bss :
+ {
+ *(.dynbss)
+ *(.bss)
+ *(COMMON)
+ }
+ PROVIDE (__bss_end = .);
+ .plt : { *(.plt) }
+ .dynamic : { *(.dynamic) }
+ .reloc : { *(.reloc) }
+ .hash : { *(.hash) }
+ .dynsym : { *(.dynsym) }
+ .dynstr : { *(.dynstr) }
+ _edata = .;
+}
diff --git a/sys/boot/efi/loader/arch/arm/reloc.c b/sys/boot/efi/loader/arch/arm/reloc.c
new file mode 100644
index 0000000..8b19f1b
--- /dev/null
+++ b/sys/boot/efi/loader/arch/arm/reloc.c
@@ -0,0 +1,83 @@
+/*-
+ * Copyright (c) 2008-2010 Rui Paulo <rpaulo@FreeBSD.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, 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 <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/types.h>
+#include <elf.h>
+#include <bootstrap.h>
+
+/*
+ * A simple relocator for ARM binaries.
+ */
+void
+_reloc(unsigned long ImageBase, Elf32_Dyn *dynamic)
+{
+ unsigned long relsz, relent;
+ unsigned long *newaddr;
+ Elf32_Rel *rel;
+ Elf32_Dyn *dynp;
+
+ /*
+ * Find the relocation address, its size and the relocation entry.
+ */
+ relsz = 0;
+ relent = 0;
+ for (dynp = dynamic; dynp->d_tag != DT_NULL; dynp++) {
+ switch (dynp->d_tag) {
+ case DT_REL:
+ rel = (Elf32_Rel *) ((unsigned long) dynp->d_un.d_ptr +
+ ImageBase);
+ break;
+ case DT_RELSZ:
+ relsz = dynp->d_un.d_val;
+ break;
+ case DT_RELENT:
+ relent = dynp->d_un.d_val;
+ break;
+ default:
+ break;
+ }
+ }
+
+ /*
+ * Perform the actual relocation.
+ */
+ for (; relsz > 0; relsz -= relent) {
+ switch (ELF32_R_TYPE(rel->r_info)) {
+ case R_ARM_RELATIVE:
+ /* Address relative to the base address. */
+ newaddr = (unsigned long *)(ImageBase + rel->r_offset);
+ *newaddr += ImageBase;
+ break;
+ default:
+ /* XXX: do we need other relocations ? */
+ break;
+ }
+ rel = (Elf32_Rel *) ((caddr_t) rel + relent);
+ }
+}
diff --git a/sys/boot/efi/loader/arch/arm/start.S b/sys/boot/efi/loader/arch/arm/start.S
new file mode 100644
index 0000000..0bb709c
--- /dev/null
+++ b/sys/boot/efi/loader/arch/arm/start.S
@@ -0,0 +1,190 @@
+/*-
+ * Copyright (c) 2014, 2015 Andrew Turner
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, 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.
+ *
+ * $FreeBSD$
+ */
+
+#include <machine/asm.h>
+
+/*
+ * We need to be a PE32 file for EFI. On some architectures we can use
+ * objcopy to create the correct file, however on arm we need to do
+ * it ourselves.
+ */
+
+#define IMAGE_FILE_MACHINE_ARM 0x01c2
+
+#define IMAGE_SCN_CNT_CODE 0x00000020
+#define IMAGE_SCN_CNT_INITIALIZED_DATA 0x00000040
+#define IMAGE_SCN_MEM_DISCARDABLE 0x02000000
+#define IMAGE_SCN_MEM_EXECUTE 0x20000000
+#define IMAGE_SCN_MEM_READ 0x40000000
+
+ .section .peheader
+efi_start:
+ /* The MS-DOS Stub, only used to get the offset of the COFF header */
+ .ascii "MZ"
+ .short 0
+ .space 0x38
+ .long pe_sig - efi_start
+
+ /* The PE32 Signature. Needs to be 8-byte aligned */
+ .align 3
+pe_sig:
+ .ascii "PE"
+ .short 0
+coff_head:
+ .short IMAGE_FILE_MACHINE_ARM /* ARM file */
+ .short 2 /* 2 Sections */
+ .long 0 /* Timestamp */
+ .long 0 /* No symbol table */
+ .long 0 /* No symbols */
+ .short section_table - optional_header /* Optional header size */
+ .short 0 /* Characteristics TODO: Fill in */
+
+optional_header:
+ .short 0x010b /* PE32 (32-bit addressing) */
+ .byte 0 /* Major linker version */
+ .byte 0 /* Minor linker version */
+ .long _edata - _end_header /* Code size */
+ .long 0 /* No initialized data */
+ .long 0 /* No uninitialized data */
+ .long _start - efi_start /* Entry point */
+ .long _end_header - efi_start /* Start of code */
+ .long 0 /* Start of data */
+
+optional_windows_header:
+ .long 0 /* Image base */
+ .long 32 /* Section Alignment */
+ .long 8 /* File alignment */
+ .short 0 /* Major OS version */
+ .short 0 /* Minor OS version */
+ .short 0 /* Major image version */
+ .short 0 /* Minor image version */
+ .short 0 /* Major subsystem version */
+ .short 0 /* Minor subsystem version */
+ .long 0 /* Win32 version */
+ .long _edata - efi_start /* Image size */
+ .long _end_header - efi_start /* Header size */
+ .long 0 /* Checksum */
+ .short 0xa /* Subsystem (EFI app) */
+ .short 0 /* DLL Characteristics */
+ .long 0 /* Stack reserve */
+ .long 0 /* Stack commit */
+ .long 0 /* Heap reserve */
+ .long 0 /* Heap commit */
+ .long 0 /* Loader flags */
+ .long 6 /* Number of RVAs */
+
+ /* RVAs: */
+ .quad 0
+ .quad 0
+ .quad 0
+ .quad 0
+ .quad 0
+ .quad 0
+
+section_table:
+ /* We need a .reloc section for EFI */
+ .ascii ".reloc"
+ .byte 0
+ .byte 0 /* Pad to 8 bytes */
+ .long 0 /* Virtual size */
+ .long 0 /* Virtual address */
+ .long 0 /* Size of raw data */
+ .long 0 /* Pointer to raw data */
+ .long 0 /* Pointer to relocations */
+ .long 0 /* Pointer to line numbers */
+ .short 0 /* Number of relocations */
+ .short 0 /* Number of line numbers */
+ .long (IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ | \
+ IMAGE_SCN_MEM_DISCARDABLE) /* Characteristics */
+
+ /* The contents of the loader */
+ .ascii ".text"
+ .byte 0
+ .byte 0
+ .byte 0 /* Pad to 8 bytes */
+ .long _edata - _end_header /* Virtual size */
+ .long _end_header - efi_start /* Virtual address */
+ .long _edata - _end_header /* Size of raw data */
+ .long _end_header - efi_start /* Pointer to raw data */
+ .long 0 /* Pointer to relocations */
+ .long 0 /* Pointer to line numbers */
+ .short 0 /* Number of relocations */
+ .short 0 /* Number of line numbers */
+ .long (IMAGE_SCN_CNT_CODE | IMAGE_SCN_MEM_EXECUTE | \
+ IMAGE_SCN_MEM_READ) /* Characteristics */
+_end_header:
+
+ .text
+_start:
+ /* Save the boot params to the stack */
+ push {r0, r1}
+
+ adr r0, .Lbase
+ ldr r1, [r0]
+ sub r5, r0, r1
+
+ ldr r0, .Limagebase
+ add r0, r0, r5
+ ldr r1, .Ldynamic
+ add r1, r1, r5
+
+ bl _C_LABEL(_reloc)
+
+ /* Zero the BSS, _reloc fixed the values for us */
+ ldr r0, .Lbss
+ ldr r1, .Lbssend
+ mov r2, #0
+
+1: cmp r0, r1
+ bgt 2f
+ str r2, [r0], #4
+ b 1b
+2:
+
+ pop {r0, r1}
+ bl _C_LABEL(efi_main)
+
+1: WFI
+ b 1b
+
+.Lbase:
+ .word .
+.Limagebase:
+ .word ImageBase
+.Ldynamic:
+ .word _DYNAMIC
+.Lbss:
+ .word __bss_start
+.Lbssend:
+ .word __bss_end
+
+.align 3
+stack:
+ .space 512
+stack_end:
+
diff --git a/sys/boot/efi/loader/bootinfo.c b/sys/boot/efi/loader/bootinfo.c
index d6607cd..988bdf2 100644
--- a/sys/boot/efi/loader/bootinfo.c
+++ b/sys/boot/efi/loader/bootinfo.c
@@ -219,6 +219,9 @@ bi_copymodules(vm_offset_t addr)
if (fp->f_args)
MOD_ARGS(addr, fp->f_args, c);
v = fp->f_addr;
+#if defined(__arm__)
+ v -= __elfN(relocation_offset);
+#endif
MOD_ADDR(addr, v, c);
v = fp->f_size;
MOD_SIZE(addr, v, c);
@@ -332,6 +335,21 @@ bi_load(char *args, vm_offset_t *modulep, vm_offset_t *kernendp)
vm_offset_t dtbp;
int dtb_size;
#endif
+#if defined(__arm__)
+ vm_offset_t vaddr;
+ int i;
+ /*
+ * These metadata addreses must be converted for kernel after
+ * relocation.
+ */
+ uint32_t mdt[] = {
+ MODINFOMD_SSYM, MODINFOMD_ESYM, MODINFOMD_KERNEND,
+ MODINFOMD_ENVP,
+#if defined(LOADER_FDT_SUPPORT)
+ MODINFOMD_DTBP
+#endif
+ };
+#endif
howto = bi_getboothowto(args);
@@ -405,6 +423,22 @@ bi_load(char *args, vm_offset_t *modulep, vm_offset_t *kernendp)
md = file_findmetadata(kfp, MODINFOMD_KERNEND);
bcopy(&kernend, md->md_data, sizeof kernend);
+#if defined(__arm__)
+ *modulep -= __elfN(relocation_offset);
+
+ /* Do relocation fixup on metadata of each module. */
+ for (xp = file_findfile(NULL, NULL); xp != NULL; xp = xp->f_next) {
+ for (i = 0; i < sizeof mdt / sizeof mdt[0]; i++) {
+ md = file_findmetadata(xp, mdt[i]);
+ if (md) {
+ bcopy(md->md_data, &vaddr, sizeof vaddr);
+ vaddr -= __elfN(relocation_offset);
+ bcopy(&vaddr, md->md_data, sizeof vaddr);
+ }
+ }
+ }
+#endif
+
/* Copy module list and metadata. */
(void)bi_copymodules(addr);
diff --git a/sys/boot/efi/loader/copy.c b/sys/boot/efi/loader/copy.c
index 1da3f43..406e945 100644
--- a/sys/boot/efi/loader/copy.c
+++ b/sys/boot/efi/loader/copy.c
@@ -61,9 +61,21 @@ efi_copy_init(void)
}
staging_end = staging + STAGE_PAGES * 4096;
+#ifdef __arm__
+ /* Round the kernel load address to a 2MiB value */
+ staging = roundup2(staging, 2 * 1024 * 1024);
+#endif
+
return (0);
}
+void *
+efi_translate(vm_offset_t ptr)
+{
+
+ return ((void *)(ptr + stage_offset));
+}
+
ssize_t
efi_copyin(const void *src, vm_offset_t dest, const size_t len)
{
OpenPOWER on IntegriCloud