[PATCH 2/4] spl: ufs: add Falcon mode load path
Alexey Charkov
alchark at flipper.net
Tue Jun 9 18:52:25 CEST 2026
In Falcon mode, the SPL loads a FIT image containing a Linux kernel
instead of U-boot proper, and it may need to fall back to loading U-boot
if Linux is unavailable.
Add support for images containing a Linux kernel, optionally on a
different UFS LUN and/or offset vs. U-boot proper to enable fallback.
Signed-off-by: Alexey Charkov <alchark at flipper.net>
---
common/spl/Kconfig | 18 +++++++++++++++++
common/spl/spl_ufs.c | 57 ++++++++++++++++++++++++++++++++++++++++++++++++++--
2 files changed, 73 insertions(+), 2 deletions(-)
diff --git a/common/spl/Kconfig b/common/spl/Kconfig
index cc819344cad2..2ce48eb981d2 100644
--- a/common/spl/Kconfig
+++ b/common/spl/Kconfig
@@ -1635,6 +1635,16 @@ config SPL_UFS_RAW_U_BOOT_DEVNUM
SCSI device number, which might differ from the UFS LUN if you have
multiple SCSI devices attached and recognized by the SPL.
+config SPL_UFS_RAW_OS_DEVNUM
+ int "Falcon mode: SCSI device number of the UFS device to load OS from"
+ depends on SPL_UFS_SUPPORT && SPL_OS_BOOT
+ default SPL_UFS_RAW_U_BOOT_DEVNUM
+ help
+ UFS devices are usually configured with multiple LUNs, which present
+ themselves as sequentially numbered SCSI devices. This option controls
+ which of them SPL will attempt to load a Falcon OS payload from.
+ It allows putting Linux FITs on a different UFS LU than U-Boot.
+
config SPL_UFS_RAW_U_BOOT_SECTOR
hex "Address on the UFS to load U-Boot from"
depends on SPL_UFS_SUPPORT
@@ -1643,6 +1653,14 @@ config SPL_UFS_RAW_U_BOOT_SECTOR
Address on the block device to load U-Boot from.
Units: UFS sectors (1 sector = 4096 bytes).
+config SPL_UFS_RAW_OS_SECTOR
+ hex "Falcon mode: address on the UFS to load OS image from"
+ depends on SPL_UFS_SUPPORT && SPL_OS_BOOT
+ default SPL_UFS_RAW_U_BOOT_SECTOR
+ help
+ Address on the block device to load a Falcon OS FIT/image from.
+ Units: UFS sectors (1 sector = 4096 bytes).
+
config SPL_WATCHDOG
bool "Support watchdog drivers"
imply SPL_WDT if !HW_WATCHDOG
diff --git a/common/spl/spl_ufs.c b/common/spl/spl_ufs.c
index cef1843f40f3..5c7ec869ab0c 100644
--- a/common/spl/spl_ufs.c
+++ b/common/spl/spl_ufs.c
@@ -20,13 +20,37 @@ 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_raw_os(struct spl_image_info *spl_image,
+ struct spl_boot_device *bootdev,
+ struct spl_load_info *load,
+ struct blk_desc *bd)
+{
+ ulong sector = config_opt_enabled(CONFIG_SPL_OS_BOOT,
+ CONFIG_SPL_UFS_RAW_OS_SECTOR, 0);
+ int err;
+
+ err = spl_load(spl_image, bootdev, load, 0,
+ sector << bd->log2blksz);
+ if (err)
+ return err;
+
+ if (spl_image->os != IH_OS_LINUX && spl_image->os != IH_OS_TEE &&
+ spl_image->os != IH_OS_ARM_TRUSTED_FIRMWARE) {
+ puts("Expected OS image is not found\n");
+ return -ENOENT;
+ }
+
+ return 0;
+}
+
static int spl_ufs_load_image(struct spl_image_info *spl_image,
struct spl_boot_device *bootdev)
{
unsigned long sector = CONFIG_SPL_UFS_RAW_U_BOOT_SECTOR;
int devnum = CONFIG_SPL_UFS_RAW_U_BOOT_DEVNUM;
- struct spl_load_info load;
- struct blk_desc *bd;
+ int os_devnum;
+ struct spl_load_info load, os_load;
+ struct blk_desc *bd, *os_bd;
int err;
/* try to recognize storage devices immediately */
@@ -36,6 +60,35 @@ static int spl_ufs_load_image(struct spl_image_info *spl_image,
return -ENODEV;
spl_load_init(&load, spl_ufs_load_read, bd, bd->blksz);
+ if (IS_ENABLED(CONFIG_SPL_OS_BOOT) && !spl_start_uboot()) {
+ os_devnum = config_opt_enabled(CONFIG_SPL_OS_BOOT,
+ CONFIG_SPL_UFS_RAW_OS_DEVNUM,
+ CONFIG_SPL_UFS_RAW_U_BOOT_DEVNUM);
+ if (os_devnum == devnum) {
+ os_bd = bd;
+ os_load = load;
+ } else {
+ os_bd = blk_get_devnum_by_uclass_id(UCLASS_SCSI, os_devnum);
+ if (!os_bd) {
+ puts("spl_ufs_load_image: UFS OS device not found\n");
+ if (IS_ENABLED(CONFIG_SPL_OS_BOOT_SECURE))
+ return -ENODEV;
+ goto load_uboot;
+ }
+ spl_load_init(&os_load, spl_ufs_load_read, os_bd, os_bd->blksz);
+ }
+
+ err = spl_ufs_load_image_raw_os(spl_image, bootdev, &os_load, os_bd);
+ if (!err)
+ return 0;
+
+ puts("spl_ufs_load_image: Failed to load falcon payload\n");
+ log_debug("(error=%d)\n", err);
+ if (IS_ENABLED(CONFIG_SPL_OS_BOOT_SECURE))
+ return err;
+ }
+
+load_uboot:
err = spl_load(spl_image, bootdev, &load, 0, sector << bd->log2blksz);
if (err) {
puts("spl_ufs_load_image: ufs block read error\n");
--
2.53.0
More information about the U-Boot
mailing list