Skip to content

Commit 1c82248

Browse files
sjg20LeanSheng
authored andcommitted
Document how FIT should be used in a bootloader
The current documentation mentioned configuration matching but only in passing and in a reference to U-Boot. Add a new section which focusses on how FIT is used in the bootloader, including more detailed information about configuration matching. Adjust the material to ensure that it does not assume that the bootloader is always U-Boot. Signed-off-by: Simon Glass <[email protected]>
1 parent daa526f commit 1c82248

6 files changed

+193
-6
lines changed

Diff for: source/chapter1-introduction.rst

+2
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,8 @@ along with grouping and selection mechanisms.
3333
* :numref:`Chapter %s <chapter-source-file-format>` introduces the FIT concept
3434
and describes its logical structure and standard properties.
3535
certain classes of devices and specific device types.
36+
* :numref:`Chapter %s <chapter-usage>` describes how FIT is used in bootloaders
37+
to handle booting Operating Systems as well as firmware.
3638

3739
**Conventions Used in this Document**
3840

Diff for: source/chapter2-source-file-format.rst

+13-5
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,8 @@ checking required.
7171

7272
.. index:: External data
7373

74+
.. _ExternalData:
75+
7476
External data
7577
~~~~~~~~~~~~~
7678

@@ -341,6 +343,8 @@ entry
341343
'#address-cells' property of the root node.
342344
Mandatory for types: "firmware", and "kernel".
343345

346+
.. _prop_load:
347+
344348
load
345349
load address, address size is determined by '#address-cells'
346350
property of the root node.
@@ -365,6 +369,8 @@ load
365369
The compatible here is not derived from the fdt, nor is it used to identify
366370
the fdt. Such usage belongs in the configuration node.
367371

372+
.. _prop_phase:
373+
368374
:index:`phase`
369375
:index:`U-Boot phase <pair: U-Boot; phase>` for which the image is intended.
370376

@@ -593,15 +599,17 @@ script
593599
source command).
594600

595601
compatible
596-
The root compatible string of the U-Boot device tree that
597-
this configuration shall automatically match when
598-
:index:`CONFIG_FIT_BEST_MATCH` is
599-
enabled. If this property is not provided, the compatible string will be
602+
The root compatible string of the bootloader device tree that
603+
this configuration shall automatically match. If this property is not
604+
provided, the compatible string will be
600605
extracted from the fdt blob instead. This is only possible if the fdt is
601606
not compressed, so images with compressed fdts that want to use compatible
602607
string matching must always provide this property.
603608

604-
The FDT blob is required to properly boot FDT-based kernel, so the minimal
609+
Note that U-Boot requires the :index:`CONFIG_FIT_BEST_MATCH` option to be
610+
enabled for this matching to work.
611+
612+
The FDT blob is required to properly boot FDT based kernel, so the minimal
605613
configuration for 2.6 FDT kernel is (kernel, fdt) pair.
606614

607615
Older, 2.4 kernel and 2.6 non-FDT kernel do not use FDT blob, in such cases

Diff for: source/chapter3-usage.rst

