mirror of
https://github.com/u-boot/u-boot.git
synced 2025-05-08 19:11:53 +00:00
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>
This commit is contained in:
parent
eea264ead3
commit
f667e45b1c
5 changed files with 99 additions and 1 deletions
|
@ -98,6 +98,26 @@ def ListEntries(image_fname, entry_paths):
|
||||||
out += txt
|
out += txt
|
||||||
print(out.rstrip())
|
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):
|
def Binman(args):
|
||||||
"""The main control code for binman
|
"""The main control code for binman
|
||||||
|
|
||||||
|
|
|
@ -659,3 +659,24 @@ features to produce new behaviours.
|
||||||
"""
|
"""
|
||||||
self.AddEntryInfo(entries, indent, self.name, self.etype, self.size,
|
self.AddEntryInfo(entries, indent, self.name, self.etype, self.size,
|
||||||
self.image_pos, self.uncomp_size, self.offset, self)
|
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]
|
||||||
|
|
|
@ -9,6 +9,7 @@ from entry import Entry
|
||||||
import fdt_util
|
import fdt_util
|
||||||
import state
|
import state
|
||||||
import tools
|
import tools
|
||||||
|
import tout
|
||||||
|
|
||||||
class Entry_blob(Entry):
|
class Entry_blob(Entry):
|
||||||
"""Entry containing an arbitrary binary blob
|
"""Entry containing an arbitrary binary blob
|
||||||
|
@ -66,3 +67,15 @@ class Entry_blob(Entry):
|
||||||
|
|
||||||
def GetDefaultFilename(self):
|
def GetDefaultFilename(self):
|
||||||
return self._filename
|
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
|
||||||
|
|
|
@ -69,6 +69,8 @@ FILES_DATA = (b"sorry I'm late\nOh, don't bother apologising, I'm " +
|
||||||
COMPRESS_DATA = b'compress xxxxxxxxxxxxxxxxxxxxxx data'
|
COMPRESS_DATA = b'compress xxxxxxxxxxxxxxxxxxxxxx data'
|
||||||
REFCODE_DATA = b'refcode'
|
REFCODE_DATA = b'refcode'
|
||||||
|
|
||||||
|
EXTRACT_DTB_SIZE = 0x3c9
|
||||||
|
|
||||||
|
|
||||||
class TestFunctional(unittest.TestCase):
|
class TestFunctional(unittest.TestCase):
|
||||||
"""Functional tests for binman
|
"""Functional tests for binman
|
||||||
|
@ -2423,6 +2425,46 @@ class TestFunctional(unittest.TestCase):
|
||||||
"""Test listing the files in a sub-entry of a section"""
|
"""Test listing the files in a sub-entry of a section"""
|
||||||
self._RunListCmd(['section/cbfs'], ['cbfs', 'u-boot', 'u-boot-dtb'])
|
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__":
|
if __name__ == "__main__":
|
||||||
unittest.main()
|
unittest.main()
|
||||||
|
|
|
@ -82,7 +82,9 @@ class Image(section.Entry_section):
|
||||||
dtb.Scan()
|
dtb.Scan()
|
||||||
|
|
||||||
# Return an Image with the associated nodes
|
# 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):
|
def Raise(self, msg):
|
||||||
"""Convenience function to raise an error referencing an image"""
|
"""Convenience function to raise an error referencing an image"""
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue