mirror of
https://xff.cz/git/u-boot/
synced 2025-09-02 09:12:08 +02:00
binman: Add support for outputing a map file
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 <sjg@chromium.org>
This commit is contained in:
@@ -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.
|
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
|
Code coverage
|
||||||
-------------
|
-------------
|
||||||
|
|
||||||
@@ -628,7 +647,6 @@ Some ideas:
|
|||||||
'Access to binman entry positions at run time' above
|
'Access to binman entry positions at run time' above
|
||||||
- Use of-platdata to make the information available to code that is unable
|
- Use of-platdata to make the information available to code that is unable
|
||||||
to use device tree (such as a very small SPL image)
|
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
|
- Allow easy building of images by specifying just the board name
|
||||||
- Produce a full Python binding for libfdt (for upstream)
|
- Produce a full Python binding for libfdt (for upstream)
|
||||||
- Add an option to decode an image into the constituent binaries
|
- Add an option to decode an image into the constituent binaries
|
||||||
|
@@ -301,3 +301,12 @@ class Section(object):
|
|||||||
|
|
||||||
def GetEntries(self):
|
def GetEntries(self):
|
||||||
return self._entries
|
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)
|
||||||
|
@@ -30,6 +30,8 @@ def ParseArgs(argv):
|
|||||||
help='Add a path to a directory to use for input files')
|
help='Add a path to a directory to use for input files')
|
||||||
parser.add_option('-H', '--full-help', action='store_true',
|
parser.add_option('-H', '--full-help', action='store_true',
|
||||||
default=False, help='Display the README file')
|
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',
|
parser.add_option('-O', '--outdir', type='string',
|
||||||
action='store', help='Path to directory to use for intermediate and '
|
action='store', help='Path to directory to use for intermediate and '
|
||||||
'output files')
|
'output files')
|
||||||
|
@@ -112,6 +112,8 @@ def Binman(options, args):
|
|||||||
image.ProcessEntryContents()
|
image.ProcessEntryContents()
|
||||||
image.WriteSymbols()
|
image.WriteSymbols()
|
||||||
image.BuildImage()
|
image.BuildImage()
|
||||||
|
if options.map:
|
||||||
|
image.WriteMap()
|
||||||
finally:
|
finally:
|
||||||
tools.FinaliseOutputDir()
|
tools.FinaliseOutputDir()
|
||||||
finally:
|
finally:
|
||||||
|
@@ -4,6 +4,8 @@
|
|||||||
# Base class for all entries
|
# 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
|
# 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:
|
# working in 2.7.12, so we work around this:
|
||||||
# http://lists.denx.de/pipermail/u-boot/2016-October/269729.html
|
# http://lists.denx.de/pipermail/u-boot/2016-October/269729.html
|
||||||
@@ -50,6 +52,7 @@ class Entry(object):
|
|||||||
self.section = section
|
self.section = section
|
||||||
self.etype = etype
|
self.etype = etype
|
||||||
self._node = node
|
self._node = node
|
||||||
|
self.name = node and node.name or 'none'
|
||||||
self.pos = None
|
self.pos = None
|
||||||
self.size = None
|
self.size = None
|
||||||
self.contents_size = 0
|
self.contents_size = 0
|
||||||
@@ -229,3 +232,13 @@ class Entry(object):
|
|||||||
this function and raise if there is a problem.
|
this function and raise if there is a problem.
|
||||||
"""
|
"""
|
||||||
pass
|
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)
|
||||||
|
@@ -48,3 +48,12 @@ class Entry_section(Entry):
|
|||||||
|
|
||||||
def CheckPosition(self):
|
def CheckPosition(self):
|
||||||
self._section.CheckEntries()
|
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)
|
||||||
|
@@ -146,16 +146,19 @@ class TestFunctional(unittest.TestCase):
|
|||||||
# options.verbosity = tout.DEBUG
|
# options.verbosity = tout.DEBUG
|
||||||
return control.Binman(options, args)
|
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
|
"""Run binman with a given test file
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
fname: Device-tree source filename to use (e.g. 05_simple.dts)
|
fname: Device-tree source filename to use (e.g. 05_simple.dts)
|
||||||
debug: True to enable debugging output
|
debug: True to enable debugging output
|
||||||
|
map: True to output map files for the images
|
||||||
"""
|
"""
|
||||||
args = ['-p', '-I', self._indir, '-d', self.TestFile(fname)]
|
args = ['-p', '-I', self._indir, '-d', self.TestFile(fname)]
|
||||||
if debug:
|
if debug:
|
||||||
args.append('-D')
|
args.append('-D')
|
||||||
|
if map:
|
||||||
|
args.append('-m')
|
||||||
return self._DoBinman(*args)
|
return self._DoBinman(*args)
|
||||||
|
|
||||||
def _SetupDtb(self, fname, outfile='u-boot.dtb'):
|
def _SetupDtb(self, fname, outfile='u-boot.dtb'):
|
||||||
@@ -180,7 +183,7 @@ class TestFunctional(unittest.TestCase):
|
|||||||
TestFunctional._MakeInputFile(outfile, data)
|
TestFunctional._MakeInputFile(outfile, data)
|
||||||
return 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
|
"""Run binman and return the resulting image
|
||||||
|
|
||||||
This runs binman with a given test file and then reads the resulting
|
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
|
the u-boot-dtb entry. Normally this is not needed and the
|
||||||
test contents (the U_BOOT_DTB_DATA string) can be used.
|
test contents (the U_BOOT_DTB_DATA string) can be used.
|
||||||
But in some test we need the real contents.
|
But in some test we need the real contents.
|
||||||
|
map: True to output map files for the images
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
Tuple:
|
Tuple:
|
||||||
Resulting image contents
|
Resulting image contents
|
||||||
Device tree contents
|
Device tree contents
|
||||||
|
Map data showing contents of image (or None if none)
|
||||||
"""
|
"""
|
||||||
dtb_data = None
|
dtb_data = None
|
||||||
# Use the compiled test file as the u-boot-dtb input
|
# Use the compiled test file as the u-boot-dtb input
|
||||||
@@ -207,15 +212,21 @@ class TestFunctional(unittest.TestCase):
|
|||||||
dtb_data = self._SetupDtb(fname)
|
dtb_data = self._SetupDtb(fname)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
retcode = self._DoTestFile(fname)
|
retcode = self._DoTestFile(fname, map=map)
|
||||||
self.assertEqual(0, retcode)
|
self.assertEqual(0, retcode)
|
||||||
|
|
||||||
# Find the (only) image, read it and return its contents
|
# Find the (only) image, read it and return its contents
|
||||||
image = control.images['image']
|
image = control.images['image']
|
||||||
fname = tools.GetOutputFilename('image.bin')
|
fname = tools.GetOutputFilename('image.bin')
|
||||||
self.assertTrue(os.path.exists(fname))
|
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:
|
with open(fname) as fd:
|
||||||
return fd.read(), dtb_data
|
return fd.read(), dtb_data, map_data
|
||||||
finally:
|
finally:
|
||||||
# Put the test file back
|
# Put the test file back
|
||||||
if use_real_dtb:
|
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)"""
|
"""Test that we can cope with an image without microcode (e.g. qemu)"""
|
||||||
with open(self.TestFile('u_boot_no_ucode_ptr')) as fd:
|
with open(self.TestFile('u_boot_no_ucode_ptr')) as fd:
|
||||||
TestFunctional._MakeInputFile('u-boot', fd.read())
|
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
|
# Now check the device tree has no microcode
|
||||||
self.assertEqual(U_BOOT_NODTB_DATA, data[:len(U_BOOT_NODTB_DATA)])
|
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
|
expected = U_BOOT_DATA + '!' * 12 + U_BOOT_DATA + 'a' * 12 + '&' * 8
|
||||||
self.assertEqual(expected, data)
|
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__":
|
if __name__ == "__main__":
|
||||||
unittest.main()
|
unittest.main()
|
||||||
|
@@ -98,3 +98,11 @@ class Image:
|
|||||||
|
|
||||||
def GetEntries(self):
|
def GetEntries(self):
|
||||||
return self._section.GetEntries()
|
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)
|
||||||
|
Reference in New Issue
Block a user