summaryrefslogtreecommitdiffstats
path: root/arch/arm/cpu
diff options
context:
space:
mode:
authorSascha Hauer <s.hauer@pengutronix.de>2016-09-14 10:10:24 +0200
committerSascha Hauer <s.hauer@pengutronix.de>2016-09-15 09:23:43 +0200
commitc9dbd886ef3b05d64bc10551f9fcde267291ef91 (patch)
treec838d25fc2fe217d1a1dcdb36dbca7925d2782ec /arch/arm/cpu
parent5e61dd3fb5506fe647f95deca95d97cced51aeb3 (diff)
downloadbarebox-c9dbd886ef3b05d64bc10551f9fcde267291ef91.tar.gz
barebox-c9dbd886ef3b05d64bc10551f9fcde267291ef91.tar.xz
ARM: Fix calling of arm_mem_barebox_image()
arm_mem_barebox_image() is used to pick a suitable place where to put the final image to. This is called from both the PBL uncompression code and also from the final image. To make it work properly it is crucial that it's called with the same arguments both times. Currently it is called with the wrong image size from the PBL uncompression code. The size passed to arm_mem_barebox_image() has to be the size of the whole uncompressed image including the BSS segment size. The PBL code calls it with the compressed image size instead and without the BSS segment. This patch fixes this by reading the uncompressed image size from the compressed binary (the uncompressed size is appended to the end of the compressed binary by our compression wrappers). The size of the BSS segment is unknown though by the PBL uncompression code, so we introduce a maximum BSS size which is used instead. The code before this patch worked by accident because the base address of the final image was aligned down to a 1MiB boundary. The alignment was sufficient already to make enough space. This breaks though when the uncompressed image including BSS becomes bigger than 1MiB while the compressed image is smaller. Fixes: 65071bd0: arm: Clarify memory layout calculation Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
Diffstat (limited to 'arch/arm/cpu')
-rw-r--r--arch/arm/cpu/start-pbl.c6
-rw-r--r--arch/arm/cpu/start.c3
-rw-r--r--arch/arm/cpu/uncompress.c10
3 files changed, 11 insertions, 8 deletions
diff --git a/arch/arm/cpu/start-pbl.c b/arch/arm/cpu/start-pbl.c
index f723edc613..5f1469bb3e 100644
--- a/arch/arm/cpu/start-pbl.c
+++ b/arch/arm/cpu/start-pbl.c
@@ -28,6 +28,7 @@
#include <asm/sections.h>
#include <asm/pgtable.h>
#include <asm/cache.h>
+#include <asm/unaligned.h>
#include "mmu-early.h"
@@ -49,7 +50,7 @@ __noreturn void barebox_single_pbl_start(unsigned long membase,
unsigned long memsize, void *boarddata)
{
uint32_t offset;
- uint32_t pg_start, pg_end, pg_len;
+ uint32_t pg_start, pg_end, pg_len, uncompressed_len;
void __noreturn (*barebox)(unsigned long, unsigned long, void *);
uint32_t endmem = membase + memsize;
unsigned long barebox_base;
@@ -63,9 +64,10 @@ __noreturn void barebox_single_pbl_start(unsigned long membase,
pg_start = (uint32_t)&input_data - offset;
pg_end = (uint32_t)&input_data_end - offset;
pg_len = pg_end - pg_start;
+ uncompressed_len = get_unaligned((const u32 *)(pg_start + pg_len - 4));
if (IS_ENABLED(CONFIG_RELOCATABLE))
- barebox_base = arm_mem_barebox_image(membase, endmem, pg_len);
+ barebox_base = arm_mem_barebox_image(membase, endmem, uncompressed_len + MAX_BSS_SIZE);
else
barebox_base = TEXT_BASE;
diff --git a/arch/arm/cpu/start.c b/arch/arm/cpu/start.c
index f25e5928cb..0120117e01 100644
--- a/arch/arm/cpu/start.c
+++ b/arch/arm/cpu/start.c
@@ -143,8 +143,7 @@ __noreturn void barebox_non_pbl_start(unsigned long membase,
{
unsigned long endmem = membase + memsize;
unsigned long malloc_start, malloc_end;
- unsigned long barebox_size = barebox_image_size +
- ((unsigned long)&__bss_stop - (unsigned long)&__bss_start);
+ unsigned long barebox_size = barebox_image_size + MAX_BSS_SIZE;
if (IS_ENABLED(CONFIG_RELOCATABLE)) {
unsigned long barebox_base = arm_mem_barebox_image(membase,
diff --git a/arch/arm/cpu/uncompress.c b/arch/arm/cpu/uncompress.c
index b8e2e9ffd7..eeb5a65439 100644
--- a/arch/arm/cpu/uncompress.c
+++ b/arch/arm/cpu/uncompress.c
@@ -29,6 +29,7 @@
#include <asm/sections.h>
#include <asm/pgtable.h>
#include <asm/cache.h>
+#include <asm/unaligned.h>
#include <debug_ll.h>
@@ -44,7 +45,7 @@ static int __attribute__((__used__))
void __noreturn barebox_multi_pbl_start(unsigned long membase,
unsigned long memsize, void *boarddata)
{
- uint32_t pg_len;
+ uint32_t pg_len, uncompressed_len;
void __noreturn (*barebox)(unsigned long, unsigned long, void *);
uint32_t endmem = membase + memsize;
unsigned long barebox_base;
@@ -72,10 +73,11 @@ void __noreturn barebox_multi_pbl_start(unsigned long membase,
*/
pg_start = image_end + 1;
pg_len = *(image_end);
+ uncompressed_len = get_unaligned((const u32 *)(pg_start + pg_len - 4));
if (IS_ENABLED(CONFIG_RELOCATABLE))
barebox_base = arm_mem_barebox_image(membase, endmem,
- pg_len);
+ uncompressed_len + MAX_BSS_SIZE);
else
barebox_base = TEXT_BASE;
@@ -92,8 +94,8 @@ void __noreturn barebox_multi_pbl_start(unsigned long membase,
free_mem_ptr = arm_mem_early_malloc(membase, endmem);
free_mem_end_ptr = arm_mem_early_malloc_end(membase, endmem);
- pr_debug("uncompressing barebox binary at 0x%p (size 0x%08x) to 0x%08lx\n",
- pg_start, pg_len, barebox_base);
+ pr_debug("uncompressing barebox binary at 0x%p (size 0x%08x) to 0x%08lx (uncompressed size: 0x%08x)\n",
+ pg_start, pg_len, barebox_base, uncompressed_len);
pbl_barebox_uncompress((void*)barebox_base, pg_start, pg_len);