+172
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,172 @@
1+
.. SPDX-License-Identifier: GPL-2.0+
2+
3+
.. _chapter-usage:
4+
5+
Flattened Image Tree (FIT) Usage
6+
================================
7+
8+
Introduction
9+
------------
10+
11+
This section describes how FIT is typically used. This is not necessarily
12+
proscriptive but may be useful for those implementing this specification.
13+
14+
Boot process
15+
------------
16+
17+
At some point in the boot process, the bootloader select and boot an Operating
18+
System. To do this, it follows these steps:
19+
20+
#. Load a FIT into memory
21+
#. Select a configuration to boot
22+
#. Load the images from the selected configuration
23+
#. Fix up the devicetree
24+
#. Jump to the OS
25+
26+
Each of these is now dealt with in turn.
27+
28+
Load a FIT into memory
29+
~~~~~~~~~~~~~~~~~~~~~~
30+
31+
The bootloader provides a way to select a FIT to load into memory. This is
32+
typically on boot media available to the bootloader, such as eMMC or UFS.
33+
34+
There may be multiple FITs available. The mechanism for locating and selecting
35+
a FIT is not defined by this specification. See for example [VBE]_.
36+
37+
The bootloader may load the entire FIT into memory at once, before processing
38+
it. For simple applications where there are just a few images, this is the
39+
easiest approach.
40+
41+
Where there are many configuration and several images, such that only a subset
42+
of the available images will actually be used on any one boot, it is inefficient
43+
to load the entire FIT, since most of the loaded data will not be used. In this
44+
case, an external-data FIT can be used. See :ref:`Externaldata`.
45+
46+
In this case, the bootloader reads the FDT header (say 64 bytes), checks that
47+
it is valid, then reads enough more bytes to bring in ``totalsize`` bytes
48+
(``totalsize`` is the second 32-bit word in the header). Typically this will be
49+
a few KB of data, consisting just of the FIT metadata. Later, the bootloader can
50+
read more data from the FIT as it needs to load each image.
51+
52+
Another case that sometimes comes up is loading images from a FIT into internal
53+
SRAM, which may be very limited. In that case it may be useful to align images
54+
on a storage-device's block boundary (see ``-B`` flag in :ref:`Externaldata`).
55+
The bootloader can then avoid needing bounce buffers and other complications.
56+
57+
Select a configuration to boot
58+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
59+
60+
The FIT typically contains more than one configuration. It is common to use a
61+
separate configuration for each supported model. The configuration contains
62+
a ``compatible`` stringlist which indicates which models the configuration is
63+
compatible with.
64+
65+
The bootloader itself typically has a compatible stringlist, indicating the
66+
model that it is running on. For U-Boot this is in the root node of the
67+
devicetree used by U-Boot, typically exactly the same devicetree as is used by
68+
Linux for that model. For other bootloaders, the stringlist may be hard-coded,
69+
or obtained by some other means.
70+
71+
The bootloader should loop through each configuration to find the best match to
72+
its own compatible string. The best match is the configuration which matches
73+
earliest string in the bootloader's compatible stringlist.
74+
75+
For example, imagine the bootloader has ``compatible = "foo,bar", "bim,bam"``
76+
and the FIT has two configurations::
77+
78+
config-1 {
79+
compatible = "foo,bar";
80+
fdt = "fdt-1";
81+
...
82+
};
83+
config-2 {
84+
compatible = "bim,bam", "baz,biz";
85+
fdt = "fdt-2";
86+
...
87+
};
88+
89+
Here, the bootloader chooses ``config-1`` since it is a better match. The first
90+
string in the bootloader's compatible list, ``"foo,bar"``, matches a compatible
91+
string in the root of ``fdt1``. Although ``"bim,bam"`` in ``fdt2`` matches the
92+
second string, this isn't as good a match as ``fdt1``.
93+
94+
In U-Boot this algorithm is handled by ``fit_conf_find_compat()`` and enabled
95+
by the ``CONFIG_FIT_BEST_MATCH`` option.
96+
97+
Load the images from the selected configuration
98+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
99+
100+
The configuration contains a number of images. One of these is the OS itself.
101+
Another is typically a devicetree blob, which provides information about
102+
available devices, useful for the OS as it boots and runs. Another image may be
103+
a ramdisk (or initrd) which provides an initial root disk for the OS to use,
104+
before it is able to access the real root disk.
105+
106+
The bootloader reads each image from the FIT and 'loads' it to the correct
107+
address. This address may be provided by the image's ``load`` property
108+
(see :ref:`prop_load`), but if not provided, the bootloader can load it to any
109+
suitable address. In some cases it may be possible to avoid loading the image
110+
and just refer to the image data within the FIT itself.
111+
112+
Fix up the devicetree
113+
~~~~~~~~~~~~~~~~~~~~~
114+
115+
Many Operating Systems use devicetree blobs for configuration. As a result, most
116+
bootloaders provide a way to update the devicetree in the FIT before passing it
117+
to the OS. This may be used to pass command-line parameters to Linux, to select
118+
the console device to use, or to pass the ramdisk to the OS. It is also common
119+
to enable or disable certain devicetree nodes based on the hardware
120+
in use.
121+
122+
The fixups required depend on the OS and its expectations. The result is a
123+
devicetree slightly modified from the FIT version.
124+
125+
Jump to the OS
126+
~~~~~~~~~~~~~~
127+
128+
Once everything is ready, the bootloader jumps to the OS. At this point the FIT
129+
is no longer in use. The OS typically does not see the FIT itself and only cares
130+
about the images that were loaded. At this point, the FIT has served its
131+
purpose.
132+
133+
Firmware usage
134+
--------------
135+
136+
As firmware has become more complex, with multiple binaries loaded at each
137+
phase of the boot, it has become common to use FIT to load firmware.
138+
139+
In this case, there is the concept of a boot phase (see :ref:`prop_phase`),
140+
indicating which phase each image is for.
141+
142+
In this case the bootloader itself is likely split into multiple phases. For
143+
U-Boot, a common approach is for SPL (Secondary Program Loader) to load U-Boot
144+
proper, along with :index:`ATF` and any other images required by U-Boot proper.
145+
146+
FIT processing for firmware images is no different from the approach described
147+
above, except that any image with a ``phase`` property is only loaded if the
148+
phase matches the phase being loaded. So, for example, SPL loads U-Boot proper
149+
so will only load images with a phase of "u-boot". If TPL is in use (the phase
150+
before SPL), then TPL will only load images with a phase of "spl". This allows
151+
all images to be provided in a single FIT, with each phase pulling out what is
152+
needed as the boot proceeds.
153+
154+
Security
155+
--------
156+
157+
FIT has robust security features. When enabled, each FIT configuration has
158+
one or more signatures. These protect the configuration and the images it
159+
refers to. The bootloader must check the signatures against a public key which
160+
it has stored elsewhere.
161+
162+
If any configuration fails its signature check, then it must be ignored. Images
163+
must each include a suitable hash node, so that images are actually protected
164+
against modification. Once each image is loaded, its hash must be computed and
165+
checked against the hash in the FIT.
166+
167+
For more information on FIT security, see
168+
`U-Boot's documentation <https://docs.u-boot.org/en/latest/usage/fit/signature.html>`_.
169+
The mechanism is also widely covered in conference talks, some of which are
170+
listed at `elinux.org <https://elinux.org/Boot_Loaders#U-Boot>`_.
171+
172+
.. sectionauthor:: Simon Glass <[email protected]>

Diff for: source/index.rst

+1
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
revhistory
1515
chapter1-introduction
1616
chapter2-source-file-format
17+
chapter3-usage
1718
references
1819

1920
..

Diff for: source/references.rst

+4-1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
11
.. SPDX-License-Identifier: Apache-2.0
22
3-
.. [dtspec] https://www.devicetree.org/specifications/
3+
.. [dtspec] Devicetree Specification
4+
https://www.devicetree.org/specifications
5+
.. [VBE] Verified Boot for Embedded (VBE)
6+
https://docs.u-boot.org/en/latest/develop/vbe.html

Diff for: source/rst_prolog

+1
Original file line numberDiff line numberDiff line change
@@ -10,3 +10,4 @@
1010
.. |spec| replace:: FITSpec
1111
.. |spec-fullname| replace:: Flattened Image Tree Specification
1212
.. |dtspec| replace:: Devicetree Specification
13+
.. |VBE| replace:: Verified Boot for Embedded (VBE)

0 commit comments

Comments
 (0)