binman: Allow different operations in FIT generator nodes
At present we only support expanding out FDT nodes. Make the operation
into an @operation property, so that others can be supported.
Re-arrange and tidy up the documentation so that it has separate
headings for each topic.
Signed-off-by: Simon Glass <sjg@chromium.org>
diff --git a/tools/binman/entries.rst b/tools/binman/entries.rst
index 053e1d7..484cde5 100644
--- a/tools/binman/entries.rst
+++ b/tools/binman/entries.rst
@@ -553,6 +553,68 @@
};
};
+More complex setups can be created, with generated nodes, as described
+below.
+
+Properties (in the 'fit' node itself)
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Special properties have a `fit,` prefix, indicating that they should be
+processed but not included in the final FIT.
+
+The top-level 'fit' node supports the following special properties:
+
+ fit,external-offset
+ Indicates that the contents of the FIT are external and provides the
+ external offset. This is passed to mkimage via the -E and -p flags.
+
+ fit,fdt-list
+ Indicates the entry argument which provides the list of device tree
+ files for the gen-fdt-nodes operation (as below). This is often
+ `of-list` meaning that `-a of-list="dtb1 dtb2..."` should be passed
+ to binman.
+
+Substitutions
+~~~~~~~~~~~~~
+
+Node names and property values support a basic string-substitution feature.
+Available substitutions for '@' nodes (and property values) are:
+
+SEQ:
+ Sequence number of the generated fdt (1, 2, ...)
+NAME
+ Name of the dtb as provided (i.e. without adding '.dtb')
+
+The `default` property, if present, will be automatically set to the name
+if of configuration whose devicetree matches the `default-dt` entry
+argument, e.g. with `-a default-dt=sun50i-a64-pine64-lts`.
+
+Available substitutions for property values in these nodes are:
+
+DEFAULT-SEQ:
+ Sequence number of the default fdt, as provided by the 'default-dt'
+ entry argument
+
+Available operations
+~~~~~~~~~~~~~~~~~~~~
+
+You can add an operation to an '@' node to indicate which operation is
+required::
+
+ @fdt-SEQ {
+ fit,operation = "gen-fdt-nodes";
+ ...
+ };
+
+Available operations are:
+
+gen-fdt-nodes
+ Generate FDT nodes as above. This is the default if there is no
+ `fit,operation` property.
+
+Generating nodes from an FDT list (gen-fdt-nodes)
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
U-Boot supports creating fdt and config nodes automatically. To do this,
pass an `of-list` property (e.g. `-a of-list=file1 file2`). This tells
binman that you want to generates nodes for two files: `file1.dtb` and
@@ -590,32 +652,9 @@
This tells binman to create nodes `config-1` and `config-2`, i.e. a config
for each of your two files.
-Available substitutions for '@' nodes are:
-
-SEQ:
- Sequence number of the generated fdt (1, 2, ...)
-NAME
- Name of the dtb as provided (i.e. without adding '.dtb')
-
Note that if no devicetree files are provided (with '-a of-list' as above)
then no nodes will be generated.
-The 'default' property, if present, will be automatically set to the name
-if of configuration whose devicetree matches the 'default-dt' entry
-argument, e.g. with '-a default-dt=sun50i-a64-pine64-lts'.
-
-Available substitutions for '@' property values are
-
-DEFAULT-SEQ:
- Sequence number of the default fdt,as provided by the 'default-dt' entry
- argument
-
-Properties (in the 'fit' node itself):
- fit,external-offset: Indicates that the contents of the FIT are external
- and provides the external offset. This is passsed to mkimage via
- the -E and -p flags.
-
-
Entry: fmap: An entry which contains an Fmap section
diff --git a/tools/binman/etype/fit.py b/tools/binman/etype/fit.py
index d3e61c4..2d4c5f6 100644
--- a/tools/binman/etype/fit.py
+++ b/tools/binman/etype/fit.py
@@ -14,7 +14,14 @@
from dtoc.fdt import Fdt
from patman import tools
+# Supported operations, with the fit,operation property
+OP_GEN_FDT_NODES = range(1)
+OPERATIONS = {
+ 'gen-fdt-nodes': OP_GEN_FDT_NODES,
+ }
+
class Entry_fit(Entry_section):
+
"""Flat Image Tree (FIT)
This calls mkimage to create a FIT (U-Boot Flat Image Tree) based on the
@@ -47,6 +54,68 @@
};
};
+ More complex setups can be created, with generated nodes, as described
+ below.
+
+ Properties (in the 'fit' node itself)
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+ Special properties have a `fit,` prefix, indicating that they should be
+ processed but not included in the final FIT.
+
+ The top-level 'fit' node supports the following special properties:
+
+ fit,external-offset
+ Indicates that the contents of the FIT are external and provides the
+ external offset. This is passed to mkimage via the -E and -p flags.
+
+ fit,fdt-list
+ Indicates the entry argument which provides the list of device tree
+ files for the gen-fdt-nodes operation (as below). This is often
+ `of-list` meaning that `-a of-list="dtb1 dtb2..."` should be passed
+ to binman.
+
+ Substitutions
+ ~~~~~~~~~~~~~
+
+ Node names and property values support a basic string-substitution feature.
+ Available substitutions for '@' nodes (and property values) are:
+
+ SEQ:
+ Sequence number of the generated fdt (1, 2, ...)
+ NAME
+ Name of the dtb as provided (i.e. without adding '.dtb')
+
+ The `default` property, if present, will be automatically set to the name
+ if of configuration whose devicetree matches the `default-dt` entry
+ argument, e.g. with `-a default-dt=sun50i-a64-pine64-lts`.
+
+ Available substitutions for property values in these nodes are:
+
+ DEFAULT-SEQ:
+ Sequence number of the default fdt, as provided by the 'default-dt'
+ entry argument
+
+ Available operations
+ ~~~~~~~~~~~~~~~~~~~~
+
+ You can add an operation to an '@' node to indicate which operation is
+ required::
+
+ @fdt-SEQ {
+ fit,operation = "gen-fdt-nodes";
+ ...
+ };
+
+ Available operations are:
+
+ gen-fdt-nodes
+ Generate FDT nodes as above. This is the default if there is no
+ `fit,operation` property.
+
+ Generating nodes from an FDT list (gen-fdt-nodes)
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
U-Boot supports creating fdt and config nodes automatically. To do this,
pass an `of-list` property (e.g. `-a of-list=file1 file2`). This tells
binman that you want to generates nodes for two files: `file1.dtb` and
@@ -84,31 +153,8 @@
This tells binman to create nodes `config-1` and `config-2`, i.e. a config
for each of your two files.
- Available substitutions for '@' nodes are:
-
- SEQ:
- Sequence number of the generated fdt (1, 2, ...)
- NAME
- Name of the dtb as provided (i.e. without adding '.dtb')
-
Note that if no devicetree files are provided (with '-a of-list' as above)
then no nodes will be generated.
-
- The 'default' property, if present, will be automatically set to the name
- if of configuration whose devicetree matches the 'default-dt' entry
- argument, e.g. with '-a default-dt=sun50i-a64-pine64-lts'.
-
- Available substitutions for '@' property values are
-
- DEFAULT-SEQ:
- Sequence number of the default fdt,as provided by the 'default-dt' entry
- argument
-
- Properties (in the 'fit' node itself):
- fit,external-offset: Indicates that the contents of the FIT are external
- and provides the external offset. This is passsed to mkimage via
- the -E and -p flags.
-
"""
def __init__(self, section, etype, node):
"""
@@ -142,6 +188,26 @@
self.ReadEntries()
super().ReadNode()
+ def _get_operation(self, subnode):
+ """Get the operation referenced by a subnode
+
+ Args:
+ subnode (Node): Subnode (of the FIT) to check
+
+ Returns:
+ int: Operation to perform
+
+ Raises:
+ ValueError: Invalid operation name
+ """
+ oper_name = subnode.props.get('fit,operation')
+ if not oper_name:
+ return OP_GEN_FDT_NODES
+ oper = OPERATIONS.get(oper_name.value)
+ if not oper:
+ self.Raise(f"Unknown operation '{oper_name.value}'")
+ return oper
+
def ReadEntries(self):
def _process_prop(pname, prop):
"""Process special properties
@@ -172,8 +238,8 @@
return
fsw.property(pname, prop.bytes)
- def _generate_node(subnode, depth, in_images):
- """Generate nodes from a template
+ def _scan_gen_fdt_nodes(subnode, depth, in_images):
+ """Generate FDT nodes
This creates one node for each member of self._fdts using the
provided template. If a property value contains 'NAME' it is
@@ -211,6 +277,25 @@
else:
self.Raise("Generator node requires 'fit,fdt-list' property")
+ def _scan_node(subnode, depth, in_images):
+ """Generate nodes from a template
+
+ This creates one node for each member of self._fdts using the
+ provided template. If a property value contains 'NAME' it is
+ replaced with the filename of the FDT. If a property value contains
+ SEQ it is replaced with the node sequence number, where 1 is the
+ first.
+
+ Args:
+ subnode (None): Generator node to process
+ depth: Current node depth (0 is the base 'fit' node)
+ in_images: True if this is inside the 'images' node, so that
+ 'data' properties should be generated
+ """
+ oper = self._get_operation(subnode)
+ if oper == OP_GEN_FDT_NODES:
+ _scan_gen_fdt_nodes(subnode, depth, in_images)
+
def _AddNode(base_node, depth, node):
"""Add a node to the FIT
@@ -251,7 +336,7 @@
# fsw.add_node() or _AddNode() for it.
pass
elif self.GetImage().generate and subnode.name.startswith('@'):
- _generate_node(subnode, depth, in_images)
+ _scan_node(subnode, depth, in_images)
else:
with fsw.add_node(subnode.name):
_AddNode(base_node, depth + 1, subnode)
diff --git a/tools/binman/ftest.py b/tools/binman/ftest.py
index 6a77f1d..8f00db6 100644
--- a/tools/binman/ftest.py
+++ b/tools/binman/ftest.py
@@ -5303,6 +5303,24 @@
data = self._DoReadFile('222_tee_os.dts')
self.assertEqual(TEE_OS_DATA, data[:len(TEE_OS_DATA)])
+ def testFitFdtOper(self):
+ """Check handling of a specified FIT operation"""
+ entry_args = {
+ 'of-list': 'test-fdt1 test-fdt2',
+ 'default-dt': 'test-fdt2',
+ }
+ self._DoReadFileDtb(
+ '223_fit_fdt_oper.dts',
+ entry_args=entry_args,
+ extra_indirs=[os.path.join(self._indir, TEST_FDT_SUBDIR)])[0]
+
+ def testFitFdtBadOper(self):
+ """Check handling of an FDT map when the section cannot be found"""
+ with self.assertRaises(ValueError) as exc:
+ self._DoReadFileDtb('224_fit_bad_oper.dts')
+ self.assertIn("Node '/binman/fit': Unknown operation 'unknown'",
+ str(exc.exception))
+
if __name__ == "__main__":
unittest.main()
diff --git a/tools/binman/test/223_fit_fdt_oper.dts b/tools/binman/test/223_fit_fdt_oper.dts
new file mode 100644
index 0000000..e630165
--- /dev/null
+++ b/tools/binman/test/223_fit_fdt_oper.dts
@@ -0,0 +1,56 @@
+// SPDX-License-Identifier: GPL-2.0+
+
+/dts-v1/;
+
+/ {
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ binman {
+ u-boot {
+ };
+ fit {
+ description = "test-desc";
+ #address-cells = <1>;
+ fit,fdt-list = "of-list";
+
+ images {
+ kernel {
+ description = "Vanilla Linux kernel";
+ type = "kernel";
+ arch = "ppc";
+ os = "linux";
+ compression = "gzip";
+ load = <00000000>;
+ entry = <00000000>;
+ hash-1 {
+ algo = "crc32";
+ };
+ hash-2 {
+ algo = "sha1";
+ };
+ u-boot {
+ };
+ };
+ @fdt-SEQ {
+ fit,operation = "gen-fdt-nodes";
+ description = "fdt-NAME.dtb";
+ type = "flat_dt";
+ compression = "none";
+ };
+ };
+
+ configurations {
+ default = "@config-DEFAULT-SEQ";
+ @config-SEQ {
+ description = "conf-NAME.dtb";
+ firmware = "uboot";
+ loadables = "atf";
+ fdt = "fdt-SEQ";
+ };
+ };
+ };
+ u-boot-nodtb {
+ };
+ };
+};
diff --git a/tools/binman/test/224_fit_bad_oper.dts b/tools/binman/test/224_fit_bad_oper.dts
new file mode 100644
index 0000000..cee801e
--- /dev/null
+++ b/tools/binman/test/224_fit_bad_oper.dts
@@ -0,0 +1,27 @@
+// SPDX-License-Identifier: GPL-2.0+
+
+/dts-v1/;
+
+/ {
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ binman {
+ fit {
+ description = "test-desc";
+ #address-cells = <1>;
+ fit,fdt-list = "of-list";
+
+ images {
+ @fdt-SEQ {
+ fit,operation = "unknown";
+ description = "fdt-NAME.dtb";
+ type = "flat_dt";
+ compression = "none";
+ };
+ };
+ };
+ fdtmap {
+ };
+ };
+};