[PATCH 03/11] binman: Add support for a collection of entries
Simon Glass
sjg at chromium.org
Sun Mar 21 06:24:31 CET 2021
The vblock entry type includes code to collect the data from a number of
other entries (not necessarily subentries) and concatenating it. This is
a useful feature for other entry types.
Make it a base class, so that vblock can use it, along with other entry
types.
Signed-off-by: Simon Glass <sjg at chromium.org>
---
tools/binman/entries.rst | 13 ++++++
tools/binman/entry.py | 5 +++
tools/binman/etype/collection.py | 61 ++++++++++++++++++++++++++++
tools/binman/etype/vblock.py | 26 ++++++------
tools/binman/ftest.py | 10 ++++-
tools/binman/test/198_collection.dts | 27 ++++++++++++
6 files changed, 128 insertions(+), 14 deletions(-)
create mode 100644 tools/binman/etype/collection.py
create mode 100644 tools/binman/test/198_collection.dts
diff --git a/tools/binman/entries.rst b/tools/binman/entries.rst
index 1a71413f940..d5f8d95dc19 100644
--- a/tools/binman/entries.rst
+++ b/tools/binman/entries.rst
@@ -248,6 +248,19 @@ both of size 1MB.
+Entry: collection: An entry which contains a collection of other entries
+------------------------------------------------------------------------
+
+Properties / Entry arguments:
+ - content: List of phandles to entries to include
+
+This allows reusing the contents of other entries. The contents of the
+listed entries are combined to form this entry. This serves as a useful
+base class for entry types which need to process data from elsewhere in
+the image, not necessarily child entries.
+
+
+
Entry: cros-ec-rw: A blob entry which contains a Chromium OS read-write EC image
--------------------------------------------------------------------------------
diff --git a/tools/binman/entry.py b/tools/binman/entry.py
index ac25986ee6e..a157038d4e3 100644
--- a/tools/binman/entry.py
+++ b/tools/binman/entry.py
@@ -438,6 +438,11 @@ class Entry(object):
"""Convenience function to raise an error referencing a node"""
raise ValueError("Node '%s': %s" % (self._node.path, msg))
+ def Info(self, msg):
+ """Convenience function to log info referencing a node"""
+ tag = "Info '%s'" % self._node.path
+ tout.Detail('%30s: %s' % (tag, msg))
+
def Detail(self, msg):
"""Convenience function to log detail referencing a node"""
tag = "Node '%s'" % self._node.path
diff --git a/tools/binman/etype/collection.py b/tools/binman/etype/collection.py
new file mode 100644
index 00000000000..c0c552ac4f3
--- /dev/null
+++ b/tools/binman/etype/collection.py
@@ -0,0 +1,61 @@
+# SPDX-License-Identifier: GPL-2.0+
+# Copyright 2021 Google LLC
+# Written by Simon Glass <sjg at chromium.org>
+#
+
+# Support for a collection of entries from other parts of an image
+
+from collections import OrderedDict
+import os
+
+from binman.entry import Entry
+from dtoc import fdt_util
+
+class Entry_collection(Entry):
+ """An entry which contains a collection of other entries
+
+ Properties / Entry arguments:
+ - content: List of phandles to entries to include
+
+ This allows reusing the contents of other entries. The contents of the
+ listed entries are combined to form this entry. This serves as a useful
+ base class for entry types which need to process data from elsewhere in
+ the image, not necessarily child entries.
+ """
+ def __init__(self, section, etype, node):
+ super().__init__(section, etype, node)
+ self.content = fdt_util.GetPhandleList(self._node, 'content')
+ if not self.content:
+ self.Raise("Collection must have a 'content' property")
+
+ def GetContents(self):
+ """Get the contents of this entry
+
+ Returns:
+ bytes content of the entry
+ """
+ # Join up all the data
+ self.Info('Getting content')
+ data = b''
+ for entry_phandle in self.content:
+ entry_data = self.section.GetContentsByPhandle(entry_phandle, self)
+ if entry_data is None:
+ # Data not available yet
+ return None
+ data += entry_data
+
+ self.Info('Returning contents size %x' % len(data))
+
+ return data
+
+ def ObtainContents(self):
+ data = self.GetContents()
+ if data is None:
+ return False
+ self.SetContents(data)
+ return True
+
+ def ProcessContents(self):
+ # The blob may have changed due to WriteSymbols()
+ data = self.GetContents()
+ return self.ProcessContentsUpdate(data)
diff --git a/tools/binman/etype/vblock.py b/tools/binman/etype/vblock.py
index eba5351dd52..d473083cab8 100644
--- a/tools/binman/etype/vblock.py
+++ b/tools/binman/etype/vblock.py
@@ -9,12 +9,13 @@
from collections import OrderedDict
import os
-from binman.entry import Entry, EntryArg
+from binman.entry import EntryArg
+from binman.etype.collection import Entry_collection
from dtoc import fdt_util
from patman import tools
-class Entry_vblock(Entry):
+class Entry_vblock(Entry_collection):
"""An entry which contains a Chromium OS verified boot block
Properties / Entry arguments:
@@ -37,9 +38,6 @@ class Entry_vblock(Entry):
"""
def __init__(self, section, etype, node):
super().__init__(section, etype, node)
- self.content = fdt_util.GetPhandleList(self._node, 'content')
- if not self.content:
- self.Raise("Vblock must have a 'content' property")
(self.keydir, self.keyblock, self.signprivate, self.version,
self.kernelkey, self.preamble_flags) = self.GetEntryArgsOrProps([
EntryArg('keydir', str),
@@ -50,14 +48,16 @@ class Entry_vblock(Entry):
EntryArg('preamble-flags', int)])
def GetVblock(self):
+ """Get the contents of this entry
+
+ Returns:
+ bytes content of the entry, which is the signed vblock for the
+ provided data
+ """
# Join up the data files to be signed
- input_data = b''
- for entry_phandle in self.content:
- data = self.section.GetContentsByPhandle(entry_phandle, self)
- if data is None:
- # Data not available yet
- return False
- input_data += data
+ input_data = self.GetContents()
+ if input_data is None:
+ return None
uniq = self.GetUniqueName()
output_fname = tools.GetOutputFilename('vblock.%s' % uniq)
@@ -80,7 +80,7 @@ class Entry_vblock(Entry):
def ObtainContents(self):
data = self.GetVblock()
- if data is False:
+ if data is None:
return False
self.SetContents(data)
return True
diff --git a/tools/binman/ftest.py b/tools/binman/ftest.py
index cd93dc153a7..fdd4f4d2fad 100644
--- a/tools/binman/ftest.py
+++ b/tools/binman/ftest.py
@@ -1718,7 +1718,7 @@ class TestFunctional(unittest.TestCase):
"""Test we detect a vblock which has no content to sign"""
with self.assertRaises(ValueError) as e:
self._DoReadFile('075_vblock_no_content.dts')
- self.assertIn("Node '/binman/vblock': Vblock must have a 'content' "
+ self.assertIn("Node '/binman/vblock': Collection must have a 'content' "
'property', str(e.exception))
def testVblockBadPhandle(self):
@@ -4476,5 +4476,13 @@ class TestFunctional(unittest.TestCase):
U_BOOT_SPL_DTB_DATA, 0x38,
entry_args=entry_args, use_expanded=True)
+ def testCollection(self):
+ """Test a collection"""
+ data = self._DoReadFile('198_collection.dts')
+ self.assertEqual(U_BOOT_NODTB_DATA + U_BOOT_DTB_DATA +
+ tools.GetBytes(0xff, 2) + U_BOOT_NODTB_DATA +
+ tools.GetBytes(0xfe, 3) + U_BOOT_DTB_DATA,
+ data)
+
if __name__ == "__main__":
unittest.main()
diff --git a/tools/binman/test/198_collection.dts b/tools/binman/test/198_collection.dts
new file mode 100644
index 00000000000..484a1b0050d
--- /dev/null
+++ b/tools/binman/test/198_collection.dts
@@ -0,0 +1,27 @@
+// SPDX-License-Identifier: GPL-2.0+
+
+/dts-v1/;
+
+/ {
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ binman {
+ collection {
+ content = <&u_boot_nodtb &dtb>;
+ };
+ fill {
+ size = <2>;
+ fill-byte = [ff];
+ };
+ u_boot_nodtb: u-boot-nodtb {
+ };
+ fill2 {
+ type = "fill";
+ size = <3>;
+ fill-byte = [fe];
+ };
+ dtb: u-boot-dtb {
+ };
+ };
+};
--
2.31.0.rc2.261.g7f71774620-goog
More information about the U-Boot
mailing list