binman: Support templates containing phandles

This provides support for phandles to be copied over from templates. This
is not quite safe, since if the template is instantiated twice (i.e. in
two different nodes), then duplicate phandles will be found. This will
result in an error.

Signed-off-by: Simon Glass <sjg@chromium.org>
This commit is contained in:
Simon Glass 2023-07-22 21:43:57 -06:00
parent af41b24eba
commit d4d97661d2
5 changed files with 165 additions and 0 deletions

View file

@ -1264,6 +1264,24 @@ The initial devicetree produced by the templating process is written to the
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
====================

View file

@ -575,6 +575,10 @@ def PrepareImagesAndDtbs(dtb_fname, select_images, update_fdt, use_expanded):
_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())

View file

@ -6969,6 +6969,33 @@ fdt fdtmap Extract the devicetree blob from the fdtmap
# 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')

View file

@ -0,0 +1,51 @@
// 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";
};
};
};
};
};
};
};

View file

@ -0,0 +1,65 @@
// 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";
};
};
};
};
};
};
};