summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--tools/binman/control.py2
-rw-r--r--tools/dtoc/fdt.py91
-rwxr-xr-xtools/dtoc/test_fdt.py8
3 files changed, 91 insertions, 10 deletions
diff --git a/tools/binman/control.py b/tools/binman/control.py
index 8c48008fc75..ded1b71109b 100644
--- a/tools/binman/control.py
+++ b/tools/binman/control.py
@@ -183,6 +183,7 @@ def Binman(options, args):
image.AddMissingProperties()
image.ProcessFdt(dtb)
+ dtb.Sync(auto_resize=True)
dtb.Pack()
dtb.Flush()
@@ -199,6 +200,7 @@ def Binman(options, args):
image.SetImagePos()
if options.update_fdt:
image.SetCalculatedProperties()
+ dtb.Sync()
image.ProcessEntryContents()
image.WriteSymbols()
image.BuildImage()
diff --git a/tools/dtoc/fdt.py b/tools/dtoc/fdt.py
index 55baa3857f7..76cd66fbf95 100644
--- a/tools/dtoc/fdt.py
+++ b/tools/dtoc/fdt.py
@@ -43,6 +43,7 @@ class Prop:
self.name = name
self.value = None
self.bytes = str(bytes)
+ self.dirty = False
if not bytes:
self.type = TYPE_BOOL
self.value = True
@@ -160,6 +161,45 @@ class Prop:
self._node._fdt.CheckCache()
return self._node._fdt.GetStructOffset(self._offset)
+ def SetInt(self, val):
+ """Set the integer value of the property
+
+ The device tree is marked dirty so that the value will be written to
+ the block on the next sync.
+
+ Args:
+ val: Integer value (32-bit, single cell)
+ """
+ self.bytes = struct.pack('>I', val);
+ self.value = val
+ self.type = TYPE_INT
+ self.dirty = True
+
+ def Sync(self, auto_resize=False):
+ """Sync property changes back to the device tree
+
+ This updates the device tree blob with any changes to this property
+ since the last sync.
+
+ Args:
+ auto_resize: Resize the device tree automatically if it does not
+ have enough space for the update
+
+ Raises:
+ FdtException if auto_resize is False and there is not enough space
+ """
+ if self._offset is None or self.dirty:
+ node = self._node
+ fdt_obj = node._fdt._fdt_obj
+ if auto_resize:
+ while fdt_obj.setprop(node.Offset(), self.name, self.bytes,
+ (libfdt.NOSPACE,)) == -libfdt.NOSPACE:
+ fdt_obj.resize(fdt_obj.totalsize() + 1024)
+ fdt_obj.setprop(node.Offset(), self.name, self.bytes)
+ else:
+ fdt_obj.setprop(node.Offset(), self.name, self.bytes)
+
+
class Node:
"""A device tree node
@@ -284,13 +324,7 @@ class Node:
Args:
prop_name: Name of property
"""
- fdt_obj = self._fdt._fdt_obj
- if fdt_obj.setprop_u32(self.Offset(), prop_name, 0,
- (libfdt.NOSPACE,)) == -libfdt.NOSPACE:
- fdt_obj.resize(fdt_obj.totalsize() + 1024)
- fdt_obj.setprop_u32(self.Offset(), prop_name, 0)
- self.props[prop_name] = Prop(self, -1, prop_name, '\0' * 4)
- self._fdt.Invalidate()
+ self.props[prop_name] = Prop(self, None, prop_name, '\0' * 4)
def SetInt(self, prop_name, val):
"""Update an integer property int the device tree.
@@ -301,8 +335,34 @@ class Node:
prop_name: Name of property
val: Value to set
"""
- fdt_obj = self._fdt._fdt_obj
- fdt_obj.setprop_u32(self.Offset(), prop_name, val)
+ self.props[prop_name].SetInt(val)
+
+ def Sync(self, auto_resize=False):
+ """Sync node changes back to the device tree
+
+ This updates the device tree blob with any changes to this node and its
+ subnodes since the last sync.
+
+ Args:
+ auto_resize: Resize the device tree automatically if it does not
+ have enough space for the update
+
+ Raises:
+ FdtException if auto_resize is False and there is not enough space
+ """
+ # Sync subnodes in reverse so that we don't disturb node offsets for
+ # nodes that are earlier in the DT. This avoids an O(n^2) rescan of
+ # node offsets.
+ for node in reversed(self.subnodes):
+ node.Sync(auto_resize)
+
+ # Sync properties now, whose offsets should not have been disturbed.
+ # We do this after subnodes, since this disturbs the offsets of these
+ # properties.
+ prop_list = sorted(self.props.values(), key=lambda prop: prop._offset,
+ reverse=True)
+ for prop in prop_list:
+ prop.Sync(auto_resize)
class Fdt:
@@ -381,6 +441,19 @@ class Fdt:
with open(self._fname, 'wb') as fd:
fd.write(self._fdt_obj.as_bytearray())
+ def Sync(self, auto_resize=False):
+ """Make sure any DT changes are written to the blob
+
+ Args:
+ auto_resize: Resize the device tree automatically if it does not
+ have enough space for the update
+
+ Raises:
+ FdtException if auto_resize is False and there is not enough space
+ """
+ self._root.Sync(auto_resize)
+ self.Invalidate()
+
def Pack(self):
"""Pack the device tree down to its minimum size
diff --git a/tools/dtoc/test_fdt.py b/tools/dtoc/test_fdt.py
index e88d19f80ef..4a67f8949df 100755
--- a/tools/dtoc/test_fdt.py
+++ b/tools/dtoc/test_fdt.py
@@ -337,6 +337,7 @@ class TestProp(unittest.TestCase):
self.node.AddZeroProp('one')
self.node.AddZeroProp('two')
self.node.AddZeroProp('three')
+ self.dtb.Sync(auto_resize=True)
# Updating existing properties should be OK, since the device-tree size
# does not change
@@ -344,12 +345,17 @@ class TestProp(unittest.TestCase):
self.node.SetInt('one', 1)
self.node.SetInt('two', 2)
self.node.SetInt('three', 3)
+ self.dtb.Sync(auto_resize=False)
# This should fail since it would need to increase the device-tree size
+ self.node.AddZeroProp('four')
with self.assertRaises(libfdt.FdtException) as e:
- self.node.SetInt('four', 4)
+ self.dtb.Sync(auto_resize=False)
self.assertIn('FDT_ERR_NOSPACE', str(e.exception))
+ def testAddNode(self):
+ self.fdt.pack()
+
class TestFdtUtil(unittest.TestCase):
"""Tests for the fdt_util module