[U-Boot] [PATCH 14/26 v2][NEXT] ARM: implement relocation for ARM V7 (OMAP)

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


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

Adapt the Beagle board (Cortex A8) to test the changes.

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/armv7/mx51/u-boot.lds |   14 +++-
 arch/arm/cpu/armv7/omap3/emif4.c   |   34 +++++++
 arch/arm/cpu/armv7/omap3/sdrc.c    |   38 +++++++
 arch/arm/cpu/armv7/start.S         |  191 +++++++++++++++++++++++++++++++++++-
 arch/arm/cpu/armv7/u-boot.lds      |   14 +++-
 board/ti/beagle/config.mk          |    2 +-
 include/configs/omap3_beagle.h     |    5 +
 7 files changed, 291 insertions(+), 7 deletions(-)

diff --git a/arch/arm/cpu/armv7/mx51/u-boot.lds b/arch/arm/cpu/armv7/mx51/u-boot.lds
index d66434c..55d6599 100644
--- a/arch/arm/cpu/armv7/mx51/u-boot.lds
+++ b/arch/arm/cpu/armv7/mx51/u-boot.lds
@@ -44,10 +44,22 @@ SECTIONS
 	.rodata : { *(.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 = .;
diff --git a/arch/arm/cpu/armv7/omap3/emif4.c b/arch/arm/cpu/armv7/omap3/emif4.c
index fae5b11..da2cd90 100644
--- a/arch/arm/cpu/armv7/omap3/emif4.c
+++ b/arch/arm/cpu/armv7/omap3/emif4.c
@@ -136,6 +136,7 @@ void do_emif4_init(void)
  * dram_init -
  *  - Sets uboots idea of sdram size
  */
+#if defined(CONFIG_SYS_ARM_WITHOUT_RELOC)
 int dram_init(void)
 {
 	DECLARE_GLOBAL_DATA_PTR;
@@ -157,6 +158,39 @@ int dram_init(void)
 
 	return 0;
 }
+#else
+int dram_init(void)
+{
+	DECLARE_GLOBAL_DATA_PTR;
+	unsigned int size0 = 0, size1 = 0;
+
+	size0 = get_sdr_cs_size(CS0);
+	/*
+	 * If a second bank of DDR is attached to CS1 this is
+	 * where it can be started.  Early init code will init
+	 * memory on CS0.
+	 */
+	if ((sysinfo.mtype == DDR_COMBO) || (sysinfo.mtype == DDR_STACKED))
+		size1 = get_sdr_cs_size(CS1);
+
+	gd->ram_size = size0 + size1;
+	return 0;
+}
+
+void dram_init_banksize (void)
+{
+	DECLARE_GLOBAL_DATA_PTR;
+	unsigned int size0 = 0, size1 = 0;
+
+	size0 = get_sdr_cs_size(CS0);
+	size1 = get_sdr_cs_size(CS1);
+
+	gd->bd->bi_dram[0].start = PHYS_SDRAM_1;
+	gd->bd->bi_dram[0].size = size0;
+	gd->bd->bi_dram[1].start = PHYS_SDRAM_1 + get_sdr_cs_offset(CS1);
+	gd->bd->bi_dram[1].size = size1;
+}
+#endif
 
 /*
  * mem_init() -
diff --git a/arch/arm/cpu/armv7/omap3/sdrc.c b/arch/arm/cpu/armv7/omap3/sdrc.c
index 8905224..2719bb5 100644
--- a/arch/arm/cpu/armv7/omap3/sdrc.c
+++ b/arch/arm/cpu/armv7/omap3/sdrc.c
@@ -163,6 +163,7 @@ void do_sdrc_init(u32 cs, u32 early)
  * dram_init -
  *  - Sets uboots idea of sdram size
  */
+#if defined(CONFIG_SYS_ARM_WITHOUT_RELOC)
 int dram_init(void)
 {
 	DECLARE_GLOBAL_DATA_PTR;
@@ -188,6 +189,43 @@ int dram_init(void)
 
 	return 0;
 }
+#else
+int dram_init(void)
+{
+	DECLARE_GLOBAL_DATA_PTR;
+	unsigned int size0 = 0, size1 = 0;
+
+	size0 = get_sdr_cs_size(CS0);
+	/*
+	 * If a second bank of DDR is attached to CS1 this is
+	 * where it can be started.  Early init code will init
+	 * memory on CS0.
+	 */
+	if ((sysinfo.mtype == DDR_COMBO) || (sysinfo.mtype == DDR_STACKED)) {
+		do_sdrc_init(CS1, NOT_EARLY);
+		make_cs1_contiguous();
+
+		size1 = get_sdr_cs_size(CS1);
+	}
+	gd->ram_size = size0 + size1;
+
+	return 0;
+}
+
+void dram_init_banksize (void)
+{
+	DECLARE_GLOBAL_DATA_PTR;
+	unsigned int size0 = 0, size1 = 0;
+
+	size0 = get_sdr_cs_size(CS0);
+	size1 = get_sdr_cs_size(CS1);
+
+	gd->bd->bi_dram[0].start = PHYS_SDRAM_1;
+	gd->bd->bi_dram[0].size = size0;
+	gd->bd->bi_dram[1].start = PHYS_SDRAM_1 + get_sdr_cs_offset(CS1);
+	gd->bd->bi_dram[1].size = size1;
+}
+#endif
 
 /*
  * mem_init -
diff --git a/arch/arm/cpu/armv7/start.S b/arch/arm/cpu/armv7/start.S
index 1e0a150..f411c0f 100644
--- a/arch/arm/cpu/armv7/start.S
+++ b/arch/arm/cpu/armv7/start.S
@@ -65,12 +65,15 @@ _end_vect:
  *
  *************************************************************************/
 
+.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.
@@ -95,6 +98,176 @@ 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
+
+#if (CONFIG_OMAP34XX)
+	/* Copy vectors to mask ROM indirect addr */
+	adr	r0, _start		@ r0 <- current position of code
+	add	r0, r0, #4		@ skip reset vector
+	mov	r2, #64			@ r2 <- size to copy
+	add	r2, r0, r2		@ r2 <- source end address
+	mov	r1, #SRAM_OFFSET0	@ build vect addr
+	mov	r3, #SRAM_OFFSET1
+	add	r1, r1, r3
+	mov	r3, #SRAM_OFFSET2
+	add	r1, r1, r3
+next:
+	ldmia	r0!, {r3 - r10}		@ copy from source address [r0]
+	stmia	r1!, {r3 - r10}		@ copy to   target address [r1]
+	cmp	r0, r2			@ until source end address [r2]
+	bne	next			@ loop until equal */
+#if !defined(CONFIG_SYS_NAND_BOOT) && !defined(CONFIG_SYS_ONENAND_BOOT)
+	/* No need to copy/exec the clock code - DPLL adjust already done
+	 * in NAND/oneNAND Boot.
+	 */
+	bl	cpy_clk_code		@ put dpll adjust code behind vectors
+#endif /* NAND Boot */
+#endif
+	/* the mask ROM code should have PLL and others stable */
+#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
+
+#ifndef CONFIG_SKIP_RELOCATE_UBOOT
+	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
+#ifndef CONFIG_PRELOADER
+	beq	jump_2_ram
+#endif
+
+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
+	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
+
+clear_bss:
+	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	/* #ifndef CONFIG_PRELOADER */
+#endif	/* #ifndef CONFIG_SKIP_RELOCATE_UBOOT */
+
+/*
+ * We are done. Do not return, instead branch to second part of board
+ * initialization, now running from RAM.
+ */
+jump_2_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
  */
@@ -180,7 +353,7 @@ clbss_l:
 	ldr	pc, _start_armboot	@ jump to C code
 
 _start_armboot: .word start_armboot
-
+#endif /* #if !defined(CONFIG_SYS_ARM_WITHOUT_RELOC) */
 
 /*************************************************************************
  *
@@ -263,11 +436,14 @@ cpu_init_crit:
 						@ user stack
 	stmia	sp, {r0 - r12}			@ Save user registers (now in
 						@ svc mode) r0-r12
-
+#if defined(CONFIG_SYS_ARM_WITHOUT_RELOC)
 	ldr	r2, _armboot_start
 	sub	r2, r2, #(CONFIG_SYS_MALLOC_LEN)
 	sub	r2, r2, #(CONFIG_SYS_GBL_DATA_SIZE + 8)	@ set base 2 words into abort
+#else
+	ldr	r2, IRQ_STACK_START_IN		@ set base 2 words into abort
 						@ stack
+#endif
 	ldmia	r2, {r2 - r3}			@ get values for "aborted" pc
 						@ and cpsr (into parm regs)
 	add	r0, sp, #S_FRAME_SIZE		@ grab pointer to old stack
@@ -303,11 +479,14 @@ cpu_init_crit:
 	.endm
 
 	.macro get_bad_stack
+#if defined(CONFIG_SYS_ARM_WITHOUT_RELOC)
 	ldr	r13, _armboot_start		@ setup our mode stack (enter
-						@ in banked mode)
 	sub	r13, r13, #(CONFIG_SYS_MALLOC_LEN)	@ move past malloc pool
 	sub	r13, r13, #(CONFIG_SYS_GBL_DATA_SIZE + 8) @ move to reserved a couple
-						@ spots for abort stack
+#else
+	ldr	r13, IRQ_STACK_START_IN		@ setup our mode stack (enter
+						@ in banked mode)
+#endif
 
 	str	lr, [r13]			@ save caller lr in position 0
 						@ of saved stack
@@ -328,10 +507,14 @@ cpu_init_crit:
 	sub	r13, r13, #4			@ space on current stack for
 						@ scratch reg.
 	str	r0, [r13]			@ save R0's value.
+#if defined(CONFIG_SYS_ARM_WITHOUT_RELOC)
 	ldr	r0, _armboot_start		@ get data regions start
 	sub	r0, r0, #(CONFIG_SYS_MALLOC_LEN)	@ move past malloc pool
 	sub	r0, r0, #(CONFIG_SYS_GBL_DATA_SIZE + 8)	@ move past gbl and a couple
+#else
+	ldr	r0, IRQ_STACK_START_IN		@ get data regions start
 						@ spots for abort stack
+#endif
 	str	lr, [r0]			@ save caller lr in position 0
 						@ of saved stack
 	mrs	r0, spsr			@ get the spsr
diff --git a/arch/arm/cpu/armv7/u-boot.lds b/arch/arm/cpu/armv7/u-boot.lds
index 9e5b5a9..d4fd3fc 100644
--- a/arch/arm/cpu/armv7/u-boot.lds
+++ b/arch/arm/cpu/armv7/u-boot.lds
@@ -42,10 +42,22 @@ 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) }
diff --git a/board/ti/beagle/config.mk b/board/ti/beagle/config.mk
index 879b2e2..6fb10e3 100644
--- a/board/ti/beagle/config.mk
+++ b/board/ti/beagle/config.mk
@@ -30,4 +30,4 @@
 # (mem base + reserved)
 
 # For use with external or internal boots.
-TEXT_BASE = 0x80e80000
+TEXT_BASE = 0x80008000
diff --git a/include/configs/omap3_beagle.h b/include/configs/omap3_beagle.h
index 3f6e803..2463be4 100644
--- a/include/configs/omap3_beagle.h
+++ b/include/configs/omap3_beagle.h
@@ -340,4 +340,9 @@ extern unsigned int boot_flash_sec;
 extern unsigned int boot_flash_type;
 #endif
 
+/* additions for new relocation code, must added to all boards */
+#undef CONFIG_SYS_ARM_WITHOUT_RELOC /* This board is tested with relocation support */
+#define CONFIG_SYS_SDRAM_BASE		PHYS_SDRAM_1
+#define CONFIG_SYS_INIT_SP_ADDR		(LOW_LEVEL_SRAM_STACK - CONFIG_SYS_GBL_DATA_SIZE)
+
 #endif /* __CONFIG_H */
-- 
1.6.2.5



More information about the U-Boot mailing list