@ -8,7 +8,9 @@
# include <asm-generic/sections.h>
# include <asm-generic/sections.h>
extern ulong __image_copy_start ;
extern ulong __image_copy_start ;
extern ulong __ivt_start ;
extern ulong __ivt_end ;
extern ulong __ivt_end ;
extern ulong __text_end ;
DECLARE_GLOBAL_DATA_PTR ;
DECLARE_GLOBAL_DATA_PTR ;
@ -48,7 +50,7 @@ int do_elf_reloc_fixups(void)
debug ( " Section .rela.dyn is located at %08x-%08x \n " ,
debug ( " Section .rela.dyn is located at %08x-%08x \n " ,
( unsigned int ) re_src , ( unsigned int ) re_end ) ;
( unsigned int ) re_src , ( unsigned int ) re_end ) ;
Elf32_Addr * offset_ptr_rom , * last_offset = NULL ;
Elf32_Addr * offset_ptr_rom ;
Elf32_Addr * offset_ptr_ram ;
Elf32_Addr * offset_ptr_ram ;
do {
do {
@ -57,15 +59,28 @@ int do_elf_reloc_fixups(void)
/* Check that the location of the relocation is in .text */
/* Check that the location of the relocation is in .text */
if ( offset_ptr_rom > = ( Elf32_Addr * ) & __image_copy_start & &
if ( offset_ptr_rom > = ( Elf32_Addr * ) & __image_copy_start & &
offset_ptr_rom > last_offset ) {
offset_ptr_rom < ( Elf32_Addr * ) & __image_copy_end ) {
unsigned int val ;
unsigned int val , do_swap = 0 ;
/* Switch to the in-RAM version */
/* Switch to the in-RAM version */
offset_ptr_ram = ( Elf32_Addr * ) ( ( ulong ) offset_ptr_rom +
offset_ptr_ram = ( Elf32_Addr * ) ( ( ulong ) offset_ptr_rom +
gd - > reloc_off ) ;
gd - > reloc_off ) ;
debug ( " Patching value @ %08x (relocated to %08x) \n " ,
# ifdef __LITTLE_ENDIAN__
/* If location in ".text" section swap value */
if ( ( ( u32 ) offset_ptr_rom > = ( u32 ) & __text_start & &
( u32 ) offset_ptr_rom < = ( u32 ) & __text_end )
# if defined(__ARC700__) || defined(__ARC600__)
| | ( ( u32 ) offset_ptr_rom > = ( u32 ) & __ivt_start & &
( u32 ) offset_ptr_rom < = ( u32 ) & __ivt_end )
# endif
)
do_swap = 1 ;
# endif
debug ( " Patching value @ %08x (relocated to %08x)%s \n " ,
( unsigned int ) offset_ptr_rom ,
( unsigned int ) offset_ptr_rom ,
( unsigned int ) offset_ptr_ram ) ;
( unsigned int ) offset_ptr_ram ,
do_swap ? " , middle-endian encoded " : " " ) ;
/*
/*
* Use " memcpy " because target location might be
* Use " memcpy " because target location might be
@ -75,28 +90,45 @@ int do_elf_reloc_fixups(void)
*/
*/
memcpy ( & val , offset_ptr_ram , sizeof ( int ) ) ;
memcpy ( & val , offset_ptr_ram , sizeof ( int ) ) ;
# ifdef __LITTLE_ENDIAN__
if ( do_swap )
/* If location in ".text" section swap value */
if ( ( unsigned int ) offset_ptr_rom <
( unsigned int ) & __ivt_end )
val = ( val < < 16 ) | ( val > > 16 ) ;
val = ( val < < 16 ) | ( val > > 16 ) ;
# endif
/* Check that the target points into executable */
/* Check that the target points into executable */
if ( val > = ( unsigned int ) & __image_copy_start & & val < =
if ( val < ( unsigned int ) & __image_copy_start | |
( unsigned int ) & __image_copy_end ) {
val > ( unsigned int ) & __image_copy_end ) {
val + = gd - > reloc_off ;
/* TODO: Use panic() instead of debug()
# ifdef __LITTLE_ENDIAN__
*
/* If location in ".text" section swap value */
* For some reason GCC might generate
if ( ( unsigned int ) offset_ptr_rom <
* fake relocation even for LD / SC of constant
( unsigned int ) & __ivt_end )
* inderectly . See an example below :
val = ( val < < 16 ) | ( val > > 16 ) ;
* - - - - - - - - - - - - - - - - - - - - - - - > 8 - - - - - - - - - - - - - - - - - - - -
# endif
* static int setup_mon_len ( void )
memcpy ( offset_ptr_ram , & val , sizeof ( int ) ) ;
* {
* gd - > mon_len = ( ulong ) & __bss_end - CONFIG_SYS_MONITOR_BASE ;
* return 0 ;
* }
* - - - - - - - - - - - - - - - - - - - - - - - > 8 - - - - - - - - - - - - - - - - - - - -
*
* And that ' s what we get in the binary :
* - - - - - - - - - - - - - - - - - - - - - - - > 8 - - - - - - - - - - - - - - - - - - - -
* 10005 cb4 < setup_mon_len > :
* 10005 cb4 : 193 c 3f 80 0003 2f 80 st 0x32f80 , [ r25 , 60 ]
* 10005 cb8 : R_ARC_RELATIVE * ABS * - 0x10000000
* 10005 cbc : 7f e0 j_s . d [ blink ]
* 10005 cbe : 700 c mov_s r0 , 0
* - - - - - - - - - - - - - - - - - - - - - - - > 8 - - - - - - - - - - - - - - - - - - - -
*/
debug ( " Relocation target %08x points outside of image \n " ,
val ) ;
}
}
}
last_offset = offset_ptr_rom ;
val + = gd - > reloc_off ;
if ( do_swap )
val = ( val < < 16 ) | ( val > > 16 ) ;
memcpy ( offset_ptr_ram , & val , sizeof ( int ) ) ;
}
} while ( + + re_src < re_end ) ;
} while ( + + re_src < re_end ) ;
return 0 ;
return 0 ;