summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/arm/boards/at91sam9260ek/Makefile1
-rw-r--r--arch/arm/boards/at91sam9260ek/lowlevel_init.S25
-rw-r--r--arch/arm/cpu/Makefile4
-rw-r--r--arch/arm/cpu/setupc.S34
-rw-r--r--arch/arm/cpu/start-pbl.c49
-rw-r--r--arch/arm/cpu/start.c41
-rw-r--r--arch/arm/include/asm/barebox-arm.h2
-rw-r--r--include/common.h13
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_ */