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.
+Dealing with phandles
+---------------------
+
+Templates can contain phandles and these are copied to the destination node.
+However this should be used with care, since if a template is instantiated twice
+then the phandle will be copied twice, resulting in a devicetree with duplicate
+phandles, i.e. the same phandle used by two different nodes. Binman detects this
+situation and produces an error, for example::
+
+ Duplicate phandle 1 in nodes /binman/image/fit/images/atf/atf-bl31 and
+ /binman/image-2/fit/images/atf/atf-bl31
+
+In this case an atf-bl31 node containing a phandle has been copied into two
+different target nodes, resulting in the same phandle for each. See
+testTemplatePhandleDup() for the test case.
+
+The solution is typically to put the phandles in the corresponding target nodes
+(one for each) and remove the phandle from the template.
Updating an ELF file
====================
_RemoveTemplates(node)
dtb.Sync(True)
+
+ # Rescan the dtb to pick up the new phandles
+ dtb.Scan()
+ node = _FindBinmanNode(dtb)
fname = tools.get_output_filename('u-boot.dtb.tmpl2')
tools.write_file(fname, dtb.GetContents())
# Move to next
spl_data = content[:0x18]
+ def testTemplatePhandle(self):
+ """Test using a template in a node containing a phandle"""
+ entry_args = {
+ 'atf-bl31-path': 'bl31.elf',
+ }
+ data = self._DoReadFileDtb('291_template_phandle.dts',
+ entry_args=entry_args)
+ fname = tools.get_output_filename('image.bin')
+ out = tools.run('dumpimage', '-l', fname)
+
+ # We should see the FIT description and one for each of the two images
+ lines = out.splitlines()
+ descs = [line.split()[-1] for line in lines if 'escription' in line]
+ self.assertEqual(['test-desc', 'atf', 'fdt'], descs)
+
+ def testTemplatePhandleDup(self):
+ """Test using a template in a node containing a phandle"""
+ entry_args = {
+ 'atf-bl31-path': 'bl31.elf',
+ }
+ with self.assertRaises(ValueError) as e:
+ self._DoReadFileDtb('292_template_phandle_dup.dts',
+ entry_args=entry_args)
+ self.assertIn(
+ 'Duplicate phandle 1 in nodes /binman/image/fit/images/atf/atf-bl31 and /binman/image-2/fit/images/atf/atf-bl31',
+ str(e.exception))
+
def testTIBoardConfig(self):
"""Test that a schema validated board config file can be generated"""
data = self._DoReadFile('293_ti_board_cfg.dts')
--- /dev/null
+// SPDX-License-Identifier: GPL-2.0+
+
+/dts-v1/;
+
+/ {
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ binman {
+ multiple-images;
+
+ ti_spl_template: template-1 {
+ fit {
+ description = "test-desc";
+ #address-cells = <1>;
+ images {
+ atf {
+ description = "atf";
+ ti-secure {
+ type = "collection";
+ content = <&atf>;
+ keyfile = "key.pem";
+ };
+ atf: atf-bl31 {
+ description = "atf";
+ };
+ };
+ };
+ };
+ };
+
+ image {
+ insert-template = <&ti_spl_template>;
+ fit {
+ images {
+ fdt-0 {
+ description = "fdt";
+ ti-secure {
+ type = "collection";
+ content = <&foo_dtb>;
+ keyfile = "key.pem";
+ };
+ foo_dtb: blob-ext {
+ filename = "vga.bin";
+ };
+ };
+ };
+ };
+ };
+ };
+};
--- /dev/null
+// SPDX-License-Identifier: GPL-2.0+
+
+/dts-v1/;
+
+/ {
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ binman {
+ multiple-images;
+
+ ti_spl_template: template-1 {
+ fit {
+ description = "test-desc";
+ #address-cells = <1>;
+ images {
+ atf {
+ description = "atf";
+ ti-secure {
+ type = "collection";
+ content = <&atf>;
+ keyfile = "key.pem";
+ };
+ atf: atf-bl31 {
+ description = "atf";
+ };
+ };
+ };
+ };
+ };
+
+ image {
+ insert-template = <&ti_spl_template>;
+ fit {
+ images {
+ fdt-0 {
+ description = "fdt";
+ ti-secure {
+ type = "collection";
+ content = <&foo_dtb>;
+ keyfile = "key.pem";
+ };
+ foo_dtb: blob-ext {
+ filename = "vga.bin";
+ };
+ };
+ };
+ };
+ };
+
+ image-2 {
+ insert-template = <&ti_spl_template>;
+ fit {
+ images {
+ fdt-0 {
+ description = "fdt";
+ blob-ext {
+ filename = "vga.bin";
+ };
+ };
+ };
+ };
+ };
+ };
+};