[PATCH 1/2] spl: Add A/B sector mode for mmc raw mode
Andri Yngvason
andri at yngvason.is
Thu Jul 31 20:15:32 CEST 2025
This makes it possible to select between 2 raw sectors from which
to boot U-Boot Proper by writing to one pre-defined sector.
If the first byte of the sector contains the value 1, SPL will load
U-Boot Proper. The second byte, if set to 1 or 2, instructs SPL to try
loading only once from A or B, respectively.
Signed-off-by: Andri Yngvason <andri at yngvason.is>
---
common/spl/Kconfig | 28 +++++++++++++++++--
common/spl/spl_mmc.c | 66 ++++++++++++++++++++++++++++++++++++++++++--
include/spl.h | 1 +
3 files changed, 90 insertions(+), 5 deletions(-)
diff --git a/common/spl/Kconfig b/common/spl/Kconfig
index ab05536bd02..706f7db1225 100644
--- a/common/spl/Kconfig
+++ b/common/spl/Kconfig
@@ -565,6 +565,14 @@ config SYS_MMCSD_RAW_MODE_U_BOOT_USE_SECTOR
Use sector number for specifying U-Boot location on MMC/SD in
raw mode.
+config SYS_MMCSD_RAW_MODE_U_BOOT_USE_SECTOR_AB
+ bool "MMC raw mode: by sector with A/B selection"
+ select SPL_LOAD_BLOCK
+ select SPL_MMC_WRITE
+ help
+ Use sector numbers for specifying U-Boot location on MMC/SD in
+ raw mode. Allows selecting between two sectors.
+
config SYS_MMCSD_RAW_MODE_U_BOOT_USE_PARTITION
bool "MMC raw mode: by partition"
select SPL_LOAD_BLOCK
@@ -583,7 +591,8 @@ endchoice
config SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR
hex "Address on the MMC to load U-Boot from"
- depends on SYS_MMCSD_RAW_MODE_U_BOOT_USE_SECTOR
+ depends on SYS_MMCSD_RAW_MODE_U_BOOT_USE_SECTOR || \
+ SYS_MMCSD_RAW_MODE_U_BOOT_USE_SECTOR_AB
default 0x40 if ARCH_SUNXI
default 0x75 if ARCH_DAVINCI
default 0x8a if ARCH_MX6 || ARCH_MX7
@@ -598,9 +607,24 @@ config SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR
Address on the MMC to load U-Boot from, when the MMC is being used
in raw mode. Units: MMC sectors (1 sector = 512 bytes).
+config SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR_B
+ hex "Secondary address on the MMC to load U-Boot from"
+ depends on SYS_MMCSD_RAW_MODE_U_BOOT_USE_SECTOR_AB
+ help
+ Address on the MMC to load secondary U-Boot from, when the MMC is
+ being used in raw mode. Units: MMC sectors (1 sector = 512 bytes).
+
+config SYS_MMCSD_RAW_MODE_U_BOOT_AB_CONTROL_SECTOR
+ hex "Raw MMC A/B boot control sector"
+ depends on SYS_MMCSD_RAW_MODE_U_BOOT_USE_SECTOR_AB
+ help
+ Location of A/B bool control sector on the MMC. The contents of this
+ sector control from which sector U-Boot is loaded.
+
config SYS_MMCSD_RAW_MODE_U_BOOT_DATA_PART_OFFSET
hex "U-Boot main hardware partition image offset"
- depends on SYS_MMCSD_RAW_MODE_U_BOOT_USE_SECTOR
+ depends on SYS_MMCSD_RAW_MODE_U_BOOT_USE_SECTOR || \
+ SYS_MMCSD_RAW_MODE_U_BOOT_USE_SECTOR_AB
default 0x10 if ARCH_SUNXI
default 0x0
help
diff --git a/common/spl/spl_mmc.c b/common/spl/spl_mmc.c
index d06f9f0dee6..f4a1a3425b5 100644
--- a/common/spl/spl_mmc.c
+++ b/common/spl/spl_mmc.c
@@ -29,7 +29,8 @@ static ulong h_spl_load_read(struct spl_load_info *load, ulong off,
static __maybe_unused unsigned long spl_mmc_raw_uboot_offset(int part)
{
-#if IS_ENABLED(CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_USE_SECTOR)
+#if IS_ENABLED(CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_USE_SECTOR) || \
+ IS_ENABLED(CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_USE_SECTOR_AB)
if (part == 0)
return CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_DATA_PART_OFFSET;
#endif
@@ -137,7 +138,8 @@ static int mmc_load_image_raw_partition(struct spl_image_info *spl_image,
return ret;
}
-#ifdef CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_USE_SECTOR
+#if defined(CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_USE_SECTOR) || \
+ defined(CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_USE_SECTOR_AB)
return mmc_load_image_raw_sector(spl_image, bootdev, mmc, info.start + sector);
#else
return mmc_load_image_raw_sector(spl_image, bootdev, mmc, info.start);
@@ -270,6 +272,8 @@ u32 __weak spl_mmc_boot_mode(struct mmc *mmc, const u32 boot_device)
return MMCSD_MODE_FS;
#elif defined(CONFIG_SUPPORT_EMMC_BOOT)
return MMCSD_MODE_EMMCBOOT;
+#elif defined(CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_USE_SECTOR_AB)
+ return MMCSD_MODE_RAW_AB;
#else
return MMCSD_MODE_RAW;
#endif
@@ -323,6 +327,53 @@ int __weak spl_mmc_emmc_boot_partition(struct mmc *mmc)
return default_spl_mmc_emmc_boot_partition(mmc);
}
+#ifdef CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_USE_SECTOR_AB
+unsigned long spl_mmc_get_raw_ab_sector(struct mmc *mmc, unsigned long raw_sect)
+{
+ u8 buf[512];
+ int ret = blk_dread(mmc_get_blk_desc(mmc),
+ CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_AB_CONTROL_SECTOR,
+ 1, buf);
+ if (ret < 0) {
+ puts("Failed to read mmc a/b control sector\n");
+ log_debug("(error=%d)\n", ret);
+ goto out;
+ }
+
+ switch (buf[1]) {
+ case 1:
+ raw_sect = CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR;
+ puts("Trying to boot from mmc raw sector A\n");
+ break;
+ case 2:
+ raw_sect = CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR_B;
+ puts("Trying to boot from mmc raw sector B\n");
+ break;
+ default:
+ if (buf[0] != 1) {
+ raw_sect = CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR;
+ puts("Selected mmc raw sector A\n");
+ } else {
+ raw_sect = CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR_B;
+ puts("Selected mmc raw sector B\n");
+ }
+ return raw_sect;
+ }
+
+ buf[1] = 0xff;
+ ret = blk_dwrite(mmc_get_blk_desc(mmc),
+ CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_AB_CONTROL_SECTOR,
+ 1, buf);
+ if (ret < 0) {
+ puts("Failed to update mmc a/b control sector\n");
+ log_debug("(error=%d)\n", ret);
+ }
+
+out:
+ return raw_sect;
+}
+#endif
+
static int spl_mmc_get_mmc_devnum(struct mmc *mmc)
{
struct blk_desc *block_dev;
@@ -385,6 +436,14 @@ int spl_mmc_load(struct spl_image_info *spl_image,
return ret;
}
/* Fall through */
+#ifdef CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_USE_SECTOR_AB
+ case MMCSD_MODE_RAW_AB:
+ debug("spl: mmc boot mode: raw a/b\n");
+
+ raw_sect = spl_mmc_get_raw_ab_sector(mmc, raw_sect);
+
+ fallthrough;
+#endif
case MMCSD_MODE_RAW:
debug("spl: mmc boot mode: raw\n");
@@ -403,7 +462,8 @@ int spl_mmc_load(struct spl_image_info *spl_image,
if (!ret)
return 0;
#endif
-#ifdef CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_USE_SECTOR
+#if defined(CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_USE_SECTOR) || \
+ defined(CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_USE_SECTOR_AB)
ret = mmc_load_image_raw_sector(spl_image, bootdev, mmc,
raw_sect +
spl_mmc_raw_uboot_offset(part));
diff --git a/include/spl.h b/include/spl.h
index 7c10c7f792e..7736b00c474 100644
--- a/include/spl.h
+++ b/include/spl.h
@@ -28,6 +28,7 @@ struct legacy_img_hdr;
#define MMCSD_MODE_RAW 1
#define MMCSD_MODE_FS 2
#define MMCSD_MODE_EMMCBOOT 3
+#define MMCSD_MODE_RAW_AB 4
struct blk_desc;
struct legacy_img_hdr;
--
2.50.0
More information about the U-Boot
mailing list