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 entry type (e.g.
15 # 'u-boot-spl-dtb'). These are the output FDT files, which can be updated by
16 # binman. They have been copied to <xxx>.out files.
24 # Arguments passed to binman to provide arguments to entries
27 # True to use fake device-tree files for testing (see U_BOOT_DTB_DATA in
31 # Dict of device trees, keyed by entry type. These are the input device trees,
32 # before any modification by U-Boot
33 # The value is as returned by Entry.GetFdts(), i.e. a tuple:
34 # Fdt object for this dtb, or None if not available
35 # Filename of file containing this dtb
38 # The DTB which contains the full image information
41 # Allow entries to expand after they have been packed. This is detected and
42 # forces a re-pack. If not allowed, any attempted expansion causes an error in
43 # Entry.ProcessContentsUpdate()
44 allow_entry_expansion = True
46 def GetFdtForEtype(etype):
47 """Get the Fdt object for a particular device-tree entry
49 Binman keeps track of at least one device-tree file called u-boot.dtb but
50 can also have others (e.g. for SPL). This function looks up the given
51 entry and returns the associated Fdt object.
54 etype: Entry type of device tree (e.g. 'u-boot-dtb')
57 Fdt object associated with the entry type
59 return output_fdt_files[etype][0]
61 def GetFdtPath(etype):
62 """Get the full pathname of a particular Fdt object
64 Similar to GetFdtForEtype() but returns the pathname associated with the
68 etype: Entry type of device tree (e.g. 'u-boot-dtb')
71 Full path name to the associated Fdt
73 return output_fdt_files[etype][0]._fname
75 def GetFdtContents(etype='u-boot-dtb'):
76 """Looks up the FDT pathname and contents
78 This is used to obtain the Fdt pathname and contents when needed by an
79 entry. It supports a 'fake' dtb, allowing tests to substitute test data for
83 etype: Entry type to look up (e.g. 'u-boot.dtb').
90 if etype in output_fdt_files and not use_fake_dtb:
91 pathname = GetFdtPath(etype)
92 data = GetFdtForEtype(etype).GetContents()
94 fname = output_fdt_files[etype][1]
95 pathname = tools.GetInputFilename(fname)
96 data = tools.ReadFile(pathname)
99 def SetEntryArgs(args):
100 """Set the value of the entry args
102 This sets up the entry_args dict which is used to supply entry arguments to
106 args: List of entry arguments, each in the format "name=value"
113 m = re.match('([^=]*)=(.*)', arg)
115 raise ValueError("Invalid entry arguemnt '%s'" % arg)
116 entry_args[m.group(1)] = m.group(2)
118 def GetEntryArg(name):
119 """Get the value of an entry argument
122 name: Name of argument to retrieve
125 String value of argument
127 return entry_args.get(name)
129 def Prepare(images, dtb):
130 """Get device tree files ready for use
132 This sets up a set of device tree files that can be retrieved by
133 GetAllFdts(). This includes U-Boot proper and any SPL device trees.
136 images: List of images being used
139 global fdt_set, output_fdt_files, main_dtb
140 # Import these here in case libfdt.py is not available, in which case
141 # the above help option still works.
145 # If we are updating the DTBs we need to put these updated versions
146 # where Entry_blob_dtb can find them. We can ignore 'u-boot.dtb'
147 # since it is assumed to be the one passed in with options.dt, and
148 # was handled just above.
150 output_fdt_files.clear()
151 output_fdt_files['u-boot-dtb'] = [dtb, 'u-boot.dtb']
152 output_fdt_files['u-boot-spl-dtb'] = [dtb, 'spl/u-boot-spl.dtb']
153 output_fdt_files['u-boot-tpl-dtb'] = [dtb, 'tpl/u-boot-tpl.dtb']
156 for image in images.values():
157 fdt_set.update(image.GetFdts())
158 for etype, other in fdt_set.items():
159 _, other_fname = other
160 infile = tools.GetInputFilename(other_fname)
161 other_fname_dtb = fdt_util.EnsureCompiled(infile)
162 out_fname = tools.GetOutputFilename('%s.out' %
163 os.path.split(other_fname)[1])
164 tools.WriteFile(out_fname, tools.ReadFile(other_fname_dtb))
165 other_dtb = fdt.FdtScan(out_fname)
166 output_fdt_files[etype] = [other_dtb, other_fname]
169 """Yield all device tree files being used by binman
172 Device trees being used (U-Boot proper, SPL, TPL)
175 for etype in fdt_set:
176 dtb = output_fdt_files[etype][0]
180 def GetUpdateNodes(node):
181 """Yield all the nodes that need to be updated in all device trees
183 The property referenced by this node is added to any device trees which
184 have the given node. Due to removable of unwanted notes, SPL and TPL may
188 node: Node object in the main device tree to look up
191 Node objects in each device tree that is in use (U-Boot proper, which
192 is node, SPL and TPL)
195 for dtb, fname in output_fdt_files.values():
196 if dtb != node.GetFdt():
197 other_node = dtb.GetNode(node.path)
201 def AddZeroProp(node, prop):
202 """Add a new property to affected device trees with an integer value of 0.
205 prop_name: Name of property
207 for n in GetUpdateNodes(node):
210 def AddSubnode(node, name):
211 """Add a new subnode to a node in affected device trees
215 name: name of node to add
218 New subnode that was created in main tree
221 for n in GetUpdateNodes(node):
222 subnode = n.AddSubnode(name)
227 def AddString(node, prop, value):
228 """Add a new string property to affected device trees
231 prop_name: Name of property
232 value: String value (which will be \0-terminated in the DT)
234 for n in GetUpdateNodes(node):
235 n.AddString(prop, value)
237 def SetInt(node, prop, value):
238 """Update an integer property in affected device trees with an integer value
240 This is not allowed to change the size of the FDT.
243 prop_name: Name of property
245 for n in GetUpdateNodes(node):
246 n.SetInt(prop, value)
248 def CheckAddHashProp(node):
249 hash_node = node.FindNode('hash')
251 algo = hash_node.props.get('algo')
253 return "Missing 'algo' property for hash node"
254 if algo.value == 'sha256':
257 return "Unknown hash algorithm '%s'" % algo
258 for n in GetUpdateNodes(hash_node):
259 n.AddEmptyProp('value', size)
261 def CheckSetHashValue(node, get_data_func):
262 hash_node = node.FindNode('hash')
264 algo = hash_node.props.get('algo').value
267 m.update(get_data_func())
269 for n in GetUpdateNodes(hash_node):
270 n.SetData('value', data)
272 def SetAllowEntryExpansion(allow):
273 """Set whether post-pack expansion of entries is allowed
276 allow: True to allow expansion, False to raise an exception
278 global allow_entry_expansion
280 allow_entry_expansion = allow
282 def AllowEntryExpansion():
283 """Check whether post-pack expansion of entries is allowed
286 True if expansion should be allowed, False if an exception should be
289 return allow_entry_expansion