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

Reply via email to