[PATCH v5 14/20] dtoc: Allow inserting a list of nodes into another

Simon Glass sjg at chromium.org
Tue Jul 18 15:24:03 CEST 2023


Provide a way to specify a phandle list of nodes which are to be inserted
into an existing node.

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

(no changes since v4)

Changes in v4:
- Support copying over properties from each template node
- Make sure phandles are not copied

Changes in v3:
- Adjust to use the new example file

 tools/dtoc/fdt.py                  | 22 +++++++++++++++++
 tools/dtoc/test/dtoc_test_copy.dts | 14 ++++++++++-
 tools/dtoc/test_fdt.py             | 39 ++++++++++++++++++++++++++++++
 3 files changed, 74 insertions(+), 1 deletion(-)

diff --git a/tools/dtoc/fdt.py b/tools/dtoc/fdt.py
index f4d84083e491..fd0f3e94f5c0 100644
--- a/tools/dtoc/fdt.py
+++ b/tools/dtoc/fdt.py
@@ -748,6 +748,28 @@ class Node:
             dst.copy_node(node)
         return dst
 
+    def copy_subnodes_from_phandles(self, phandle_list):
+        """Copy subnodes of a list of nodes into another node
+
+        Args:
+            phandle_list (list of int): List of phandles of nodes to copy
+
+        For each node in the phandle list, its subnodes and their properties are
+        copied recursively. Note that it does not copy the node itself, nor its
+        properties.
+        """
+        # Process in reverse order, since new nodes are inserted at the start of
+        # the destination's node list. We want them to appear in order of the
+        # phandle list
+        for phandle in phandle_list.__reversed__():
+            parent = self.GetFdt().LookupPhandle(phandle)
+            tout.debug(f'adding template {parent.path} to node {self.path}')
+            for node in parent.subnodes.__reversed__():
+                dst = self.copy_node(node)
+
+            tout.debug(f'merge props from {parent.path} to {dst.path}')
+            self.merge_props(parent)
+
 
 class Fdt:
     """Provides simple access to a flat device tree blob using libfdts.
diff --git a/tools/dtoc/test/dtoc_test_copy.dts b/tools/dtoc/test/dtoc_test_copy.dts
index 85e2c342a7ed..36faa9b72b56 100644
--- a/tools/dtoc/test/dtoc_test_copy.dts
+++ b/tools/dtoc/test/dtoc_test_copy.dts
@@ -11,6 +11,7 @@
 	#address-cells = <1>;
 	#size-cells = <1>;
 	reference = <&over>;	/* nake sure that the 'over' phandle exists */
+	copy-list = <&another &base>;
 
 	dest {
 		bootph-all;
@@ -46,7 +47,7 @@
 		};
 	};
 
-	base {
+	base: base {
 		compatible = "sandbox,i2c";
 		bootph-all;
 		#address-cells = <1>;
@@ -73,4 +74,15 @@
 			};
 		};
 	};
+
+	another: another {
+		new-prop = "hello";
+		earlier {
+			wibble = <2>;
+		};
+
+		later {
+			fibble = <3>;
+		};
+	};
 };
diff --git a/tools/dtoc/test_fdt.py b/tools/dtoc/test_fdt.py
index ebc5297b5067..3e54694eec9f 100755
--- a/tools/dtoc/test_fdt.py
+++ b/tools/dtoc/test_fdt.py
@@ -380,6 +380,45 @@ class TestNode(unittest.TestCase):
         dst = new_dtb.GetNode('/dest')
         do_copy_checks(new_dtb, dst, expect_none=False)
 
+    def test_copy_subnodes_from_phandles(self):
+        """Test copy_node() function"""
+        dtb = fdt.FdtScan(find_dtb_file('dtoc_test_copy.dts'))
+
+        orig = dtb.GetNode('/')
+        node_list = fdt_util.GetPhandleList(orig, 'copy-list')
+
+        dst = dtb.GetNode('/dest')
+        dst.copy_subnodes_from_phandles(node_list)
+
+        pmic = dtb.GetNode('/dest/over')
+        self.assertTrue(pmic)
+
+        subn = dtb.GetNode('/dest/first at 0')
+        self.assertTrue(subn)
+        self.assertEqual({'a-prop', 'b-prop', 'reg'}, subn.props.keys())
+
+        self.assertEqual(
+            ['/dest/earlier', '/dest/later', '/dest/over', '/dest/first at 0',
+             '/dest/second', '/dest/existing', '/dest/base'],
+            [n.path for n in dst.subnodes])
+
+        # Make sure that the phandle for 'over' is not copied
+        over = dst.FindNode('over')
+        print('keys', over.props.keys())
+        self.assertNotIn('phandle', over.props.keys())
+
+        # Check the merged properties, first the base ones in '/dest'
+        expect = {'bootph-all', 'compatible', 'stringarray', 'longbytearray',
+                  'maybe-empty-int'}
+
+        # Properties from 'base'
+        expect.update({'#address-cells', '#size-cells'})
+
+        # Properties from 'another'
+        expect.add('new-prop')
+
+        self.assertEqual(expect, set(dst.props.keys()))
+
 
 class TestProp(unittest.TestCase):
     """Test operation of the Prop class"""
-- 
2.41.0.455.g037347b96a-goog



More information about the U-Boot mailing list