This article describes how to use mkimage utility to generate different type of images that are loaded by U-Boot.

Task Dependencies (Pre-requisites)


Tools Required

  • mkimage (Can be installed or use the one generated in the U-Boot build process)
  • dumpimage (Can be installed or use the one generated in the U-Boot build process)
  • dtc (Can be installed or use the one generated in the DTC build or Kernel build)

Input Files Required

  • Image binaries (Kernel, ramdisk/initramfs, DTS)
  • Image source file (.its)

Output Files Produced

  • U-Boot wrapped binaries (Legacy)
  • FIT uImage

Task Description

Legacy Images

The way on Linux images were boot in the Xilinx provided Linux image releases was based on the legacy boot mode where each of the components is loaded individually and used as argument on bootm command, as explained in the "Bootm Command Details" of main U-Boot wiki page. The Linux image and the ramdisk/initramfs files requires a U-Boot header file in order to be used in the boot command, so mkimage tool is used to add the extra information.
bootm <Linux uImage address> <mkimage wrapped ramdisk address> <device tree (dtb) address>

Root file system

As explained in the kernel docs, since Kernel 2.6 release, the main root file system format is the initramfs, which in the different Xilinx workflows is generated as a CPIO file (the name may vary between released images/Petalinux/Yocto flows and it might be compressed as well). If the rootfs will be used to boot in a legacy image mode, then it must be wrapped with the U-Boot header as in the bellow examples.
mkimage -n 'Ramdisk Image' -A arm -O linux -T ramdisk -C gzip -d initramfs.cpio.gz initramfs.ub
mkimage -n 'Ramdisk Image' -A arm64 -O linux -T ramdisk -C none -d initramfs.cpio initramfs.ub

Kernel Image

The compiled kernel image needs to be wrapped with the U-Boot header in order to be used to boot the Linux image in the legacy image mode. If the kernel image is build from the repository, the build process includes a last step where the U-Boot wrapper is added to the image and a uImage file is generated, however for Petalinux releases, as far as a FIT image mode is used by default the kernel image is not wrapped.
mkimage -n 'Kernel Image' -A arm -O linux -C gzip -T kernel -a 0x8000 -e 0x8000 -d zImage uImage
mkimage -n 'Kernel Image' -A arm64 -O linux -C none -T kernel -a 0x8000 -e 0x8000 -d Image uImage

Flattened Image Tree

Since Flattened Device-Tree was introduced in kernel 2.6 the amount of use cases that a embedded system could face was increasing (FDT missing in legacy platform, ramdisk optional...) so even the extension to the legacy image type to support multi-image was not enough to cover all the use cases as explained in here. Nowadays security features also are required in most the embedded systems so security/integrity features, so a new Flattened Image Tree (FIT) uImage format was defined to provide all these features. This format has been the default image mode for Petalinux and for the Linux Image releases since 2017.1 (The three components are wrapped in a single image.ub file).

Generate Images

FIT works as a tree structure, like the device-tree, where a image source file (.its) and a set of data files are used as an input, and a image tree blob (.itb) is generated as an output.
Note: Xilinx tends to use .ub extension (i.e. image.ub)

The image source file is defined by mandatory/optional properties and nodes as explained here. The common use case for a Xilinx based device will use three input files (Kernel, DTB and initramfs) and just once configuration, so the following .its file could be used to generate define that configuration:
/dts-v1/;
 
