dtoc: Keep track of property offsets

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>
lime2-spi
Simon Glass 6 years ago
parent 2a2d91d0d6
commit f9b88b3a5d
  1. 20
      tools/dtoc/fdt.py
  2. 65
      tools/dtoc/test_fdt.py

@ -49,6 +49,9 @@ class Prop:
return return
self.type, self.value = self.BytesToValue(bytes) self.type, self.value = self.BytesToValue(bytes)
def RefreshOffset(self, poffset):
self._offset = poffset
def Widen(self, newprop): def Widen(self, newprop):
"""Figure out which property type is more general """Figure out which property type is more general
@ -154,6 +157,7 @@ class Prop:
Returns: Returns:
The offset of the property (struct fdt_property) within the file The offset of the property (struct fdt_property) within the file
""" """
self._node._fdt.CheckCache()
return self._node._fdt.GetStructOffset(self._offset) return self._node._fdt.GetStructOffset(self._offset)
class Node: class Node:
@ -233,8 +237,23 @@ class Node:
self._offset = my_offset self._offset = my_offset
offset = fdt_obj.first_subnode(self._offset, QUIET_NOTFOUND) offset = fdt_obj.first_subnode(self._offset, QUIET_NOTFOUND)
for subnode in self.subnodes: 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) subnode.Refresh(offset)
offset = fdt_obj.next_subnode(offset, QUIET_NOTFOUND) 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): def DeleteProp(self, prop_name):
"""Delete a property of a node """Delete a property of a node
@ -278,6 +297,7 @@ class Fdt:
TODO(sjg@chromium.org): Implement the 'root' parameter TODO(sjg@chromium.org): Implement the 'root' parameter
""" """
self._cached_offsets = True
self._root = self.Node(self, None, 0, '/', '/') self._root = self.Node(self, None, 0, '/', '/')
self._root.Scan() self._root.Scan()

@ -24,6 +24,30 @@ import libfdt
import test_util import test_util
import tools 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): class TestFdt(unittest.TestCase):
"""Tests for the Fdt module """Tests for the Fdt module
@ -124,6 +148,12 @@ class TestNode(unittest.TestCase):
with self.assertRaises(libfdt.FdtException): with self.assertRaises(libfdt.FdtException):
self.node.DeleteProp('missing') 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): def testFindNode(self):
"""Tests that we can find a node using the _FindNode() functoin""" """Tests that we can find a node using the _FindNode() functoin"""
node = self.dtb.GetRoot()._FindNode('i2c@0') node = self.dtb.GetRoot()._FindNode('i2c@0')
@ -132,6 +162,32 @@ class TestNode(unittest.TestCase):
self.assertEqual('pmic@9', subnode.name) self.assertEqual('pmic@9', subnode.name)
self.assertEqual(None, node._FindNode('missing')) 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): class TestProp(unittest.TestCase):
"""Test operation of the Prop class""" """Test operation of the Prop class"""
@ -210,13 +266,8 @@ class TestProp(unittest.TestCase):
def testGetOffset(self): def testGetOffset(self):
"""Test we can get the offset of a property""" """Test we can get the offset of a property"""
prop = self.node.props['longbytearray'] prop, value = _GetPropertyValue(self.dtb, self.node, 'longbytearray')
self.assertEqual(prop.value, value)
# 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)
def testWiden(self): def testWiden(self):
"""Test widening of values""" """Test widening of values"""

Loading…
Cancel
Save