123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189 |
- # 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
- from image import Image
- import state
- import tout
- # List of images we plan to create
- # Make this global so that it can be referenced from tests
- images = OrderedDict()
- 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 WriteEntryDocs(modules, test_missing=None):
- """Write out documentation for all entries
- Args:
- modules: List of Module objects to get docs for
- test_missing: Used for testing only, to force an entry's documeentation
- to show as missing even if it is present. Should be set to None in
- normal use.
- """
- from entry import Entry
- Entry.WriteDocs(modules, test_missing)
- 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:
- # Import these here in case libfdt.py is not available, in which case
- # the above help option still works.
- import fdt
- import fdt_util
- tout.Init(options.verbosity)
- elf.debug = options.debug
- state.use_fake_dtb = options.fake_dtb
- try:
- tools.SetInputDirs(options.indir)
- tools.PrepareOutputDir(options.outdir, options.preserve)
- state.SetEntryArgs(options.entry_arg)
- # 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.dtb.out')
- tools.WriteFile(fname, tools.ReadFile(dtb_fname))
- dtb = fdt.FdtScan(fname)
- node = _FindBinmanNode(dtb)
- if not node:
- raise ValueError("Device tree '%s' does not have a 'binman' "
- "node" % dtb_fname)
- images = _ReadImageDesc(node)
- if options.image:
- skip = []
- for name, image in images.iteritems():
- if name not in options.image:
- del images[name]
- skip.append(name)
- if skip:
- print 'Skipping images: %s\n' % ', '.join(skip)
- state.Prepare(images, dtb)
- # 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():
- image.ExpandEntries()
- if options.update_fdt:
- image.AddMissingProperties()
- image.ProcessFdt(dtb)
- for dtb_item in state.GetFdts():
- dtb_item.Sync(auto_resize=True)
- dtb_item.Pack()
- dtb_item.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()
- for dtb_item in state.GetFdts():
- dtb_item.Sync()
- image.ProcessEntryContents()
- image.WriteSymbols()
- image.BuildImage()
- if options.map:
- image.WriteMap()
- # Write the updated FDTs to our output files
- for dtb_item in state.GetFdts():
- tools.WriteFile(dtb_item._fname, dtb_item.GetContents())
- finally:
- tools.FinaliseOutputDir()
- finally:
- tout.Uninit()
- return 0
|