Refactor spl_ufs.c to support loading U-Boot either from a raw sector offset or from a named/numbered partition, controlled by the Kconfig choice introduced in the previous commit.
The monolithic spl_ufs_load_image() is split into helper functions: ufs_load_image_raw_sector() handles sector-based loading, and ufs_load_image_raw_partition() resolves the target sector by looking up a partition name first, falling back to partition number. A new exported spl_ufs_load() function drives the boot-mode switch and can be reused by other callers. A weak spl_ufs_boot_mode() hook allows board code to override the default raw boot mode. Signed-off-by: Balaji Selvanathan <[email protected]> --- Changes in v2: - Refactored the codes in common/spl/spl_ufs.c to use helper functions to make the codes readable and clear --- --- common/spl/spl_ufs.c | 153 ++++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 134 insertions(+), 19 deletions(-) diff --git a/common/spl/spl_ufs.c b/common/spl/spl_ufs.c index cef1843f40f..0590b796267 100644 --- a/common/spl/spl_ufs.c +++ b/common/spl/spl_ufs.c @@ -3,15 +3,19 @@ * (C) Copyright 2025 Alexey Charkov <[email protected]> */ +#include <dm.h> +#include <log.h> #include <spl.h> #include <spl_load.h> #include <scsi.h> -#include <errno.h> -#include <image.h> +#include <part.h> +#include <blk.h> #include <linux/compiler.h> -#include <log.h> +#include <errno.h> -static ulong spl_ufs_load_read(struct spl_load_info *load, ulong off, ulong size, void *buf) +/* Block read callback for spl_load framework */ +static ulong h_spl_load_read(struct spl_load_info *load, ulong off, + ulong size, void *buf) { struct blk_desc *bd = load->priv; lbaint_t sector = off >> bd->log2blksz; @@ -20,30 +24,141 @@ static ulong spl_ufs_load_read(struct spl_load_info *load, ulong off, ulong size return blk_dread(bd, sector, count, buf) << bd->log2blksz; } -static int spl_ufs_load_image(struct spl_image_info *spl_image, - struct spl_boot_device *bootdev) +/* Load image from raw sector */ +static int ufs_load_image_raw_sector(struct spl_image_info *spl_image, + struct spl_boot_device *bootdev, + struct blk_desc *bd, + unsigned long sector) { - unsigned long sector = CONFIG_SPL_UFS_RAW_U_BOOT_SECTOR; - int devnum = CONFIG_SPL_UFS_RAW_U_BOOT_DEVNUM; struct spl_load_info load; + int ret; + + debug("spl: ufs: loading from sector 0x%lx\n", sector); + + spl_load_init(&load, h_spl_load_read, bd, bd->blksz); + ret = spl_load(spl_image, bootdev, &load, 0, sector << bd->log2blksz); + + if (ret) { + printf("%s: ufs block read error\n", __func__); + log_debug("(error=%d)\n", ret); + return ret; + } + + return 0; +} + +/* Find and load from partition */ +static int ufs_load_image_raw_partition(struct spl_image_info *spl_image, + struct spl_boot_device *bootdev, + struct blk_desc *bd) +{ + struct disk_partition part_info; + int ret; + + /* Try partition name first if configured */ +#ifdef CONFIG_SPL_UFS_RAW_U_BOOT_PARTITION_NAME + if (strlen(CONFIG_SPL_UFS_RAW_U_BOOT_PARTITION_NAME) > 0) { + debug("spl: ufs: trying partition name '%s'\n", + CONFIG_SPL_UFS_RAW_U_BOOT_PARTITION_NAME); + + ret = part_get_info_by_name(bd, + CONFIG_SPL_UFS_RAW_U_BOOT_PARTITION_NAME, + &part_info); + if (ret >= 0) { + debug("spl: ufs: found partition '%s' at 0x%lx\n", + CONFIG_SPL_UFS_RAW_U_BOOT_PARTITION_NAME, + (ulong)part_info.start); + return ufs_load_image_raw_sector(spl_image, bootdev, bd, + part_info.start); + } + debug("spl: ufs: partition name not found: %d\n", ret); + } +#endif + + /* Try partition number if configured */ + if (IS_ENABLED(CONFIG_SPL_UFS_RAW_U_BOOT_PARTITION_NUM)) { + debug("spl: ufs: trying partition number %d\n", + CONFIG_SPL_UFS_RAW_U_BOOT_PARTITION_NUM); + + ret = part_get_info(bd, CONFIG_SPL_UFS_RAW_U_BOOT_PARTITION_NUM, + &part_info); + if (ret >= 0) { + debug("spl: ufs: found partition %d at 0x%lx\n", + CONFIG_SPL_UFS_RAW_U_BOOT_PARTITION_NUM, + (ulong)part_info.start); + return ufs_load_image_raw_sector(spl_image, bootdev, bd, + part_info.start); + } + debug("spl: ufs: partition number not found: %d\n", ret); + } + + puts("spl: ufs: partition error\n"); + return -ENOENT; +} + +u32 __weak spl_ufs_boot_mode(const u32 boot_device) +{ + return UFS_MODE_RAW; +} + +int spl_ufs_load(struct spl_image_info *spl_image, + struct spl_boot_device *bootdev, + const char *filename) +{ + u32 boot_mode; + int ret = 0; + int devnum = CONFIG_SPL_UFS_RAW_U_BOOT_DEVNUM; struct blk_desc *bd; - int err; - /* try to recognize storage devices immediately */ - scsi_scan(false); + log_debug("spl: ufs: devnum=%d\n", devnum); + + ret = scsi_scan(false); + if (ret) { + printf("spl: ufs: scsi scan failed: %d\n", ret); + return ret; + } + bd = blk_get_devnum_by_uclass_id(UCLASS_SCSI, devnum); - if (!bd) + if (!bd) { + printf("spl: ufs: could not get device %d\n", devnum); return -ENODEV; + } + + boot_mode = spl_ufs_boot_mode(bootdev->boot_device); + ret = -EINVAL; - spl_load_init(&load, spl_ufs_load_read, bd, bd->blksz); - err = spl_load(spl_image, bootdev, &load, 0, sector << bd->log2blksz); - if (err) { - puts("spl_ufs_load_image: ufs block read error\n"); - log_debug("(error=%d)\n", err); - return err; + switch (boot_mode) { + case UFS_MODE_RAW: + debug("spl: ufs: boot mode: raw\n"); + +#ifdef CONFIG_SPL_UFS_RAW_U_BOOT_USE_SECTOR + ret = ufs_load_image_raw_sector(spl_image, bootdev, bd, + CONFIG_SPL_UFS_RAW_U_BOOT_SECTOR); + if (!ret) + return 0; +#elif defined(CONFIG_SPL_UFS_RAW_U_BOOT_USE_PARTITION) + ret = ufs_load_image_raw_partition(spl_image, bootdev, bd); + if (!ret) + return 0; +#endif + break; + default: + puts("spl: ufs: wrong boot mode\n"); } - return 0; + return ret; +} + +/* SPL load image entry point */ +static int spl_ufs_load_image(struct spl_image_info *spl_image, + struct spl_boot_device *bootdev) +{ + return spl_ufs_load(spl_image, bootdev, +#ifdef CONFIG_SPL_FS_LOAD_PAYLOAD_NAME + CONFIG_SPL_FS_LOAD_PAYLOAD_NAME); +#else + NULL); +#endif } SPL_LOAD_IMAGE_METHOD("UFS", 0, BOOT_DEVICE_UFS, spl_ufs_load_image); -- 2.34.1

