blob: 3b52326641707b70e430108908303f005d052433 [file] [log] [blame]
Tom Rini83d290c2018-05-06 17:58:06 -04001# SPDX-License-Identifier: GPL-2.0+
Simon Glassbf7fd502016-11-25 20:15:51 -07002# Copyright (c) 2016 Google, Inc
3# Written by Simon Glass <sjg@chromium.org>
4#
Simon Glassbf7fd502016-11-25 20:15:51 -07005# Creates binary images from input files controlled by a description
6#
7
8from collections import OrderedDict
Simon Glass87d43322020-08-05 13:27:46 -06009import glob
Simon Glassbf7fd502016-11-25 20:15:51 -070010import os
Simon Glass9fbfaba2020-08-29 11:36:14 -060011import pkg_resources
12
Simon Glassbf7fd502016-11-25 20:15:51 -070013import sys
Simon Glassbf776672020-04-17 18:09:04 -060014from patman import tools
Simon Glassbf7fd502016-11-25 20:15:51 -070015
Simon Glass16287932020-04-17 18:09:03 -060016from binman import cbfs_util
17from binman import elf
Simon Glassbf776672020-04-17 18:09:04 -060018from patman import command
19from patman import tout
Simon Glassbf7fd502016-11-25 20:15:51 -070020
21# List of images we plan to create
22# Make this global so that it can be referenced from tests
23images = OrderedDict()
24
25def _ReadImageDesc(binman_node):
26 """Read the image descriptions from the /binman node
27
28 This normally produces a single Image object called 'image'. But if
29 multiple images are present, they will all be returned.
30
31 Args:
32 binman_node: Node object of the /binman node
33 Returns:
34 OrderedDict of Image objects, each of which describes an image
35 """
36 images = OrderedDict()
37 if 'multiple-images' in binman_node.props:
38 for node in binman_node.subnodes:
39 images[node.name] = Image(node.name, node)
40 else:
41 images['image'] = Image('image', binman_node)
42 return images
43
Simon Glassec3f3782017-05-27 07:38:29 -060044def _FindBinmanNode(dtb):
Simon Glassbf7fd502016-11-25 20:15:51 -070045 """Find the 'binman' node in the device tree
46
47 Args:
Simon Glassec3f3782017-05-27 07:38:29 -060048 dtb: Fdt object to scan
Simon Glassbf7fd502016-11-25 20:15:51 -070049 Returns:
50 Node object of /binman node, or None if not found
51 """
Simon Glassec3f3782017-05-27 07:38:29 -060052 for node in dtb.GetRoot().subnodes:
Simon Glassbf7fd502016-11-25 20:15:51 -070053 if node.name == 'binman':
54 return node
55 return None
56
Simon Glass87d43322020-08-05 13:27:46 -060057def GetEntryModules(include_testing=True):
58 """Get a set of entry class implementations
59
60 Returns:
61 Set of paths to entry class filenames
62 """
Simon Glass9fbfaba2020-08-29 11:36:14 -060063 glob_list = pkg_resources.resource_listdir(__name__, 'etype')
64 glob_list = [fname for fname in glob_list if fname.endswith('.py')]
Simon Glass87d43322020-08-05 13:27:46 -060065 return set([os.path.splitext(os.path.basename(item))[0]
66 for item in glob_list
67 if include_testing or '_testing' not in item])
68
Simon Glassc55a50f2018-09-14 04:57:19 -060069def WriteEntryDocs(modules, test_missing=None):
70 """Write out documentation for all entries
Simon Glassecab8972018-07-06 10:27:40 -060071
72 Args:
Simon Glassc55a50f2018-09-14 04:57:19 -060073 modules: List of Module objects to get docs for
74 test_missing: Used for testing only, to force an entry's documeentation
75 to show as missing even if it is present. Should be set to None in
76 normal use.
Simon Glassecab8972018-07-06 10:27:40 -060077 """
Simon Glass16287932020-04-17 18:09:03 -060078 from binman.entry import Entry
Simon Glassfd8d1f72018-07-17 13:25:36 -060079 Entry.WriteDocs(modules, test_missing)
80
Simon Glass61f564d2019-07-08 14:25:48 -060081
82def ListEntries(image_fname, entry_paths):
83 """List the entries in an image
84
85 This decodes the supplied image and displays a table of entries from that
86 image, preceded by a header.
87
88 Args:
89 image_fname: Image filename to process
90 entry_paths: List of wildcarded paths (e.g. ['*dtb*', 'u-boot*',
91 'section/u-boot'])
92 """
93 image = Image.FromFile(image_fname)
94
95 entries, lines, widths = image.GetListEntries(entry_paths)
96
97 num_columns = len(widths)
98 for linenum, line in enumerate(lines):
99 if linenum == 1:
100 # Print header line
101 print('-' * (sum(widths) + num_columns * 2))
102 out = ''
103 for i, item in enumerate(line):
104 width = -widths[i]
105 if item.startswith('>'):
106 width = -width
107 item = item[1:]
108 txt = '%*s ' % (width, item)
109 out += txt
110 print(out.rstrip())
111
Simon Glassf667e452019-07-08 14:25:50 -0600112
113def ReadEntry(image_fname, entry_path, decomp=True):
114 """Extract an entry from an image
115
116 This extracts the data from a particular entry in an image
117
118 Args:
119 image_fname: Image filename to process
120 entry_path: Path to entry to extract
121 decomp: True to return uncompressed data, if the data is compress
122 False to return the raw data
123
124 Returns:
125 data extracted from the entry
126 """
Simon Glass8dbb7442019-08-24 07:22:44 -0600127 global Image
Simon Glass07237982020-08-05 13:27:47 -0600128 from binman.image import Image
Simon Glass8dbb7442019-08-24 07:22:44 -0600129
Simon Glassf667e452019-07-08 14:25:50 -0600130 image = Image.FromFile(image_fname)
131 entry = image.FindEntryPath(entry_path)
132 return entry.ReadData(decomp)
133
134
Simon Glass71ce0ba2019-07-08 14:25:52 -0600135def ExtractEntries(image_fname, output_fname, outdir, entry_paths,
136 decomp=True):
137 """Extract the data from one or more entries and write it to files
138
139 Args:
140 image_fname: Image filename to process
141 output_fname: Single output filename to use if extracting one file, None
142 otherwise
143 outdir: Output directory to use (for any number of files), else None
144 entry_paths: List of entry paths to extract
Simon Glass3ad804e2019-07-20 12:24:12 -0600145 decomp: True to decompress the entry data
Simon Glass71ce0ba2019-07-08 14:25:52 -0600146
147 Returns:
148 List of EntryInfo records that were written
149 """
150 image = Image.FromFile(image_fname)
151
152 # Output an entry to a single file, as a special case
153 if output_fname:
154 if not entry_paths:
Simon Glassbb5edc12019-07-20 12:24:14 -0600155 raise ValueError('Must specify an entry path to write with -f')
Simon Glass71ce0ba2019-07-08 14:25:52 -0600156 if len(entry_paths) != 1:
Simon Glassbb5edc12019-07-20 12:24:14 -0600157 raise ValueError('Must specify exactly one entry path to write with -f')
Simon Glass71ce0ba2019-07-08 14:25:52 -0600158 entry = image.FindEntryPath(entry_paths[0])
159 data = entry.ReadData(decomp)
160 tools.WriteFile(output_fname, data)
161 tout.Notice("Wrote %#x bytes to file '%s'" % (len(data), output_fname))
162 return
163
164 # Otherwise we will output to a path given by the entry path of each entry.
165 # This means that entries will appear in subdirectories if they are part of
166 # a sub-section.
167 einfos = image.GetListEntries(entry_paths)[0]
168 tout.Notice('%d entries match and will be written' % len(einfos))
169 for einfo in einfos:
170 entry = einfo.entry
171 data = entry.ReadData(decomp)
172 path = entry.GetPath()[1:]
173 fname = os.path.join(outdir, path)
174
175 # If this entry has children, create a directory for it and put its
176 # data in a file called 'root' in that directory
177 if entry.GetEntries():
178 if not os.path.exists(fname):
179 os.makedirs(fname)
180 fname = os.path.join(fname, 'root')
181 tout.Notice("Write entry '%s' to '%s'" % (entry.GetPath(), fname))
182 tools.WriteFile(fname, data)
183 return einfos
184
185
Simon Glassd7fa4e42019-07-20 12:24:13 -0600186def BeforeReplace(image, allow_resize):
187 """Handle getting an image ready for replacing entries in it
188
189 Args:
190 image: Image to prepare
191 """
192 state.PrepareFromLoadedData(image)
193 image.LoadData()
194
195 # If repacking, drop the old offset/size values except for the original
196 # ones, so we are only left with the constraints.
197 if allow_resize:
198 image.ResetForPack()
199
200
201def ReplaceOneEntry(image, entry, data, do_compress, allow_resize):
202 """Handle replacing a single entry an an image
203
204 Args:
205 image: Image to update
206 entry: Entry to write
207 data: Data to replace with
208 do_compress: True to compress the data if needed, False if data is
209 already compressed so should be used as is
210 allow_resize: True to allow entries to change size (this does a re-pack
211 of the entries), False to raise an exception
212 """
213 if not entry.WriteData(data, do_compress):
214 if not image.allow_repack:
215 entry.Raise('Entry data size does not match, but allow-repack is not present for this image')
216 if not allow_resize:
217 entry.Raise('Entry data size does not match, but resize is disabled')
218
219
220def AfterReplace(image, allow_resize, write_map):
221 """Handle write out an image after replacing entries in it
222
223 Args:
224 image: Image to write
225 allow_resize: True to allow entries to change size (this does a re-pack
226 of the entries), False to raise an exception
227 write_map: True to write a map file
228 """
229 tout.Info('Processing image')
230 ProcessImage(image, update_fdt=True, write_map=write_map,
231 get_contents=False, allow_resize=allow_resize)
232
233
234def WriteEntryToImage(image, entry, data, do_compress=True, allow_resize=True,
235 write_map=False):
236 BeforeReplace(image, allow_resize)
237 tout.Info('Writing data to %s' % entry.GetPath())
238 ReplaceOneEntry(image, entry, data, do_compress, allow_resize)
239 AfterReplace(image, allow_resize=allow_resize, write_map=write_map)
240
241
Simon Glass3ad804e2019-07-20 12:24:12 -0600242def WriteEntry(image_fname, entry_path, data, do_compress=True,
243 allow_resize=True, write_map=False):
Simon Glass22a76b72019-07-20 12:24:11 -0600244 """Replace an entry in an image
245
246 This replaces the data in a particular entry in an image. This size of the
247 new data must match the size of the old data unless allow_resize is True.
248
249 Args:
250 image_fname: Image filename to process
251 entry_path: Path to entry to extract
252 data: Data to replace with
Simon Glass3ad804e2019-07-20 12:24:12 -0600253 do_compress: True to compress the data if needed, False if data is
Simon Glass22a76b72019-07-20 12:24:11 -0600254 already compressed so should be used as is
255 allow_resize: True to allow entries to change size (this does a re-pack
256 of the entries), False to raise an exception
Simon Glass3ad804e2019-07-20 12:24:12 -0600257 write_map: True to write a map file
Simon Glass22a76b72019-07-20 12:24:11 -0600258
259 Returns:
260 Image object that was updated
261 """
Simon Glassd7fa4e42019-07-20 12:24:13 -0600262 tout.Info("Write entry '%s', file '%s'" % (entry_path, image_fname))
Simon Glass22a76b72019-07-20 12:24:11 -0600263 image = Image.FromFile(image_fname)
264 entry = image.FindEntryPath(entry_path)
Simon Glassd7fa4e42019-07-20 12:24:13 -0600265 WriteEntryToImage(image, entry, data, do_compress=do_compress,
266 allow_resize=allow_resize, write_map=write_map)
Simon Glass22a76b72019-07-20 12:24:11 -0600267
Simon Glass22a76b72019-07-20 12:24:11 -0600268 return image
269
Simon Glassa6cb9952019-07-20 12:24:15 -0600270
271def ReplaceEntries(image_fname, input_fname, indir, entry_paths,
272 do_compress=True, allow_resize=True, write_map=False):
273 """Replace the data from one or more entries from input files
274
275 Args:
276 image_fname: Image filename to process
277 input_fname: Single input ilename to use if replacing one file, None
278 otherwise
279 indir: Input directory to use (for any number of files), else None
280 entry_paths: List of entry paths to extract
281 do_compress: True if the input data is uncompressed and may need to be
282 compressed if the entry requires it, False if the data is already
283 compressed.
284 write_map: True to write a map file
285
286 Returns:
287 List of EntryInfo records that were written
288 """
289 image = Image.FromFile(image_fname)
290
291 # Replace an entry from a single file, as a special case
292 if input_fname:
293 if not entry_paths:
294 raise ValueError('Must specify an entry path to read with -f')
295 if len(entry_paths) != 1:
296 raise ValueError('Must specify exactly one entry path to write with -f')
297 entry = image.FindEntryPath(entry_paths[0])
298 data = tools.ReadFile(input_fname)
299 tout.Notice("Read %#x bytes from file '%s'" % (len(data), input_fname))
300 WriteEntryToImage(image, entry, data, do_compress=do_compress,
301 allow_resize=allow_resize, write_map=write_map)
302 return
303
304 # Otherwise we will input from a path given by the entry path of each entry.
305 # This means that files must appear in subdirectories if they are part of
306 # a sub-section.
307 einfos = image.GetListEntries(entry_paths)[0]
308 tout.Notice("Replacing %d matching entries in image '%s'" %
309 (len(einfos), image_fname))
310
311 BeforeReplace(image, allow_resize)
312
313 for einfo in einfos:
314 entry = einfo.entry
315 if entry.GetEntries():
316 tout.Info("Skipping section entry '%s'" % entry.GetPath())
317 continue
318
319 path = entry.GetPath()[1:]
320 fname = os.path.join(indir, path)
321
322 if os.path.exists(fname):
323 tout.Notice("Write entry '%s' from file '%s'" %
324 (entry.GetPath(), fname))
325 data = tools.ReadFile(fname)
326 ReplaceOneEntry(image, entry, data, do_compress, allow_resize)
327 else:
328 tout.Warning("Skipping entry '%s' from missing file '%s'" %
329 (entry.GetPath(), fname))
330
331 AfterReplace(image, allow_resize=allow_resize, write_map=write_map)
332 return image
333
334
Simon Glassa8573c42019-07-20 12:23:27 -0600335def PrepareImagesAndDtbs(dtb_fname, select_images, update_fdt):
336 """Prepare the images to be processed and select the device tree
337
338 This function:
339 - reads in the device tree
340 - finds and scans the binman node to create all entries
341 - selects which images to build
342 - Updates the device tress with placeholder properties for offset,
343 image-pos, etc.
344
345 Args:
346 dtb_fname: Filename of the device tree file to use (.dts or .dtb)
347 selected_images: List of images to output, or None for all
348 update_fdt: True to update the FDT wth entry offsets, etc.
349 """
350 # Import these here in case libfdt.py is not available, in which case
351 # the above help option still works.
Simon Glass16287932020-04-17 18:09:03 -0600352 from dtoc import fdt
353 from dtoc import fdt_util
Simon Glassa8573c42019-07-20 12:23:27 -0600354 global images
355
356 # Get the device tree ready by compiling it and copying the compiled
357 # output into a file in our output directly. Then scan it for use
358 # in binman.
359 dtb_fname = fdt_util.EnsureCompiled(dtb_fname)
360 fname = tools.GetOutputFilename('u-boot.dtb.out')
361 tools.WriteFile(fname, tools.ReadFile(dtb_fname))
362 dtb = fdt.FdtScan(fname)
363
364 node = _FindBinmanNode(dtb)
365 if not node:
366 raise ValueError("Device tree '%s' does not have a 'binman' "
367 "node" % dtb_fname)
368
369 images = _ReadImageDesc(node)
370
371 if select_images:
372 skip = []
373 new_images = OrderedDict()
374 for name, image in images.items():
375 if name in select_images:
376 new_images[name] = image
377 else:
378 skip.append(name)
379 images = new_images
380 tout.Notice('Skipping images: %s' % ', '.join(skip))
381
382 state.Prepare(images, dtb)
383
384 # Prepare the device tree by making sure that any missing
385 # properties are added (e.g. 'pos' and 'size'). The values of these
386 # may not be correct yet, but we add placeholders so that the
387 # size of the device tree is correct. Later, in
388 # SetCalculatedProperties() we will insert the correct values
389 # without changing the device-tree size, thus ensuring that our
390 # entry offsets remain the same.
391 for image in images.values():
392 image.ExpandEntries()
393 if update_fdt:
394 image.AddMissingProperties()
395 image.ProcessFdt(dtb)
396
Simon Glass4bdd1152019-07-20 12:23:29 -0600397 for dtb_item in state.GetAllFdts():
Simon Glassa8573c42019-07-20 12:23:27 -0600398 dtb_item.Sync(auto_resize=True)
399 dtb_item.Pack()
400 dtb_item.Flush()
401 return images
402
403
Simon Glass51014aa2019-07-20 12:23:56 -0600404def ProcessImage(image, update_fdt, write_map, get_contents=True,
Simon Glass4f9f1052020-07-09 18:39:38 -0600405 allow_resize=True, allow_missing=False):
Simon Glassb88e81c2019-07-20 12:23:24 -0600406 """Perform all steps for this image, including checking and # writing it.
407
408 This means that errors found with a later image will be reported after
409 earlier images are already completed and written, but that does not seem
410 important.
411
412 Args:
413 image: Image to process
414 update_fdt: True to update the FDT wth entry offsets, etc.
415 write_map: True to write a map file
Simon Glass10f9d002019-07-20 12:23:50 -0600416 get_contents: True to get the image contents from files, etc., False if
417 the contents is already present
Simon Glass51014aa2019-07-20 12:23:56 -0600418 allow_resize: True to allow entries to change size (this does a re-pack
419 of the entries), False to raise an exception
Simon Glass4f9f1052020-07-09 18:39:38 -0600420 allow_missing: Allow blob_ext objects to be missing
Simon Glassb1cca952020-07-09 18:39:40 -0600421
422 Returns:
423 True if one or more external blobs are missing, False if all are present
Simon Glassb88e81c2019-07-20 12:23:24 -0600424 """
Simon Glass10f9d002019-07-20 12:23:50 -0600425 if get_contents:
Simon Glass4f9f1052020-07-09 18:39:38 -0600426 image.SetAllowMissing(allow_missing)
Simon Glass10f9d002019-07-20 12:23:50 -0600427 image.GetEntryContents()
Simon Glassb88e81c2019-07-20 12:23:24 -0600428 image.GetEntryOffsets()
429
430 # We need to pack the entries to figure out where everything
431 # should be placed. This sets the offset/size of each entry.
432 # However, after packing we call ProcessEntryContents() which
433 # may result in an entry changing size. In that case we need to
434 # do another pass. Since the device tree often contains the
435 # final offset/size information we try to make space for this in
436 # AddMissingProperties() above. However, if the device is
437 # compressed we cannot know this compressed size in advance,
438 # since changing an offset from 0x100 to 0x104 (for example) can
439 # alter the compressed size of the device tree. So we need a
440 # third pass for this.
Simon Glasseb0f4a42019-07-20 12:24:06 -0600441 passes = 5
Simon Glassb88e81c2019-07-20 12:23:24 -0600442 for pack_pass in range(passes):
443 try:
444 image.PackEntries()
445 image.CheckSize()
446 image.CheckEntries()
447 except Exception as e:
448 if write_map:
449 fname = image.WriteMap()
450 print("Wrote map file '%s' to show errors" % fname)
451 raise
452 image.SetImagePos()
453 if update_fdt:
454 image.SetCalculatedProperties()
Simon Glass4bdd1152019-07-20 12:23:29 -0600455 for dtb_item in state.GetAllFdts():
Simon Glassb88e81c2019-07-20 12:23:24 -0600456 dtb_item.Sync()
Simon Glass51014aa2019-07-20 12:23:56 -0600457 dtb_item.Flush()
Simon Glass261cbe02019-08-24 07:23:12 -0600458 image.WriteSymbols()
Simon Glassb88e81c2019-07-20 12:23:24 -0600459 sizes_ok = image.ProcessEntryContents()
460 if sizes_ok:
461 break
462 image.ResetForPack()
Simon Glassaed6c0b2019-08-24 07:23:13 -0600463 tout.Info('Pack completed after %d pass(es)' % (pack_pass + 1))
Simon Glassb88e81c2019-07-20 12:23:24 -0600464 if not sizes_ok:
Simon Glass61ec04f2019-07-20 12:23:58 -0600465 image.Raise('Entries changed size after packing (tried %s passes)' %
Simon Glassb88e81c2019-07-20 12:23:24 -0600466 passes)
467
Simon Glassb88e81c2019-07-20 12:23:24 -0600468 image.BuildImage()
469 if write_map:
470 image.WriteMap()
Simon Glassb1cca952020-07-09 18:39:40 -0600471 missing_list = []
472 image.CheckMissing(missing_list)
473 if missing_list:
474 tout.Warning("Image '%s' is missing external blobs and is non-functional: %s" %
475 (image.name, ' '.join([e.name for e in missing_list])))
476 return bool(missing_list)
Simon Glassb88e81c2019-07-20 12:23:24 -0600477
478
Simon Glass53cd5d92019-07-08 14:25:29 -0600479def Binman(args):
Simon Glassbf7fd502016-11-25 20:15:51 -0700480 """The main control code for binman
481
482 This assumes that help and test options have already been dealt with. It
483 deals with the core task of building images.
484
485 Args:
Simon Glass53cd5d92019-07-08 14:25:29 -0600486 args: Command line arguments Namespace object
Simon Glassbf7fd502016-11-25 20:15:51 -0700487 """
Simon Glass8dbb7442019-08-24 07:22:44 -0600488 global Image
489 global state
490
Simon Glass53cd5d92019-07-08 14:25:29 -0600491 if args.full_help:
Simon Glassbf7fd502016-11-25 20:15:51 -0700492 pager = os.getenv('PAGER')
493 if not pager:
494 pager = 'more'
495 fname = os.path.join(os.path.dirname(os.path.realpath(sys.argv[0])),
496 'README')
497 command.Run(pager, fname)
498 return 0
499
Simon Glass8dbb7442019-08-24 07:22:44 -0600500 # Put these here so that we can import this module without libfdt
Simon Glass07237982020-08-05 13:27:47 -0600501 from binman.image import Image
Simon Glass16287932020-04-17 18:09:03 -0600502 from binman import state
Simon Glass8dbb7442019-08-24 07:22:44 -0600503
Simon Glass7bc4f0f2019-09-15 18:10:36 -0600504 if args.cmd in ['ls', 'extract', 'replace']:
Simon Glass96b6c502019-07-20 12:23:53 -0600505 try:
Simon Glass7bc4f0f2019-09-15 18:10:36 -0600506 tout.Init(args.verbosity)
Simon Glass96b6c502019-07-20 12:23:53 -0600507 tools.PrepareOutputDir(None)
Simon Glass7bc4f0f2019-09-15 18:10:36 -0600508 if args.cmd == 'ls':
509 ListEntries(args.image, args.paths)
Simon Glass61f564d2019-07-08 14:25:48 -0600510
Simon Glass7bc4f0f2019-09-15 18:10:36 -0600511 if args.cmd == 'extract':
512 ExtractEntries(args.image, args.filename, args.outdir, args.paths,
513 not args.uncompressed)
Simon Glass71ce0ba2019-07-08 14:25:52 -0600514
Simon Glass7bc4f0f2019-09-15 18:10:36 -0600515 if args.cmd == 'replace':
516 ReplaceEntries(args.image, args.filename, args.indir, args.paths,
517 do_compress=not args.compressed,
518 allow_resize=not args.fix_size, write_map=args.map)
519 except:
520 raise
Simon Glassa6cb9952019-07-20 12:24:15 -0600521 finally:
522 tools.FinaliseOutputDir()
523 return 0
524
Simon Glassbf7fd502016-11-25 20:15:51 -0700525 # Try to figure out which device tree contains our image description
Simon Glass53cd5d92019-07-08 14:25:29 -0600526 if args.dt:
527 dtb_fname = args.dt
Simon Glassbf7fd502016-11-25 20:15:51 -0700528 else:
Simon Glass53cd5d92019-07-08 14:25:29 -0600529 board = args.board
Simon Glassbf7fd502016-11-25 20:15:51 -0700530 if not board:
531 raise ValueError('Must provide a board to process (use -b <board>)')
Simon Glass53cd5d92019-07-08 14:25:29 -0600532 board_pathname = os.path.join(args.build_dir, board)
Simon Glassbf7fd502016-11-25 20:15:51 -0700533 dtb_fname = os.path.join(board_pathname, 'u-boot.dtb')
Simon Glass53cd5d92019-07-08 14:25:29 -0600534 if not args.indir:
535 args.indir = ['.']
536 args.indir.append(board_pathname)
Simon Glassbf7fd502016-11-25 20:15:51 -0700537
538 try:
Simon Glass53cd5d92019-07-08 14:25:29 -0600539 tout.Init(args.verbosity)
540 elf.debug = args.debug
541 cbfs_util.VERBOSE = args.verbosity > 2
542 state.use_fake_dtb = args.fake_dtb
Simon Glassbf7fd502016-11-25 20:15:51 -0700543 try:
Simon Glass53cd5d92019-07-08 14:25:29 -0600544 tools.SetInputDirs(args.indir)
545 tools.PrepareOutputDir(args.outdir, args.preserve)
546 tools.SetToolPaths(args.toolpath)
547 state.SetEntryArgs(args.entry_arg)
Simon Glassecab8972018-07-06 10:27:40 -0600548
Simon Glassa8573c42019-07-20 12:23:27 -0600549 images = PrepareImagesAndDtbs(dtb_fname, args.image,
550 args.update_fdt)
Simon Glassb1cca952020-07-09 18:39:40 -0600551 missing = False
Simon Glassbf7fd502016-11-25 20:15:51 -0700552 for image in images.values():
Simon Glassb1cca952020-07-09 18:39:40 -0600553 missing |= ProcessImage(image, args.update_fdt, args.map,
554 allow_missing=args.allow_missing)
Simon Glass2a72cc72018-09-14 04:57:20 -0600555
556 # Write the updated FDTs to our output files
Simon Glass4bdd1152019-07-20 12:23:29 -0600557 for dtb_item in state.GetAllFdts():
Simon Glass2a72cc72018-09-14 04:57:20 -0600558 tools.WriteFile(dtb_item._fname, dtb_item.GetContents())
559
Simon Glassb1cca952020-07-09 18:39:40 -0600560 if missing:
561 tout.Warning("Some images are invalid")
Simon Glassbf7fd502016-11-25 20:15:51 -0700562 finally:
563 tools.FinaliseOutputDir()
564 finally:
565 tout.Uninit()
566
567 return 0