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