Flattened Image Tree Specification v0.8-11-gc749139

Copyright

Copyright 2008 Marian Balakowicz <m8@semihalf.com>
Copyright 2008 Bartlomiej Sieka <tur@semihalf.com>
Copyright 2022 Simon Glass <sjg@chromium.com>

THIS SPECIFICATION PROVIDED “AS IS” AND WITHOUT ANY WARRANTY OF ANY KIND, INCLUDING, WITHOUT LIMITATION, ANY EXPRESS OR IMPLIED WARRANTY OF NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL LINARO OR ANY MEMBER OF LINARO BE LIABLE FOR ANY DIRECT, INDIRECT, SPECIAL, EXEMPLARY, PUNITIVE, OR CONSEQUENTIAL DAMAGES, INCLUDING, WITHOUT LIMITATION, LOST PROFITS, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.

Questions pertaining to this document, or the terms or conditions of its provision, should be addressed to:

Open Source Firmware Foundation
530 Lawrence Expy
PMB 992
Sunnyvale, CA 94085
United States

License Information

Licensed under the Apache License, Version 2.0 (the “License”); you may not use this file except in compliance with the License. You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an “AS IS” BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.

Acknowledgements

FIT (Flattened Image Tree) was developed in 2008 by Marian Balakowicz and Bartlomiej Sieka of Semihalf, under the guidance of Wolfgang Denk, founder of Denx Software Engineering and creator of U-Boot.

Since then, FIT has been maintained and extended by the U-Boot community to deal with the developing needs of Open Source firmware.

This specification builds on this previous work.

FIT has stood the test of time due to its simplicity and extensibility. This specification aims to build on this work and provide a means for further improvement with a wider group of collaborators.

Revision History

Table 1 Revision History

Revision

Date

Description

0.8

2023-AUG-9

Initial prerelease version. Imported text from U-Boot source tree.

1. Introduction

1.1. Purpose and Scope

The number of elements playing a role in the kernel booting process has increased over time and now typically includes the devicetree, kernel image and possibly a ramdisk image. Generally, all must be placed in the system memory and booted together.

For firmware images a similar process has taken place, with various binaries loaded at different addresses, such as ARM’s ATF, OpenSBI, FPGA and U-Boot itself.

FIT provides a flexible and extensible format to deal with this complexity. It provides support for multiple components. It also supports multiple configurations, so that the same FIT can be used to boot multiple boards, with some components in common (e.g. kernel) and some specific to that board (e.g. devicetree).

This specification, the Flattened Image Tree Specification (FITSpec), provides a suitable format which can be used to describe any set of files along with grouping and selection mechanisms.

  • Chapter 1 introduces the purpose and background of FITSpec.

  • Chapter 2 introduces the FIT concept and describes its logical structure and standard properties. certain classes of devices and specific device types.

  • Chapter 3 describes how FIT is used in bootloaders to handle booting Operating Systems as well as firmware.

Conventions Used in this Document

The word shall is used to indicate mandatory requirements strictly to be followed in order to conform to the standard and from which no deviation is permitted (shall equals is required to).

The word should is used to indicate that among several possibilities one is recommended as particularly suitable, without mentioning or excluding others; or that a certain course of action is preferred but not necessarily required; or that (in the negative form) a certain course of action is deprecated but not prohibited (should equals is recommended that).

The word may is used to indicate a course of action permissible within the limits of the standard (may equals is permitted).

Examples of devicetree constructs are frequently shown in Devicetree Syntax form. See [dtspec] for a description of this.

1.2. Relationship to Devicetree Specification

FITSpec is based on the Devicetree Specification, in that it uses the same structure and shares some concepts.

1.3. 32-bit and 64-bit Support

The FITSpec supports CPUs with both 32-bit and 64-bit addressing capabilities. Where applicable, sections of the FITSpec describe any requirements or considerations for 32-bit and 64-bit addressing.

1.4. Definition of Terms

DTB

Devicetree blob. Compact binary representation of the devicetree.

DTC

Devicetree compiler. An open source tool used to create DTB files from DTS files.

