[U-Boot] [PATCH] futile c relocation attempt

Reinhard Meyer u-boot at emk-elektronik.de
Tue Oct 5 16:48:52 CEST 2010


---
 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
-- 
1.5.6.5



More information about the U-Boot mailing list