blob: 20186ee1980282cfbd6b78d12d6ee1bbf7468fa3 [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
Simon Glass7cca27d2019-05-14 15:53:37 -06008from __future__ import print_function
9
Simon Glass2574ef62016-11-25 20:15:51 -070010from collections import OrderedDict
11import os
12import sys
13import tools
14
15import command
Simon Glass075a45c2017-11-13 18:55:00 -070016import elf
Simon Glass2574ef62016-11-25 20:15:51 -070017from image import Image
Simon Glass29aa7362018-09-14 04:57:19 -060018import state
Simon Glass2574ef62016-11-25 20:15:51 -070019import tout
20
21# List of images we plan to create
22# Make this global so that it can be referenced from tests
23images = OrderedDict()
24
25def _ReadImageDesc(binman_node):
26 """Read the image descriptions from the /binman node
27
28 This normally produces a single Image object called 'image'. But if
29 multiple images are present, they will all be returned.
30
31 Args:
32 binman_node: Node object of the /binman node
33 Returns:
34 OrderedDict of Image objects, each of which describes an image
35 """
36 images = OrderedDict()
37 if 'multiple-images' in binman_node.props:
38 for node in binman_node.subnodes:
39 images[node.name] = Image(node.name, node)
40 else:
41 images['image'] = Image('image', binman_node)
42 return images
43
Simon Glass22c92ca2017-05-27 07:38:29 -060044def _FindBinmanNode(dtb):
Simon Glass2574ef62016-11-25 20:15:51 -070045 """Find the 'binman' node in the device tree
46
47 Args:
Simon Glass22c92ca2017-05-27 07:38:29 -060048 dtb: Fdt object to scan
Simon Glass2574ef62016-11-25 20:15:51 -070049 Returns:
50 Node object of /binman node, or None if not found
51 """
Simon Glass22c92ca2017-05-27 07:38:29 -060052 for node in dtb.GetRoot().subnodes:
Simon Glass2574ef62016-11-25 20:15:51 -070053 if node.name == 'binman':
54 return node
55 return None
56
Simon Glass29aa7362018-09-14 04:57:19 -060057def WriteEntryDocs(modules, test_missing=None):
58 """Write out documentation for all entries
Simon Glass92307732018-07-06 10:27:40 -060059
60 Args:
Simon Glass29aa7362018-09-14 04:57:19 -060061 modules: List of Module objects to get docs for
62 test_missing: Used for testing only, to force an entry's documeentation
63 to show as missing even if it is present. Should be set to None in
64 normal use.
Simon Glass92307732018-07-06 10:27:40 -060065 """
Simon Glass969616c2018-07-17 13:25:36 -060066 from entry import Entry
67 Entry.WriteDocs(modules, test_missing)
68
Simon Glass2574ef62016-11-25 20:15:51 -070069def Binman(options, args):
70 """The main control code for binman
71
72 This assumes that help and test options have already been dealt with. It
73 deals with the core task of building images.
74
75 Args:
76 options: Command line options object
77 args: Command line arguments (list of strings)
78 """
79 global images
80
81 if options.full_help:
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
91 if options.dt:
92 dtb_fname = options.dt
93 else:
94 board = options.board
95 if not board:
96 raise ValueError('Must provide a board to process (use -b <board>)')
97 board_pathname = os.path.join(options.build_dir, board)
98 dtb_fname = os.path.join(board_pathname, 'u-boot.dtb')
99 if not options.indir:
100 options.indir = ['.']
101 options.indir.append(board_pathname)
102
103 try:
Simon Glass63a336b2018-07-17 13:25:34 -0600104 # 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
Simon Glass2574ef62016-11-25 20:15:51 -0700109 tout.Init(options.verbosity)
Simon Glass4ca8e042017-11-13 18:55:01 -0700110 elf.debug = options.debug
Simon Glass31402012018-09-14 04:57:23 -0600111 state.use_fake_dtb = options.fake_dtb
Simon Glass2574ef62016-11-25 20:15:51 -0700112 try:
113 tools.SetInputDirs(options.indir)
114 tools.PrepareOutputDir(options.outdir, options.preserve)
Simon Glass29aa7362018-09-14 04:57:19 -0600115 state.SetEntryArgs(options.entry_arg)
Simon Glass92307732018-07-06 10:27:40 -0600116
117 # Get the device tree ready by compiling it and copying the compiled
118 # output into a file in our output directly. Then scan it for use
119 # in binman.
120 dtb_fname = fdt_util.EnsureCompiled(dtb_fname)
Simon Glasse219aa42018-09-14 04:57:24 -0600121 fname = tools.GetOutputFilename('u-boot.dtb.out')
122 tools.WriteFile(fname, tools.ReadFile(dtb_fname))
Simon Glass92307732018-07-06 10:27:40 -0600123 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 = []
Simon Glass42775432019-05-17 22:00:45 -0600134 new_images = OrderedDict()
Simon Glass5f3645b2019-05-14 15:53:41 -0600135 for name, image in images.items():
Simon Glass42775432019-05-17 22:00:45 -0600136 if name in options.image:
137 new_images[name] = image
138 else:
Simon Glass3b376c32018-09-14 04:57:12 -0600139 skip.append(name)
Simon Glass42775432019-05-17 22:00:45 -0600140 images = new_images
Simon Glassb4595d82019-04-25 21:58:34 -0600141 if skip and options.verbosity >= 2:
Simon Glass7cca27d2019-05-14 15:53:37 -0600142 print('Skipping images: %s' % ', '.join(skip))
Simon Glass3b376c32018-09-14 04:57:12 -0600143
Simon Glass0c9d5b52018-09-14 04:57:22 -0600144 state.Prepare(images, dtb)
Simon Glassbdb40312018-09-14 04:57:20 -0600145
Simon Glass92307732018-07-06 10:27:40 -0600146 # Prepare the device tree by making sure that any missing
147 # properties are added (e.g. 'pos' and 'size'). The values of these
148 # may not be correct yet, but we add placeholders so that the
149 # size of the device tree is correct. Later, in
150 # SetCalculatedProperties() we will insert the correct values
151 # without changing the device-tree size, thus ensuring that our
Simon Glasse8561af2018-08-01 15:22:37 -0600152 # entry offsets remain the same.
Simon Glass92307732018-07-06 10:27:40 -0600153 for image in images.values():
Simon Glassac6328c2018-09-14 04:57:28 -0600154 image.ExpandEntries()
Simon Glasse22f8fa2018-07-06 10:27:41 -0600155 if options.update_fdt:
156 image.AddMissingProperties()
Simon Glass92307732018-07-06 10:27:40 -0600157 image.ProcessFdt(dtb)
158
Simon Glassbdb40312018-09-14 04:57:20 -0600159 for dtb_item in state.GetFdts():
160 dtb_item.Sync(auto_resize=True)
161 dtb_item.Pack()
162 dtb_item.Flush()
Simon Glass92307732018-07-06 10:27:40 -0600163
Simon Glass2574ef62016-11-25 20:15:51 -0700164 for image in images.values():
165 # Perform all steps for this image, including checking and
166 # writing it. This means that errors found with a later
167 # image will be reported after earlier images are already
168 # completed and written, but that does not seem important.
169 image.GetEntryContents()
Simon Glasse8561af2018-08-01 15:22:37 -0600170 image.GetEntryOffsets()
Simon Glasscd817d52018-09-14 04:57:36 -0600171 try:
172 image.PackEntries()
173 image.CheckSize()
174 image.CheckEntries()
175 except Exception as e:
176 if options.map:
177 fname = image.WriteMap()
Simon Glass7cca27d2019-05-14 15:53:37 -0600178 print("Wrote map file '%s' to show errors" % fname)
Simon Glasscd817d52018-09-14 04:57:36 -0600179 raise
Simon Glass9dcc8612018-08-01 15:22:42 -0600180 image.SetImagePos()
Simon Glasse22f8fa2018-07-06 10:27:41 -0600181 if options.update_fdt:
182 image.SetCalculatedProperties()
Simon Glassbdb40312018-09-14 04:57:20 -0600183 for dtb_item in state.GetFdts():
184 dtb_item.Sync()
Simon Glass2574ef62016-11-25 20:15:51 -0700185 image.ProcessEntryContents()
Simon Glass4ca8e042017-11-13 18:55:01 -0700186 image.WriteSymbols()
Simon Glass2574ef62016-11-25 20:15:51 -0700187 image.BuildImage()
Simon Glass30732662018-06-01 09:38:20 -0600188 if options.map:
189 image.WriteMap()
Simon Glassbdb40312018-09-14 04:57:20 -0600190
191 # Write the updated FDTs to our output files
192 for dtb_item in state.GetFdts():
193 tools.WriteFile(dtb_item._fname, dtb_item.GetContents())
194
Simon Glass2574ef62016-11-25 20:15:51 -0700195 finally:
196 tools.FinaliseOutputDir()
197 finally:
198 tout.Uninit()
199
200 return 0