summaryrefslogtreecommitdiffstats
path: root/sys/boot/arm
diff options
context:
space:
mode:
authorian <ian@FreeBSD.org>2015-05-25 01:06:55 +0000
committerian <ian@FreeBSD.org>2015-05-25 01:06:55 +0000
commite82e4a2984f477320d58c14411c8586e21927e7f (patch)
tree3a6c2f4b5391fdbd325cc93515716b0cabf36c16 /sys/boot/arm
parent78deac1ab875086fbd65b24fcda18097e5692921 (diff)
downloadFreeBSD-src-e82e4a2984f477320d58c14411c8586e21927e7f.zip
FreeBSD-src-e82e4a2984f477320d58c14411c8586e21927e7f.tar.gz
MFC r277962, r277988, r282661, r282727, r282731, r283013, r283035:
Add support for booting relocatable kernels on PowerPC. Add code to support loading relocatable kernels at offsets that are not zero. Move ubldr text section to the start of the output file, so that when you create a stripped .bin file from it the entry point is the first byte of the file. (Will allow "load $addr $file ; go $addr" in u-boot.) Create a relocatable instance of ubldr for ARM (ubldr.bin). Re-link ubldr when any of its libraries change. An ARM kernel can be loaded at any 2MB boundary, make ubldr aware of that.
Diffstat (limited to 'sys/boot/arm')
-rw-r--r--sys/boot/arm/uboot/Makefile40
-rw-r--r--sys/boot/arm/uboot/ldscript.arm18
-rw-r--r--sys/boot/arm/uboot/start.S48
3 files changed, 72 insertions, 34 deletions
diff --git a/sys/boot/arm/uboot/Makefile b/sys/boot/arm/uboot/Makefile
index 8f718be..b4c5463 100644
--- a/sys/boot/arm/uboot/Makefile
+++ b/sys/boot/arm/uboot/Makefile
@@ -2,7 +2,8 @@
.include <bsd.own.mk>
-PROG= ubldr
+FILES= ubldr ubldr.bin
+
NEWVERSWHAT= "U-Boot loader" ${MACHINE_ARCH}
BINDIR?= /boot
INSTALLFLAGS= -b
@@ -12,7 +13,7 @@ WARNS?= 1
UBLDR_LOADADDR?= 0x1000000
# Architecture-specific loader code
-SRCS= start.S conf.c vers.c
+SRCS= start.S conf.c self_reloc.c vers.c
.if !defined(LOADER_NO_DISK_SUPPORT)
LOADER_DISK_SUPPORT?= yes
@@ -93,9 +94,7 @@ CLEANFILES+= vers.c loader.help
CFLAGS+= -ffreestanding -msoft-float
-LDFLAGS= -nostdlib -static
-LDFLAGS+= -T ldscript.generated
-LDFLAGS+= -T ${.CURDIR}/ldscript.${MACHINE_CPUARCH}
+LDFLAGS= -nostdlib -static -T ${.CURDIR}/ldscript.${MACHINE_CPUARCH}
# Pull in common loader code
.PATH: ${.CURDIR}/../../uboot/common
@@ -116,6 +115,8 @@ NO_WERROR.clang=
DPADD= ${LIBFICL} ${LIBUBOOT} ${LIBFDT} ${LIBUBOOT_FDT} ${LIBSTAND}
LDADD= ${LIBFICL} ${LIBUBOOT} ${LIBFDT} ${LIBUBOOT_FDT} -lstand
+OBJS+= ${SRCS:N*.h:R:S/$/.o/g}
+
vers.c: ${.CURDIR}/../../common/newvers.sh ${.CURDIR}/version
sh ${.CURDIR}/../../common/newvers.sh ${.CURDIR}/version ${NEWVERSWHAT}
@@ -123,17 +124,24 @@ loader.help: help.common help.uboot ${.CURDIR}/../../fdt/help.fdt
cat ${.ALLSRC} | \
awk -f ${.CURDIR}/../../common/merge_help.awk > ${.TARGET}
-${PROG}: ldscript.generated ${.CURDIR}/ldscript.${MACHINE_CPUARCH}
-
-ldscript.generated::
- rm -f ldscript.generated.tmp
- echo "UBLDR_LOADADDR = ${UBLDR_LOADADDR};" >ldscript.generated.tmp
- if diff ldscript.generated ldscript.generated.tmp > /dev/null; then \
- true; \
- else \
- rm -f ldscript.generated; \
- mv ldscript.generated.tmp ldscript.generated; \
- fi
+ldscript.abs:
+ echo "UBLDR_LOADADDR = ${UBLDR_LOADADDR};" >${.TARGET}
+
+ldscript.pie:
+ echo "UBLDR_LOADADDR = 0;" >${.TARGET}
+
+ubldr: ${OBJS} ldscript.abs ${.CURDIR}/ldscript.${MACHINE_CPUARCH} ${DPADD}
+ ${CC} ${CFLAGS} -T ldscript.abs ${LDFLAGS} \
+ -o ${.TARGET} ${OBJS} ${LDADD}
+
+ubldr.pie: ${OBJS} ldscript.pie ${.CURDIR}/ldscript.${MACHINE_CPUARCH} ${DPADD}
+ ${CC} ${CFLAGS} -T ldscript.pie ${LDFLAGS} -pie -Wl,-Bsymbolic \
+ -o ${.TARGET} ${OBJS} ${LDADD}
+
+ubldr.bin: ubldr.pie
+ ${OBJCOPY} -S -O binary ubldr.pie ${.TARGET}
+
+CLEANFILES+= ldscript.abs ldscript.pie ubldr ubldr.pie ubldr.bin
.if !defined(LOADER_ONLY)
.PATH: ${.CURDIR}/../../forth
diff --git a/sys/boot/arm/uboot/ldscript.arm b/sys/boot/arm/uboot/ldscript.arm
index b3be119..1eb10a8 100644
--- a/sys/boot/arm/uboot/ldscript.arm
+++ b/sys/boot/arm/uboot/ldscript.arm
@@ -6,6 +6,15 @@ SECTIONS
{
/* Read-only sections, merged into text segment: */
. = UBLDR_LOADADDR + SIZEOF_HEADERS;
+ .text :
+ {
+ *(.text)
+ /* .gnu.warning sections are handled specially by elf32.em. */
+ *(.gnu.warning)
+ *(.gnu.linkonce.t*)
+ } =0
+ _etext = .;
+ PROVIDE (etext = .);
.interp : { *(.interp) }
.hash : { *(.hash) }
.dynsym : { *(.dynsym) }
@@ -32,15 +41,6 @@ SECTIONS
.rela.sbss : { *(.rela.sbss) }
.rela.sdata2 : { *(.rela.sdata2) }
.rela.sbss2 : { *(.rela.sbss2) }
- .text :
- {
- *(.text)
- /* .gnu.warning sections are handled specially by elf32.em. */
- *(.gnu.warning)
- *(.gnu.linkonce.t*)
- } =0
- _etext = .;
- PROVIDE (etext = .);
.init : { *(.init) } =0
.fini : { *(.fini) } =0
.rodata : { *(.rodata) *(.gnu.linkonce.r*) }
diff --git a/sys/boot/arm/uboot/start.S b/sys/boot/arm/uboot/start.S
index 6e8f117..1ef21f3 100644
--- a/sys/boot/arm/uboot/start.S
+++ b/sys/boot/arm/uboot/start.S
@@ -29,12 +29,38 @@
#include <machine/asm.h>
#include <machine/armreg.h>
+ .text
+ .extern _C_LABEL(self_reloc), _C_LABEL(main)
+ .weak _DYNAMIC
+
/*
* Entry point to the loader that U-Boot passes control to.
*/
- .text
.globl _start
_start:
+
+#ifdef _ARM_ARCH_6
+ mrc p15, 0, ip, c1, c0, 0
+ orr ip, ip, #(CPU_CONTROL_UNAL_ENABLE)
+ orr ip, ip, #(CPU_CONTROL_AFLT_ENABLE)
+ mcr p15, 0, ip, c1, c0, 0
+#endif
+ /*
+ * Do self-relocation when the weak external symbol _DYNAMIC is non-NULL.
+ * When linked as a dynamic relocatable file, the linker automatically
+ * defines _DYNAMIC with a value that is the offset of the dynamic
+ * relocation info section.
+ * Note that we're still on u-boot's stack here, but the self_reloc
+ * code uses only a couple dozen bytes of stack space.
+ */
+ adr ip, .here_off /* .here_off is a symbol whose value */
+ ldr r0, [ip] /* is its own offset in the text seg. */
+ sub r0, ip, r0 /* Get its pc-relative address and */
+ ldr r1, .dynamic_off /* subtract its value and we get */
+ teq r1, #0 /* r0 = physaddr we were loaded at. */
+ addne r1, r1, r0 /* r1 = dynamic section physaddr. */
+ blne _C_LABEL(self_reloc) /* Do reloc if _DYNAMIC is non-NULL. */
+
/* Hint where to look for the API signature */
ldr ip, =uboot_address
str sp, [ip]
@@ -44,16 +70,20 @@ _start:
str r8, [ip, #0]
str r9, [ip, #4]
-#ifdef _ARM_ARCH_6
- mrc p15, 0, r2, c1, c0, 0
- orr r2, r2, #(CPU_CONTROL_UNAL_ENABLE)
- orr r2, r2, #(CPU_CONTROL_AFLT_ENABLE)
- mcr p15, 0, r2, c1, c0, 0
-#endif
-
- /* Start loader */
+ /*
+ * Start loader. This is basically a tail-recursion call; if main()
+ * returns, it returns to u-boot (which reports the value returned r0).
+ */
b main
+ /*
+ * Data for self-relocation, in the text segment for pc-rel access.
+ */
+.here_off:
+ .word .
+.dynamic_off:
+ .word _DYNAMIC
+
/*
* syscall()
*/
OpenPOWER on IntegriCloud