
Peter Tyser ptyser@xes-inc.com wrote on 23/09/2009 14:57:19:
I made the same changes recently, but ran into an "issue" that prevented me from sending the change upstream. Some boards/arches have the bss at address 0 and later relocate it, unlike every other NULL pointer. If you don't fix up the bss address, the board will not function. If you run readelf on an 83xx u-boot image vs a 85xx u-boot image it should be more clear what's going on. I was doing my testing on the XPedite5370 fwiw.
Ouch, the horror continues :(
Yeah... Its seemingly never ending:)
In any case, the change as is would break some other arches. Seems like the proper workaround would be to "fix" the 85xx (and other arches) link script to locate the bss similar to the 83xx boards.
Yes, something should be done. Does it work for you with a "fixed" linker script?
My "fix" to the linker script was to change: __bss_start = .; into: __bss_start = . | 4;
ie, a big hack, but it did work:) I'll take a peek at a more proper link script workaround.
It might be nice to consolidate all the ppc relocate code into 1 function while we were at it.
Played around a little and this is what I got sofar, possibly WS damged and fixups untested:
Nice! It'd be great to have the magical 20 lines of assembly put into some semi-understandable c.
Played some more and got this, running out of time now so I figured I should post as is in case you (or someone else) wants to play some more. I will answer questions though.
From 684443ce6870eac2878026e47cc107fbfcdefc02 Mon Sep 17 00:00:00 2001
From: Joakim Tjernlund Joakim.Tjernlund@transmode.se Date: Wed, 23 Sep 2009 18:41:44 +0200 Subject: [PATCH] relocation: Use C as much as possible to do relocation.
--- cpu/mpc83xx/start.S | 64 ++++++++++++++++++++++++++++++++------------------ lib_ppc/board.c | 21 ++++++++++++++++- 2 files changed, 61 insertions(+), 24 deletions(-)
diff --git a/cpu/mpc83xx/start.S b/cpu/mpc83xx/start.S index 868b070..ccd337a 100644 --- a/cpu/mpc83xx/start.S +++ b/cpu/mpc83xx/start.S @@ -307,6 +307,39 @@ in_flash: /* run 1st part of board init code (in Flash)*/ bl board_init_f
+ .globl got_off /* void * got_off(void * ptr) */ +got_off: + /* Adds GOT offset to ptr, might be useful for true PIC too */ + /* Would be great if this could be inline C __asm__ instead */ +#if 1 + /* Hand coded as we cannot clobber r14 when called from C */ + mflr r4 + bl 1f + .text 2 +0: .long .LCTOC1-1f + .text +1: mflr r6 + lwz r0,0b-1b(r6) + add r6,r0,r6 + mtlr r4 + addi r4,r6,.L__GOT2_TABLE_ + lwz r5, .L__GOT2_TABLE_(r6) + sub r4,r5,r4 + sub r3,r3,r4 + blr +#else + /* Use predefined macros instead */ + mflr r4 + mr r6,r14 /* GET_GOT clobbers r14 so save it */ + GET_GOT + mtlr r4 + la r4,GOT(_GOT2_TABLE_) /* addi r4, r14, .L__GOT2_TABLE_ */ + lwz r5,GOT(_GOT2_TABLE_) /* lwz r5, .L__GOT2_TABLE_(r14) */ + sub r4,r5,r4 + sub r3,r3,r4 + mr r6,r14 + blr +#endif #ifndef CONFIG_NAND_SPL /* * Vector Table @@ -842,8 +875,8 @@ flush_dcache: .globl relocate_code relocate_code: mr r1, r3 /* Set new stack pointer */ - mr r9, r4 /* Save copy of Global Data pointer */ - mr r10, r5 /* Save copy of Destination Address */ + mr r16, r4 /* Save copy of Global Data pointer */ + mr r17, r5 /* Save copy of Destination Address */
mr r3, r5 /* Destination Address */ lis r4, CONFIG_SYS_MONITOR_BASE@h /* Source Address */ @@ -860,7 +893,7 @@ relocate_code: * * Offset: */ - sub r15, r10, r4 + sub r15, r17, r4
/* First our own GOT */ add r14, r14, r15 @@ -938,7 +971,7 @@ relocate_code: * We are done. Do not return, instead branch to second part of board * initialization, now running from RAM. */ - addi r0, r10, in_ram - _start + EXC_OFF_SYS_RESET + addi r0, r17, in_ram - _start + EXC_OFF_SYS_RESET mtlr r0 blr
@@ -950,24 +983,9 @@ in_ram: * Adjust got2 pointers, no need to check for 0, this code * already puts a few entries in the table. */ - la r3,GOT(_GOT2_TABLE_) - li r4,__got2_entries@sectoff@l - lwz r5,GOT(_GOT2_TABLE_) - sub r5,r3,r5 - mr r30,r5 - bl __eabi_convert - -#ifndef CONFIG_NAND_SPL - /* - * Now adjust the fixups and the pointers to the fixups - * in case we need to move ourselves again. - */ - lwz r3,GOT(_FIXUP_TABLE_) + li r3,__got2_entries@sectoff@l li r4,__fixup_entries@sectoff@l - mr r5,r30 - bl __eabi_uconvert -#endif - + bl __do_eabi_reloc clear_bss: /* * Now clear BSS segment @@ -997,8 +1015,8 @@ clear_bss: bne 5b 6:
- mr r3, r9 /* Global Data pointer */ - mr r4, r10 /* Destination Address */ + mr r3, r16 /* Global Data pointer */ + mr r4, r17 /* Destination Address */ bl board_init_r
#ifndef CONFIG_NAND_SPL diff --git a/lib_ppc/board.c b/lib_ppc/board.c index 0afc7c3..2a9b16e 100644 --- a/lib_ppc/board.c +++ b/lib_ppc/board.c @@ -147,7 +147,9 @@ static ulong mem_malloc_brk = 0; * Utilities * ************************************************************************ */ - +extern unsigned long *_GOT2_TABLE_; +extern unsigned long *_FIXUP_TABLE_; +extern void * got_off(void*); /* Relocate the .got2 pointers. */ void __eabi_convert(unsigned long *low, unsigned long len, unsigned long addend) @@ -178,6 +180,23 @@ void __eabi_uconvert(unsigned long *low, unsigned long len, *v2p = val2; } } +void __do_eabi_reloc(unsigned long got2_len, unsigned long fixup_len) +{ + unsigned long addend = (unsigned long)got_off(NULL); + unsigned long *low; + + low = (unsigned long *)(*_GOT2_TABLE_ + addend); + printf("GOT2:%lx, addend:%lx low:%p\n", + *_GOT2_TABLE_, addend, low); + __eabi_convert(low, got2_len, addend); + +#ifndef CONFIG_NAND_SPL + low = (unsigned long *)(*_FIXUP_TABLE_ + addend); + printf("FIXUP:%lx, addend:%lx low:%p\n", + *_FIXUP_TABLE_, addend, low); + __eabi_uconvert(low, fixup_len, addend); +#endif +}
/* * The Malloc area is immediately below the monitor copy in DRAM -- 1.6.4.4