blob: df78848e13d312c425b565bde23f8f4227f63540 [file] [log] [blame]
Tom Rini83d290c2018-05-06 17:58:06 -04001# SPDX-License-Identifier: GPL-2.0+
Simon Glassbf7fd502016-11-25 20:15:51 -07002# Copyright (c) 2016 Google, Inc
3# Written by Simon Glass <sjg@chromium.org>
4#
Simon Glassbf7fd502016-11-25 20:15:51 -07005# Creates binary images from input files controlled by a description
6#
7
Simon Glass2ca84682019-05-14 15:53:37 -06008from __future__ import print_function
9
Simon Glassbf7fd502016-11-25 20:15:51 -070010from collections import OrderedDict
11import os
12import sys
13import tools
14
15import command
Simon Glass7fe91732017-11-13 18:55:00 -070016import elf
Simon Glassbf7fd502016-11-25 20:15:51 -070017from image import Image
Simon Glassc55a50f2018-09-14 04:57:19 -060018import state
Simon Glassbf7fd502016-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 Glassec3f3782017-05-27 07:38:29 -060044def _FindBinmanNode(dtb):
Simon Glassbf7fd502016-11-25 20:15:51 -070045 """Find the 'binman' node in the device tree
46
47 Args:
Simon Glassec3f3782017-05-27 07:38:29 -060048 dtb: Fdt object to scan
Simon Glassbf7fd502016-11-25 20:15:51 -070049 Returns:
50 Node object of /binman node, or None if not found
51 """
Simon Glassec3f3782017-05-27 07:38:29 -060052 for node in dtb.GetRoot().subnodes:
Simon Glassbf7fd502016-11-25 20:15:51 -070053 if node.name == 'binman':
54 return node
55 return None
56
Simon Glassc55a50f2018-09-14 04:57:19 -060057def WriteEntryDocs(modules, test_missing=None):
58 """Write out documentation for all entries
Simon Glassecab8972018-07-06 10:27:40 -060059
60 Args:
Simon Glassc55a50f2018-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 Glassecab8972018-07-06 10:27:40 -060065 """
Simon Glassfd8d1f72018-07-17 13:25:36 -060066 from entry import Entry
67 Entry.WriteDocs(modules, test_missing)
68
Simon Glassbf7fd502016-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 Glass9b1a8042018-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 Glassbf7fd502016-11-25 20:15:51 -0700109 tout.Init(options.verbosity)
Simon Glass19790632017-11-13 18:55:01 -0700110 elf.debug = options.debug
Simon Glass93d17412018-09-14 04:57:23 -0600111 state.use_fake_dtb = options.fake_dtb
Simon Glassbf7fd502016-11-25 20:15:51 -0700112 try:
113 tools.SetInputDirs(options.indir)
114 tools.PrepareOutputDir(options.outdir, options.preserve)
Simon Glassc7d80352019-07-08 13:18:28 -0600115 tools.SetToolPaths(options.toolpath)
Simon Glassc55a50f2018-09-14 04:57:19 -0600116 state.SetEntryArgs(options.entry_arg)
Simon Glassecab8972018-07-06 10:27:40 -0600117
118 # Get the device tree ready by compiling it and copying the compiled
119 # output into a file in our output directly. Then scan it for use
120 # in binman.
121 dtb_fname = fdt_util.EnsureCompiled(dtb_fname)
Simon Glass6ed45ba2018-09-14 04:57:24 -0600122 fname = tools.GetOutputFilename('u-boot.dtb.out')
123 tools.WriteFile(fname, tools.ReadFile(dtb_fname))
Simon Glassecab8972018-07-06 10:27:40 -0600124 dtb = fdt.FdtScan(fname)
125
Simon Glassec3f3782017-05-27 07:38:29 -0600126 node = _FindBinmanNode(dtb)
Simon Glassbf7fd502016-11-25 20:15:51 -0700127 if not node:
128 raise ValueError("Device tree '%s' does not have a 'binman' "
129 "node" % dtb_fname)
Simon Glassecab8972018-07-06 10:27:40 -0600130
Simon Glassbf7fd502016-11-25 20:15:51 -0700131 images = _ReadImageDesc(node)
Simon Glassecab8972018-07-06 10:27:40 -0600132
Simon Glass0bfa7b02018-09-14 04:57:12 -0600133 if options.image:
134 skip = []
Simon Glass58632a72019-05-17 22:00:45 -0600135 new_images = OrderedDict()
Simon Glass50979152019-05-14 15:53:41 -0600136 for name, image in images.items():
Simon Glass58632a72019-05-17 22:00:45 -0600137 if name in options.image:
138 new_images[name] = image
139 else:
Simon Glass0bfa7b02018-09-14 04:57:12 -0600140 skip.append(name)
Simon Glass58632a72019-05-17 22:00:45 -0600141 images = new_images
Simon Glasseb833d82019-04-25 21:58:34 -0600142 if skip and options.verbosity >= 2:
Simon Glass2ca84682019-05-14 15:53:37 -0600143 print('Skipping images: %s' % ', '.join(skip))
Simon Glass0bfa7b02018-09-14 04:57:12 -0600144
Simon Glass539aece2018-09-14 04:57:22 -0600145 state.Prepare(images, dtb)
Simon Glass2a72cc72018-09-14 04:57:20 -0600146
Simon Glassecab8972018-07-06 10:27:40 -0600147 # Prepare the device tree by making sure that any missing
148 # properties are added (e.g. 'pos' and 'size'). The values of these
149 # may not be correct yet, but we add placeholders so that the
150 # size of the device tree is correct. Later, in
151 # SetCalculatedProperties() we will insert the correct values
152 # without changing the device-tree size, thus ensuring that our
Simon Glass3ab95982018-08-01 15:22:37 -0600153 # entry offsets remain the same.
Simon Glassecab8972018-07-06 10:27:40 -0600154 for image in images.values():
Simon Glass0a98b282018-09-14 04:57:28 -0600155 image.ExpandEntries()
Simon Glass078ab1a2018-07-06 10:27:41 -0600156 if options.update_fdt:
157 image.AddMissingProperties()
Simon Glassecab8972018-07-06 10:27:40 -0600158 image.ProcessFdt(dtb)
159
Simon Glass2a72cc72018-09-14 04:57:20 -0600160 for dtb_item in state.GetFdts():
161 dtb_item.Sync(auto_resize=True)
162 dtb_item.Pack()
163 dtb_item.Flush()
Simon Glassecab8972018-07-06 10:27:40 -0600164
Simon Glassbf7fd502016-11-25 20:15:51 -0700165 for image in images.values():
166 # Perform all steps for this image, including checking and
167 # writing it. This means that errors found with a later
168 # image will be reported after earlier images are already
169 # completed and written, but that does not seem important.
170 image.GetEntryContents()
Simon Glass3ab95982018-08-01 15:22:37 -0600171 image.GetEntryOffsets()
Simon Glass163ed6c2018-09-14 04:57:36 -0600172 try:
173 image.PackEntries()
174 image.CheckSize()
175 image.CheckEntries()
176 except Exception as e:
177 if options.map:
178 fname = image.WriteMap()
Simon Glass2ca84682019-05-14 15:53:37 -0600179 print("Wrote map file '%s' to show errors" % fname)
Simon Glass163ed6c2018-09-14 04:57:36 -0600180 raise
Simon Glassdbf6be92018-08-01 15:22:42 -0600181 image.SetImagePos()
Simon Glass078ab1a2018-07-06 10:27:41 -0600182 if options.update_fdt:
183 image.SetCalculatedProperties()
Simon Glass2a72cc72018-09-14 04:57:20 -0600184 for dtb_item in state.GetFdts():
185 dtb_item.Sync()
Simon Glassbf7fd502016-11-25 20:15:51 -0700186 image.ProcessEntryContents()
Simon Glass19790632017-11-13 18:55:01 -0700187 image.WriteSymbols()
Simon Glassbf7fd502016-11-25 20:15:51 -0700188 image.BuildImage()
Simon Glass3b0c3822018-06-01 09:38:20 -0600189 if options.map:
190 image.WriteMap()
Simon Glass2a72cc72018-09-14 04:57:20 -0600191
192 # Write the updated FDTs to our output files
193 for dtb_item in state.GetFdts():
194 tools.WriteFile(dtb_item._fname, dtb_item.GetContents())
195
Simon Glassbf7fd502016-11-25 20:15:51 -0700196 finally:
197 tools.FinaliseOutputDir()
198 finally:
199 tout.Uninit()
200
201 return 0