U-Boot: Boot FIT Kernel Image
The way build ramdisk is not an option for me, load both uImage and ramdisk with U-Boot seems not a good way either, and as uImage is a legacy format, there should be a modern format, it is FIT image which is short for Flattened Image Trees, and it has been there for year, and have a handful of advantages over the legacy one, Joel A Fernandes made a presentation on this topic, you can find it on Embedded Linux Wiki.
Generate FIT Image
The components in FIT image are organized just like, device tree, to build it, a its (Image Source Tree) file is required, I took this example and made some changes to make kernel boot on mini2440, for more information regarding the its file, take a look at U-Boot new uImage source file format, this is the its I used for it:
/*
* U-Boot uImage source file with multiple kernels and ramdisks
*/
/dts-v1/;
/ {
description = "Various kernels and ramdisks";
#address-cells = <1>;
images {
kernel-1 {
description = "linux-5.9.11 debug version for mini2440";
data = /incbin/("./zImage.dbg");
type = "kernel";
arch = "arm";
os = "linux";
compression = "none";
load = <0x30008000>;
entry = <0x30008000>;
hash-1 {
algo = "md5";
};
hash-2 {
algo = "sha1";
};
};
kernel-2 {
description = "linux-5.9.11 mini2440";
data = /incbin/("./zImage");
type = "kernel";
arch = "arm";
os = "linux";
compression = "none";
load = <0x30008000>;
entry = <0x30008000>;
hash-1 {
algo = "sha1";
};
};
ramdisk-1 {
description = "cpio ramdisk for mini2440";
data = /incbin/("./ramdisk.cpio.img");
type = "ramdisk";
arch = "arm";
os = "linux";
compression = "none";
load = <0x33000000>;
entry = <0x33000000>;
hash-1 {
algo = "sha1";
};
};
};
configurations {
default = "config-1";
config-1 {
description = "mini2440 5.9.11 debug configuration";
kernel = "kernel-1";
ramdisk = "ramdisk-1";
};
config-2 {
description = "mini2440 5.9.11 configuration";
kernel = "kernel-2";
ramdisk = "ramdisk-1";
};
};
};
We have zImage, ramdisk, and its file, the FIT image can be generated with mkimage, put them in the same directory and create the final image with:
$ mkimage -f kernel.its kernel.itb
FIT description: Various kernels and ramdisks
Created: Fri Jan 1 21:16:17 2021
Image 0 (kernel-1)
Description: linux-5.9.11 debug version for mini2440
Created: Fri Jan 1 21:16:17 2021
Type: Kernel Image
Compression: uncompressed
Data Size: 2353560 Bytes = 2298.40 KiB = 2.24 MiB
Architecture: ARM
OS: Linux
Load Address: 0x30008000
Entry Point: 0x30008000
Hash algo: md5
Hash value: a15208f937b196988b77ca51eab8f42e
Hash algo: sha1
Hash value: de0b5302fee57763a95e1daf0c8aa52af1f41b96
Image 1 (kernel-2)
Description: linux-5.9.11 mini2440
Created: Fri Jan 1 21:16:17 2021
Type: Kernel Image
Compression: uncompressed
Data Size: 2254480 Bytes = 2201.64 KiB = 2.15 MiB
Architecture: ARM
OS: Linux
Load Address: 0x30008000
Entry Point: 0x30008000
Hash algo: sha1
Hash value: f4cff2995aff1220848ba39c96d928ab2bdac55a
Image 2 (ramdisk-1)
Description: cpio ramdisk for mini2440
Created: Fri Jan 1 21:16:17 2021
Type: RAMDisk Image
Compression: uncompressed
Data Size: 2691561 Bytes = 2628.48 KiB = 2.57 MiB
Architecture: ARM
OS: Linux
Load Address: 0x33000000
Entry Point: 0x33000000
Hash algo: sha1
Hash value: 4ed9e3ae849eb9fcaeb59d219b74f9d82c64d780
Default Configuration: 'config-1'
Configuration 0 (config-1)
Description: mini2440 5.9.11 debug configuration
Kernel: kernel-1
Init Ramdisk: ramdisk-1
Configuration 1 (config-2)
Description: mini2440 5.9.11 configuration
Kernel: kernel-2
Init Ramdisk: ramdisk-1
The components packed into the FIT image can be extracted with dumpimage
, for
example to extract the first file:
$ dumpimage -T flat_dt -p 0 kernel.itb -o zImage.dbg
Use the -p
option to specify the index of the image you wanna extract, the index
in the FIT image can be examined with -l
option:
$ dumpimage -l kernel.itb
Boot FIT Kernel Image with bootm
To boot FIT kernel image with U-Boot, FIT supported is mandatory, build U-Boot with below configs:
+CONFIG_FIT=y
+CONFIG_FIT_VERBOSE=y
Download and boot kernel with:
MINI2440 # tftp 30800000 kernel.itb
MINI2440 # bootm 30800000
This will boot with the default configuration, which is config-1
.
Boot other kernel image is also supported by bootm:
MINI2440 # bootm 30800000#config-1
MINI2440 # bootm :kernel-2 :ramdisk-1
MINI2440 # bootm 30800000:kernel-1 30800000:ramdisk-1
MINI2440 # bootm 30800000:kernel-1 :ramdisk-1
More combinations can be found in Command syntax extensions for the new uImage format.
The image info can be inspected with iminfo
, for example:
MINI2440 # iminfo 0x30800000
## Checking Image at 30800000 ...
FIT image found
FIT description: Various kernels and ramdisks
Image 0 (kernel-1)
Description: linux-5.9.11 debug version for mini2440
Type: Kernel Image
Compression: uncompressed
Data Start: 0x308000e8
Data Size: 2353560 Bytes = 2.2 MiB
Architecture: ARM
OS: Linux
Load Address: 0x30008000
Entry Point: 0x30008000
Hash algo: md5
Hash value: a15208f937b196988b77ca51eab8f42e
Hash algo: sha1
Hash value: de0b5302fee57763a95e1daf0c8aa52af1f41b96
[...]
## Checking hash(es) for FIT Image at 30800000 ...
Hash(es) for Image 0 (kernel-1): md5+ sha1+
Hash(es) for Image 1 (kernel-2): sha1+
Hash(es) for Image 2 (ramdisk-1): sha1+
Troubleshooting
Could not find configuration node
MINI2440 # tftp 30800000 kernel.itb
dm9000 i/o: 0x20000000, id: 0x90000a46
DM9000: running in 16 bit mode
MAC: 0c:96:e6:15:09:12
could not establish link
Using dm9000 device
TFTP from server 192.168.0.3; our IP address is 192.168.0.89
Filename 'kernel.itb'.
## Current stack ends at 0x33bbcc40 Load address: 0x30800000
Loading: #T ################################################################
[...]
##############################################################
790 KiB/s
done
Bytes transferred = 7301836 (6f6acc hex)
MINI2440 # bootm 30800000
## Current stack ends at 0x33bbccf0 ## Loading kernel from FIT Image at 30800000 ...
Could not find configuration node
ERROR: can't get kernel image!
Fixed by removing FIT_BEST_MATCH
in default config file.
Wrong Ramdisk Image Format
MINI2440 # bootm 30800000:kernel-1 33000000:ramdisk-1
## Current stack ends at 0x33bbccf0 ## Loading kernel from FIT Image at 30800000 ...
Trying 'kernel-1' kernel subimage
Description: linux-5.9.11 debug version for mini2440
Type: Kernel Image
Compression: uncompressed
Data Start: 0x308000e8
Data Size: 2353560 Bytes = 2.2 MiB
Architecture: ARM
OS: Linux
Load Address: 0x30008000
Entry Point: 0x30008000
Hash algo: md5
Hash value: a15208f937b196988b77ca51eab8f42e
Hash algo: sha1
Hash value: de0b5302fee57763a95e1daf0c8aa52af1f41b96
Verifying Hash Integrity ... md5+ sha1+ OK
Wrong Ramdisk Image Format
Ramdisk image is corrupt or invalid
This is because the ramdisk does not exist at that address:
MINI2440 # iminfo 33000000
## Checking Image at 33000000 ...
Unknown image format!