diff options
Diffstat (limited to 'boot/image-fdt.c')
-rw-r--r-- | boot/image-fdt.c | 40 |
1 files changed, 36 insertions, 4 deletions
diff --git a/boot/image-fdt.c b/boot/image-fdt.c index fdb69926a2..9db2cee994 100644 --- a/boot/image-fdt.c +++ b/boot/image-fdt.c @@ -165,8 +165,11 @@ int boot_relocate_fdt(struct lmb *lmb, char **of_flat_tree, ulong *of_size) { void *fdt_blob = *of_flat_tree; void *of_start = NULL; + u64 start, size, usable; char *fdt_high; + ulong mapsize, low; ulong of_len = 0; + int bank; int err; int disable_relocation = 0; @@ -206,10 +209,39 @@ int boot_relocate_fdt(struct lmb *lmb, char **of_flat_tree, ulong *of_size) (void *)(ulong) lmb_alloc(lmb, of_len, 0x1000); } } else { - of_start = - (void *)(ulong) lmb_alloc_base(lmb, of_len, 0x1000, - env_get_bootm_mapsize() - + env_get_bootm_low()); + mapsize = env_get_bootm_mapsize(); + low = env_get_bootm_low(); + of_start = NULL; + + for (bank = 0; bank < CONFIG_NR_DRAM_BANKS; bank++) { + start = gd->bd->bi_dram[bank].start; + size = gd->bd->bi_dram[bank].size; + + /* DRAM bank addresses are too low, skip it. */ + if (start + size < low) + continue; + + usable = min(size, (u64)mapsize); + + /* + * At least part of this DRAM bank is usable, try + * using it for LMB allocation. + */ + of_start = + (void *)(ulong) lmb_alloc_base(lmb, of_len, 0x1000, + start + usable); + /* Allocation succeeded, use this block. */ + if (of_start != NULL) + break; + + /* + * Reduce the mapping size in the next bank + * by the size of attempt in current bank. + */ + mapsize -= usable - max(start, (u64)low); + if (!mapsize) + break; + } } if (of_start == NULL) { |