Getting U-Boot to load dtb from FIT image

u-boot

I'm working towards setting up U-Boot to boot only verified Linux kernel from a Kernel+fdt FIT image. (Everything is built under Yocto).
The U-Boot bin has a basic device tree appended to it which it boots up using, but the FIT image has the full tree for the kernel.

I have everything pretty much working, except that when the kernel is booted, U-Boot is ignoring the device tree in the FIT image and instead passing its own one – based on the value of fdtaddr (== 0x11000000):

Hit any key to stop autoboot:  0
reading uImage
3346230 bytes read in 100 ms (31.9 MiB/s)
## Loading kernel from FIT Image at 18000000 ...
No configuration specified, trying default...
Found default configuration: 'conf@1'
   Using 'conf@1' configuration
   Verifying Hash Integrity ... sha1,rsa2048:dev+ OK
   Trying 'kernel@1' kernel subimage
     Description:  Linux kernel
     Type:         Kernel Image
     Compression:  uncompressed
     Data Start:   0x180000e8
     Data Size:    3304016 Bytes = 3.2 MiB
     Architecture: ARM
     OS:           Linux
     Load Address: 0x10008000
     Entry Point:  0x10008000
     Hash node:    'hash@1'
     Hash algo:    sha1
     Hash value:   ff0333f01a894f81d716605f7c7995d651ff8111
     Hash len:     20
   Verifying Hash Integrity ... sha1+ OK
*  fdt: cmdline image address = 0x11000000
## Checking for 'FDT'/'FDT Image' at 11000000
Wrong FIT format: no description
*  fdt: raw FDT blob
## Flattened Device Tree blob at 11000000
   Booting using the fdt blob at 0x11000000
   of_flat_tree at 0x11000000 size 0x0000505a
   Loading Kernel Image ... OK
## device tree at 11000000 ... 11005059 (len=32858 [0x805A])
   Loading Device Tree to 2f72e000, end 2f736059 ... OK

[NB my U-Boot has some board-specific modules – from the board manufacturer – which might be altering U-Boot's standard behaviour]

I can get correct operation, if after the image is loaded, I "setenv fdtaddr ${loadaddr}" (== 0x18000000) – then U-Boot does find the device tree in the FIT image and passes that instead:

Hit any key to stop autoboot:  0
reading uImage
3346230 bytes read in 101 ms (31.6 MiB/s)
## Loading kernel from FIT Image at 18000000 ...
No configuration specified, trying default...
Found default configuration: 'conf@1'
   Using 'conf@1' configuration
   Verifying Hash Integrity ... sha1,rsa2048:dev+ OK
   Trying 'kernel@1' kernel subimage
     Description:  Linux kernel
     Type:         Kernel Image
     Compression:  uncompressed
     Data Start:   0x180000e8
     Data Size:    3304016 Bytes = 3.2 MiB
     Architecture: ARM
     OS:           Linux
     Load Address: 0x10008000
     Entry Point:  0x10008000
     Hash node:    'hash@1'
     Hash algo:    sha1
     Hash value:   ff0333f01a894f81d716605f7c7995d651ff8111
     Hash len:     20
   Verifying Hash Integrity ... sha1+ OK
*  fdt: cmdline image address = 0x18000000
## Checking for 'FDT'/'FDT Image' at 18000000
## Loading fdt from FIT Image at 18000000 ...
No configuration specified, trying default...
Found default configuration: 'conf@1'
   Using 'conf@1' configuration
   Trying 'fdt@1' fdt subimage
     Description:  Flattened Device Tree blob
     Type:         Flat Device Tree
     Compression:  uncompressed
     Data Start:   0x18326c2c
     Data Size:    38269 Bytes = 37.4 KiB
     Architecture: ARM
     Hash node:    'hash@1'
     Hash algo:    sha1
     Hash value:   79d5eeb892ef059566c04d98cdc6b30e92a665a2
     Hash len:     20
   Verifying Hash Integrity ... sha1+ OK
Can't get 'load' property from FIT 0x18000000, node: offset 3304372, name fdt@1 (FDT_ERR_NOTFOUND)
   Booting using the fdt blob at 0x18326c2c
   of_flat_tree at 0x18326c2c size 0x0000957d
   Loading Kernel Image ... OK
## device tree at 18326c2c ... 183301a8 (len=50557 [0xC57D])
   Loading Device Tree to 2f72a000, end 2f73657c ... OK

This is fine (I can add the above command to 'default_bootargs'), but I wondered if I'm missing some 'proper' trick to get the same behaviour – I kinda assumed that if you loaded a FIT image then U-Boot would naturally load not only the kernel from it but also the device tree. (I've not yet been able to grasp the options on the bootm command…)

