1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
|
U-Boot FDT Overlay FIT usage
============================
Introduction
------------
In many cases it is desirable to have a single FIT image support a multitude
of similar boards and their expansion options. The same kernel on DT enabled
platforms can support this easily enough by providing a DT blob upon boot
that matches the desired configuration.
This document focuses on specifically using overlays as part of a FIT image.
General information regarding overlays including its syntax and building it
can be found in doc/README.fdt-overlays
Configuration without overlays
------------------------------
Take a hypothetical board named 'foo' where there are different supported
revisions, reva and revb. Assume that both board revisions can use add a bar
add-on board, while only the revb board can use a baz add-on board.
Without using overlays the configuration would be as follows for every case.
/dts-v1/;
/ {
images {
kernel {
data = /incbin/("./zImage");
type = "kernel";
arch = "arm";
os = "linux";
load = <0x82000000>;
entry = <0x82000000>;
};
fdt-1 {
data = /incbin/("./foo-reva.dtb");
type = "flat_dt";
arch = "arm";
};
fdt-2 {
data = /incbin/("./foo-revb.dtb");
type = "flat_dt";
arch = "arm";
};
fdt-3 {
data = /incbin/("./foo-reva-bar.dtb");
type = "flat_dt";
arch = "arm";
};
fdt-4 {
data = /incbin/("./foo-revb-bar.dtb");
type = "flat_dt";
arch = "arm";
};
fdt-5 {
data = /incbin/("./foo-revb-baz.dtb");
type = "flat_dt";
arch = "arm";
};
fdt-6 {
data = /incbin/("./foo-revb-bar-baz.dtb");
type = "flat_dt";
arch = "arm";
};
};
configurations {
default = "foo-reva.dtb;
foo-reva.dtb {
kernel = "kernel";
fdt = "fdt-1";
};
foo-revb.dtb {
kernel = "kernel";
fdt = "fdt-2";
};
foo-reva-bar.dtb {
kernel = "kernel";
fdt = "fdt-3";
};
foo-revb-bar.dtb {
kernel = "kernel";
fdt = "fdt-4";
};
foo-revb-baz.dtb {
kernel = "kernel";
fdt = "fdt-5";
};
foo-revb-bar-baz.dtb {
kernel = "kernel";
fdt = "fdt-6";
};
};
};
Note the blob needs to be compiled for each case and the combinatorial explosion of
configurations. A typical device tree blob is in the low hunderds of kbytes so a
multitude of configuration grows the image quite a bit.
Booting this image is done by using
# bootm <addr>#<config>
Where config is one of:
foo-reva.dtb, foo-revb.dtb, foo-reva-bar.dtb, foo-revb-bar.dtb,
foo-revb-baz.dtb, foo-revb-bar-baz.dtb
This selects the DTB to use when booting.
Configuration using overlays
----------------------------
Device tree overlays can be applied to a base DT and result in the same blob
being passed to the booting kernel. This saves on space and avoid the combinatorial
explosion problem.
/dts-v1/;
/ {
images {
kernel {
data = /incbin/("./zImage");
type = "kernel";
arch = "arm";
os = "linux";
load = <0x82000000>;
entry = <0x82000000>;
};
fdt-1 {
data = /incbin/("./foo.dtb");
type = "flat_dt";
arch = "arm";
load = <0x87f00000>;
};
fdt-2 {
data = /incbin/("./reva.dtbo");
type = "flat_dt";
arch = "arm";
load = <0x87fc0000>;
};
fdt-3 {
data = /incbin/("./revb.dtbo");
type = "flat_dt";
arch = "arm";
load = <0x87fc0000>;
};
fdt-4 {
data = /incbin/("./bar.dtbo");
type = "flat_dt";
arch = "arm";
load = <0x87fc0000>;
};
fdt-5 {
data = /incbin/("./baz.dtbo");
type = "flat_dt";
arch = "arm";
load = <0x87fc0000>;
};
};
configurations {
default = "foo-reva.dtb;
foo-reva.dtb {
kernel = "kernel";
fdt = "fdt-1", "fdt-2";
};
foo-revb.dtb {
kernel = "kernel";
fdt = "fdt-1", "fdt-3";
};
foo-reva-bar.dtb {
kernel = "kernel";
fdt = "fdt-1", "fdt-2", "fdt-4";
};
foo-revb-bar.dtb {
kernel = "kernel";
fdt = "fdt-1", "fdt-3", "fdt-4";
};
foo-revb-baz.dtb {
kernel = "kernel";
fdt = "fdt-1", "fdt-3", "fdt-5";
};
foo-revb-bar-baz.dtb {
kernel = "kernel";
fdt = "fdt-1", "fdt-3", "fdt-4", "fdt-5";
};
bar {
fdt = "fdt-4";
};
baz {
fdt = "fdt-5";
};
};
};
Booting this image is exactly the same as the non-overlay example.
u-boot will retrieve the base blob and apply the overlays in sequence as
they are declared in the configuration.
Note the minimum amount of different DT blobs, as well as the requirement for
the DT blobs to have a load address; the overlay application requires the blobs
to be writeable.
Configuration using overlays and feature selection
--------------------------------------------------
Although the configuration in the previous section works is a bit inflexible
since it requires all possible configuration options to be laid out before
hand in the FIT image. For the add-on boards the extra config selection method
might make sense.
Note the two bar & baz configuration nodes. To boot a reva board with
the bar add-on board enabled simply use:
# bootm <addr>#foo-reva.dtb#bar
While booting a revb with bar and baz is as follows:
# bootm <addr>#foo-revb.dtb#bar#baz
The limitation for a feature selection configuration node is that a single
fdt option is currently supported.
Pantelis Antoniou
pantelis.antoniou@konsulko.com
12/6/2017
|