
Add support for listing the entries in an image. This relies on the image having an FDT map.
Signed-off-by: Simon Glass sjg@chromium.org ---
tools/binman/README | 25 +++++++++++++- tools/binman/control.py | 73 +++++++++++++++++++++++++++++++++++++++++ tools/binman/ftest.py | 31 +++++++++++++++++ 3 files changed, 128 insertions(+), 1 deletion(-)
diff --git a/tools/binman/README b/tools/binman/README index 7e745a2d466..2f3ded58c91 100644 --- a/tools/binman/README +++ b/tools/binman/README @@ -490,6 +490,30 @@ see README.entries. This is generated from the source code using: binman entry-docs >tools/binman/README.entries
+Listing images +-------------- + +It is possible to list the entries in an existing firmware image created by +binman. For example: + + $ binman list image.bin + Name Image-pos Size Entry-type Offset Uncomp-size + ---------------------------------------------------------------------- + main-section c00 section 0 + u-boot 0 4 u-boot 0 + section 5ff section 4 + cbfs 100 400 cbfs 0 + u-boot 138 4 u-boot 38 + u-boot-dtb 180 108 u-boot-dtb 80 3b5 + u-boot-dtb 500 1ff u-boot-dtb 400 3b5 + fdtmap 6ff 381 fdtmap 6ff + image-header bf8 8 image-header bf8 + +This shows the hierarchy of the image, the position, size and type of each +entry, the offset of each entry within its parent and the uncompressed size if +the entry is compressed. + + Hashing Entries ---------------
@@ -825,7 +849,6 @@ Some ideas: - Add an option to decode an image into the constituent binaries - Support building an image for a board (-b) more completely, with a configurable build directory -- Support listing files in images - Support logging of binman's operations, with different levels of verbosity
-- diff --git a/tools/binman/control.py b/tools/binman/control.py index d48e7ac0070..3ac3f0c3e71 100644 --- a/tools/binman/control.py +++ b/tools/binman/control.py @@ -67,6 +67,75 @@ def WriteEntryDocs(modules, test_missing=None): from entry import Entry Entry.WriteDocs(modules, test_missing)
+def EntryToStrings(entry): + """Convert an entry to a list of strings, one for each column + + Args: + entry: EntryInfo object containing information to output + + Returns: + List of strings, one for each field in entry + """ + def _AppendHex(val): + """Append a hex value, or an empty string if val is None + + Args: + val: Integer value, or None if none + """ + args.append('' if val is None else '>%x' % val) + + args = [' ' * entry.indent + entry.name] + _AppendHex(entry.image_pos) + _AppendHex(entry.size) + args.append(entry.etype) + _AppendHex(entry.offset) + _AppendHex(entry.uncomp_size) + return args + +def ListEntries(fname): + """List the entries in an image + + This decodes the supplied image and displays a table of entries from that + image, preceded by a header. + + Args: + fname: Filename to process + """ + def _DoLine(line): + out = [] + for i, item in enumerate(line): + lengths[i] = max(lengths[i], len(item)) + out.append(item) + return out + + image = Image.FromFile(fname) + + # Check for error + if isinstance(image, str): + print("Unable to read image '%s' (%s)" % (fname, image)) + return + entries = image.ListEntries() + + num_columns = 6 + lines = [] + lengths = [0] * num_columns + lines.append(_DoLine(['Name', 'Image-pos', 'Size', 'Entry-type', + 'Offset', 'Uncomp-size'])) + for entry in entries: + lines.append(_DoLine(EntryToStrings(entry))) + for linenum, line in enumerate(lines): + if linenum == 1: + print('-' * (sum(lengths) + num_columns * 2)) + out = '' + for i, item in enumerate(line): + width = -lengths[i] + if item.startswith('>'): + width = -width + item = item[1:] + txt = '%*s ' % (width, item) + out += txt + print(out.rstrip()) + def Binman(args): """The main control code for binman
@@ -87,6 +156,10 @@ def Binman(args): command.Run(pager, fname) return 0
+ if args.cmd == 'list': + ListEntries(args.fname) + return 0 + # Try to figure out which device tree contains our image description if args.dt: dtb_fname = args.dt diff --git a/tools/binman/ftest.py b/tools/binman/ftest.py index 88c3d847f82..f5353911705 100644 --- a/tools/binman/ftest.py +++ b/tools/binman/ftest.py @@ -2336,5 +2336,36 @@ class TestFunctional(unittest.TestCase): self.assertTrue(isinstance(image, str)) self.assertEqual('Cannot find FDT map in image', image)
+ def testListCmd(self): + """Test listing the files in an image using an Fdtmap""" + data = self._DoReadFileDtb('129_list_fdtmap.dts', use_real_dtb=True, + update_dtb=True)[0] + image_fname = tools.GetOutputFilename('image.bin') + with test_util.capture_sys_output() as (stdout, stderr): + self._DoBinman('list', image_fname) + lines = stdout.getvalue().splitlines() + expected = [ + 'Name Image-pos Size Entry-type Offset Uncomp-size', +'----------------------------------------------------------------------', +'main-section c00 section 0', +' u-boot 0 4 u-boot 0', +' section 5ff section 4', +' cbfs 100 400 cbfs 0', +' u-boot 138 4 u-boot 38', +' u-boot-dtb 180 108 u-boot-dtb 80 3b5', +' u-boot-dtb 500 1ff u-boot-dtb 400 3b5', +' fdtmap 6ff 381 fdtmap 6ff', +' image-header bf8 8 image-header bf8', + ] + self.assertEqual(expected, lines) + + def testListCmdFail(self): + """Test failing to list an image""" + self._DoReadFile('005_simple.dts') + image_fname = tools.GetOutputFilename('image.bin') + with test_util.capture_sys_output() as (stdout, stderr): + self._DoBinman('list', image_fname) + + if __name__ == "__main__": unittest.main()