[U-Boot] [PATCH] [NEXT] arm926ejs: add split relocation support

Albert Aribaud
2010-09-14T18:25:41Z

Many arm926ejs-based SoCs boot at 0xffff0000.
Currently these last 64 KB of flash are wasted just
for a jump to the location where u-boot was flashed.
This commit provides split relocation where the first
part of u-boot is stored from the reset address to the
end of the flash, and the second part is stored below
the first one.
This allows booting directly into _start at 0xffff0000,
thus fully using the last flash sector. For the ED Mini
V2, this frees 12.5% of the flash for other uses.

Signed-off-by: Albert Aribaud <albert.aribaud@free.fr>
---
As indicated in the subject line, this patch is *not* a bugfix
and thus *not* expected to be integrated into 2010.09.

It was heavily tested on an ED Mini V2 and a 5Big Network. All
the following cases were debugged step by step through JTAG:

- boot from RAM (with relocation, without low level init)
- boot from linear image in FLASH (with reloc & ll init)
- boot from split image in FLASH (with reloc & ll init)

'checkpatch.pl --no-tree' reported 0 errors and warnings.

arch/arm/cpu/arm926ejs/start.S | 81 +++++++++++++++++++++++++++++++++------
1 files changed, 68 insertions(+), 13 deletions(-)

diff --git a/arch/arm/cpu/arm926ejs/start.S b/arch/arm/cpu/arm926ejs/start.S
index cf40ce1..9a0a9ef 100644
--- a/arch/arm/cpu/arm926ejs/start.S
+++ b/arch/arm/cpu/arm926ejs/start.S
@@ -5,8 +5,8 @@
*
* ----- Adapted for OMAP1610 OMAP730 from ARM925t code ------
*
- * Copyright (c) 2001 Marius Gr?ger <mag@sysgo.de>
- * Copyright (c) 2002 Alex Z?pke <azu@sysgo.de>
+ * Copyright (c) 2001 Marius Gr??ger <mag@sysgo.de>
+ * Copyright (c) 2002 Alex Z??pke <azu@sysgo.de>
* Copyright (c) 2002 Gary Jennejohn <garyj@denx.de>
* Copyright (c) 2003 Richard Woodruff <r-woodruff2@ti.com>
* Copyright (c) 2003 Kshitij <kshitij@ti.com>
@@ -166,21 +166,74 @@ reset:
bl cpu_init_crit
#endif

+/*
+ * This code copies SIZE bytes of u-boot from 'source' _start (in FLASH)
+ * to 'destination' _TEXT_BASE (in RAM) RAM. It can handle two cases:
+ *
+ * 1) source is entirely located at [_start,_start+_bss_start-_armboot_start[
+ * i.e. u-boot.bin was linearly written to FLASH (this is the case when
+ * the target's reset vector can be _start, or points to some code which
+ * will eventually jump inside FLASH to _start)
+ *
+ * 2) source was split in two parts, one located at [_start,0x1.0000.0000[
+ * (for SIZE1 bytes where SIZE1 = (0x1.0000.000 - _start) and one located
+ * at [_start-A, SIZE-SIZE1[ where A = (_bss_start-_armboot_start) rounded
+ * up to the nearest multiple of SIZE1. This is the case when the target's
+ * reset vector must point directly to _start but there is not enough room
+ * between _start and the end of the 32-bit addressable FLASH.
+ *
+ * Example for the Orion5x 88F5182, which resets at 0xFFFF0000, and with an
+ * overall u-boot size of 0x0001CAFE:
+ * - the first 64 KB of u-boot.bin are flashed at [0xFFFF0000, 0x100000000[;
+ * - there are 0xCAFE bytes left, which take up one 64KB block. The second
+ * part of u-boot will thus be flashed at [0xfffE0000, 0xfffECAFE[.
+ *
+ * To determine if the copy must be split, we taken the start addresse
+ * of the source and add the source length to it to form the end address.
+ * if this end address is below the start address, then the image was split.
+ * If it is above the start address, the image was not split.
+ */
+
#ifndef CONFIG_SKIP_RELOCATE_UBOOT
-relocate: /* relocate U-Boot to RAM */
+ /* relocate U-Boot to RAM */
+relocate:
+ /* skip copy if source == destination */
adr r0, _start /* r0 <- current position of code */
ldr r1, _TEXT_BASE /* test if we run from flash or RAM */
cmp r0, r1 /* don't reloc during debug */
beq stack_setup
+
+ /* skip split copying if copy is split */
ldr r2, _armboot_start
ldr r3, _bss_start
- sub r2, r3, r2 /* r2 <- size of armboot */
- add r2, r0, r2 /* r2 <- source end address */
+ sub r4, r3, r2 /* r4 <- size of armboot */
+ add r2, r0, r4 /* r2 <- source end address */
+ cmp r2, r0 /* does the source rollover? */
+ bhi copy_loop /* no: copy is linear, go do it. */
+
+ /* block size is 0x1.0000.0000 - _start */
+ rsb r3, r0, #0
+
+ /* round u-boot size up to the nearest multiple of block size */
+ sub r3, r3, #1
+ orr r4, r4, r3
+ add r4, r4, #1
+
+ /* copy second part, end condition is r0 rollover to 0 */
+copy_second:
+ ldmia r0!, {r5-r12} /* copy from source address [r0] */
+ stmia r1!, {r5-r12} /* copy to target address [r1] */
+ cmp r0, #0 /* until source end address [#0] */
+ bne copy_second
+
+ /* move source start and end back by the u-boot size rounded up */
+ sub r0, r0, r4 /* r0 <- source address of 2nd part */
+ sub r2, r2, r4 /* r2 <- source end adr of 2nd part */

