summaryrefslogtreecommitdiff
path: root/common
diff options
context:
space:
mode:
authorTom Rini <[email protected]>2025-10-20 10:17:54 -0600
committerTom Rini <[email protected]>2025-10-20 10:17:54 -0600
commitd5996409cecbc181ab3f4f04bdb24284a2837d9c (patch)
tree971253a2fd6e768d07324b37c03b05e18def4dff /common
parentaabda5407ff2f6d896215b2b8a31064f939fb4dc (diff)
parentd3ac0d60da066bf4ddb5a60174be8108fdc16862 (diff)
Merge patch series "Add support for secure falcon mode: disable fallback"
Anshul Dalal <[email protected]> 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/[email protected]/ Link: https://lore.kernel.org/r/[email protected]
Diffstat (limited to 'common')
-rw-r--r--common/spl/Kconfig8
-rw-r--r--common/spl/spl_mmc.c84
-rw-r--r--common/spl/spl_nand.c95
-rw-r--r--common/spl/spl_nor.c105
-rw-r--r--common/spl/spl_spi.c33
-rw-r--r--common/spl/spl_ubi.c46
6 files changed, 235 insertions, 136 deletions
diff --git a/common/spl/Kconfig b/common/spl/Kconfig
index 4ece5d168f9..ba94d6fe05a 100644
--- a/common/spl/Kconfig
+++ b/common/spl/Kconfig
@@ -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
diff --git a/common/spl/spl_mmc.c b/common/spl/spl_mmc.c
index cd56cf71055..0a00d295575 100644
--- a/common/spl/spl_mmc.c
+++ b/common/spl/spl_mmc.c
@@ -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);
- if (!ret)
- return 0;
- }
-#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);
+ 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_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);
diff --git a/common/spl/spl_nand.c b/common/spl/spl_nand.c
index 22883f4e8b9..3da292f1437 100644
--- a/common/spl/spl_nand.c
+++ b/common/spl/spl_nand.c
@@ -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
diff --git a/common/spl/spl_nor.c b/common/spl/spl_nor.c
index 1021d933999..bb91f4ab8f8 100644
--- a/common/spl/spl_nor.c
+++ b/common/spl/spl_nor.c
@@ -25,66 +25,81 @@ unsigned long __weak spl_nor_get_uboot_base(void)
return CFG_SYS_UBOOT_BASE;
}
-static int spl_nor_load_image(struct spl_image_info *spl_image,
- struct spl_boot_device *bootdev)
+#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)
{
- struct spl_load_info load;
-
/*
- * Loading of the payload to SDRAM is done with skipping of
- * the mkimage header in this SPL NOR driver
+ * Load Linux from its location in NOR flash to its defined
+ * location in SDRAM
*/
- spl_image->flags |= SPL_COPY_PAYLOAD_ONLY;
+ const struct legacy_img_hdr *header =
+ (const struct legacy_img_hdr *)CONFIG_SYS_OS_BASE;
+ struct spl_load_info load;
-#if CONFIG_IS_ENABLED(OS_BOOT)
- 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;
+ if (image_get_magic(header) == FDT_MAGIC) {
+ int ret;
- debug("Found FIT\n");
- spl_load_init(&load, spl_nor_load_read, NULL, 1);
+ 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);
+ 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);
+ memcpy((void *)CONFIG_SPL_PAYLOAD_ARGS_ADDR,
+ (void *)CONFIG_CMD_SPL_NOR_OFS,
+ CONFIG_CMD_SPL_WRITE_SIZE);
#endif
- return ret;
- }
+ 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);
+ 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;
+ 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)
+{
+ struct spl_load_info load;
+
+ /*
+ * Loading of the payload to SDRAM is done with skipping of
+ * the mkimage header in this SPL NOR driver
+ */
+ spl_image->flags |= SPL_COPY_PAYLOAD_ONLY;
+
+#if IS_ENABLED(CONFIG_SPL_OS_BOOT)
+ int err;
+
+ if (!spl_start_uboot()) {
+ 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
diff --git a/common/spl/spl_spi.c b/common/spl/spl_spi.c
index c2b188371c2..4d61214bceb 100644
--- a/common/spl/spl_spi.c
+++ b/common/spl/spl_spi.c
@@ -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
diff --git a/common/spl/spl_ubi.c b/common/spl/spl_ubi.c
index a8d3f43b452..25e7599703c 100644
--- a/common/spl/spl_ubi.c
+++ b/common/spl/spl_ubi.c
@@ -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;