1*4882a593Smuzhiyun# Copyright (c) 2016 Google, Inc 2*4882a593Smuzhiyun# Written by Simon Glass <sjg@chromium.org> 3*4882a593Smuzhiyun# 4*4882a593Smuzhiyun# SPDX-License-Identifier: GPL-2.0+ 5*4882a593Smuzhiyun# 6*4882a593Smuzhiyun# Creates binary images from input files controlled by a description 7*4882a593Smuzhiyun# 8*4882a593Smuzhiyun 9*4882a593Smuzhiyunfrom collections import OrderedDict 10*4882a593Smuzhiyunimport os 11*4882a593Smuzhiyunimport sys 12*4882a593Smuzhiyunimport tools 13*4882a593Smuzhiyun 14*4882a593Smuzhiyunimport command 15*4882a593Smuzhiyunimport fdt 16*4882a593Smuzhiyunimport fdt_util 17*4882a593Smuzhiyunfrom image import Image 18*4882a593Smuzhiyunimport tout 19*4882a593Smuzhiyun 20*4882a593Smuzhiyun# List of images we plan to create 21*4882a593Smuzhiyun# Make this global so that it can be referenced from tests 22*4882a593Smuzhiyunimages = OrderedDict() 23*4882a593Smuzhiyun 24*4882a593Smuzhiyundef _ReadImageDesc(binman_node): 25*4882a593Smuzhiyun """Read the image descriptions from the /binman node 26*4882a593Smuzhiyun 27*4882a593Smuzhiyun This normally produces a single Image object called 'image'. But if 28*4882a593Smuzhiyun multiple images are present, they will all be returned. 29*4882a593Smuzhiyun 30*4882a593Smuzhiyun Args: 31*4882a593Smuzhiyun binman_node: Node object of the /binman node 32*4882a593Smuzhiyun Returns: 33*4882a593Smuzhiyun OrderedDict of Image objects, each of which describes an image 34*4882a593Smuzhiyun """ 35*4882a593Smuzhiyun images = OrderedDict() 36*4882a593Smuzhiyun if 'multiple-images' in binman_node.props: 37*4882a593Smuzhiyun for node in binman_node.subnodes: 38*4882a593Smuzhiyun images[node.name] = Image(node.name, node) 39*4882a593Smuzhiyun else: 40*4882a593Smuzhiyun images['image'] = Image('image', binman_node) 41*4882a593Smuzhiyun return images 42*4882a593Smuzhiyun 43*4882a593Smuzhiyundef _FindBinmanNode(dtb): 44*4882a593Smuzhiyun """Find the 'binman' node in the device tree 45*4882a593Smuzhiyun 46*4882a593Smuzhiyun Args: 47*4882a593Smuzhiyun dtb: Fdt object to scan 48*4882a593Smuzhiyun Returns: 49*4882a593Smuzhiyun Node object of /binman node, or None if not found 50*4882a593Smuzhiyun """ 51*4882a593Smuzhiyun for node in dtb.GetRoot().subnodes: 52*4882a593Smuzhiyun if node.name == 'binman': 53*4882a593Smuzhiyun return node 54*4882a593Smuzhiyun return None 55*4882a593Smuzhiyun 56*4882a593Smuzhiyundef Binman(options, args): 57*4882a593Smuzhiyun """The main control code for binman 58*4882a593Smuzhiyun 59*4882a593Smuzhiyun This assumes that help and test options have already been dealt with. It 60*4882a593Smuzhiyun deals with the core task of building images. 61*4882a593Smuzhiyun 62*4882a593Smuzhiyun Args: 63*4882a593Smuzhiyun options: Command line options object 64*4882a593Smuzhiyun args: Command line arguments (list of strings) 65*4882a593Smuzhiyun """ 66*4882a593Smuzhiyun global images 67*4882a593Smuzhiyun 68*4882a593Smuzhiyun if options.full_help: 69*4882a593Smuzhiyun pager = os.getenv('PAGER') 70*4882a593Smuzhiyun if not pager: 71*4882a593Smuzhiyun pager = 'more' 72*4882a593Smuzhiyun fname = os.path.join(os.path.dirname(os.path.realpath(sys.argv[0])), 73*4882a593Smuzhiyun 'README') 74*4882a593Smuzhiyun command.Run(pager, fname) 75*4882a593Smuzhiyun return 0 76*4882a593Smuzhiyun 77*4882a593Smuzhiyun # Try to figure out which device tree contains our image description 78*4882a593Smuzhiyun if options.dt: 79*4882a593Smuzhiyun dtb_fname = options.dt 80*4882a593Smuzhiyun else: 81*4882a593Smuzhiyun board = options.board 82*4882a593Smuzhiyun if not board: 83*4882a593Smuzhiyun raise ValueError('Must provide a board to process (use -b <board>)') 84*4882a593Smuzhiyun board_pathname = os.path.join(options.build_dir, board) 85*4882a593Smuzhiyun dtb_fname = os.path.join(board_pathname, 'u-boot.dtb') 86*4882a593Smuzhiyun if not options.indir: 87*4882a593Smuzhiyun options.indir = ['.'] 88*4882a593Smuzhiyun options.indir.append(board_pathname) 89*4882a593Smuzhiyun 90*4882a593Smuzhiyun try: 91*4882a593Smuzhiyun tout.Init(options.verbosity) 92*4882a593Smuzhiyun try: 93*4882a593Smuzhiyun tools.SetInputDirs(options.indir) 94*4882a593Smuzhiyun tools.PrepareOutputDir(options.outdir, options.preserve) 95*4882a593Smuzhiyun dtb = fdt.FdtScan(dtb_fname) 96*4882a593Smuzhiyun node = _FindBinmanNode(dtb) 97*4882a593Smuzhiyun if not node: 98*4882a593Smuzhiyun raise ValueError("Device tree '%s' does not have a 'binman' " 99*4882a593Smuzhiyun "node" % dtb_fname) 100*4882a593Smuzhiyun images = _ReadImageDesc(node) 101*4882a593Smuzhiyun for image in images.values(): 102*4882a593Smuzhiyun # Perform all steps for this image, including checking and 103*4882a593Smuzhiyun # writing it. This means that errors found with a later 104*4882a593Smuzhiyun # image will be reported after earlier images are already 105*4882a593Smuzhiyun # completed and written, but that does not seem important. 106*4882a593Smuzhiyun image.GetEntryContents() 107*4882a593Smuzhiyun image.GetEntryPositions() 108*4882a593Smuzhiyun image.PackEntries() 109*4882a593Smuzhiyun image.CheckSize() 110*4882a593Smuzhiyun image.CheckEntries() 111*4882a593Smuzhiyun image.ProcessEntryContents() 112*4882a593Smuzhiyun image.BuildImage() 113*4882a593Smuzhiyun finally: 114*4882a593Smuzhiyun tools.FinaliseOutputDir() 115*4882a593Smuzhiyun finally: 116*4882a593Smuzhiyun tout.Uninit() 117*4882a593Smuzhiyun 118*4882a593Smuzhiyun return 0 119