Re: [U-Boot] [PATCH v2 16/29] dtoc: Keep track of property offsets

2018-07-09 Thread Simon Glass
On 6 July 2018 at 10:27, Simon Glass  wrote:
> 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 
> ---
>
> Changes in v2: None
>
>  tools/dtoc/fdt.py  | 20 +
>  tools/dtoc/test_fdt.py | 65 +-
>  2 files changed, 78 insertions(+), 7 deletions(-)
>

Applied to u-boot-dm.
___
U-Boot mailing list
U-Boot@lists.denx.de
https://lists.denx.de/listinfo/u-boot


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

2018-07-06 Thread Simon Glass
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 
---

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(s...@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@0')
@@ -132,6 +162,32 @@ class TestNode(unittest.TestCase):
 self.assertEqual('pmic@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()
+