DTS

Devicetree syntax. A textual representation of a devicetree consumed by the DTC. See Appendix A Devicetree Source Format (version 1).

2. Flattened Image Tree (FIT) Format

2.1. Introduction

FIT consists of a devicetree blob with nodes and properties following a certain schema. Therefore this document defines FIT by providing FDT (Flat Device Tree) bindings. These describe the final form of the FIT at the moment when it is used. The user perspective may be simpler, as some of the properties (like timestamps and hashes) are filled in automatically by available tooling, such as mkimage.

To avoid confusion with the index:kernel FDT <pair: kernel; FDT> the following naming convention is used:

FIT

Flattened Image Tree

FIT is formally a flattened devicetree (in the libfdt meaning), which conforms to bindings defined in this document.

.its

image tree source

.fit

flattened image tree blob

This was previously known as .itb but has been renamed to .fit.

2.1.1. Image-building procedure

The following picture shows how the FIT is prepared. Input consists of image source file (.its) and a set of data files. Image is created with the help of standard U-Boot mkimage tool which in turn uses dtc (device tree compiler) to produce image tree blob (.fit). The resulting .fit file is the actual binary of a new FIT:

tqm5200.its
+
vmlinux.bin.gz     mkimage + dtc               xfer to target
eldk-4.2-ramdisk  --------------> tqm5200.fit --------------> boot
tqm5200.dtb                          /|\
                                      |
                                 'new FIT'

Steps:

  1. Create .its file, automatically filled-in properties are omitted

  2. Call mkimage tool on .its file

  3. mkimage calls dtc to create .fit image and assures that missing properties are added

  4. .fit (new FIT) is uploaded onto the target and used therein

2.1.2. Unique identifiers

To identify FIT sub-nodes representing images, hashes, configurations (which are defined in the following sections), the “unit name” of the given sub-node is used as it’s identifier as it assures uniqueness without additional checking required.

2.1.3. External data

FIT is normally built initially with image data in the ‘data’ property of each image node. It is also possible for this data to reside outside the FIT itself. This allows the ‘FDT’ part of the FIT to be quite small, so that it can be loaded and scanned without loading a large amount of data. Then when an image is needed it can be loaded from an external source.

External FITs use ‘data-offset’ or ‘data-position’ instead of ‘data’.

The mkimage tool can convert a FIT to use external data using the -E argument, optionally using -p to specific a fixed position.

It is often desirable to align each image to a block size or cache-line size (e.g. 512 bytes), so that there is no need to copy it to an aligned address when reading the image data. The mkimage tool provides a -B argument to support this.

2.2. Root-node properties

The root node of the FIT should have the following layout:

/ o image-tree
    |- description = "image description"
    |- timestamp = <12399321>
    |- #address-cells = <1>
    |
    o images
    | |
    | o image-1 {...}
    | o image-2 {...}
    | ...
    |
    o configurations
      |- default = "conf-1"
      |
      o conf-1 {...}
      o conf-2 {...}
      ...

2.2.1. Optional property

description

Textual description of the FIT

2.2.2. Mandatory property

timestamp

Last image modification time being counted in seconds since 1970-01-01 00:00:00 - to be automatically calculated by mkimage tool.

2.2.3. Conditionally mandatory property

#address-cells

Number of 32bit cells required to represent entry and load addresses supplied within sub-image nodes. May be omitted when no entry or load addresses are used.

2.2.4. Mandatory nodes

images

This node contains a set of sub-nodes, each of them representing single component sub-image (like kernel, ramdisk, etc.). At least one sub-image is required.

configurations

Contains a set of available configuration nodes and defines a default configuration.

2.3. ‘/images’ node

This node is a container node for component sub-image nodes. Each sub-node of the ‘/images’ node should have the following layout:

o image-1
    |- description = "component sub-image description"
    |- data = /incbin/("path/to/data/file.bin")
    |- type = "sub-image type name"
    |- arch = "ARCH name"
    |- os = "OS name"
    |- compression = "compression name"
    |- load = <00000000>
    |- entry = <00000000>
    |
    o hash-1 {...}
    o hash-2 {...}
    ...

