
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@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@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@0'", str(exc.exception))
+ def test_copy_node(self): + """Test copy_node() function""" + tmpl = self.dtb.GetNode('/i2c@0') + dst = self.dtb.GetNode('/spl-test3') + dst.copy_node(tmpl) + + self.assertEqual(['/spl-test3/first-node', '/spl-test3/i2c@0'], + [n.path for n in dst.subnodes]) + + chk = self.dtb.GetNode('/spl-test3/i2c@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@9') + self.assertTrue(chk) + + pmic = self.dtb.GetNode('/spl-test3/i2c@0/pmic@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"""