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
16 from image import Image
19 # List of images we plan to create
20 # Make this global so that it can be referenced from tests
21 images = OrderedDict()
23 # Records the device-tree files known to binman, keyed by filename (e.g.
27 # Arguments passed to binman to provide arguments to entries
31 def _ReadImageDesc(binman_node):
32 """Read the image descriptions from the /binman node
34 This normally produces a single Image object called 'image'. But if
35 multiple images are present, they will all be returned.
38 binman_node: Node object of the /binman node
40 OrderedDict of Image objects, each of which describes an image
42 images = OrderedDict()
43 if 'multiple-images' in binman_node.props:
44 for node in binman_node.subnodes:
45 images[node.name] = Image(node.name, node)
47 images['image'] = Image('image', binman_node)
50 def _FindBinmanNode(dtb):
51 """Find the 'binman' node in the device tree
54 dtb: Fdt object to scan
56 Node object of /binman node, or None if not found
58 for node in dtb.GetRoot().subnodes:
59 if node.name == 'binman':
64 """Get the Fdt object for a particular device-tree filename
66 Binman keeps track of at least one device-tree file called u-boot.dtb but
67 can also have others (e.g. for SPL). This function looks up the given
68 filename and returns the associated Fdt object.
71 fname: Filename to look up (e.g. 'u-boot.dtb').
74 Fdt object associated with the filename
76 return fdt_files[fname]
78 def GetFdtPath(fname):
79 return fdt_files[fname]._fname
81 def SetEntryArgs(args):
87 m = re.match('([^=]*)=(.*)', arg)
89 raise ValueError("Invalid entry arguemnt '%s'" % arg)
90 entry_args[m.group(1)] = m.group(2)
92 def GetEntryArg(name):
93 return entry_args.get(name)
95 def WriteEntryDocs(modules, test_missing=None):
96 from entry import Entry
97 Entry.WriteDocs(modules, test_missing)
99 def Binman(options, args):
100 """The main control code for binman
102 This assumes that help and test options have already been dealt with. It
103 deals with the core task of building images.
106 options: Command line options object
107 args: Command line arguments (list of strings)
111 if options.full_help:
112 pager = os.getenv('PAGER')
115 fname = os.path.join(os.path.dirname(os.path.realpath(sys.argv[0])),
117 command.Run(pager, fname)
120 # Try to figure out which device tree contains our image description
122 dtb_fname = options.dt
124 board = options.board
126 raise ValueError('Must provide a board to process (use -b <board>)')
127 board_pathname = os.path.join(options.build_dir, board)
128 dtb_fname = os.path.join(board_pathname, 'u-boot.dtb')
129 if not options.indir:
130 options.indir = ['.']
131 options.indir.append(board_pathname)
134 # Import these here in case libfdt.py is not available, in which case
135 # the above help option still works.
139 tout.Init(options.verbosity)
140 elf.debug = options.debug
142 tools.SetInputDirs(options.indir)
143 tools.PrepareOutputDir(options.outdir, options.preserve)
144 SetEntryArgs(options.entry_arg)
146 # Get the device tree ready by compiling it and copying the compiled
147 # output into a file in our output directly. Then scan it for use
149 dtb_fname = fdt_util.EnsureCompiled(dtb_fname)
150 fname = tools.GetOutputFilename('u-boot-out.dtb')
151 with open(dtb_fname) as infd:
152 with open(fname, 'wb') as outfd:
153 outfd.write(infd.read())
154 dtb = fdt.FdtScan(fname)
156 # Note the file so that GetFdt() can find it
157 fdt_files['u-boot.dtb'] = dtb
158 node = _FindBinmanNode(dtb)
160 raise ValueError("Device tree '%s' does not have a 'binman' "
163 images = _ReadImageDesc(node)
167 for name, image in images.iteritems():
168 if name not in options.image:
172 print 'Skipping images: %s\n' % ', '.join(skip)
174 # Prepare the device tree by making sure that any missing
175 # properties are added (e.g. 'pos' and 'size'). The values of these
176 # may not be correct yet, but we add placeholders so that the
177 # size of the device tree is correct. Later, in
178 # SetCalculatedProperties() we will insert the correct values
179 # without changing the device-tree size, thus ensuring that our
180 # entry offsets remain the same.
181 for image in images.values():
182 if options.update_fdt:
183 image.AddMissingProperties()
184 image.ProcessFdt(dtb)
189 for image in images.values():
190 # Perform all steps for this image, including checking and
191 # writing it. This means that errors found with a later
192 # image will be reported after earlier images are already
193 # completed and written, but that does not seem important.
194 image.GetEntryContents()
195 image.GetEntryOffsets()
200 if options.update_fdt:
201 image.SetCalculatedProperties()
202 image.ProcessEntryContents()
207 with open(fname, 'wb') as outfd:
208 outfd.write(dtb.GetContents())
210 tools.FinaliseOutputDir()