2.3.1. Mandatory properties

description

Textual description of the component sub-image

type

Name of component sub-image type. Supported types are:

Sub-image type

Meaning

invalid

Invalid Image

aisimage

Davinci AIS image

atmelimage

ATMEL ROM-Boot Image

copro

Coprocessor Image

fdt_legacy

legacy Image with Flat Device Tree

filesystem

Filesystem Image

firmware

Firmware

firmware_ivt

Firmware with HABv4 IVT

flat_dt

Flat Device Tree

fpga

FPGA Device Image (bitstream file, vendor specific)

gpimage

TI Keystone SPL Image

imx8image

NXP i.MX8 Boot Image

imx8mimage

NXP i.MX8M Boot Image

imximage

Freescale i.MX Boot Image

kernel

Kernel Image

kernel_noload

Kernel Image (no loading done)

kwbimage

Kirkwood Boot Image

lpc32xximage

LPC32XX Boot Image

mtk_image

MediaTek BootROM loadable Image

multi

Multi-File Image

mxsimage

Freescale MXS Boot Image

omapimage

TI OMAP SPL With GP CH

pblimage

Freescale PBL Boot Image

pmmc

TI Power Management Micro-Controller Firmware

ramdisk

RAMDisk Image

rkimage

Rockchip Boot Image

rksd

Rockchip SD Boot Image

rkspi

Rockchip SPI Boot Image

script

Script

socfpgaimage

Altera SoCFPGA CV/AV preloader

socfpgaimage_v1

Altera SoCFPGA A10 preloader

spkgimage

Renesas SPKG Image

standalone

Standalone Program

stm32image

STMicroelectronics STM32 Image

sunxi_egon

Allwinner eGON Boot Image

sunxi_toc0

Allwinner TOC0 Boot Image

tee

Trusted Execution Environment Image

ublimage

Davinci UBL image

vybridimage

Vybrid Boot Image

x86_setup

x86 setup.bin

zynqimage

Xilinx Zynq Boot Image

zynqmpbif

Xilinx ZynqMP Boot Image (bif)

zynqmpimage

Xilinx ZynqMP Boot Image

compression

Compression used by included data. If no compression is used, the compression property should be set to “none”. If the data is compressed but it should not be uncompressed by the loader (e.g. compressed ramdisk <pair: ramdisk; compressed), this should also be set to “none”.

Supported compression types are:

Compression type

Meaning

none

uncompressed

bzip2

bzip2 compressed

gzip

gzip compressed

lz4

lz4 compressed

lzma

lzma compressed

lzo

lzo compressed

zstd

zstd compressed

2.3.2. Conditionally mandatory property

data

Path to the external file which contains this node’s binary data. Within the FIT this is the contents of the file. This is mandatory unless external data is used.

data-size

size of the data in bytes. This is mandatory if external data is used.

data-offset

Offset of the data in a separate image store. The image store is placed immediately after the last byte of the device tree binary, aligned to a 4-byte boundary. This is mandatory if external data is used, with an offset.

data-position

Machine address at which the data is to be found. This is a fixed address not relative to the loading of the FIT. This is mandatory if external data is used with a fixed address.

os

OS name, mandatory for types “kernel”. Valid OS names are:

OS name

Meaning

invalid

Invalid OS

4_4bsd

4_4BSD

arm-trusted-firmware

ARM Trusted Firmware

dell

Dell

efi

EFI Firmware

esix

Esix

freebsd

FreeBSD

integrity

INTEGRITY

irix

Irix

linux

Linux

ncr

NCR

netbsd

NetBSD

openbsd

OpenBSD

openrtos

OpenRTOS

opensbi

RISC-V OpenSBI

ose

Enea OSE

plan9

Plan 9

psos

pSOS

qnx

QNX

rtems

RTEMS

sco

SCO

solaris

Solaris

svr4

SVR4

tee

Trusted Execution Environment

u-boot

U-Boot

vxworks

VxWorks

