binman: Remove templates after use

It is not necessary to keep templates around after they have been
processed. They can cause confusion and potentially duplicate phandles.

Remove them.

Use the same means of detecting a template node in _ReadImageDesc so that
the two places are consistent.

Signed-off-by: Simon Glass <sjg@chromium.org>
diff --git a/tools/binman/binman.rst b/tools/binman/binman.rst
index 67bc3e8..147fbc5 100644
--- a/tools/binman/binman.rst
+++ b/tools/binman/binman.rst
@@ -1256,11 +1256,13 @@
 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 removed from the binman description after
+processing and before binman builds the image descriptions.
+
 The initial devicetree produced by the templating process is written to the
 `u-boot.dtb.tmpl1` file. This can be useful to see what is going on if there is
-a failure before the final `u-boot.dtb.out` file is written.
-
-Note that template nodes are not removed from the binman description at present.
+a failure before the final `u-boot.dtb.out` file is written. A second
+`u-boot.dtb.tmpl2` file is written when the templates themselves are removed.
 
 
 Updating an ELF file
diff --git a/tools/binman/control.py b/tools/binman/control.py
index 963f9b9..da33c88 100644
--- a/tools/binman/control.py
+++ b/tools/binman/control.py
@@ -57,7 +57,7 @@
     images = OrderedDict()
     if 'multiple-images' in binman_node.props:
         for node in binman_node.subnodes:
-            if 'template' not in node.name:
+            if not node.name.startswith('template'):
                 images[node.name] = Image(node.name, node,
                                           use_expanded=use_expanded)
     else:
@@ -519,6 +519,13 @@
         found |= _ProcessTemplates(node)
     return found
 
+def _RemoveTemplates(parent):
+    """Remove any templates in the binman description
+    """
+    for node in parent.subnodes:
+        if node.name.startswith('template'):
+            node.Delete()
+
 def PrepareImagesAndDtbs(dtb_fname, select_images, update_fdt, use_expanded):
     """Prepare the images to be processed and select the device tree
 
@@ -566,6 +573,11 @@
         fname = tools.get_output_filename('u-boot.dtb.tmpl1')
         tools.write_file(fname, dtb.GetContents())
 
+        _RemoveTemplates(node)
+        dtb.Sync(True)
+        fname = tools.get_output_filename('u-boot.dtb.tmpl2')
+        tools.write_file(fname, dtb.GetContents())
+
     images = _ReadImageDesc(node, use_expanded)
 
     if select_images:
diff --git a/tools/binman/ftest.py b/tools/binman/ftest.py
index b15f5ac..ecada41 100644
--- a/tools/binman/ftest.py
+++ b/tools/binman/ftest.py
@@ -6871,6 +6871,13 @@
         vga = dtb.GetNode('/binman/first/intel-vga')
         self.assertTrue(vga)
 
+        dtb_fname2 = tools.get_output_filename('u-boot.dtb.tmpl2')
+        self.assertTrue(os.path.exists(dtb_fname2))
+        dtb2 = fdt.Fdt.FromData(tools.read_file(dtb_fname2))
+        dtb2.Scan()
+        node2 = dtb2.GetNode('/binman/template')
+        self.assertFalse(node2)
+
     def testTemplateBlobMulti(self):
         """Test using a template with 'multiple-images' enabled"""
         TestFunctional._MakeInputFile('my-blob.bin', b'blob')