Flattened Image Tree Specification v0.8-11-gc749139¶
Copyright
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:
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
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¶
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:
Create .its file, automatically filled-in properties are omitted
Call mkimage tool on .its file
mkimage calls dtc to create .fit image and assures that missing properties are added
.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:
Load a FIT into memory
Select a configuration to boot
Load the images from the selected configuration
Fix up the devicetree
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.
Devicetree Specification https://www.devicetree.org/specifications
Verified Boot for Embedded (VBE) https://docs.u-boot.org/en/latest/develop/vbe.html