diff options
| author | Tom Rini <[email protected]> | 2025-10-20 10:17:54 -0600 |
|---|---|---|
| committer | Tom Rini <[email protected]> | 2025-10-20 10:17:54 -0600 |
| commit | d5996409cecbc181ab3f4f04bdb24284a2837d9c (patch) | |
| tree | 971253a2fd6e768d07324b37c03b05e18def4dff /common | |
| parent | aabda5407ff2f6d896215b2b8a31064f939fb4dc (diff) | |
| parent | d3ac0d60da066bf4ddb5a60174be8108fdc16862 (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/Kconfig | 8 | ||||
| -rw-r--r-- | common/spl/spl_mmc.c | 84 | ||||
| -rw-r--r-- | common/spl/spl_nand.c | 95 | ||||
| -rw-r--r-- | common/spl/spl_nor.c | 105 | ||||
| -rw-r--r-- | common/spl/spl_spi.c | 33 | ||||
| -rw-r--r-- | common/spl/spl_ubi.c | 46 |
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; |
