[PATCH 15/20] binman: Add support for alternative FDTs
Neha Malcom Francis
n-francis at ti.com
Tue Jul 30 06:44:33 CEST 2024
Hi Simon
On 20/07/24 16:19, Simon Glass wrote:
> FIT provides a way to select between different devicetree blobs
> depending on the model. This works fine for U-Boot proper and allows SPL
> to select the correct blob for the current board at runtime. The boot
> sequence (SPL->U-Boot proper) is therefore covered by the existing
> feature set.
>
> The first boot phase (typically TPL) cannot use FIT since SoC boot ROMs
> don't currently support it. Therefore the TPL image must be specific to
> each model it boots on.
>
> To support booting on mulitple models, binman must therefore produce a
> separate TPL image for each model, even if the images for the rest of
> the phases are identical.
>
> TPL needs to be packaged as an executable binary along with a reduced
> devicetree. When multiple models are supported, a reduced devicetree
> must be provided for each model.
>
> U-Boot's build system is designed to build a single devicetree for SPL
> builds, so does not support this requirement.
>
> Add a new 'alternatives' feature to Binman, allowing it to automatically
> subset a devicetree to produce the reduced devicetree for a particular
> phase for each supported model. With this it is possible to produce a
> separate TPL image for each of the models. The correct one can then be
> loaded onto a board, along with the common FIT image(s).
>
Realized I caught up too late to this thread, and it's already pulled in,
anyways thanks for the effort this was needed.
> Signed-off-by: Simon Glass <sjg at chromium.org>
> ---
>
> tools/binman/btool/fdtgrep.py | 2 +-
> tools/binman/control.py | 3 +
> tools/binman/entries.rst | 42 ++++++
> tools/binman/entry.py | 4 +-
> tools/binman/etype/alternates_fdt.py | 132 +++++++++++++++++++
> tools/binman/ftest.py | 121 +++++++++++++++++
> tools/binman/image.py | 13 ++
> tools/binman/test/328_alternates_fdt.dts | 28 ++++
> tools/binman/test/329_alternates_fdtgrep.dts | 29 ++++
> tools/binman/test/330_alternates_vpl.dts | 29 ++++
> tools/binman/test/331_alternates_spl.dts | 29 ++++
> tools/binman/test/332_alternates_inval.dts | 29 ++++
> tools/binman/test/alt_dts/model1.dts | 24 ++++
> tools/binman/test/alt_dts/model2.dts | 24 ++++
> 14 files changed, 507 insertions(+), 2 deletions(-)
> create mode 100644 tools/binman/etype/alternates_fdt.py
> create mode 100644 tools/binman/test/328_alternates_fdt.dts
> create mode 100644 tools/binman/test/329_alternates_fdtgrep.dts
> create mode 100644 tools/binman/test/330_alternates_vpl.dts
> create mode 100644 tools/binman/test/331_alternates_spl.dts
> create mode 100644 tools/binman/test/332_alternates_inval.dts
> create mode 100644 tools/binman/test/alt_dts/model1.dts
> create mode 100644 tools/binman/test/alt_dts/model2.dts
>
> diff --git a/tools/binman/btool/fdtgrep.py b/tools/binman/btool/fdtgrep.py
> index c34d8d8943b..da1f8c7bf4e 100644
> --- a/tools/binman/btool/fdtgrep.py
> +++ b/tools/binman/btool/fdtgrep.py
> @@ -84,7 +84,7 @@ class Bintoolfdtgrep(bintool.Bintool):
> elif phase == 'spl':
> tag = 'bootph-pre-ram'
> else:
> - raise(f"Invalid U-Boot phase '{phase}': Use tpl/vpl/spl")
> + raise ValueError(f"Invalid U-Boot phase '{phase}': Use tpl/vpl/spl")
>
> # These args mirror those in cmd_fdtgrep in scripts/Makefile.lib
> # First do the first stage
> diff --git a/tools/binman/control.py b/tools/binman/control.py
> index a233c778d5e..542c2b45644 100644
> --- a/tools/binman/control.py
> +++ b/tools/binman/control.py
> @@ -734,6 +734,9 @@ def ProcessImage(image, update_fdt, write_map, get_contents=True,
> image.WriteMap()
>
> has_problems = CheckForProblems(image)
> +
> + image.WriteAlternates()
> +
> return has_problems
>
> def Binman(args):
> diff --git a/tools/binman/entries.rst b/tools/binman/entries.rst
> index 38dfe2c7db9..8bfec8b434e 100644
> --- a/tools/binman/entries.rst
> +++ b/tools/binman/entries.rst
> @@ -11,6 +11,48 @@ features to produce new behaviours.
>
>
>
> +.. _etype_alternates_fdt:
> +
> +Entry: alternates-fdt: Entry that generates alternative sections for each devicetree provided
> +---------------------------------------------------------------------------------------------
> +
> +When creating an image designed to boot on multiple models, each model
> +requires its own devicetree. This entry deals with selecting the correct
> +devicetree from a directory containing them. Each one is read in turn, then
> +used to produce section contents which are written to a file. This results
> +in a number of images, one for each model.
> +
> +For example this produces images for each .dtb file in the 'dtb' directory::
> +
> + alternates-fdt {
> + fdt-list-dir = "dtb";
> + filename-pattern = "NAME.bin";
> + fdt-phase = "tpl";
> +
> + section {
> + u-boot-tpl {
> + };
> + };
> + };
> +
> +Each output file is named based on its input file, so an input file of
> +`model1.dtb` results in an output file of `model1.bin` (i.e. the `NAME` in
> +the `filename-pattern` property is replaced with the .dtb basename).
> +
> +Note that this entry type still produces contents for the 'main' image, in
> +that case using the normal dtb provided to Binman, e.g. `u-boot-tpl.dtb`.
> +But that image is unlikely to be useful, since it relates to whatever dtb
> +happened to be the default when U-Boot builds
> +(i.e. `CONFIG_DEFAULT_DEVICE_TREE`). However, Binman ensures that the size
> +of each of the alternates is the same as the 'default' one, so they can in
> +principle be 'slotted in' to the appropriate place in the main image.
> +
> +The optional `fdt-phase` property indicates the phase to build. In this
> +case, it etype runs fdtgrep to obtain the devicetree subset for that phase,
> +respecting the `bootph-xxx` tags in the devicetree.
> +
> +
> +
> .. _etype_atf_bl31:
>
> Entry: atf-bl31: ARM Trusted Firmware (ATF) BL31 blob
> diff --git a/tools/binman/entry.py b/tools/binman/entry.py
> index 494b1b1278d..6d2f3789940 100644
> --- a/tools/binman/entry.py
> +++ b/tools/binman/entry.py
> @@ -1395,6 +1395,8 @@ features to produce new behaviours.
> 'u-boot-tpl-dtb'
>
> Returns:
> - bytes: Contents of requested FDT
> + tuple:
> + fname (str): Filename of .dtb
> + bytes: Contents of FDT (possibly run through fdtgrep)
> """
> return self.section.FdtContents(fdt_etype)
> diff --git a/tools/binman/etype/alternates_fdt.py b/tools/binman/etype/alternates_fdt.py
> new file mode 100644
> index 00000000000..808f535aa1b
> --- /dev/null
> +++ b/tools/binman/etype/alternates_fdt.py
> @@ -0,0 +1,132 @@
> +# SPDX-License-Identifier: GPL-2.0+
> +# Copyright 2024 Google LLC
> +# Written by Simon Glass <sjg at chromium.org>
> +
> +"""Entry-type module for producing multiple alternate sections"""
> +
> +import glob
> +import os
> +
> +from binman.entry import EntryArg
> +from binman.etype.section import Entry_section
> +from dtoc import fdt_util
> +from u_boot_pylib import tools
> +
> +class Entry_alternates_fdt(Entry_section):
> + """Entry that generates alternative sections for each devicetree provided
> +
> + When creating an image designed to boot on multiple models, each model
> + requires its own devicetree. This entry deals with selecting the correct
> + devicetree from a directory containing them. Each one is read in turn, then
> + used to produce section contents which are written to a file. This results
> + in a number of images, one for each model.
> +
> + For example this produces images for each .dtb file in the 'dtb' directory::
> +
> + alternates-fdt {
> + fdt-list-dir = "dtb";
> + filename-pattern = "NAME.bin";
> + fdt-phase = "tpl";
> +
> + section {
> + u-boot-tpl {
> + };
> + };
> + };
> +
> + Each output file is named based on its input file, so an input file of
> + `model1.dtb` results in an output file of `model1.bin` (i.e. the `NAME` in
> + the `filename-pattern` property is replaced with the .dtb basename).
> +
> + Note that this entry type still produces contents for the 'main' image, in
> + that case using the normal dtb provided to Binman, e.g. `u-boot-tpl.dtb`.
> + But that image is unlikely to be useful, since it relates to whatever dtb
> + happened to be the default when U-Boot builds
> + (i.e. `CONFIG_DEFAULT_DEVICE_TREE`). However, Binman ensures that the size
> + of each of the alternates is the same as the 'default' one, so they can in
> + principle be 'slotted in' to the appropriate place in the main image.
> +
> + The optional `fdt-phase` property indicates the phase to build. In this
> + case, it etype runs fdtgrep to obtain the devicetree subset for that phase,
> + respecting the `bootph-xxx` tags in the devicetree.
> + """
> + def __init__(self, section, etype, node):
> + super().__init__(section, etype, node)
> + self.fdt_list_dir = None
> + self.filename_pattern = None
> + self.required_props = ['fdt-list-dir']
> + self._cur_fdt = None
> + self._fdt_phase = None
> + self.fdtgrep = None
> + self._fdt_dir = None
> + self._fdts = None
> + self._fname_pattern = None
> + self._remove_props = None
> + self.alternates = None
> +
> + def ReadNode(self):
> + """Read properties from the node"""
> + super().ReadNode()
> + self._fdt_dir = fdt_util.GetString(self._node, 'fdt-list-dir')
> + fname = tools.get_input_filename(self._fdt_dir)
> + fdts = glob.glob('*.dtb', root_dir=fname)
> + self._fdts = [os.path.splitext(f)[0] for f in fdts]
> +
> + self._fdt_phase = fdt_util.GetString(self._node, 'fdt-phase')
> +
> + # This is used by Image.WriteAlternates()
> + self.alternates = self._fdts
> +
> + self._fname_pattern = fdt_util.GetString(self._node, 'filename-pattern')
> +
> + self._remove_props = []
> + props, = self.GetEntryArgsOrProps(
> + [EntryArg('of-spl-remove-props', str)], required=False)
> + if props:
> + self._remove_props = props.split()
> +
> + def FdtContents(self, fdt_etype):
> + # If there is no current FDT, just use the normal one
> + if not self._cur_fdt:
> + return self.section.FdtContents(fdt_etype)
> +
> + # Find the file to use
> + fname = os.path.join(self._fdt_dir, f'{self._cur_fdt}.dtb')
> + infile = tools.get_input_filename(fname)
> +
> + # Run fdtgrep if needed, to remove unwanted nodes and properties
> + if self._fdt_phase:
> + uniq = self.GetUniqueName()
> + outfile = tools.get_output_filename(
> + f'{uniq}.{self._cur_fdt}-{self._fdt_phase}.dtb')
> + self.fdtgrep.create_for_phase(infile, self._fdt_phase, outfile,
> + self._remove_props)
> + return outfile, tools.read_file(outfile)
> + return fname, tools.read_file(infile)
> +
> + def ProcessWithFdt(self, alt):
> + """Produce the contents of this entry, using a particular FDT blob
> +
> + Args:
> + alt (str): Name of the alternate
> +
> + Returns:
> + tuple:
> + str: Filename to use for the alternate's .bin file
> + bytes: Contents of this entry's section, using the selected FDT
> + """
> + pattern = self._fname_pattern or 'NAME.bin'
> + fname = pattern.replace('NAME', alt)
> +
> + data = b''
> + try:
> + self._cur_fdt = alt
> + self.ProcessContents()
> + data = self.GetPaddedData()
> + finally:
> + self._cur_fdt = None
> + return fname, data
> +
> + def AddBintools(self, btools):
> + super().AddBintools(btools)
> + self.fdtgrep = self.AddBintool(btools, 'fdtgrep')
> diff --git a/tools/binman/ftest.py b/tools/binman/ftest.py
> index d091855b8e3..684e960b582 100644
> --- a/tools/binman/ftest.py
> +++ b/tools/binman/ftest.py
> @@ -7,6 +7,7 @@
> # python -m unittest func_test.TestFunctional.testHelp
>
> import collections
> +import glob
> import gzip
> import hashlib
> from optparse import OptionParser
> @@ -7484,6 +7485,126 @@ fdt fdtmap Extract the devicetree blob from the fdtmap
> err,
> "Image '.*' is missing external blobs and is non-functional: .*")
>
> + def CheckAlternates(self, dts, phase, xpl_data):
> + """Run the test for the alterative-fdt etype
> +
> + Args:
> + dts (str): Devicetree file to process
> + phase (str): Phase to process ('spl', 'tpl' or 'vpl')
> + xpl_data (bytes): Expected data for the phase's binary
> +
> + Returns:
> + dict of .dtb files produced
> + key: str filename
> + value: Fdt object
> + """
> + testdir = TestFunctional._MakeInputDir('dtb')
> + dtb_list = []
> + for fname in glob.glob(f'{self.TestFile("alt_dts")}/*.dts'):
> + tmp_fname = fdt_util.EnsureCompiled(fname, testdir)
> + base = os.path.splitext(os.path.basename(fname))[0]
> + dtb_list.append(base + '.bin')
> + shutil.move(tmp_fname, os.path.join(testdir, base + '.dtb'))
> +
> + entry_args = {
> + f'{phase}-dtb': '1',
> + f'{phase}-bss-pad': 'y',
> + 'of-spl-remove-props': 'prop-to-remove another-prop-to-get-rid-of',
> + }
> + data = self._DoReadFileDtb(dts, use_real_dtb=True, update_dtb=True,
> + use_expanded=True, entry_args=entry_args)[0]
> + self.assertEqual(xpl_data, data[:len(xpl_data)])
> + rest = data[len(xpl_data):]
> + pad_len = 10
> + self.assertEqual(tools.get_bytes(0, pad_len), rest[:pad_len])
> +
> + # Check the dtb is using the test file
> + dtb_data = rest[pad_len:]
> + dtb = fdt.Fdt.FromData(dtb_data)
> + dtb.Scan()
> + fdt_size = dtb.GetFdtObj().totalsize()
> + self.assertEqual('model-not-set',
> + fdt_util.GetString(dtb.GetRoot(), 'compatible'))
> +
> + pad_len = 10
> +
> + # Check the other output files
> + dtbs = {}
> + for fname in dtb_list:
> + pathname = tools.get_output_filename(fname)
> + self.assertTrue(os.path.exists(pathname))
> +
> + data = tools.read_file(pathname)
> + self.assertEqual(xpl_data, data[:len(xpl_data)])
> + rest = data[len(xpl_data):]
> +
> + self.assertEqual(tools.get_bytes(0, pad_len), rest[:pad_len])
> + rest = rest[pad_len:]
> +
> + dtb = fdt.Fdt.FromData(rest)
> + dtb.Scan()
> + dtbs[fname] = dtb
> +
> + expected = 'one' if '1' in fname else 'two'
> + self.assertEqual(f'u-boot,model-{expected}',
> + fdt_util.GetString(dtb.GetRoot(), 'compatible'))
> +
> + # Make sure the FDT is the same size as the 'main' one
> + rest = rest[fdt_size:]
> +
> + self.assertEqual(b'', rest)
> + return dtbs
> +
> + def testAlternatesFdt(self):
> + """Test handling of alternates-fdt etype"""
> + self._SetupTplElf()
> + dtbs = self.CheckAlternates('328_alternates_fdt.dts', 'tpl',
> + U_BOOT_TPL_NODTB_DATA)
> + for dtb in dtbs.values():
> + # Check for the node with the tag
> + node = dtb.GetNode('/node')
> + self.assertIsNotNone(node)
> + self.assertEqual(5, len(node.props.keys()))
> +
> + # Make sure the other node is still there
> + self.assertIsNotNone(dtb.GetNode('/node/other-node'))
> +
> + def testAlternatesFdtgrep(self):
> + """Test handling of alternates-fdt etype using fdtgrep"""
> + self._SetupTplElf()
> + dtbs = self.CheckAlternates('329_alternates_fdtgrep.dts', 'tpl',
> + U_BOOT_TPL_NODTB_DATA)
> + for dtb in dtbs.values():
> + # Check for the node with the tag
> + node = dtb.GetNode('/node')
> + self.assertIsNotNone(node)
> + self.assertEqual({'some-prop', 'not-a-prop-to-remove'},
> + node.props.keys())
> +
> + # Make sure the other node is gone
> + self.assertIsNone(dtb.GetNode('/node/other-node'))
> +
> + def testAlternatesFdtgrepVpl(self):
> + """Test handling of alternates-fdt etype using fdtgrep with vpl"""
> + self._SetupVplElf()
> + dtbs = self.CheckAlternates('330_alternates_vpl.dts', 'vpl',
> + U_BOOT_VPL_NODTB_DATA)
> +
> + def testAlternatesFdtgrepSpl(self):
> + """Test handling of alternates-fdt etype using fdtgrep with spl"""
> + self._SetupSplElf()
> + dtbs = self.CheckAlternates('331_alternates_spl.dts', 'spl',
> + U_BOOT_SPL_NODTB_DATA)
> +
> + def testAlternatesFdtgrepInval(self):
> + """Test alternates-fdt etype using fdtgrep with invalid phase"""
> + self._SetupSplElf()
> + with self.assertRaises(ValueError) as e:
> + dtbs = self.CheckAlternates('332_alternates_inval.dts', 'spl',
> + U_BOOT_SPL_NODTB_DATA)
> + self.assertIn("Invalid U-Boot phase 'bad-phase': Use tpl/vpl/spl",
> + str(e.exception))
> +
>
> if __name__ == "__main__":
> unittest.main()
> diff --git a/tools/binman/image.py b/tools/binman/image.py
> index c1be5cc23a2..702c9055585 100644
> --- a/tools/binman/image.py
> +++ b/tools/binman/image.py
> @@ -193,6 +193,19 @@ class Image(section.Entry_section):
> os.remove(sname)
> os.symlink(fname, sname)
>
> + def WriteAlternates(self):
> + """Write out alternative devicetree blobs, each in its own file"""
> + alt_entry = self.FindEntryType('alternates-fdt')
> + if not alt_entry:
> + return
> +
> + for alt in alt_entry.alternates:
> + fname, data = alt_entry.ProcessWithFdt(alt)
> + pathname = tools.get_output_filename(fname)
> + tout.info(f"Writing alternate '{alt}' to '{pathname}'")
> + tools.write_file(pathname, data)
> + tout.info("Wrote %#x bytes" % len(data))
> +
> def WriteMap(self):
> """Write a map of the image to a .map file
>
> diff --git a/tools/binman/test/328_alternates_fdt.dts b/tools/binman/test/328_alternates_fdt.dts
> new file mode 100644
> index 00000000000..c913c8e4745
> --- /dev/null
> +++ b/tools/binman/test/328_alternates_fdt.dts
> @@ -0,0 +1,28 @@
> +// SPDX-License-Identifier: GPL-2.0+
> +// Copyright 2024 Google LLC
> +// Written by Simon Glass <sjg at chromium.org>
> +
> +/dts-v1/;
> +
> +/ {
> + #address-cells = <1>;
> + #size-cells = <1>;
> +
> + compatible = "model-not-set";
> +
> + binman {
> + alternates-fdt {
> + fdt-list-dir = "dtb";
> + filename-pattern = "NAME.bin";
> +
> + section {
> + u-boot-tpl {
> + };
> + };
> + };
> +
> + blob {
> + filename = "blobfile";
> + };
> + };
> +};
> diff --git a/tools/binman/test/329_alternates_fdtgrep.dts b/tools/binman/test/329_alternates_fdtgrep.dts
> new file mode 100644
> index 00000000000..41695281456
> --- /dev/null
> +++ b/tools/binman/test/329_alternates_fdtgrep.dts
> @@ -0,0 +1,29 @@
> +// SPDX-License-Identifier: GPL-2.0+
> +// Copyright 2024 Google LLC
> +// Written by Simon Glass <sjg at chromium.org>
> +
> +/dts-v1/;
> +
> +/ {
> + #address-cells = <1>;
> + #size-cells = <1>;
> +
> + compatible = "model-not-set";
> +
> + binman {
> + alternates-fdt {
> + fdt-list-dir = "dtb";
> + filename-pattern = "NAME.bin";
> + fdt-phase = "tpl";
> +
> + section {
> + u-boot-tpl {
> + };
> + };
> + };
> +
> + blob {
> + filename = "blobfile";
> + };
> + };
> +};
> diff --git a/tools/binman/test/330_alternates_vpl.dts b/tools/binman/test/330_alternates_vpl.dts
> new file mode 100644
> index 00000000000..5b57069e2ab
> --- /dev/null
> +++ b/tools/binman/test/330_alternates_vpl.dts
> @@ -0,0 +1,29 @@
> +// SPDX-License-Identifier: GPL-2.0+
> +// Copyright 2024 Google LLC
> +// Written by Simon Glass <sjg at chromium.org>
> +
> +/dts-v1/;
> +
> +/ {
> + #address-cells = <1>;
> + #size-cells = <1>;
> +
> + compatible = "model-not-set";
> +
> + binman {
> + alternates-fdt {
> + fdt-list-dir = "dtb";
> + filename-pattern = "NAME.bin";
> + fdt-phase = "vpl";
> +
> + section {
> + u-boot-vpl {
> + };
> + };
> + };
> +
> + blob {
> + filename = "blobfile";
> + };
> + };
> +};
> diff --git a/tools/binman/test/331_alternates_spl.dts b/tools/binman/test/331_alternates_spl.dts
> new file mode 100644
> index 00000000000..882fefce34a
> --- /dev/null
> +++ b/tools/binman/test/331_alternates_spl.dts
> @@ -0,0 +1,29 @@
> +// SPDX-License-Identifier: GPL-2.0+
> +// Copyright 2024 Google LLC
> +// Written by Simon Glass <sjg at chromium.org>
> +
> +/dts-v1/;
> +
> +/ {
> + #address-cells = <1>;
> + #size-cells = <1>;
> +
> + compatible = "model-not-set";
> +
> + binman {
> + alternates-fdt {
> + fdt-list-dir = "dtb";
> + filename-pattern = "NAME.bin";
> + fdt-phase = "spl";
> +
> + section {
> + u-boot-spl {
> + };
> + };
> + };
> +
> + blob {
> + filename = "blobfile";
> + };
> + };
> +};
> diff --git a/tools/binman/test/332_alternates_inval.dts b/tools/binman/test/332_alternates_inval.dts
> new file mode 100644
> index 00000000000..8c145dd2449
> --- /dev/null
> +++ b/tools/binman/test/332_alternates_inval.dts
> @@ -0,0 +1,29 @@
> +// SPDX-License-Identifier: GPL-2.0+
> +// Copyright 2024 Google LLC
> +// Written by Simon Glass <sjg at chromium.org>
> +
> +/dts-v1/;
> +
> +/ {
> + #address-cells = <1>;
> + #size-cells = <1>;
> +
> + compatible = "model-not-set";
> +
> + binman {
> + alternates-fdt {
> + fdt-list-dir = "dtb";
> + filename-pattern = "NAME.bin";
> + fdt-phase = "bad-phase";
> +
> + section {
> + u-boot-spl {
> + };
> + };
> + };
> +
> + blob {
> + filename = "blobfile";
> + };
> + };
> +};
> diff --git a/tools/binman/test/alt_dts/model1.dts b/tools/binman/test/alt_dts/model1.dts
> new file mode 100644
> index 00000000000..01e95e8fabe
> --- /dev/null
> +++ b/tools/binman/test/alt_dts/model1.dts
> @@ -0,0 +1,24 @@
> +// SPDX-License-Identifier: GPL-2.0+
> +// Copyright 2024 Google LLC
> +// Written by Simon Glass <sjg at chromium.org>
> +
> +/dts-v1/;
> +
> +/ {
> + model = "Model One";
> + compatible = "u-boot,model-one";
> +
> + /* this node remains due to bootph-pre-sram tag */
> + node {
> + some-prop;
> + prop-to-remove;
> + another-prop-to-get-rid-of;
> + not-a-prop-to-remove;
> + bootph-pre-sram;
> +
> + /* this node get removed by fdtgrep */
> + other-node {
> + another-prop;
> + };
> + };
> +};
> diff --git a/tools/binman/test/alt_dts/model2.dts b/tools/binman/test/alt_dts/model2.dts
> new file mode 100644
> index 00000000000..7829c519772
> --- /dev/null
> +++ b/tools/binman/test/alt_dts/model2.dts
> @@ -0,0 +1,24 @@
> +// SPDX-License-Identifier: GPL-2.0+
> +// Copyright 2024 Google LLC
> +// Written by Simon Glass <sjg at chromium.org>
> +
> +/dts-v1/;
> +
> +/ {
> + model = "Model Two";
> + compatible = "u-boot,model-two";
> +
> + /* this node remains due to bootph-pre-sram tag */
> + node {
> + some-prop;
> + prop-to-remove;
> + another-prop-to-get-rid-of;
> + not-a-prop-to-remove;
> + bootph-pre-sram;
> +
> + /* this node get removed by fdtgrep */
> + other-node {
> + another-prop;
> + };
> + };
> +};
--
Thanking You
Neha Malcom Francis
More information about the U-Boot
mailing list