summaryrefslogtreecommitdiff
path: root/tools/dtoc/fdt.py
diff options
context:
space:
mode:
Diffstat (limited to 'tools/dtoc/fdt.py')
-rw-r--r--tools/dtoc/fdt.py92
1 files changed, 72 insertions, 20 deletions
diff --git a/tools/dtoc/fdt.py b/tools/dtoc/fdt.py
index 25ce5136eb..3996971e39 100644
--- a/tools/dtoc/fdt.py
+++ b/tools/dtoc/fdt.py
@@ -103,6 +103,8 @@ class Prop:
"""A device tree property
Properties:
+ node: Node containing this property
+ offset: Offset of the property (None if still to be synced)
name: Property name (as per the device tree)
value: Property value as a string of bytes, or a list of strings of
bytes
@@ -114,7 +116,7 @@ class Prop:
self.name = name
self.value = None
self.bytes = bytes(data)
- self.dirty = False
+ self.dirty = offset is None
if not data:
self.type = Type.BOOL
self.value = True
@@ -228,9 +230,14 @@ class Prop:
Raises:
FdtException if auto_resize is False and there is not enough space
"""
- if self._offset is None or self.dirty:
+ if self.dirty:
node = self._node
fdt_obj = node._fdt._fdt_obj
+ node_name = fdt_obj.get_name(node._offset)
+ if node_name and node_name != node.name:
+ raise ValueError("Internal error, node '%s' name mismatch '%s'" %
+ (node.path, node_name))
+
if auto_resize:
while fdt_obj.setprop(node.Offset(), self.name, self.bytes,
(libfdt.NOSPACE,)) == -libfdt.NOSPACE:
@@ -239,13 +246,15 @@ class Prop:
fdt_obj.setprop(node.Offset(), self.name, self.bytes)
else:
fdt_obj.setprop(node.Offset(), self.name, self.bytes)
+ self.dirty = False
class Node:
"""A device tree node
Properties:
- offset: Integer offset in the device tree
+ parent: Parent Node
+ offset: Integer offset in the device tree (None if to be synced)
name: Device tree node tname
path: Full path to node, along with the node name itself
_fdt: Device tree object
@@ -324,6 +333,11 @@ class Node:
fdt_obj = self._fdt._fdt_obj
if self._offset != my_offset:
self._offset = my_offset
+ name = fdt_obj.get_name(self._offset)
+ if name and self.name != name:
+ raise ValueError("Internal error, node '%s' name mismatch '%s'" %
+ (self.path, name))
+
offset = fdt_obj.first_subnode(self._offset, QUIET_NOTFOUND)
for subnode in self.subnodes:
if subnode.name != fdt_obj.get_name(offset):
@@ -339,8 +353,8 @@ class Node:
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))
+ raise ValueError("Internal error, node '%s' property '%s' missing, "
+ 'offset %d' % (self.path, p.name, poffset))
prop.RefreshOffset(poffset)
poffset = fdt_obj.next_property_offset(poffset, QUIET_NOTFOUND)
@@ -447,8 +461,13 @@ class Node:
Args:
prop_name: Name of property to add
val: Bytes value of property
+
+ Returns:
+ Prop added
"""
- self.props[prop_name] = Prop(self, None, prop_name, val)
+ prop = Prop(self, None, prop_name, val)
+ self.props[prop_name] = prop
+ return prop
def AddString(self, prop_name, val):
"""Add a new string property to a node
@@ -459,9 +478,12 @@ class Node:
Args:
prop_name: Name of property to add
val: String value of property
+
+ Returns:
+ Prop added
"""
val = bytes(val, 'utf-8')
- self.AddData(prop_name, val + b'\0')
+ return self.AddData(prop_name, val + b'\0')
def AddInt(self, prop_name, val):
"""Add a new integer property to a node
@@ -472,8 +494,11 @@ class Node:
Args:
prop_name: Name of property to add
val: Integer value of property
+
+ Returns:
+ Prop added
"""
- self.AddData(prop_name, struct.pack('>I', val))
+ return self.AddData(prop_name, struct.pack('>I', val))
def AddSubnode(self, name):
"""Add a new subnode to the node
@@ -499,9 +524,13 @@ class Node:
auto_resize: Resize the device tree automatically if it does not
have enough space for the update
+ Returns:
+ True if the node had to be added, False if it already existed
+
Raises:
FdtException if auto_resize is False and there is not enough space
"""
+ added = False
if self._offset is None:
# The subnode doesn't exist yet, so add it
fdt_obj = self._fdt._fdt_obj
@@ -515,23 +544,45 @@ class Node:
else:
offset = fdt_obj.add_subnode(self.parent._offset, self.name)
self._offset = offset
+ added = True
- # 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.
+ # Sync the existing subnodes first, so that we can rely on the offsets
+ # being correct. As soon as we add new subnodes, it pushes all the
+ # existing subnodes up.
for node in reversed(self.subnodes):
- node.Sync(auto_resize)
+ if node._offset is not None:
+ 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. Note that new properties will have an offset of None here,
- # which Python 3 cannot sort against int. So use a large value instead
- # to ensure that the new properties are added first.
+ # Sync subnodes in reverse so that we get the expected order. Each
+ # new node goes at the start of the subnode list. This avoids an O(n^2)
+ # rescan of node offsets.
+ num_added = 0
+ for node in reversed(self.subnodes):
+ if node.Sync(auto_resize):
+ num_added += 1
+ if num_added:
+ # Reorder our list of nodes to put the new ones first, since that's
+ # what libfdt does
+ old_count = len(self.subnodes) - num_added
+ subnodes = self.subnodes[old_count:] + self.subnodes[:old_count]
+ self.subnodes = subnodes
+
+ # Sync properties now, whose offsets should not have been disturbed,
+ # since properties come before subnodes. This is done after all the
+ # subnode processing above, since updating properties can disturb the
+ # offsets of those subnodes.
+ # Properties are synced in reverse order, with new properties added
+ # before existing properties are synced. This ensures that the offsets
+ # of earlier properties are not disturbed.
+ # Note that new properties will have an offset of None here, which
+ # Python cannot sort against int. So use a large value instead so that
+ # new properties are added first.
prop_list = sorted(self.props.values(),
key=lambda prop: prop._offset or 1 << 31,
reverse=True)
for prop in prop_list:
prop.Sync(auto_resize)
+ return added
class Fdt:
@@ -642,8 +693,9 @@ class Fdt:
Raises:
FdtException if auto_resize is False and there is not enough space
"""
+ self.CheckCache()
self._root.Sync(auto_resize)
- self.Invalidate()
+ self.Refresh()
def Pack(self):
"""Pack the device tree down to its minimum size
@@ -652,7 +704,7 @@ class Fdt:
build up in the device tree binary.
"""
CheckErr(self._fdt_obj.pack(), 'pack')
- self.Invalidate()
+ self.Refresh()
def GetContents(self):
"""Get the contents of the FDT
@@ -704,11 +756,11 @@ class Fdt:
if self._cached_offsets:
return
self.Refresh()
- self._cached_offsets = True
def Refresh(self):
"""Refresh the offset cache"""
self._root.Refresh(0)
+ self._cached_offsets = True
def GetStructOffset(self, offset):
"""Get the file offset of a given struct offset