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]>
