blob: 69c36ed658274f8bc6f2788eb5c0420255d29c8b [file] [log] [blame]
Tom Rini10e47792018-05-06 17:58:06 -04001# SPDX-License-Identifier: GPL-2.0+
Simon Glass2574ef62016-11-25 20:15:51 -07002# Copyright (c) 2016 Google, Inc
3# Written by Simon Glass <sjg@chromium.org>
4#
Simon Glass2574ef62016-11-25 20:15:51 -07005# Creates binary images from input files controlled by a description
6#
7
8from collections import OrderedDict
Simon Glass220ff5f2020-08-05 13:27:46 -06009import glob
Simon Glass2574ef62016-11-25 20:15:51 -070010import os
11import sys
Simon Glassa997ea52020-04-17 18:09:04 -060012from patman import tools
Simon Glass2574ef62016-11-25 20:15:51 -070013
Simon Glassc585dd42020-04-17 18:09:03 -060014from binman import cbfs_util
15from binman import elf
Simon Glassa997ea52020-04-17 18:09:04 -060016from patman import command
17from patman import tout
Simon Glass2574ef62016-11-25 20:15:51 -070018
19# List of images we plan to create
20# Make this global so that it can be referenced from tests
21images = OrderedDict()
22
23def _ReadImageDesc(binman_node):
24 """Read the image descriptions from the /binman node
25
26 This normally produces a single Image object called 'image'. But if
27 multiple images are present, they will all be returned.
28
29 Args:
30 binman_node: Node object of the /binman node
31 Returns:
32 OrderedDict of Image objects, each of which describes an image
33 """
34 images = OrderedDict()
35 if 'multiple-images' in binman_node.props:
36 for node in binman_node.subnodes:
37 images[node.name] = Image(node.name, node)
38 else:
39 images['image'] = Image('image', binman_node)
40 return images
41
Simon Glass22c92ca2017-05-27 07:38:29 -060042def _FindBinmanNode(dtb):
Simon Glass2574ef62016-11-25 20:15:51 -070043 """Find the 'binman' node in the device tree
44
45 Args:
Simon Glass22c92ca2017-05-27 07:38:29 -060046 dtb: Fdt object to scan
Simon Glass2574ef62016-11-25 20:15:51 -070047 Returns:
48 Node object of /binman node, or None if not found
49 """
Simon Glass22c92ca2017-05-27 07:38:29 -060050 for node in dtb.GetRoot().subnodes:
Simon Glass2574ef62016-11-25 20:15:51 -070051 if node.name == 'binman':
52 return node
53 return None
54
Simon Glass220ff5f2020-08-05 13:27:46 -060055def GetEntryModules(include_testing=True):
56 """Get a set of entry class implementations
57
58 Returns:
59 Set of paths to entry class filenames
60 """
61 our_path = os.path.dirname(os.path.realpath(__file__))
62 glob_list = glob.glob(os.path.join(our_path, 'etype/*.py'))
63 return set([os.path.splitext(os.path.basename(item))[0]
64 for item in glob_list
65 if include_testing or '_testing' not in item])
66
Simon Glass29aa7362018-09-14 04:57:19 -060067def WriteEntryDocs(modules, test_missing=None):
68 """Write out documentation for all entries
Simon Glass92307732018-07-06 10:27:40 -060069
70 Args:
Simon Glass29aa7362018-09-14 04:57:19 -060071 modules: List of Module objects to get docs for
72 test_missing: Used for testing only, to force an entry's documeentation
73 to show as missing even if it is present. Should be set to None in
74 normal use.
Simon Glass92307732018-07-06 10:27:40 -060075 """
Simon Glassc585dd42020-04-17 18:09:03 -060076 from binman.entry import Entry
Simon Glass969616c2018-07-17 13:25:36 -060077 Entry.WriteDocs(modules, test_missing)
78
Simon Glassb2fd11d2019-07-08 14:25:48 -060079
80def ListEntries(image_fname, entry_paths):
81 """List the entries in an image
82
83 This decodes the supplied image and displays a table of entries from that
84 image, preceded by a header.
85
86 Args:
87 image_fname: Image filename to process
88 entry_paths: List of wildcarded paths (e.g. ['*dtb*', 'u-boot*',
89 'section/u-boot'])
90 """
91 image = Image.FromFile(image_fname)
92
93 entries, lines, widths = image.GetListEntries(entry_paths)
94
95 num_columns = len(widths)
96 for linenum, line in enumerate(lines):
97 if linenum == 1:
98 # Print header line
99 print('-' * (sum(widths) + num_columns * 2))
100 out = ''
101 for i, item in enumerate(line):
102 width = -widths[i]
103 if item.startswith('>'):
104 width = -width
105 item = item[1:]
106 txt = '%*s ' % (width, item)
107 out += txt
108 print(out.rstrip())
109
Simon Glass4c613bf2019-07-08 14:25:50 -0600110
111def ReadEntry(image_fname, entry_path, decomp=True):
112 """Extract an entry from an image
113
114 This extracts the data from a particular entry in an image
115
116 Args:
117 image_fname: Image filename to process
118 entry_path: Path to entry to extract
119 decomp: True to return uncompressed data, if the data is compress
120 False to return the raw data
121
122 Returns:
123 data extracted from the entry
124 """
Simon Glassb9ba4e02019-08-24 07:22:44 -0600125 global Image
126 from image import Image
127
Simon Glass4c613bf2019-07-08 14:25:50 -0600128 image = Image.FromFile(image_fname)
129 entry = image.FindEntryPath(entry_path)
130 return entry.ReadData(decomp)
131
132
Simon Glass980a2842019-07-08 14:25:52 -0600133def ExtractEntries(image_fname, output_fname, outdir, entry_paths,
134 decomp=True):
135 """Extract the data from one or more entries and write it to files
136
137 Args:
138 image_fname: Image filename to process
139 output_fname: Single output filename to use if extracting one file, None
140 otherwise
141 outdir: Output directory to use (for any number of files), else None
142 entry_paths: List of entry paths to extract
Simon Glassd48f94e2019-07-20 12:24:12 -0600143 decomp: True to decompress the entry data
Simon Glass980a2842019-07-08 14:25:52 -0600144
145 Returns:
146 List of EntryInfo records that were written
147 """
148 image = Image.FromFile(image_fname)
149
150 # Output an entry to a single file, as a special case
151 if output_fname:
152 if not entry_paths:
Simon Glassa772d3f2019-07-20 12:24:14 -0600153 raise ValueError('Must specify an entry path to write with -f')
Simon Glass980a2842019-07-08 14:25:52 -0600154 if len(entry_paths) != 1:
Simon Glassa772d3f2019-07-20 12:24:14 -0600155 raise ValueError('Must specify exactly one entry path to write with -f')
Simon Glass980a2842019-07-08 14:25:52 -0600156 entry = image.FindEntryPath(entry_paths[0])
157 data = entry.ReadData(decomp)
158 tools.WriteFile(output_fname, data)
159 tout.Notice("Wrote %#x bytes to file '%s'" % (len(data), output_fname))
160 return
161
162 # Otherwise we will output to a path given by the entry path of each entry.
163 # This means that entries will appear in subdirectories if they are part of
164 # a sub-section.
165 einfos = image.GetListEntries(entry_paths)[0]
166 tout.Notice('%d entries match and will be written' % len(einfos))
167 for einfo in einfos:
168 entry = einfo.entry
169 data = entry.ReadData(decomp)
170 path = entry.GetPath()[1:]
171 fname = os.path.join(outdir, path)
172
173 # If this entry has children, create a directory for it and put its
174 # data in a file called 'root' in that directory
175 if entry.GetEntries():
176 if not os.path.exists(fname):
177 os.makedirs(fname)
178 fname = os.path.join(fname, 'root')
179 tout.Notice("Write entry '%s' to '%s'" % (entry.GetPath(), fname))
180 tools.WriteFile(fname, data)
181 return einfos
182
183
Simon Glass274bd0e2019-07-20 12:24:13 -0600184def BeforeReplace(image, allow_resize):
185 """Handle getting an image ready for replacing entries in it
186
187 Args:
188 image: Image to prepare
189 """
190 state.PrepareFromLoadedData(image)
191 image.LoadData()
192
193 # If repacking, drop the old offset/size values except for the original
194 # ones, so we are only left with the constraints.
195 if allow_resize:
196 image.ResetForPack()
197
198
199def ReplaceOneEntry(image, entry, data, do_compress, allow_resize):
200 """Handle replacing a single entry an an image
201
202 Args:
203 image: Image to update
204 entry: Entry to write
205 data: Data to replace with
206 do_compress: True to compress the data if needed, False if data is
207 already compressed so should be used as is
208 allow_resize: True to allow entries to change size (this does a re-pack
209 of the entries), False to raise an exception
210 """
211 if not entry.WriteData(data, do_compress):
212 if not image.allow_repack:
213 entry.Raise('Entry data size does not match, but allow-repack is not present for this image')
214 if not allow_resize:
215 entry.Raise('Entry data size does not match, but resize is disabled')
216
217
218def AfterReplace(image, allow_resize, write_map):
219 """Handle write out an image after replacing entries in it
220
221 Args:
222 image: Image to write
223 allow_resize: True to allow entries to change size (this does a re-pack
224 of the entries), False to raise an exception
225 write_map: True to write a map file
226 """
227 tout.Info('Processing image')
228 ProcessImage(image, update_fdt=True, write_map=write_map,
229 get_contents=False, allow_resize=allow_resize)
230
231
232def WriteEntryToImage(image, entry, data, do_compress=True, allow_resize=True,
233 write_map=False):
234 BeforeReplace(image, allow_resize)
235 tout.Info('Writing data to %s' % entry.GetPath())
236 ReplaceOneEntry(image, entry, data, do_compress, allow_resize)
237 AfterReplace(image, allow_resize=allow_resize, write_map=write_map)
238
239
Simon Glassd48f94e2019-07-20 12:24:12 -0600240def WriteEntry(image_fname, entry_path, data, do_compress=True,
241 allow_resize=True, write_map=False):
Simon Glass3971c952019-07-20 12:24:11 -0600242 """Replace an entry in an image
243
244 This replaces the data in a particular entry in an image. This size of the
245 new data must match the size of the old data unless allow_resize is True.
246
247 Args:
248 image_fname: Image filename to process
249 entry_path: Path to entry to extract
250 data: Data to replace with
Simon Glassd48f94e2019-07-20 12:24:12 -0600251 do_compress: True to compress the data if needed, False if data is
Simon Glass3971c952019-07-20 12:24:11 -0600252 already compressed so should be used as is
253 allow_resize: True to allow entries to change size (this does a re-pack
254 of the entries), False to raise an exception
Simon Glassd48f94e2019-07-20 12:24:12 -0600255 write_map: True to write a map file
Simon Glass3971c952019-07-20 12:24:11 -0600256
257 Returns:
258 Image object that was updated
259 """
Simon Glass274bd0e2019-07-20 12:24:13 -0600260 tout.Info("Write entry '%s', file '%s'" % (entry_path, image_fname))
Simon Glass3971c952019-07-20 12:24:11 -0600261 image = Image.FromFile(image_fname)
262 entry = image.FindEntryPath(entry_path)
Simon Glass274bd0e2019-07-20 12:24:13 -0600263 WriteEntryToImage(image, entry, data, do_compress=do_compress,
264 allow_resize=allow_resize, write_map=write_map)
Simon Glass3971c952019-07-20 12:24:11 -0600265
Simon Glass3971c952019-07-20 12:24:11 -0600266 return image
267
Simon Glass30033c22019-07-20 12:24:15 -0600268
269def ReplaceEntries(image_fname, input_fname, indir, entry_paths,
270 do_compress=True, allow_resize=True, write_map=False):
271 """Replace the data from one or more entries from input files
272
273 Args:
274 image_fname: Image filename to process
275 input_fname: Single input ilename to use if replacing one file, None
276 otherwise
277 indir: Input directory to use (for any number of files), else None
278 entry_paths: List of entry paths to extract
279 do_compress: True if the input data is uncompressed and may need to be
280 compressed if the entry requires it, False if the data is already
281 compressed.
282 write_map: True to write a map file
283
284 Returns:
285 List of EntryInfo records that were written
286 """
287 image = Image.FromFile(image_fname)
288
289 # Replace an entry from a single file, as a special case
290 if input_fname:
291 if not entry_paths:
292 raise ValueError('Must specify an entry path to read with -f')
293 if len(entry_paths) != 1:
294 raise ValueError('Must specify exactly one entry path to write with -f')
295 entry = image.FindEntryPath(entry_paths[0])
296 data = tools.ReadFile(input_fname)
297 tout.Notice("Read %#x bytes from file '%s'" % (len(data), input_fname))
298 WriteEntryToImage(image, entry, data, do_compress=do_compress,
299 allow_resize=allow_resize, write_map=write_map)
300 return
301
302 # Otherwise we will input from a path given by the entry path of each entry.
303 # This means that files must appear in subdirectories if they are part of
304 # a sub-section.
305 einfos = image.GetListEntries(entry_paths)[0]
306 tout.Notice("Replacing %d matching entries in image '%s'" %
307 (len(einfos), image_fname))
308
309 BeforeReplace(image, allow_resize)
310
311 for einfo in einfos:
312 entry = einfo.entry
313 if entry.GetEntries():
314 tout.Info("Skipping section entry '%s'" % entry.GetPath())
315 continue
316
317 path = entry.GetPath()[1:]
318 fname = os.path.join(indir, path)
319
320 if os.path.exists(fname):
321 tout.Notice("Write entry '%s' from file '%s'" %
322 (entry.GetPath(), fname))
323 data = tools.ReadFile(fname)
324 ReplaceOneEntry(image, entry, data, do_compress, allow_resize)
325 else:
326 tout.Warning("Skipping entry '%s' from missing file '%s'" %
327 (entry.GetPath(), fname))
328
329 AfterReplace(image, allow_resize=allow_resize, write_map=write_map)
330 return image
331
332
Simon Glassd3151ff2019-07-20 12:23:27 -0600333def PrepareImagesAndDtbs(dtb_fname, select_images, update_fdt):
334 """Prepare the images to be processed and select the device tree
335
336 This function:
337 - reads in the device tree
338 - finds and scans the binman node to create all entries
339 - selects which images to build
340 - Updates the device tress with placeholder properties for offset,
341 image-pos, etc.
342
343 Args:
344 dtb_fname: Filename of the device tree file to use (.dts or .dtb)
345 selected_images: List of images to output, or None for all
346 update_fdt: True to update the FDT wth entry offsets, etc.
347 """
348 # Import these here in case libfdt.py is not available, in which case
349 # the above help option still works.
Simon Glassc585dd42020-04-17 18:09:03 -0600350 from dtoc import fdt
351 from dtoc import fdt_util
Simon Glassd3151ff2019-07-20 12:23:27 -0600352 global images
353
354 # Get the device tree ready by compiling it and copying the compiled
355 # output into a file in our output directly. Then scan it for use
356 # in binman.
357 dtb_fname = fdt_util.EnsureCompiled(dtb_fname)
358 fname = tools.GetOutputFilename('u-boot.dtb.out')
359 tools.WriteFile(fname, tools.ReadFile(dtb_fname))
360 dtb = fdt.FdtScan(fname)
361
362 node = _FindBinmanNode(dtb)
363 if not node:
364 raise ValueError("Device tree '%s' does not have a 'binman' "
365 "node" % dtb_fname)
366
367 images = _ReadImageDesc(node)
368
369 if select_images:
370 skip = []
371 new_images = OrderedDict()
372 for name, image in images.items():
373 if name in select_images:
374 new_images[name] = image
375 else:
376 skip.append(name)
377 images = new_images
378 tout.Notice('Skipping images: %s' % ', '.join(skip))
379
380 state.Prepare(images, dtb)
381
382 # Prepare the device tree by making sure that any missing
383 # properties are added (e.g. 'pos' and 'size'). The values of these
384 # may not be correct yet, but we add placeholders so that the
385 # size of the device tree is correct. Later, in
386 # SetCalculatedProperties() we will insert the correct values
387 # without changing the device-tree size, thus ensuring that our
388 # entry offsets remain the same.
389 for image in images.values():
390 image.ExpandEntries()
391 if update_fdt:
392 image.AddMissingProperties()
393 image.ProcessFdt(dtb)
394
Simon Glass5a300602019-07-20 12:23:29 -0600395 for dtb_item in state.GetAllFdts():
Simon Glassd3151ff2019-07-20 12:23:27 -0600396 dtb_item.Sync(auto_resize=True)
397 dtb_item.Pack()
398 dtb_item.Flush()
399 return images
400
401
Simon Glassf8a54bc2019-07-20 12:23:56 -0600402def ProcessImage(image, update_fdt, write_map, get_contents=True,
Simon Glass5d94cc62020-07-09 18:39:38 -0600403 allow_resize=True, allow_missing=False):
Simon Glassb766c5e52019-07-20 12:23:24 -0600404 """Perform all steps for this image, including checking and # writing it.
405
406 This means that errors found with a later image will be reported after
407 earlier images are already completed and written, but that does not seem
408 important.
409
410 Args:
411 image: Image to process
412 update_fdt: True to update the FDT wth entry offsets, etc.
413 write_map: True to write a map file
Simon Glass072959a2019-07-20 12:23:50 -0600414 get_contents: True to get the image contents from files, etc., False if
415 the contents is already present
Simon Glassf8a54bc2019-07-20 12:23:56 -0600416 allow_resize: True to allow entries to change size (this does a re-pack
417 of the entries), False to raise an exception
Simon Glass5d94cc62020-07-09 18:39:38 -0600418 allow_missing: Allow blob_ext objects to be missing
Simon Glassa003cd32020-07-09 18:39:40 -0600419
420 Returns:
421 True if one or more external blobs are missing, False if all are present
Simon Glassb766c5e52019-07-20 12:23:24 -0600422 """
Simon Glass072959a2019-07-20 12:23:50 -0600423 if get_contents:
Simon Glass5d94cc62020-07-09 18:39:38 -0600424 image.SetAllowMissing(allow_missing)
Simon Glass072959a2019-07-20 12:23:50 -0600425 image.GetEntryContents()
Simon Glassb766c5e52019-07-20 12:23:24 -0600426 image.GetEntryOffsets()
427
428 # We need to pack the entries to figure out where everything
429 # should be placed. This sets the offset/size of each entry.
430 # However, after packing we call ProcessEntryContents() which
431 # may result in an entry changing size. In that case we need to
432 # do another pass. Since the device tree often contains the
433 # final offset/size information we try to make space for this in
434 # AddMissingProperties() above. However, if the device is
435 # compressed we cannot know this compressed size in advance,
436 # since changing an offset from 0x100 to 0x104 (for example) can
437 # alter the compressed size of the device tree. So we need a
438 # third pass for this.
Simon Glass37fdd142019-07-20 12:24:06 -0600439 passes = 5
Simon Glassb766c5e52019-07-20 12:23:24 -0600440 for pack_pass in range(passes):
441 try:
442 image.PackEntries()
443 image.CheckSize()
444 image.CheckEntries()
445 except Exception as e:
446 if write_map:
447 fname = image.WriteMap()
448 print("Wrote map file '%s' to show errors" % fname)
449 raise
450 image.SetImagePos()
451 if update_fdt:
452 image.SetCalculatedProperties()
Simon Glass5a300602019-07-20 12:23:29 -0600453 for dtb_item in state.GetAllFdts():
Simon Glassb766c5e52019-07-20 12:23:24 -0600454 dtb_item.Sync()
Simon Glassf8a54bc2019-07-20 12:23:56 -0600455 dtb_item.Flush()
Simon Glasse5943412019-08-24 07:23:12 -0600456 image.WriteSymbols()
Simon Glassb766c5e52019-07-20 12:23:24 -0600457 sizes_ok = image.ProcessEntryContents()
458 if sizes_ok:
459 break
460 image.ResetForPack()
Simon Glass6bf9b472019-08-24 07:23:13 -0600461 tout.Info('Pack completed after %d pass(es)' % (pack_pass + 1))
Simon Glassb766c5e52019-07-20 12:23:24 -0600462 if not sizes_ok:
Simon Glass9d8ee322019-07-20 12:23:58 -0600463 image.Raise('Entries changed size after packing (tried %s passes)' %
Simon Glassb766c5e52019-07-20 12:23:24 -0600464 passes)
465
Simon Glassb766c5e52019-07-20 12:23:24 -0600466 image.BuildImage()
467 if write_map:
468 image.WriteMap()
Simon Glassa003cd32020-07-09 18:39:40 -0600469 missing_list = []
470 image.CheckMissing(missing_list)
471 if missing_list:
472 tout.Warning("Image '%s' is missing external blobs and is non-functional: %s" %
473 (image.name, ' '.join([e.name for e in missing_list])))
474 return bool(missing_list)
Simon Glassb766c5e52019-07-20 12:23:24 -0600475
476
Simon Glassf46732a2019-07-08 14:25:29 -0600477def Binman(args):
Simon Glass2574ef62016-11-25 20:15:51 -0700478 """The main control code for binman
479
480 This assumes that help and test options have already been dealt with. It
481 deals with the core task of building images.
482
483 Args:
Simon Glassf46732a2019-07-08 14:25:29 -0600484 args: Command line arguments Namespace object
Simon Glass2574ef62016-11-25 20:15:51 -0700485 """
Simon Glassb9ba4e02019-08-24 07:22:44 -0600486 global Image
487 global state
488
Simon Glassf46732a2019-07-08 14:25:29 -0600489 if args.full_help:
Simon Glass2574ef62016-11-25 20:15:51 -0700490 pager = os.getenv('PAGER')
491 if not pager:
492 pager = 'more'
493 fname = os.path.join(os.path.dirname(os.path.realpath(sys.argv[0])),
494 'README')
495 command.Run(pager, fname)
496 return 0
497
Simon Glassb9ba4e02019-08-24 07:22:44 -0600498 # Put these here so that we can import this module without libfdt
499 from image import Image
Simon Glassc585dd42020-04-17 18:09:03 -0600500 from binman import state
Simon Glassb9ba4e02019-08-24 07:22:44 -0600501
Simon Glassdf08cbb2019-09-15 18:10:36 -0600502 if args.cmd in ['ls', 'extract', 'replace']:
Simon Glass9b7f5002019-07-20 12:23:53 -0600503 try:
Simon Glassdf08cbb2019-09-15 18:10:36 -0600504 tout.Init(args.verbosity)
Simon Glass9b7f5002019-07-20 12:23:53 -0600505 tools.PrepareOutputDir(None)
Simon Glassdf08cbb2019-09-15 18:10:36 -0600506 if args.cmd == 'ls':
507 ListEntries(args.image, args.paths)
Simon Glassb2fd11d2019-07-08 14:25:48 -0600508
Simon Glassdf08cbb2019-09-15 18:10:36 -0600509 if args.cmd == 'extract':
510 ExtractEntries(args.image, args.filename, args.outdir, args.paths,
511 not args.uncompressed)
Simon Glass980a2842019-07-08 14:25:52 -0600512
Simon Glassdf08cbb2019-09-15 18:10:36 -0600513 if args.cmd == 'replace':
514 ReplaceEntries(args.image, args.filename, args.indir, args.paths,
515 do_compress=not args.compressed,
516 allow_resize=not args.fix_size, write_map=args.map)
517 except:
518 raise
Simon Glass30033c22019-07-20 12:24:15 -0600519 finally:
520 tools.FinaliseOutputDir()
521 return 0
522
Simon Glass2574ef62016-11-25 20:15:51 -0700523 # Try to figure out which device tree contains our image description
Simon Glassf46732a2019-07-08 14:25:29 -0600524 if args.dt:
525 dtb_fname = args.dt
Simon Glass2574ef62016-11-25 20:15:51 -0700526 else:
Simon Glassf46732a2019-07-08 14:25:29 -0600527 board = args.board
Simon Glass2574ef62016-11-25 20:15:51 -0700528 if not board:
529 raise ValueError('Must provide a board to process (use -b <board>)')
Simon Glassf46732a2019-07-08 14:25:29 -0600530 board_pathname = os.path.join(args.build_dir, board)
Simon Glass2574ef62016-11-25 20:15:51 -0700531 dtb_fname = os.path.join(board_pathname, 'u-boot.dtb')
Simon Glassf46732a2019-07-08 14:25:29 -0600532 if not args.indir:
533 args.indir = ['.']
534 args.indir.append(board_pathname)
Simon Glass2574ef62016-11-25 20:15:51 -0700535
536 try:
Simon Glassf46732a2019-07-08 14:25:29 -0600537 tout.Init(args.verbosity)
538 elf.debug = args.debug
539 cbfs_util.VERBOSE = args.verbosity > 2
540 state.use_fake_dtb = args.fake_dtb
Simon Glass2574ef62016-11-25 20:15:51 -0700541 try:
Simon Glassf46732a2019-07-08 14:25:29 -0600542 tools.SetInputDirs(args.indir)
543 tools.PrepareOutputDir(args.outdir, args.preserve)
544 tools.SetToolPaths(args.toolpath)
545 state.SetEntryArgs(args.entry_arg)
Simon Glass92307732018-07-06 10:27:40 -0600546
Simon Glassd3151ff2019-07-20 12:23:27 -0600547 images = PrepareImagesAndDtbs(dtb_fname, args.image,
548 args.update_fdt)
Simon Glassa003cd32020-07-09 18:39:40 -0600549 missing = False
Simon Glass2574ef62016-11-25 20:15:51 -0700550 for image in images.values():
Simon Glassa003cd32020-07-09 18:39:40 -0600551 missing |= ProcessImage(image, args.update_fdt, args.map,
552 allow_missing=args.allow_missing)
Simon Glassbdb40312018-09-14 04:57:20 -0600553
554 # Write the updated FDTs to our output files
Simon Glass5a300602019-07-20 12:23:29 -0600555 for dtb_item in state.GetAllFdts():
Simon Glassbdb40312018-09-14 04:57:20 -0600556 tools.WriteFile(dtb_item._fname, dtb_item.GetContents())
557
Simon Glassa003cd32020-07-09 18:39:40 -0600558 if missing:
559 tout.Warning("Some images are invalid")
Simon Glass2574ef62016-11-25 20:15:51 -0700560 finally:
561 tools.FinaliseOutputDir()
562 finally:
563 tout.Uninit()
564
565 return 0