summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSimon Glass <sjg@chromium.org>2019-07-08 14:25:50 -0600
committerSimon Glass <sjg@chromium.org>2019-07-24 12:54:08 -0700
commitf667e45b1c0a7f21d433ee8f3ec18858d87dd2e5 (patch)
treeae849665f80553e7689976d578e90250545f5423
parenteea264ead3ca198ed66f62a78dc4940075621ae7 (diff)
downloadu-boot-f667e45b1c0a7f21d433ee8f3ec18858d87dd2e5.tar.gz
u-boot-f667e45b1c0a7f21d433ee8f3ec18858d87dd2e5.tar.bz2
u-boot-f667e45b1c0a7f21d433ee8f3ec18858d87dd2e5.zip
binman: Allow reading an entry from an image
It is useful to be able to extract entry contents from an image to see what is inside. Add a simple function to read the contents of an entry, decompressing it by default. Signed-off-by: Simon Glass <sjg@chromium.org>
-rw-r--r--tools/binman/control.py20
-rw-r--r--tools/binman/entry.py21
-rw-r--r--tools/binman/etype/blob.py13
-rw-r--r--tools/binman/ftest.py42
-rw-r--r--tools/binman/image.py4
5 files changed, 99 insertions, 1 deletions
diff --git a/tools/binman/control.py b/tools/binman/control.py
index 813c8b1bf9..b244e7a0cd 100644
--- a/tools/binman/control.py
+++ b/tools/binman/control.py
@@ -98,6 +98,26 @@ def ListEntries(image_fname, entry_paths):
out += txt
print(out.rstrip())
+
+def ReadEntry(image_fname, entry_path, decomp=True):
+ """Extract an entry from an image
+
+ This extracts the data from a particular entry in an image
+
+ Args:
+ image_fname: Image filename to process
+ entry_path: Path to entry to extract
+ decomp: True to return uncompressed data, if the data is compress
+ False to return the raw data
+
+ Returns:
+ data extracted from the entry
+ """
+ image = Image.FromFile(image_fname)
+ entry = image.FindEntryPath(entry_path)
+ return entry.ReadData(decomp)
+
+
def Binman(args):
"""The main control code for binman
diff --git a/tools/binman/entry.py b/tools/binman/entry.py
index 33d3f1e4d4..1c382f3b85 100644
--- a/tools/binman/entry.py
+++ b/tools/binman/entry.py
@@ -659,3 +659,24 @@ features to produce new behaviours.
"""
self.AddEntryInfo(entries, indent, self.name, self.etype, self.size,
self.image_pos, self.uncomp_size, self.offset, self)
+
+ def ReadData(self, decomp=True):
+ """Read the data for an entry from the image
+
+ This is used when the image has been read in and we want to extract the
+ data for a particular entry from that image.
+
+ Args:
+ decomp: True to decompress any compressed data before returning it;
+ False to return the raw, uncompressed data
+
+ Returns:
+ Entry data (bytes)
+ """
+ # Use True here so that we get an uncompressed section to work from,
+ # although compressed sections are currently not supported
+ data = self.section.ReadData(True)
+ tout.Info('%s: Reading data from offset %#x-%#x, size %#x (avail %#x)' %
+ (self.GetPath(), self.offset, self.offset + self.size,
+ self.size, len(data)))
+ return data[self.offset:self.offset + self.size]
diff --git a/tools/binman/etype/blob.py b/tools/binman/etype/blob.py
index a4ff0efceb..00cad33718 100644
--- a/tools/binman/etype/blob.py
+++ b/tools/binman/etype/blob.py
@@ -9,6 +9,7 @@ from entry import Entry
import fdt_util
import state
import tools
+import tout
class Entry_blob(Entry):
"""Entry containing an arbitrary binary blob
@@ -66,3 +67,15 @@ class Entry_blob(Entry):
def GetDefaultFilename(self):
return self._filename
+
+ def ReadData(self, decomp=True):
+ indata = Entry.ReadData(self, decomp)
+ if decomp:
+ data = tools.Decompress(indata, self.compress)
+ if self.uncomp_size:
+ tout.Info("%s: Decompressing data size %#x with algo '%s' to data size %#x" %
+ (self.GetPath(), len(indata), self.compress,
+ len(data)))
+ else:
+ data = indata
+ return data
diff --git a/tools/binman/ftest.py b/tools/binman/ftest.py
index ad828041f3..c11dd1b85a 100644
--- a/tools/binman/ftest.py
+++ b/tools/binman/ftest.py
@@ -69,6 +69,8 @@ FILES_DATA = (b"sorry I'm late\nOh, don't bother apologising, I'm " +
COMPRESS_DATA = b'compress xxxxxxxxxxxxxxxxxxxxxx data'
REFCODE_DATA = b'refcode'
+EXTRACT_DTB_SIZE = 0x3c9
+
class TestFunctional(unittest.TestCase):
"""Functional tests for binman
@@ -2423,6 +2425,46 @@ class TestFunctional(unittest.TestCase):
"""Test listing the files in a sub-entry of a section"""
self._RunListCmd(['section/cbfs'], ['cbfs', 'u-boot', 'u-boot-dtb'])
+ def _RunExtractCmd(self, entry_name, decomp=True):
+ """Extract an entry from an image
+
+ Args:
+ entry_name: Entry name to extract
+ decomp: True to decompress the data if compressed, False to leave
+ it in its raw uncompressed format
+
+ Returns:
+ data from entry
+ """
+ self._CheckLz4()
+ self._DoReadFileRealDtb('130_list_fdtmap.dts')
+ image_fname = tools.GetOutputFilename('image.bin')
+ return control.ReadEntry(image_fname, entry_name, decomp)
+
+ def testExtractSimple(self):
+ """Test extracting a single file"""
+ data = self._RunExtractCmd('u-boot')
+ self.assertEqual(U_BOOT_DATA, data)
+
+ def testExtractBadEntry(self):
+ """Test extracting a bad section path"""
+ with self.assertRaises(ValueError) as e:
+ self._RunExtractCmd('section/does-not-exist')
+ self.assertIn("Entry 'does-not-exist' not found in '/section'",
+ str(e.exception))
+
+ def testExtractMissingFile(self):
+ """Test extracting file that does not exist"""
+ with self.assertRaises(IOError) as e:
+ control.ReadEntry('missing-file', 'name')
+
+ def testExtractBadFile(self):
+ """Test extracting an invalid file"""
+ fname = os.path.join(self._indir, 'badfile')
+ tools.WriteFile(fname, b'')
+ with self.assertRaises(ValueError) as e:
+ control.ReadEntry(fname, 'name')
+
if __name__ == "__main__":
unittest.main()
diff --git a/tools/binman/image.py b/tools/binman/image.py
index bbb5e23c3b..fb6e591ca6 100644
--- a/tools/binman/image.py
+++ b/tools/binman/image.py
@@ -82,7 +82,9 @@ class Image(section.Entry_section):
dtb.Scan()
# Return an Image with the associated nodes
- return Image('image', dtb.GetRoot())
+ image = Image('image', dtb.GetRoot())
+ image._data = data
+ return image
def Raise(self, msg):
"""Convenience function to raise an error referencing an image"""