[PATCH 10/12] dtoc: Support copying the contents of a node into another

Simon Glass sjg at chromium.org
Wed Jun 28 13:41:43 CEST 2023


This permits implementation of a simple templating system, where a node
can be reused as a base for others.

For now this adds new subnodes after any existing ones.

Signed-off-by: Simon Glass <sjg at chromium.org>
---

 tools/dtoc/fdt.py                    | 22 ++++++++++++++
 tools/dtoc/test/dtoc_test_simple.dts |  3 ++
 tools/dtoc/test_fdt.py               | 43 ++++++++++++++++++++++++++++
 3 files changed, 68 insertions(+)

diff --git a/tools/dtoc/fdt.py b/tools/dtoc/fdt.py
index a8e05349a720..fcf229f83036 100644
--- a/tools/dtoc/fdt.py
+++ b/tools/dtoc/fdt.py
@@ -13,6 +13,7 @@ from dtoc import fdt_util
 import libfdt
 from libfdt import QUIET_NOTFOUND
 from u_boot_pylib import tools
+from u_boot_pylib import tout
 
 # This deals with a device tree, presenting it as an assortment of Node and
 # Prop objects, representing nodes and properties, respectively. This file
@@ -635,6 +636,27 @@ class Node:
             prop.Sync(auto_resize)
         return added
 
+    def copy_node(self, src):
+        """Copy a node and all its subnodes into this node
+
+        Args:
+            src (Node): Node to copy
+
+        This works recursively.
+
+        The new node is put after all other nodes. If the node already
+        exists, just its properties are copied. Properties which exist in the
+        destination node already are not copied.
+        """
+        dst = self.FindNode(src.name)
+        if not dst:
+            dst = self.AddSubnode(src.name)
+        for name, src_prop in src.props.items():
+            if name not in dst.props:
+                dst.props[name] = Prop(dst, None, name, src_prop.bytes)
+        for node in src.subnodes:
+            dst.copy_node(node)
+
 
 class Fdt:
     """Provides simple access to a flat device tree blob using libfdts.
diff --git a/tools/dtoc/test/dtoc_test_simple.dts b/tools/dtoc/test/dtoc_test_simple.dts
index 08f667ee5a10..c51f1a5908ce 100644
--- a/tools/dtoc/test/dtoc_test_simple.dts
+++ b/tools/dtoc/test/dtoc_test_simple.dts
@@ -45,6 +45,9 @@
 		stringarray = "one";
 		longbytearray = [09 0a 0b 0c 0d 0e 0f 10];
 		maybe-empty-int = <1>;
+
+		first-node {
+		};
 	};
 
 	i2c at 0 {
diff --git a/tools/dtoc/test_fdt.py b/tools/dtoc/test_fdt.py
index 4fe8d12c403a..5d9d99eb384b 100755
--- a/tools/dtoc/test_fdt.py
+++ b/tools/dtoc/test_fdt.py
@@ -306,6 +306,49 @@ class TestNode(unittest.TestCase):
         self.assertIn("Internal error, node '/spl-test' name mismatch 'i2c at 0'",
                       str(exc.exception))
 
+    def test_copy_node(self):
+        """Test copy_node() function"""
+        tmpl = self.dtb.GetNode('/i2c at 0')
+        dst = self.dtb.GetNode('/spl-test3')
+        dst.copy_node(tmpl)
+
+        self.assertEqual(['/spl-test3/first-node', '/spl-test3/i2c at 0'],
+                         [n.path for n in dst.subnodes])
+
+        chk = self.dtb.GetNode('/spl-test3/i2c at 0')
+        self.assertTrue(chk)
+        self.assertEqual(
+            {'bootph-all', 'compatible', '#address-cells', '#size-cells'},
+            chk.props.keys())
+
+        # Check the first property
+        prop = chk.props['bootph-all']
+        self.assertEqual('bootph-all', prop.name)
+        self.assertEqual(True, prop.value)
+        self.assertIsNone(prop._offset)
+        self.assertEqual(chk.path, prop._node.path)
+
+        # Check the second property
+        prop = chk.props['compatible']
+        self.assertEqual('compatible', prop.name)
+        self.assertEqual('sandbox,i2c', prop.value)
+        self.assertIsNone(prop._offset)
+        self.assertEqual(chk.path, prop._node.path)
+
+        pmic = chk.FindNode('pmic at 9')
+        self.assertTrue(chk)
+
+        pmic = self.dtb.GetNode('/spl-test3/i2c at 0/pmic at 9')
+        self.assertTrue(pmic)
+        self.assertEqual([pmic], chk.subnodes)
+        self.assertEqual(chk, pmic.parent)
+        self.assertIsNone(pmic._offset)
+        self.assertEqual(
+            {'bootph-all', 'compatible', 'reg', 'low-power'},
+            pmic.props.keys())
+
+        self.dtb.Sync(auto_resize=True)
+
 
 class TestProp(unittest.TestCase):
     """Test operation of the Prop class"""
-- 
2.41.0.162.gfafddb0af9-goog



More information about the U-Boot mailing list