[PATCH v2 09/10] rockchip: binman: Add support for Falcon mode FIT images with TF-A+Linux

Alexey Charkov <[email protected]> Fri, 31 Jul 2026 21:10:53 +0400
Newsgroups gmane.comp.boot-loaders.u-boot
Message-ID <[email protected]>
Modern Rockchip SoCs such as RK3576 require TF-A to be running to provide
firmware services to the OS. To enable booting Linux in Falcon mode on
such SoCs, add a binman template for generation of FIT images containing
appropriately split TF-A and TEE binaries (as is currently done by binman
for U-boot proper images), externally provided Linux kernel and optionally
an initrd.

Any FDTs provided to the generator will be pre-patched with a /chosen
node containing an initrd load address and size (if an initrd is provided)
and a bootargs property containing the kernel command line (if provided),
so that the kernel can be booted directly without external preprocessing.

A config fragment rockchip-falcon.config can be used to enable Falcon
mode boot and the building of TF-A+Falcon with binman, e.g.:

  make nanopi-m5-rk3576_defconfig \
        rockchip-falcon.config

This will produce a FIT image u-boot-rockchip-falcon.itb containing TF-A,
TEE, Linux kernel and optionally an initrd, which can be flashed to UFS
and booted in Falcon mode.

This can also be combined with the existing rockchip-ramboot.config
fragment to obtain images suitable for booting from RAM, e.g.:

  make nanopi-m5-rk3576_defconfig \
        rockchip-falcon.config \
        rockchip-ramboot.config

The resulting images can be uploaded directly to RAM via Maskrom with no
storage or USB loader required, e.g.:

  rockusb download-sram u-boot-rockchip-usb471.bin
  rockusb download-ddr u-boot-rockchip-usb472-falcon.bin

Signed-off-by: Alexey Charkov <[email protected]>
---
 arch/arm/dts/rockchip-u-boot.dtsi     | 204 ++++++++++++++++++++++++++++------
 arch/arm/mach-rockchip/Kconfig        |  49 ++++++++
 board/rockchip/rockchip-falcon.config |   3 +
 3 files changed, 225 insertions(+), 31 deletions(-)

diff --git a/arch/arm/dts/rockchip-u-boot.dtsi b/arch/arm/dts/rockchip-u-boot.dtsi
index 4ba6a87e78ab..5e23ff761751 100644
--- a/arch/arm/dts/rockchip-u-boot.dtsi
+++ b/arch/arm/dts/rockchip-u-boot.dtsi
@@ -35,6 +35,16 @@
 #define HAS_FIT
 #endif
 
