[U-Boot] [PATCH 14/26] ARM: implement relocation for ARM V7 (OMAP)
Heiko Schocher
hs at denx.de
Wed Aug 11 20:16:13 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.
Signed-off-by: Heiko Schocher <hs at denx.de>
---
- changes since v1:
- removed converted but not tested boards
- add CONFIG_SYS_ARM_WITHOUT_RELOC
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 96fd990..3d4836b 100644
--- a/arch/arm/cpu/armv7/omap3/sdrc.c
+++ b/arch/arm/cpu/armv7/omap3/sdrc.c
@@ -164,6 +164,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;
@@ -189,6 +190,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 b066d4d..9ae40ec 100644
--- a/include/configs/omap3_beagle.h
+++ b/include/configs/omap3_beagle.h
@@ -336,4 +336,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
--
DENX Software Engineering GmbH, MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
More information about the U-Boot
mailing list