arch

Architecture name, mandatory for types: “standalone”, “kernel”, “firmware”, “ramdisk” and “fdt”. Valid architecture names are:

Architecture type

Meaning

invalid

Invalid ARCH

alpha

Alpha

arc

ARC

arm64

AArch64

arm

ARM

avr32

AVR32

blackfin

Blackfin

ia64

IA64

m68k

M68K

microblaze

MicroBlaze

mips64

MIPS 64 Bit

mips

MIPS

nds32

NDS32

nios2

NIOS II

or1k

OpenRISC 1000

powerpc

PowerPC

ppc

PowerPC

riscv

RISC-V

s390

IBM S390

sandbox

Sandbox

sh

SuperH

sparc64

SPARC 64 Bit

sparc

SPARC

x86_64

AMD x86_64

x86

Intel x86

xtensa

Xtensa

entry

entry point address, address size is determined by ‘#address-cells’ property of the root node. Mandatory for types: “firmware”, and “kernel”.

load

load address, address size is determined by ‘#address-cells’ property of the root node. Mandatory for types: “firmware”, and “kernel”.

compatible

compatible method for loading image. Mandatory for types: “fpga”, and images that do not specify a load address. Supported compatible methods:

Compatible string

Meaning

u-boot,fpga-legacy

Generic fpga loading routine.

u-boot,zynqmp-fpga-ddrauth

Signed non-encrypted FPGA bitstream for Xilinx Zynq UltraScale+ (ZymqMP) device.

u-boot,zynqmp-fpga-enc

Encrypted FPGA bitstream for Xilinx Zynq UltraScale+ (ZynqMP) device.

Note For fdt images, the node should not have a compatible for the model. The compatible here is not derived from the fdt, nor is it used to identify the fdt. Such usage belongs in the configuration node.

phase

U-Boot phase for which the image is intended.

“spl”

image is an SPL image

“u-boot”

image is a U-Boot image

Optional nodes:

hash-1

Each hash sub-node represents separate hash or checksum calculated for node’s data according to specified algorithm.

signature-1

Each signature sub-node represents separate signature calculated for node’s data according to specified algorithm.

2.4. Hash nodes

o hash-1
    |- algo = "hash or checksum algorithm name"
    |- value = [hash or checksum value]

2.4.1. Mandatory properties

algo

Algorithm name. Supported algoriths and their value sizes are:

Sub-image type

Size (bytes)

Meaning

crc16-ccitt

2

Cyclic Redundancy Check 16-bit (Consultative Committee for International Telegraphy and Telephony)

crc32

4

Cyclic Redundancy Check 32-bit

md5

16

Message Digest 5 (MD5)

sha1

20

Secure Hash Algorithm 1 (SHA1)

sha256

32

Secure Hash Algorithm 2 (SHA256)

sha384

48

Secure Hash Algorithm 2 (SHA384)

sha512

64

Secure Hash Algorithm 2 (SHA512)

value

Actual checksum or hash value.

2.5. Image-signature nodes

o signature-1
    |- algo = "algorithm name"
    |- key-name-hint = "key name"
    |- value = [hash or checksum value]

2.5.1. Mandatory properties

FIT Algorithm:

algo

Algorithm name. Supported algorithms and their value sizes are shown below. Note that the hash is specified separately from the signing algorithm, so it is possible to mix and match any SHA algorithm with any signing algorithm. The size of the signature relates to the signing algorithm, not the hash, since it is the hash that is signed.

Sub-image type

Size (bytes)

Meaning

sha1,rsa2048

256

SHA1 hash signed with 2048-bit Rivest–Shamir–Adleman algorithm

sha1,rsa3072

384

SHA1 hash signed with 2048-bit RSA

sha1,rsa4096

512

SHA1 hash signed with 2048-bit RSA

sha1,ecdsa256

32

SHA1 hash signed with 256-bit Elliptic Curve Digital Signature Algorithm

sha256,…

sha384,…

sha512,…

key-name-hint

