Resize device tree to allow space for board changes and the chosen node

Current code requires that a compiled device tree have space added to the end to
leave room for extra nodes added by board code (and the chosen node).  This
requires that device tree creators anticipate how much space U-Boot will add to
the tree, which is absurd.  Ideally, the code would resize and/or relocate the
tree when it needed more space, but this would require a systemic change to the
fdt code, which is non-trivial.  Instead, we resize the tree inside
boot_relocate_fdt, reserving either the remainder of the bootmap (in the case
where the fdt is inside the bootmap), or adding CFG_FDT_PAD bytes to the size.

Signed-off-by: Andy Fleming <afleming@freescale.com>
This commit is contained in:
Andy Fleming 2008-06-16 13:58:56 -05:00 committed by Wolfgang Denk
parent 7570a9941f
commit 41c5eaa725

View File

@ -51,6 +51,10 @@ static int boot_relocate_fdt (struct lmb *lmb, ulong bootmap_base,
#include <asm/cache.h>
#endif
#ifndef CFG_FDT_PAD
#define CFG_FDT_PAD 0x3000
#endif
DECLARE_GLOBAL_DATA_PTR;
extern int do_reset (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]);
@ -191,6 +195,44 @@ do_bootm_linux(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[],
ft_board_setup(of_flat_tree, gd->bd);
#endif
}
/* Fixup the fdt memreserve now that we know how big it is */
if (of_flat_tree) {
int j;
uint64_t addr, size;
int total = fdt_num_mem_rsv(of_flat_tree);
uint actualsize;
for (j = 0; j < total; j++) {
fdt_get_mem_rsv(of_flat_tree, j, &addr, &size);
if (addr == (uint64_t)of_flat_tree) {
fdt_del_mem_rsv(of_flat_tree, j);
break;
}
}
/* Delete the old LMB reservation */
lmb_free(lmb, of_flat_tree, fdt_totalsize(of_flat_tree));
/* Calculate the actual size of the fdt */
actualsize = fdt_off_dt_strings(of_flat_tree) +
fdt_size_dt_strings(of_flat_tree);
/* Make it so the fdt ends on a page boundary */
actualsize = ALIGN(actualsize, 0x1000);
actualsize = actualsize - ((uint)of_flat_tree & 0xfff);
/* Change the fdt header to reflect the correct size */
fdt_set_totalsize(of_flat_tree, actualsize);
of_size = actualsize;
/* Add the new reservation */
ret = fdt_add_mem_rsv(of_flat_tree, (uint)of_flat_tree,
of_size);
/* Create a new LMB reservation */
lmb_reserve(lmb, (ulong)of_flat_tree, of_size);
}
#endif /* CONFIG_OF_LIBFDT */
ret = boot_ramdisk_high (lmb, rd_data_start, rd_len, &initrd_start, &initrd_end);
@ -713,22 +755,25 @@ static int boot_relocate_fdt (struct lmb *lmb, ulong bootmap_base,
#endif
/*
* The blob must be within CFG_BOOTMAPSZ,
* so we flag it to be copied if it is not.
* The blob needs to be inside the boot mapping.
*/
if (fdt_blob >= (char *)CFG_BOOTMAPSZ)
if (fdt_blob < (char *)bootmap_base)
relocate = 1;
of_len = be32_to_cpu (fdt_totalsize (fdt_blob));
if ((fdt_blob + *of_size + CFG_FDT_PAD) >=
((char *)CFG_BOOTMAPSZ + bootmap_base))
relocate = 1;
/* move flattend device tree if needed */
if (relocate) {
int err;
ulong of_start;
ulong of_start = 0;
/* position on a 4K boundary before the alloc_current */
/* Pad the FDT by a specified amount */
of_len = *of_size + CFG_FDT_PAD;
of_start = (unsigned long)lmb_alloc_base(lmb, of_len, 0x1000,
(CFG_BOOTMAPSZ + bootmap_base));
(CFG_BOOTMAPSZ + bootmap_base));
if (of_start == 0) {
puts("device tree - allocation error\n");
@ -736,7 +781,7 @@ static int boot_relocate_fdt (struct lmb *lmb, ulong bootmap_base,
}
debug ("## device tree at 0x%08lX ... 0x%08lX (len=%ld=0x%lX)\n",
(ulong)fdt_blob, (ulong)fdt_blob + of_len - 1,
(ulong)fdt_blob, (ulong)fdt_blob + *of_size - 1,
of_len, of_len);
printf (" Loading Device Tree to %08lx, end %08lx ... ",
@ -750,9 +795,14 @@ static int boot_relocate_fdt (struct lmb *lmb, ulong bootmap_base,
puts ("OK\n");
*of_flat_tree = (char *)of_start;
*of_size = of_len;
} else {
*of_flat_tree = fdt_blob;
lmb_reserve(lmb, (ulong)working_fdt, of_len);
of_len = (CFG_BOOTMAPSZ + bootmap_base) - (ulong)fdt_blob;
lmb_reserve(lmb, (ulong)fdt_blob, of_len);
fdt_set_totalsize(*of_flat_tree, of_len);
*of_size = of_len;
}
return 0;