123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179 |
- # SPDX-License-Identifier: GPL-2.0+
- # Copyright (c) 2016 Google, Inc
- # Written by Simon Glass <sjg@chromium.org>
- #
- # Creates binary images from input files controlled by a description
- #
- from collections import OrderedDict
- import os
- import sys
- import tools
- import command
- import elf
- import fdt
- import fdt_util
- from image import Image
- import tout
- # List of images we plan to create
- # Make this global so that it can be referenced from tests
- images = OrderedDict()
- # Records the device-tree files known to binman, keyed by filename (e.g.
- # 'u-boot-spl.dtb')
- fdt_files = {}
- def _ReadImageDesc(binman_node):
- """Read the image descriptions from the /binman node
- This normally produces a single Image object called 'image'. But if
- multiple images are present, they will all be returned.
- Args:
- binman_node: Node object of the /binman node
- Returns:
- OrderedDict of Image objects, each of which describes an image
- """
- images = OrderedDict()
- if 'multiple-images' in binman_node.props:
- for node in binman_node.subnodes:
- images[node.name] = Image(node.name, node)
- else:
- images['image'] = Image('image', binman_node)
- return images
- def _FindBinmanNode(dtb):
- """Find the 'binman' node in the device tree
- Args:
- dtb: Fdt object to scan
- Returns:
- Node object of /binman node, or None if not found
- """
- for node in dtb.GetRoot().subnodes:
- if node.name == 'binman':
- return node
- return None
- def GetFdt(fname):
- """Get the Fdt object for a particular device-tree filename
- Binman keeps track of at least one device-tree file called u-boot.dtb but
- can also have others (e.g. for SPL). This function looks up the given
- filename and returns the associated Fdt object.
- Args:
- fname: Filename to look up (e.g. 'u-boot.dtb').
- Returns:
- Fdt object associated with the filename
- """
- return fdt_files[fname]
- def GetFdtPath(fname):
- return fdt_files[fname]._fname
- def Binman(options, args):
- """The main control code for binman
- This assumes that help and test options have already been dealt with. It
- deals with the core task of building images.
- Args:
- options: Command line options object
- args: Command line arguments (list of strings)
- """
- global images
- if options.full_help:
- pager = os.getenv('PAGER')
- if not pager:
- pager = 'more'
- fname = os.path.join(os.path.dirname(os.path.realpath(sys.argv[0])),
- 'README')
- command.Run(pager, fname)
- return 0
- # Try to figure out which device tree contains our image description
- if options.dt:
- dtb_fname = options.dt
- else:
- board = options.board
- if not board:
- raise ValueError('Must provide a board to process (use -b <board>)')
- board_pathname = os.path.join(options.build_dir, board)
- dtb_fname = os.path.join(board_pathname, 'u-boot.dtb')
- if not options.indir:
- options.indir = ['.']
- options.indir.append(board_pathname)
- try:
- tout.Init(options.verbosity)
- elf.debug = options.debug
- try:
- tools.SetInputDirs(options.indir)
- tools.PrepareOutputDir(options.outdir, options.preserve)
- # Get the device tree ready by compiling it and copying the compiled
- # output into a file in our output directly. Then scan it for use
- # in binman.
- dtb_fname = fdt_util.EnsureCompiled(dtb_fname)
- fname = tools.GetOutputFilename('u-boot-out.dtb')
- with open(dtb_fname) as infd:
- with open(fname, 'wb') as outfd:
- outfd.write(infd.read())
- dtb = fdt.FdtScan(fname)
- # Note the file so that GetFdt() can find it
- fdt_files['u-boot.dtb'] = dtb
- node = _FindBinmanNode(dtb)
- if not node:
- raise ValueError("Device tree '%s' does not have a 'binman' "
- "node" % dtb_fname)
- images = _ReadImageDesc(node)
- # Prepare the device tree by making sure that any missing
- # properties are added (e.g. 'pos' and 'size'). The values of these
- # may not be correct yet, but we add placeholders so that the
- # size of the device tree is correct. Later, in
- # SetCalculatedProperties() we will insert the correct values
- # without changing the device-tree size, thus ensuring that our
- # entry offsets remain the same.
- for image in images.values():
- if options.update_fdt:
- image.AddMissingProperties()
- image.ProcessFdt(dtb)
- dtb.Pack()
- dtb.Flush()
- for image in images.values():
- # Perform all steps for this image, including checking and
- # writing it. This means that errors found with a later
- # image will be reported after earlier images are already
- # completed and written, but that does not seem important.
- image.GetEntryContents()
- image.GetEntryOffsets()
- image.PackEntries()
- image.CheckSize()
- image.CheckEntries()
- image.SetImagePos()
- if options.update_fdt:
- image.SetCalculatedProperties()
- image.ProcessEntryContents()
- image.WriteSymbols()
- image.BuildImage()
- if options.map:
- image.WriteMap()
- with open(fname, 'wb') as outfd:
- outfd.write(dtb.GetContents())
- finally:
- tools.FinaliseOutputDir()
- finally:
- tout.Uninit()
- return 0
|