[U-Boot] [PATCH 01/10] x86: Add function to get top of usable ram

The memory layout calculations are done in calculate_relocation_address(), and coreboot has its own version of this function. But in fact all we really need is to set the top of usable RAM, and then the base version will work as is.
So instead of allowing the whole calculate_relocation_address() function to be replaced, create board_get_usable_ram_top() which can be used by a board to specify the top of the area where U-Boot relocations to.
Signed-off-by: Simon Glass sjg@chromium.org --- arch/x86/cpu/coreboot/sdram.c | 18 ++++-------------- arch/x86/lib/init_helpers.c | 28 ++++++++++++++++++---------- 2 files changed, 22 insertions(+), 24 deletions(-)
diff --git a/arch/x86/cpu/coreboot/sdram.c b/arch/x86/cpu/coreboot/sdram.c index 76274cb..a8136a0 100644 --- a/arch/x86/cpu/coreboot/sdram.c +++ b/arch/x86/cpu/coreboot/sdram.c @@ -60,12 +60,8 @@ unsigned install_e820_map(unsigned max_entries, struct e820entry *entries) * address, and how far U-Boot is moved by relocation are set in the global * data structure. */ -int calculate_relocation_address(void) +ulong board_get_usable_ram_top(ulong total_size) { - const uint64_t uboot_size = (uintptr_t)&__bss_end - - (uintptr_t)&__text_start; - const uint64_t total_size = uboot_size + CONFIG_SYS_MALLOC_LEN + - CONFIG_SYS_STACK_SIZE; uintptr_t dest_addr = 0; int i;
@@ -87,21 +83,15 @@ int calculate_relocation_address(void) continue;
/* Use this address if it's the largest so far. */ - if (end - uboot_size > dest_addr) + if (end > dest_addr) dest_addr = end; }
/* If no suitable area was found, return an error. */ if (!dest_addr) - return 1; + panic("No available memory found for relocation");
- dest_addr -= uboot_size; - dest_addr &= ~((1 << 12) - 1); - gd->relocaddr = dest_addr; - gd->reloc_off = dest_addr - (uintptr_t)&__text_start; - gd->start_addr_sp = dest_addr - CONFIG_SYS_MALLOC_LEN; - - return 0; + return (ulong)dest_addr; }
int dram_init_f(void) diff --git a/arch/x86/lib/init_helpers.c b/arch/x86/lib/init_helpers.c index 3eec9a6..1a097f1 100644 --- a/arch/x86/lib/init_helpers.c +++ b/arch/x86/lib/init_helpers.c @@ -73,26 +73,34 @@ int init_baudrate_f(void) return 0; }
-__weak int calculate_relocation_address(void) +/* Get the top of usable RAM */ +__weak ulong board_get_usable_ram_top(ulong total_size) { - ulong text_start = (ulong)&__text_start; - ulong bss_end = (ulong)&__bss_end; + return gd->ram_size; +} + +int calculate_relocation_address(void) +{ + const ulong uboot_size = (uintptr_t)&__bss_end - + (uintptr_t)&__text_start; + ulong total_size; ulong dest_addr;
+ total_size = ALIGN(uboot_size, 1 << 12) + CONFIG_SYS_MALLOC_LEN + + CONFIG_SYS_STACK_SIZE; + /* * NOTE: All destination address are rounded down to 16-byte * boundary to satisfy various worst-case alignment * requirements */ + dest_addr = board_get_usable_ram_top(total_size);
- /* Stack is at top of available memory */ - dest_addr = gd->ram_size; - - /* U-Boot is at the top */ - dest_addr -= (bss_end - text_start); - dest_addr &= ~15; + /* U-Boot is below the FDT */ + dest_addr -= uboot_size; + dest_addr &= ~((1 << 12) - 1); gd->relocaddr = dest_addr; - gd->reloc_off = (dest_addr - text_start); + gd->reloc_off = dest_addr - (uintptr_t)&__text_start;
/* Stack is at the bottom, so it can grow down */ gd->start_addr_sp = dest_addr - CONFIG_SYS_MALLOC_LEN;

At present most x86 cache operations are undefined. Add a basic implementation for these.
Signed-off-by: Simon Glass sjg@chromium.org --- arch/x86/cpu/cpu.c | 23 +++++++++++++++++++++++ 1 files changed, 23 insertions(+), 0 deletions(-)
diff --git a/arch/x86/cpu/cpu.c b/arch/x86/cpu/cpu.c index 315e87a..fe6e568 100644 --- a/arch/x86/cpu/cpu.c +++ b/arch/x86/cpu/cpu.c @@ -226,3 +226,26 @@ void flush_dcache_range(unsigned long start, unsigned long stop) void invalidate_dcache_range(unsigned long start, unsigned long stop) { } + +void dcache_enable(void) +{ + enable_caches(); +} + +void dcache_disable(void) +{ + disable_caches(); +} + +void icache_enable(void) +{ +} + +void icache_disable(void) +{ +} + +int icache_status(void) +{ + return 1; +}

It is useful to be able to access the timer before U-Boot has relocated so that we can fully support bootstage.
Move the relevant variables to the data region to support this.
Signed-off-by: Simon Glass sjg@chromium.org --- arch/x86/cpu/coreboot/coreboot.c | 4 ++-- arch/x86/cpu/interrupts.c | 2 +- arch/x86/lib/timer.c | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/arch/x86/cpu/coreboot/coreboot.c b/arch/x86/cpu/coreboot/coreboot.c index 9c9431e..22474f5 100644 --- a/arch/x86/cpu/coreboot/coreboot.c +++ b/arch/x86/cpu/coreboot/coreboot.c @@ -68,8 +68,8 @@ int board_early_init_r(void) void show_boot_progress(int val) { #if MIN_PORT80_KCLOCKS_DELAY - static uint32_t prev_stamp; - static uint32_t base; + static uint32_t prev_stamp __attribute__((section(".data"))); + static uint32_t base __attribute__((section(".data")));
/* * Scale the time counter reading to avoid using 64 bit arithmetics. diff --git a/arch/x86/cpu/interrupts.c b/arch/x86/cpu/interrupts.c index dd30a05..60ae950 100644 --- a/arch/x86/cpu/interrupts.c +++ b/arch/x86/cpu/interrupts.c @@ -626,7 +626,7 @@ asm(".globl irq_common_entry\n" \ */ u64 get_ticks(void) { - static u64 tick_base; + static u64 tick_base __attribute__((section(".data"))); u64 now_tick = rdtsc();
if (!tick_base) diff --git a/arch/x86/lib/timer.c b/arch/x86/lib/timer.c index a13424b..6303ca5 100644 --- a/arch/x86/lib/timer.c +++ b/arch/x86/lib/timer.c @@ -37,7 +37,7 @@ struct timer_isr_function {
static struct timer_isr_function *first_timer_isr; static unsigned long system_ticks; -static uint64_t base_value; +static uint64_t base_value __attribute__((section(".data")));
/* * register_timer_isr() allows multiple architecture and board specific

Hi Simon,
On 15/12/12 08:13, Simon Glass wrote:
It is useful to be able to access the timer before U-Boot has relocated so that we can fully support bootstage.
Move the relevant variables to the data region to support this.
Signed-off-by: Simon Glass sjg@chromium.org
arch/x86/cpu/coreboot/coreboot.c | 4 ++-- arch/x86/cpu/interrupts.c | 2 +- arch/x86/lib/timer.c | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/arch/x86/cpu/coreboot/coreboot.c b/arch/x86/cpu/coreboot/coreboot.c index 9c9431e..22474f5 100644 --- a/arch/x86/cpu/coreboot/coreboot.c +++ b/arch/x86/cpu/coreboot/coreboot.c @@ -68,8 +68,8 @@ int board_early_init_r(void) void show_boot_progress(int val) { #if MIN_PORT80_KCLOCKS_DELAY
- static uint32_t prev_stamp;
- static uint32_t base;
- static uint32_t prev_stamp __attribute__((section(".data")));
- static uint32_t base __attribute__((section(".data")));
NAK
This may work for coreboot where SDRAM is already initialised and you've loaded U-Boot into RAM, but it will not work when U-Boot is in Flash as all sections (including .data) are read-only until after relocation.
The stack and Global Data are the only guaranteed read/write locations prior to relocation
Regards,
Graeme

Hi Graeme,
On Fri, Dec 14, 2012 at 2:15 PM, Graeme Russ graeme.russ@gmail.com wrote:
Hi Simon,
On 15/12/12 08:13, Simon Glass wrote:
It is useful to be able to access the timer before U-Boot has relocated so that we can fully support bootstage.
Move the relevant variables to the data region to support this.
Signed-off-by: Simon Glass sjg@chromium.org
arch/x86/cpu/coreboot/coreboot.c | 4 ++-- arch/x86/cpu/interrupts.c | 2 +- arch/x86/lib/timer.c | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/arch/x86/cpu/coreboot/coreboot.c b/arch/x86/cpu/coreboot/coreboot.c index 9c9431e..22474f5 100644 --- a/arch/x86/cpu/coreboot/coreboot.c +++ b/arch/x86/cpu/coreboot/coreboot.c @@ -68,8 +68,8 @@ int board_early_init_r(void) void show_boot_progress(int val) { #if MIN_PORT80_KCLOCKS_DELAY
static uint32_t prev_stamp;
static uint32_t base;
static uint32_t prev_stamp __attribute__((section(".data")));
static uint32_t base __attribute__((section(".data")));
NAK
This may work for coreboot where SDRAM is already initialised and you've loaded U-Boot into RAM, but it will not work when U-Boot is in Flash as all sections (including .data) are read-only until after relocation.
The stack and Global Data are the only guaranteed read/write locations prior to relocation
Ah yes, I was thinking of your comment that all boards would move to use coreboot. If that is not the case, then I will need to add something to global data for the timer. And I don't want to do that while generic board is in progress since it creates conflicts.
Regards, Simon
Regards,
Graeme

Hi Graeme,
On Fri, Dec 14, 2012 at 2:35 PM, Simon Glass sjg@chromium.org wrote:
Hi Graeme,
On Fri, Dec 14, 2012 at 2:15 PM, Graeme Russ graeme.russ@gmail.com wrote:
Hi Simon,
On 15/12/12 08:13, Simon Glass wrote:
It is useful to be able to access the timer before U-Boot has relocated so that we can fully support bootstage.
Move the relevant variables to the data region to support this.
Signed-off-by: Simon Glass sjg@chromium.org
arch/x86/cpu/coreboot/coreboot.c | 4 ++-- arch/x86/cpu/interrupts.c | 2 +- arch/x86/lib/timer.c | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/arch/x86/cpu/coreboot/coreboot.c
b/arch/x86/cpu/coreboot/coreboot.c
index 9c9431e..22474f5 100644 --- a/arch/x86/cpu/coreboot/coreboot.c +++ b/arch/x86/cpu/coreboot/coreboot.c @@ -68,8 +68,8 @@ int board_early_init_r(void) void show_boot_progress(int val) { #if MIN_PORT80_KCLOCKS_DELAY
static uint32_t prev_stamp;
static uint32_t base;
static uint32_t prev_stamp __attribute__((section(".data")));
static uint32_t base __attribute__((section(".data")));
NAK
This may work for coreboot where SDRAM is already initialised and you've loaded U-Boot into RAM, but it will not work when U-Boot is in Flash as
all
sections (including .data) are read-only until after relocation.
The stack and Global Data are the only guaranteed read/write locations prior to relocation
Ah yes, I was thinking of your comment that all boards would move to use coreboot. If that is not the case, then I will need to add something to global data for the timer. And I don't want to do that while generic board is in progress since it creates conflicts.
Any thoughts on this point, please? I presume at least I can use RAM once dram_init() is called. But when running from coreboot the RAM is already set up...
Regards, Simon
Regards, Simon
Regards,
Graeme

Hi Simon,
On Wed, Dec 19, 2012 at 12:32 PM, Simon Glass sjg@chromium.org wrote:
Hi Graeme,
On Fri, Dec 14, 2012 at 2:35 PM, Simon Glass sjg@chromium.org wrote:
Hi Graeme,
On Fri, Dec 14, 2012 at 2:15 PM, Graeme Russ graeme.russ@gmail.com wrote:
Hi Simon,
On 15/12/12 08:13, Simon Glass wrote:
It is useful to be able to access the timer before U-Boot has relocated so that we can fully support bootstage.
Move the relevant variables to the data region to support this.
Signed-off-by: Simon Glass sjg@chromium.org
arch/x86/cpu/coreboot/coreboot.c | 4 ++-- arch/x86/cpu/interrupts.c | 2 +- arch/x86/lib/timer.c | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/arch/x86/cpu/coreboot/coreboot.c b/arch/x86/cpu/coreboot/coreboot.c index 9c9431e..22474f5 100644 --- a/arch/x86/cpu/coreboot/coreboot.c +++ b/arch/x86/cpu/coreboot/coreboot.c @@ -68,8 +68,8 @@ int board_early_init_r(void) void show_boot_progress(int val) { #if MIN_PORT80_KCLOCKS_DELAY
static uint32_t prev_stamp;
static uint32_t base;
static uint32_t prev_stamp __attribute__((section(".data")));
static uint32_t base __attribute__((section(".data")));
NAK
This may work for coreboot where SDRAM is already initialised and you've loaded U-Boot into RAM, but it will not work when U-Boot is in Flash as all sections (including .data) are read-only until after relocation.
The stack and Global Data are the only guaranteed read/write locations prior to relocation
Ah yes, I was thinking of your comment that all boards would move to use coreboot. If that is not the case, then I will need to add something to global data for the timer. And I don't want to do that while generic board is in progress since it creates conflicts.
I'm trying to remember the context of my comment regarding only having coreboot boards. But anyway, not having any writeable data prior to relocation (other than the stack and gd) is a fundamental principle that we cannot simply avoid (although I must admit I don't know what the go is with SPL and U-Boot relocation).
Any thoughts on this point, please? I presume at least I can use RAM once dram_init() is called. But when running from coreboot the RAM is already set up...
You will need to use global data to store the static variables. That's what the other arches do
Regards,
Graeme

Hi Graeme,
On Wed, Dec 19, 2012 at 1:39 PM, Graeme Russ graeme.russ@gmail.com wrote:
Hi Simon,
On Wed, Dec 19, 2012 at 12:32 PM, Simon Glass sjg@chromium.org wrote:
Hi Graeme,
On Fri, Dec 14, 2012 at 2:35 PM, Simon Glass sjg@chromium.org wrote:
Hi Graeme,
On Fri, Dec 14, 2012 at 2:15 PM, Graeme Russ graeme.russ@gmail.com wrote:
Hi Simon,
On 15/12/12 08:13, Simon Glass wrote:
It is useful to be able to access the timer before U-Boot has relocated so that we can fully support bootstage.
Move the relevant variables to the data region to support this.
Signed-off-by: Simon Glass sjg@chromium.org
arch/x86/cpu/coreboot/coreboot.c | 4 ++-- arch/x86/cpu/interrupts.c | 2 +- arch/x86/lib/timer.c | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/arch/x86/cpu/coreboot/coreboot.c b/arch/x86/cpu/coreboot/coreboot.c index 9c9431e..22474f5 100644 --- a/arch/x86/cpu/coreboot/coreboot.c +++ b/arch/x86/cpu/coreboot/coreboot.c @@ -68,8 +68,8 @@ int board_early_init_r(void) void show_boot_progress(int val) { #if MIN_PORT80_KCLOCKS_DELAY
static uint32_t prev_stamp;
static uint32_t base;
static uint32_t prev_stamp __attribute__((section(".data")));
static uint32_t base __attribute__((section(".data")));
NAK
This may work for coreboot where SDRAM is already initialised and you've loaded U-Boot into RAM, but it will not work when U-Boot is in Flash as all sections (including .data) are read-only until after relocation.
The stack and Global Data are the only guaranteed read/write locations prior to relocation
Ah yes, I was thinking of your comment that all boards would move to use coreboot. If that is not the case, then I will need to add something to global data for the timer. And I don't want to do that while generic board is in progress since it creates conflicts.
I'm trying to remember the context of my comment regarding only having coreboot boards. But anyway, not having any writeable data prior to relocation (other than the stack and gd) is a fundamental principle that we cannot simply avoid (although I must admit I don't know what the go is with SPL and U-Boot relocation).
Any thoughts on this point, please? I presume at least I can use RAM once dram_init() is called. But when running from coreboot the RAM is already set up...
You will need to use global data to store the static variables. That's what the other arches do
That line is blurred a bit now, but OK I will do that. I will put this series on hold until we see what happens with the arch-specific global_data series.
Regards, Simon
Regards,
Graeme

With this symbol we can easy append something (e.g. an FDT) to the U-Boot binary and access it from within U-Boot.
Signed-off-by: Simon Glass sjg@chromium.org --- arch/x86/cpu/u-boot.lds | 2 ++ arch/x86/include/asm/u-boot-x86.h | 1 + arch/x86/lib/init_helpers.c | 2 +- 3 files changed, 4 insertions(+), 1 deletions(-)
diff --git a/arch/x86/cpu/u-boot.lds b/arch/x86/cpu/u-boot.lds index 0c6f0e3..2a7d0fd 100644 --- a/arch/x86/cpu/u-boot.lds +++ b/arch/x86/cpu/u-boot.lds @@ -67,6 +67,8 @@ SECTIONS __rel_dyn_start = .; .rel.dyn : { *(.rel.dyn) } __rel_dyn_end = .; + . = ALIGN(4); + __end = .;
/DISCARD/ : { *(.dynstr*) } /DISCARD/ : { *(.dynamic*) } diff --git a/arch/x86/include/asm/u-boot-x86.h b/arch/x86/include/asm/u-boot-x86.h index 99062e5..ef0da4f 100644 --- a/arch/x86/include/asm/u-boot-x86.h +++ b/arch/x86/include/asm/u-boot-x86.h @@ -31,6 +31,7 @@ extern ulong __rel_dyn_start; extern ulong __rel_dyn_end; extern ulong __bss_start; extern ulong __bss_end; +extern ulong __end;
/* cpu/.../cpu.c */ int x86_cpu_init_r(void); diff --git a/arch/x86/lib/init_helpers.c b/arch/x86/lib/init_helpers.c index 1a097f1..9a72f3b 100644 --- a/arch/x86/lib/init_helpers.c +++ b/arch/x86/lib/init_helpers.c @@ -188,7 +188,7 @@ int find_fdt(void) gd->fdt_blob = _binary_dt_dtb_start; #elif defined CONFIG_OF_SEPARATE /* FDT is at end of image */ - gd->fdt_blob = (void *)(_end_ofs + _TEXT_BASE); + gd->fdt_blob = (ulong *)&__end; #endif /* Allow the early environment to override the fdt address */ gd->fdt_blob = (void *)getenv_ulong("fdtcontroladdr", 16,

At present BSS data is including in the image, which wastes binary space. Remove it by rearranging the sections so that BSS is last.
Signed-off-by: Simon Glass sjg@chromium.org --- arch/x86/cpu/u-boot.lds | 19 ++++++++++++------- 1 files changed, 12 insertions(+), 7 deletions(-)
diff --git a/arch/x86/cpu/u-boot.lds b/arch/x86/cpu/u-boot.lds index 2a7d0fd..e455fb9 100644 --- a/arch/x86/cpu/u-boot.lds +++ b/arch/x86/cpu/u-boot.lds @@ -46,9 +46,6 @@ SECTIONS .data : { *(.data*) }
. = ALIGN(4); - .dynsym : { *(.dynsym*) } - - . = ALIGN(4); .hash : { *(.hash*) }
. = ALIGN(4); @@ -58,10 +55,7 @@ SECTIONS __data_end = .;
. = ALIGN(4); - __bss_start = ABSOLUTE(.); - .bss (NOLOAD) : { *(.bss) } - . = ALIGN(4); - __bss_end = ABSOLUTE(.); + .dynsym : { *(.dynsym*) }
. = ALIGN(4); __rel_dyn_start = .; @@ -70,6 +64,17 @@ SECTIONS . = ALIGN(4); __end = .;
+ . = ALIGN(4); + + __end = .; + .bss __rel_dyn_start (OVERLAY) : { + __bss_start = .; + *(.bss) + *(COM*) + . = ALIGN(4); + __bss_end = .; + } + /DISCARD/ : { *(.dynstr*) } /DISCARD/ : { *(.dynamic*) } /DISCARD/ : { *(.plt*) }

With CONFIG_OF_CONTROL we may have an FDT in the BSS region. Relocate it up with the rest of U-Boot to keep the rest of memory free.
Signed-off-by: Simon Glass sjg@chromium.org --- arch/x86/include/asm/global_data.h | 1 + arch/x86/include/asm/init_helpers.h | 2 ++ arch/x86/include/asm/relocate.h | 1 + arch/x86/lib/board.c | 3 +++ arch/x86/lib/init_helpers.c | 23 +++++++++++++++++++++-- arch/x86/lib/init_wrappers.c | 1 + arch/x86/lib/relocate.c | 17 +++++++++++++++++ 7 files changed, 46 insertions(+), 2 deletions(-)
diff --git a/arch/x86/include/asm/global_data.h b/arch/x86/include/asm/global_data.h index dc6402b..2f3644e 100644 --- a/arch/x86/include/asm/global_data.h +++ b/arch/x86/include/asm/global_data.h @@ -59,6 +59,7 @@ struct global_data { phys_size_t ram_size; /* RAM size */ unsigned long reset_status; /* reset status register at boot */ const void *fdt_blob; /* Our device tree, NULL if none */ + void *new_fdt; /* Relocated FDT */ void **jt; /* jump table */ char env_buf[32]; /* buffer for getenv() before reloc. */ }; diff --git a/arch/x86/include/asm/init_helpers.h b/arch/x86/include/asm/init_helpers.h index 2f437e0..d018b29 100644 --- a/arch/x86/include/asm/init_helpers.h +++ b/arch/x86/include/asm/init_helpers.h @@ -38,5 +38,7 @@ int flash_init_r(void); int status_led_set_r(void); int set_load_addr_r(void); int init_func_spi(void); +int find_fdt(void); +int prepare_fdt(void);
#endif /* !_INIT_HELPERS_H_ */ diff --git a/arch/x86/include/asm/relocate.h b/arch/x86/include/asm/relocate.h index 33129ef..d371c9d 100644 --- a/arch/x86/include/asm/relocate.h +++ b/arch/x86/include/asm/relocate.h @@ -27,6 +27,7 @@ #include <common.h>
int copy_uboot_to_ram(void); +int copy_fdt_to_ram(void); int clear_bss(void); int do_elf_reloc_fixups(void);
diff --git a/arch/x86/lib/board.c b/arch/x86/lib/board.c index 22bc26d..555301a 100644 --- a/arch/x86/lib/board.c +++ b/arch/x86/lib/board.c @@ -32,6 +32,7 @@ */
#include <common.h> +#include <fdtdec.h> #include <watchdog.h> #include <stdio_dev.h> #include <asm/u-boot-x86.h> @@ -131,6 +132,7 @@ init_fnc_t *init_sequence_f[] = { init_fnc_t *init_sequence_f_r[] = { init_cache_f_r, copy_uboot_to_ram, + copy_fdt_to_ram, clear_bss, do_elf_reloc_fixups,
@@ -217,6 +219,7 @@ static void do_init_loop(init_fnc_t **init_fnc_ptr)
void board_init_f(ulong boot_flags) { + gd->fdt_blob = gd->new_fdt = NULL; gd->flags = boot_flags;
do_init_loop(init_sequence_f); diff --git a/arch/x86/lib/init_helpers.c b/arch/x86/lib/init_helpers.c index 9a72f3b..5b28dcf 100644 --- a/arch/x86/lib/init_helpers.c +++ b/arch/x86/lib/init_helpers.c @@ -22,6 +22,7 @@ */ #include <common.h> #include <command.h> +#include <fdtdec.h> #include <stdio_dev.h> #include <version.h> #include <malloc.h> @@ -85,17 +86,35 @@ int calculate_relocation_address(void) (uintptr_t)&__text_start; ulong total_size; ulong dest_addr; + ulong fdt_size = 0;
+#if defined(CONFIG_OF_SEPARATE) && defined(CONFIG_OF_CONTROL) + if (gd->fdt_blob) + fdt_size = ALIGN(fdt_totalsize(gd->fdt_blob) + 0x1000, 32); +#endif total_size = ALIGN(uboot_size, 1 << 12) + CONFIG_SYS_MALLOC_LEN + - CONFIG_SYS_STACK_SIZE; + CONFIG_SYS_STACK_SIZE + fdt_size;
+ dest_addr = board_get_usable_ram_top(total_size); /* * NOTE: All destination address are rounded down to 16-byte * boundary to satisfy various worst-case alignment * requirements */ - dest_addr = board_get_usable_ram_top(total_size); + dest_addr &= ~15;
+#if defined(CONFIG_OF_SEPARATE) && defined(CONFIG_OF_CONTROL) + /* + * If the device tree is sitting immediate above our image then we + * must relocate it. If it is embedded in the data section, then it + * will be relocated with other data. + */ + if (gd->fdt_blob) { + dest_addr -= fdt_size; + gd->new_fdt = (void *)dest_addr; + dest_addr &= ~15; + } +#endif /* U-Boot is below the FDT */ dest_addr -= uboot_size; dest_addr &= ~((1 << 12) - 1); diff --git a/arch/x86/lib/init_wrappers.c b/arch/x86/lib/init_wrappers.c index cca018f..19af875 100644 --- a/arch/x86/lib/init_wrappers.c +++ b/arch/x86/lib/init_wrappers.c @@ -22,6 +22,7 @@ */ #include <common.h> #include <environment.h> +#include <fdtdec.h> #include <serial.h> #include <kgdb.h> #include <scsi.h> diff --git a/arch/x86/lib/relocate.c b/arch/x86/lib/relocate.c index 23edca9..e9188a7 100644 --- a/arch/x86/lib/relocate.c +++ b/arch/x86/lib/relocate.c @@ -32,6 +32,7 @@ */
#include <common.h> +#include <libfdt.h> #include <malloc.h> #include <asm/u-boot-x86.h> #include <asm/relocate.h> @@ -46,6 +47,22 @@ int copy_uboot_to_ram(void) return 0; }
+int copy_fdt_to_ram(void) +{ + if (gd->new_fdt) { + ulong fdt_size; + + fdt_size = ALIGN(fdt_totalsize(gd->fdt_blob) + 0x1000, 32); + + memcpy(gd->new_fdt, gd->fdt_blob, fdt_size); + debug("Relocated fdt from %p to %p, size %lx\n", + gd->fdt_blob, gd->new_fdt, fdt_size); + gd->fdt_blob = gd->new_fdt; + } + + return 0; +} + int clear_bss(void) { ulong dst_addr = (ulong)&__bss_start + gd->reloc_off;

This does not actually change normal behaviour, but adds a check that should detect corruption of relocation data (e.g. by using BSS data prior to relocation).
Also add additional debugging output when enabled.
During this investigation, two situations have been seen: 1. calculate_relocation_address(): uintptr_t size = (uintptr_t)&__bss_end - (uintptr_t)&__text_start;
turns into 111166f: b8 83 c4 17 01 mov $0x117c483,%eax
whih is beyond the end of bss:
0117b484 g .bss 00000000 __bss_end
Somehow the __bss_end here is 255 bytes ahead.
2. do_elf_reloc_fixups():
uintptr_t size = (uintptr_t)&__bss_end - (uintptr_t)&__text_start;
Here the __text_start is 0 in the file:
1111d9f: bb a0 e0 13 01 mov $0x113e0a0,%ebx 1111da4: 81 ef 00 00 00 00 sub $0x0,%edi
As it happens, both of these are in pre-relocation code.
For these reasons we silent check and ignore bad relocations.
Signed-off-by: Simon Glass sjg@chromium.org --- arch/x86/lib/relocate.c | 20 ++++++++++++++++++-- 1 files changed, 18 insertions(+), 2 deletions(-)
diff --git a/arch/x86/lib/relocate.c b/arch/x86/lib/relocate.c index e9188a7..e893c2b 100644 --- a/arch/x86/lib/relocate.c +++ b/arch/x86/lib/relocate.c @@ -73,12 +73,16 @@ int clear_bss(void) return 0; }
+/* + * This function has more error checking than you might expect. Please see + * the commit message for more informaiton. + */ int do_elf_reloc_fixups(void) { Elf32_Rel *re_src = (Elf32_Rel *)(&__rel_dyn_start); Elf32_Rel *re_end = (Elf32_Rel *)(&__rel_dyn_end);
- Elf32_Addr *offset_ptr_rom; + Elf32_Addr *offset_ptr_rom, *last_offset = NULL; Elf32_Addr *offset_ptr_ram;
/* The size of the region of u-boot that runs out of RAM. */ @@ -89,7 +93,8 @@ int do_elf_reloc_fixups(void) offset_ptr_rom = (Elf32_Addr *)re_src->r_offset;
/* Check that the location of the relocation is in .text */ - if (offset_ptr_rom >= (Elf32_Addr *)CONFIG_SYS_TEXT_BASE) { + if (offset_ptr_rom >= (Elf32_Addr *)CONFIG_SYS_TEXT_BASE && + offset_ptr_rom > last_offset) {
/* Switch to the in-RAM version */ offset_ptr_ram = (Elf32_Addr *)((ulong)offset_ptr_rom + @@ -100,8 +105,19 @@ int do_elf_reloc_fixups(void) *offset_ptr_ram <= (CONFIG_SYS_TEXT_BASE + size)) { *offset_ptr_ram += gd->reloc_off; + } else { + debug(" %p: rom reloc %x, ram %p, value %x," + " limit %lx\n", re_src, + re_src->r_offset, offset_ptr_ram, + *offset_ptr_ram, + CONFIG_SYS_TEXT_BASE + size); } + } else { + debug(" %p: rom reloc %x, last %p\n", re_src, + re_src->r_offset, last_offset); } + last_offset = offset_ptr_rom; + } while (++re_src < re_end);
return 0;

This is currently set to coreboot.dtsi, but we cannot support this on old device tree compilers (dtc <= 1.3), so adjust to use ARCH_CPU_DTS to let the Makefile preprocessor sort this out.
Signed-off-by: Simon Glass sjg@chromium.org --- board/chromebook-x86/dts/link.dts | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/board/chromebook-x86/dts/link.dts b/board/chromebook-x86/dts/link.dts index af60f59..ae8217d 100644 --- a/board/chromebook-x86/dts/link.dts +++ b/board/chromebook-x86/dts/link.dts @@ -1,6 +1,6 @@ /dts-v1/;
-/include/ "coreboot.dtsi" +/include/ ARCH_CPU_DTS
/ { #address-cells = <1>;

Make use of a device tree on coreboot boards, and set the default to link.
Signed-off-by: Simon Glass sjg@chromium.org --- include/configs/coreboot.h | 6 ++++++ 1 files changed, 6 insertions(+), 0 deletions(-)
diff --git a/include/configs/coreboot.h b/include/configs/coreboot.h index adeace0..5f736f2 100644 --- a/include/configs/coreboot.h +++ b/include/configs/coreboot.h @@ -43,6 +43,12 @@ #define CONFIG_ZBOOT_32 #define CONFIG_PHYSMEM
+#define CONFIG_LMB +#define CONFIG_OF_LIBFDT +#define CONFIG_OF_CONTROL +#define CONFIG_OF_SEPARATE +#define CONFIG_DEFAULT_DEVICE_TREE link + /*----------------------------------------------------------------------- * Watchdog Configuration */

We don't need this code with coreboot.
Signed-off-by: Simon Glass sjg@chromium.org --- include/configs/coreboot.h | 1 + 1 files changed, 1 insertions(+), 0 deletions(-)
diff --git a/include/configs/coreboot.h b/include/configs/coreboot.h index 5f736f2..fd383ff 100644 --- a/include/configs/coreboot.h +++ b/include/configs/coreboot.h @@ -38,6 +38,7 @@ #define CONFIG_SHOW_BOOT_PROGRESS #define CONFIG_LAST_STAGE_INIT #define CONFIG_X86_NO_RESET_VECTOR +#define CONFIG_X86_NO_REAL_MODE #define CONFIG_SYS_VSNPRINTF #define CONFIG_INTEL_CORE_ARCH /* Sandy bridge and ivy bridge chipsets. */ #define CONFIG_ZBOOT_32
participants (2)
-
Graeme Russ
-
Simon Glass