Boards using boot metadata should not have to configure an unused fixed
partition number. Make board-selected partitions an alternative to fixed
numbers and partition types in the existing raw-location choice.

Keep the selection policies together so the MMC loader only has to select
a partition and load it. Selection failures in dynamic mode must stop the
MMC attempt instead of falling back to an unrelated filesystem partition.
Existing fixed-number and partition-type fallback behavior is preserved.

Distinguish shared partition-loading support from settings specific to
partition-number modes. This keeps existing platform defaults and guards
while allowing dynamic selection to use the same partition loader. The
STM32 fixed override remains conditional on its static partition setting.

Signed-off-by: Carlo Caione <[email protected]>
---
 arch/arm/mach-k3/r5/Kconfig          |  4 +-
 arch/arm/mach-stm32mp/stm32mp1/spl.c |  2 +-
 common/spl/Kconfig                   | 13 +++++++
 common/spl/spl_mmc.c                 | 73 +++++++++++++++++++++++++-----------
 include/part.h                       |  3 +-
 include/spl.h                        | 16 +++++---
 6 files changed, 80 insertions(+), 31 deletions(-)

diff --git a/arch/arm/mach-k3/r5/Kconfig b/arch/arm/mach-k3/r5/Kconfig
index 12335880e10..672c8a226df 100644
--- a/arch/arm/mach-k3/r5/Kconfig
+++ b/arch/arm/mach-k3/r5/Kconfig
@@ -35,7 +35,9 @@ config K3_SYSFW_IMAGE_MMCSD_RAW_MODE_SECT
 
 config K3_SYSFW_IMAGE_MMCSD_RAW_MODE_PART
        hex "MMC partition to load SYSFW firmware and configuration blob from"
-       depends on K3_LOAD_SYSFW && SYS_MMCSD_RAW_MODE_U_BOOT_USE_PARTITION
+       depends on K3_LOAD_SYSFW
+       depends on SYS_MMCSD_RAW_MODE_U_BOOT_USE_PARTITION || \
+                  SYS_MMCSD_RAW_MODE_U_BOOT_USE_PARTITION_DYNAMIC
        default 2
        help
          Partition on the MMC to the combined System Firmware and configuration
diff --git a/arch/arm/mach-stm32mp/stm32mp1/spl.c 
b/arch/arm/mach-stm32mp/stm32mp1/spl.c
index 2229ebf5eeb..c1be468cb1d 100644
--- a/arch/arm/mach-stm32mp/stm32mp1/spl.c
+++ b/arch/arm/mach-stm32mp/stm32mp1/spl.c
@@ -61,7 +61,7 @@ u32 spl_mmc_boot_mode(struct mmc *mmc, const u32 boot_device)
        return MMCSD_MODE_RAW;
 }
 