Name of key to use for signing. The keys will normally be in a single directory (parameter -k to mkimage). For a given key <name>, its private key is stored in <name>.key and the certificate is stored in <name>.crt.

sign-images

A list of images to sign, each being a property of the conf node that contains then. The default is “kernel,fdt” which means that these two images will be looked up in the config and signed if present. This is used by mkimage to determine which images to sign.

The following properies are added as part of signing, and are mandatory:

value

Actual signature value. This is added by mkimage.

hashed-nodes

A list of nodes which were hashed by the signer. Each is a string - the full path to node. A typical value might be:

hashed-nodes = "/", "/configurations/conf-1", "/images/kernel",
    "/images/kernel/hash-1", "/images/fdt-1",
    "/images/fdt-1/hash-1";
hashed-strings

The start and size of the string region of the FIT that was hashed. The start is normally 0, indicating the first byte of the string table. The size indicates the number of bytes hashed as part of signing.

The following properies are added as part of signing, and are optional:

timestamp

Time when image was signed (standard Unix time_t format)

signer-name

Name of the signer (e.g. “mkimage”)

signer-version

Version string of the signer (e.g. “2013.01”)

comment

Additional information about the signer or image

padding

The padding algorithm, it may be pkcs-1.5 or pss, if no value is provided we assume pkcs-1.5

2.6. ‘/configurations’ node

The ‘configurations’ node creates convenient, labeled boot configurations, which combine together kernel images with their ramdisks and fdt blobs.

The ‘configurations’ node has the following structure:

o configurations
    |- default = "default configuration sub-node unit name"
    |
    o config-1 {...}
    o config-2 {...}
    ...

2.6.1. Optional property

default

Selects one of the configuration sub-nodes as a default configuration.

2.6.2. Mandatory nodes

configuration-sub-node-unit-name

At least one of the configuration sub-nodes is required.

2.6.3. Optional nodes

signature-1

Each signature sub-node represents separate signature calculated for the configuration according to specified algorithm.

2.7. Configuration nodes

Each configuration has the following structure:

o config-1
    |- description = "configuration description"
    |- kernel = "kernel sub-node unit name"
    |- fdt = "fdt sub-node unit-name" [, "fdt overlay sub-node unit-name", ...]
    |- loadables = "loadables sub-node unit-name"
    |- script = "
    |- compatible = "vendor,board-style device tree compatible string"
    o signature-1 {...}

2.7.1. Mandatory properties

description

Textual configuration description.

kernel or firmware

Unit name of the corresponding kernel or firmware (u-boot, op-tee, etc) image. If both “kernel” and “firmware” are specified, control is passed to the firmware image.

2.7.2. Optional properties

fdt

Unit name of the corresponding fdt blob (component image node of a “fdt type”). Additional fdt overlay nodes can be supplied which signify that the resulting device tree blob is generated by the first base fdt blob with all subsequent overlays applied.

fpga

Unit name of the corresponding fpga bitstream blob (component image node of a “fpga type”).

loadables

Unit name containing a list of additional binaries to be loaded at their given locations. “loadables” is a comma-separated list of strings. U-Boot will load each binary at its given start-address and may optionally invoke additional post-processing steps on this binary based on its component image node type.

script

The image to use when loading a U-Boot script (for use with the source command).

compatible

The root compatible string of the bootloader device tree that this configuration shall automatically match. If this property is not provided, the compatible string will be extracted from the fdt blob instead. This is only possible if the fdt is not compressed, so images with compressed fdts that want to use compatible string matching must always provide this property.

Note that U-Boot requires the CONFIG_FIT_BEST_MATCH option to be enabled for this matching to work.

The FDT blob is required to properly boot FDT based kernel, so the minimal configuration for 2.6 FDT kernel is (kernel, fdt) pair.

Older, 2.4 kernel and 2.6 non-FDT kernel do not use FDT blob, in such cases ‘struct bd_info’ must be passed instead of FDT blob, thus fdt property must not be specified in a configuration node.

2.8. Configuration-signature nodes

