[PATCH v2 03/14] spl: ufs: add partition-based U-Boot loading support

Balaji Selvanathan balaji.selvanathan at oss.qualcomm.com
Mon Jun 15 10:58:16 CEST 2026


Hi Varada,

On 6/11/2026 4:56 PM, Varadarajan Narayanan wrote:
> On Sat, Jun 06, 2026 at 03:48:34PM +0530, Balaji Selvanathan wrote:
>> 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 <balaji.selvanathan at oss.qualcomm.com>
>> ---
>> 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 <alchark at gmail.com>
>>    */
>>   
>> +#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)
> Not sure why the 'spl_ufs' prefix has changed. I assume these are SPL specific
> since this is in spl_ufs.c.
Changed to spl_ufs_load_read in v3: 
https://lore.kernel.org/u-boot/20260615-spl_ufs-v3-0-360bceb29596@oss.qualcomm.com/ 

>
>>   {
>>   	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);
>> +	}
> The debug() is not considered, both the above if blocks are same except for
> part_get_info_by_name & part_get_info.
>
> 	if (strlen(CONFIG_SPL_UFS_RAW_U_BOOT_PARTITION_NAME) > 0)
> 		ret = part_get_info_by_name(bd, ...);
>
> 	if (IS_ENABLED(CONFIG_SPL_UFS_RAW_U_BOOT_PARTITION_NUM))
> 		ret = part_get_info(bd, ...);
>
> 	if (ret >= 0)
> 		return ufs_load_image_raw_sector(...);

Implemented above in v3: 
https://lore.kernel.org/u-boot/20260615-spl_ufs-v3-0-360bceb29596@oss.qualcomm.com/

Thanks,

Balaji

>
> -Varada
>
>> +
>> +	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
>>


More information about the U-Boot mailing list