[PATCH v5 15/20] binman: Support simple templates

Neha Malcom Francis n-francis at ti.com
Wed Jul 19 13:08:15 CEST 2023


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 <sjg at chromium.org>
> ---
> 
> (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


More information about the U-Boot mailing list