o signature-1
    |- algo = "algorithm name"
    |- key-name-hint = "key name"
    |- sign-images = "path1", "path2";
    |- value = [hash or checksum value]
    |- hashed-strings = <0 len>

2.8.1. Mandatory properties

algo

See FIT Algorithm.

key-name-hint

Name of key to use for signing. The keys will normally be in a single directory (parameter -k to mkimage). For a given key <name>, its private key is stored in <name>.key and the certificate is stored in <name>.crt.

The following properies are added as part of signing, and are mandatory:

value

Actual signature value. This is added by mkimage.

The following properies are added as part of signing, and are optional:

timestamp

Time when image was signed (standard Unix time_t format)

signer-name

Name of the signer (e.g. “mkimage”)

signer-version

Version string of the signer (e.g. “2013.01”)

comment

Additional information about the signer or image

padding

The padding algorithm, it may be pkcs-1.5 or pss, if no value is provided we assume pkcs-1.5

3. Flattened Image Tree (FIT) Usage

3.1. Introduction

This section describes how FIT is typically used. This is not necessarily proscriptive but may be useful for those implementing this specification.

3.2. Boot process

At some point in the boot process, the bootloader select and boot an Operating System. To do this, it follows these steps:

  1. Load a FIT into memory

  2. Select a configuration to boot

  3. Load the images from the selected configuration

  4. Fix up the devicetree

  5. Jump to the OS

Each of these is now dealt with in turn.

3.2.1. Load a FIT into memory

The bootloader provides a way to select a FIT to load into memory. This is typically on boot media available to the bootloader, such as eMMC or UFS.

There may be multiple FITs available. The mechanism for locating and selecting a FIT is not defined by this specification. See for example [VBE].

The bootloader may load the entire FIT into memory at once, before processing it. For simple applications where there are just a few images, this is the easiest approach.

Where there are many configuration and several images, such that only a subset of the available images will actually be used on any one boot, it is inefficient to load the entire FIT, since most of the loaded data will not be used. In this case, an external-data FIT can be used. See External data.

In this case, the bootloader reads the FDT header (say 64 bytes), checks that it is valid, then reads enough more bytes to bring in totalsize bytes (totalsize is the second 32-bit word in the header). Typically this will be a few KB of data, consisting just of the FIT metadata. Later, the bootloader can read more data from the FIT as it needs to load each image.

Another case that sometimes comes up is loading images from a FIT into internal SRAM, which may be very limited. In that case it may be useful to align images on a storage-device’s block boundary (see -B flag in External data). The bootloader can then avoid needing bounce buffers and other complications.

3.2.2. Select a configuration to boot

The FIT typically contains more than one configuration. It is common to use a separate configuration for each supported model. The configuration contains a compatible stringlist which indicates which models the configuration is compatible with.

The bootloader itself typically has a compatible stringlist, indicating the model that it is running on. For U-Boot this is in the root node of the devicetree used by U-Boot, typically exactly the same devicetree as is used by Linux for that model. For other bootloaders, the stringlist may be hard-coded, or obtained by some other means.

The bootloader should loop through each configuration to find the best match to its own compatible string. The best match is the configuration which matches earliest string in the bootloader’s compatible stringlist.

For example, imagine the bootloader has compatible = "foo,bar", "bim,bam" and the FIT has two configurations:

config-1 {
    compatible = "foo,bar";
    fdt = "fdt-1";
    ...
};
config-2 {
    compatible = "bim,bam", "baz,biz";
    fdt = "fdt-2";
    ...
};

Here, the bootloader chooses config-1 since it is a better match. The first string in the bootloader’s compatible list, "foo,bar", matches a compatible string in the root of fdt1. Although "bim,bam" in fdt2 matches the second string, this isn’t as good a match as fdt1.

In U-Boot this algorithm is handled by fit_conf_find_compat() and enabled by the CONFIG_FIT_BEST_MATCH option.

Sometime models have multiple PCB revisions or different minor variants, often referred to as SKUs. For this reason, bootloaders may want to select configurations in a finer-grained way. In this case, rather than using the compatible stringlist in its devicetree, if any, it constructs a single string using the base name along with any available suffixes, each beginning with a hyphen. The best match algorithm is then run using that string.

