[PATCH 2/2] Forward chosen raw mmc A/B sector to OS
Andri Yngvason
andri at yngvason.is
Thu Jul 31 20:15:33 CEST 2025
This adds a property named u-boot,mmc-boot-sector to the /chosen node in
the device tree. It can be either "a" or "b", based on which sector was
chosen by the SPL to boot U-Boot Proper.
This makes it possible to check from the OS if an upgrade to U-Boot was
successful before committing to it.
The way this is intended to be used is as follows:
- Write new U-Boot image to the sector that's currently unused
- Write 00 XX to control sector, where XX = 1 for A and 2 for B
- Reboot
- If u-boot,mmc-boot-sector contains the correct value, update the
control sector to boot from the new U-Boot.
- If it contains the wrong value, then the update must have failed.
Signed-off-by: Andri Yngvason <andri at yngvason.is>
---
boot/fdt_support.c | 20 ++++++++++++++++++++
common/bloblist.c | 1 +
common/spl/spl_mmc.c | 21 ++++++++++++++++++++-
include/bloblist.h | 1 +
include/spl.h | 9 +++++++++
5 files changed, 51 insertions(+), 1 deletion(-)
diff --git a/boot/fdt_support.c b/boot/fdt_support.c
index b7331bb76b3..309f3726314 100644
--- a/boot/fdt_support.c
+++ b/boot/fdt_support.c
@@ -27,6 +27,8 @@
#include <fdtdec.h>
#include <version.h>
#include <video.h>
+#include <bloblist.h>
+#include <spl.h>
DECLARE_GLOBAL_DATA_PTR;
@@ -342,6 +344,7 @@ int fdt_chosen(void *fdt)
int nodeoffset;
int err;
const char *str; /* used to set string properties */
+ __maybe_unused struct spl_mmcsd_raw_ab_handoff *handoff;
err = fdt_check_header(fdt);
if (err < 0) {
@@ -396,6 +399,23 @@ int fdt_chosen(void *fdt)
return err;
}
+ if (IS_ENABLED(CONFIG_BLOBLIST) &&
+ IS_ENABLED(CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_USE_SECTOR_AB)) {
+ handoff = bloblist_find(BLOBLISTT_MMCSD_RAW_AB,
+ sizeof(struct spl_mmcsd_raw_ab_handoff));
+ if (handoff) {
+ err = fdt_setprop(fdt, nodeoffset, "u-boot,mmc-boot-sector",
+ handoff->sector == SPL_MMCSD_RAW_B_SECTOR ? "b" : "a", 2);
+ if (err < 0) {
+ printf("WARNING: could not set u-boot,mmc-boot-sector %s.\n",
+ fdt_strerror(err));
+ return err;
+ }
+ } else {
+ printf("WARNING: Missing mmc a/b boot sector\n");
+ }
+ }
+
return fdt_fixup_stdout(fdt, nodeoffset);
}
diff --git a/common/bloblist.c b/common/bloblist.c
index 6e4f020d7c4..cafa2036084 100644
--- a/common/bloblist.c
+++ b/common/bloblist.c
@@ -61,6 +61,7 @@ static struct tag_name {
{ BLOBLISTT_U_BOOT_SPL_HANDOFF, "SPL hand-off" },
{ BLOBLISTT_VBE, "VBE" },
{ BLOBLISTT_U_BOOT_VIDEO, "SPL video handoff" },
+ { BLOBLISTT_MMCSD_RAW_AB, "MMC raw A/B boot sector" },
/* BLOBLISTT_VENDOR_AREA */
};
diff --git a/common/spl/spl_mmc.c b/common/spl/spl_mmc.c
index f4a1a3425b5..22cea00bc96 100644
--- a/common/spl/spl_mmc.c
+++ b/common/spl/spl_mmc.c
@@ -16,6 +16,7 @@
#include <mmc.h>
#include <image.h>
#include <imx_container.h>
+#include <bloblist.h>
static ulong h_spl_load_read(struct spl_load_info *load, ulong off,
ulong size, void *buf)
@@ -330,6 +331,7 @@ int __weak spl_mmc_emmc_boot_partition(struct mmc *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)
{
+ __maybe_unused struct spl_mmcsd_raw_ab_handoff *handoff;
u8 buf[512];
int ret = blk_dread(mmc_get_blk_desc(mmc),
CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_AB_CONTROL_SECTOR,
@@ -357,7 +359,7 @@ unsigned long spl_mmc_get_raw_ab_sector(struct mmc *mmc, unsigned long raw_sect)
raw_sect = CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR_B;
puts("Selected mmc raw sector B\n");
}
- return raw_sect;
+ goto out;
}
buf[1] = 0xff;
@@ -370,6 +372,23 @@ unsigned long spl_mmc_get_raw_ab_sector(struct mmc *mmc, unsigned long raw_sect)
}
out:
+ if (IS_ENABLED(CONFIG_BLOBLIST)) {
+ ret = bloblist_ensure_size(BLOBLISTT_MMCSD_RAW_AB,
+ sizeof(struct spl_mmcsd_raw_ab_handoff),
+ 0, (void **)&handoff);
+ if (ret)
+ return raw_sect;
+
+ switch (raw_sect) {
+ case CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR:
+ handoff->sector = SPL_MMCSD_RAW_A_SECTOR;
+ break;
+ case CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR_B:
+ handoff->sector = SPL_MMCSD_RAW_B_SECTOR;
+ break;
+ }
+ }
+
return raw_sect;
}
#endif
diff --git a/include/bloblist.h b/include/bloblist.h
index f32faf78560..bf50b82ef3c 100644
--- a/include/bloblist.h
+++ b/include/bloblist.h
@@ -153,6 +153,7 @@ enum bloblist_tag_t {
BLOBLISTT_U_BOOT_SPL_HANDOFF = 0xfff000, /* Hand-off info from SPL */
BLOBLISTT_VBE = 0xfff001, /* VBE per-phase state */
BLOBLISTT_U_BOOT_VIDEO = 0xfff002, /* Video info from SPL */
+ BLOBLISTT_MMCSD_RAW_AB = 0xfff003, /* MMC A/B Sector from SPL */
};
/**
diff --git a/include/spl.h b/include/spl.h
index 7736b00c474..e1895db736b 100644
--- a/include/spl.h
+++ b/include/spl.h
@@ -804,6 +804,15 @@ struct spl_image_loader {
struct spl_boot_device *bootdev);
};
+enum spl_mmcsd_raw_ab_sector {
+ SPL_MMCSD_RAW_A_SECTOR = 0,
+ SPL_MMCSD_RAW_B_SECTOR,
+};
+
+struct spl_mmcsd_raw_ab_handoff {
+ enum spl_mmcsd_raw_ab_sector sector;
+};
+
/* Helper function for accessing the name */
static inline const char *spl_loader_name(const struct spl_image_loader *loader)
{
--
2.50.0
More information about the U-Boot
mailing list