
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(-)
diff --git a/tools/dtoc/fdt.py b/tools/dtoc/fdt.py index e24acf12804..2d7b6328f11 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 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()
diff --git a/tools/dtoc/test_fdt.py b/tools/dtoc/test_fdt.py index ba95a4b77de..cd86144896f 100755 --- a/tools/dtoc/test_fdt.py +++ b/tools/dtoc/test_fdt.py @@ -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"""