diff options
author | Simon Glass <sjg@chromium.org> | 2013-02-28 19:26:15 +0000 |
---|---|---|
committer | Simon Glass <sjg@chromium.org> | 2013-03-04 15:57:47 -0800 |
commit | f697d528caba0c30382b7269fd36f1111e51810d (patch) | |
tree | d2dceffbd191c1e1a3481c06a32597af9d580a98 /arch/x86/lib | |
parent | f82d15ead1badc329c4c804f0405e32289f46dd8 (diff) |
x86: Support relocation of FDT on start-up
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>
Diffstat (limited to 'arch/x86/lib')
-rw-r--r-- | arch/x86/lib/board.c | 3 | ||||
-rw-r--r-- | arch/x86/lib/init_helpers.c | 23 | ||||
-rw-r--r-- | arch/x86/lib/init_wrappers.c | 1 | ||||
-rw-r--r-- | arch/x86/lib/relocate.c | 17 |
4 files changed, 42 insertions, 2 deletions
diff --git a/arch/x86/lib/board.c b/arch/x86/lib/board.c index 22bc26dde9..2441a66ae2 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->arch.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 ff2d21f4c5..414fdcc4c9 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->arch.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 cca018fa9b..19af875c0e 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 23edca9526..3a38e52ac9 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->arch.new_fdt) { + ulong fdt_size; + + fdt_size = ALIGN(fdt_totalsize(gd->fdt_blob) + 0x1000, 32); + + memcpy(gd->arch.new_fdt, gd->fdt_blob, fdt_size); + debug("Relocated fdt from %p to %p, size %lx\n", + gd->fdt_blob, gd->arch.new_fdt, fdt_size); + gd->fdt_blob = gd->arch.new_fdt; + } + + return 0; +} + int clear_bss(void) { ulong dst_addr = (ulong)&__bss_start + gd->reloc_off; |