diff mbox series

[U-Boot,16/29] dtoc: Keep track of property offsets

Message ID 20180606004705.79641-17-sjg@chromium.org
State Superseded
Delegated to: Simon Glass
Headers show
Series binman: Add more tests and support for updating the device tree | expand

Commit Message

Simon Glass June 6, 2018, 12:46 a.m. UTC
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 mbox series

Patch

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"""