[uboot] uboot startup kernel (a) - Legacy-uImage & FIT-uImage

First, uImage

After compiling the kernel, an Image or a compressed zImage is generated. However, the format of these two images does not provide enough information for uboot to perform load, jump or verification operations. Therefore, uboot provides the mkimage tool to make the kernel a format that uboot can recognize, and the generated file is called uImage. Uboot supports two types of uImage.

  • Legacy-uImageBased on the kernel image, plus 64 bytes of information is provided to uboot.

  • FIT-uImagePacks kernel, fdt, ramdisk, etc. into an image file in a way similar to FDT, plus some required information (attributes). As long as uboot obtains the image file, it can get the specific information and content of the kernel, fdt, ramdisk and so on.

The Legacy-uImage implementation is simpler and has a smaller length. However, it is actually more troublesome to use, and you need to add the loading information of fdt and ramdisk in the command to start the kernel. The FIT-uImage implementation is more complicated, but it is simpler to use and has better compatibility (can be compatible with multiple configurations). But the extra information needed is longer.

Second, Legacy-uImage

1, enable the macro you need to open

CONFIG_IMAGE_FORMAT_LEGACY=y

Note that this macro is automatically configured in the auto-generated autoconf.mk and does not require additional configuration.

2, how to make & use

(1) tool mkimage After compiling uboot, the mkimage executable file will be generated in the uboot tools directory. (2) order

Mkimage -A arm -O linux -C none -T kernel -a 0x20008000 -e 0x20008040 -n Linux_Image -d zImage uImage

The meaning of each parameter is as follows
Usage: mkimage -l image
          -l ==> list image header information
       Mkimage [-x] -A arch -O os -T type -C comp -a addr -e ep -n name -d data_file[:data_file...] image
          -A ==> set architecture to 'arch' // system
          -O ==> set operating system to 'os' // operating system
          -T ==> set image type to 'type' // image type
          -C ==> set compression type 'comp' // compression type
          -a ==> set load address to 'addr' (hex) // load address
          -e ==> set entry point to 'ep' (hex) // entry address
          -n ==> set image name to 'name' // image name, note that it cannot exceed 32B
          -d ==> use image data from 'datafile' // input file
          -x ==> set XIP (execute in place)

(3) use Download the generated Legacy-uImage to the load address specified in the parameter and use the bootm ‘actual load address’ command to jump to the kernel. Note, however, that if you use Legacy-uImage, you will need to keep up with the ram address of the file system and the ram address of dtb, otherwise bootm may fail. The format is as follows:

Bootm Legacy-uImage load address ramdisk load address dtb load address

3, the difference between zImage and zImage

-rw-rw-rw-  1 hlos hlos 1560120 Dec  5 14:46 uImage
-rwxrwxrwx  1 hlos hlos 1560056 Nov 30 15:42 zImage*

It can be seen that uImage is 64 bytes more than zImage. By comparison, it can be found that the 64Byte data is loaded in the head of zImage. View the 64Byte data directly, and view it as follows through the od command:

[email protected]:boot$ od -tx1 -tc -Ax -N64 uImage
000000  27  05  19  56  5a  f3  f7  8e  58  45  0d  3d  00  17  cd  f8
         ' 005 031   V   Z 363 367 216   X   E  \r   =  \0 027 315 370
000010  20  00  80  00  20  00  80  40  e2  4b  43  b6  05  02  02  00
            \0 200  \0      \0 200   @ 342   K   C 266 005 002 002  \0
000020  4c  69  6e  75  78  5f  49  6d  61  67  65  00  00  00  00  00
         L   i   n   u   x   _   I   m   a   g   e  \0  \0  \0  \0  \0
000030  00  00  00  00  00  00  00  00  00  00  00  00  00  00  00  00
        \0  \0  \0  \0  \0  \0  \0  \0  \0  \0  \0  \0  \0  \0  \0  \0

Legacy-uImage adds a 64-byte header to the zImage. The following data is parsed by the header data structure of Legacy-uImage.

4, format header description

Uboot uses image_header to represent the head of Legacy-uImage

Typedef struct image_header {
    __be32 ih_magic; /* Image Header Magic Number */ // Magic number header used to check if it is a Legacy-uImage
    __be32 ih_hcrc; /* Image Header CRC Checksum */ // Header CRC check value
    __be32 ih_time; /* Image Creation Timestamp */ // Timestamp created by image
    __be32 ih_size; /* Image Data Size */ // Mirror data length
    __be32 ih_load; /* Data Load Address */ // load address
    __be32 ih_ep; /* Entry Point Address */ // Entry Address
    __be32 ih_dcrc; /* Image Data CRC Checksum */ // Mirrored CRC check
    Uint8_t ih_os; /* Operating System */ // Operating system type
    Uint8_t ih_arch; /* CPU architecture */ // system
    Uint8_t ih_type; /* Image Type */ // Mirror type
    Uint8_t ih_comp; /* Compression Type */ // Compression type
    Uint8_t ih_name[IH_NMLEN]; /* Image Name */ // Image name
} image_header_t;
#define IH_NMLEN 32 /* Image Name Length */

