summaryrefslogtreecommitdiff
path: root/tools/binman/state.py
diff options
context:
space:
mode:
Diffstat (limited to 'tools/binman/state.py')
-rw-r--r--tools/binman/state.py253
1 files changed, 253 insertions, 0 deletions
diff --git a/tools/binman/state.py b/tools/binman/state.py
new file mode 100644
index 0000000000..d945e4bf65
--- /dev/null
+++ b/tools/binman/state.py
@@ -0,0 +1,253 @@
+# SPDX-License-Identifier: GPL-2.0+
+# Copyright 2018 Google, Inc
+# Written by Simon Glass <sjg@chromium.org>
+#
+# Holds and modifies the state information held by binman
+#
+
+import hashlib
+import re
+from sets import Set
+
+import os
+import tools
+
+# Records the device-tree files known to binman, keyed by filename (e.g.
+# 'u-boot-spl.dtb')
+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()
+
+# Same as above, but excluding the main one
+fdt_subset = Set()
+
+# The DTB which contains the full image information
+main_dtb = None
+
+def GetFdt(fname):
+ """Get the Fdt object for a particular device-tree filename
+
+ Binman keeps track of at least one device-tree file called u-boot.dtb but
+ can also have others (e.g. for SPL). This function looks up the given
+ filename and returns the associated Fdt object.
+
+ Args:
+ fname: Filename to look up (e.g. 'u-boot.dtb').
+
+ Returns:
+ Fdt object associated with the filename
+ """
+ return fdt_files[fname]
+
+def GetFdtPath(fname):
+ """Get the full pathname of a particular Fdt object
+
+ Similar to GetFdt() but returns the pathname associated with the Fdt.
+
+ Args:
+ fname: Filename to look up (e.g. 'u-boot.dtb').
+
+ Returns:
+ Full path name to the associated Fdt
+ """
+ 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
+
+ This sets up the entry_args dict which is used to supply entry arguments to
+ entries.
+
+ Args:
+ args: List of entry arguments, each in the format "name=value"
+ """
+ global entry_args
+
+ entry_args = {}
+ if args:
+ for arg in args:
+ m = re.match('([^=]*)=(.*)', arg)
+ if not m:
+ raise ValueError("Invalid entry arguemnt '%s'" % arg)
+ entry_args[m.group(1)] = m.group(2)
+
+def GetEntryArg(name):
+ """Get the value of an entry argument
+
+ Args:
+ name: Name of argument to retrieve
+
+ Returns:
+ String value of argument
+ """
+ return entry_args.get(name)
+
+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
+ # Import these here in case libfdt.py is not available, in which case
+ # the above help option still works.
+ import fdt
+ import fdt_util
+
+ # If we are updating the DTBs we need to put these updated versions
+ # where Entry_blob_dtb can find them. We can ignore 'u-boot.dtb'
+ # since it is assumed to be the one passed in with options.dt, and
+ # was handled just above.
+ main_dtb = dtb
+ fdt_files.clear()
+ fdt_files['u-boot.dtb'] = dtb
+ 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
+
+ Yields:
+ 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
+
+ The property referenced by this node is added to any device trees which
+ have the given node. Due to removable of unwanted notes, SPL and TPL may
+ not have this node.
+
+ Args:
+ node: Node object in the main device tree to look up
+
+ Yields:
+ Node objects in each device tree that is in use (U-Boot proper, which
+ 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.
+
+ Args:
+ prop_name: Name of property
+ """
+ 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
+
+ This is not allowed to change the size of the FDT.
+
+ Args:
+ prop_name: Name of property
+ """
+ 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)