diff options
-rw-r--r-- | arch/arm/boards/at91sam9260ek/Makefile | 1 | ||||
-rw-r--r-- | arch/arm/boards/at91sam9260ek/lowlevel_init.S | 25 | ||||
-rw-r--r-- | arch/arm/cpu/Makefile | 4 | ||||
-rw-r--r-- | arch/arm/cpu/setupc.S | 34 | ||||
-rw-r--r-- | arch/arm/cpu/start-pbl.c | 49 | ||||
-rw-r--r-- | arch/arm/cpu/start.c | 41 | ||||
-rw-r--r-- | arch/arm/include/asm/barebox-arm.h | 2 | ||||
-rw-r--r-- | include/common.h | 13 |
8 files changed, 68 insertions, 101 deletions
diff --git a/arch/arm/boards/at91sam9260ek/Makefile b/arch/arm/boards/at91sam9260ek/Makefile index 73ef72e210..eb072c0161 100644 --- a/arch/arm/boards/at91sam9260ek/Makefile +++ b/arch/arm/boards/at91sam9260ek/Makefile @@ -1,2 +1 @@ -obj-y += lowlevel_init.o obj-y += init.o diff --git a/arch/arm/boards/at91sam9260ek/lowlevel_init.S b/arch/arm/boards/at91sam9260ek/lowlevel_init.S deleted file mode 100644 index 043892122c..0000000000 --- a/arch/arm/boards/at91sam9260ek/lowlevel_init.S +++ /dev/null @@ -1,25 +0,0 @@ -/* - * Board specific setup info - * - * - * See file CREDITS for list of people who contributed to this - * project. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - */ - -#include <asm/barebox-arm-head.h> - -.globl reset -reset: - common_reset r0 - b board_init_lowlevel_return diff --git a/arch/arm/cpu/Makefile b/arch/arm/cpu/Makefile index 6aab3aee89..4b0259c15b 100644 --- a/arch/arm/cpu/Makefile +++ b/arch/arm/cpu/Makefile @@ -1,7 +1,7 @@ obj-y += cpu.o obj-$(CONFIG_ARM_EXCEPTIONS) += exceptions.o obj-$(CONFIG_ARM_EXCEPTIONS) += interrupts.o -obj-y += start.o +obj-y += start.o setupc.o # # Any variants can be called as start-armxyz.S @@ -20,4 +20,4 @@ obj-$(CONFIG_CPU_32v7) += cache-armv7.o pbl-$(CONFIG_CPU_32v7) += cache-armv7.o obj-$(CONFIG_CACHE_L2X0) += cache-l2x0.o -pbl-y += start-pbl.o +pbl-y += start-pbl.o setupc.o diff --git a/arch/arm/cpu/setupc.S b/arch/arm/cpu/setupc.S new file mode 100644 index 0000000000..9a8d54c224 --- /dev/null +++ b/arch/arm/cpu/setupc.S @@ -0,0 +1,34 @@ +#include <linux/linkage.h> + +.section .text.setupc + +/* + * setup_c: copy binary to link address, clear bss and + * continue executing at new address. + * + * This function does not return to the address it is + * called from, but to the same location in the copied + * binary. + */ +ENTRY(setup_c) + push {r4, r5} + mov r5, lr + bl get_runtime_offset + subs r4, r0, #0 + beq 1f /* skip memcpy if already at correct address */ + ldr r0,=_text + ldr r2,=__bss_start + sub r2, r2, r0 + sub r1, r0, r4 + bl memcpy /* memcpy(_text, _text - offset, __bss_start - _text) */ +1: ldr r0, =__bss_start + mov r1, #0 + ldr r2, =__bss_stop + sub r2, r2, r0 + bl memset /* clear bss */ + mov r0, #0 + mcr p15, 0, r0, c7, c5, 0 /* flush icache */ + add lr, r5, r4 /* adjust return address to new location */ + pop {r4, r5} + mov pc, lr +ENDPROC(setup_c) diff --git a/arch/arm/cpu/start-pbl.c b/arch/arm/cpu/start-pbl.c index 929cc26055..609aedb39c 100644 --- a/arch/arm/cpu/start-pbl.c +++ b/arch/arm/cpu/start-pbl.c @@ -174,7 +174,7 @@ static void barebox_uncompress(void *compressed_start, unsigned int len) */ void __naked board_init_lowlevel_return(void) { - uint32_t r, offset; + uint32_t offset; uint32_t pg_start, pg_end, pg_len; /* Setup the stack */ @@ -187,43 +187,16 @@ void __naked board_init_lowlevel_return(void) pg_end = (uint32_t)&input_data_end - offset; pg_len = pg_end - pg_start; - if (IS_ENABLED(CONFIG_PBL_FORCE_PIGGYDATA_COPY)) - goto copy_piggy_link; + if (offset && (IS_ENABLED(CONFIG_PBL_FORCE_PIGGYDATA_COPY) || + region_overlap(pg_start, pg_len, TEXT_BASE, pg_len * 4))) { + /* + * copy piggydata binary to its link address + */ + memcpy(&input_data, (void *)pg_start, pg_len); + pg_start = (uint32_t)&input_data; + } - /* - * Check if the piggydata binary will be overwritten - * by the uncompressed binary or by the pbl relocation - */ - if (!offset || - !((pg_start >= TEXT_BASE && pg_start < TEXT_BASE + pg_len * 4) || - ((uint32_t)_text >= pg_start && (uint32_t)_text <= pg_end))) - goto copy_link; - -copy_piggy_link: - /* - * copy piggydata binary to its link address - */ - memcpy(&input_data, (void *)pg_start, pg_len); - pg_start = (uint32_t)&input_data; - -copy_link: - /* relocate to link address if necessary */ - if (offset) - memcpy((void *)_text, (void *)(_text - offset), - __bss_start - _text); - - /* clear bss */ - memset(__bss_start, 0, __bss_stop - __bss_start); - - flush_icache(); + setup_c(); - r = (unsigned int)&barebox_uncompress; - /* call barebox_uncompress with its absolute address */ - __asm__ __volatile__( - "mov r0, %1\n" - "mov r1, %2\n" - "mov pc, %0\n" - : - : "r"(r), "r"(pg_start), "r"(pg_len) - : "r0", "r1"); + barebox_uncompress((void *)pg_start, pg_len); } diff --git a/arch/arm/cpu/start.c b/arch/arm/cpu/start.c index af83899ce8..793445a828 100644 --- a/arch/arm/cpu/start.c +++ b/arch/arm/cpu/start.c @@ -24,32 +24,19 @@ #include <asm-generic/memory_layout.h> #include <asm/sections.h> #include <asm/cache.h> +#include <memory.h> -#ifdef CONFIG_PBL_IMAGE /* * First function in the uncompressed image. We get here from * the pbl. */ void __naked __section(.text_entry) start(void) { - u32 r; - - /* Setup the stack */ - r = STACK_BASE + STACK_SIZE - 16; - __asm__ __volatile__("mov sp, %0" : : "r"(r)); - /* clear bss */ - memset(__bss_start, 0, __bss_stop - __bss_start); - - start_barebox(); -} +#ifdef CONFIG_PBL_IMAGE + board_init_lowlevel_return(); #else - -/* - * First function in the image without pbl support - */ -void __naked __section(.text_entry) start(void) -{ barebox_arm_head(); +#endif } /* @@ -70,25 +57,9 @@ void __naked __bare_init reset(void) */ void __naked board_init_lowlevel_return(void) { - uint32_t r, offset; - arm_setup_stack(STACK_BASE + STACK_SIZE - 16); - /* Get offset between linked address and runtime address */ - offset = get_runtime_offset(); - - /* relocate to link address if necessary */ - if (offset) - memcpy((void *)_text, (void *)(_text - offset), - __bss_start - _text); + setup_c(); - /* clear bss */ - memset(__bss_start, 0, __bss_stop - __bss_start); - - flush_icache(); - - /* call start_barebox with its absolute address */ - r = (unsigned int)&start_barebox; - __asm__ __volatile__("mov pc, %0" : : "r"(r)); + start_barebox(); } -#endif diff --git a/arch/arm/include/asm/barebox-arm.h b/arch/arm/include/asm/barebox-arm.h index 9e17b4f5fb..993130df2d 100644 --- a/arch/arm/include/asm/barebox-arm.h +++ b/arch/arm/include/asm/barebox-arm.h @@ -38,4 +38,6 @@ void board_init_lowlevel(void); void board_init_lowlevel_return(void); uint32_t get_runtime_offset(void); +void setup_c(void); + #endif /* _BAREBOX_ARM_H_ */ diff --git a/include/common.h b/include/common.h index c1f44b402c..e30774a43e 100644 --- a/include/common.h +++ b/include/common.h @@ -256,4 +256,17 @@ static inline void barebox_banner(void) {} (__x < 0) ? -__x : __x; \ }) +/* + * Check if two regions overlap. returns true if they do, false otherwise + */ +static inline bool region_overlap(unsigned long starta, unsigned long lena, + unsigned long startb, unsigned long lenb) +{ + if (starta + lena <= startb) + return 0; + if (startb + lenb <= starta) + return 0; + return 1; +} + #endif /* __COMMON_H_ */ |