
--- arch/arm/cpu/arm926ejs/start.S | 8 ++++- arch/arm/lib/board.c | 57 +++++++++++++++++++++++++++++++++++++++- include/configs/top9000_9xe.h | 1 + 3 files changed, 63 insertions(+), 3 deletions(-)
diff --git a/arch/arm/cpu/arm926ejs/start.S b/arch/arm/cpu/arm926ejs/start.S index 5a7ae7e..b7517db 100644 --- a/arch/arm/cpu/arm926ejs/start.S +++ b/arch/arm/cpu/arm926ejs/start.S @@ -213,7 +213,7 @@ relocate_code: /* Set up the stack */ stack_setup: mov sp, r4 - +#ifndef CONFIG_USE_C_RELOCATION adr r0, _start ldr r2, _TEXT_BASE ldr r3, _bss_start_ofs @@ -266,7 +266,7 @@ fixnext: str r1, [r0] add r2, r2, #8 /* each rel.dyn entry is 8 bytes */ cmp r2, r3 - ble fixloop + blt fixloop #endif #endif /* #ifndef CONFIG_SKIP_RELOCATE_UBOOT */
@@ -288,6 +288,7 @@ clbss_l:str r2, [r0] /* clear loop... */ bl coloured_LED_init bl red_LED_on #endif +#endif /* CONFIG_USE_C_RELOCATION */
/* * We are done. Do not return, instead branch to second part of board @@ -314,10 +315,13 @@ _board_init_r_ofs: .word board_init_r - _start #endif
+.globl _rel_dyn_start_ofs _rel_dyn_start_ofs: .word __rel_dyn_start - _start +.globl _rel_dyn_end_ofs _rel_dyn_end_ofs: .word __rel_dyn_end - _start +.globl _dynsym_start_ofs _dynsym_start_ofs: .word __dynsym_start - _start
diff --git a/arch/arm/lib/board.c b/arch/arm/lib/board.c index e411d93..0b6b3ed 100644 --- a/arch/arm/lib/board.c +++ b/arch/arm/lib/board.c @@ -37,7 +37,7 @@ * IRQ Stack: 00ebff7c * FIQ Stack: 00ebef7c */ - +#define DEBUG #include <common.h> #include <command.h> #include <malloc.h> @@ -50,6 +50,10 @@ #include <onenand_uboot.h> #include <mmc.h>
+#ifdef CONFIG_USE_C_RELOCATION +#include <elf.h> +#endif + #ifdef CONFIG_BITBANGMII #include <miiphy.h> #endif @@ -509,6 +513,15 @@ void board_init_f (ulong bootflag) init_fnc_t **init_fnc_ptr; gd_t *id; ulong addr, addr_sp; +#ifdef CONFIG_USE_C_RELOCATION + extern ulong _dynsym_start_ofs; + extern ulong _rel_dyn_start_ofs; + extern ulong _rel_dyn_end_ofs; + extern ulong _bss_start_ofs; + extern ulong _bss_end_ofs; + Elf32_Rel *rel_dyn_ptr; + ulong *p; +#endif
/* Pointer is writable since we allocated a register for it */ gd = (gd_t *) (CONFIG_SYS_INIT_SP_ADDR); @@ -661,6 +674,48 @@ void board_init_f (ulong bootflag) debug ("relocation Offset is: %08lx\n", gd->reloc_off); memcpy (id, (void *)gd, sizeof (gd_t));
+#ifdef CONFIG_USE_C_RELOCATION + /* TODO: check for identical source and destination */ + /* TODO: check for overlapping */ + /* copy image, including initialized data */ + debug ("memcpy(%08lx,%08lx,%ld)\n", + addr, _TEXT_BASE, _bss_start_ofs); + memcpy ((void *)addr, (void *)_TEXT_BASE, _bss_start_ofs); + /* now fix the code */ + debug ("_dynsym_start_ofs=%08lx _rel_dyn_start_ofs=%08lx _rel_dyn_end_ofs=%08lx\n", + _dynsym_start_ofs, _rel_dyn_start_ofs, _rel_dyn_end_ofs); + for (rel_dyn_ptr = (Elf32_Rel *)(_TEXT_BASE + _rel_dyn_start_ofs); + rel_dyn_ptr < (Elf32_Rel *)(_TEXT_BASE + _rel_dyn_end_ofs); + rel_dyn_ptr++) { + ulong *patchaddr = (ulong *) (rel_dyn_ptr->r_offset + gd->reloc_off); + debug ("patch %08lx : %08lx\n", + (ulong)patchaddr, (ulong)rel_dyn_ptr->r_info); + switch (ELF32_R_TYPE(rel_dyn_ptr->r_info)) { + case 23: /* rel fixup */ + *patchaddr += gd->reloc_off; + break; + case 2: /* abs fixup */ + { + Elf32_Sym *sym = (Elf32_Sym *)(_TEXT_BASE + _dynsym_start_ofs); + sym += ELF32_R_SYM(rel_dyn_ptr->r_info); + *patchaddr = gd->reloc_off + sym->st_value; + } + break; + default: /* unhandled fixup */ + break; + } + } + /* clear BSS */ +# ifndef CONFIG_PRELOADER + debug ("clearing BSS %08lx..%08lx\n", + addr + _bss_start_ofs, addr + _bss_end_ofs); + for (p = (ulong *)(addr + _bss_start_ofs); + p < (ulong *)(addr + _bss_end_ofs); + *p++ = 0) + ; +# endif +#endif + debug ("calling relocate_code\n"); relocate_code (addr_sp, id, addr);
/* NOTREACHED - relocate_code() does not return */ diff --git a/include/configs/top9000_9xe.h b/include/configs/top9000_9xe.h index f7fa198..e4ca026 100644 --- a/include/configs/top9000_9xe.h +++ b/include/configs/top9000_9xe.h @@ -73,6 +73,7 @@ #define CONFIG_SKIP_LOWLEVEL_INIT /*#define CONFIG_SKIP_RELOCATE_UBOOT*/ /*#define CONFIG_SYS_ARM_WITHOUT_RELOC*/ +#define CONFIG_USE_C_RELOCATION #define CONFIG_RELOC_FIXUP_WORKS #define CONFIG_SYS_NO_ICACHE #define CONFIG_SYS_NO_DCACHE