[U-Boot] [PATCH v2 16/29] dtoc: Keep track of property offsets
Simon Glass
sjg at chromium.org
Fri Jul 6 16:27:29 UTC 2018
At present the Fdt class does not keep track of property offsets if they
change due to removal of properties. Update the code to handle this, and
add a test.
Signed-off-by: Simon Glass <sjg at chromium.org>
---
Changes in v2: None
tools/dtoc/fdt.py | 20 +++++++++++++
tools/dtoc/test_fdt.py | 65 +++++++++++++++++++++++++++++++++++++-----
2 files changed, 78 insertions(+), 7 deletions(-)
diff --git a/tools/dtoc/fdt.py b/tools/dtoc/fdt.py
index fd016bb8ce..274c142e7a 100644
--- a/tools/dtoc/fdt.py
+++ b/tools/dtoc/fdt.py
@@ -49,6 +49,9 @@ class Prop:
return
self.type, self.value = self.BytesToValue(bytes)
+ def RefreshOffset(self, poffset):
+ self._offset = poffset
+
def Widen(self, newprop):
"""Figure out which property type is more general
@@ -154,6 +157,7 @@ class Prop:
Returns:
The offset of the property (struct fdt_property) within the file
"""
+ self._node._fdt.CheckCache()
return self._node._fdt.GetStructOffset(self._offset)
class Node:
@@ -233,8 +237,23 @@ class Node:
self._offset = my_offset
offset = fdt_obj.first_subnode(self._offset, QUIET_NOTFOUND)
for subnode in self.subnodes:
+ if subnode.name != fdt_obj.get_name(offset):
+ raise ValueError('Internal error, node name mismatch %s != %s' %
+ (subnode.name, fdt_obj.get_name(offset)))
subnode.Refresh(offset)
offset = fdt_obj.next_subnode(offset, QUIET_NOTFOUND)
+ if offset != -libfdt.FDT_ERR_NOTFOUND:
+ raise ValueError('Internal error, offset == %d' % offset)
+
+ poffset = fdt_obj.first_property_offset(self._offset, QUIET_NOTFOUND)
+ while poffset >= 0:
+ p = fdt_obj.get_property_by_offset(poffset)
+ prop = self.props.get(p.name)
+ if not prop:
+ raise ValueError("Internal error, property '%s' missing, "
+ 'offset %d' % (p.name, poffset))
+ prop.RefreshOffset(poffset)
+ poffset = fdt_obj.next_property_offset(poffset, QUIET_NOTFOUND)
def DeleteProp(self, prop_name):
"""Delete a property of a node
@@ -278,6 +297,7 @@ class Fdt:
TODO(sjg at chromium.org): Implement the 'root' parameter
"""
+ self._cached_offsets = True
self._root = self.Node(self, None, 0, '/', '/')
self._root.Scan()
diff --git a/tools/dtoc/test_fdt.py b/tools/dtoc/test_fdt.py
index d44e4dd842..e57298dbe7 100755
--- a/tools/dtoc/test_fdt.py
+++ b/tools/dtoc/test_fdt.py
@@ -24,6 +24,30 @@ import libfdt
import test_util
import tools
+def _GetPropertyValue(dtb, node, prop_name):
+ """Low-level function to get the property value based on its offset
+
+ This looks directly in the device tree at the property's offset to find
+ its value. It is useful as a check that the property is in the correct
+ place.
+
+ Args:
+ node: Node to look in
+ prop_name: Property name to find
+
+ Returns:
+ Tuple:
+ Prop object found
+ Value of property as a string (found using property offset)
+ """
+ prop = node.props[prop_name]
+
+ # Add 12, which is sizeof(struct fdt_property), to get to start of data
+ offset = prop.GetOffset() + 12
+ data = dtb.GetContents()[offset:offset + len(prop.value)]
+ return prop, [chr(x) for x in data]
+
+
class TestFdt(unittest.TestCase):
"""Tests for the Fdt module
@@ -124,6 +148,12 @@ class TestNode(unittest.TestCase):
with self.assertRaises(libfdt.FdtException):
self.node.DeleteProp('missing')
+ def testDeleteGetOffset(self):
+ """Test that property offset update when properties are deleted"""
+ self.node.DeleteProp('intval')
+ prop, value = _GetPropertyValue(self.dtb, self.node, 'longbytearray')
+ self.assertEqual(prop.value, value)
+
def testFindNode(self):
"""Tests that we can find a node using the _FindNode() functoin"""
node = self.dtb.GetRoot()._FindNode('i2c at 0')
@@ -132,6 +162,32 @@ class TestNode(unittest.TestCase):
self.assertEqual('pmic at 9', subnode.name)
self.assertEqual(None, node._FindNode('missing'))
+ def testRefreshMissingNode(self):
+ """Test refreshing offsets when an extra node is present in dtb"""
+ # Delete it from our tables, not the device tree
+ del self.dtb._root.subnodes[-1]
+ with self.assertRaises(ValueError) as e:
+ self.dtb.Refresh()
+ self.assertIn('Internal error, offset', str(e.exception))
+
+ def testRefreshExtraNode(self):
+ """Test refreshing offsets when an expected node is missing"""
+ # Delete it from the device tre, not our tables
+ self.dtb.GetFdtObj().del_node(self.node.Offset())
+ with self.assertRaises(ValueError) as e:
+ self.dtb.Refresh()
+ self.assertIn('Internal error, node name mismatch '
+ 'spl-test != spl-test2', str(e.exception))
+
+ def testRefreshMissingProp(self):
+ """Test refreshing offsets when an extra property is present in dtb"""
+ # Delete it from our tables, not the device tree
+ del self.node.props['notstring']
+ with self.assertRaises(ValueError) as e:
+ self.dtb.Refresh()
+ self.assertIn("Internal error, property 'notstring' missing, offset ",
+ str(e.exception))
+
class TestProp(unittest.TestCase):
"""Test operation of the Prop class"""
@@ -210,13 +266,8 @@ class TestProp(unittest.TestCase):
def testGetOffset(self):
"""Test we can get the offset of a property"""
- prop = self.node.props['longbytearray']
-
- # Add 12, which is sizeof(struct fdt_property), to get to start of data
- offset = prop.GetOffset() + 12
- data = self.dtb.GetContents()[offset:offset + len(prop.value)]
- bytes = [chr(x) for x in data]
- self.assertEqual(bytes, prop.value)
+ prop, value = _GetPropertyValue(self.dtb, self.node, 'longbytearray')
+ self.assertEqual(prop.value, value)
def testWiden(self):
"""Test widening of values"""
--
2.18.0.203.gfac676dfb9-goog
More information about the U-Boot
mailing list