Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 10 May 2015 19:14:28 +0000 (UTC)
From:      Ian Lepore <ian@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r282731 - head/sys/boot/arm/uboot
Message-ID:  <201505101914.t4AJESCC006158@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: ian
Date: Sun May 10 19:14:28 2015
New Revision: 282731
URL: https://svnweb.freebsd.org/changeset/base/282731

Log:
  Create a relocatable instance of ubldr for ARM.  The original ubldr,
  static-linked to run at a fixed position, is still installed to maintain
  compatibility with existing configurations.  The makefile now also creates
  and installs ubldr.bin, a stripped binary (no elf headers) with an entry
  point offset of 0 that can be loaded by u-boot at any address and launched
  with "go ${loadaddr}".
  
  To use ubldr.bin, U-Boot must still be built with the CONFIG_API option,
  but no longer needs the CONFIG_ELF option.

Modified:
  head/sys/boot/arm/uboot/Makefile
  head/sys/boot/arm/uboot/start.S

Modified: head/sys/boot/arm/uboot/Makefile
==============================================================================
--- head/sys/boot/arm/uboot/Makefile	Sun May 10 17:11:04 2015	(r282730)
+++ head/sys/boot/arm/uboot/Makefile	Sun May 10 19:14:28 2015	(r282731)
@@ -2,7 +2,8 @@
 
 .include <src.opts.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 ${.C
 	cat ${.ALLSRC} | \
 	    awk -f ${.CURDIR}/../../common/merge_help.awk > ${.TARGET}
 
-${PROG}: ldscript.generated ${.CURDIR}/ldscript.${MACHINE_CPUARCH}
+ldscript.abs:
+	echo "UBLDR_LOADADDR = ${UBLDR_LOADADDR};" >${.TARGET}
+
+ldscript.pie:
+	echo "UBLDR_LOADADDR = 0;" >${.TARGET}
+
+ubldr: ${OBJS} ldscript.abs ${.CURDIR}/ldscript.${MACHINE_CPUARCH}
+	${CC} ${CFLAGS} -T ldscript.abs ${LDFLAGS} \
+	    -o ${.TARGET} ${OBJS} ${LDADD}
+
+ubldr.pie: ${OBJS} ldscript.pie ${.CURDIR}/ldscript.${MACHINE_CPUARCH}
+	${CC} ${CFLAGS} -T ldscript.pie ${LDFLAGS} -pie -Wl,-Bsymbolic \
+	    -o ${.TARGET} ${OBJS} ${LDADD}
+
+ubldr.bin: ubldr.pie
+	${OBJCOPY} -S -O binary ubldr.pie ${.TARGET}
 
-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
+CLEANFILES+=	ldscript.abs ldscript.pie ubldr ubldr.pie ubldr.bin
 
 .if !defined(LOADER_ONLY)
 .PATH: ${.CURDIR}/../../forth

Modified: head/sys/boot/arm/uboot/start.S
==============================================================================
--- head/sys/boot/arm/uboot/start.S	Sun May 10 17:11:04 2015	(r282730)
+++ head/sys/boot/arm/uboot/start.S	Sun May 10 19:14:28 2015	(r282731)
@@ -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()
  */



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201505101914.t4AJESCC006158>