blob: 15bfac582a7eaa75880e62087482706da9749dcf [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.
Simon Glasse9d336d2020-09-01 05:13:55 -0600349
350 Returns:
351 OrderedDict of images:
352 key: Image name (str)
353 value: Image object
Simon Glassa8573c42019-07-20 12:23:27 -0600354 """
355 # Import these here in case libfdt.py is not available, in which case
356 # the above help option still works.
Simon Glass16287932020-04-17 18:09:03 -0600357 from dtoc import fdt
358 from dtoc import fdt_util
Simon Glassa8573c42019-07-20 12:23:27 -0600359 global images
360
361 # Get the device tree ready by compiling it and copying the compiled
362 # output into a file in our output directly. Then scan it for use
363 # in binman.
364 dtb_fname = fdt_util.EnsureCompiled(dtb_fname)
365 fname = tools.GetOutputFilename('u-boot.dtb.out')
366 tools.WriteFile(fname, tools.ReadFile(dtb_fname))
367 dtb = fdt.FdtScan(fname)
368
369 node = _FindBinmanNode(dtb)
370 if not node:
371 raise ValueError("Device tree '%s' does not have a 'binman' "
372 "node" % dtb_fname)
373
374 images = _ReadImageDesc(node)
375
376 if select_images:
377 skip = []
378 new_images = OrderedDict()
379 for name, image in images.items():
380 if name in select_images:
381 new_images[name] = image
382 else:
383 skip.append(name)
384 images = new_images
385 tout.Notice('Skipping images: %s' % ', '.join(skip))
386
387 state.Prepare(images, dtb)
388
389 # Prepare the device tree by making sure that any missing
390 # properties are added (e.g. 'pos' and 'size'). The values of these
391 # may not be correct yet, but we add placeholders so that the
392 # size of the device tree is correct. Later, in
393 # SetCalculatedProperties() we will insert the correct values
394 # without changing the device-tree size, thus ensuring that our
395 # entry offsets remain the same.
396 for image in images.values():
397 image.ExpandEntries()
398 if update_fdt:
399 image.AddMissingProperties()
400 image.ProcessFdt(dtb)
401
Simon Glass4bdd1152019-07-20 12:23:29 -0600402 for dtb_item in state.GetAllFdts():
Simon Glassa8573c42019-07-20 12:23:27 -0600403 dtb_item.Sync(auto_resize=True)
404 dtb_item.Pack()
405 dtb_item.Flush()
406 return images
407
408
Simon Glass51014aa2019-07-20 12:23:56 -0600409def ProcessImage(image, update_fdt, write_map, get_contents=True,
Simon Glass4f9f1052020-07-09 18:39:38 -0600410 allow_resize=True, allow_missing=False):
Simon Glassb88e81c2019-07-20 12:23:24 -0600411 """Perform all steps for this image, including checking and # writing it.
412
413 This means that errors found with a later image will be reported after
414 earlier images are already completed and written, but that does not seem
415 important.
416
417 Args:
418 image: Image to process
419 update_fdt: True to update the FDT wth entry offsets, etc.
420 write_map: True to write a map file
Simon Glass10f9d002019-07-20 12:23:50 -0600421 get_contents: True to get the image contents from files, etc., False if
422 the contents is already present
Simon Glass51014aa2019-07-20 12:23:56 -0600423 allow_resize: True to allow entries to change size (this does a re-pack
424 of the entries), False to raise an exception
Simon Glass4f9f1052020-07-09 18:39:38 -0600425 allow_missing: Allow blob_ext objects to be missing
Simon Glassb1cca952020-07-09 18:39:40 -0600426
427 Returns:
428 True if one or more external blobs are missing, False if all are present
Simon Glassb88e81c2019-07-20 12:23:24 -0600429 """
Simon Glass10f9d002019-07-20 12:23:50 -0600430 if get_contents:
Simon Glass4f9f1052020-07-09 18:39:38 -0600431 image.SetAllowMissing(allow_missing)
Simon Glass10f9d002019-07-20 12:23:50 -0600432 image.GetEntryContents()
Simon Glassb88e81c2019-07-20 12:23:24 -0600433 image.GetEntryOffsets()
434
435 # We need to pack the entries to figure out where everything
436 # should be placed. This sets the offset/size of each entry.
437 # However, after packing we call ProcessEntryContents() which
438 # may result in an entry changing size. In that case we need to
439 # do another pass. Since the device tree often contains the
440 # final offset/size information we try to make space for this in
441 # AddMissingProperties() above. However, if the device is
442 # compressed we cannot know this compressed size in advance,
443 # since changing an offset from 0x100 to 0x104 (for example) can
444 # alter the compressed size of the device tree. So we need a
445 # third pass for this.
Simon Glasseb0f4a42019-07-20 12:24:06 -0600446 passes = 5
Simon Glassb88e81c2019-07-20 12:23:24 -0600447 for pack_pass in range(passes):
448 try:
449 image.PackEntries()
450 image.CheckSize()
451 image.CheckEntries()
452 except Exception as e:
453 if write_map:
454 fname = image.WriteMap()
455 print("Wrote map file '%s' to show errors" % fname)
456 raise
457 image.SetImagePos()
458 if update_fdt:
459 image.SetCalculatedProperties()
Simon Glass4bdd1152019-07-20 12:23:29 -0600460 for dtb_item in state.GetAllFdts():
Simon Glassb88e81c2019-07-20 12:23:24 -0600461 dtb_item.Sync()
Simon Glass51014aa2019-07-20 12:23:56 -0600462 dtb_item.Flush()
Simon Glass261cbe02019-08-24 07:23:12 -0600463 image.WriteSymbols()
Simon Glassb88e81c2019-07-20 12:23:24 -0600464 sizes_ok = image.ProcessEntryContents()
465 if sizes_ok:
466 break
467 image.ResetForPack()
Simon Glassaed6c0b2019-08-24 07:23:13 -0600468 tout.Info('Pack completed after %d pass(es)' % (pack_pass + 1))
Simon Glassb88e81c2019-07-20 12:23:24 -0600469 if not sizes_ok:
Simon Glass61ec04f2019-07-20 12:23:58 -0600470 image.Raise('Entries changed size after packing (tried %s passes)' %
Simon Glassb88e81c2019-07-20 12:23:24 -0600471 passes)
472
Simon Glassb88e81c2019-07-20 12:23:24 -0600473 image.BuildImage()
474 if write_map:
475 image.WriteMap()
Simon Glassb1cca952020-07-09 18:39:40 -0600476 missing_list = []
477 image.CheckMissing(missing_list)
478 if missing_list:
479 tout.Warning("Image '%s' is missing external blobs and is non-functional: %s" %
480 (image.name, ' '.join([e.name for e in missing_list])))
481 return bool(missing_list)
Simon Glassb88e81c2019-07-20 12:23:24 -0600482
483
Simon Glass53cd5d92019-07-08 14:25:29 -0600484def Binman(args):
Simon Glassbf7fd502016-11-25 20:15:51 -0700485 """The main control code for binman
486
487 This assumes that help and test options have already been dealt with. It
488 deals with the core task of building images.
489
490 Args:
Simon Glass53cd5d92019-07-08 14:25:29 -0600491 args: Command line arguments Namespace object
Simon Glassbf7fd502016-11-25 20:15:51 -0700492 """
Simon Glass8dbb7442019-08-24 07:22:44 -0600493 global Image
494 global state
495
Simon Glass53cd5d92019-07-08 14:25:29 -0600496 if args.full_help:
Simon Glassbf7fd502016-11-25 20:15:51 -0700497 pager = os.getenv('PAGER')
498 if not pager:
499 pager = 'more'
500 fname = os.path.join(os.path.dirname(os.path.realpath(sys.argv[0])),
501 'README')
502 command.Run(pager, fname)
503 return 0
504
Simon Glass8dbb7442019-08-24 07:22:44 -0600505 # Put these here so that we can import this module without libfdt
Simon Glass07237982020-08-05 13:27:47 -0600506 from binman.image import Image
Simon Glass16287932020-04-17 18:09:03 -0600507 from binman import state
Simon Glass8dbb7442019-08-24 07:22:44 -0600508
Simon Glass7bc4f0f2019-09-15 18:10:36 -0600509 if args.cmd in ['ls', 'extract', 'replace']:
Simon Glass96b6c502019-07-20 12:23:53 -0600510 try:
Simon Glass7bc4f0f2019-09-15 18:10:36 -0600511 tout.Init(args.verbosity)
Simon Glass96b6c502019-07-20 12:23:53 -0600512 tools.PrepareOutputDir(None)
Simon Glass7bc4f0f2019-09-15 18:10:36 -0600513 if args.cmd == 'ls':
514 ListEntries(args.image, args.paths)
Simon Glass61f564d2019-07-08 14:25:48 -0600515
Simon Glass7bc4f0f2019-09-15 18:10:36 -0600516 if args.cmd == 'extract':
517 ExtractEntries(args.image, args.filename, args.outdir, args.paths,
518 not args.uncompressed)
Simon Glass71ce0ba2019-07-08 14:25:52 -0600519
Simon Glass7bc4f0f2019-09-15 18:10:36 -0600520 if args.cmd == 'replace':
521 ReplaceEntries(args.image, args.filename, args.indir, args.paths,
522 do_compress=not args.compressed,
523 allow_resize=not args.fix_size, write_map=args.map)
524 except:
525 raise
Simon Glassa6cb9952019-07-20 12:24:15 -0600526 finally:
527 tools.FinaliseOutputDir()
528 return 0
529
Simon Glassbf7fd502016-11-25 20:15:51 -0700530 # Try to figure out which device tree contains our image description
Simon Glass53cd5d92019-07-08 14:25:29 -0600531 if args.dt:
532 dtb_fname = args.dt
Simon Glassbf7fd502016-11-25 20:15:51 -0700533 else:
Simon Glass53cd5d92019-07-08 14:25:29 -0600534 board = args.board
Simon Glassbf7fd502016-11-25 20:15:51 -0700535 if not board:
536 raise ValueError('Must provide a board to process (use -b <board>)')
Simon Glass53cd5d92019-07-08 14:25:29 -0600537 board_pathname = os.path.join(args.build_dir, board)
Simon Glassbf7fd502016-11-25 20:15:51 -0700538 dtb_fname = os.path.join(board_pathname, 'u-boot.dtb')
Simon Glass53cd5d92019-07-08 14:25:29 -0600539 if not args.indir:
540 args.indir = ['.']
541 args.indir.append(board_pathname)
Simon Glassbf7fd502016-11-25 20:15:51 -0700542
543 try:
Simon Glass53cd5d92019-07-08 14:25:29 -0600544 tout.Init(args.verbosity)
545 elf.debug = args.debug
546 cbfs_util.VERBOSE = args.verbosity > 2
547 state.use_fake_dtb = args.fake_dtb
Simon Glassbf7fd502016-11-25 20:15:51 -0700548 try:
Simon Glass53cd5d92019-07-08 14:25:29 -0600549 tools.SetInputDirs(args.indir)
550 tools.PrepareOutputDir(args.outdir, args.preserve)
551 tools.SetToolPaths(args.toolpath)
552 state.SetEntryArgs(args.entry_arg)
Simon Glassecab8972018-07-06 10:27:40 -0600553
Simon Glassa8573c42019-07-20 12:23:27 -0600554 images = PrepareImagesAndDtbs(dtb_fname, args.image,
555 args.update_fdt)
Simon Glassb1cca952020-07-09 18:39:40 -0600556 missing = False
Simon Glassbf7fd502016-11-25 20:15:51 -0700557 for image in images.values():
Simon Glassb1cca952020-07-09 18:39:40 -0600558 missing |= ProcessImage(image, args.update_fdt, args.map,
559 allow_missing=args.allow_missing)
Simon Glass2a72cc72018-09-14 04:57:20 -0600560
561 # Write the updated FDTs to our output files
Simon Glass4bdd1152019-07-20 12:23:29 -0600562 for dtb_item in state.GetAllFdts():
Simon Glass2a72cc72018-09-14 04:57:20 -0600563 tools.WriteFile(dtb_item._fname, dtb_item.GetContents())
564
Simon Glassb1cca952020-07-09 18:39:40 -0600565 if missing:
566 tout.Warning("Some images are invalid")
Simon Glassbf7fd502016-11-25 20:15:51 -0700567 finally:
568 tools.FinaliseOutputDir()
569 finally:
570 tout.Uninit()
571
572 return 0