1 # SPDX-License-Identifier: GPL-2.0+
2 # Copyright 2018 Google, Inc
3 # Written by Simon Glass <sjg@chromium.org>
5 # Holds and modifies the state information held by binman
14 # Records the device-tree files known to binman, keyed by filename (e.g.
18 # Arguments passed to binman to provide arguments to entries
21 # True to use fake device-tree files for testing (see U_BOOT_DTB_DATA in
25 # Dict of device trees, keyed by filename, but excluding the main one
28 # The DTB which contains the full image information
31 # Allow entries to expand after they have been packed. This is detected and
32 # forces a re-pack. If not allowed, any attempted expansion causes an error in
33 # Entry.ProcessContentsUpdate()
34 allow_entry_expansion = True
37 """Get the Fdt object for a particular device-tree filename
39 Binman keeps track of at least one device-tree file called u-boot.dtb but
40 can also have others (e.g. for SPL). This function looks up the given
41 filename and returns the associated Fdt object.
44 fname: Filename to look up (e.g. 'u-boot.dtb').
47 Fdt object associated with the filename
49 return fdt_files[fname]
51 def GetFdtPath(fname):
52 """Get the full pathname of a particular Fdt object
54 Similar to GetFdt() but returns the pathname associated with the Fdt.
57 fname: Filename to look up (e.g. 'u-boot.dtb').
60 Full path name to the associated Fdt
62 return fdt_files[fname]._fname
64 def GetFdtContents(fname='u-boot.dtb'):
65 """Looks up the FDT pathname and contents
67 This is used to obtain the Fdt pathname and contents when needed by an
68 entry. It supports a 'fake' dtb, allowing tests to substitute test data for
72 fname: Filename to look up (e.g. 'u-boot.dtb').
79 if fname in fdt_files and not use_fake_dtb:
80 pathname = GetFdtPath(fname)
81 data = GetFdt(fname).GetContents()
83 pathname = tools.GetInputFilename(fname)
84 data = tools.ReadFile(pathname)
87 def SetEntryArgs(args):
88 """Set the value of the entry args
90 This sets up the entry_args dict which is used to supply entry arguments to
94 args: List of entry arguments, each in the format "name=value"
101 m = re.match('([^=]*)=(.*)', arg)
103 raise ValueError("Invalid entry arguemnt '%s'" % arg)
104 entry_args[m.group(1)] = m.group(2)
106 def GetEntryArg(name):
107 """Get the value of an entry argument
110 name: Name of argument to retrieve
113 String value of argument
115 return entry_args.get(name)
117 def Prepare(images, dtb):
118 """Get device tree files ready for use
120 This sets up a set of device tree files that can be retrieved by
121 GetAllFdts(). This includes U-Boot proper and any SPL device trees.
124 images: List of images being used
127 global fdt_set, fdt_subset, fdt_files, main_dtb
128 # Import these here in case libfdt.py is not available, in which case
129 # the above help option still works.
133 # If we are updating the DTBs we need to put these updated versions
134 # where Entry_blob_dtb can find them. We can ignore 'u-boot.dtb'
135 # since it is assumed to be the one passed in with options.dt, and
136 # was handled just above.
139 fdt_files['u-boot.dtb'] = dtb
142 for image in images.values():
143 fdt_subset.update(image.GetFdts())
144 if 'u-boot.dtb' in fdt_subset:
145 del fdt_subset['u-boot.dtb']
146 for other_fname in fdt_subset:
147 infile = tools.GetInputFilename(other_fname)
148 other_fname_dtb = fdt_util.EnsureCompiled(infile)
149 out_fname = tools.GetOutputFilename('%s.out' %
150 os.path.split(other_fname)[1])
151 tools.WriteFile(out_fname, tools.ReadFile(other_fname_dtb))
152 other_dtb = fdt.FdtScan(out_fname)
153 fdt_files[other_fname] = other_dtb
156 """Yield all device tree files being used by binman
159 Device trees being used (U-Boot proper, SPL, TPL)
162 for other_fname in fdt_subset:
163 yield fdt_files[other_fname]
165 def GetUpdateNodes(node):
166 """Yield all the nodes that need to be updated in all device trees
168 The property referenced by this node is added to any device trees which
169 have the given node. Due to removable of unwanted notes, SPL and TPL may
173 node: Node object in the main device tree to look up
176 Node objects in each device tree that is in use (U-Boot proper, which
177 is node, SPL and TPL)
180 for dtb in fdt_files.values():
181 if dtb != node.GetFdt():
182 other_node = dtb.GetNode(node.path)
186 def AddZeroProp(node, prop):
187 """Add a new property to affected device trees with an integer value of 0.
190 prop_name: Name of property
192 for n in GetUpdateNodes(node):
195 def AddSubnode(node, name):
196 """Add a new subnode to a node in affected device trees
200 name: name of node to add
203 New subnode that was created in main tree
206 for n in GetUpdateNodes(node):
207 subnode = n.AddSubnode(name)
212 def AddString(node, prop, value):
213 """Add a new string property to affected device trees
216 prop_name: Name of property
217 value: String value (which will be \0-terminated in the DT)
219 for n in GetUpdateNodes(node):
220 n.AddString(prop, value)
222 def SetInt(node, prop, value):
223 """Update an integer property in affected device trees with an integer value
225 This is not allowed to change the size of the FDT.
228 prop_name: Name of property
230 for n in GetUpdateNodes(node):
231 n.SetInt(prop, value)
233 def CheckAddHashProp(node):
234 hash_node = node.FindNode('hash')
236 algo = hash_node.props.get('algo')
238 return "Missing 'algo' property for hash node"
239 if algo.value == 'sha256':
242 return "Unknown hash algorithm '%s'" % algo
243 for n in GetUpdateNodes(hash_node):
244 n.AddEmptyProp('value', size)
246 def CheckSetHashValue(node, get_data_func):
247 hash_node = node.FindNode('hash')
249 algo = hash_node.props.get('algo').value
252 m.update(get_data_func())
254 for n in GetUpdateNodes(hash_node):
255 n.SetData('value', data)
257 def SetAllowEntryExpansion(allow):
258 """Set whether post-pack expansion of entries is allowed
261 allow: True to allow expansion, False to raise an exception
263 global allow_entry_expansion
265 allow_entry_expansion = allow
267 def AllowEntryExpansion():
268 """Check whether post-pack expansion of entries is allowed
271 True if expansion should be allowed, False if an exception should be
274 return allow_entry_expansion