Merge tag 'dm-pull-9jul19-take2' of https://gitlab.denx.de/u-boot/custodians/u-boot-dm
[oweals/u-boot.git] / tools / binman / state.py
index 5f25b907b9ef9873594ce4159029728fc362ef8f..af9678649cd7187cac9d21140b2b3f9942f531dc 100644 (file)
@@ -5,8 +5,8 @@
 # Holds and modifies the state information held by binman
 #
 
+import hashlib
 import re
-from sets import Set
 
 import os
 import tools
@@ -18,11 +18,15 @@ fdt_files = {}
 # Arguments passed to binman to provide arguments to entries
 entry_args = {}
 
+# True to use fake device-tree files for testing (see U_BOOT_DTB_DATA in
+# ftest.py)
+use_fake_dtb = False
+
 # Set of all device tree files references by images
-fdt_set = Set()
+fdt_set = set()
 
 # Same as above, but excluding the main one
-fdt_subset = Set()
+fdt_subset = set()
 
 # The DTB which contains the full image information
 main_dtb = None
@@ -55,6 +59,29 @@ def GetFdtPath(fname):
     """
     return fdt_files[fname]._fname
 
+def GetFdtContents(fname):
+    """Looks up the FDT pathname and contents
+
+    This is used to obtain the Fdt pathname and contents when needed by an
+    entry. It supports a 'fake' dtb, allowing tests to substitute test data for
+    the real dtb.
+
+    Args:
+        fname: Filename to look up (e.g. 'u-boot.dtb').
+
+    Returns:
+        tuple:
+            pathname to Fdt
+            Fdt data (as bytes)
+    """
+    if fname in fdt_files and not use_fake_dtb:
+        pathname = GetFdtPath(fname)
+        data = GetFdt(fname).GetContents()
+    else:
+        pathname = tools.GetInputFilename(fname)
+        data = tools.ReadFile(pathname)
+    return pathname, data
+
 def SetEntryArgs(args):
     """Set the value of the entry args
 
@@ -85,13 +112,14 @@ def GetEntryArg(name):
     """
     return entry_args.get(name)
 
-def Prepare(dtb):
+def Prepare(images, dtb):
     """Get device tree files ready for use
 
     This sets up a set of device tree files that can be retrieved by GetFdts().
     At present there is only one, that for U-Boot proper.
 
     Args:
+        images: List of images being used
         dtb: Main dtb
     """
     global fdt_set, fdt_subset, fdt_files, main_dtb
@@ -107,8 +135,19 @@ def Prepare(dtb):
     main_dtb = dtb
     fdt_files.clear()
     fdt_files['u-boot.dtb'] = dtb
-    fdt_set = Set()
-    fdt_subset = Set()
+    fdt_subset = set()
+    if not use_fake_dtb:
+        for image in images.values():
+            fdt_subset.update(image.GetFdtSet())
+        fdt_subset.discard('u-boot.dtb')
+        for other_fname in fdt_subset:
+            infile = tools.GetInputFilename(other_fname)
+            other_fname_dtb = fdt_util.EnsureCompiled(infile)
+            out_fname = tools.GetOutputFilename('%s.out' %
+                    os.path.split(other_fname)[1])
+            tools.WriteFile(out_fname, tools.ReadFile(other_fname_dtb))
+            other_dtb = fdt.FdtScan(out_fname)
+            fdt_files[other_fname] = other_dtb
 
 def GetFdts():
     """Yield all device tree files being used by binman
@@ -117,6 +156,8 @@ def GetFdts():
         Device trees being used (U-Boot proper, SPL, TPL)
     """
     yield main_dtb
+    for other_fname in fdt_subset:
+        yield fdt_files[other_fname]
 
 def GetUpdateNodes(node):
     """Yield all the nodes that need to be updated in all device trees
@@ -133,6 +174,11 @@ def GetUpdateNodes(node):
             is node, SPL and TPL)
     """
     yield node
+    for dtb in fdt_files.values():
+        if dtb != node.GetFdt():
+            other_node = dtb.GetNode(node.path)
+            if other_node:
+                yield other_node
 
 def AddZeroProp(node, prop):
     """Add a new property to affected device trees with an integer value of 0.
@@ -143,6 +189,33 @@ def AddZeroProp(node, prop):
     for n in GetUpdateNodes(node):
         n.AddZeroProp(prop)
 
+def AddSubnode(node, name):
+    """Add a new subnode to a node in affected device trees
+
+    Args:
+        node: Node to add to
+        name: name of node to add
+
+    Returns:
+        New subnode that was created in main tree
+    """
+    first = None
+    for n in GetUpdateNodes(node):
+        subnode = n.AddSubnode(name)
+        if not first:
+            first = subnode
+    return first
+
+def AddString(node, prop, value):
+    """Add a new string property to affected device trees
+
+    Args:
+        prop_name: Name of property
+        value: String value (which will be \0-terminated in the DT)
+    """
+    for n in GetUpdateNodes(node):
+        n.AddString(prop, value)
+
 def SetInt(node, prop, value):
     """Update an integer property in affected device trees with an integer value
 
@@ -153,3 +226,27 @@ def SetInt(node, prop, value):
     """
     for n in GetUpdateNodes(node):
         n.SetInt(prop, value)
+
+def CheckAddHashProp(node):
+    hash_node = node.FindNode('hash')
+    if hash_node:
+        algo = hash_node.props.get('algo')
+        if not algo:
+            return "Missing 'algo' property for hash node"
+        if algo.value == 'sha256':
+            size = 32
+        else:
+            return "Unknown hash algorithm '%s'" % algo
+        for n in GetUpdateNodes(hash_node):
+            n.AddEmptyProp('value', size)
+
+def CheckSetHashValue(node, get_data_func):
+    hash_node = node.FindNode('hash')
+    if hash_node:
+        algo = hash_node.props.get('algo').value
+        if algo == 'sha256':
+            m = hashlib.sha256()
+            m.update(get_data_func())
+            data = m.digest()
+        for n in GetUpdateNodes(hash_node):
+            n.SetData('value', data)