Boards may need to select the boot partition using on-device metadata,
such as A/B slot state. The existing partition hook runs before MMC
initialization, so it cannot read that metadata.

A separate dynamic-partition mode makes this policy explicit while
preserving fixed-partition selection and explicit requests to load other
firmware.

Signed-off-by: Carlo Caione <[email protected]>
---
 common/spl/Kconfig   |  9 +++++++
 common/spl/spl_mmc.c | 67 +++++++++++++++++++++++++++++++++++++---------------
 include/part.h       |  3 ++-
 include/spl.h        | 21 ++++++++++++++++
 4 files changed, 80 insertions(+), 20 deletions(-)

diff --git a/common/spl/Kconfig b/common/spl/Kconfig
index 0618f42c941..f5904af3ed2 100644
--- a/common/spl/Kconfig
+++ b/common/spl/Kconfig
@@ -574,6 +574,15 @@ config SYS_MMCSD_RAW_MODE_U_BOOT_USE_PARTITION_TYPE
          raw mode. U-Boot will be loaded from the first partition of this
          type to be found.
 
+config SYS_MMCSD_RAW_MODE_U_BOOT_USE_PARTITION_DYNAMIC
+       bool "MMC raw mode: by board-selected partition"
+       select SPL_LOAD_BLOCK
+       depends on SPL_PARTITIONS
+       help
+         Use a partition selected by the board at runtime for loading
+         U-Boot when using MMC/SD in raw mode.
+         Override spl_mmc_get_uboot_raw_partition() to select the partition.
+
 endchoice
 
 config SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR
diff --git a/common/spl/spl_mmc.c b/common/spl/spl_mmc.c
index cc16709dc9b..bd5b6371611 100644
--- a/common/spl/spl_mmc.c
+++ b/common/spl/spl_mmc.c
@@ -107,7 +107,8 @@ static int spl_mmc_find_device(struct mmc **mmcp, int 
mmc_dev)
 }
 
 #if defined(CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_USE_PARTITION) || \
-    defined(CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_USE_PARTITION_TYPE)
+       defined(CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_USE_PARTITION_TYPE) || \
+       defined(CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_USE_PARTITION_DYNAMIC)
 static int mmc_load_image_raw_partition(struct spl_image_info *spl_image,
                                        struct spl_boot_device *bootdev,
                                        struct mmc *mmc, int partition,
@@ -307,6 +308,11 @@ int __weak spl_mmc_boot_partition(const u32 boot_device)
 }
 #endif
 
+int __weak spl_mmc_get_uboot_raw_partition(struct mmc *mmc)
+{
+       return -ENOSYS;
+}
+
 unsigned long __weak arch_spl_mmc_get_uboot_raw_sector(struct mmc *mmc,
                                                       unsigned long raw_sect)
 {
@@ -366,11 +372,10 @@ void spl_mmc_clear_cache(void)
        mmc = NULL;
 }
 
