[U-Boot] [PATCH 1/2] spl: add relocation support

Andy Yan andy.yan at rock-chips.com
Mon Apr 29 09:04:47 UTC 2019


Some times we want to relocate spl code to dram after dram
initialization or relocate spl code to a high memory to avoid
code overide.

For example on Rockchip armv8 platform, we run with boot flow
TPL->SPL->ATF->U-Boot.

TPL run in sram and is responsible for dram initialization.
SPL run from the start address of dram and is responsible for
loading ATF and U-Boot.

The case here is that the ATF load address is from 64KB of dram,
which overlaps with spl code itself.

So we want to relocate spl itself to high memory to aovid this.

Signed-off-by: Andy Yan <andy.yan at rock-chips.com>
---

 common/spl/Kconfig | 13 +++++++++++
 common/spl/spl.c   | 55 ++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 68 insertions(+)

diff --git a/common/spl/Kconfig b/common/spl/Kconfig
index 206c24076d..52669ce1f8 100644
--- a/common/spl/Kconfig
+++ b/common/spl/Kconfig
@@ -189,6 +189,19 @@ config SPL_DISPLAY_PRINT
 	  banner ("U-Boot SPL ..."). This function should be provided by
 	  the board.
 
+config SPL_SKIP_RELOCATE
+	bool "Skip code relocation in SPL"
+	default y
+	help
+	  The SPL code will be relocated to a high memory if you say no here.
+	  Only ARM64 and PowerPC SPL support relocate now.
+
+config SPL_RELOC_TEXT_BASE
+	hex "Address the SPL relocate to"
+	depends on !SPL_SKIP_RELOCATE
+	help
+	  The address on the ram where the SPL relocate to.
+
 config SYS_MMCSD_RAW_MODE_U_BOOT_USE_SECTOR
 	bool "MMC raw mode: by sector"
 	default y if ARCH_SUNXI || ARCH_DAVINCI || ARCH_UNIPHIER || \
diff --git a/common/spl/spl.c b/common/spl/spl.c
index 88d4b8a9bf..affb65ccbd 100644
--- a/common/spl/spl.c
+++ b/common/spl/spl.c
@@ -12,6 +12,7 @@
 #include <dm.h>
 #include <handoff.h>
 #include <spl.h>
+#include <asm/sections.h>
 #include <asm/u-boot.h>
 #include <nand.h>
 #include <fat.h>
@@ -439,6 +440,28 @@ static int spl_common_init(bool setup_malloc)
 	return 0;
 }
 
+#if !defined(CONFIG_SPL_SKIP_RELOCATE) && !defined(CONFIG_TPL_BUILD)
+static void spl_setup_relocate(void)
+{
+	gd->relocaddr = CONFIG_SPL_RELOC_TEXT_BASE;
+	gd->new_gd = (gd_t *)gd;
+	gd->start_addr_sp = gd->relocaddr;
+	gd->fdt_size = ALIGN(fdt_totalsize(gd->fdt_blob) + 0x1000, 32);
+
+	gd->start_addr_sp -= gd->fdt_size;
+	gd->new_fdt = (void *)gd->start_addr_sp;
+	memcpy(gd->new_fdt, gd->fdt_blob, gd->fdt_size);
+	gd->fdt_blob = gd->new_fdt;
+
+	gd->reloc_off = gd->relocaddr - (unsigned long)__image_copy_start;
+}
+#else
+static void spl_setup_relocate(void)
+{
+
+}
+#endif
+
 void spl_set_bd(void)
 {
 	/*
@@ -460,6 +483,8 @@ int spl_early_init(void)
 		return ret;
 	gd->flags |= GD_FLG_SPL_EARLY_INIT;
 
+	spl_setup_relocate();
+
 	return 0;
 }
 
@@ -563,6 +588,34 @@ static int boot_from_devices(struct spl_image_info *spl_image,
 	return -ENODEV;
 }
 
+#if defined(CONFIG_DM) && !defined(CONFIG_SPL_SKIP_RELOCATE) && !defined(CONFIG_TPL_BUILD)
+static int spl_initr_dm(void)
+{
+	int ret;
+
+	/* Save the pre-reloc driver model and start a new one */
+	gd->dm_root_f = gd->dm_root;
+	gd->dm_root = NULL;
+	bootstage_start(BOOTSTATE_ID_ACCUM_DM_R, "dm_r");
+	ret = dm_init_and_scan(false);
+	bootstage_accum(BOOTSTATE_ID_ACCUM_DM_R);
+	if (ret)
+		return ret;
+
+#if defined(CONFIG_TIMER)
+	gd->timer = NULL;
+#endif
+	serial_init();
+
+	return 0;
+}
+#else
+static int spl_initr_dm(void)
+{
+	return 0;
+}
+#endif
+
 void board_init_r(gd_t *dummy1, ulong dummy2)
 {
 	u32 spl_boot_list[] = {
@@ -577,6 +630,8 @@ void board_init_r(gd_t *dummy1, ulong dummy2)
 
 	debug(">>" SPL_TPL_PROMPT "board_init_r()\n");
 
+	spl_initr_dm();
+
 	spl_set_bd();
 
 #if defined(CONFIG_SYS_SPL_MALLOC_START)
-- 
2.17.1





More information about the U-Boot mailing list