[PATCH v2 1/3] mach-sunxi: Add boot device detection for SUNIV/F1C100s

Jesse Taube mr.bossman075 at gmail.com
Sat Feb 12 01:32:33 CET 2022


In contrast to other Allwinner SoCs the F1C100s BROM does not store a
boot source indicator in the eGON header in SRAM. This leaves the SPL
guessing where we were exactly booted from, and for instance trying
the SD card first, even though we booted from SPI flash.

By inspecting the BROM code and by experimentation, Samuel found that the
top of the BROM stack contains unique pointers for each of the boot
sources, which we can use as a boot source indicator.

This patch removes the existing board_boot_order bodge and replace it
with a proper boot source indication function.

Signed-off-by: Jesse Taube <Mr.Bossman075 at gmail.com>
Suggested-by: Samuel Holland <samuel at sholland.org>
---
V1 -> V2:
* Bail on NAND
* Change commit description
* Change sunxi_get_boot_source to u32
* Fix FEL boot by next change
* Move suniv_get_boot_device call into sunxi_get_boot_source
* Rename suniv_get_boot_device
* Remove redundant comments
---
 arch/arm/include/asm/arch-sunxi/spl.h | 10 +++++
 arch/arm/mach-sunxi/board.c           | 57 +++++++++++++--------------
 2 files changed, 38 insertions(+), 29 deletions(-)

diff --git a/arch/arm/include/asm/arch-sunxi/spl.h b/arch/arm/include/asm/arch-sunxi/spl.h
index 58cdf806d9..9a6e8da8e1 100644
--- a/arch/arm/include/asm/arch-sunxi/spl.h
+++ b/arch/arm/include/asm/arch-sunxi/spl.h
@@ -19,6 +19,16 @@
 #define SUNXI_BOOTED_FROM_MMC0_HIGH	0x10
 #define SUNXI_BOOTED_FROM_MMC2_HIGH	0x12
 
+/*
+ * Values taken from the Bootrom's stack used
+ * to determine where we booted from.
+ */
+
+#define SUNIV_BOOTED_FROM_MMC0	0xffff40f8
+#define SUNIV_BOOTED_FROM_NAND	0xffff4114
+#define SUNIV_BOOTED_FROM_SPI	0xffff4130
+#define SUNIV_BOOTED_FROM_MMC1	0xffff4150
+
 #define is_boot0_magic(addr)	(memcmp((void *)(addr), BOOT0_MAGIC, 8) == 0)
 
 uint32_t sunxi_get_boot_device(void);
diff --git a/arch/arm/mach-sunxi/board.c b/arch/arm/mach-sunxi/board.c
index 57078f7a7b..27aee1e445 100644
--- a/arch/arm/mach-sunxi/board.c
+++ b/arch/arm/mach-sunxi/board.c
@@ -191,12 +191,37 @@ SPL_LOAD_IMAGE_METHOD("FEL", 0, BOOT_DEVICE_BOARD, spl_board_load_image);
 
 #define SUNXI_INVALID_BOOT_SOURCE	-1
 
-static int sunxi_get_boot_source(void)
+static uint32_t suniv_get_boot_source(void)
+{
+	/* Get the last function call from BootRom's stack. */
+	u32 brom_call = *(u32 *)(fel_stash.sp - 4);
+
+	/* translate SUNIV Bootrom stack to standard SUNXI boot sources */
+	switch (brom_call) {
+	case SUNIV_BOOTED_FROM_MMC0:
+		return SUNXI_BOOTED_FROM_MMC0;
+	case SUNIV_BOOTED_FROM_SPI:
+		return SUNXI_BOOTED_FROM_SPI;
+	case SUNIV_BOOTED_FROM_MMC1:
+		return SUNXI_BOOTED_FROM_MMC2;
+	/* SPI nand is invalid try to boot from FEL*/
+	case SUNIV_BOOTED_FROM_NAND:
+		return SUNXI_INVALID_BOOT_SOURCE;
+	}
+	/* If we get here something went wrong try to boot from FEL.*/
+	printf("Unknown boot source from BROM: 0x%x\n", brom_call);
+	return SUNXI_INVALID_BOOT_SOURCE;
+}
+
+static uint32_t sunxi_get_boot_source(void)
 {
 	if (!is_boot0_magic(SPL_ADDR + 4)) /* eGON.BT0 */
 		return SUNXI_INVALID_BOOT_SOURCE;
 
-	return readb(SPL_ADDR + 0x28);
+	if (IS_ENABLED(CONFIG_MACH_SUNIV))
+		return suniv_get_boot_source();
+	else
+		return readb(SPL_ADDR + 0x28);
 }
 
 /* The sunxi internal brom will try to loader external bootloader
@@ -204,7 +229,7 @@ static int sunxi_get_boot_source(void)
  */
 uint32_t sunxi_get_boot_device(void)
 {
-	int boot_source = sunxi_get_boot_source();
+	uint32_t boot_source = sunxi_get_boot_source();
 
 	/*
 	 * When booting from the SD card or NAND memory, the "eGON.BT0"
@@ -276,36 +301,10 @@ unsigned long spl_mmc_get_uboot_raw_sector(struct mmc *mmc,
 	return sector;
 }
 
-#ifdef CONFIG_MACH_SUNIV
-/*
- * The suniv BROM does not pass the boot media type to SPL, so we try with the
- * boot sequence in BROM: mmc0->spinor->fail.
- * TODO: This has the slight chance of being wrong (invalid SPL signature,
- * but valid U-Boot legacy image on the SD card), but this should be rare.
- * It looks like we can deduce from some BROM state upon entering the SPL
- * (registers, SP, or stack itself) where the BROM was coming from and use
- * that here.
- */
-void board_boot_order(u32 *spl_boot_list)
-{
-	/*
-	 * See the comments above in sunxi_get_boot_device() for information
-	 * about FEL boot.
-	 */
-	if (!is_boot0_magic(SPL_ADDR + 4)) {
-		spl_boot_list[0] = BOOT_DEVICE_BOARD;
-		return;
-	}
-
-	spl_boot_list[0] = BOOT_DEVICE_MMC1;
-	spl_boot_list[1] = BOOT_DEVICE_SPI;
-}
-#else
 u32 spl_boot_device(void)
 {
 	return sunxi_get_boot_device();
 }
-#endif
 
 __weak void sunxi_sram_init(void)
 {
-- 
2.34.1



More information about the U-Boot mailing list