From a08b04b5c75a7e9122dfc733c66b978aa0afe4ba Mon Sep 17 00:00:00 2001 From: Jesse Taube Date: Fri, 11 Feb 2022 19:32:33 -0500 Subject: [PATCH] mach-sunxi: Add boot device detection for SUNIV/F1C100s 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. The only caveat is that this only works in the SPL, as the SPL header gets overwritten with the exception vectors, once U-Boot proper takes over. Always return MMC0 as the boot source, when called from U-Boot proper, as a placeholder for now, until we find another way. Signed-off-by: Jesse Taube Suggested-by: Samuel Holland Reviewed-by: Andre Przywara Signed-off-by: Andre Przywara --- arch/arm/include/asm/arch-sunxi/spl.h | 9 ++++ arch/arm/mach-sunxi/board.c | 64 ++++++++++++++++----------- 2 files changed, 46 insertions(+), 27 deletions(-) diff --git a/arch/arm/include/asm/arch-sunxi/spl.h b/arch/arm/include/asm/arch-sunxi/spl.h index 58cdf806d9..b543d24e5a 100644 --- a/arch/arm/include/asm/arch-sunxi/spl.h +++ b/arch/arm/include/asm/arch-sunxi/spl.h @@ -19,6 +19,15 @@ #define SUNXI_BOOTED_FROM_MMC0_HIGH 0x10 #define SUNXI_BOOTED_FROM_MMC2_HIGH 0x12 +/* + * Values taken from the F1C200s BootROM stack + * 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..0071de19ff 100644 --- a/arch/arm/mach-sunxi/board.c +++ b/arch/arm/mach-sunxi/board.c @@ -191,12 +191,48 @@ SPL_LOAD_IMAGE_METHOD("FEL", 0, BOOT_DEVICE_BOARD, spl_board_load_image); #define SUNXI_INVALID_BOOT_SOURCE -1 +static int suniv_get_boot_source(void) +{ + /* Get the last function call from BootROM's stack. */ + u32 brom_call = *(u32 *)(uintptr_t)(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 not supported yet. */ + 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 int sunxi_get_boot_source(void) { + /* + * On the ARMv5 SoCs, the SPL header in SRAM is overwritten by the + * exception vectors in U-Boot proper, so we won't find any + * information there. Also the FEL stash is only valid in the SPL, + * so we can't use that either. So if this is called from U-Boot + * proper, just return MMC0 as a placeholder, for now. + */ + if (IS_ENABLED(CONFIG_MACH_SUNIV) && + !IS_ENABLED(CONFIG_SPL_BUILD)) + return SUNXI_BOOTED_FROM_MMC0; + 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 @@ -276,36 +312,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.39.5