Hi Simon

On 18/07/23 18:54, Simon Glass wrote:
Collections can used to collect the contents of other entries into a
single entry, but they result in a single entry, with the original entries
'left behind' in their old place.

It is useful to be able to specific a set of entries ones and have it used
in multiple images, or parts of an image.

Implement this mechanism.

Signed-off-by: Simon Glass <[email protected]>
---

(no changes since v4)

Changes in v4:
- Copy over properties from the top-level template node

Changes in v2:
- Correct ordering of template nodes
- Fix 'preseverd' and 'inserter' typos

  tools/binman/binman.rst            | 87 ++++++++++++++++++++++++++++++
  tools/binman/control.py            | 26 +++++++++
  tools/binman/etype/section.py      |  3 +-
  tools/binman/ftest.py              |  8 +++
  tools/binman/test/286_template.dts | 42 +++++++++++++++
  5 files changed, 165 insertions(+), 1 deletion(-)
  create mode 100644 tools/binman/test/286_template.dts

diff --git a/tools/binman/binman.rst b/tools/binman/binman.rst
index a4b31fe5397b..8f57b6cfc76f 100644
--- a/tools/binman/binman.rst
+++ b/tools/binman/binman.rst
@@ -727,6 +727,13 @@ optional:
      Note that missing, optional blobs do not produce a non-zero exit code from
      binman, although it does show a warning about the missing external blob.
+insert-template:
+    This is not strictly speaking an entry property, since it is processed 
early
+    in Binman before the entries are read. It is a list of phandles of nodes to
+    include in the current (target) node. For each node, its subnodes and their
+    properties are brought into the target node. See Templates_ below for
+    more information.
+
  The attributes supported for images and sections are described below. Several
  are similar to those for entries.
@@ -1172,6 +1179,86 @@ If you are having trouble figuring out what is going on, you can use
       arch/arm/dts/u-boot.dtsi ... found: "arch/arm/dts/juno-r2-u-boot.dtsi"
+Templates
+=========
+
+Sometimes multiple images need to be created which have all have a common
+part. For example, a board may generate SPI and eMMC images which both include
+a FIT. Since the FIT includes many entries, it is tedious to repeat them twice
+in the image description.
+
+Templates provide a simple way to handle this::
+
+    binman {
+        multiple-images;
+        common_part: template-1 {
+            some-property;
+            fit {
+                ... lots of entries in here
+            };
+
+            text {
+                text = "base image";
+            };
+        };
+
+        spi-image {
+            filename = "image-spi.bin";
+            insert-template = <&fit>;
+
+            /* things specific to SPI follow */
+            footer {
+            ];
+
+            text {
+                text = "SPI image";
+            };
+        };
+
+        mmc-image {
+            filename = "image-mmc.bin";
+            insert-template = <&fit>;
+
+            /* things specific to MMC follow */
+            footer {
+            ];
+
+            text {
+                text = "MMC image";
+            };
+        };
+    };
+
+The template node name must start with 'template', so it is not considered to 
be
+an image itself.
+
+The mechanism is very simple. For each phandle in the 'insert-templates'
+property, the source node is looked up. Then the subnodes of that source node
+are copied into the target node, i.e. the one containing the `insert-template`
+property.
+
+If the target node has a node with the same name as a template, its properties
+override corresponding properties in the template. This allows the template to
+be uses as a base, with the node providing updates to the properties as needed.
+The overriding happens recursively.
+
+Template nodes appear first in each node that they are inserted into and
+ordering of template nodes is preserved. Other nodes come afterwards. If a
+template node also appears in the target node, then the template node sets the
+order. Thus the template can be used to set the ordering, even if the target
+node provides all the properties. In the above example, `fit` and `text` appear
+first in the `spi-image` and `mmc-image` images, followed by `footer`.
+
+Where there are multiple template nodes, they are inserted in that order. so
+the first template node appears first, then the second.
+
+Properties in the template node are inserted into the destination node if they
+do not exist there. In the example above, `some-property` is added to each of
+`spi-image` and `mmc-image`.
+
+Note that template nodes are not removed from the binman description at 
present.
+
+
  Updating an ELF file
  ====================
diff --git a/tools/binman/control.py b/tools/binman/control.py
index 7e2dd3541b96..e9c4a65a75a1 100644
--- a/tools/binman/control.py
+++ b/tools/binman/control.py
@@ -22,6 +22,7 @@ from binman import bintool
  from binman import cbfs_util
  from binman import elf
  from binman import entry
+from dtoc import fdt_util
  from u_boot_pylib import command
  from u_boot_pylib import tools
  from u_boot_pylib import tout
