[PATCH v2 4/4] common: Allow relocations on the top of the last bank
Jonas Karlman
jonas at kwiboo.se
Wed Apr 1 10:04:36 CEST 2026
Hi Ilias,
On 3/31/2026 10:01 AM, Ilias Apalodimas wrote:
> Right now we only relocate u-boot to the top of the first
> memory bank unless the board specific code overwrites it.
> This is problematic when loading big binaries as it
> fragments the contiguous memory space for no apparent reason.
>
> It's worth noting that there are cases where we must not relocate
> above the 4GiB boundary (64bit hardware with 32bit only capable
> DMA). E.g This will break platforms, if the ethernet
> controller cannot DMA above 4 GiB, and once U-Boot does
> get relocated above 4 GiB, the packet buffer which is built
> into the U-Boot binary is also relocated above 4 GiB.
>
> Add a Kconfig option and allow the common code to relocate U-Boot
> to the top of the last discovered bank.
>
> Signed-off-by: Ilias Apalodimas <ilias.apalodimas at linaro.org>
> ---
> Kconfig | 7 +++++++
> common/board_f.c | 15 +++++++++++++++
> 2 files changed, 22 insertions(+)
>
> diff --git a/Kconfig b/Kconfig
> index ce25ea24a60f..3ebdee1b2794 100644
> --- a/Kconfig
> +++ b/Kconfig
> @@ -474,6 +474,13 @@ config SKIP_RELOCATE
> Skips relocation of U-Boot allowing for systems that have extremely
> limited RAM to run U-Boot.
>
> +config RELOCATE_LAST_BANK
> + bool "Relocate to the topmost memory address"
> + help
> + When U-Boot relocates, it chooses the end of the first memory bank.
> + Enable this if you have multiple banks and want U-Boot to relocate
> + to the topmost memory address
> +
> endif # EXPERT
>
> config PHYS_64BIT
> diff --git a/common/board_f.c b/common/board_f.c
> index df2b0dc899bf..4270f368e653 100644
> --- a/common/board_f.c
> +++ b/common/board_f.c
> @@ -309,6 +309,8 @@ __weak int mach_cpu_init(void)
> /* Get the top of usable RAM */
> __weak phys_addr_t board_get_usable_ram_top(phys_size_t total_size)
> {
> + int ret;
> +
> #if defined(CFG_SYS_SDRAM_BASE) && CFG_SYS_SDRAM_BASE > 0
> /*
> * Detect whether we have so much RAM that it goes past the end of our
> @@ -321,6 +323,19 @@ __weak phys_addr_t board_get_usable_ram_top(phys_size_t total_size)
> */
> return 0;
> #endif
> + if (IS_ENABLED(CONFIG_RELOCATE_LAST_BANK)) {
> + phys_addr_t old_top = gd->ram_top;
> +
> + ret = fdtdec_setup_mem_ram_top();
This seem to make assumption that memory is already fully described in
FDT? Maybe this should instead be based on gd->bd->bi_dram, however that
is possible initialized at a later initcall.
If I got the call chain correct board_get_usable_ram_top() is normally
called from INITCALL(setup_dest_addr), and gd->bd->bi_dram banks are
typically initialized in INITCALL(dram_init_banksize), a later initcall.
On e.g. Rockchip there is no memory bank information in FDT at that
stage and memory banks is populated to gd->bd->bi_dram based on
information from dram init and only later possible added to the FDT for
booting OS.
Rockchip does have a platform board_get_usable_ram_top() so this will
not be an issue, but the new generic Kconfig option added here seem to
have a dependency on FDT containing memory bank information, if I am not
mistaken. Maybe something worth mentioning in help and commit message?
Regards,
Jonas
> + if (ret)
> + debug("failed to relocate to ram top");
> + ret = fdtdec_setup_ram_size();
> + if (ret) {
> + debug("failed to calculate RAM size");
> + gd->ram_top = old_top;
> + }
> + }
> +
> return gd->ram_top;
> }
>
More information about the U-Boot
mailing list