Thanks

[Edit:]

/dts-v1/;

/ {
        description = "U-Boot fitImage for MyBoard/4.4/tx6";
        #address-cells = <1>;

        images {
                kernel@1 {
                        description = "Linux kernel";
                        data = /incbin/("linux.bin");
                        type = "kernel";
                        arch = "arm";
                        os = "linux";
                        compression = "none";
                        load = <0x10008000>;
                        entry = <0x10008000>;
                        hash@1 {
                                algo = "sha1";
                        };
                };
                fdt@1 {
                        description = "Flattened Device Tree blob";
                        data = /incbin/("arch/arm/boot/dts/tx6.dtb");
                        type = "flat_dt";
                        arch = "arm";
                        compression = "none";
                        hash@1 {
                                algo = "sha1";
                        };
                };
    };

        configurations {
                default = "conf@1";
                conf@1 {
                        description = "Linux kernel, FDT blob";
            kernel = "kernel@1";
            fdt = "fdt@1";


                        hash@1 {
                                algo = "sha1";
                        };
                        signature@1 {
                                algo = "sha1,rsa2048";
                                key-name-hint = "dev-example";
                sign-images = "kernel", "fdt";
                        };
                };
    };
};

[Edit:]

autoload=no
autostart=no
baseboard=stk5-v3
baudrate=115200
boot_mode=mmc
bootargs_jffs2=run default_bootargs;setenv bootargs ${bootargs} root=/dev/mtdblock3 rootfstype=jffs2
bootargs_mmc=run default_bootargs;setenv bootargs ${bootargs} root=PARTUUID=${rootpart_uuid} rootwait
bootargs_nfs=run default_bootargs;setenv bootargs ${bootargs} root=/dev/nfs nfsroot=${nfs_server}:${nfsroot},nolock ip=dhcp
bootargs_sdcard=run default_bootargs;setenv bootargs ${bootargs} root=/dev/mmcblk0p2 rootwait
bootargs_ubifs=run default_bootargs;setenv bootargs ${bootargs} ubi.mtd=rootfs root=ubi0:rootfs rootfstype=ubifs
bootcmd=run bootcmd_${boot_mode} bootm_cmd
bootcmd_jffs2=setenv autostart no;run bootargs_jffs2;nboot linux
bootcmd_mmc=setenv autostart no;run bootargs_mmc;fatload mmc 0 ${loadaddr} ${bootfile}
bootcmd_net=setenv autoload y;setenv autostart n;run bootargs_nfs;dhcp
bootcmd_sdcard=setenv autostart no;run bootargs_sdcard;fatload mmc 1:1 ${loadaddr} ${bootfile}
bootdelay=1
bootfile=uImage
bootm_cmd=bootm ${loadaddr} - ${fdtaddr}
cpu_clk=792
default_bootargs=setenv bootargs init=/sbin/init console=ttymxc0,115200 ro debug panic=1 ${append_bootargs}; setenv fdtaddr ${loadaddr}
emmc_boot_ack=1
emmc_boot_part=1
ethact=FEC
ethaddr=00:01:02:7f:e5:50
fdtaddr=11000000
fdtsave=mmc partconf 0 ${emmc_boot_ack} ${emmc_boot_part} ${emmc_boot_part};mmc write ${fdtaddr} 0x680 80;mmc partconf 0 ${emmc_boot_ack} ${emmc_boot_part} 0
fdtsize=505a
loadaddr=18000000
nfsroot=/tftpboot/rootfs
otg_mode=device
rootpart_uuid=0cc66cc0-02
splashimage=18000000
stderr=serial
stdin=serial
stdout=serial
touchpanel=edt-ft5x06
ver=U-Boot 2015.10-rc2 (Aug 11 2017 - 18:57:06 +0100)
video_mode=VGA

Best Answer

The answer to this exact problem comes from understanding that U-Boot tries to be extremely flexible and this can lead to some confusion at times. Looking at the provided environment we can see that we have the bootcmd (which is executed when the boot delay runs out) boils down to:

bootm ${loadaddr} - ${fdtaddr}

And this means that we look at ${loadaddr} for our image, no where for a ramdisk and ${fdtaddr} for the device tree to use. In the case of a legacy-style uImage this makes sense as the ramdisk and device tree are not (likely) to be contained within the file. A FIT image however has all of this included, and offers lots of extra useful features (which the poster wishes to use). What happens is that after picking out the device tree included in the FIT image, U-Boot then parses the rest of the arguments and looks at ${fdtaddr} for the device tree to use. If bootm_cmd was set to simply:

bootm ${loadaddr}

instead, it would work as expected.

Related Question