+#ifdef CONFIG_ROCKCHIP_FALCON_IMAGE
+/* Falcon-mode load addresses, relative to the SoC DRAM base. */
+#define FALCON_KERNEL_LOAD \
+	(CFG_SYS_SDRAM_BASE + CONFIG_ROCKCHIP_FALCON_KERNEL_LOAD)
+#define FALCON_FDT_LOAD \
+	(CFG_SYS_SDRAM_BASE + CONFIG_ROCKCHIP_FALCON_FDT_LOAD)
+#define FALCON_INITRD_LOAD \
+	(CFG_SYS_SDRAM_BASE + CONFIG_ROCKCHIP_FALCON_INITRD_LOAD)
+#endif
+
 / {
 	binman: binman {
 		multiple-images;
@@ -44,37 +54,13 @@
 #ifdef CONFIG_SPL
 &binman {
 #ifdef HAS_FIT
-	fit_template: template-1 {
-		type = "fit";
 #ifdef CONFIG_ARM64
-		description = "FIT image for U-Boot with bl31 (TF-A)";
-#else
-		description = "FIT image with OP-TEE";
-#endif
-		#address-cells = <1>;
-		fit,fdt-list = "of-list";
-		fit,external-offset = <CONFIG_FIT_EXTERNAL_OFFSET>;
-		fit,align = <512>;
+	/*
+	 * Shared ARM Trusted Firmware (BL31) and optional OP-TEE split-elf
+	 * images, reused by both the U-Boot and Falcon Linux FIT templates.
+	 */
+	fit_firmware_template: template-firmware {
 		images {
-			u-boot {
-				description = "U-Boot";
-				type = "standalone";
-				os = "u-boot";
-				arch = FIT_ARCH;
-				compression = FIT_UBOOT_COMP;
-				load = <CONFIG_TEXT_BASE>;
-				entry = <CONFIG_TEXT_BASE>;
-				u-boot-nodtb {
-					compress = FIT_UBOOT_COMP;
-				};
-#ifdef FIT_HASH_ALGO
-				hash {
-					algo = FIT_HASH_ALGO;
-				};
-#endif
-			};
-
-#ifdef CONFIG_ARM64
 			@atf-SEQ {
 				fit,operation = "split-elf";
 				description = "ARM Trusted Firmware";
@@ -114,7 +100,42 @@
 				};
 #endif
 			};
-#else /* !CONFIG_ARM64 */
+		};
+	};
+#endif /* CONFIG_ARM64 */
+
+	fit_template: template-1 {
+		type = "fit";
+#ifdef CONFIG_ARM64
+		description = "FIT image for U-Boot with bl31 (TF-A)";
+		insert-template = <&fit_firmware_template>;
+#else
+		description = "FIT image with OP-TEE";
+#endif
+		#address-cells = <1>;
+		fit,fdt-list = "of-list";
+		fit,external-offset = <CONFIG_FIT_EXTERNAL_OFFSET>;
+		fit,align = <512>;
+		images {
+			u-boot {
+				description = "U-Boot";
+				type = "standalone";
+				os = "u-boot";
+				arch = FIT_ARCH;
+				compression = FIT_UBOOT_COMP;
+				load = <CONFIG_TEXT_BASE>;
+				entry = <CONFIG_TEXT_BASE>;
+				u-boot-nodtb {
+					compress = FIT_UBOOT_COMP;
+				};
+#ifdef FIT_HASH_ALGO
+				hash {
+					algo = FIT_HASH_ALGO;
+				};
+#endif
+			};
+
+#ifndef CONFIG_ARM64
 			op-tee {
 				description = "OP-TEE";
 				type = "tee";
@@ -132,7 +153,7 @@
 				};
 #endif
 			};
-#endif /* CONFIG_ARM64 */
+#endif /* !CONFIG_ARM64 */
 
 			@fdt-SEQ {
 				description = "fdt-NAME";
@@ -161,6 +182,97 @@
 			};
 		};
 	};
+
+#ifdef CONFIG_ROCKCHIP_FALCON_IMAGE
+	fit_falcon_template: template-falcon {
+		type = "fit";
+		description = "FIT image for Falcon Linux with bl31 (TF-A)";
+		insert-template = <&fit_firmware_template>;
+		#address-cells = <1>;
+		fit,fdt-list = "of-list";
+		fit,external-offset = <CONFIG_FIT_EXTERNAL_OFFSET>;
+		fit,align = <512>;
+
+		images {
+			kernel {
+				description = "Linux kernel";
+				type = "kernel";
+				arch = FIT_ARCH;
+				os = "linux";
+				compression = FIT_UBOOT_COMP;
+				load = <FALCON_KERNEL_LOAD>;
+				entry = <FALCON_KERNEL_LOAD>;
+
+				linux-kernel {
+					compress = FIT_UBOOT_COMP;
+				};
+#ifdef FIT_HASH_ALGO
+				hash {
+					algo = FIT_HASH_ALGO;
+				};
+#endif
+			};
+
+			ramdisk {
+				description = "ramdisk";
+				type = "ramdisk";
+				arch = FIT_ARCH;
+				compression = "none";
+				load = <FALCON_INITRD_LOAD>;
+
+				linux-initrd {
+					optional;
+				};
+#ifdef FIT_HASH_ALGO
+				hash {
+					algo = FIT_HASH_ALGO;
+				};
+#endif
+			};
+
+			@fdt-SEQ {
+				description = "fdt-NAME";
+				type = "flat_dt";
+				arch = FIT_ARCH;
+				compression = "none";
+				load = <FALCON_FDT_LOAD>;
+#ifdef CONFIG_USE_BOOTARGS
+				fit,bootargs = CONFIG_BOOTARGS;
+#endif
+				fit,initrd = "ramdisk";
+#ifdef FIT_HASH_ALGO
+				hash {
+					algo = FIT_HASH_ALGO;
+				};
+#endif
+			};
+		};
+
+		configurations {
+			default = "@config-DEFAULT-SEQ";
+			@config-SEQ {
+				description = "NAME.dtb";
+				fit,firmware = "atf-1", "kernel", "ramdisk";
+				fit,loadables;
+				fit,compatible;
+				fdt = "fdt-SEQ";
+#ifdef FIT_HASH_ALGO
+				hash {
+					algo = FIT_HASH_ALGO;
+				};
+#endif
+			};
+		};
+	};
+
+	falcon-fit {
+		filename = "u-boot-rockchip-falcon.itb";
+
+		fit {
+			insert-template = <&fit_falcon_template>;
+		};
+	};
+#endif
 #endif /* HAS_FIT */
 
 	simple-bin {
@@ -260,6 +372,36 @@
 		};
 		};
 	};
