blob: 34ec74ba1b30079d7a7a32c609a7104365075d07 [file] [log] [blame]
Tom Rini10e47792018-05-06 17:58:06 -04001# SPDX-License-Identifier: GPL-2.0+
Simon Glass2574ef62016-11-25 20:15:51 -07002# Copyright (c) 2016 Google, Inc
3# Written by Simon Glass <sjg@chromium.org>
4#
Simon Glass2574ef62016-11-25 20:15:51 -07005# Creates binary images from input files controlled by a description
6#
7
8from collections import OrderedDict
9import os
10import sys
11import tools
12
13import command
Simon Glass075a45c2017-11-13 18:55:00 -070014import elf
Simon Glass2574ef62016-11-25 20:15:51 -070015from image import Image
Simon Glass29aa7362018-09-14 04:57:19 -060016import state
Simon Glass2574ef62016-11-25 20:15:51 -070017import tout
18
19# List of images we plan to create
20# Make this global so that it can be referenced from tests
21images = OrderedDict()
22
23def _ReadImageDesc(binman_node):
24 """Read the image descriptions from the /binman node
25
26 This normally produces a single Image object called 'image'. But if
27 multiple images are present, they will all be returned.
28
29 Args:
30 binman_node: Node object of the /binman node
31 Returns:
32 OrderedDict of Image objects, each of which describes an image
33 """
34 images = OrderedDict()
35 if 'multiple-images' in binman_node.props:
36 for node in binman_node.subnodes:
37 images[node.name] = Image(node.name, node)
38 else:
39 images['image'] = Image('image', binman_node)
40 return images
41
Simon Glass22c92ca2017-05-27 07:38:29 -060042def _FindBinmanNode(dtb):
Simon Glass2574ef62016-11-25 20:15:51 -070043 """Find the 'binman' node in the device tree
44
45 Args:
Simon Glass22c92ca2017-05-27 07:38:29 -060046 dtb: Fdt object to scan
Simon Glass2574ef62016-11-25 20:15:51 -070047 Returns:
48 Node object of /binman node, or None if not found
49 """
Simon Glass22c92ca2017-05-27 07:38:29 -060050 for node in dtb.GetRoot().subnodes:
Simon Glass2574ef62016-11-25 20:15:51 -070051 if node.name == 'binman':
52 return node
53 return None
54
Simon Glass29aa7362018-09-14 04:57:19 -060055def WriteEntryDocs(modules, test_missing=None):
56 """Write out documentation for all entries
Simon Glass92307732018-07-06 10:27:40 -060057
58 Args:
Simon Glass29aa7362018-09-14 04:57:19 -060059 modules: List of Module objects to get docs for
60 test_missing: Used for testing only, to force an entry's documeentation
61 to show as missing even if it is present. Should be set to None in
62 normal use.
Simon Glass92307732018-07-06 10:27:40 -060063 """
Simon Glass969616c2018-07-17 13:25:36 -060064 from entry import Entry
65 Entry.WriteDocs(modules, test_missing)
66
Simon Glass2574ef62016-11-25 20:15:51 -070067def Binman(options, args):
68 """The main control code for binman
69
70 This assumes that help and test options have already been dealt with. It
71 deals with the core task of building images.
72
73 Args:
74 options: Command line options object
75 args: Command line arguments (list of strings)
76 """
77 global images
78
79 if options.full_help:
80 pager = os.getenv('PAGER')
81 if not pager:
82 pager = 'more'
83 fname = os.path.join(os.path.dirname(os.path.realpath(sys.argv[0])),
84 'README')
85 command.Run(pager, fname)
86 return 0
87
88 # Try to figure out which device tree contains our image description
89 if options.dt:
90 dtb_fname = options.dt
91 else:
92 board = options.board
93 if not board:
94 raise ValueError('Must provide a board to process (use -b <board>)')
95 board_pathname = os.path.join(options.build_dir, board)
96 dtb_fname = os.path.join(board_pathname, 'u-boot.dtb')
97 if not options.indir:
98 options.indir = ['.']
99 options.indir.append(board_pathname)
100
101 try:
Simon Glass63a336b2018-07-17 13:25:34 -0600102 # Import these here in case libfdt.py is not available, in which case
103 # the above help option still works.
104 import fdt
105 import fdt_util
106
Simon Glass2574ef62016-11-25 20:15:51 -0700107 tout.Init(options.verbosity)
Simon Glass4ca8e042017-11-13 18:55:01 -0700108 elf.debug = options.debug
Simon Glass31402012018-09-14 04:57:23 -0600109 state.use_fake_dtb = options.fake_dtb
Simon Glass2574ef62016-11-25 20:15:51 -0700110 try:
111 tools.SetInputDirs(options.indir)
112 tools.PrepareOutputDir(options.outdir, options.preserve)
Simon Glass29aa7362018-09-14 04:57:19 -0600113 state.SetEntryArgs(options.entry_arg)
Simon Glass92307732018-07-06 10:27:40 -0600114
115 # Get the device tree ready by compiling it and copying the compiled
116 # output into a file in our output directly. Then scan it for use
117 # in binman.
118 dtb_fname = fdt_util.EnsureCompiled(dtb_fname)
119 fname = tools.GetOutputFilename('u-boot-out.dtb')
120 with open(dtb_fname) as infd:
121 with open(fname, 'wb') as outfd:
122 outfd.write(infd.read())
123 dtb = fdt.FdtScan(fname)
124
Simon Glass22c92ca2017-05-27 07:38:29 -0600125 node = _FindBinmanNode(dtb)
Simon Glass2574ef62016-11-25 20:15:51 -0700126 if not node:
127 raise ValueError("Device tree '%s' does not have a 'binman' "
128 "node" % dtb_fname)
Simon Glass92307732018-07-06 10:27:40 -0600129
Simon Glass2574ef62016-11-25 20:15:51 -0700130 images = _ReadImageDesc(node)
Simon Glass92307732018-07-06 10:27:40 -0600131
Simon Glass3b376c32018-09-14 04:57:12 -0600132 if options.image:
133 skip = []
134 for name, image in images.iteritems():
135 if name not in options.image:
136 del images[name]
137 skip.append(name)
138 if skip:
139 print 'Skipping images: %s\n' % ', '.join(skip)
140
Simon Glass0c9d5b52018-09-14 04:57:22 -0600141 state.Prepare(images, dtb)
Simon Glassbdb40312018-09-14 04:57:20 -0600142
Simon Glass92307732018-07-06 10:27:40 -0600143 # Prepare the device tree by making sure that any missing
144 # properties are added (e.g. 'pos' and 'size'). The values of these
145 # may not be correct yet, but we add placeholders so that the
146 # size of the device tree is correct. Later, in
147 # SetCalculatedProperties() we will insert the correct values
148 # without changing the device-tree size, thus ensuring that our
Simon Glasse8561af2018-08-01 15:22:37 -0600149 # entry offsets remain the same.
Simon Glass92307732018-07-06 10:27:40 -0600150 for image in images.values():
Simon Glasse22f8fa2018-07-06 10:27:41 -0600151 if options.update_fdt:
152 image.AddMissingProperties()
Simon Glass92307732018-07-06 10:27:40 -0600153 image.ProcessFdt(dtb)
154
Simon Glassbdb40312018-09-14 04:57:20 -0600155 for dtb_item in state.GetFdts():
156 dtb_item.Sync(auto_resize=True)
157 dtb_item.Pack()
158 dtb_item.Flush()
Simon Glass92307732018-07-06 10:27:40 -0600159
Simon Glass2574ef62016-11-25 20:15:51 -0700160 for image in images.values():
161 # Perform all steps for this image, including checking and
162 # writing it. This means that errors found with a later
163 # image will be reported after earlier images are already
164 # completed and written, but that does not seem important.
165 image.GetEntryContents()
Simon Glasse8561af2018-08-01 15:22:37 -0600166 image.GetEntryOffsets()
Simon Glass2574ef62016-11-25 20:15:51 -0700167 image.PackEntries()
168 image.CheckSize()
169 image.CheckEntries()
Simon Glass9dcc8612018-08-01 15:22:42 -0600170 image.SetImagePos()
Simon Glasse22f8fa2018-07-06 10:27:41 -0600171 if options.update_fdt:
172 image.SetCalculatedProperties()
Simon Glassbdb40312018-09-14 04:57:20 -0600173 for dtb_item in state.GetFdts():
174 dtb_item.Sync()
Simon Glass2574ef62016-11-25 20:15:51 -0700175 image.ProcessEntryContents()
Simon Glass4ca8e042017-11-13 18:55:01 -0700176 image.WriteSymbols()
Simon Glass2574ef62016-11-25 20:15:51 -0700177 image.BuildImage()
Simon Glass30732662018-06-01 09:38:20 -0600178 if options.map:
179 image.WriteMap()
Simon Glassbdb40312018-09-14 04:57:20 -0600180
181 # Write the updated FDTs to our output files
182 for dtb_item in state.GetFdts():
183 tools.WriteFile(dtb_item._fname, dtb_item.GetContents())
184
Simon Glass2574ef62016-11-25 20:15:51 -0700185 finally:
186 tools.FinaliseOutputDir()
187 finally:
188 tout.Uninit()
189
190 return 0