From 346179f0d3383e88f7df117b13820df70f68c74a Mon Sep 17 00:00:00 2001
From: Simon Glass <sjg@chromium.org>
Date: Mon, 25 Jul 2016 18:59:12 -0600
Subject: [PATCH] dtoc: Prepare for supporting changing of device trees

For binman we need to support deleting properties in the device tree. This
will change the offsets of nodes after the deletion. In preparation, add
code to keep track of when the offsets are invalid, and regenerate them.

Signed-off-by: Simon Glass <sjg@chromium.org>
---
 tools/dtoc/fdt_normal.py | 46 ++++++++++++++++++++++++++++++++++++----
 1 file changed, 42 insertions(+), 4 deletions(-)

diff --git a/tools/dtoc/fdt_normal.py b/tools/dtoc/fdt_normal.py
index d9ba4aca80a..4a667a115d6 100644
--- a/tools/dtoc/fdt_normal.py
+++ b/tools/dtoc/fdt_normal.py
@@ -53,15 +53,24 @@ class Node(NodeBase):
     def __init__(self, fdt, offset, name, path):
         NodeBase.__init__(self, fdt, offset, name, path)
 
+    def Offset(self):
+        """Returns the offset of a node, after checking the cache
+
+        This should be used instead of self._offset directly, to ensure that
+        the cache does not contain invalid offsets.
+        """
+        self._fdt.CheckCache()
+        return self._offset
+
     def Scan(self):
         """Scan a node's properties and subnodes
 
         This fills in the props and subnodes properties, recursively
         searching into subnodes so that the entire tree is built.
         """
-        self.props = self._fdt.GetProps(self.path)
+        self.props = self._fdt.GetProps(self, self.path)
 
-        offset = libfdt.fdt_first_subnode(self._fdt.GetFdt(), self._offset)
+        offset = libfdt.fdt_first_subnode(self._fdt.GetFdt(), self.Offset())
         while offset >= 0:
             sep = '' if self.path[-1] == '/' else '/'
             name = libfdt.Name(self._fdt.GetFdt(), offset)
@@ -72,6 +81,19 @@ class Node(NodeBase):
             node.Scan()
             offset = libfdt.fdt_next_subnode(self._fdt.GetFdt(), offset)
 
+    def Refresh(self, my_offset):
+        """Fix up the _offset for each node, recursively
+
+        Note: This does not take account of property offsets - these will not
+        be updated.
+        """
+        if self._offset != my_offset:
+            #print '%s: %d -> %d\n' % (self.path, self._offset, my_offset)
+            self._offset = my_offset
+        offset = libfdt.fdt_first_subnode(self._fdt.GetFdt(), self._offset)
+        for subnode in self.subnodes:
+            subnode.Refresh(offset)
+            offset = libfdt.fdt_next_subnode(self._fdt.GetFdt(), offset)
 
 class FdtNormal(Fdt):
     """Provides simple access to a flat device tree blob using libfdt.
@@ -83,6 +105,7 @@ class FdtNormal(Fdt):
     """
     def __init__(self, fname):
         Fdt.__init__(self, fname)
+        self._cached_offsets = False
         if self._fname:
             self._fname = fdt_util.EnsureCompiled(self._fname)
 
@@ -97,7 +120,7 @@ class FdtNormal(Fdt):
         """
         return self._fdt
 
-    def GetProps(self, node):
+    def GetProps(self, node, path):
         """Get all properties from a node.
 
         Args:
@@ -110,7 +133,7 @@ class FdtNormal(Fdt):
         Raises:
             ValueError: if the node does not exist.
         """
-        offset = libfdt.fdt_path_offset(self._fdt, node)
+        offset = libfdt.fdt_path_offset(self._fdt, path)
         if offset < 0:
             libfdt.Raise(offset)
         props_dict = {}
@@ -124,6 +147,21 @@ class FdtNormal(Fdt):
             poffset = libfdt.fdt_next_property_offset(self._fdt, poffset)
         return props_dict
 
+    def Invalidate(self):
+        """Mark our offset cache as invalid"""
+        self._cached_offsets = False
+
+    def CheckCache(self):
+        """Refresh the offset cache if needed"""
+        if self._cached_offsets:
+            return
+        self.Refresh()
+        self._cached_offsets = True
+
+    def Refresh(self):
+        """Refresh the offset cache"""
+        self._root.Refresh(0)
+
     @classmethod
     def Node(self, fdt, offset, name, path):
         """Create a new node
-- 
GitLab