summaryrefslogtreecommitdiffstats
path: root/sys/arm
diff options
context:
space:
mode:
authorcognet <cognet@FreeBSD.org>2010-11-01 21:04:23 +0000
committercognet <cognet@FreeBSD.org>2010-11-01 21:04:23 +0000
commit71407681fdd1b75689f0d0a1e99666c0b45dfc6a (patch)
tree7e278202cc6548bf07fe1689d58e09152d1e5880 /sys/arm
parenta4ab528826d1ac9cc9de0ba3fead29d68b978e3e (diff)
downloadFreeBSD-src-71407681fdd1b75689f0d0a1e99666c0b45dfc6a.zip
FreeBSD-src-71407681fdd1b75689f0d0a1e99666c0b45dfc6a.tar.gz
Try to be a little smart at guessing where _start is located in flash, instead
of relying on a binutils bug. Reported by: dim
Diffstat (limited to 'sys/arm')
-rw-r--r--sys/arm/arm/elf_trampoline.c6
1 files changed, 4 insertions, 2 deletions
diff --git a/sys/arm/arm/elf_trampoline.c b/sys/arm/arm/elf_trampoline.c
index 0f725c8..4adb025 100644
--- a/sys/arm/arm/elf_trampoline.c
+++ b/sys/arm/arm/elf_trampoline.c
@@ -159,7 +159,7 @@ _startC(void)
#if defined(FLASHADDR) && defined(LOADERRAMADDR)
unsigned int pc;
- __asm __volatile("adr %0, _start\n"
+ __asm __volatile("mov %0, pc\n"
: "=r" (pc));
if ((FLASHADDR > LOADERRAMADDR && pc >= FLASHADDR) ||
(FLASHADDR < LOADERRAMADDR && pc < LOADERRAMADDR)) {
@@ -173,11 +173,13 @@ _startC(void)
*/
unsigned int target_addr;
unsigned int tmp_sp;
+ uint32_t src_addr = (uint32_t)&_start - PHYSADDR + FLASHADDR
+ + (pc - FLASHADDR - ((uint32_t)&_startC - PHYSADDR)) & 0xfffff000;
target_addr = (unsigned int)&_start - PHYSADDR + LOADERRAMADDR;
tmp_sp = target_addr + 0x100000 +
(unsigned int)&_end - (unsigned int)&_start;
- memcpy((char *)target_addr, (char *)pc,
+ memcpy((char *)target_addr, (char *)src_addr,
(unsigned int)&_end - (unsigned int)&_start);
/* Temporary set the sp and jump to the new location. */
__asm __volatile(
OpenPOWER on IntegriCloud