-int spl_mmc_load(struct spl_image_info *spl_image,
-                struct spl_boot_device *bootdev,
-                const char *filename,
-                int raw_part,
-                unsigned long raw_sect)
+static int __spl_mmc_load(struct spl_image_info *spl_image,
+                         struct spl_boot_device *bootdev,
+                         const char *filename, int raw_part,
+                         unsigned long raw_sect, bool select_partition)
 {
        u32 boot_mode;
        int ret = 0;
@@ -430,12 +435,23 @@ int spl_mmc_load(struct spl_image_info *spl_image,
                if (!ret)
                        return 0;
 #elif defined(CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_USE_PARTITION) || \
-      defined(CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_USE_PARTITION_TYPE)
-               ret = mmc_load_image_raw_partition(spl_image, bootdev,
-                                                  mmc, raw_part,
-                                                  raw_sect);
-               if (!ret)
-                       return 0;
+       defined(CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_USE_PARTITION_TYPE) || \
+       defined(CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_USE_PARTITION_DYNAMIC)
+               ret = 0;
+               if 
(IS_ENABLED(CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_USE_PARTITION_DYNAMIC) &&
+                   select_partition) {
+                       raw_part = spl_mmc_get_uboot_raw_partition(mmc);
+                       if (raw_part <= 0)
+                               ret = raw_part ? raw_part : -EINVAL;
+               }
+
+               if (!ret) {
+                       ret = mmc_load_image_raw_partition(spl_image, bootdev,
+                                                          mmc, raw_part,
+                                                          raw_sect);
+                       if (!ret)
+                               return 0;
+               }
 #endif
                /* If RAW mode fails, try FS mode. */
                fallthrough;
@@ -456,25 +472,38 @@ int spl_mmc_load(struct spl_image_info *spl_image,
        return ret;
 }
 
+int spl_mmc_load(struct spl_image_info *spl_image,
+                struct spl_boot_device *bootdev,
+                const char *filename, int raw_part,
+                unsigned long raw_sect)
+{
+       return __spl_mmc_load(spl_image, bootdev, filename, raw_part,
+                             raw_sect, false);
+}
+
 int spl_mmc_load_image(struct spl_image_info *spl_image,
                       struct spl_boot_device *bootdev)
 {
-       return spl_mmc_load(spl_image, bootdev,
+       bool select_partition =
+               
IS_ENABLED(CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_USE_PARTITION_DYNAMIC);
+
+       return __spl_mmc_load(spl_image, bootdev,
 #ifdef CONFIG_SPL_FS_LOAD_PAYLOAD_NAME
-                           CONFIG_SPL_FS_LOAD_PAYLOAD_NAME,
+                             CONFIG_SPL_FS_LOAD_PAYLOAD_NAME,
 #else
-                           NULL,
+                             NULL,
 #endif
 #ifdef CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_PARTITION
-                           spl_mmc_boot_partition(bootdev->boot_device),
+                             spl_mmc_boot_partition(bootdev->boot_device),
 #else
-                           0,
+                             0,
 #endif
 #ifdef CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR
-                           CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR);
+                             CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR,
 #else
-                           0);
+                             0,
 #endif
+                             select_partition);
 }
 
 SPL_LOAD_IMAGE_METHOD("MMC1", 0, BOOT_DEVICE_MMC1, spl_mmc_load_image);
diff --git a/include/part.h b/include/part.h
index 15daacd7faa..8282f31e2a3 100644
--- a/include/part.h
+++ b/include/part.h
@@ -463,7 +463,8 @@ ulong disk_blk_erase(struct udevice *dev, lbaint_t start, 
lbaint_t blkcnt);
 # if defined(CONFIG_SPL_FS_EXT4) || defined(CONFIG_SPL_FS_FAT) || \
        defined(CONFIG_SPL_FS_SQUASHFS) || \
        defined(CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_USE_PARTITION) || \
-       defined(CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_USE_PARTITION_TYPE)
+       defined(CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_USE_PARTITION_TYPE) || \
+       defined(CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_USE_PARTITION_DYNAMIC)
 #  define part_get_info_ptr(x) x
 # else
 #  define part_get_info_ptr(x) NULL
diff --git a/include/spl.h b/include/spl.h
index 5078d7525ab..1839dd2e343 100644
--- a/include/spl.h
+++ b/include/spl.h
@@ -607,6 +607,23 @@ u32 spl_mmc_boot_mode(struct mmc *mmc, const u32 
boot_device);
 int spl_mmc_boot_partition(const u32 boot_device);
 
 struct mmc;
+
+/**
+ * spl_mmc_get_uboot_raw_partition() - Select the raw U-Boot partition
+ * @mmc: Initialized MMC device
+ *
+ * Used by spl_mmc_load_image() when
+ * CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_USE_PARTITION_DYNAMIC is enabled,
+ * after hardware partition selection. Direct spl_mmc_load() calls bypass it.
+ *
+ * Preserve the hardware partition selection. This hook may run repeatedly
+ * during one boot; guard any once-per-boot metadata updates accordingly.
+ *
+ * Return: Partition number >= 1, or a negative error to skip the raw load
+ * and allow normal boot fallback. The weak default returns -ENOSYS.
+ */
+int spl_mmc_get_uboot_raw_partition(struct mmc *mmc);
+
 /**
  * default_spl_mmc_emmc_boot_partition() - eMMC boot partition to load U-Boot 
from.
  * mmc:                        Pointer for the mmc device structure
@@ -975,6 +992,10 @@ int spl_mmc_load_image(struct spl_image_info *spl_image,
  * @param raw_part     Partition to load from (in RAW mode)
  * @param raw_sect     Sector to load from (in RAW mode)
  *
+ * Explicit partition requests bypass spl_mmc_get_uboot_raw_partition(), even
+ * when board-selected partition mode is enabled. Use spl_mmc_load_image() to
+ * load the next boot phase using that configured selection policy.
+ *
  * Return: 0 on success, otherwise error code
  */
 int spl_mmc_load(struct spl_image_info *spl_image,

---
base-commit: 527115ef6783cec49e5610c523c124b399011361
change-id: 20260909-ccaione-upstream-part-dynamic-4c192e2d4bb6

Best regards,
--  
Carlo Caione <[email protected]>

Reply via email to