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 Binman(options, args):
96 """The main control code for binman
98 This assumes that help and test options have already been dealt with. It
99 deals with the core task of building images.
102 options: Command line options object
103 args: Command line arguments (list of strings)
107 if options.full_help:
108 pager = os.getenv('PAGER')
111 fname = os.path.join(os.path.dirname(os.path.realpath(sys.argv[0])),
113 command.Run(pager, fname)
116 # Try to figure out which device tree contains our image description
118 dtb_fname = options.dt
120 board = options.board
122 raise ValueError('Must provide a board to process (use -b <board>)')
123 board_pathname = os.path.join(options.build_dir, board)
124 dtb_fname = os.path.join(board_pathname, 'u-boot.dtb')
125 if not options.indir:
126 options.indir = ['.']
127 options.indir.append(board_pathname)
130 # Import these here in case libfdt.py is not available, in which case
131 # the above help option still works.
135 tout.Init(options.verbosity)
136 elf.debug = options.debug
138 tools.SetInputDirs(options.indir)
139 tools.PrepareOutputDir(options.outdir, options.preserve)
140 SetEntryArgs(options.entry_arg)
142 # Get the device tree ready by compiling it and copying the compiled
143 # output into a file in our output directly. Then scan it for use
145 dtb_fname = fdt_util.EnsureCompiled(dtb_fname)
146 fname = tools.GetOutputFilename('u-boot-out.dtb')
147 with open(dtb_fname) as infd:
148 with open(fname, 'wb') as outfd:
149 outfd.write(infd.read())
150 dtb = fdt.FdtScan(fname)
152 # Note the file so that GetFdt() can find it
153 fdt_files['u-boot.dtb'] = dtb
154 node = _FindBinmanNode(dtb)
156 raise ValueError("Device tree '%s' does not have a 'binman' "
159 images = _ReadImageDesc(node)
161 # Prepare the device tree by making sure that any missing
162 # properties are added (e.g. 'pos' and 'size'). The values of these
163 # may not be correct yet, but we add placeholders so that the
164 # size of the device tree is correct. Later, in
165 # SetCalculatedProperties() we will insert the correct values
166 # without changing the device-tree size, thus ensuring that our
167 # entry offsets remain the same.
168 for image in images.values():
169 if options.update_fdt:
170 image.AddMissingProperties()
171 image.ProcessFdt(dtb)
176 for image in images.values():
177 # Perform all steps for this image, including checking and
178 # writing it. This means that errors found with a later
179 # image will be reported after earlier images are already
180 # completed and written, but that does not seem important.
181 image.GetEntryContents()
182 image.GetEntryOffsets()
187 if options.update_fdt:
188 image.SetCalculatedProperties()
189 image.ProcessEntryContents()
194 with open(fname, 'wb') as outfd:
195 outfd.write(dtb.GetContents())
197 tools.FinaliseOutputDir()