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

Balaji Selvanathan balaji.selvanathan at oss.qualcomm.com
Sat Jun 6 12:18:34 CEST 2026


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)
 {
 	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



More information about the U-Boot mailing list