dtoc: Allow inserting a list of nodes into another

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@chromium.org>
This commit is contained in:
Simon Glass 2023-07-18 07:24:03 -06:00
parent 4df457b657
commit 55e1278d5e
3 changed files with 74 additions and 1 deletions

View file

@ -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.

View file

@ -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>;
};
};
};

View file

@ -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@0')
self.assertTrue(subn)
self.assertEqual({'a-prop', 'b-prop', 'reg'}, subn.props.keys())
self.assertEqual(
['/dest/earlier', '/dest/later', '/dest/over', '/dest/first@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"""