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
18 from image import Image
21 # List of images we plan to create
22 # Make this global so that it can be referenced from tests
23 images = OrderedDict()
25 # Records the device-tree files known to binman, keyed by filename (e.g.
29 # Arguments passed to binman to provide arguments to entries
33 def _ReadImageDesc(binman_node):
34 """Read the image descriptions from the /binman node
36 This normally produces a single Image object called 'image'. But if
37 multiple images are present, they will all be returned.
40 binman_node: Node object of the /binman node
42 OrderedDict of Image objects, each of which describes an image
44 images = OrderedDict()
45 if 'multiple-images' in binman_node.props:
46 for node in binman_node.subnodes:
47 images[node.name] = Image(node.name, node)
49 images['image'] = Image('image', binman_node)
52 def _FindBinmanNode(dtb):
53 """Find the 'binman' node in the device tree
56 dtb: Fdt object to scan
58 Node object of /binman node, or None if not found
60 for node in dtb.GetRoot().subnodes:
61 if node.name == 'binman':
66 """Get the Fdt object for a particular device-tree filename
68 Binman keeps track of at least one device-tree file called u-boot.dtb but
69 can also have others (e.g. for SPL). This function looks up the given
70 filename and returns the associated Fdt object.
73 fname: Filename to look up (e.g. 'u-boot.dtb').
76 Fdt object associated with the filename
78 return fdt_files[fname]
80 def GetFdtPath(fname):
81 return fdt_files[fname]._fname
83 def SetEntryArgs(args):
89 m = re.match('([^=]*)=(.*)', arg)
91 raise ValueError("Invalid entry arguemnt '%s'" % arg)
92 entry_args[m.group(1)] = m.group(2)
94 def GetEntryArg(name):
95 return entry_args.get(name)
97 def Binman(options, args):
98 """The main control code for binman
100 This assumes that help and test options have already been dealt with. It
101 deals with the core task of building images.
104 options: Command line options object
105 args: Command line arguments (list of strings)
109 if options.full_help:
110 pager = os.getenv('PAGER')
113 fname = os.path.join(os.path.dirname(os.path.realpath(sys.argv[0])),
115 command.Run(pager, fname)
118 # Try to figure out which device tree contains our image description
120 dtb_fname = options.dt
122 board = options.board
124 raise ValueError('Must provide a board to process (use -b <board>)')
125 board_pathname = os.path.join(options.build_dir, board)
126 dtb_fname = os.path.join(board_pathname, 'u-boot.dtb')
127 if not options.indir:
128 options.indir = ['.']
129 options.indir.append(board_pathname)
132 tout.Init(options.verbosity)
133 elf.debug = options.debug
135 tools.SetInputDirs(options.indir)
136 tools.PrepareOutputDir(options.outdir, options.preserve)
137 SetEntryArgs(options.entry_arg)
139 # Get the device tree ready by compiling it and copying the compiled
140 # output into a file in our output directly. Then scan it for use
142 dtb_fname = fdt_util.EnsureCompiled(dtb_fname)
143 fname = tools.GetOutputFilename('u-boot-out.dtb')
144 with open(dtb_fname) as infd:
145 with open(fname, 'wb') as outfd:
146 outfd.write(infd.read())
147 dtb = fdt.FdtScan(fname)
149 # Note the file so that GetFdt() can find it
150 fdt_files['u-boot.dtb'] = dtb
151 node = _FindBinmanNode(dtb)
153 raise ValueError("Device tree '%s' does not have a 'binman' "
156 images = _ReadImageDesc(node)
158 # Prepare the device tree by making sure that any missing
159 # properties are added (e.g. 'pos' and 'size'). The values of these
160 # may not be correct yet, but we add placeholders so that the
161 # size of the device tree is correct. Later, in
162 # SetCalculatedProperties() we will insert the correct values
163 # without changing the device-tree size, thus ensuring that our
164 # entry offsets remain the same.
165 for image in images.values():
166 if options.update_fdt:
167 image.AddMissingProperties()
168 image.ProcessFdt(dtb)
173 for image in images.values():
174 # Perform all steps for this image, including checking and
175 # writing it. This means that errors found with a later
176 # image will be reported after earlier images are already
177 # completed and written, but that does not seem important.
178 image.GetEntryContents()
179 image.GetEntryOffsets()
184 if options.update_fdt:
185 image.SetCalculatedProperties()
186 image.ProcessEntryContents()
191 with open(fname, 'wb') as outfd:
192 outfd.write(dtb.GetContents())
194 tools.FinaliseOutputDir()