[U-Boot] [PATCH 23/26 v2][NEXT] ARM: implement relocation for lh7a40x

Heiko Schocher hs at denx.de
Fri Sep 17 13:10:50 CEST 2010


Change the implementation for lh7a40x to relocate the code to
an arbitrary address in RAM.

Portions of this work were supported by funding from
the CE Linux Forum.

Signed-off-by: Heiko Schocher <hs at denx.de>
---
 arch/arm/cpu/lh7a40x/start.S    |  187 ++++++++++++++++++++++++++++++++++++++-
 arch/arm/cpu/lh7a40x/u-boot.lds |   14 +++-
 2 files changed, 199 insertions(+), 2 deletions(-)

diff --git a/arch/arm/cpu/lh7a40x/start.S b/arch/arm/cpu/lh7a40x/start.S
index 14a1fbe..002116a 100644
--- a/arch/arm/cpu/lh7a40x/start.S
+++ b/arch/arm/cpu/lh7a40x/start.S
@@ -72,12 +72,15 @@ _fiq:			.word fiq
  *************************************************************************
  */
 
+.globl _TEXT_BASE
 _TEXT_BASE:
 	.word	TEXT_BASE
 
+#if defined(CONFIG_SYS_ARM_WITHOUT_RELOC)
 .globl _armboot_start
 _armboot_start:
 	.word _start
+#endif
 
 /*
  * These are defined in the board-specific linker script.
@@ -102,8 +105,182 @@ FIQ_STACK_START:
 	.word 0x0badc0de
 #endif
 
+#if !defined(CONFIG_SYS_ARM_WITHOUT_RELOC)
+/* IRQ stack memory (calculated at run-time) + 8 bytes */
+.globl IRQ_STACK_START_IN
+IRQ_STACK_START_IN:
+	.word	0x0badc0de
+
+.globl _datarel_start
+_datarel_start:
+	.word __datarel_start
+
+.globl _datarelrolocal_start
+_datarelrolocal_start:
+	.word __datarelrolocal_start
+
+.globl _datarellocal_start
+_datarellocal_start:
+	.word __datarellocal_start
+
+.globl _datarelro_start
+_datarelro_start:
+	.word __datarelro_start
+
+.globl _got_start
+_got_start:
+	.word __got_start
+
+.globl _got_end
+_got_end:
+	.word __got_end
+
+/*
+ * the actual reset code
+ */
+
+reset:
+	/*
+	 * set the cpu to SVC32 mode
+	 */
+	mrs	r0,cpsr
+	bic	r0,r0,#0x1f
+	orr	r0,r0,#0xd3
+	msr	cpsr,r0
+
+#define pWDTCTL		0x80001400  /* Watchdog Timer control register */
+#define pINTENC		0x8000050C  /* Interupt-Controller enable clear register */
+#define pCLKSET		0x80000420  /* clock divisor register */
+
+	/* disable watchdog, set watchdog control register to
+	 * all zeros (default reset)
+	 */
+	ldr     r0, =pWDTCTL
+	mov     r1, #0x0
+	str     r1, [r0]
+
+	/*
+	 * mask all IRQs by setting all bits in the INTENC register (default)
+	 */
+	mov	r1, #0xffffffff
+	ldr	r0, =pINTENC
+	str	r1, [r0]
+
+	/* FCLK:HCLK:PCLK = 1:2:2 */
+	/* default FCLK is 200 MHz, using 14.7456 MHz fin */
+	ldr	r0, =pCLKSET
+	ldr r1, =0x0004ee39
+@	ldr r1, =0x0005ee39	@ 1: 2: 4
+	str	r1, [r0]
+
+	/*
+	 * we do sys-critical inits only at reboot,
+	 * not when booting from ram!
+	 */
+#ifndef CONFIG_SKIP_LOWLEVEL_INIT
+	bl	cpu_init_crit
+#endif
+
+/* Set stackpointer in internal RAM to call board_init_f */
+call_board_init_f:
+	ldr	sp, =(CONFIG_SYS_INIT_SP_ADDR)
+	ldr	r0,=0x00000000
+	bl	board_init_f
+
+/*------------------------------------------------------------------------------*/
 
 /*
+ * void relocate_code (addr_sp, gd, addr_moni)
+ *
+ * This "function" does not return, instead it continues in RAM
+ * after relocating the monitor code.
+ *
+ */
+	.globl	relocate_code
+relocate_code:
+	mov	r4, r0	/* save addr_sp */
+	mov	r5, r1	/* save addr of gd */
+	mov	r6, r2	/* save addr of destination */
+	mov	r7, r2	/* save addr of destination */
+
+	/* Set up the stack						    */
+stack_setup:
+	mov	sp, r4
+
+	adr	r0, _start
+	ldr	r2, _TEXT_BASE
+	ldr	r3, _bss_start
+	sub	r2, r3, r2		/* r2 <- size of armboot	    */
+	add	r2, r0, r2		/* r2 <- source end address	    */
+	cmp	r0, r6
+	beq	clear_bss
+
+#ifndef CONFIG_SKIP_RELOCATE_UBOOT
+copy_loop:
+	ldmia	r0!, {r9-r10}		/* copy from source address [r0]    */
+	stmia	r6!, {r9-r10}		/* copy to   target address [r1]    */
+	cmp	r0, r2			/* until source end addreee [r2]    */
+	ble	copy_loop
+
+#ifndef CONFIG_PRELOADER
+	/* fix got entries */
+	ldr	r1, _TEXT_BASE		/* Text base */
+	mov	r0, r7			/* reloc addr */
+	ldr	r2, _got_start		/* addr in Flash */
+	ldr	r3, _got_end		/* addr in Flash */
+	sub	r3, r3, r1
+	add	r3, r3, r0
+	sub	r2, r2, r1
+	add	r2, r2, r0
+
+fixloop:
+	ldr	r4, [r2]
+	sub	r4, r4, r1
+	add	r4, r4, r0
+	str	r4, [r2]
+	add	r2, r2, #4
+	cmp	r2, r3
+	bne	fixloop
+#endif
+#endif	/* #ifndef CONFIG_SKIP_RELOCATE_UBOOT */
+
+clear_bss:
+#ifndef CONFIG_PRELOADER
+	ldr	r0, _bss_start
+	ldr	r1, _bss_end
+	ldr	r3, _TEXT_BASE		/* Text base */
+	mov	r4, r7			/* reloc addr */
+	sub	r0, r0, r3
+	add	r0, r0, r4
+	sub	r1, r1, r3
+	add	r1, r1, r4
+	mov	r2, #0x00000000		/* clear			    */
+
+clbss_l:str	r2, [r0]		/* clear loop...		    */
+	add	r0, r0, #4
+	cmp	r0, r1
+	bne	clbss_l
+#endif
+
+/*
+ * We are done. Do not return, instead branch to second part of board
+ * initialization, now running from RAM.
+ */
+	ldr	r0, _TEXT_BASE
+	ldr	r2, _board_init_r
+	sub	r2, r2, r0
+	add	r2, r2, r7	/* position from board_init_r in RAM */
+	/* setup parameters for board_init_r */
+	mov	r0, r5		/* gd_t */
+	mov	r1, r7		/* dest_addr */
+	/* jump to it ... */
+	mov	lr, r2
+	mov	pc, lr
+
+_board_init_r: .word board_init_r
+
+#else /* #if !defined(CONFIG_SYS_ARM_WITHOUT_RELOC) */
+/*
  * the actual reset code
  */
 