@@ -478,6 +479,29 @@ def SignEntries(image_fname, input_fname, 
privatekey_fname, algo, entry_paths,
AfterReplace(image, allow_resize=True, write_map=write_map) +def _ProcessTemplates(parent):
+    """Handle any templates in the binman description
+
+    Args:
+        parent: Binman node to process (typically /binman)
+
+    Search though each target node looking for those with an 'insert-template'
+    property. Use that as a list of references to template nodes to use to
+    adjust the target node.
+
+    Processing involves copying each subnode of the template node into the
+    target node.
+
+    For now this is not done recursively, so templates must be at the top level
+    of the binman image.
+
+    See 'Templates' in the Binman documnentation for details.
+    """
+    for node in parent.subnodes:
+        tmpl = fdt_util.GetPhandleList(node, 'insert-template')
+        if tmpl:
+            node.copy_subnodes_from_phandles(tmpl)
+
  def PrepareImagesAndDtbs(dtb_fname, select_images, update_fdt, use_expanded):
      """Prepare the images to be processed and select the device tree
@@ -520,6 +544,8 @@ def PrepareImagesAndDtbs(dtb_fname, select_images, update_fdt, use_expanded):
          raise ValueError("Device tree '%s' does not have a 'binman' "
                              "node" % dtb_fname)
+ _ProcessTemplates(node)
+
      images = _ReadImageDesc(node, use_expanded)
if select_images:
diff --git a/tools/binman/etype/section.py b/tools/binman/etype/section.py
index d9b9e428024a..7c4d312c16c0 100644
--- a/tools/binman/etype/section.py
+++ b/tools/binman/etype/section.py
@@ -179,7 +179,8 @@ class Entry_section(Entry):
          Returns:
              bool: True if the node is a special one, else False
          """
-        return node.name.startswith('hash') or 
node.name.startswith('signature')
+        start_list = ('hash', 'signature', 'template')
+        return any(node.name.startswith(name) for name in start_list)
def ReadNode(self):
          """Read properties from the section node"""
diff --git a/tools/binman/ftest.py b/tools/binman/ftest.py
index dc9a95d341e5..fc5d8a839e6b 100644
--- a/tools/binman/ftest.py
+++ b/tools/binman/ftest.py
@@ -6785,6 +6785,14 @@ fdt         fdtmap                Extract the devicetree 
blob from the fdtmap
          data = self._DoReadFileDtb('285_spl_expand.dts',
                                     use_expanded=True, 
entry_args=entry_args)[0]
+ def testTemplate(self):
+        """Test using a template"""
+        TestFunctional._MakeInputFile('vga2.bin', b'#' + VGA_DATA)
+        data = self._DoReadFile('286_template.dts')
+        first = U_BOOT_DATA + VGA_DATA + U_BOOT_DTB_DATA
+        second = U_BOOT_DATA + b'#' + VGA_DATA + U_BOOT_DTB_DATA
+        self.assertEqual(U_BOOT_IMG_DATA + first + second, data)
+
if __name__ == "__main__":
      unittest.main()
diff --git a/tools/binman/test/286_template.dts 
b/tools/binman/test/286_template.dts
new file mode 100644
index 000000000000..6980dbfafcc6
--- /dev/null
+++ b/tools/binman/test/286_template.dts
@@ -0,0 +1,42 @@
+// SPDX-License-Identifier: GPL-2.0+
+
+/dts-v1/;
+
+/ {
+       #address-cells = <1>;
+       #size-cells = <1>;
+
+       binman {
+               u-boot-img {
+               };
+
+               common_part: template {
+                       u-boot {
+                       };
+
+                       intel-vga {
+                               filename = "vga.bin";
+                       };
+               };
+
+               first {
+                       type = "section";
+                       insert-template = <&common_part>;
+
+                       u-boot-dtb {
+                       };
+               };
+
+               second {
+                       type = "section";
+                       insert-template = <&common_part>;
+
+                       u-boot-dtb {
+                       };
+
+                       intel-vga {
+                               filename = "vga2.bin";
+                       };
+               };
+       };
+};

While trying to use the templating feature in the K3 boot-loader generation, I seem to face an issue getting a node via phandle. My dts looks something like this:

ti_spl_template: template-1 {
        fit {
                images {
                        atf {
                                ti-secure {
                                        content = <&atf>;
                                        keyfile = "key.pem";
                                };
                                atf: atf-bl31 {
                                };
                        };
                };
        };
};

ti-spl {
        insert-template = <&ti_spl_template>;
        fit {
                images {
                        fdt-0 {
                                ti-secure {
                                        content = <&foo_dtb>;
                                        keyfile = "key.pem";
                                };
                                foo_dtb: blob-ext {
                                        filename = "foo.dtb";
                                };
                        };
                };
        };
};

The signing in the template node throws the error:
binman: Node '/binman/ti-spl/fit/images/atf/ti-secure': Cannot find entry for node 'atf-bl31'

I understand the phandle is not copied over. And I can work around this by moving the signing contents over to the target node instead of the template. But again, trying for least code duplication here; so any way around?

--
Thanking You
Neha Malcom Francis

Reply via email to