You can find that this header is 64Byte. Explain this data structure according to the above 3

  • Ih_magic 27 05 19 56 The head magic number is used to determine if this is the head of the Legacy-uImage. 0x27051956 means it is a Legacy-uImage.
  • Ih_size 00 17 cd f8 Data mirror length. Here is 0x17cdf8, which is 1560056, which is the same length as the zImage we measured earlier.
  • Ih_load 20 00 80 00 The load address, which is 0x20008000, is consistent with the parameters we use to execute mkimage.
  • Ih_ep 20 00 80 40 The entry address, which is 0x20008040, is consistent with the parameters we use to execute mkimage.

Third, FIT-uImage

0, principle description

Flattened image tree, similar to an implementation mechanism of FDT (flattened device tree). It combines some of the images that need to be used (such as kernel, dtb, and file system) with a certain syntax and format to generate an image file. It mainly uses four components.

  • Its file Image source file, similar to the dts file, is responsible for describing the information of the image to be claimed. Need to construct by yourself.
  • Itb file The resulting image file, similar to the dtb file, is the FIT-uImage that uboot can directly identify and parse.
  • Mkimage Mkimage is responsible for the role of dtc, used to parse its file, get the corresponding image, and finally generate an itb file that uboot can directly identify and parse.
  • Image data file The image file actually used.

Mkimage packs its file and its corresponding image data file into an itb file, which is the image file (FIT-uImage) that uboot can recognize. We will download this file into the memory and execute it using the bootm command.

1, enable the macro you need to open

CONFIG_FIT=y

2, how to make & use

(1) its file production Because mkimage is based on the description in its file to package the image to generate the itb file (FIT-uImage), so you first need to make a its file, in its file describes the image that needs to be packaged, mainly the kernel image, dtb file, ramdisk image . A simple example is as follows:

/*
 * U-Boot uImage source file for "X project"
 */

/dts-v1/;

/ {
    description = "U-Boot uImage source file for X project";
    #address-cells = <1>;

    images {
        [email protected] {
            description = "Unify(TODO) Linux kernel for project-x";
            data = /incbin/("/home/hlos/code/xys/temp/project-x/build/out/linux/arch/arm/boot/zImage");
            type = "kernel";
            arch = "arm";
            os = "linux";
            compression = "none";
            load = <0x20008000>;
            entry = <0x20008000>;
        };
        [email protected] {
            description = "Flattened Device Tree blob for project-x";
            data = /incbin/("/home/hlos/code/xys/temp/project-x/build/out/linux/arch/arm/boot/dts/s5pv210-tiny210.dtb");
            type = "flat_dt";
            arch = "arm";
            compression = "none";
        };
        [email protected] {
            description = "Ramdisk for project-x";
            data = /incbin/("/home/hlos/code/xys/temp/project-x/build/out/rootfs/initramfs.gz");
            type = "ramdisk";
            arch = "arm";
            os = "linux";
            compression = "gzip";
        };
    };

    configurations {
        default = "[email protected]";
        [email protected] {
            description = "Boot Linux kernel with FDT blob";
            kernel = "[email protected]";
            fdt = "[email protected]";
            ramdisk = "[email protected]";
        };
    };
};
  • The grammar can refer to the introduction of u-boot FIT image of Wowo Technology.Note that there can be multiple kernel nodes or fdt nodes, etc., which is more compatible. At the same time, there are a variety of configurations to combine kernel, fdt, and ramdisk to make FIT-uImage compatible with multiple boards without having to recompile.

(2) Generate FIT-uImage The generated command is relatively simpler than the Legacy-uImage because the information is described in its file.

Mkimage -f ITS file The ITB file to be generated is as follows:
${UBOOT_OUT_DIR}/tools/mkimage -f ${UIMAGE_ITS_FILE} ${UIMAGE_ITB_FILE}

Finally, xprj_uImage.itb is generated on the project X project, which is the FIT-uImage file we need.

(3) use Download the generated FIT-uImage to the load address specified in the parameter and use the bootm ‘actual load address’ command to jump to the kernel. Uboot will automatically parse out the information of FIT-uImage, kernel, ramdisk, dtb, which is quite convenient to use.

3, a brief description

The format of FIT-uImage is similar to DTB. Uboot will parse the configuration node in FIT-uImage and select the required kernel, dtb, rootfs according to the node. Therefore, on the basis of the node, add a lot of node information to provide uboot use.