Skip to content

Commit 17c31ad

Browse files
wensmasahir0y
authored andcommitted
scripts/make_fit: Support decomposing DTBs
The kernel tree builds some "composite" DTBs, where the final DTB is the result of applying one or more DTB overlays on top of a base DTB with fdtoverlay. The FIT image specification already supports configurations having one base DTB and overlays applied on top. It is then up to the bootloader to apply said overlays and either use or pass on the final result. This allows the FIT image builder to reuse the same FDT images for multiple configurations, if such cases exist. The decomposition function depends on the kernel build system, reading back the .cmd files for the to-be-packaged DTB files to check for the fdtoverlay command being called. This will not work outside the kernel tree. The function is off by default to keep compatibility with possible existing users. To facilitate the decomposition and keep the code clean, the model and compatitble string extraction have been moved out of the output_dtb function. The FDT image description is replaced with the base file name of the included image. Signed-off-by: Chen-Yu Tsai <[email protected]> Reviewed-by: Simon Glass <[email protected]> Signed-off-by: Masahiro Yamada <[email protected]>
1 parent e61b190 commit 17c31ad

File tree

2 files changed

+65
-22
lines changed

2 files changed

+65
-22
lines changed

scripts/Makefile.lib

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -522,6 +522,7 @@ quiet_cmd_fit = FIT $@
522522
cmd_fit = $(MAKE_FIT) -o $@ --arch $(UIMAGE_ARCH) --os linux \
523523
--name '$(UIMAGE_NAME)' \
524524
$(if $(findstring 1,$(KBUILD_VERBOSE)),-v) \
525+
$(if $(FIT_DECOMPOSE_DTBS),--decompose-dtbs) \
525526
--compress $(FIT_COMPRESSION) -k $< @$(word 2,$^)
526527

527528
# XZ

scripts/make_fit.py

Lines changed: 64 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,11 @@
2222
Use -c to compress the data, using bzip2, gzip, lz4, lzma, lzo and
2323
zstd algorithms.
2424
25+
Use -D to decompose "composite" DTBs into their base components and
26+
deduplicate the resulting base DTBs and DTB overlays. This requires the
27+
DTBs to be sourced from the kernel build directory, as the implementation
28+
looks at the .cmd files produced by the kernel build.
29+
2530
The resulting FIT can be booted by bootloaders which support FIT, such
2631
as U-Boot, Linuxboot, Tianocore, etc.
2732
@@ -64,6 +69,8 @@ def parse_args():
6469
help='Specifies the architecture')
6570
parser.add_argument('-c', '--compress', type=str, default='none',
6671
help='Specifies the compression')
72+
parser.add_argument('-D', '--decompose-dtbs', action='store_true',
73+
help='Decompose composite DTBs into base DTB and overlays')
6774
parser.add_argument('-E', '--external', action='store_true',
6875
help='Convert the FIT to use external data')
6976
parser.add_argument('-n', '--name', type=str, required=True,
@@ -140,12 +147,12 @@ def finish_fit(fsw, entries):
140147
fsw.end_node()
141148
seq = 0
142149
with fsw.add_node('configurations'):
143-
for model, compat in entries:
150+
for model, compat, files in entries:
144151
seq += 1
145152
with fsw.add_node(f'conf-{seq}'):
146153
fsw.property('compatible', bytes(compat))
147154
fsw.property_string('description', model)
148-
fsw.property_string('fdt', f'fdt-{seq}')
155+
fsw.property('fdt', bytes(''.join(f'fdt-{x}\x00' for x in files), "ascii"))
149156
fsw.property_string('kernel', 'kernel')
150157
fsw.end_node()
151158

@@ -193,31 +200,55 @@ def output_dtb(fsw, seq, fname, arch, compress):
193200
fname (str): Filename containing the DTB
194201
arch: FIT architecture, e.g. 'arm64'
195202
compress (str): Compressed algorithm, e.g. 'gzip'
196-
197-
Returns:
198-
tuple:
199-
str: Model name
200-
bytes: Compatible stringlist
201203
"""
202204
with fsw.add_node(f'fdt-{seq}'):
203-
# Get the compatible / model information
204-
with open(fname, 'rb') as inf:
205-
data = inf.read()
206-
fdt = libfdt.FdtRo(data)
207-
model = fdt.getprop(0, 'model').as_str()
208-
compat = fdt.getprop(0, 'compatible')
209-
210-
fsw.property_string('description', model)
205+
fsw.property_string('description', os.path.basename(fname))
211206
fsw.property_string('type', 'flat_dt')
212207
fsw.property_string('arch', arch)
213208
fsw.property_string('compression', compress)
214209

215210
with open(fname, 'rb') as inf:
216211
compressed = compress_data(inf, compress)
217212
fsw.property('data', compressed)
218-
return model, compat
219213

220214

215+
def process_dtb(fname, args):
216+
"""Process an input DTB, decomposing it if requested and is possible
217+
218+
Args:
219+
fname (str): Filename containing the DTB
220+
args (Namespace): Program arguments
221+
Returns:
222+
tuple:
223+
str: Model name string
224+
str: Root compatible string
225+
files: list of filenames corresponding to the DTB
226+
"""
227+
# Get the compatible / model information
228+
with open(fname, 'rb') as inf:
229+
data = inf.read()
230+
fdt = libfdt.FdtRo(data)
231+
model = fdt.getprop(0, 'model').as_str()
232+
compat = fdt.getprop(0, 'compatible')
233+
234+
if args.decompose_dtbs:
235+
# Check if the DTB needs to be decomposed
236+
path, basename = os.path.split(fname)
237+
cmd_fname = os.path.join(path, f'.{basename}.cmd')
238+
with open(cmd_fname, 'r', encoding='ascii') as inf:
239+
cmd = inf.read()
240+
241+
if 'scripts/dtc/fdtoverlay' in cmd:
242+
# This depends on the structure of the composite DTB command
243+
files = cmd.split()
244+
files = files[files.index('-i') + 1:]
245+
else:
246+
files = [fname]
247+
else:
248+
files = [fname]
249+
250+
return (model, compat, files)
251+
221252
def build_fit(args):
222253
"""Build the FIT from the provided files and arguments
223254
@@ -235,6 +266,7 @@ def build_fit(args):
235266
fsw = libfdt.FdtSw()
236267
setup_fit(fsw, args.name)
237268
entries = []
269+
fdts = {}
238270

239271
# Handle the kernel
240272
with open(args.kernel, 'rb') as inf:
@@ -243,12 +275,22 @@ def build_fit(args):
243275
write_kernel(fsw, comp_data, args)
244276

245277
for fname in args.dtbs:
246-
# Ignore overlay (.dtbo) files
247-
if os.path.splitext(fname)[1] == '.dtb':
248-
seq += 1
249-
size += os.path.getsize(fname)
250-
model, compat = output_dtb(fsw, seq, fname, args.arch, args.compress)
251-
entries.append([model, compat])
278+
# Ignore non-DTB (*.dtb) files
279+
if os.path.splitext(fname)[1] != '.dtb':
280+
continue
281+
282+
(model, compat, files) = process_dtb(fname, args)
283+
284+
for fn in files:
285+
if fn not in fdts:
286+
seq += 1
287+
size += os.path.getsize(fn)
288+
output_dtb(fsw, seq, fn, args.arch, args.compress)
289+
fdts[fn] = seq
290+
291+
files_seq = [fdts[fn] for fn in files]
292+
293+
entries.append([model, compat, files_seq])
252294

253295
finish_fit(fsw, entries)
254296

0 commit comments

Comments
 (0)