Using FIT image and Device Tree Overlays
Using FIT with overlays
Since U-boot 2018.07, released with linux4sam_6.0, we have the feature of adding Device Tree overlays to the base Device Tree at boot time, from U-boot. To achieve this, we use a FIT image, which embeds the Kernel + Device Tree blobs in a single file.
Device Tree Overlays
Device Tree Overlays are available in our repository at
Github. Compiling the Device Tree overlays with the corresponding kernel zImage results in a FIT image. The Makefile will do that for you.
Loading FIT image with U-boot
The FIT image is a placeholder that has the zImage and the base Device Tree, plus additional overlays that can be selected at boot time.
The following steps are required to boot the FIT Image from U-boot:
- Load the FIT image like you would normally load the uImage or zImage.
- There is no need to load additional Device Tree Blob, the FIT image includes it
- When booting the FIT image, specify the FIT configuration to use. Several configurations can be appended to the basic configuration, which we name 'kernel_dtb'
U-boot 2021.04 and newer cannot load FIT images created before linux4sam_2021.04. This is due to an incompatible change in the FIT image configuration check in U-boot.
Example:
bootm 0x24000000#kernel_dtb
This will load the FIT image from address 0x24000000 in memory and then run the configuration named 'kernel_dtb'. This configuration includes the kernel plus the base Device Tree Blob built with the kernel.
To load additional FIT configurations, just append another configuration to the command.
Example to load the image sensor controller Device Tree overlay + sensor omnivision 0v7740:
bootm 0x24000000#kernel_dtb#isc#ov7740
Example
Further more, if we inspect the U-boot environment (just an example)
The default U-boot environment adds loading commands for the screens TM7000, TM7000B, TM5000 and TM4300.
If you
have a different screen you need to similarly edit this environment and take your
specific screen into consideration.
=> print
at91_pda_detect=run pda4300test; run pda7000test; run pda7000btest; run pda5000test; run hdmi_test;
at91_prepare_bootargs=test -n $display_var && setenv bootargs ${bootargs} ${at91_video_bootargs}
at91_prepare_overlays_config=test -n $display_var && setenv at91_overlays_config '#'${display_var}
at91_prepare_video_bootargs=test -n $display_var && setenv at91_video_bootargs video=${video_mode}
at91_set_display=test -n $pda && setenv display $pda
baudrate=115200
bootargs=console=ttyS0,115200 root=/dev/mmcblk0p1 rw rootfstype=ext4 rootwait atmel.pm_modes=standby,ulp1
bootcmd=run at91_set_display; run at91_pda_detect; run at91_prepare_video_bootargs; run at91_prepare_bootargs; run at91_prepare_overlays_config; run bootcmd_boot;
bootcmd_boot=ext4load mmc 0 0x24000000 boot/sama5d2_xplained.itb; bootm 0x24000000#kernel_dtb${at91_overlays_config}
bootdelay=1
ethaddr=fc:c2:3d:0d:1f:4b
fdtcontroladdr=3fb773c8
hdmi_test=test -n $display && test $display = hdmi && setenv display_var 'hdmi' && setenv video_mode ${video_mode_hdmi}
pda4300test=test -n $display && test $display = 4300 && setenv display_var 'pda4' && setenv video_mode ${video_mode_pda4}
pda5000test=test -n $display && test $display = 5000 && setenv display_var 'pda5' && setenv video_mode ${video_mode_pda5}
pda7000btest=test -n $display && test $display = 7000B && setenv display_var 'pda7b' && setenv video_mode ${video_mode_pda7b}
pda7000test=test -n $display && test $display = 7000 && setenv display_var 'pda7' && setenv video_mode ${video_mode_pda7}
stderr=serial@f8020000
stdin=serial@f8020000
stdout=serial@f8020000
video_mode_hdmi=HDMI-A-1:1152x768-16
video_mode_pda4=Unknown-1:480x272-16
video_mode_pda5=Unknown-1:800x480-16
video_mode_pda7=Unknown-1:800x480-16
video_mode_pda7b=Unknown-1:800x480-16
We can see that the variable 'bootcmd_boot' loads the FIT image from SD-Card, and then it boots it with the 'kernel_dtb' configuration, plus an additional configuration for a
specific PDA if it's detected at boot-time
U-boot env explained
video_mode_hdmi=HDMI-A-1:1152x768-16
video_mode_pda4=Unknown-1:480x272-16
video_mode_pda5=Unknown-1:800x480-16
video_mode_pda7=Unknown-1:800x480-16
video_mode_pda7b=Unknown-1:800x480-16
These are hardcoded variables that are written by default in the u-boot env that comes with the release.
at91_set_display=test -n $pda && setenv display $pda
This command will test to see if U-boot detected any screen and set the 'display' variable accordingly.
at91_pda_detect=run pda4300test; run pda7000test; run pda7000btest; run pda5000test; run hdmi_test;
This command will run a test on the display variable for each possible screen that we have.
The tests are detailed below:
hdmi_test=test -n $display && test $display = hdmi && setenv display_var 'hdmi' && setenv video_mode ${video_mode_hdmi}
pda4300test=test -n $display && test $display = 4300 && setenv display_var 'pda4' && setenv video_mode ${video_mode_pda4}
pda5000test=test -n $display && test $display = 5000 && setenv display_var 'pda5' && setenv video_mode ${video_mode_pda5}
pda7000btest=test -n $display && test $display = 7000B && setenv display_var 'pda7b' && setenv video_mode ${video_mode_pda7b}
pda7000test=test -n $display && test $display = 7000 && setenv display_var 'pda7' && setenv video_mode ${video_mode_pda7}
These tests check for the 'display' variable and configure the video mode correctly and the 'display_var' . This display_var is the actual name of the screen configuration for the overlays, that we pass to the overlay configuration.
at91_prepare_video_bootargs=test -n $display_var && setenv at91_video_bootargs video=${video_mode}
This command will prepare the bootargs that we need to pass to the kernel in case we are using video.
at91_prepare_bootargs=test -n $display_var && setenv bootargs ${bootargs} ${at91_video_bootargs}
This command will actually append the video bootargs to our default bootargs if the display is detected. In case we do not have any display, bootargs is not modified.
at91_prepare_overlays_config=test -n $display_var && setenv at91_overlays_config '#'${display_var}
This command will configure an overlay name , with the appended '#' that we just need to append to the bootm FIT image booting sequence.
bootcmd=run at91_set_display; run at91_pda_detect; run at91_prepare_video_bootargs; run at91_prepare_bootargs; run at91_prepare_overlays_config; run bootcmd_boot;
The new bootcmd will first run all the display tests , in order, and then run a new bootcommand, bootcmd_boot
bootcmd_boot=ext4load mmc 0 0x24000000 boot/sama5d2_xplained.itb; bootm 0x24000000#kernel_dtb${at91_overlays_config}
This is the actual boot command, that will load the FIT image and add the configured overlays in the FIT boot sequence.
Extract parts of the FIT image with U-boot
With the use of the imxtract command in U-boot, we can extract parts of the FIT image into the memory and use them.
The imxtract command uses the syntax:
imxtract <FIT addr> <FIT subimage> <address in DRAM>
It will extract from the FIT image at
FIT addr the subimage named
FIT subimage and place it into the DRAM at
address in DRAM
To obtain information about which subimages are in a FIT image, use the
iminfo command .
Here is an example:
- Step 1: load the FIT from a hardware media, in this example mmc:
=> fatload mmc 1:1 0x24000000 sama5d2_xplained.itb;
4430768 bytes read in 305 ms (13.9 MiB/s)
- Step 2: Check possible images in this FIT we downloaded:
=> iminfo 0x24000000
## Checking Image at 24000000 ...
FIT image found
FIT description: Microchip SAMA5D2 Xplained FIT Image
Image 0 (kernel)
Description: Linux4SAM Linux kernel
Type: Kernel Image
Compression: uncompressed
Data Start: 0x240000e0
Data Size: 4360432 Bytes = 4.2 MiB
Architecture: ARM
OS: Linux
Load Address: 0x22000000
Entry Point: 0x22000000
Hash algo: crc32
Hash value: ed62149a
Hash algo: sha1
Hash value: 1cf2de3d85ee120240c0f2cb955327c607846a2c
Image 1 (base_fdt)
Description: Flattened Device Tree blob
Type: Flat Device Tree
Compression: uncompressed
Data Start: 0x24428afc
Data Size: 40797 Bytes = 39.8 KiB
Architecture: ARM
Load Address: 0x23000000
Hash algo: crc32
Hash value: 86179ff1
Hash algo: sha1
Hash value: 8a64ec5fc53f0a318c630387ed55e57f537b0061
Image 2 (fdt_isc)
Description: Device Tree blob ISC overlay
Type: Flat Device Tree
Compression: uncompressed
Data Start: 0x24432b64
Data Size: 1074 Bytes = 1 KiB
Architecture: ARM
Load Address: 0x23100000
Hash algo: crc32
Hash value: ea22f84e
Hash algo: sha1
Hash value: 6feab4a58949dd88593c8aba3ad6d73d8124403f
Image 3 (fdt_ov7670)
Description: Device Tree blob Ov7670 overlay
Type: Flat Device Tree
Compression: uncompressed
Data Start: 0x244330a4
Data Size: 2045 Bytes = 2 KiB
Architecture: ARM
Load Address: 0x23110000
Hash algo: crc32
Hash value: 44c22b8b
Hash algo: sha1
Hash value: 8e319fc07d00806b866bfe60b9b87849813ecefd
Image 4 (fdt_ov7740)
Description: Device Tree blob OV7740 overlay
Type: Flat Device Tree
Compression: uncompressed
Data Start: 0x244339b0
Data Size: 2045 Bytes = 2 KiB
Architecture: ARM
Load Address: 0x23120000
Hash algo: crc32
Hash value: cc72f933
Hash algo: sha1
Hash value: 3c44d90fe915d0e1fb63dfc50038fb0fc861b8a5
Image 5 (fdt_pda4)
Description: Device Tree blob pda4300 overlay
Type: Flat Device Tree
Compression: uncompressed
Data Start: 0x244342c0
Data Size: 4499 Bytes = 4.4 KiB
Architecture: ARM
Load Address: 0x23130000
Hash algo: crc32
Hash value: c9b532e8
Hash algo: sha1
Hash value: a7f75ea4a91884840d40b379e7b843a95b9b9da4
Image 6 (fdt_pda5)
Description: Device Tree blob pda5000 overlay
Type: Flat Device Tree
Compression: uncompressed
Data Start: 0x24435564
Data Size: 4499 Bytes = 4.4 KiB
Architecture: ARM
Load Address: 0x23140000
Hash algo: crc32
Hash value: 591d531b
Hash algo: sha1
Hash value: f9f3c25e8591f603492451b4e4eb369eba818ab2
Image 7 (fdt_pda7)
Description: Device Tree blob pda7000 overlay
Type: Flat Device Tree
Compression: uncompressed
Data Start: 0x24436808
Data Size: 4507 Bytes = 4.4 KiB
Architecture: ARM
Load Address: 0x23150000
Hash algo: crc32
Hash value: 3fc0c1ec
Hash algo: sha1
Hash value: d202bd4cc83aef48b33fae2a1b104c5bc597956c
Image 8 (fdt_pda7b)
Description: Device Tree blob pda7000b overlay
Type: Flat Device Tree
Compression: uncompressed
Data Start: 0x24437ab4
Data Size: 4507 Bytes = 4.4 KiB
Architecture: ARM
Load Address: 0x23160000
Hash algo: crc32
Hash value: a27df839
Hash algo: sha1
Hash value: 94f77b4afd7718cd309be34147c49753abf53375
Image 9 (fdt_i2s0_proto)
Description: Device Tree blob PROTO Audio board overlay
Type: Flat Device Tree
Compression: uncompressed
Data Start: 0x24438d6c
Data Size: 1066 Bytes = 1 KiB
Architecture: ARM
Load Address: 0x23170000
Hash algo: crc32
Hash value: 38a511f6
Hash algo: sha1
Hash value: 74d5c3996811a9307097969d8fe3c5e63b9973a0
Image 10 (fdt_qspi)
Description: Device Tree blob QSPI overlay
Type: Flat Device Tree
Compression: uncompressed
Data Start: 0x244392a4
Data Size: 461 Bytes = 461 Bytes
Architecture: ARM
Load Address: 0x23180000
Hash algo: crc32
Hash value: df13d1c0
Hash algo: sha1
Hash value: 0abdc429d44d5f0fc7f97bea47e5c58308e8c5b1
Default Configuration: 'kernel_dtb'
Configuration 0 (kernel_dtb)
Description: Linux kernel and base FDT blob for SAMA5D2_XPLAINED board
Kernel: kernel
FDT: base_fdt
Configuration 1 (base_dtb)
Description: Base FDT blob for SAMA5D2_XPLAINED board
Kernel: unavailable
FDT: base_fdt
Configuration 2 (isc)
Description: FDT overlay blob for isc
Kernel: unavailable
FDT: fdt_isc
Configuration 3 (ov7670)
Description: FDT overlay blob for ov7670 sensor
Kernel: unavailable
FDT: fdt_ov7670
Configuration 4 (ov7740)
Description: FDT overlay blob for ov7740 sensor
Kernel: unavailable
FDT: fdt_ov7740
Configuration 5 (pda4)
Description: FDT overlay blob for PDA TM4300 screen
Kernel: unavailable
FDT: fdt_pda4
Configuration 6 (pda5)
Description: FDT overlay blob for PDA TM5000 screen
Kernel: unavailable
FDT: fdt_pda5
Configuration 7 (pda7)
Description: FDT overlay blob for PDA TM7000 screen
Kernel: unavailable
FDT: fdt_pda7
Configuration 8 (pda7b)
Description: FDT overlay blob for PDA TM7000B screen
Kernel: unavailable
FDT: fdt_pda7b
Configuration 9 (i2s0_proto)
Description: FDT overlay blob for I2S0 PROTO audio board
Kernel: unavailable
FDT: fdt_i2s0_proto
Configuration 10 (qspi)
Description: FDT overlay blob for QSPI memory
Kernel: unavailable
FDT: fdt_qspi
## Checking hash(es) for FIT Image at 24000000 ...
Hash(es) for Image 0 (kernel): crc32+ sha1+
Hash(es) for Image 1 (base_fdt): crc32+ sha1+
Hash(es) for Image 2 (fdt_isc): crc32+ sha1+
Hash(es) for Image 3 (fdt_ov7670): crc32+ sha1+
Hash(es) for Image 4 (fdt_ov7740): crc32+ sha1+
Hash(es) for Image 5 (fdt_pda4): crc32+ sha1+
Hash(es) for Image 6 (fdt_pda5): crc32+ sha1+
Hash(es) for Image 7 (fdt_pda7): crc32+ sha1+
Hash(es) for Image 8 (fdt_pda7b): crc32+ sha1+
Hash(es) for Image 9 (fdt_i2s0_proto): crc32+ sha1+
Hash(es) for Image 10 (fdt_qspi): crc32+ sha1+
- Step 3: extract the kernel image, for example:
=> imxtract 0x24000000 kernel 0x21000000
## Copying 'kernel' subimage from FIT image at 24000000 ...
crc32+ sha1+ Loading part 0 ... OK
- Step 4: extract a base device tree , for example:
=> imxtract 0x24000000 base_fdt 0x22000000
## Copying 'base_fdt' subimage from FIT image at 24000000 ...
crc32+ sha1+ Loading part 186 ... OK
- Step 5: Boot the kernel with this device tree, for example:
=> bootz 0x21000000 - 0x22000000
## Flattened Device Tree blob at 22000000
Booting using the fdt blob at 0x22000000
Loading Device Tree to 3fb48000, end 3fb54f5c ... OK
Starting kernel ...
Booting Linux on physical CPU 0x0
Linux version 4.19.0+ (eugen@eh-station) (gcc version 7.3.1 20180425 [linaro-7.3-2018.05 revision d29120a424ecfbc167ef90065c0eeb7f91977701] (Linaro GCC 7.3-2018.05)) #6 Thu Nov 1 17:35:45 EET 2018
CPU: ARMv7 Processor [410fc051] revision 1 (ARMv7), cr=10c53c7d
....