[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