diff options
author | Sascha Hauer <s.hauer@pengutronix.de> | 2012-10-07 19:06:30 +0200 |
---|---|---|
committer | Sascha Hauer <s.hauer@pengutronix.de> | 2013-03-07 12:38:01 +0100 |
commit | a81ec0225f5a100341c20b4329c8b1d81ab025c4 (patch) | |
tree | 0d38efb6ba77f80dc0759513d33ab73f7f9bc868 /arch/arm/cpu/setupc.S | |
parent | b08e08506b9752d3768e42d075283f91d2ed5180 (diff) | |
download | barebox-a81ec0225f5a100341c20b4329c8b1d81ab025c4.tar.gz barebox-a81ec0225f5a100341c20b4329c8b1d81ab025c4.tar.xz |
ARM: Add relocatable binary support
For making the same binary executable on different SoCs which have
different DRAM addresses we have to be independent of the compile
time link address.
This patch adds relocatable binary support for the ARM architecture.
With this two new functions are available. relocate_to_current_adr
will fixup the binary to continue executing from the current position.
relocate_to_adr will copy the binary to a given address, fixup the
binary and continue executing from there.
For the PBL and the real image relocatable support can be enabled
independently. This is done to (hopefully) better cope with setups
where the PBL runs from SRAM or ROM and the real binary does not.
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
Diffstat (limited to 'arch/arm/cpu/setupc.S')
-rw-r--r-- | arch/arm/cpu/setupc.S | 59 |
1 files changed, 59 insertions, 0 deletions
diff --git a/arch/arm/cpu/setupc.S b/arch/arm/cpu/setupc.S index d0de87dd9b..7fd5d012f0 100644 --- a/arch/arm/cpu/setupc.S +++ b/arch/arm/cpu/setupc.S @@ -1,4 +1,5 @@ #include <linux/linkage.h> +#include <asm/sections.h> .section .text.setupc @@ -35,3 +36,61 @@ ENTRY(setup_c) pop {r4, r5} mov pc, lr ENDPROC(setup_c) + +#ifdef CONFIG_RELOCATABLE +/* + * void relocate_to_adr(unsigned long targetadr) + * + * Copy binary to targetadr, relocate code, clear bss and continue + * executing at new address. + */ +.section .text.relocate_to_adr +ENTRY(relocate_to_adr) + /* r0: target address */ + push {r3, r4, r5, r6, r7, r8} + mov r7, lr + + mov r6, r0 + + bl get_runtime_offset + + mov r5, r0 + + ld_var _text, r0, r4 + mov r8, r0 + + sub r1, r0, r5 /* r1: from address */ + + cmp r1, r6 /* already at correct address? */ + beq 1f /* yes, skip copy to new address */ + + ld_var __bss_start, r2, r4 + + sub r2, r2, r0 /* r2: size */ + mov r0, r6 /* r0: target */ + + add r7, r7, r0 /* adjust return address */ + sub r7, r7, r1 /* lr += offset */ + + bl memcpy /* copy binary */ + +#ifdef CONFIG_MMU + bl arm_early_mmu_cache_flush +#endif + mov r0,#0 + mcr p15, 0, r0, c7, c5, 0 /* flush icache */ + + ldr r0,=1f + sub r0, r0, r8 + add r0, r0, r6 + mov pc, r0 /* jump to relocated address */ +1: + bl relocate_to_current_adr /* relocate binary */ + + mov lr, r7 + + pop {r3, r4, r5, r6, r7, r8} + mov pc, lr + +ENDPROC(relocate_to_adr) +#endif |