def ExtractEntries(image_fname, output_fname, outdir, entry_paths, decomp=True): """Extract the data from one or more entries and write it to files Args: image_fname: Image filename to process output_fname: Single output filename to use if extracting one file, None otherwise outdir: Output directory to use (for any number of files), else None entry_paths: List of entry paths to extract decomp: True to decompress the entry data Returns: List of EntryInfo records that were written """ image = Image.FromFile(image_fname) # Output an entry to a single file, as a special case if output_fname: if not entry_paths: raise ValueError('Must specify an entry path to write with -f') if len(entry_paths) != 1: raise ValueError( 'Must specify exactly one entry path to write with -f') entry = image.FindEntryPath(entry_paths[0]) data = entry.ReadData(decomp) tools.WriteFile(output_fname, data) tout.Notice("Wrote %#x bytes to file '%s'" % (len(data), output_fname)) return # Otherwise we will output to a path given by the entry path of each entry. # This means that entries will appear in subdirectories if they are part of # a sub-section. einfos = image.GetListEntries(entry_paths)[0] tout.Notice('%d entries match and will be written' % len(einfos)) for einfo in einfos: entry = einfo.entry data = entry.ReadData(decomp) path = entry.GetPath()[1:] fname = os.path.join(outdir, path) # If this entry has children, create a directory for it and put its # data in a file called 'root' in that directory if entry.GetEntries(): if not os.path.exists(fname): os.makedirs(fname) fname = os.path.join(fname, 'root') tout.Notice("Write entry '%s' to '%s'" % (entry.GetPath(), fname)) tools.WriteFile(fname, data) return einfos
def _BuildIfwi(self): """Build the contents of the IFWI and write it to the 'data' property""" # Create the IFWI file if needed if self._convert_fit: inname = self._pathname outname = tools.GetOutputFilename('ifwi.bin') tools.RunIfwiTool(inname, tools.CMD_CREATE, outname) self._filename = 'ifwi.bin' self._pathname = outname else: # Provide a different code path here to ensure we have test coverage outname = self._pathname # Delete OBBP if it is there, then add the required new items. tools.RunIfwiTool(outname, tools.CMD_DELETE, subpart='OBBP') for entry in self._ifwi_entries.values(): # First get the input data and put it in a file data = entry.GetData() uniq = self.GetUniqueName() input_fname = tools.GetOutputFilename('input.%s' % uniq) tools.WriteFile(input_fname, data) tools.RunIfwiTool( outname, tools.CMD_REPLACE if entry._ifwi_replace else tools.CMD_ADD, input_fname, entry._ifwi_subpart, entry._ifwi_entry_name) self.ReadBlobContents() return True
def ProduceFinalImage(self, tools, out, tmpdir, image_fname): """Produce the final image for an Intel ME system Some Intel systems require that an image contains the Management Engine firmware, and also a firmware descriptor. This function takes the existing image, removes the front part of it, and replaces it with these required pieces using ifdtool. Args: tools: Tools object to use to run tools. out: Output object to send output to tmpdir: Temporary directory to use to create required files. image_fname: Output image filename """ out.Progress('Setting up Intel ME') data = tools.ReadFile(image_fname) # We can assume that the ifd section is at the start of the image. if self.offset != 0: raise ConfigError('IFD section must be at offset 0 in the image') data = data[self.size:] input_fname = os.path.join(tmpdir, 'ifd-input.bin') tools.WriteFile(input_fname, data) ifd_output = os.path.join(tmpdir, 'image.ifd') # This works by modifying a skeleton file. shutil.copyfile(tools.Filename(self.pack.props['skeleton']), ifd_output) args = ['-i', 'BIOS:%s' % input_fname, ifd_output] tools.Run('ifdtool', args) # ifdtool puts the output in a file with '.new' tacked on the end. shutil.move(ifd_output + '.new', image_fname) tools.OutputSize('IFD image', image_fname)
def _HandleMake(self, commit, brd, stage, cwd, *args, **kwargs): """Handle execution of 'make' Args: commit: Commit object that is being built brd: Board object that is being built stage: Stage that we are at (mrproper, config, build) cwd: Directory where make should be run args: Arguments to pass to make kwargs: Arguments to pass to command.RunPipe() """ self._make_calls += 1 if stage == 'mrproper': return command.CommandResult(return_code=0) elif stage == 'config': return command.CommandResult( return_code=0, combined='Test configuration complete') elif stage == 'build': stderr = '' out_dir = '' for arg in args: if arg.startswith('O='): out_dir = arg[2:] fname = os.path.join(cwd or '', out_dir, 'u-boot') tools.WriteFile(fname, b'U-Boot') if type(commit) is not str: stderr = self._error.get((brd.target, commit.sequence)) if stderr: return command.CommandResult(return_code=1, stderr=stderr) return command.CommandResult(return_code=0) # Not handled, so abort print('make', stage) sys.exit(1)
def RunTools(self, tools, out, tmpdir): """Create a vblock for the given firmware image""" self.path = os.path.join(tmpdir, 'vblock.%s' % self.label) input_data = os.path.join(tmpdir, 'input.%s' % self.label) try: prefix = self.pack.props['keydir'] + '/' # Join up the data files to be signed data = self.pack.tools.ReadFileAndConcat( self.value, self.compress, self.with_index)[0] tools.WriteFile(input_data, data) args = [ '--vblock', self.path, '--keyblock', prefix + self.keyblock, '--signprivate', prefix + self.signprivate, '--version', '%d' % self.version, '--fv', input_data, '--kernelkey', prefix + self.kernelkey, '--flags', '%d' % self.preamble_flags, ] out.Notice("Sign '%s' into %s" % (', '.join(self.value), self.label)) stdout = tools.Run('vbutil_firmware', args) out.Debug(stdout) # Update value to the actual filename to be used self.value = [self.path] except CmdError as err: raise PackError('Cannot make key block: vbutil_firmware failed\n%s' % err)
def ObtainContents(self): # Join up the data files to be signed input_data = '' for entry_phandle in self.content: data = self.section.GetContentsByPhandle(entry_phandle, self) if data is None: # Data not available yet return False input_data += data uniq = self.GetUniqueName() output_fname = tools.GetOutputFilename('vblock.%s' % uniq) input_fname = tools.GetOutputFilename('input.%s' % uniq) tools.WriteFile(input_fname, input_data) prefix = self.keydir + '/' args = [ 'vbutil_firmware', '--vblock', output_fname, '--keyblock', prefix + self.keyblock, '--signprivate', prefix + self.signprivate, '--version', '%d' % self.version, '--fv', input_fname, '--kernelkey', prefix + self.kernelkey, '--flags', '%d' % self.preamble_flags, ] #out.Notice("Sign '%s' into %s" % (', '.join(self.value), self.label)) stdout = tools.Run('futility', *args) self.SetContents(tools.ReadFile(output_fname)) return True
def ReadBlobContents(self): if self._strip: uniq = self.GetUniqueName() out_fname = tools.GetOutputFilename('%s.stripped' % uniq) tools.WriteFile(out_fname, tools.ReadFile(self._pathname)) tools.Run('strip', out_fname) self._pathname = out_fname Entry_blob.ReadBlobContents(self) return True
def _compare_expected_cbfs(self, data, cbfstool_fname): """Compare against what cbfstool creates This compares what binman creates with what cbfstool creates for what is proportedly the same thing. Args: data: CBFS created by binman cbfstool_fname: CBFS created by cbfstool """ if not self.have_cbfstool or not self.have_lz4: return expect = tools.ReadFile(cbfstool_fname) if expect != data: tools.WriteFile('/tmp/expect', expect) tools.WriteFile('/tmp/actual', data) print('diff -y <(xxd -g1 /tmp/expect) <(xxd -g1 /tmp/actual) | colordiff') self.fail('cbfstool produced a different result')
def _make_input_file(cls, fname, contents): """Create a new test input file, creating directories as needed Args: fname: Filename to create contents: File contents to write in to the file Returns: Full pathname of file created """ pathname = os.path.join(cls._indir, fname) tools.WriteFile(pathname, contents) return pathname
def UpdateFdtContents(etype, data): """Update the contents of a particular device tree The device tree is updated and written back to its file. This affects what is returned from future called to GetFdtContents(), etc. Args: etype: Entry type (e.g. 'u-boot-dtb') data: Data to replace the DTB with """ dtb, fname, entry = output_fdt_info[etype] dtb_fname = dtb.GetFilename() tools.WriteFile(dtb_fname, data) dtb = fdt.FdtScan(dtb_fname) output_fdt_info[etype] = [dtb, fname, entry]
def ObtainContents(self): """Get the contects for the IFWI Unfortunately we cannot create anything from scratch here, as Intel has tools which create precursor binaries with lots of data and settings, and these are not incorporated into binman. The first step is to get a file in the IFWI format. This is either supplied directly or is extracted from a fitimage using the 'create' subcommand. After that we delete the OBBP sub-partition and add each of the files that we want in the IFWI file, one for each sub-entry of the IWFI node. """ self._pathname = tools.GetInputFilename(self._filename) # Create the IFWI file if needed if self._convert_fit: inname = self._pathname outname = tools.GetOutputFilename('ifwi.bin') tools.RunIfwiTool(inname, tools.CMD_CREATE, outname) self._filename = 'ifwi.bin' self._pathname = outname else: # Provide a different code path here to ensure we have test coverage inname = self._pathname # Delete OBBP if it is there, then add the required new items. tools.RunIfwiTool(inname, tools.CMD_DELETE, subpart='OBBP') for entry in self._ifwi_entries.values(): # First get the input data and put it in a file if not entry.ObtainContents(): return False data = entry.GetData() uniq = self.GetUniqueName() input_fname = tools.GetOutputFilename('input.%s' % uniq) tools.WriteFile(input_fname, data) tools.RunIfwiTool( inname, tools.CMD_REPLACE if entry._ifwi_replace else tools.CMD_ADD, input_fname, entry._ifwi_subpart, entry._ifwi_entry_name) self.ReadBlobContents() return True
def FromFile(cls, fname): """Convert an image file into an Image for use in binman Args: fname: Filename of image file to read Returns: Image object on success Raises: ValueError if something goes wrong """ data = tools.ReadFile(fname) size = len(data) # First look for an image header pos = image_header.LocateHeaderOffset(data) if pos is None: # Look for the FDT map pos = fdtmap.LocateFdtmap(data) if pos is None: raise ValueError('Cannot find FDT map in image') # We don't know the FDT size, so check its header first probe_dtb = fdt.Fdt.FromData( data[pos + fdtmap.FDTMAP_HDR_LEN:pos + 256]) dtb_size = probe_dtb.GetFdtObj().totalsize() fdtmap_data = data[pos:pos + dtb_size + fdtmap.FDTMAP_HDR_LEN] fdt_data = fdtmap_data[fdtmap.FDTMAP_HDR_LEN:] out_fname = tools.GetOutputFilename('fdtmap.in.dtb') tools.WriteFile(out_fname, fdt_data) dtb = fdt.Fdt(out_fname) dtb.Scan() # Return an Image with the associated nodes root = dtb.GetRoot() image = Image('image', root, copy_to_orig=False) image.image_node = fdt_util.GetString(root, 'image-node', 'image') image.fdtmap_dtb = dtb image.fdtmap_data = fdtmap_data image._data = data image._filename = fname image.image_name, _ = os.path.splitext(fname) return image
def PrepareFromLoadedData(image): """Get device tree files ready for use with a loaded image Loaded images are different from images that are being created by binman, since there is generally already an fdtmap and we read the description from that. This provides the position and size of every entry in the image with no calculation required. This function uses the same output_fdt_info[] as Prepare(). It finds the device tree files, adds a reference to the fdtmap and sets the FDT path prefix to translate from the fdtmap (where the root node is the image node) to the normal device tree (where the image node is under a /binman node). Args: images: List of images being used """ global output_fdt_info, main_dtb, fdt_path_prefix tout.Info('Preparing device trees') output_fdt_info.clear() fdt_path_prefix = '' output_fdt_info['fdtmap'] = [image.fdtmap_dtb, 'u-boot.dtb', None] main_dtb = None tout.Info(" Found device tree type 'fdtmap' '%s'" % image.fdtmap_dtb.name) for etype, value in image.GetFdts().items(): entry, fname = value out_fname = tools.GetOutputFilename('%s.dtb' % entry.etype) tout.Info(" Found device tree type '%s' at '%s' path '%s'" % (etype, out_fname, entry.GetPath())) entry._filename = entry.GetDefaultFilename() data = entry.ReadData() tools.WriteFile(out_fname, data) dtb = fdt.Fdt(out_fname) dtb.Scan() image_node = dtb.GetNode('/binman') if 'multiple-images' in image_node.props: image_node = dtb.GetNode('/binman/%s' % image.image_node) fdt_path_prefix = image_node.path output_fdt_info[etype] = [dtb, None, entry] tout.Info(" FDT path prefix '%s'" % fdt_path_prefix)
def Prepare(images, dtb): """Get device tree files ready for use This sets up a set of device tree files that can be retrieved by GetAllFdts(). This includes U-Boot proper and any SPL device trees. Args: images: List of images being used dtb: Main dtb """ global output_fdt_info, main_dtb, fdt_path_prefix # Import these here in case libfdt.py is not available, in which case # the above help option still works. import fdt import fdt_util # If we are updating the DTBs we need to put these updated versions # where Entry_blob_dtb can find them. We can ignore 'u-boot.dtb' # since it is assumed to be the one passed in with options.dt, and # was handled just above. main_dtb = dtb output_fdt_info.clear() fdt_path_prefix = '' output_fdt_info['u-boot-dtb'] = [dtb, 'u-boot.dtb', None] output_fdt_info['u-boot-spl-dtb'] = [dtb, 'spl/u-boot-spl.dtb', None] output_fdt_info['u-boot-tpl-dtb'] = [dtb, 'tpl/u-boot-tpl.dtb', None] if not use_fake_dtb: fdt_set = {} for image in images.values(): fdt_set.update(image.GetFdts()) for etype, other in fdt_set.items(): entry, other_fname = other infile = tools.GetInputFilename(other_fname) other_fname_dtb = fdt_util.EnsureCompiled(infile) out_fname = tools.GetOutputFilename('%s.out' % os.path.split(other_fname)[1]) tools.WriteFile(out_fname, tools.ReadFile(other_fname_dtb)) other_dtb = fdt.FdtScan(out_fname) output_fdt_info[etype] = [other_dtb, out_fname, entry]
def ObtainContents(self): # If the section does not need microcode, there is nothing to do found = False for suffix in ['', '-spl', '-tpl']: name = 'u-boot%s-with-ucode-ptr' % suffix entry = self.section.FindEntryType(name) if entry and entry.target_offset: found = True if not found: self.data = b'' return True # Get the microcode from the device tree entry. If it is not available # yet, return False so we will be called later. If the section simply # doesn't exist, then we may as well return True, since we are going to # get an error anyway. for suffix in ['', '-spl', '-tpl']: name = 'u-boot%s-dtb-with-ucode' % suffix fdt_entry = self.section.FindEntryType(name) if fdt_entry: break if not fdt_entry: return True if not fdt_entry.ready: return False if not fdt_entry.collate: # This binary can be empty self.data = b'' return True # Write it out to a file self._pathname = tools.GetOutputFilename('u-boot-ucode.bin') tools.WriteFile(self._pathname, fdt_entry.ucode_data) self.ReadBlobContents() return True
def Prepare(images, dtb): """Get device tree files ready for use This sets up a set of device tree files that can be retrieved by GetFdts(). At present there is only one, that for U-Boot proper. Args: images: List of images being used dtb: Main dtb """ global fdt_set, fdt_subset, fdt_files, main_dtb # Import these here in case libfdt.py is not available, in which case # the above help option still works. import fdt import fdt_util # If we are updating the DTBs we need to put these updated versions # where Entry_blob_dtb can find them. We can ignore 'u-boot.dtb' # since it is assumed to be the one passed in with options.dt, and # was handled just above. main_dtb = dtb fdt_files.clear() fdt_files['u-boot.dtb'] = dtb fdt_subset = set() if not use_fake_dtb: for image in images.values(): fdt_subset.update(image.GetFdtSet()) fdt_subset.discard('u-boot.dtb') for other_fname in fdt_subset: infile = tools.GetInputFilename(other_fname) other_fname_dtb = fdt_util.EnsureCompiled(infile) out_fname = tools.GetOutputFilename('%s.out' % os.path.split(other_fname)[1]) tools.WriteFile(out_fname, tools.ReadFile(other_fname_dtb)) other_dtb = fdt.FdtScan(out_fname) fdt_files[other_fname] = other_dtb
def PrepareImagesAndDtbs(dtb_fname, select_images, update_fdt): """Prepare the images to be processed and select the device tree This function: - reads in the device tree - finds and scans the binman node to create all entries - selects which images to build - Updates the device tress with placeholder properties for offset, image-pos, etc. Args: dtb_fname: Filename of the device tree file to use (.dts or .dtb) selected_images: List of images to output, or None for all update_fdt: True to update the FDT wth entry offsets, etc. """ # Import these here in case libfdt.py is not available, in which case # the above help option still works. import fdt import fdt_util global images # 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 select_images: skip = [] new_images = OrderedDict() for name, image in images.items(): if name in select_images: new_images[name] = image else: skip.append(name) images = new_images tout.Notice('Skipping images: %s' % ', '.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 update_fdt: image.AddMissingProperties() image.ProcessFdt(dtb) for dtb_item in state.GetAllFdts(): dtb_item.Sync(auto_resize=True) dtb_item.Pack() dtb_item.Flush() return images
def _Touch(fname): tools.WriteFile(os.path.join(base_dir, fname), b'')
def Binman(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: args: Command line arguments Namespace object """ global images if args.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 if args.cmd == 'ls': ListEntries(args.image, args.paths) return 0 if args.cmd == 'extract': try: tools.PrepareOutputDir(None) ExtractEntries(args.image, args.filename, args.outdir, args.paths, not args.uncompressed) finally: tools.FinaliseOutputDir() return 0 # Try to figure out which device tree contains our image description if args.dt: dtb_fname = args.dt else: board = args.board if not board: raise ValueError( 'Must provide a board to process (use -b <board>)') board_pathname = os.path.join(args.build_dir, board) dtb_fname = os.path.join(board_pathname, 'u-boot.dtb') if not args.indir: args.indir = ['.'] args.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(args.verbosity) elf.debug = args.debug cbfs_util.VERBOSE = args.verbosity > 2 state.use_fake_dtb = args.fake_dtb try: tools.SetInputDirs(args.indir) tools.PrepareOutputDir(args.outdir, args.preserve) tools.SetToolPaths(args.toolpath) state.SetEntryArgs(args.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 args.image: skip = [] new_images = OrderedDict() for name, image in images.items(): if name in args.image: new_images[name] = image else: skip.append(name) images = new_images if skip and args.verbosity >= 2: print('Skipping images: %s' % ', '.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 args.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() # We need to pack the entries to figure out where everything # should be placed. This sets the offset/size of each entry. # However, after packing we call ProcessEntryContents() which # may result in an entry changing size. In that case we need to # do another pass. Since the device tree often contains the # final offset/size information we try to make space for this in # AddMissingProperties() above. However, if the device is # compressed we cannot know this compressed size in advance, # since changing an offset from 0x100 to 0x104 (for example) can # alter the compressed size of the device tree. So we need a # third pass for this. passes = 3 for pack_pass in range(passes): try: image.PackEntries() image.CheckSize() image.CheckEntries() except Exception as e: if args.map: fname = image.WriteMap() print("Wrote map file '%s' to show errors" % fname) raise image.SetImagePos() if args.update_fdt: image.SetCalculatedProperties() for dtb_item in state.GetFdts(): dtb_item.Sync() sizes_ok = image.ProcessEntryContents() if sizes_ok: break image.ResetForPack() if not sizes_ok: image.Raise( 'Entries expanded after packing (tried %s passes)' % passes) image.WriteSymbols() image.BuildImage() if args.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
def Binman(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: args: Command line arguments Namespace object """ if args.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 if args.cmd == 'ls': try: tools.PrepareOutputDir(None) ListEntries(args.image, args.paths) finally: tools.FinaliseOutputDir() return 0 if args.cmd == 'extract': try: tools.PrepareOutputDir(None) ExtractEntries(args.image, args.filename, args.outdir, args.paths, not args.uncompressed) finally: tools.FinaliseOutputDir() return 0 if args.cmd == 'replace': try: tools.PrepareOutputDir(None) ReplaceEntries(args.image, args.filename, args.indir, args.paths, do_compress=not args.compressed, allow_resize=not args.fix_size, write_map=args.map) finally: tools.FinaliseOutputDir() return 0 # Try to figure out which device tree contains our image description if args.dt: dtb_fname = args.dt else: board = args.board if not board: raise ValueError( 'Must provide a board to process (use -b <board>)') board_pathname = os.path.join(args.build_dir, board) dtb_fname = os.path.join(board_pathname, 'u-boot.dtb') if not args.indir: args.indir = ['.'] args.indir.append(board_pathname) try: tout.Init(args.verbosity) elf.debug = args.debug cbfs_util.VERBOSE = args.verbosity > 2 state.use_fake_dtb = args.fake_dtb try: tools.SetInputDirs(args.indir) tools.PrepareOutputDir(args.outdir, args.preserve) tools.SetToolPaths(args.toolpath) state.SetEntryArgs(args.entry_arg) images = PrepareImagesAndDtbs(dtb_fname, args.image, args.update_fdt) for image in images.values(): ProcessImage(image, args.update_fdt, args.map) # Write the updated FDTs to our output files for dtb_item in state.GetAllFdts(): tools.WriteFile(dtb_item._fname, dtb_item.GetContents()) finally: tools.FinaliseOutputDir() finally: tout.Uninit() return 0
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 = [] new_images = OrderedDict() for name, image in images.items(): if name in options.image: new_images[name] = image else: skip.append(name) images = new_images if skip and options.verbosity >= 2: print('Skipping images: %s' % ', '.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() try: image.PackEntries() image.CheckSize() image.CheckEntries() except Exception as e: if options.map: fname = image.WriteMap() print("Wrote map file '%s' to show errors" % fname) raise 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