U-boot FIT from scratch

After a standard u-boot build:

$ export CROSS_COMPILE=riscv64-linux-gnu-
$ export OPENSBI=/usr/share/qemu/opensbi-riscv64-generic-fw_dynamic.bin

$ make sifive_unleashed_defconfig

$ make all 

We collect some of the outputs into a directory:

our-directory <- u-boot/spl/u-boot-spl.bin 
our-directory <- u-boot/u-boot-nodtb.bin 
our-directory <- u-boot/arch/riscv/dts/hifive-unleashed-a00.dtb

We also fetch opensbi fw_dynamic (into the same directory):

our-directory <- /usr/share/qemu/opensbi-riscv64-generic-fw_dynamic.bin

Lets pause for a second. What do we know about the generated .itb file (which we did not fetch)?

$ dumpimage -l u-boot.itb
FIT description: Configuration to load OpenSBI before U-Boot
Created:         Thu Nov 27 03:03:59 2025
 Image 0 (uboot)
  Description:  U-Boot
  Created:      Thu Nov 27 03:03:59 2025
  Type:         Standalone Program
  Compression:  uncompressed
  Data Size:    583224 Bytes = 569.55 KiB = 0.56 MiB
  Architecture: RISC-V
  Load Address: 0x80200000
  Entry Point:  unavailable
 Image 1 (opensbi)
  Description:  OpenSBI fw_dynamic Firmware
  Created:      Thu Nov 27 03:03:59 2025
  Type:         Firmware
  Compression:  uncompressed
  Data Size:    115328 Bytes = 112.62 KiB = 0.11 MiB
  Architecture: RISC-V
  OS:           RISC-V OpenSBI
  Load Address: 0x80000000
 Image 2 (fdt-1)
  Description:  hifive-unleashed-a00
  Created:      Thu Nov 27 03:03:59 2025
  Type:         Flat Device Tree
  Compression:  uncompressed
  Data Size:    19464 Bytes = 19.01 KiB = 0.02 MiB
  Architecture: Unknown Architecture
 Default Configuration: 'conf-1'
 Configuration 0 (conf-1)
  Description:  hifive-unleashed-a00
  Kernel:       unavailable
  Firmware:     opensbi
  FDT:          fdt-1
  Loadables:    uboot

Neat! Okay, lets make the same thing as a starting point for future work.

$ cd /our-directory
$ nano u-boot.its

/dts-v1/;

/ {
    description = "Configuration to load OpenSBI before U-Boot";
    #address-cells = <2>;

    images {

        uboot {
            description = "U-Boot"; 
            type = "standalone"; 
            arch = "riscv";
            compression = "none";
            load = <0x80200000>;
            data = /incbin/("u-boot-nodtb.bin");
        };

        opensbi {
            description = "OpenSBI fw_dynamic Firmware";
            type = "firmware";
            arch = "riscv";
            os = "opensbi";
            compression = "none";
            load = <0x80000000>;
            entry = <0x80000000>;
            data = /incbin/("opensbi-riscv64-generic-fw_dynamic.bin");
        };

        fdt-1 {
            description = "hifive-unleashed-a00";
            type = "flat_dt";
            compression = "none";
            data = /incbin/("hifive-unleashed-a00.dtb");
        };
    };

    configurations {
        default = "conf-1";
        
        conf-1 {
            description = "hifive-unleashed-a00";
            firmware = "opensbi";
            fdt = "fdt-1";
            loadables = "uboot";
        };
    };
};

That should do it. Lets generate a .itb from our .its file:

$ mkimage u-boot.its u-boot.itb

# hmm. or, maybe...

$ mkimage -E -B 0x8 -f u-boot.its u-boot.itb

# what about...

$ mkimage -B 0x8 -f u-boot.its u-boot.itb

Well, lets just stick with the first one. Okay, now lets dump that .itb file we just made:

$ dumpimage -l u-boot.itb
FIT description: Configuration to load OpenSBI before U-Boot
Created:         Thu Nov 27 04:15:19 2025
 Image 0 (uboot)
  Description:  U-Boot
  Created:      Thu Nov 27 04:15:19 2025
  Type:         Standalone Program
  Compression:  uncompressed
  Data Size:    583224 Bytes = 569.55 KiB = 0.56 MiB
  Architecture: RISC-V
  Load Address: 0x80200000
  Entry Point:  unavailable
 Image 1 (opensbi)
  Description:  OpenSBI fw_dynamic Firmware
  Created:      Thu Nov 27 04:15:19 2025
  Type:         Firmware
  Compression:  uncompressed
  Data Size:    115328 Bytes = 112.62 KiB = 0.11 MiB
  Architecture: RISC-V
  OS:           RISC-V OpenSBI
  Load Address: 0x80000000
 Image 2 (fdt-1)
  Description:  hifive-unleashed-a00
  Created:      Thu Nov 27 04:15:19 2025
  Type:         Flat Device Tree
  Compression:  uncompressed
  Data Size:    19464 Bytes = 19.01 KiB = 0.02 MiB
  Architecture: Unknown Architecture
 Default Configuration: 'conf-1'
 Configuration 0 (conf-1)
  Description:  hifive-unleashed-a00
  Kernel:       unavailable
  Firmware:     opensbi
  FDT:          fdt-1
  Loadables:    uboot

Looks good! Only the dates are different. But, wait. The file sizes are different:

Original (built automatically by u-boot): 719973 bytes

Ours: 719871 bytes

Hmm. Lets try to boot it in qemu:

$ nano genimage-sdcard.cfg

image sdcard.img {
        size = 128M

        hdimage {
                gpt = true
        }

        partition u-boot-spl {
                image = "u-boot-spl.bin"
                offset = 17K
                partition-type-uuid = 5B193300-FC78-40CD-8002-E86C45580B47
        }

        partition u-boot {
                image = "u-boot.itb"
                offset = 1041K
                partition-type-uuid = 2E54B353-1271-4842-806F-E436D6AF6985
        }
}
$ genimage --config genimage-sdcard.cfg --inputpath . --outputpath .
$ qemu-system-riscv64 \
-machine sifive_u,msel=11 \
-m 8G \
-smp 5 \
-display none \
-serial stdio \
-bios u-boot-spl.bin \
-drive file=sdcard.img,if=sd,format=raw

What happens?

Well, if we use the original .itb built by uboot in our sdcard.img, everything works fine. If we use our own which outputs the same details, it doesn’t. We know the files are different sizes. And, if you open them with a hex editor, the differences start pretty early on.

Does anyone have any experience with this? (Not hex editors! Haha. Has anyone already run into this issue and solved it?)

Kind Regards,

  • Tim