/ {
    description = "U-Boot fitImage for plnx_aarch64 kernel";
    #address-cells = <1>;
 
    images {
        kernel@0 {
            description = "Linux Kernel";
            data = /incbin/("./Image");
            type = "kernel";
            arch = "arm64";
            os = "linux";
            compression = "none";
            load = <0x80000>;
            entry = <0x80000>;
            hash@1 {
                algo = "sha1";
            };
        };
        fdt@0 {
            description = "Flattened Device Tree blob";
            data = /incbin/("./system.dtb");
            type = "flat_dt";
            arch = "arm64";
            compression = "none";
            hash@1 {
                algo = "sha1";
            };
        };
        ramdisk@0 {
            description = "ramdisk";
            data = /incbin/("./ramdisk.cpio");
            type = "ramdisk";
            arch = "arm64";
            os = "linux";
            compression = "none";
            hash@1 {
                algo = "sha1";
            };
        };
    };
    configurations {
        default = "conf@1";
        conf@1 {
            description = "Boot Linux kernel with FDT blob + ramdisk";
            kernel = "kernel@0";
            fdt = "fdt@0";
            ramdisk = "ramdisk@0";
            hash@1 {
                algo = "sha1";
            };
        };
    };
};
The image source file is used as an input argument for the mkimage utility to generate the resulting .itb file, which is going to be used by the bootm command in the target to load the Linux image.
$ mkimage -f image.its image.itb
FIT description: U-Boot fitImage for plnx_aarch64 kernel
Created:         Thu Sep 14 17:05:07 2017
 Image 0 (kernel@0)
  Description:  Linux Kernel
  Created:      Thu Sep 14 17:05:07 2017
  Type:         Kernel Image
  Compression:  uncompressed
  Data Size:    12263936 Bytes = 11976.50 kB = 11.70 MB
  Architecture: AArch64
  OS:           Linux
  Load Address: 0x00080000
  Entry Point:  0x00080000
  Hash algo:    sha1
  Hash value:   7e1178ec42f6ae6e39275a04234b0c7d73140f2a
 Image 1 (fdt@0)
  Description:  Flattened Device Tree blob
  Created:      Thu Sep 14 17:05:07 2017
  Type:         Flat Device Tree
  Compression:  uncompressed
  Data Size:    30150 Bytes = 29.44 kB = 0.03 MB
  Architecture: AArch64
  Hash algo:    sha1
  Hash value:   7f6bd3d535b8b214df392ffd6b2b2bcea058a485
 Image 2 (ramdisk@0)
  Description:  ramdisk
  Created:      Thu Sep 14 17:05:07 2017
  Type:         RAMDisk Image
  Compression:  uncompressed
  Data Size:    23563776 Bytes = 23011.50 kB = 22.47 MB
  Architecture: AArch64
  OS:           Linux
  Load Address: unavailable
  Entry Point:  unavailable
  Hash algo:    sha1
  Hash value:   c4f32910b03776481e2997e6e86a1a1d26f33a8f
 Default Configuration: 'conf@1'
 Configuration 0 (conf@1)
  Description:  Boot Linux kernel with FDT blob + ramdisk
  Kernel:       kernel@0
  Init Ramdisk: ramdisk@0
  FDT:          fdt@0

Dump Images

In the same way that FIT images are generated, the containing sub images can be extracted as well using dumpimage tool.
The image header files can be listed with the following command:
$ dumpimage -l image.itb
FIT description: U-Boot fitImage for plnx_aarch64 kernel
Created:         Thu Sep 14 17:05:07 2017
 Image 0 (kernel@0)
  Description:  Linux Kernel
  Created:      Thu Sep 14 17:05:07 2017
  Type:         Kernel Image
  Compression:  uncompressed
  Data Size:    12263936 Bytes = 11976.50 kB = 11.70 MB
  Architecture: AArch64
  OS:           Linux
  Load Address: 0x00080000
  Entry Point:  0x00080000
  Hash algo:    sha1
  Hash value:   7e1178ec42f6ae6e39275a04234b0c7d73140f2a
 Image 1 (fdt@0)
  Description:  Flattened Device Tree blob
  Created:      Thu Sep 14 17:05:07 2017
  Type:         Flat Device Tree
  Compression:  uncompressed
  Data Size:    30150 Bytes = 29.44 kB = 0.03 MB
  Architecture: AArch64
  Hash algo:    sha1
  Hash value:   7f6bd3d535b8b214df392ffd6b2b2bcea058a485
 Image 2 (ramdisk@0)
  Description:  ramdisk
  Created:      Thu Sep 14 17:05:07 2017
  Type:         RAMDisk Image
  Compression:  uncompressed
  Data Size:    23563776 Bytes = 23011.50 kB = 22.47 MB
  Architecture: AArch64
  OS:           Linux
  Load Address: unavailable
  Entry Point:  unavailable
  Hash algo:    sha1
  Hash value:   c4f32910b03776481e2997e6e86a1a1d26f33a8f
 Default Configuration: 'conf@1'
 Configuration 0 (conf@1)
  Description:  Boot Linux kernel with FDT blob + ramdisk
  Kernel:       kernel@0
  Init Ramdisk: ramdisk@0
  FDT:          fdt@0

An image can be extracted from the ITB using the following command: (X is the position of the image)
dumpimage -T flat_dt -p X -i image.itb outputfile
xir-psgpwts06:/home/ibaie/Workspace/Examples/mkimage/zcu102 $ dumpimage -T flat_dt -p 1 -i image.itb device-tree.dtb
Extracted:
 Image 1 (fdt@0)
  Description:  Flattened Device Tree blob
  Created:      Thu Sep 14 17:05:07 2017
  Type:         Flat Device Tree
  Compression:  uncompressed
  Data Size:    30150 Bytes = 29.44 kB = 0.03 MB
  Architecture: AArch64
  Hash algo:    sha1
  Hash value:   7f6bd3d535b8b214df392ffd6b2b2bcea058a485

Related Links