summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--tools/binman/README5
-rw-r--r--tools/binman/README.entries38
-rw-r--r--tools/binman/etype/fdtmap.py109
-rw-r--r--tools/binman/ftest.py52
-rw-r--r--tools/binman/state.py2
-rw-r--r--tools/binman/test/115_fdtmap.dts13
6 files changed, 211 insertions, 8 deletions
diff --git a/tools/binman/README b/tools/binman/README
index b067d3b78c..8a5f3320dc 100644
--- a/tools/binman/README
+++ b/tools/binman/README
@@ -638,6 +638,10 @@ the image definition, binman calculates the final values and writes these to
the device tree. These can be used by U-Boot at run-time to find the location
of each entry.
+Alternatively, an FDT map entry can be used to add a special FDT containing
+just the information about the image. This is preceded by a magic string so can
+be located anywhere in the image.
+
Compression
-----------
@@ -814,7 +818,6 @@ Some ideas:
- Support building an image for a board (-b) more completely, with a
configurable build directory
- Support putting the FDT in an image with a suitable magic number
-- Support adding a pointer to the FDT map
- Support listing files in images
- Support logging of binman's operations, with different levels of verbosity
- Support updating binaries in an image (with no size change / repacking)
diff --git a/tools/binman/README.entries b/tools/binman/README.entries
index 3241befc7f..7014d36f5f 100644
--- a/tools/binman/README.entries
+++ b/tools/binman/README.entries
@@ -223,6 +223,44 @@ updating the EC on startup via software sync.
+Entry: fdtmap: An entry which contains an FDT map
+-------------------------------------------------
+
+Properties / Entry arguments:
+ None
+
+An FDT map is just a header followed by an FDT containing a list of all the
+entries in the image.
+
+The header is the string _FDTMAP_ followed by 8 unused bytes.
+
+When used, this entry will be populated with an FDT map which reflects the
+entries in the current image. Hierarchy is preserved, and all offsets and
+sizes are included.
+
+Note that the -u option must be provided to ensure that binman updates the
+FDT with the position of each entry.
+
+Example output for a simple image with U-Boot and an FDT map:
+
+/ {
+ size = <0x00000112>;
+ image-pos = <0x00000000>;
+ offset = <0x00000000>;
+ u-boot {
+ size = <0x00000004>;
+ image-pos = <0x00000000>;
+ offset = <0x00000000>;
+ };
+ fdtmap {
+ size = <0x0000010e>;
+ image-pos = <0x00000004>;
+ offset = <0x00000004>;
+ };
+};
+
+
+
Entry: files: Entry containing a set of files
---------------------------------------------
diff --git a/tools/binman/etype/fdtmap.py b/tools/binman/etype/fdtmap.py
new file mode 100644
index 0000000000..cdeb491ebd
--- /dev/null
+++ b/tools/binman/etype/fdtmap.py
@@ -0,0 +1,109 @@
+# SPDX-License-Identifier: GPL-2.0+
+# Copyright (c) 2018 Google, Inc
+# Written by Simon Glass <sjg@chromium.org>
+
+"""# Entry-type module for a full map of the firmware image
+
+This handles putting an FDT into the image with just the information about the
+image.
+"""
+
+import libfdt
+
+from entry import Entry
+from fdt import Fdt
+import state
+import tools
+
+FDTMAP_MAGIC = b'_FDTMAP_'
+
+class Entry_fdtmap(Entry):
+ """An entry which contains an FDT map
+
+ Properties / Entry arguments:
+ None
+
+ An FDT map is just a header followed by an FDT containing a list of all the
+ entries in the image.
+
+ The header is the string _FDTMAP_ followed by 8 unused bytes.
+
+ When used, this entry will be populated with an FDT map which reflects the
+ entries in the current image. Hierarchy is preserved, and all offsets and
+ sizes are included.
+
+ Note that the -u option must be provided to ensure that binman updates the
+ FDT with the position of each entry.
+
+ Example output for a simple image with U-Boot and an FDT map:
+
+ / {
+ size = <0x00000112>;
+ image-pos = <0x00000000>;
+ offset = <0x00000000>;
+ u-boot {
+ size = <0x00000004>;
+ image-pos = <0x00000000>;
+ offset = <0x00000000>;
+ };
+ fdtmap {
+ size = <0x0000010e>;
+ image-pos = <0x00000004>;
+ offset = <0x00000004>;
+ };
+ };
+ """
+ def __init__(self, section, etype, node):
+ Entry.__init__(self, section, etype, node)
+
+ def _GetFdtmap(self):
+ """Build an FDT map from the entries in the current image
+
+ Returns:
+ FDT map binary data
+ """
+ def _AddNode(node):
+ """Add a node to the FDT map"""
+ for pname, prop in node.props.items():
+ fsw.property(pname, prop.bytes)
+ for subnode in node.subnodes:
+ with fsw.add_node(subnode.name):
+ _AddNode(subnode)
+
+ # Get the FDT data into an Fdt object
+ data = state.GetFdtContents()[1]
+ infdt = Fdt.FromData(data)
+ infdt.Scan()
+
+ # Find the node for the image containing the Fdt-map entry
+ path = self.section.GetPath()
+ node = infdt.GetNode(path)
+ if not node:
+ self.Raise("Internal error: Cannot locate node for path '%s'" %
+ path)
+
+ # Build a new tree with all nodes and properties starting from that node
+ fsw = libfdt.FdtSw()
+ fsw.finish_reservemap()
+ with fsw.add_node(''):
+ _AddNode(node)
+ fdt = fsw.as_fdt()
+
+ # Pack this new FDT and return its contents
+ fdt.pack()
+ outfdt = Fdt.FromData(fdt.as_bytearray())
+ data = FDTMAP_MAGIC + tools.GetBytes(0, 8) + outfdt.GetContents()
+ return data
+
+ def ObtainContents(self):
+ """Obtain a placeholder for the fdt-map contents"""
+ self.SetContents(self._GetFdtmap())
+ return True
+
+ def ProcessContents(self):
+ """Write an updated version of the FDT map to this entry
+
+ This is necessary since new data may have been written back to it during
+ processing, e.g. the image-pos properties.
+ """
+ self.SetContents(self._GetFdtmap())
diff --git a/tools/binman/ftest.py b/tools/binman/ftest.py
index ed125670e2..934145ca3c 100644
--- a/tools/binman/ftest.py
+++ b/tools/binman/ftest.py
@@ -487,16 +487,16 @@ class TestFunctional(unittest.TestCase):
"""
return struct.unpack('>L', dtb[4:8])[0]
- def _GetPropTree(self, dtb, prop_names):
+ def _GetPropTree(self, dtb, prop_names, prefix='/binman/'):
def AddNode(node, path):
if node.name != '/':
path += '/' + node.name
+ for prop in node.props.values():
+ if prop.name in prop_names:
+ prop_path = path + ':' + prop.name
+ tree[prop_path[len(prefix):]] = fdt_util.fdt32_to_cpu(
+ prop.value)
for subnode in node.subnodes:
- for prop in subnode.props.values():
- if prop.name in prop_names:
- prop_path = path + '/' + subnode.name + ':' + prop.name
- tree[prop_path[len('/binman/'):]] = fdt_util.fdt32_to_cpu(
- prop.value)
AddNode(subnode, path)
tree = {}
@@ -2044,6 +2044,46 @@ class TestFunctional(unittest.TestCase):
self.assertEqual(U_BOOT_DTB_DATA, cfile2.data)
self.assertEqual(0x140, cfile2.cbfs_offset)
+ def testFdtmap(self):
+ """Test an FDT map can be inserted in the image"""
+ data = self.data = self._DoReadFileRealDtb('115_fdtmap.dts')
+ fdtmap_data = data[len(U_BOOT_DATA):]
+ magic = fdtmap_data[:8]
+ self.assertEqual('_FDTMAP_', magic)
+ self.assertEqual(tools.GetBytes(0, 8), fdtmap_data[8:16])
+
+ fdt_data = fdtmap_data[16:]
+ dtb = fdt.Fdt.FromData(fdt_data)
+ dtb.Scan()
+ props = self._GetPropTree(dtb, ['offset', 'size', 'image-pos'],
+ prefix='/')
+ self.assertEqual({
+ 'image-pos': 0,
+ 'offset': 0,
+ 'u-boot:offset': 0,
+ 'u-boot:size': len(U_BOOT_DATA),
+ 'u-boot:image-pos': 0,
+ 'fdtmap:image-pos': 4,
+ 'fdtmap:offset': 4,
+ 'fdtmap:size': len(fdtmap_data),
+ 'size': len(data),
+ }, props)
+
+ def testFdtmapNoMatch(self):
+ """Check handling of an FDT map when the section cannot be found"""
+ self.data = self._DoReadFileRealDtb('115_fdtmap.dts')
+
+ # Mangle the section name, which should cause a mismatch between the
+ # correct FDT path and the one expected by the section
+ image = control.images['image']
+ image._section._node.path += '-suffix'
+ entries = image.GetEntries()
+ fdtmap = entries['fdtmap']
+ with self.assertRaises(ValueError) as e:
+ fdtmap._GetFdtmap()
+ self.assertIn("Cannot locate node for path '/binman-suffix'",
+ str(e.exception))
+
if __name__ == "__main__":
unittest.main()
diff --git a/tools/binman/state.py b/tools/binman/state.py
index af9678649c..3ccd7855d4 100644
--- a/tools/binman/state.py
+++ b/tools/binman/state.py
@@ -59,7 +59,7 @@ def GetFdtPath(fname):
"""
return fdt_files[fname]._fname
-def GetFdtContents(fname):
+def GetFdtContents(fname='u-boot.dtb'):
"""Looks up the FDT pathname and contents
This is used to obtain the Fdt pathname and contents when needed by an
diff --git a/tools/binman/test/115_fdtmap.dts b/tools/binman/test/115_fdtmap.dts
new file mode 100644
index 0000000000..2450c41f20
--- /dev/null
+++ b/tools/binman/test/115_fdtmap.dts
@@ -0,0 +1,13 @@
+/dts-v1/;
+
+/ {
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ binman {
+ u-boot {
+ };
+ fdtmap {
+ };
+ };
+};