From 25e7dc6a6a798451973b2a3d7c02edc3658b270d Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Mon, 22 May 2017 05:05:30 -0600 Subject: [PATCH] bootstage: Support relocating boostage data Some boards cannot access pre-relocation data after relocation. Reserve space for this and copy it during preparation for relocation. Signed-off-by: Simon Glass --- common/board_f.c | 34 +++++++++++++++++++++++++++++++ common/bootstage.c | 5 +++++ include/asm-generic/global_data.h | 1 + include/bootstage.h | 12 +++++++++++ 4 files changed, 52 insertions(+) diff --git a/common/board_f.c b/common/board_f.c index 783c51a6857..14abb428144 100644 --- a/common/board_f.c +++ b/common/board_f.c @@ -491,6 +491,20 @@ static int reserve_fdt(void) return 0; } +static int reserve_bootstage(void) +{ +#ifdef CONFIG_BOOTSTAGE + int size = bootstage_get_size(); + + gd->start_addr_sp -= size; + gd->new_bootstage = map_sysmem(gd->start_addr_sp, size); + debug("Reserving %#x Bytes for bootstage at: %08lx\n", size, + gd->start_addr_sp); +#endif + + return 0; +} + int arch_reserve_stacks(void) { return 0; @@ -605,6 +619,24 @@ static int reloc_fdt(void) return 0; } +static int reloc_bootstage(void) +{ +#ifdef CONFIG_BOOTSTAGE + if (gd->flags & GD_FLG_SKIP_RELOC) + return 0; + if (gd->new_bootstage) { + int size = bootstage_get_size(); + + debug("Copying bootstage from %p to %p, size %x\n", + gd->bootstage, gd->new_bootstage, size); + memcpy(gd->new_bootstage, gd->bootstage, size); + gd->bootstage = gd->new_bootstage; + } +#endif + + return 0; +} + static int setup_reloc(void) { if (gd->flags & GD_FLG_SKIP_RELOC) { @@ -828,6 +860,7 @@ static const init_fnc_t init_sequence_f[] = { setup_machine, reserve_global_data, reserve_fdt, + reserve_bootstage, reserve_arch, reserve_stacks, dram_init_banksize, @@ -849,6 +882,7 @@ static const init_fnc_t init_sequence_f[] = { #endif INIT_FUNC_WATCHDOG_RESET reloc_fdt, + reloc_bootstage, setup_reloc, #if defined(CONFIG_X86) || defined(CONFIG_ARC) copy_uboot_to_ram, diff --git a/common/bootstage.c b/common/bootstage.c index 32f4e8b7060..a6705af1115 100644 --- a/common/bootstage.c +++ b/common/bootstage.c @@ -484,6 +484,11 @@ int bootstage_unstash(void *base, int size) return 0; } +int bootstage_get_size(void) +{ + return sizeof(struct bootstage_data); +} + int bootstage_init(bool first) { struct bootstage_data *data; diff --git a/include/asm-generic/global_data.h b/include/asm-generic/global_data.h index 8b3229e5b8d..fb90be9d3eb 100644 --- a/include/asm-generic/global_data.h +++ b/include/asm-generic/global_data.h @@ -112,6 +112,7 @@ typedef struct global_data { #endif #ifdef CONFIG_BOOTSTAGE struct bootstage_data *bootstage; /* Bootstage information */ + struct bootstage_data *new_bootstage; /* Relocated bootstage info */ #endif } gd_t; #endif diff --git a/include/bootstage.h b/include/bootstage.h index 41bd61785c6..8607e887d8b 100644 --- a/include/bootstage.h +++ b/include/bootstage.h @@ -331,6 +331,13 @@ int bootstage_stash(void *base, int size); */ int bootstage_unstash(void *base, int size); +/** + * bootstage_get_size() - Get the size of the bootstage data + * + * @return size of boostage data in bytes + */ +int bootstage_get_size(void); + /** * bootstage_init() - Prepare bootstage for use * @@ -400,6 +407,11 @@ static inline int bootstage_unstash(void *base, int size) return 0; /* Pretend to succeed */ } +static inline int bootstage_get_size(void) +{ + return 0; +} + static inline int bootstage_init(bool first) { return 0;