-#ifdef CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_USE_PARTITION
+#ifdef CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_PARTITION
 int spl_mmc_boot_partition(struct mmc *mmc, const u32 boot_device)
 {
        switch (boot_device) {
diff --git a/common/spl/Kconfig b/common/spl/Kconfig
index 0618f42c941..56375ef287d 100644
--- a/common/spl/Kconfig
+++ b/common/spl/Kconfig
@@ -574,8 +574,21 @@ 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
+       select SPL_PARTITIONS
+       help
+         Select the partition at runtime instead of using a fixed number.
+         The board must implement spl_mmc_boot_partition().
+
 endchoice
 
+config SYS_MMCSD_RAW_MODE_U_BOOT_USE_ANY_PARTITION
+       def_bool SYS_MMCSD_RAW_MODE_U_BOOT_USE_PARTITION || \
+                SYS_MMCSD_RAW_MODE_U_BOOT_USE_PARTITION_TYPE || \
+                SYS_MMCSD_RAW_MODE_U_BOOT_USE_PARTITION_DYNAMIC
+
 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
diff --git a/common/spl/spl_mmc.c b/common/spl/spl_mmc.c
index 3e637f5adbd..8f4df4104ca 100644
--- a/common/spl/spl_mmc.c
+++ b/common/spl/spl_mmc.c
@@ -106,18 +106,14 @@ static int spl_mmc_find_device(struct mmc **mmcp, int 
mmc_dev)
        return 0;
 }
 
-#if defined(CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_USE_PARTITION) || \
-    defined(CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_USE_PARTITION_TYPE)
-static int mmc_load_image_raw_partition(struct spl_image_info *spl_image,
-                                       struct spl_boot_device *bootdev,
-                                       struct mmc *mmc, int partition,
-                                       unsigned long sector)
+#ifdef CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_USE_ANY_PARTITION
+static int spl_mmc_select_partition(struct mmc *mmc, const u32 boot_device,
+                                   int *partition)
 {
+#ifdef CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_USE_PARTITION_TYPE
        struct disk_partition info;
-       int ret;
+       int type_part, ret;
 
-#ifdef CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_USE_PARTITION_TYPE
-       int type_part;
        /* Only support MBR so DOS_ENTRY_NUMBERS */
        for (type_part = 1; type_part <= DOS_ENTRY_NUMBERS; type_part++) {
                ret = part_get_info(mmc_get_blk_desc(mmc), type_part, &info);
@@ -125,11 +121,40 @@ static int mmc_load_image_raw_partition(struct 
spl_image_info *spl_image,
                        continue;
                if (info.sys_ind ==
                        CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_PARTITION_TYPE) {
-                       partition = type_part;
+                       *partition = type_part;
                        break;
                }
        }
+
+       return 0;
+#elif defined(CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_USE_PARTITION_DYNAMIC)
+       int ret;
+
+       if (*partition != -1)
+               return 0;
+
+       *partition = spl_mmc_boot_partition(mmc, boot_device);
+       if (*partition > 0)
+               return 0;
+
+       ret = *partition < 0 ? *partition : -EINVAL;
+       printf("spl: partition selection failed: %d\n", ret);
+       return ret;
+#else
+       if (*partition == -1)
+               *partition = spl_mmc_boot_partition(mmc, boot_device);
+
+       return 0;
 #endif
+}
+
+static int mmc_load_image_raw_partition(struct spl_image_info *spl_image,
+                                       struct spl_boot_device *bootdev,
+                                       struct mmc *mmc, int partition,
+                                       unsigned long sector)
+{
+       struct disk_partition info;
+       int ret;
 
        ret = part_get_info(mmc_get_blk_desc(mmc), partition, &info);
        if (ret) {
@@ -300,10 +325,15 @@ u32 __weak spl_mmc_boot_mode(struct mmc *mmc, const u32 
boot_device)
        return MMCSD_MODE_RAW;
 }
 
-#ifdef CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_USE_PARTITION
+#if defined(CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_USE_PARTITION) || \
+       defined(CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_USE_PARTITION_DYNAMIC)
 int __weak spl_mmc_boot_partition(struct mmc *mmc, const u32 boot_device)
 {
+#ifdef CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_PARTITION
        return CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_PARTITION;
+#else
+       return -ENOSYS;
+#endif
 }
 #endif
 
@@ -429,11 +459,10 @@ int spl_mmc_load(struct spl_image_info *spl_image,
                                                spl_mmc_raw_uboot_offset(part));
                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)
-               if (IS_ENABLED(CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_USE_PARTITION) 
&&
-                   raw_part == -1)
-                       raw_part = spl_mmc_boot_partition(mmc, 
bootdev->boot_device);
+#elif defined(CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_USE_ANY_PARTITION)
+               ret = spl_mmc_select_partition(mmc, bootdev->boot_device, 
&raw_part);
+               if (ret)
+                       return ret;
                ret = mmc_load_image_raw_partition(spl_image, bootdev,
                                                   mmc, raw_part,
                                                   raw_sect);
@@ -462,17 +491,19 @@ int spl_mmc_load(struct spl_image_info *spl_image,
 int spl_mmc_load_image(struct spl_image_info *spl_image,
                       struct spl_boot_device *bootdev)
 {
+       int raw_part = 0;
+
+       if (IS_ENABLED(CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_USE_PARTITION) ||
+           IS_ENABLED(CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_USE_PARTITION_DYNAMIC))
+               raw_part = -1;
+
        return spl_mmc_load(spl_image, bootdev,
 #ifdef CONFIG_SPL_FS_LOAD_PAYLOAD_NAME
                            CONFIG_SPL_FS_LOAD_PAYLOAD_NAME,
 #else
                            NULL,
 #endif
-#ifdef CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_PARTITION
-                           -1,
-#else
-                           0,
-#endif
+                           raw_part,
 #ifdef CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR
                            CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR);
 #else
diff --git a/include/part.h b/include/part.h
index 15daacd7faa..5268216b46d 100644
--- a/include/part.h
+++ b/include/part.h
@@ -462,8 +462,7 @@ ulong disk_blk_erase(struct udevice *dev, lbaint_t start, 
lbaint_t blkcnt);
 # define part_print_ptr(x)     NULL
 # 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_ANY_PARTITION)
 #  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 08a84536f51..d05623caaf6 100644
--- a/include/spl.h
+++ b/include/spl.h
@@ -599,13 +599,17 @@ u32 spl_mmc_boot_mode(struct mmc *mmc, const u32 
boot_device);
  * @boot_device:       ID of the device which the MMC driver wants to load
  *                     U-Boot from.
  *
- * Called before loading U-Boot in raw partition mode, after any Falcon
- * attempt. The hook may select the hardware area containing the image;
- * it must leave that area selected. It may run for each MMC load attempt.
+ * Called in fixed-number or dynamic mode after any Falcon attempt. The
+ * incoming hardware area is not necessarily the user area. The hook must
+ * leave the image area selected for loading and any configured filesystem
+ * fallback; the loader does not restore it. It may run for each MMC attempt.
  *
- * If not overridden, it is weakly defined in common/spl/spl_mmc.c.
+ * The default returns the configured partition, or -ENOSYS with
+ * CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_USE_PARTITION_DYNAMIC. In dynamic mode,
+ * zero or a negative error aborts this MMC attempt without filesystem
+ * fallback; SPL may still try other boot devices.
  *
- * Return: Partition number to load U-Boot from.
+ * Return: Partition number (positive in dynamic mode), or a negative error.
  */
 int spl_mmc_boot_partition(struct mmc *mmc, const u32 boot_device);
 
@@ -975,7 +979,7 @@ int spl_mmc_load_image(struct spl_image_info *spl_image,
  * @param bootdev      Describes which device to load from
  * @param filename     Name of file to load (in FS mode)
  * @param raw_part     Partition to load from (in RAW mode), or -1 to call
- *                     spl_mmc_boot_partition() in partition-number mode
+ *                     spl_mmc_boot_partition() in fixed-number or dynamic mode
  * @param raw_sect     Sector to load from (in RAW mode)
  *
  * Return: 0 on success, otherwise error code

-- 
2.55.0

Reply via email to