The following compatible-string suffixes may be used to this end. They must be provided in this order (<n> is an integer >= 0):

-rev<n>

Board revision number, typically referring to a revision of the PCB to fix a problem or adjust component selection. The intention is that the board is the same design, just with some minor fixes or improvements. The first revision is typically rev0.

-sku<n>

Board variant, called a SKU (Stock-Keeping Unit) which is a unique code that identifies a model variant. This may encode differences in the display, WiFi and the like, but where the same PCB design (and revision) is used. The base SKU is typically sku0.

Examples:

compatible = "google,kevin-rev15";
compatible = "google,kevin-rev15-sku2";

When matching, the bootloader should build the most specific string it can using any available revision / SKU information, then try to match that. If the most specific string fails (e.g. "google,kevin-rev15-sku2"), it should fall back to just "google,kevin-rev15" and then "google,kevin-sku2". If nothing matches, then it should try without any additions, i.e. "google,kevin".

This multi-stage process uses the same ‘best match’ approach as above. Each attempt finds the best match given the compatible string being searched. Where a stage does not find any match, the next stage begins. As soon as a match is found, searching stops, using the best match found in the stage.

Other suffixes may be added in future.

3.2.3. Load the images from the selected configuration

The configuration contains a number of images. One of these is the OS itself. Another is typically a devicetree blob, which provides information about available devices, useful for the OS as it boots and runs. Another image may be a ramdisk (or initrd) which provides an initial root disk for the OS to use, before it is able to access the real root disk.

The bootloader reads each image from the FIT and ‘loads’ it to the correct address. This address may be provided by the image’s load property (see load), but if not provided, the bootloader can load it to any suitable address. In some cases it may be possible to avoid loading the image and just refer to the image data within the FIT itself.

3.2.4. Fix up the devicetree

Many Operating Systems use devicetree blobs for configuration. As a result, most bootloaders provide a way to update the devicetree in the FIT before passing it to the OS. This may be used to pass command-line parameters to Linux, to select the console device to use, or to pass the ramdisk to the OS. It is also common to enable or disable certain devicetree nodes based on the hardware in use.

The fixups required depend on the OS and its expectations. The result is a devicetree slightly modified from the FIT version.

3.2.5. Jump to the OS

Once everything is ready, the bootloader jumps to the OS. At this point the FIT is no longer in use. The OS typically does not see the FIT itself and only cares about the images that were loaded. At this point, the FIT has served its purpose.

3.3. Firmware usage

As firmware has become more complex, with multiple binaries loaded at each phase of the boot, it has become common to use FIT to load firmware.

In this case, there is the concept of a boot phase (see phase), indicating which phase each image is for.

In this case the bootloader itself is likely split into multiple phases. For U-Boot, a common approach is for SPL (Secondary Program Loader) to load U-Boot proper, along with ATF and any other images required by U-Boot proper.

FIT processing for firmware images is no different from the approach described above, except that any image with a phase property is only loaded if the phase matches the phase being loaded. So, for example, SPL loads U-Boot proper so will only load images with a phase of “u-boot”. If TPL is in use (the phase before SPL), then TPL will only load images with a phase of “spl”. This allows all images to be provided in a single FIT, with each phase pulling out what is needed as the boot proceeds.

3.4. Security

FIT has robust security features. When enabled, each FIT configuration has one or more signatures. These protect the configuration and the images it refers to. The bootloader must check the signatures against a public key which it has stored elsewhere.

If any configuration fails its signature check, then it must be ignored. Images must each include a suitable hash node, so that images are actually protected against modification. Once each image is loaded, its hash must be computed and checked against the hash in the FIT.

For more information on FIT security, see U-Boot’s documentation. The mechanism is also widely covered in conference talks, some of which are listed at elinux.org.

[dtspec]

Devicetree Specification https://www.devicetree.org/specifications

[VBE]

Verified Boot for Embedded (VBE) https://docs.u-boot.org/en/latest/develop/vbe.html