always relocate fdt into an lmb-allocated memory block

The device tree (fdt) must always exist in within the bootmap (usually the
first 16MB of RAM).  If it doesn't, then boot_relocate_fdt() will allocate
an LMB region in the bootmap and copy the fdt into that region.  It will
also increase the size of the fdt.

If the fdt is already in the bootmap, then previously the memory was just
reserved.  There was no contingency if the reservation failed, however.

By always allocating an lmb region and copying/resizing the fdt into that
region, the code is simplified and the memory region is always allocated
properly.

Also change the types of some variables to avoid some typecasts.

Signed-off-by: Timur Tabi <timur@freescale.com>
Tested-by: Ira Snyder <iws@ovro.caltech.edu>
Acked-by: Gerald Van Baren <vanbaren@cideas.com>
Signed-off-by: Kumar Gala <galak@kernel.crashing.org>
This commit is contained in:
Timur Tabi 2010-05-24 15:10:25 -05:00 committed by Kumar Gala
parent a1964ea5c2
commit 43b08af53e
1 changed files with 31 additions and 58 deletions

View File

@ -1176,8 +1176,10 @@ static int fit_check_fdt (const void *fit, int fdt_noffset, int verify)
* @of_flat_tree: pointer to a char* variable, will hold fdt start address
* @of_size: pointer to a ulong variable, will hold fdt length
*
* boot_relocate_fdt() determines if the of_flat_tree address is within
* the bootmap and if not relocates it into that region
* boot_relocate_fdt() allocates a region of memory within the bootmap and
* relocates the of_flat_tree into that region, even if the fdt is already in
* the bootmap. It also expands the size of the fdt by CONFIG_SYS_FDT_PAD
* bytes.
*
* of_flat_tree and of_size are set to final (after relocation) values
*
@ -1189,9 +1191,10 @@ static int fit_check_fdt (const void *fit, int fdt_noffset, int verify)
int boot_relocate_fdt (struct lmb *lmb, ulong bootmap_base,
char **of_flat_tree, ulong *of_size)
{
char *fdt_blob = *of_flat_tree;
ulong relocate = 0;
void *fdt_blob = *of_flat_tree;
void *of_start = 0;
ulong of_len = 0;
int err;
/* nothing to do */
if (*of_size == 0)
@ -1202,63 +1205,33 @@ int boot_relocate_fdt (struct lmb *lmb, ulong bootmap_base,
goto error;
}
#ifndef CONFIG_SYS_NO_FLASH
/* move the blob if it is in flash (set relocate) */
if (addr2info ((ulong)fdt_blob) != NULL)
relocate = 1;
#endif
/* position on a 4K boundary before the alloc_current */
/* Pad the FDT by a specified amount */
of_len = *of_size + CONFIG_SYS_FDT_PAD;
of_start = (void *)(unsigned long)lmb_alloc_base(lmb, of_len, 0x1000,
(CONFIG_SYS_BOOTMAPSZ + bootmap_base));
/*
* The blob needs to be inside the boot mapping.
*/
if (fdt_blob < (char *)bootmap_base)
relocate = 1;
if ((fdt_blob + *of_size + CONFIG_SYS_FDT_PAD) >=
((char *)CONFIG_SYS_BOOTMAPSZ + bootmap_base))
relocate = 1;
/* move flattend device tree if needed */
if (relocate) {
int err;
ulong of_start = 0;
/* position on a 4K boundary before the alloc_current */
/* Pad the FDT by a specified amount */
of_len = *of_size + CONFIG_SYS_FDT_PAD;
of_start = (unsigned long)lmb_alloc_base(lmb, of_len, 0x1000,
(CONFIG_SYS_BOOTMAPSZ + bootmap_base));
if (of_start == 0) {
puts("device tree - allocation error\n");
goto error;
}
debug ("## device tree at 0x%08lX ... 0x%08lX (len=%ld=0x%lX)\n",
(ulong)fdt_blob, (ulong)fdt_blob + *of_size - 1,
of_len, of_len);
printf (" Loading Device Tree to %08lx, end %08lx ... ",
of_start, of_start + of_len - 1);
err = fdt_open_into (fdt_blob, (void *)of_start, of_len);
if (err != 0) {
fdt_error ("fdt move failed");
goto error;
}
puts ("OK\n");
*of_flat_tree = (char *)of_start;
*of_size = of_len;
} else {
*of_flat_tree = fdt_blob;
of_len = *of_size + CONFIG_SYS_FDT_PAD;
lmb_reserve(lmb, (ulong)fdt_blob, of_len);
fdt_set_totalsize(*of_flat_tree, of_len);
*of_size = of_len;
if (of_start == 0) {
puts("device tree - allocation error\n");
goto error;
}
debug ("## device tree at %p ... %p (len=%ld [0x%lX])\n",
fdt_blob, fdt_blob + *of_size - 1, of_len, of_len);
printf (" Loading Device Tree to %p, end %p ... ",
of_start, of_start + of_len - 1);
err = fdt_open_into (fdt_blob, of_start, of_len);
if (err != 0) {
fdt_error ("fdt move failed");
goto error;
}
puts ("OK\n");
*of_flat_tree = of_start;
*of_size = of_len;
set_working_fdt_addr(*of_flat_tree);
return 0;