]> Git Repo - J-u-boot.git/blame - tools/binman/control.py
binman: Convert Image to a subclass of Entry
[J-u-boot.git] / tools / binman / control.py
CommitLineData
83d290c5 1# SPDX-License-Identifier: GPL-2.0+
bf7fd50b
SG
2# Copyright (c) 2016 Google, Inc
3# Written by Simon Glass <[email protected]>
4#
bf7fd50b
SG
5# Creates binary images from input files controlled by a description
6#
7
2ca84680
SG
8from __future__ import print_function
9
bf7fd50b
SG
10from collections import OrderedDict
11import os
12import sys
13import tools
14
ac62fba4 15import cbfs_util
bf7fd50b 16import command
7fe9173b 17import elf
bf7fd50b 18from image import Image
c55a50f5 19import state
bf7fd50b
SG
20import tout
21
22# List of images we plan to create
23# Make this global so that it can be referenced from tests
24images = OrderedDict()
25
26def _ReadImageDesc(binman_node):
27 """Read the image descriptions from the /binman node
28
29 This normally produces a single Image object called 'image'. But if
30 multiple images are present, they will all be returned.
31
32 Args:
33 binman_node: Node object of the /binman node
34 Returns:
35 OrderedDict of Image objects, each of which describes an image
36 """
37 images = OrderedDict()
38 if 'multiple-images' in binman_node.props:
39 for node in binman_node.subnodes:
40 images[node.name] = Image(node.name, node)
41 else:
42 images['image'] = Image('image', binman_node)
43 return images
44
ec3f378a 45def _FindBinmanNode(dtb):
bf7fd50b
SG
46 """Find the 'binman' node in the device tree
47
48 Args:
ec3f378a 49 dtb: Fdt object to scan
bf7fd50b
SG
50 Returns:
51 Node object of /binman node, or None if not found
52 """
ec3f378a 53 for node in dtb.GetRoot().subnodes:
bf7fd50b
SG
54 if node.name == 'binman':
55 return node
56 return None
57
c55a50f5
SG
58def WriteEntryDocs(modules, test_missing=None):
59 """Write out documentation for all entries
ecab8973
SG
60
61 Args:
c55a50f5
SG
62 modules: List of Module objects to get docs for
63 test_missing: Used for testing only, to force an entry's documeentation
64 to show as missing even if it is present. Should be set to None in
65 normal use.
ecab8973 66 """
fd8d1f79
SG
67 from entry import Entry
68 Entry.WriteDocs(modules, test_missing)
69
53cd5d92 70def Binman(args):
bf7fd50b
SG
71 """The main control code for binman
72
73 This assumes that help and test options have already been dealt with. It
74 deals with the core task of building images.
75
76 Args:
53cd5d92 77 args: Command line arguments Namespace object
bf7fd50b
SG
78 """
79 global images
80
53cd5d92 81 if args.full_help:
bf7fd50b
SG
82 pager = os.getenv('PAGER')
83 if not pager:
84 pager = 'more'
85 fname = os.path.join(os.path.dirname(os.path.realpath(sys.argv[0])),
86 'README')
87 command.Run(pager, fname)
88 return 0
89
90 # Try to figure out which device tree contains our image description
53cd5d92
SG
91 if args.dt:
92 dtb_fname = args.dt
bf7fd50b 93 else:
53cd5d92 94 board = args.board
bf7fd50b
SG
95 if not board:
96 raise ValueError('Must provide a board to process (use -b <board>)')
53cd5d92 97 board_pathname = os.path.join(args.build_dir, board)
bf7fd50b 98 dtb_fname = os.path.join(board_pathname, 'u-boot.dtb')
53cd5d92
SG
99 if not args.indir:
100 args.indir = ['.']
101 args.indir.append(board_pathname)
bf7fd50b
SG
102
103 try:
9b1a804d
SG
104 # Import these here in case libfdt.py is not available, in which case
105 # the above help option still works.
106 import fdt
107 import fdt_util
108
53cd5d92
SG
109 tout.Init(args.verbosity)
110 elf.debug = args.debug
111 cbfs_util.VERBOSE = args.verbosity > 2
112 state.use_fake_dtb = args.fake_dtb
bf7fd50b 113 try:
53cd5d92
SG
114 tools.SetInputDirs(args.indir)
115 tools.PrepareOutputDir(args.outdir, args.preserve)
116 tools.SetToolPaths(args.toolpath)
117 state.SetEntryArgs(args.entry_arg)
ecab8973
SG
118
119 # Get the device tree ready by compiling it and copying the compiled
120 # output into a file in our output directly. Then scan it for use
121 # in binman.
122 dtb_fname = fdt_util.EnsureCompiled(dtb_fname)
6ed45ba0
SG
123 fname = tools.GetOutputFilename('u-boot.dtb.out')
124 tools.WriteFile(fname, tools.ReadFile(dtb_fname))
ecab8973
SG
125 dtb = fdt.FdtScan(fname)
126
ec3f378a 127 node = _FindBinmanNode(dtb)
bf7fd50b
SG
128 if not node:
129 raise ValueError("Device tree '%s' does not have a 'binman' "
130 "node" % dtb_fname)
ecab8973 131
bf7fd50b 132 images = _ReadImageDesc(node)
ecab8973 133
53cd5d92 134 if args.image:
0bfa7b09 135 skip = []
58632a7f 136 new_images = OrderedDict()
50979154 137 for name, image in images.items():
53cd5d92 138 if name in args.image:
58632a7f
SG
139 new_images[name] = image
140 else:
0bfa7b09 141 skip.append(name)
58632a7f 142 images = new_images
53cd5d92 143 if skip and args.verbosity >= 2:
2ca84680 144 print('Skipping images: %s' % ', '.join(skip))
0bfa7b09 145
539aece5 146 state.Prepare(images, dtb)
2a72cc72 147
ecab8973
SG
148 # Prepare the device tree by making sure that any missing
149 # properties are added (e.g. 'pos' and 'size'). The values of these
150 # may not be correct yet, but we add placeholders so that the
151 # size of the device tree is correct. Later, in
152 # SetCalculatedProperties() we will insert the correct values
153 # without changing the device-tree size, thus ensuring that our
3ab9598d 154 # entry offsets remain the same.
ecab8973 155 for image in images.values():
0a98b28b 156 image.ExpandEntries()
53cd5d92 157 if args.update_fdt:
078ab1a2 158 image.AddMissingProperties()
ecab8973
SG
159 image.ProcessFdt(dtb)
160
2a72cc72
SG
161 for dtb_item in state.GetFdts():
162 dtb_item.Sync(auto_resize=True)
163 dtb_item.Pack()
164 dtb_item.Flush()
ecab8973 165
bf7fd50b
SG
166 for image in images.values():
167 # Perform all steps for this image, including checking and
168 # writing it. This means that errors found with a later
169 # image will be reported after earlier images are already
170 # completed and written, but that does not seem important.
171 image.GetEntryContents()
3ab9598d 172 image.GetEntryOffsets()
c52c9e7d
SG
173
174 # We need to pack the entries to figure out where everything
175 # should be placed. This sets the offset/size of each entry.
176 # However, after packing we call ProcessEntryContents() which
177 # may result in an entry changing size. In that case we need to
178 # do another pass. Since the device tree often contains the
179 # final offset/size information we try to make space for this in
180 # AddMissingProperties() above. However, if the device is
181 # compressed we cannot know this compressed size in advance,
182 # since changing an offset from 0x100 to 0x104 (for example) can
183 # alter the compressed size of the device tree. So we need a
184 # third pass for this.
185 passes = 3
186 for pack_pass in range(passes):
187 try:
188 image.PackEntries()
189 image.CheckSize()
190 image.CheckEntries()
191 except Exception as e:
192 if args.map:
193 fname = image.WriteMap()
194 print("Wrote map file '%s' to show errors" % fname)
195 raise
196 image.SetImagePos()
197 if args.update_fdt:
198 image.SetCalculatedProperties()
199 for dtb_item in state.GetFdts():
200 dtb_item.Sync()
201 sizes_ok = image.ProcessEntryContents()
202 if sizes_ok:
203 break
204 image.ResetForPack()
205 if not sizes_ok:
206 image.Raise('Entries expanded after packing (tried %s passes)' %
207 passes)
208
19790632 209 image.WriteSymbols()
bf7fd50b 210 image.BuildImage()
53cd5d92 211 if args.map:
3b0c3821 212 image.WriteMap()
2a72cc72
SG
213
214 # Write the updated FDTs to our output files
215 for dtb_item in state.GetFdts():
216 tools.WriteFile(dtb_item._fname, dtb_item.GetContents())
217
bf7fd50b
SG
218 finally:
219 tools.FinaliseOutputDir()
220 finally:
221 tout.Uninit()
222
223 return 0
This page took 0.20817 seconds and 4 git commands to generate.