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 <an...@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