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()
  */
_______________________________________________
[email protected] mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "[email protected]"

Reply via email to