[PATCH][RFC] image: fdt: Fix DT relocation handling with multiple DRAM banks with gap
Simon Glass
sjg at chromium.org
Sat Mar 12 03:24:28 CET 2022
Hi Marek,
On Wed, 21 Jul 2021 at 18:05, Marek Vasut <marex at denx.de> wrote:
>
> The current implementation of boot_relocate_fdt() places DT at the
> highest usable DRAM address, which is calculated as:
> env_get_bootm_low() + env_get_bootm_mapsize()
> which by default becomes gd->ram_base + gd->ram_size.
>
> Systems like i.MX53 can have multiple DRAM banks with gap between them,
> e.g. have DRAM at 0x70000000-0x8fffffff and 0xb0000000-0xcfffffff , so
> for them the calculated highest DRAM address is 0xafffffff, which is
> exactly in the gap and thus not usable.
>
> Fix this by iterating over all DRAM banks and tracking the remaining
> amount of the total mapping size obtained from env_get_bootm_mapsize().
> Limit the maximum LMB area size to each bank, to avoid using nonexistent
> DRAM.
>
> Signed-off-by: Marek Vasut <marex at denx.de>
> Cc: Heinrich Schuchardt <xypron.glpk at gmx.de>
> Cc: Simon Glass <sjg at chromium.org>
> Cc: Tom Rini <trini at konsulko.com>
> ---
> common/image-fdt.c | 40 ++++++++++++++++++++++++++++++++++++----
> 1 file changed, 36 insertions(+), 4 deletions(-)
Reviewed-by: Simon Glass <sjg at chromium.org>
Should we put this behind a Kconfig option to reduce code size?
>
> diff --git a/common/image-fdt.c b/common/image-fdt.c
> index 327a8c4c395..2b199ffc2b1 100644
> --- a/common/image-fdt.c
> +++ b/common/image-fdt.c
> @@ -157,8 +157,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;
>
> @@ -198,10 +201,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) {
> --
> 2.30.2
>
Regards,
Simon
More information about the U-Boot
mailing list