Merge patch series "Add support for secure falcon mode: disable fallback"

Anshul Dalal <anshuld@ti.com> says:

Continuing from the last series[1], this patch series addresses the requirement of
allowing no fallbacks in secure falcon mode.

To do this in a clean way, all the falcon mode logic for each boot media was
refactored to a corresponding *_load_image_os function whereas the regular
boot is implemented in *_load_image, this allows us to easily return early in
case the *_load_image_os function fails with secure mode enabled.

The series also introduces the new SPL_OS_BOOT_SECURE config symbol which
enables secure falcon boot flow.

The generic flow after the patch series looks as follows:

	static int spl_<bootmedia>_load_image(...) {
		if (CONFIG_IS_ENABLED(OS_BOOT)) {

			ret = spl_<bootmedia>_load_image_os(...);

			puts("Failcon mode failed\n");
			if (CONFIG_IS_ENABLED(OS_BOOT_SECURE)) {
				puts("no fallback allowed!\n");
				return ret;
			}

			puts("Falling back to U-Boot\n");
		}

		/* Regular boot flow */
	}

[1]: https://lore.kernel.org/u-boot/20250923124639.667718-1-anshuld@ti.com/
Link: https://lore.kernel.org/r/20251017193318.4124997-1-anshuld@ti.com
This commit is contained in:
Tom Rini
2025-10-20 10:17:54 -06:00
6 changed files with 237 additions and 138 deletions
+8
View File
@@ -1207,6 +1207,14 @@ config SPL_OS_BOOT
Enable booting directly to an OS from SPL.
for more info read doc/README.falcon
config SPL_OS_BOOT_SECURE
bool "Allow Falcon Mode on secure devices"
depends on SPL_OS_BOOT
help
This allows for secure devices with signature verification capabilities
to use falcon mode by disabling certain inherently non-securable options
in the SPL boot flow.
config SPL_PAYLOAD_ARGS_ADDR
hex "Address in memory to load 'args' file for Falcon Mode to"
depends on SPL_OS_BOOT || SPL_LOAD_FIT_OPENSBI_OS_BOOT
+54 -30
View File
@@ -194,6 +194,46 @@ int spl_start_uboot(void)
#endif
#ifdef CONFIG_SYS_MMCSD_FS_BOOT
static int spl_mmc_fs_load_os(struct spl_image_info *spl_image,
struct spl_boot_device *bootdev,
struct blk_desc *blk_dev, int part)
{
int err = -ENOSYS;
if (CONFIG_IS_ENABLED(FS_FAT)) {
err = spl_load_image_fat_os(spl_image, bootdev, blk_dev, part);
if (!err)
return 0;
}
if (CONFIG_IS_ENABLED(FS_EXT4)) {
err = spl_load_image_ext_os(spl_image, bootdev, blk_dev, part);
if (!err)
return 0;
}
return err;
}
static int __maybe_unused spl_mmc_fs_load(struct spl_image_info *spl_image,
struct spl_boot_device *bootdev,
struct blk_desc *blk_dev, int part, const char *file)
{
int err = -ENOENT;
if (CONFIG_IS_ENABLED(FS_FAT)) {
err = spl_load_image_fat(spl_image, bootdev, blk_dev, part, file);
if (!err)
return 0;
}
if (CONFIG_IS_ENABLED(FS_EXT4)) {
err = spl_load_image_ext(spl_image, bootdev, blk_dev, part, file);
if (!err)
return 0;
}
return err;
}
static int spl_mmc_do_fs_boot(struct spl_image_info *spl_image,
struct spl_boot_device *bootdev,
struct mmc *mmc,
@@ -225,42 +265,24 @@ static int spl_mmc_do_fs_boot(struct spl_image_info *spl_image,
}
#endif
#ifdef CONFIG_SPL_FS_FAT
if (!spl_start_uboot()) {
ret = spl_load_image_fat_os(spl_image, bootdev, mmc_get_blk_desc(mmc),
partition);
ret = spl_mmc_fs_load_os(spl_image, bootdev,
mmc_get_blk_desc(mmc), partition);
if (!ret)
return 0;
printf("%s, Failed to load falcon payload: %d\n", __func__,
ret);
if (IS_ENABLED(CONFIG_SPL_OS_BOOT_SECURE))
return ret;
printf("Fallback to U-Boot\n");
}
#ifdef CONFIG_SPL_FS_LOAD_PAYLOAD_NAME
ret = spl_load_image_fat(spl_image, bootdev, mmc_get_blk_desc(mmc),
partition,
filename);
if (!ret)
return ret;
#endif
#endif
#ifdef CONFIG_SPL_FS_EXT4
if (!spl_start_uboot()) {
ret = spl_load_image_ext_os(spl_image, bootdev, mmc_get_blk_desc(mmc),
partition);
if (!ret)
return 0;
}
#ifdef CONFIG_SPL_FS_LOAD_PAYLOAD_NAME
ret = spl_load_image_ext(spl_image, bootdev, mmc_get_blk_desc(mmc),
partition,
filename);
if (!ret)
return 0;
#endif
#endif
#if defined(CONFIG_SPL_FS_FAT) || defined(CONFIG_SPL_FS_EXT4)
ret = -ENOENT;
#endif
#ifdef CONFIG_SPL_FS_LOAD_PAYLOAD_NAME
return spl_mmc_fs_load(spl_image, bootdev, mmc_get_blk_desc(mmc),
partition, filename);
#else
return ret;
#endif
}
#endif
@@ -392,6 +414,8 @@ int spl_mmc_load(struct spl_image_info *spl_image,
ret = mmc_load_image_raw_os(spl_image, bootdev, mmc);
if (!ret)
return 0;
if (IS_ENABLED(CONFIG_SPL_OS_BOOT_SECURE))
return ret;
}
raw_sect = spl_mmc_get_uboot_raw_sector(mmc, raw_sect);
+53 -42
View File
@@ -75,6 +75,52 @@ static int spl_nand_load_element(struct spl_image_info *spl_image,
return spl_load(spl_image, bootdev, &load, 0, offset);
}
#if IS_ENABLED(CONFIG_SPL_OS_BOOT)
static int spl_nand_load_image_os(struct spl_image_info *spl_image,
struct spl_boot_device *bootdev)
{
int *src, *dst, err;
struct legacy_img_hdr *header = spl_get_load_buffer(0, sizeof(*header));
/* load linux */
nand_spl_load_image(CONFIG_SYS_NAND_SPL_KERNEL_OFFS, sizeof(*header),
(void *)header);
err = spl_parse_image_header(spl_image, bootdev, header);
if (err)
return err;
if (header->ih_os != IH_OS_LINUX)
return -EINVAL;
/* happy - was a linux */
err = nand_spl_load_image(CONFIG_SYS_NAND_SPL_KERNEL_OFFS,
spl_image->size,
(void *)spl_image->load_addr);
nand_deselect();
if (err)
return err;
/*
* load parameter image load to temp position since nand_spl_load_image
* reads a whole block which is typically larger than
* CONFIG_CMD_SPL_WRITE_SIZE therefore may overwrite following sections
* like BSS
*/
nand_spl_load_image(CONFIG_CMD_SPL_NAND_OFS, CONFIG_CMD_SPL_WRITE_SIZE,
(void *)CONFIG_TEXT_BASE);
/* copy to destintion */
for (dst = (int *)CONFIG_SPL_PAYLOAD_ARGS_ADDR,
src = (int *)CONFIG_TEXT_BASE;
src < (int *)(CONFIG_TEXT_BASE + CONFIG_CMD_SPL_WRITE_SIZE);
src++, dst++) {
writel(readl(src), dst);
}
return 0;
}
#endif
static int spl_nand_load_image(struct spl_image_info *spl_image,
struct spl_boot_device *bootdev)
{
@@ -89,51 +135,16 @@ static int spl_nand_load_image(struct spl_image_info *spl_image,
#if CONFIG_IS_ENABLED(OS_BOOT)
if (!spl_start_uboot()) {
int *src, *dst;
struct legacy_img_hdr *header =
spl_get_load_buffer(0, sizeof(*header));
/*
* load parameter image
* load to temp position since nand_spl_load_image reads
* a whole block which is typically larger than
* CONFIG_CMD_SPL_WRITE_SIZE therefore may overwrite
* following sections like BSS
*/
nand_spl_load_image(CONFIG_CMD_SPL_NAND_OFS,
CONFIG_CMD_SPL_WRITE_SIZE,
(void *)CONFIG_TEXT_BASE);
/* copy to destintion */
for (dst = (int *)CONFIG_SPL_PAYLOAD_ARGS_ADDR,
src = (int *)CONFIG_TEXT_BASE;
src < (int *)(CONFIG_TEXT_BASE +
CONFIG_CMD_SPL_WRITE_SIZE);
src++, dst++) {
writel(readl(src), dst);
}
/* load linux */
nand_spl_load_image(CONFIG_SYS_NAND_SPL_KERNEL_OFFS,
sizeof(*header), (void *)header);
err = spl_parse_image_header(spl_image, bootdev, header);
if (err)
err = spl_nand_load_image_os(spl_image, bootdev);
if (!err)
return 0;
printf("%s: Failed in falcon boot: %d", __func__, err);
if (IS_ENABLED(CONFIG_SPL_OS_BOOT_SECURE))
return err;
if (header->ih_os == IH_OS_LINUX) {
/* happy - was a linux */
err = nand_spl_load_image(
CONFIG_SYS_NAND_SPL_KERNEL_OFFS,
spl_image->size,
(void *)spl_image->load_addr);
nand_deselect();
return err;
} else {
puts("The Expected Linux image was not "
"found. Please check your NAND "
"configuration.\n");
puts("Trying to start u-boot now...\n");
}
printf("Fallback to U-Boot\n");
}
#endif
#ifdef CONFIG_NAND_ENV_DST
spl_nand_load_element(spl_image, bootdev, CONFIG_ENV_OFFSET);
#ifdef CONFIG_ENV_OFFSET_REDUND
+62 -47
View File
@@ -25,6 +25,58 @@ unsigned long __weak spl_nor_get_uboot_base(void)
return CFG_SYS_UBOOT_BASE;
}
#if IS_ENABLED(CONFIG_SPL_OS_BOOT)
static int spl_nor_load_image_os(struct spl_image_info *spl_image,
struct spl_boot_device *bootdev)
{
/*
* Load Linux from its location in NOR flash to its defined
* location in SDRAM
*/
const struct legacy_img_hdr *header =
(const struct legacy_img_hdr *)CONFIG_SYS_OS_BASE;
struct spl_load_info load;
#ifdef CONFIG_SPL_LOAD_FIT
if (image_get_magic(header) == FDT_MAGIC) {
int ret;
debug("Found FIT\n");
spl_load_init(&load, spl_nor_load_read, NULL, 1);
ret = spl_load_simple_fit(spl_image, &load, CONFIG_SYS_OS_BASE,
(void *)header);
#if defined CONFIG_SPL_PAYLOAD_ARGS_ADDR && defined CONFIG_CMD_SPL_NOR_OFS
memcpy((void *)CONFIG_SPL_PAYLOAD_ARGS_ADDR,
(void *)CONFIG_CMD_SPL_NOR_OFS,
CONFIG_CMD_SPL_WRITE_SIZE);
#endif
return ret;
}
#endif
if (image_get_os(header) != IH_OS_LINUX)
return -EINVAL;
/* happy - was a Linux */
int ret;
ret = spl_parse_image_header(spl_image, bootdev, header);
if (ret)
return ret;
memcpy((void *)spl_image->load_addr,
(void *)(CONFIG_SYS_OS_BASE + sizeof(struct legacy_img_hdr)),
spl_image->size);
#ifdef CONFIG_SPL_PAYLOAD_ARGS_ADDR
spl_image->arg = (void *)CONFIG_SPL_PAYLOAD_ARGS_ADDR;
#endif
return 0;
}
#endif
static int spl_nor_load_image(struct spl_image_info *spl_image,
struct spl_boot_device *bootdev)
{
@@ -36,55 +88,18 @@ static int spl_nor_load_image(struct spl_image_info *spl_image,
*/
spl_image->flags |= SPL_COPY_PAYLOAD_ONLY;
#if CONFIG_IS_ENABLED(OS_BOOT)
#if IS_ENABLED(CONFIG_SPL_OS_BOOT)
int err;
if (!spl_start_uboot()) {
/*
* Load Linux from its location in NOR flash to its defined
* location in SDRAM
*/
const struct legacy_img_hdr *header =
(const struct legacy_img_hdr *)CONFIG_SYS_OS_BASE;
#ifdef CONFIG_SPL_LOAD_FIT
if (image_get_magic(header) == FDT_MAGIC) {
int ret;
debug("Found FIT\n");
spl_load_init(&load, spl_nor_load_read, NULL, 1);
ret = spl_load_simple_fit(spl_image, &load,
CONFIG_SYS_OS_BASE,
(void *)header);
#if defined CONFIG_SPL_PAYLOAD_ARGS_ADDR && defined CONFIG_CMD_SPL_NOR_OFS
memcpy((void *)CONFIG_SPL_PAYLOAD_ARGS_ADDR,
(void *)CONFIG_CMD_SPL_NOR_OFS,
CONFIG_CMD_SPL_WRITE_SIZE);
#endif
return ret;
}
#endif
if (image_get_os(header) == IH_OS_LINUX) {
/* happy - was a Linux */
int ret;
ret = spl_parse_image_header(spl_image, bootdev, header);
if (ret)
return ret;
memcpy((void *)spl_image->load_addr,
(void *)(CONFIG_SYS_OS_BASE +
sizeof(struct legacy_img_hdr)),
spl_image->size);
#ifdef CONFIG_SPL_PAYLOAD_ARGS_ADDR
spl_image->arg = (void *)CONFIG_SPL_PAYLOAD_ARGS_ADDR;
#endif
err = spl_nor_load_image_os(spl_image, bootdev);
if (!err)
return 0;
} else {
puts("The Expected Linux image was not found.\n"
"Please check your NOR configuration.\n"
"Trying to start u-boot now...\n");
}
printf("%s: Failed in falcon boot: %d", __func__, err);
if (IS_ENABLED(CONFIG_SPL_OS_BOOT_SECURE))
return err;
printf("Fallback to U-Boot\n");
}
#endif
+26 -7
View File
@@ -49,6 +49,25 @@ u32 __weak spl_spi_boot_cs(void)
return CONFIG_SF_DEFAULT_CS;
}
#if IS_ENABLED(CONFIG_SPL_OS_BOOT)
static int spl_spi_load_image_os(struct spl_image_info *spl_image,
struct spl_boot_device *bootdev,
struct spi_flash *flash,
struct spl_load_info *load)
{
int err = spl_load(spl_image, bootdev, load, 0,
CONFIG_SYS_SPI_KERNEL_OFFS);
if (err)
return err;
/* Read device tree. */
return spi_flash_read(flash, CONFIG_SYS_SPI_ARGS_OFFS,
CONFIG_SYS_SPI_ARGS_SIZE,
(void *)CONFIG_SPL_PAYLOAD_ARGS_ADDR);
}
#endif
/*
* The main entry for SPI booting. It's necessary that SDRAM is already
* configured and available since this code loads the main U-Boot image
@@ -81,15 +100,15 @@ static int spl_spi_load_image(struct spl_image_info *spl_image,
#if CONFIG_IS_ENABLED(OS_BOOT)
if (!spl_start_uboot()) {
int err = spl_load(spl_image, bootdev, &load, 0,
CONFIG_SYS_SPI_KERNEL_OFFS);
err = spl_spi_load_image_os(spl_image, bootdev, flash, &load);
if (!err)
/* Read device tree. */
return spi_flash_read(
flash, CONFIG_SYS_SPI_ARGS_OFFS,
CONFIG_SYS_SPI_ARGS_SIZE,
(void *)CONFIG_SPL_PAYLOAD_ARGS_ADDR);
return 0;
printf("%s: Failed in falcon boot: %d", __func__, err);
if (IS_ENABLED(CONFIG_SPL_OS_BOOT_SECURE))
return err;
printf("Fallback to U-Boot\n");
}
#endif
+34 -12
View File
@@ -11,6 +11,32 @@
#include <ubispl.h>
#include <spl.h>
#if IS_ENABLED(CONFIG_SPL_OS_BOOT)
int spl_ubi_load_image_os(struct spl_image_info *spl_image,
struct spl_boot_device *bootdev,
struct ubispl_info *info)
{
struct legacy_img_hdr *header;
struct ubispl_load volumes[2];
int err;
volumes[0].vol_id = CONFIG_SPL_UBI_LOAD_KERNEL_ID;
volumes[0].load_addr = (void *)CONFIG_SYS_LOAD_ADDR;
volumes[1].vol_id = CONFIG_SPL_UBI_LOAD_ARGS_ID;
volumes[1].load_addr = (void *)CONFIG_SPL_PAYLOAD_ARGS_ADDR;
err = ubispl_load_volumes(info, volumes, 2);
if (err)
return err;
header = (struct legacy_img_hdr *)volumes[0].load_addr;
spl_parse_image_header(spl_image, bootdev, header);
puts("Linux loaded.\n");
return 0;
}
#endif
int spl_ubi_load_image(struct spl_image_info *spl_image,
struct spl_boot_device *bootdev)
{
@@ -46,21 +72,17 @@ int spl_ubi_load_image(struct spl_image_info *spl_image,
#if CONFIG_IS_ENABLED(OS_BOOT)
if (!spl_start_uboot()) {
volumes[0].vol_id = CONFIG_SPL_UBI_LOAD_KERNEL_ID;
volumes[0].load_addr = (void *)CONFIG_SYS_LOAD_ADDR;
volumes[1].vol_id = CONFIG_SPL_UBI_LOAD_ARGS_ID;
volumes[1].load_addr = (void *)CONFIG_SPL_PAYLOAD_ARGS_ADDR;
ret = spl_ubi_load_image_os(spl_image, bootdev, &info);
if (!ret)
return 0;
ret = ubispl_load_volumes(&info, volumes, 2);
if (!ret) {
header = (struct legacy_img_hdr *)volumes[0].load_addr;
spl_parse_image_header(spl_image, bootdev, header);
puts("Linux loaded.\n");
goto out;
}
puts("Loading Linux failed, falling back to U-Boot.\n");
printf("%s: Failed in falcon boot: %d", __func__, ret);
if (IS_ENABLED(CONFIG_SPL_OS_BOOT_SECURE))
return ret;
printf("Fallback to U-Boot\n");
}
#endif
header = spl_get_load_buffer(-sizeof(*header), sizeof(header));
#ifdef CONFIG_SPL_UBI_LOAD_BY_VOLNAME
volumes[0].vol_id = -1;