From patchwork Wed May 16 01:52:56 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Simon Glass X-Patchwork-Id: 914122 X-Patchwork-Delegate: sjg@chromium.org Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=lists.denx.de (client-ip=81.169.180.215; helo=lists.denx.de; envelope-from=u-boot-bounces@lists.denx.de; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=chromium.org Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=google.com header.i=@google.com header.b="P+0IUKAM"; dkim-atps=neutral Received: from lists.denx.de (dione.denx.de [81.169.180.215]) by ozlabs.org (Postfix) with ESMTP id 40lyKZ3Qlxz9ryk for ; Wed, 16 May 2018 11:59:14 +1000 (AEST) Received: by lists.denx.de (Postfix, from userid 105) id 23339C21D72; Wed, 16 May 2018 01:57:10 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on lists.denx.de X-Spam-Level: X-Spam-Status: No, score=-0.0 required=5.0 tests=RCVD_IN_DNSWL_BLOCKED, RCVD_IN_MSPIKE_H3, RCVD_IN_MSPIKE_WL, T_DKIM_INVALID autolearn=unavailable autolearn_force=no version=3.4.0 Received: from lists.denx.de (localhost [IPv6:::1]) by lists.denx.de (Postfix) with ESMTP id EAEDFC21E3E; Wed, 16 May 2018 01:53:29 +0000 (UTC) Received: by lists.denx.de (Postfix, from userid 105) id 3A15BC21DE8; Wed, 16 May 2018 01:53:21 +0000 (UTC) Received: from mail-it0-f67.google.com (mail-it0-f67.google.com [209.85.214.67]) by lists.denx.de (Postfix) with ESMTPS id 53752C21DD4 for ; Wed, 16 May 2018 01:53:16 +0000 (UTC) Received: by mail-it0-f67.google.com with SMTP id e20-v6so7104384itc.1 for ; Tue, 15 May 2018 18:53:16 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20161025; h=sender:from:to:cc:subject:date:message-id:in-reply-to:references; bh=ZBwaYSom0SiXAjZX7r0PV2sC7mNEe0kGqNoXJBoPCjs=; b=P+0IUKAMoKOuNLzwmc7TrKfmJolKa+fccPb02USzWyD7j254SSPpgY6wdjuClPyrAw 72FhmHLbxjAd0XYRBriFrsig0QVRZ4EsnLsC0SQTmmqdlK/rblw2VrKc/p5StuM2O0E9 R/ivhxd4ZrLmDaLxXuNVg6l0dC28kI9AGs4Fcno6Hli9eF3e8qHWCU2ylTEzAzJvXMp9 gkPifDYtj6uMJjb40nSY2e9JJMipFV2MF7R4D+xi1S44k14LIp9Fcd9zsR2JXIuDLHh+ +gQ053yfn1pDmHFBm17bSv3HU0TK79PeHqoXQp/472qi8yIwESn4H9M0GaTBf5mlyNBO OvGQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:sender:from:to:cc:subject:date:message-id :in-reply-to:references; bh=ZBwaYSom0SiXAjZX7r0PV2sC7mNEe0kGqNoXJBoPCjs=; b=V5SC1bn4MDwucDqYHzmS3N0aMMSXKh5EDrDQRrXqaxBa99OvJi/plSyK2rOLS8yfpV XYN9tnnscTK2TGtjiV7yVSc6xzpTJuBwmU80Rt+D4wfu3yY9Z9Z+aKEi263icd7bVNsM ijKP0g3Eu465AKxX/xEDJNWWxmMoPuWHl/OZnQ7zf3Cmbov/+SM1A5U1f1+HJ/HIyOgn nuVyLA6Xk7meq7+T3Km5YiO6vWRib+UwJAuDu/vhcs2YKi0GJPWmK/RgA4R2QKgawUf/ qxjq92mk2kmWZCTBhVcrrFUPfiRusVXjYnouySrCYvkdTvf0xZvtSf2FHsPmBZU+KpBG K2RA== X-Gm-Message-State: ALKqPweOqGFDytthsDbhwpA6yBCPKfR+y6pmJRgmPTZ0FA5VAdsgWG9S tlPKmTOgh4hhn/BtoipQHm6jrw== X-Google-Smtp-Source: AB8JxZrMXfYSl31T2hjqrHR+/yj4L/mW1oN7MZKxuCruwt320fHCTqJagP/HR/zEka/dR4RpN85VWw== X-Received: by 2002:a24:6710:: with SMTP id u16-v6mr452198itc.110.1526435594716; Tue, 15 May 2018 18:53:14 -0700 (PDT) Received: from kiwi.bld.corp.google.com ([100.67.80.24]) by smtp.gmail.com with ESMTPSA id c18-v6sm1425782ioa.16.2018.05.15.18.53.13 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Tue, 15 May 2018 18:53:13 -0700 (PDT) Received: by kiwi.bld.corp.google.com (Postfix, from userid 121222) id 542FA140C6B; Tue, 15 May 2018 19:53:13 -0600 (MDT) From: Simon Glass To: U-Boot Mailing List Date: Tue, 15 May 2018 19:52:56 -0600 Message-Id: <20180516015258.187295-11-sjg@chromium.org> X-Mailer: git-send-email 2.17.0.441.gb46fe60e1d-goog In-Reply-To: <20180516015258.187295-1-sjg@chromium.org> References: <20180516015258.187295-1-sjg@chromium.org> Cc: Tom Rini Subject: [U-Boot] [PATCH 10/12] binman: Add support for outputing a map file X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.18 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" It is useful to be able to see a list of regions in each image produced by binman. Add a -m option to output this information in a '.map' file alongside the image file. Signed-off-by: Simon Glass --- tools/binman/README | 20 +++++++++++++++++++- tools/binman/bsection.py | 9 +++++++++ tools/binman/cmdline.py | 2 ++ tools/binman/control.py | 2 ++ tools/binman/entry.py | 13 +++++++++++++ tools/binman/etype/section.py | 9 +++++++++ tools/binman/ftest.py | 31 ++++++++++++++++++++++++++----- tools/binman/image.py | 8 ++++++++ 8 files changed, 88 insertions(+), 6 deletions(-) diff --git a/tools/binman/README b/tools/binman/README index f3a979e2179..64e529f06b9 100644 --- a/tools/binman/README +++ b/tools/binman/README @@ -548,6 +548,25 @@ At present this feature is only supported in SPL. In principle it is possible to fill in such symbols in U-Boot proper, as well. +Map files +--------- + +The -m option causes binman to output a .map file for each image that it +generates. This shows the position and size of each entry. For example: + + Position Size Name + 00000000 00000010 section@0 + 00000000 00000004 u-boot + 00000010 00000010 section@1 + 00000000 00000004 u-boot + +This shows a hierarchical image with two sections, each with a single entry. The +positions of the sections are absolute hex byte offsets within the image. The +positions of the entries are relative to their respective sections. The size of +each entry is also shown, in bytes (hex). The indentation shows the entries +nested inside their sections. + + Code coverage ------------- @@ -628,7 +647,6 @@ Some ideas: 'Access to binman entry positions at run time' above - Use of-platdata to make the information available to code that is unable to use device tree (such as a very small SPL image) -- Write an image map to a text file - Allow easy building of images by specifying just the board name - Produce a full Python binding for libfdt (for upstream) - Add an option to decode an image into the constituent binaries diff --git a/tools/binman/bsection.py b/tools/binman/bsection.py index 9333932d41e..2930718e11f 100644 --- a/tools/binman/bsection.py +++ b/tools/binman/bsection.py @@ -301,3 +301,12 @@ class Section(object): def GetEntries(self): return self._entries + + def WriteMap(self, fd, indent): + """Write a map of the section to a .map file + + Args: + fd: File to write the map to + """ + for entry in self._entries.values(): + entry.WriteMap(fd, indent) diff --git a/tools/binman/cmdline.py b/tools/binman/cmdline.py index e9e0434ab36..bf63919eb79 100644 --- a/tools/binman/cmdline.py +++ b/tools/binman/cmdline.py @@ -30,6 +30,8 @@ def ParseArgs(argv): help='Add a path to a directory to use for input files') parser.add_option('-H', '--full-help', action='store_true', default=False, help='Display the README file') + parser.add_option('-m', '--map', action='store_true', + default=False, help='Output a map file for each image') parser.add_option('-O', '--outdir', type='string', action='store', help='Path to directory to use for intermediate and ' 'output files') diff --git a/tools/binman/control.py b/tools/binman/control.py index bc8ed8e37ae..92434729061 100644 --- a/tools/binman/control.py +++ b/tools/binman/control.py @@ -112,6 +112,8 @@ def Binman(options, args): image.ProcessEntryContents() image.WriteSymbols() image.BuildImage() + if options.map: + image.WriteMap() finally: tools.FinaliseOutputDir() finally: diff --git a/tools/binman/entry.py b/tools/binman/entry.py index 8b46fbb5fa6..3811d33e420 100644 --- a/tools/binman/entry.py +++ b/tools/binman/entry.py @@ -4,6 +4,8 @@ # Base class for all entries # +from __future__ import print_function + # importlib was introduced in Python 2.7 but there was a report of it not # working in 2.7.12, so we work around this: # http://lists.denx.de/pipermail/u-boot/2016-October/269729.html @@ -50,6 +52,7 @@ class Entry(object): self.section = section self.etype = etype self._node = node + self.name = node and node.name or 'none' self.pos = None self.size = None self.contents_size = 0 @@ -229,3 +232,13 @@ class Entry(object): this function and raise if there is a problem. """ pass + + def WriteMap(self, fd, indent): + """Write a map of the entry to a .map file + + Args: + fd: File to write the map to + indent: Curent indent level of map (0=none, 1=one level, etc.) + """ + print('%s%08x %08x %s' % (' ' * indent, self.pos, self.size, + self.name), file=fd) diff --git a/tools/binman/etype/section.py b/tools/binman/etype/section.py index 7437f91567d..061bdada103 100644 --- a/tools/binman/etype/section.py +++ b/tools/binman/etype/section.py @@ -49,3 +49,12 @@ class Entry_section(Entry): def CheckPosition(self): self._section.CheckEntries() + + def WriteMap(self, fd, indent): + """Write a map of the section to a .map file + + Args: + fd: File to write the map to + """ + super(Entry_section, self).WriteMap(fd, indent) + self._section.WriteMap(fd, indent + 1) diff --git a/tools/binman/ftest.py b/tools/binman/ftest.py index 9e12df5d79f..61bbb53f8c3 100644 --- a/tools/binman/ftest.py +++ b/tools/binman/ftest.py @@ -146,16 +146,19 @@ class TestFunctional(unittest.TestCase): # options.verbosity = tout.DEBUG return control.Binman(options, args) - def _DoTestFile(self, fname, debug=False): + def _DoTestFile(self, fname, debug=False, map=False): """Run binman with a given test file Args: fname: Device-tree source filename to use (e.g. 05_simple.dts) debug: True to enable debugging output + map: True to output map files for the images """ args = ['-p', '-I', self._indir, '-d', self.TestFile(fname)] if debug: args.append('-D') + if map: + args.append('-m') return self._DoBinman(*args) def _SetupDtb(self, fname, outfile='u-boot.dtb'): @@ -180,7 +183,7 @@ class TestFunctional(unittest.TestCase): TestFunctional._MakeInputFile(outfile, data) return data - def _DoReadFileDtb(self, fname, use_real_dtb=False): + def _DoReadFileDtb(self, fname, use_real_dtb=False, map=False): """Run binman and return the resulting image This runs binman with a given test file and then reads the resulting @@ -195,11 +198,13 @@ class TestFunctional(unittest.TestCase): the u-boot-dtb entry. Normally this is not needed and the test contents (the U_BOOT_DTB_DATA string) can be used. But in some test we need the real contents. + map: True to output map files for the images Returns: Tuple: Resulting image contents Device tree contents + Map data showing contents of image (or None if none) """ dtb_data = None # Use the compiled test file as the u-boot-dtb input @@ -207,15 +212,21 @@ class TestFunctional(unittest.TestCase): dtb_data = self._SetupDtb(fname) try: - retcode = self._DoTestFile(fname) + retcode = self._DoTestFile(fname, map=map) self.assertEqual(0, retcode) # Find the (only) image, read it and return its contents image = control.images['image'] fname = tools.GetOutputFilename('image.bin') self.assertTrue(os.path.exists(fname)) + if map: + map_fname = tools.GetOutputFilename('image.map') + with open(map_fname) as fd: + map_data = fd.read() + else: + map_data = None with open(fname) as fd: - return fd.read(), dtb_data + return fd.read(), dtb_data, map_data finally: # Put the test file back if use_real_dtb: @@ -815,7 +826,7 @@ class TestFunctional(unittest.TestCase): """Test that we can cope with an image without microcode (e.g. qemu)""" with open(self.TestFile('u_boot_no_ucode_ptr')) as fd: TestFunctional._MakeInputFile('u-boot', fd.read()) - data, dtb = self._DoReadFileDtb('44_x86_optional_ucode.dts', True) + data, dtb, _ = self._DoReadFileDtb('44_x86_optional_ucode.dts', True) # Now check the device tree has no microcode self.assertEqual(U_BOOT_NODTB_DATA, data[:len(U_BOOT_NODTB_DATA)]) @@ -929,5 +940,15 @@ class TestFunctional(unittest.TestCase): expected = U_BOOT_DATA + '!' * 12 + U_BOOT_DATA + 'a' * 12 + '&' * 8 self.assertEqual(expected, data) + def testMap(self): + """Tests outputting a map of the images""" + _, _, map_data = self._DoReadFileDtb('55_sections.dts', map=True) + self.assertEqual('''Position Size Name +00000000 00000010 section@0 + 00000000 00000004 u-boot +00000010 00000010 section@1 + 00000000 00000004 u-boot +''', map_data) + if __name__ == "__main__": unittest.main() diff --git a/tools/binman/image.py b/tools/binman/image.py index 74bc46fd30c..835b66c99f5 100644 --- a/tools/binman/image.py +++ b/tools/binman/image.py @@ -98,3 +98,11 @@ class Image: def GetEntries(self): return self._section.GetEntries() + + def WriteMap(self): + """Write a map of the image to a .map file""" + filename = '%s.map' % self._name + fname = tools.GetOutputFilename(filename) + with open(fname, 'w') as fd: + print('%8s %8s %s' % ('Position', 'Size', 'Name'), file=fd) + self._section.WriteMap(fd, 0)