@@ -49,6 +49,9 @@ class Prop:
return
self.type, self.value = self.BytesToValue(bytes)
+ def RefreshOffset(self, poffset):
+ self._offset = poffset
+
def GetPhandle(self):
"""Get a (single) phandle value from a property
@@ -161,6 +164,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:
@@ -240,8 +244,22 @@ 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('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[p.name]
+ prop.RefreshOffset(poffset)
+ poffset = fdt_obj.next_property_offset(poffset, QUIET_NOTFOUND)
+ if poffset != -libfdt.FDT_ERR_NOTFOUND:
+ raise ValueError('Internal error, poffset == %d' % poffset)
def DeleteProp(self, prop_name):
"""Delete a property of a node
@@ -285,6 +303,7 @@ class Fdt:
TODO(sjg@chromium.org): Implement the 'root' parameter
"""
+ self._cached_offsets = True
self._root = self.Node(self, None, 0, '/', '/')
self._root.Scan()
@@ -23,6 +23,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
@@ -122,6 +146,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@0')
@@ -203,13 +233,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"""
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@chromium.org> --- tools/dtoc/fdt.py | 19 +++++++++++++++++++ tools/dtoc/test_fdt.py | 39 ++++++++++++++++++++++++++++++++------- 2 files changed, 51 insertions(+), 7 deletions(-)