[PATCH v1 4/4] common: Add an optionto relocate on ram top

Ilias Apalodimas ilias.apalodimas at linaro.org
Fri Apr 3 11:01:06 CEST 2026


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.

A previous patch moves the bi_dram[] info from bd to gd and make
the memory bank information available early. So move the
dram_init_banksize() INITCALL before the relocation address calculation
and use it to derive the address.

Also 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          |  8 ++++++++
 common/board_f.c | 17 ++++++++++++++++-
 2 files changed, 24 insertions(+), 1 deletion(-)

diff --git a/Kconfig b/Kconfig
index ce25ea24a60f..b25e7f25591d 100644
--- a/Kconfig
+++ b/Kconfig
@@ -474,6 +474,14 @@ config SKIP_RELOCATE
 	  Skips relocation of U-Boot allowing for systems that have extremely
 	  limited RAM to run U-Boot.
 
+config RELOC_ADDR_TOP
+	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. This will use the information of the
+	  board memory banks configured with dram_init_banksize().
+
 endif # EXPERT
 
 config PHYS_64BIT
diff --git a/common/board_f.c b/common/board_f.c
index dd5518b60db4..2eab344037c8 100644
--- a/common/board_f.c
+++ b/common/board_f.c
@@ -339,6 +339,10 @@ static int setup_ram_base(void)
 
 static int setup_ram_config(void)
 {
+#if CONFIG_IS_ENABLED(RELOC_ADDR_TOP)
+	int bank;
+	phys_size_t total_size = 0;
+#endif
 	debug("Monitor len: %08x\n", gd->mon_len);
 #if CONFIG_VAL(SYS_MEM_TOP_HIDE)
 	/*
@@ -353,8 +357,19 @@ static int setup_ram_config(void)
 	 */
 	gd->ram_size -= CONFIG_SYS_MEM_TOP_HIDE;
 #endif
+#if CONFIG_IS_ENABLED(RELOC_ADDR_TOP)
+	for (bank = 0; bank < CONFIG_NR_DRAM_BANKS; bank++) {
+		if (gd->ram_top <= gd->bi_dram[bank].start)
+			gd->ram_top = gd->bi_dram[bank].start +
+					gd->bi_dram[bank].size;
+		total_size += gd->bi_dram[bank].size;
+	}
+
+	gd->ram_size = total_size;
+#else
 	gd->ram_top = gd->ram_base + get_effective_memsize();
 	gd->ram_top = board_get_usable_ram_top(gd->mon_len);
+#endif
 
 	debug("Ram top: %08llX\n", (unsigned long long)gd->ram_top);
 	debug("Ram size: %08llX\n", (unsigned long long)gd->ram_size);
@@ -971,6 +986,7 @@ static void initcall_run_f(void)
 	 *  - board info struct
 	 */
 	INITCALL(setup_ram_base);
+	INITCALL(dram_init_banksize);
 	INITCALL(setup_ram_config);
 	INITCALL(setup_dest_addr);
 #if CONFIG_IS_ENABLED(OF_BOARD_FIXUP) && \
@@ -999,7 +1015,6 @@ static void initcall_run_f(void)
 	INITCALL(reserve_bloblist);
 	INITCALL(reserve_arch);
 	INITCALL(reserve_stacks);
-	INITCALL(dram_init_banksize);
 	INITCALL(show_dram_config);
 	WATCHDOG_RESET();
 	INITCALL(setup_bdinfo);
-- 
2.53.0



More information about the U-Boot mailing list