# Creates binary images from input files controlled by a description
#
-from __future__ import print_function
-
from collections import OrderedDict
import os
import sys
-import tools
+from patman import tools
-import cbfs_util
-import command
-import elf
-from image import Image
-import state
-import tout
+from binman import cbfs_util
+from binman import elf
+from patman import command
+from patman import tout
# List of images we plan to create
# Make this global so that it can be referenced from tests
to show as missing even if it is present. Should be set to None in
normal use.
"""
- from entry import Entry
+ from binman.entry import Entry
Entry.WriteDocs(modules, test_missing)
Returns:
data extracted from the entry
"""
+ global Image
+ from image import Image
+
image = Image.FromFile(image_fname)
entry = image.FindEntryPath(entry_path)
return entry.ReadData(decomp)
# 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 -o')
+ 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 -o')
+ 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)
return einfos
+def BeforeReplace(image, allow_resize):
+ """Handle getting an image ready for replacing entries in it
+
+ Args:
+ image: Image to prepare
+ """
+ state.PrepareFromLoadedData(image)
+ image.LoadData()
+
+ # If repacking, drop the old offset/size values except for the original
+ # ones, so we are only left with the constraints.
+ if allow_resize:
+ image.ResetForPack()
+
+
+def ReplaceOneEntry(image, entry, data, do_compress, allow_resize):
+ """Handle replacing a single entry an an image
+
+ Args:
+ image: Image to update
+ entry: Entry to write
+ data: Data to replace with
+ do_compress: True to compress the data if needed, False if data is
+ already compressed so should be used as is
+ allow_resize: True to allow entries to change size (this does a re-pack
+ of the entries), False to raise an exception
+ """
+ if not entry.WriteData(data, do_compress):
+ if not image.allow_repack:
+ entry.Raise('Entry data size does not match, but allow-repack is not present for this image')
+ if not allow_resize:
+ entry.Raise('Entry data size does not match, but resize is disabled')
+
+
+def AfterReplace(image, allow_resize, write_map):
+ """Handle write out an image after replacing entries in it
+
+ Args:
+ image: Image to write
+ allow_resize: True to allow entries to change size (this does a re-pack
+ of the entries), False to raise an exception
+ write_map: True to write a map file
+ """
+ tout.Info('Processing image')
+ ProcessImage(image, update_fdt=True, write_map=write_map,
+ get_contents=False, allow_resize=allow_resize)
+
+
+def WriteEntryToImage(image, entry, data, do_compress=True, allow_resize=True,
+ write_map=False):
+ BeforeReplace(image, allow_resize)
+ tout.Info('Writing data to %s' % entry.GetPath())
+ ReplaceOneEntry(image, entry, data, do_compress, allow_resize)
+ AfterReplace(image, allow_resize=allow_resize, write_map=write_map)
+
+
def WriteEntry(image_fname, entry_path, data, do_compress=True,
allow_resize=True, write_map=False):
"""Replace an entry in an image
Returns:
Image object that was updated
"""
- tout.Info("WriteEntry '%s', file '%s'" % (entry_path, image_fname))
+ tout.Info("Write entry '%s', file '%s'" % (entry_path, image_fname))
image = Image.FromFile(image_fname)
entry = image.FindEntryPath(entry_path)
- state.PrepareFromLoadedData(image)
- image.LoadData()
+ WriteEntryToImage(image, entry, data, do_compress=do_compress,
+ allow_resize=allow_resize, write_map=write_map)
- # If repacking, drop the old offset/size values except for the original
- # ones, so we are only left with the constraints.
- if allow_resize:
- image.ResetForPack()
- tout.Info('Writing data to %s' % entry.GetPath())
- if not entry.WriteData(data, do_compress):
- if not image.allow_repack:
- entry.Raise('Entry data size does not match, but allow-repack is not present for this image')
- if not allow_resize:
- entry.Raise('Entry data size does not match, but resize is disabled')
- tout.Info('Processing image')
- ProcessImage(image, update_fdt=True, write_map=False, get_contents=False,
- allow_resize=allow_resize)
- tout.Info('WriteEntry done')
return image
+
+def ReplaceEntries(image_fname, input_fname, indir, entry_paths,
+ do_compress=True, allow_resize=True, write_map=False):
+ """Replace the data from one or more entries from input files
+
+ Args:
+ image_fname: Image filename to process
+ input_fname: Single input ilename to use if replacing one file, None
+ otherwise
+ indir: Input directory to use (for any number of files), else None
+ entry_paths: List of entry paths to extract
+ do_compress: True if the input data is uncompressed and may need to be
+ compressed if the entry requires it, False if the data is already
+ compressed.
+ write_map: True to write a map file
+
+ Returns:
+ List of EntryInfo records that were written
+ """
+ image = Image.FromFile(image_fname)
+
+ # Replace an entry from a single file, as a special case
+ if input_fname:
+ if not entry_paths:
+ raise ValueError('Must specify an entry path to read 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 = tools.ReadFile(input_fname)
+ tout.Notice("Read %#x bytes from file '%s'" % (len(data), input_fname))
+ WriteEntryToImage(image, entry, data, do_compress=do_compress,
+ allow_resize=allow_resize, write_map=write_map)
+ return
+
+ # Otherwise we will input from a path given by the entry path of each entry.
+ # This means that files must appear in subdirectories if they are part of
+ # a sub-section.
+ einfos = image.GetListEntries(entry_paths)[0]
+ tout.Notice("Replacing %d matching entries in image '%s'" %
+ (len(einfos), image_fname))
+
+ BeforeReplace(image, allow_resize)
+
+ for einfo in einfos:
+ entry = einfo.entry
+ if entry.GetEntries():
+ tout.Info("Skipping section entry '%s'" % entry.GetPath())
+ continue
+
+ path = entry.GetPath()[1:]
+ fname = os.path.join(indir, path)
+
+ if os.path.exists(fname):
+ tout.Notice("Write entry '%s' from file '%s'" %
+ (entry.GetPath(), fname))
+ data = tools.ReadFile(fname)
+ ReplaceOneEntry(image, entry, data, do_compress, allow_resize)
+ else:
+ tout.Warning("Skipping entry '%s' from missing file '%s'" %
+ (entry.GetPath(), fname))
+
+ AfterReplace(image, allow_resize=allow_resize, write_map=write_map)
+ return image
+
+
def PrepareImagesAndDtbs(dtb_fname, select_images, update_fdt):
"""Prepare the images to be processed and select the device tree
"""
# Import these here in case libfdt.py is not available, in which case
# the above help option still works.
- import fdt
- import fdt_util
+ from dtoc import fdt
+ from dtoc import fdt_util
global images
# Get the device tree ready by compiling it and copying the compiled
for dtb_item in state.GetAllFdts():
dtb_item.Sync()
dtb_item.Flush()
+ image.WriteSymbols()
sizes_ok = image.ProcessEntryContents()
if sizes_ok:
break
image.ResetForPack()
+ tout.Info('Pack completed after %d pass(es)' % (pack_pass + 1))
if not sizes_ok:
image.Raise('Entries changed size after packing (tried %s passes)' %
passes)
- image.WriteSymbols()
image.BuildImage()
if write_map:
image.WriteMap()
Args:
args: Command line arguments Namespace object
"""
+ global Image
+ global state
+
if args.full_help:
pager = os.getenv('PAGER')
if not pager:
command.Run(pager, fname)
return 0
- if args.cmd == 'ls':
- try:
- tools.PrepareOutputDir(None)
- ListEntries(args.image, args.paths)
- finally:
- tools.FinaliseOutputDir()
- return 0
+ # Put these here so that we can import this module without libfdt
+ from image import Image
+ from binman import state
- if args.cmd == 'extract':
+ if args.cmd in ['ls', 'extract', 'replace']:
try:
+ tout.Init(args.verbosity)
tools.PrepareOutputDir(None)
- ExtractEntries(args.image, args.filename, args.outdir, args.paths,
- not args.uncompressed)
+ if args.cmd == 'ls':
+ ListEntries(args.image, args.paths)
+
+ if args.cmd == 'extract':
+ ExtractEntries(args.image, args.filename, args.outdir, args.paths,
+ not args.uncompressed)
+
+ if args.cmd == 'replace':
+ ReplaceEntries(args.image, args.filename, args.indir, args.paths,
+ do_compress=not args.compressed,
+ allow_resize=not args.fix_size, write_map=args.map)
+ except:
+ raise
finally:
tools.FinaliseOutputDir()
return 0