copy_loop:
- ldmia r0!, {r3-r10} /* copy from source address [r0] */
- stmia r1!, {r3-r10} /* copy to target address [r1] */
- cmp r0, r2 /* until source end addreee [r2] */
+ ldmia r0!, {r5-r12} /* copy from source address [r0] */
+ stmia r1!, {r5-r12} /* copy to target address [r1] */
+ cmp r0, r2 /* until source end address [r2] */
ble copy_loop
#endif /* CONFIG_SKIP_RELOCATE_UBOOT */

@@ -189,14 +242,14 @@ stack_setup:
ldr r0, _TEXT_BASE /* upper 128 KiB: relocated uboot */
sub sp, r0, #128 /* leave 32 words for abort-stack */
#ifndef CONFIG_PRELOADER
- sub r0, r0, #CONFIG_SYS_MALLOC_LEN /* malloc area */
- sub r0, r0, #CONFIG_SYS_GBL_DATA_SIZE /* bdinfo */
+ sub r0, r0, #CONFIG_SYS_MALLOC_LEN /* malloc area */
+ sub r0, r0, #CONFIG_SYS_GBL_DATA_SIZE /* bdinfo */
#ifdef CONFIG_USE_IRQ
sub r0, r0, #(CONFIG_STACKSIZE_IRQ+CONFIG_STACKSIZE_FIQ)
#endif
#endif /* CONFIG_PRELOADER */
sub sp, r0, #12 /* leave 3 words for abort-stack */
- bic sp, sp, #7 /* 8-byte alignment for ABI compliance */
+ bic sp, sp, #7 /* ABI-compliant 8-bit alignment */

clear_bss:
ldr r0, _bss_start /* find start of bss segment */
@@ -310,7 +363,8 @@ cpu_init_crit:

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
+ @ reserve a couple spots in abort stack
+ sub r2, r2, #(CONFIG_SYS_GBL_DATA_SIZE+8)
@ get values for "aborted" pc and cpsr (into parm regs)
ldmia r2, {r2 - r3}
add r0, sp, #S_FRAME_SIZE @ grab pointer to old stack
@@ -344,7 +398,8 @@ cpu_init_crit:
.macro get_bad_stack
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
+ @ reserve a couple spots in abort stack
+ sub r13, r13, #(CONFIG_SYS_GBL_DATA_SIZE+8)

str lr, [r13] @ save caller lr in position 0 of saved stack
mrs lr, spsr @ get the spsr
--
1.7.0.4