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 <[email protected]> --- common/spl/Kconfig | 23 +++++++++++++++++++++ common/spl/spl_ufs.c | 58 ++++++++++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 79 insertions(+), 2 deletions(-) diff --git a/common/spl/Kconfig b/common/spl/Kconfig index 7c639ed8f763..0e0c60eb9793 100644 --- a/common/spl/Kconfig +++ b/common/spl/Kconfig @@ -1653,6 +1653,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 @@ -1661,6 +1671,19 @@ 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). + + The default shares the region with U-Boot, which suits Falcon-only + boot: the OS image is written where U-Boot would have gone, so only + one region has to be reserved and there is no fallback. Point this + at a separate location to keep a working U-Boot to fall back to. + 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..d35b5e7ad33a 100644 --- a/common/spl/spl_ufs.c +++ b/common/spl/spl_ufs.c @@ -20,13 +20,38 @@ 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, + CONFIG_SPL_UFS_RAW_U_BOOT_SECTOR); + 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; + struct spl_load_info load, os_load; + struct blk_desc *bd, *os_bd; int devnum = CONFIG_SPL_UFS_RAW_U_BOOT_DEVNUM; - struct spl_load_info load; - struct blk_desc *bd; + int os_devnum; int err; /* try to recognize storage devices immediately */ @@ -36,6 +61,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 (CONFIG_IS_ENABLED(OS_BOOT) && spl_falcon_boot()) { + 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 (CONFIG_IS_ENABLED(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 (CONFIG_IS_ENABLED(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.54.0