@@ -195,7 +372,7 @@ clbss_l:str	r2, [r0]		/* clear loop...                    */
 	ldr	pc, _start_armboot
 
 _start_armboot:	.word start_armboot
-
+#endif /* #if !defined(CONFIG_SYS_ARM_WITHOUT_RELOC) */
 
 /*
  *************************************************************************
@@ -285,9 +462,13 @@ cpu_init_crit:
 	.macro	bad_save_user_regs
 	sub	sp, sp, #S_FRAME_SIZE
 	stmia	sp, {r0 - r12}			@ Calling r0-r12
+#if defined(CONFIG_SYS_ARM_WITHOUT_RELOC)
 	ldr	r2, _armboot_start
 	sub	r2, r2, #(CONFIG_STACKSIZE+CONFIG_SYS_MALLOC_LEN)
 	sub	r2, r2, #(CONFIG_SYS_GBL_DATA_SIZE+8)  @ set base 2 words into abort stack
+#else
+	ldr	r2, IRQ_STACK_START_IN
+#endif
 	ldmia	r2, {r2 - r3}			@ get pc, cpsr
 	add	r0, sp, #S_FRAME_SIZE		@ restore sp_SVC
 
@@ -318,9 +499,13 @@ cpu_init_crit:
 	.endm
 
 	.macro get_bad_stack
+#if defined(CONFIG_SYS_ARM_WITHOUT_RELOC)
 	ldr	r13, _armboot_start		@ setup our mode stack
 	sub	r13, r13, #(CONFIG_STACKSIZE+CONFIG_SYS_MALLOC_LEN)
 	sub	r13, r13, #(CONFIG_SYS_GBL_DATA_SIZE+8) @ reserved a couple spots in abort stack
+#else
+	ldr	r13, IRQ_STACK_START_IN		@ setup our mode stack
+#endif
 
 	str	lr, [r13]			@ save caller lr / spsr
 	mrs	lr, spsr
diff --git a/arch/arm/cpu/lh7a40x/u-boot.lds b/arch/arm/cpu/lh7a40x/u-boot.lds
index 5a8ccf5..cb55b0a 100644
--- a/arch/arm/cpu/lh7a40x/u-boot.lds
+++ b/arch/arm/cpu/lh7a40x/u-boot.lds
@@ -39,11 +39,23 @@ SECTIONS
 	.rodata : { *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.rodata*))) }
 
 	. = ALIGN(4);
-	.data : { *(.data) }
+	.data : {
+		*(.data)
+	__datarel_start = .;
+		*(.data.rel)
+	__datarelrolocal_start = .;
+		*(.data.rel.ro.local)
+	__datarellocal_start = .;
+		*(.data.rel.local)
+	__datarelro_start = .;
+		*(.data.rel.ro)
+	}
 
+	__got_start = .;
 	. = ALIGN(4);
 	.got : { *(.got) }
 
+	__got_end = .;
 	. = .;
 	__u_boot_cmd_start = .;
 	.u_boot_cmd : { *(.u_boot_cmd) }
-- 
1.6.2.5



More information about the U-Boot mailing list