1 # SPDX-License-Identifier: GPL-2.0+
2 # Copyright (c) 2016 Google, Inc
3 # Written by Simon Glass <sjg@chromium.org>
5 # Creates binary images from input files controlled by a description
8 from collections import OrderedDict
17 from image import Image
20 # List of images we plan to create
21 # Make this global so that it can be referenced from tests
22 images = OrderedDict()
24 # Records the device-tree files known to binman, keyed by filename (e.g.
29 def _ReadImageDesc(binman_node):
30 """Read the image descriptions from the /binman node
32 This normally produces a single Image object called 'image'. But if
33 multiple images are present, they will all be returned.
36 binman_node: Node object of the /binman node
38 OrderedDict of Image objects, each of which describes an image
40 images = OrderedDict()
41 if 'multiple-images' in binman_node.props:
42 for node in binman_node.subnodes:
43 images[node.name] = Image(node.name, node)
45 images['image'] = Image('image', binman_node)
48 def _FindBinmanNode(dtb):
49 """Find the 'binman' node in the device tree
52 dtb: Fdt object to scan
54 Node object of /binman node, or None if not found
56 for node in dtb.GetRoot().subnodes:
57 if node.name == 'binman':
62 """Get the Fdt object for a particular device-tree filename
64 Binman keeps track of at least one device-tree file called u-boot.dtb but
65 can also have others (e.g. for SPL). This function looks up the given
66 filename and returns the associated Fdt object.
69 fname: Filename to look up (e.g. 'u-boot.dtb').
72 Fdt object associated with the filename
74 return fdt_files[fname]
76 def GetFdtPath(fname):
77 return fdt_files[fname]._fname
79 def Binman(options, args):
80 """The main control code for binman
82 This assumes that help and test options have already been dealt with. It
83 deals with the core task of building images.
86 options: Command line options object
87 args: Command line arguments (list of strings)
92 pager = os.getenv('PAGER')
95 fname = os.path.join(os.path.dirname(os.path.realpath(sys.argv[0])),
97 command.Run(pager, fname)
100 # Try to figure out which device tree contains our image description
102 dtb_fname = options.dt
104 board = options.board
106 raise ValueError('Must provide a board to process (use -b <board>)')
107 board_pathname = os.path.join(options.build_dir, board)
108 dtb_fname = os.path.join(board_pathname, 'u-boot.dtb')
109 if not options.indir:
110 options.indir = ['.']
111 options.indir.append(board_pathname)
114 tout.Init(options.verbosity)
115 elf.debug = options.debug
117 tools.SetInputDirs(options.indir)
118 tools.PrepareOutputDir(options.outdir, options.preserve)
120 # Get the device tree ready by compiling it and copying the compiled
121 # output into a file in our output directly. Then scan it for use
123 dtb_fname = fdt_util.EnsureCompiled(dtb_fname)
124 fname = tools.GetOutputFilename('u-boot-out.dtb')
125 with open(dtb_fname) as infd:
126 with open(fname, 'wb') as outfd:
127 outfd.write(infd.read())
128 dtb = fdt.FdtScan(fname)
130 # Note the file so that GetFdt() can find it
131 fdt_files['u-boot.dtb'] = dtb
132 node = _FindBinmanNode(dtb)
134 raise ValueError("Device tree '%s' does not have a 'binman' "
137 images = _ReadImageDesc(node)
139 # Prepare the device tree by making sure that any missing
140 # properties are added (e.g. 'pos' and 'size'). The values of these
141 # may not be correct yet, but we add placeholders so that the
142 # size of the device tree is correct. Later, in
143 # SetCalculatedProperties() we will insert the correct values
144 # without changing the device-tree size, thus ensuring that our
145 # entry positions remain the same.
146 for image in images.values():
147 if options.update_fdt:
148 image.AddMissingProperties()
149 image.ProcessFdt(dtb)
154 for image in images.values():
155 # Perform all steps for this image, including checking and
156 # writing it. This means that errors found with a later
157 # image will be reported after earlier images are already
158 # completed and written, but that does not seem important.
159 image.GetEntryContents()
160 image.GetEntryPositions()
164 if options.update_fdt:
165 image.SetCalculatedProperties()
166 image.ProcessEntryContents()
171 with open(fname, 'wb') as outfd:
172 outfd.write(dtb.GetContents())
174 tools.FinaliseOutputDir()