+
+#ifdef CONFIG_ROCKCHIP_FALCON_IMAGE
+	simple-bin-usb472-falcon {
+		filename = "u-boot-rockchip-usb472-falcon.bin";
+		pad-byte = <0x00>;
+
+		u-boot-spl {
+		};
+
+		payload {
+			type = "section";
+			align = <CONFIG_SYS_CACHELINE_SIZE>;
+			/*
+			 * Must be named 'u-boot-any', unlike the non-Falcon
+			 * image which can call this 'fit': SPL declares
+			 * binman_sym(u_boot_any, image_pos) unconditionally, and
+			 * binman resolves that symbol against an entry of that
+			 * exact name or one called u-boot[-elf|-img|-nodtb].
+			 * Those only exist here by way of a U-Boot image inside
+			 * the FIT, which a Falcon FIT does not carry, so without
+			 * this name the symbol cannot be resolved and binman
+			 * fails. The type property is what selects the etype.
+			 */
+			u-boot-any {
+				type = "fit";
+				insert-template = <&fit_falcon_template>;
+			};
+		};
+	};
+#endif
 #endif /* CONFIG_ROCKCHIP_MASKROM_IMAGE */
 };
 #endif /* CONFIG_SPL */
diff --git a/arch/arm/mach-rockchip/Kconfig b/arch/arm/mach-rockchip/Kconfig
index 1a2e7847c9e7..321afc0fbdf6 100644
--- a/arch/arm/mach-rockchip/Kconfig
+++ b/arch/arm/mach-rockchip/Kconfig
@@ -758,6 +758,55 @@ config ROCKCHIP_MASKROM_IMAGE
 	  Rockchip SoCs support maskrom mode boot over USB. Enable this
 	  option to produce maskrom mode boot images containing U-Boot.
 
+config ROCKCHIP_FALCON_IMAGE
+	bool "Build a Falcon mode image for Rockchip"
+	depends on SPL_OS_BOOT && ARM64 && SPL_ATF && SPL_FIT
+	help
+	  Enable this option to produce a FIT image which SPL can use to boot
+	  Linux directly via TF-A, bypassing U-Boot proper (Falcon mode).
+
+	  The image bundles TF-A (BL31), an optional OP-TEE, a Linux kernel
+	  and an optional initramfs, and its device trees are pre-patched with
+	  a /chosen node so that no further processing is needed before boot.
+	  The kernel is mandatory and must be supplied at build time with
+	  LINUX_KERNEL=/path/to/Image; pass LINUX_INITRD=/path/to/initramfs to
+	  include an initramfs as well.
+
+	  This only controls image generation. Say N to build a Falcon-capable
+	  SPL without bundling a kernel into the U-Boot image, for example when
+	  the OS payload is assembled and written to storage separately.
+
+config ROCKCHIP_FALCON_KERNEL_LOAD
+	hex "Falcon mode kernel load offset"
+	depends on ROCKCHIP_FALCON_IMAGE
+	default 0x10000000
+	help
+	  Offset from the start of DRAM at which the Falcon mode kernel is
+	  loaded and entered.
+
+	  All three Falcon mode load offsets have to be checked against the
+	  memory layout of the SoC and of the firmware in use. None of the
+	  three payloads may overlap each other, and none of them may overlap
+	  the regions BL31 and OP-TEE are linked to run from - note that
+	  binman splits their ELFs, so each of those occupies several regions
+	  rather than one contiguous range.
+
+config ROCKCHIP_FALCON_FDT_LOAD
+	hex "Falcon mode devicetree load offset"
+	depends on ROCKCHIP_FALCON_IMAGE
+	default 0x1c000000
+	help
+	  Offset from the start of DRAM at which the Falcon mode devicetree is
+	  loaded. The same constraints as for the kernel offset apply.
+
+config ROCKCHIP_FALCON_INITRD_LOAD
+	hex "Falcon mode initramfs load offset"
+	depends on ROCKCHIP_FALCON_IMAGE
+	default 0x1e000000
+	help
+	  Offset from the start of DRAM at which the Falcon mode initramfs is
+	  loaded. The same constraints as for the kernel offset apply.
+
 config LNX_KRNL_IMG_TEXT_OFFSET_BASE
 	default TEXT_BASE
 
diff --git a/board/rockchip/rockchip-falcon.config b/board/rockchip/rockchip-falcon.config
new file mode 100644
index 000000000000..ac903f16f46a
--- /dev/null
+++ b/board/rockchip/rockchip-falcon.config
@@ -0,0 +1,3 @@
+CONFIG_ROCKCHIP_FALCON_IMAGE=y
+CONFIG_SPL_OS_BOOT=y
+CONFIG_SYS_SPI_KERNEL_OFFS=0x0

-- 
2.54.0