[PATCH 4/4] rockchip: binman: Add support for Falcon mode FIT images with ATF+Linux

Jonas Karlman jonas at kwiboo.se
Wed Jun 10 00:06:16 CEST 2026


Hi Alexey,

On 6/9/2026 8:26 PM, Alexey Charkov wrote:
> Hi Jonas,
> 
> On Tue, Jun 9, 2026 at 9:54 PM Jonas Karlman <jonas at kwiboo.se> wrote:
>>
>> Hi Alexey,
>>
>> On 6/9/2026 6:52 PM, Alexey Charkov wrote:
>>> Modern Rockchip SoCs such as RK3576 require ATF to be running to provide
>>> firmware services to the OS. To enable booting Linux in Falcon mode on
>>> such SoCs, add binman support for generation of FIT images containing
>>> appropriately split ATF raw binaries (as is currently done by binman for
>>> U-boot proper images), externally preprocessed DTB and a Linux kernel.
>>>
>>> Signed-off-by: Alexey Charkov <alchark at flipper.net>
>>> ---
>>>  Makefile                           |   2 +
>>>  arch/arm/dts/rockchip-u-boot.dtsi  | 109 +++++++++++++++++++++++++++++++++++++
>>>  tools/binman/etype/falcon_fdt.py   |  26 +++++++++
>>>  tools/binman/etype/linux_kernel.py |  22 ++++++++
>>>  4 files changed, 159 insertions(+)
>>>
>>> diff --git a/Makefile b/Makefile
>>> index 4e5c1dd6a1c4..844e5adb7b31 100644
>>> --- a/Makefile
>>> +++ b/Makefile
>>> @@ -1690,6 +1690,8 @@ cmd_binman = $(srctree)/tools/binman/binman $(if $(BINMAN_DEBUG),-D) \
>>>               $(foreach f,$(BINMAN_INDIRS),-I $(f)) \
>>>               -a atf-bl1-path=${BL1} \
>>>               -a atf-bl31-path=${BL31} \
>>> +             -a linux-kernel-path=${LINUX_KERNEL} \
>>> +             -a falcon-fdt-path=${FALCON_FDT} \
>>>               -a tee-os-path=${TEE} \
>>>               -a ti-dm-path=${TI_DM} \
>>>               -a opensbi-path=${OPENSBI} \
>>> diff --git a/arch/arm/dts/rockchip-u-boot.dtsi b/arch/arm/dts/rockchip-u-boot.dtsi
>>> index 4ba6a87e78ab..866a6ab654ca 100644
>>> --- a/arch/arm/dts/rockchip-u-boot.dtsi
>>> +++ b/arch/arm/dts/rockchip-u-boot.dtsi
>>> @@ -161,6 +161,96 @@
>>>                       };
>>>               };
>>>       };
>>> +
>>> +#ifdef CONFIG_SPL_OS_BOOT
>>> +     fit_falcon_template: template-falcon {
>>
>> Not sure it is possible, but this looks to add lots of duplicated
>> content. Could we try to re-use more, e.g. is it possible to extract
>> @atf-SEQ, and I also think we may want to support loading of TEE-OS?
> 
> Makes sense, will try to refactor a bit to reduce duplication.
> 
>>> +             type = "fit";
>>> +             description = "FIT image for Falcon Linux with bl31 (TF-A)";
>>> +             #address-cells = <1>;
>>> +             fit,fdt-list-val = "u-boot";
>>> +             fit,external-offset = <CONFIG_FIT_EXTERNAL_OFFSET>;
>>> +             fit,align = <512>;
>>> +
>>> +             images {
>>> +                     @atf-SEQ {
>>> +                             fit,operation = "split-elf";
>>> +                             description = "ARM Trusted Firmware";
>>> +                             type = "firmware";
>>> +                             arch = FIT_ARCH;
>>> +                             os = "arm-trusted-firmware";
>>> +                             compression = "none";
>>> +                             fit,load;
>>> +                             fit,entry;
>>> +                             fit,data;
>>> +
>>> +                             atf-bl31 {
>>> +                             };
>>> +#ifdef FIT_HASH_ALGO
>>> +                             hash {
>>> +                                     algo = FIT_HASH_ALGO;
>>> +                             };
>>> +#endif
>>> +                     };
>>> +
>>> +                     kernel {
>>> +                             description = "Linux kernel";
>>> +                             type = "kernel";
>>> +                             arch = FIT_ARCH;
>>> +                             os = "linux";
>>> +                             compression = "none";
>>> +                             load = <0x48000000>;
>>> +                             entry = <0x48000000>;
>>
>> We should not hard-code these here, they seem to be RK3576 specific.
> 
> Fair enough. Should probably come from configs.
> 
>>> +
>>> +                             linux-kernel {
>>> +                             };
>>> +#ifdef FIT_HASH_ALGO
>>> +                             hash {
>>> +                                     algo = FIT_HASH_ALGO;
>>> +                             };
>>> +#endif
>>> +                     };
>>> +
>>> +                     fdt-1 {
>>> +                             description = "falcon-fdt";
>>> +                             type = "flat_dt";
>>> +                             arch = FIT_ARCH;
>>> +                             compression = "none";
>>> +                             load = <0x52000000>;
>>
>> Same here.
> 
> Ack
> 
>>> +
>>> +                             falcon-fdt {
>>> +                             };
>>
>> If I am not mistaken we can already inject an external DT to be used as
>> control fdt during U-Boot build using EXT_DTB env, maybe it is better to
>> use that instead of passing in a new FDT?
>>
>> We probably also want to use @fdt-SEQ and @config-SEQ to be able to
>> dynamically load a config based on e.g. board_fit_config_name_match()
>> that some boards already use to select config/fdt for U-Boot proper.
> 
> Indeed, that would be quite interesting to have to make it all less
> hardcoded. Does board_fit_config_name_match() also work in SPL?

Yes, that is where I know it is currently being used for Rockchip on
such boards, e.g. rk3566-zero3 and similar.

spl_load_simple_fit()
- spl_simple_fit_parse()
   - fit_find_config_node()
      - board_fit_config_name_match()

And in U-Boot proper the board model/variant is mostly used to set
correct fdtfile env var so that correct FDT can be loaded from e.g.
fdtdir when doing pxe_utils booting.

> 
>>> +#ifdef FIT_HASH_ALGO
>>> +                             hash {
>>> +                                     algo = FIT_HASH_ALGO;
>>> +                             };
>>> +#endif
>>> +                     };
>>> +             };
>>> +
>>> +             configurations {
>>> +                     default = "config-1";
>>> +                     @config-SEQ {
>>> +                             description = "RK3576 Falcon Linux via ATF";
>>
>> This is rockchip-u-boot.dtsi, drop RK3576 specific parts :-)
> 
> RK3576 is the whole world to me! :-D
> 
> Will do, thanks for pointing out
> 
>>> +                             fit,firmware = "atf-1", "kernel";
>>> +                             fit,loadables;
>>> +                             fdt = "fdt-SEQ";
>>> +#ifdef FIT_HASH_ALGO
>>> +                             hash {
>>> +                                     algo = FIT_HASH_ALGO;
>>> +                             };
>>> +#endif
>>> +                     };
>>> +             };
>>> +     };
>>> +
>>> +     falcon-fit {
>>> +             filename = "u-boot-rockchip-falcon.itb";
>>
>> Do we need to export this file? the old .itb-file is exported because
>> some distro build scripts or flash instructions still use the older
>> files instead of the preferred u-boot-rockchip.bin.
> 
> Yes, this is the file you would actually flash onto, say, dedicated
> UFS LUN to preserve Linux-to-U-boot fallback path.
> 
> I'm currently overwriting my main U-boot by `rockusb write-file 16384
> u-boot-rockchip-falcon.itb` but in a normally working setup one
> wouldn't want to do that, so a pre-packed image with the SPL and the
> rest is less helpful in Falcon mode. The combo of
> `idbloader.img`+`u-boot-rockchip-falcon.itb` is what I believe should
> be used, with the former going to W-LU-A and the latter going wherever
> there's enough space for a Linux image.
> 
>>> +
>>> +             fit {
>>> +                     insert-template = <&fit_falcon_template>;
>>> +             };
>>> +     };
>>> +#endif
>>>  #endif /* HAS_FIT */
>>>
>>>       simple-bin {
>>> @@ -260,6 +350,25 @@
>>>               };
>>>               };
>>>       };
>>> +
>>> +#ifdef CONFIG_SPL_OS_BOOT
>>> +     simple-bin-usb472-falcon {
>>
>> Do we really need this? As you notice the BootROM loader is not really
>> optimized for large payloads, I thought using a 1-2 MiB payload with
>> TF-A + U-Boot proper was stretching it, sending a full Linux kernel seem
>> like a big stretch, as evidenced by the 6 minute load time?
> 
> It's neat for CI workloads and quick testing to jump straight to Linux
> without persistent storage or TFTP servers. I'm hoping to resolve the
> slow boot ROM execution one way or another, maybe by poking some CRU
> registers from boost.bin.

On RK3576 the extra long load time could likely be improved by adjusting
core clocks before/after DRAM init runs. I have not tried to figure out
what boost.bin v1.03 does to improve UFS boot speeds but likely some
clock tuning is going on.

> 
> There have also been attempts at enabling opensource TPL on RK3576 and
> RK356x, so if/when they land we would be free to adjust clocks much
> earlier, hopefully making the boot faster. After all, it works
> brilliantly when booting from fixed storage, so there isn't much
> reason for it not to work from Maskrom, apart from the particular boot
> ROM on RK3576 being capricious (not sure if it applies to other RK
> SoCs).

Based on testing on quite a few RK SoCs there seem to be a mix of fast
and slow crc16 implementations, possible some can be due to slow clock
speed, but I also fear a few are using a very basic implementation that
starves even cores running at full rates.

E.g. on my decent x86 labgrid exporter using similar basic crc16
implementation loading 472 image of about 2-3 MiB could take 30-60
seconds, and using table lookup, it went down to a few seconds.
I can only imagine load times on some of the weaker SoCs :-)

This is the main reason behind commit 9d3d4d619252 ("rockchip: Reduce
size of ramboot usb472 payload"), removing 1-2 MiB zero-padding could
help load time by several seconds, even on faster SoCs that normally
does not have core clocks adjusted in SPL/proper.

Regards,
Jonas

> 
>>> +             filename = "u-boot-rockchip-usb472-falcon.bin";
>>> +             pad-byte = <0x00>;
>>> +
>>> +             u-boot-spl {
>>> +             };
>>> +
>>> +             payload {
>>> +                     type = "section";
>>> +                     align = <CONFIG_SYS_CACHELINE_SIZE>;
>>
>> nit: blank line between props and nodes.
> 
> Ack
> 
>>> +                     u-boot-any {
>>> +                             type = "fit";
>>> +                             insert-template = <&fit_falcon_template>;
>>> +                     };
>>> +             };
>>> +     };
>>> +#endif
>>>  #endif /* CONFIG_ROCKCHIP_MASKROM_IMAGE */
>>>  };
>>>  #endif /* CONFIG_SPL */
>>> diff --git a/tools/binman/etype/falcon_fdt.py b/tools/binman/etype/falcon_fdt.py
>>> new file mode 100644
>>> index 000000000000..7c5b13b60d05
>>> --- /dev/null
>>> +++ b/tools/binman/etype/falcon_fdt.py
>>> @@ -0,0 +1,26 @@
>>> +# SPDX-License-Identifier: GPL-2.0+
>>> +# Copyright (c) 2026 Flipper FZCO
>>> +#
>>> +# Entry type for Linux DTB used in Falcon mode FIT images.
>>> +
>>> +from binman.etype.blob_named_by_arg import Entry_blob_named_by_arg
>>> +
>>> +
>>> +class Entry_falcon_fdt(Entry_blob_named_by_arg):
>>> +    """Falcon Linux DTB for Rockchip maskrom Falcon image
>>> +
>>> +    Properties / Entry arguments:
>>> +        - falcon-fdt-path: Filename containing the Falcon Linux DTB (optional,
>>> +            defaults to 'u-boot.dtb')
>>> +
>>> +    This allows selecting the Falcon DTB from an environment variable passed
>>> +    through binman entry arguments, while defaulting to the built U-Boot
>>> +    control DTB when not provided.
>>> +    """
>>> +
>>> +    def __init__(self, section, etype, node):
>>> +        super().__init__(section, etype, node, 'falcon-fdt')
>>> +        # Entry_blob defaults filename to etype when no filename is provided.
>>> +        # Treat that as "unset" and fall back to the control DTB.
>>> +        if not self._filename or self._filename == self.etype:
>>> +            self._filename = 'u-boot.dtb'
>>> diff --git a/tools/binman/etype/linux_kernel.py b/tools/binman/etype/linux_kernel.py
>>> new file mode 100644
>>> index 000000000000..15a1da690c4f
>>> --- /dev/null
>>> +++ b/tools/binman/etype/linux_kernel.py
>>> @@ -0,0 +1,22 @@
>>> +# SPDX-License-Identifier: GPL-2.0+
>>> +# Copyright (c) 2026 Flipper FZCO
>>> +#
>>> +# Entry-type module for Linux kernel binary blob
>>> +
>>> +from binman.etype.blob_named_by_arg import Entry_blob_named_by_arg
>>> +
>>> +
>>> +class Entry_linux_kernel(Entry_blob_named_by_arg):
>>> +    """Linux kernel image blob
>>> +
>>> +    Properties / Entry arguments:
>>> +        - linux-kernel-path: Filename of file to read into entry. This is
>>> +            typically an uncompressed ARM64 Image.
>>> +
>>> +    This entry allows binman FIT templates to consume a kernel provided via
>>> +    make variable, similar to how BL31 is passed to atf-bl31.
>>> +    """
>>> +
>>> +    def __init__(self, section, etype, node):
>>> +        super().__init__(section, etype, node, 'linux-kernel', required=True)
>>> +        self.external = True
>>>
>>
>> New binman etypes require new tests for 100% code coverage.
> 
> Ack
> 
>> Also do we need to update Rockchip documentation to cover Falcon mode?
> 
> Yes, that would be right, thanks for pointing out.
> 
> Thank you for looking into this!
> 
> Best regards,
> Alexey



More information about the U-Boot mailing list