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 # The DTB which contains the full image information
34 # Allow entries to expand after they have been packed. This is detected and
35 # forces a re-pack. If not allowed, any attempted expansion causes an error in
36 # Entry.ProcessContentsUpdate()
37 allow_entry_expansion = True
39 def GetFdtForEtype(etype):
40 """Get the Fdt object for a particular device-tree entry
42 Binman keeps track of at least one device-tree file called u-boot.dtb but
43 can also have others (e.g. for SPL). This function looks up the given
44 entry and returns the associated Fdt object.
47 etype: Entry type of device tree (e.g. 'u-boot-dtb')
50 Fdt object associated with the entry type
52 return output_fdt_files[etype][0]
54 def GetFdtPath(etype):
55 """Get the full pathname of a particular Fdt object
57 Similar to GetFdtForEtype() but returns the pathname associated with the
61 etype: Entry type of device tree (e.g. 'u-boot-dtb')
64 Full path name to the associated Fdt
66 return output_fdt_files[etype][0]._fname
68 def GetFdtContents(etype='u-boot-dtb'):
69 """Looks up the FDT pathname and contents
71 This is used to obtain the Fdt pathname and contents when needed by an
72 entry. It supports a 'fake' dtb, allowing tests to substitute test data for
76 etype: Entry type to look up (e.g. 'u-boot.dtb').
83 if etype in output_fdt_files and not use_fake_dtb:
84 pathname = GetFdtPath(etype)
85 data = GetFdtForEtype(etype).GetContents()
87 fname = output_fdt_files[etype][1]
88 pathname = tools.GetInputFilename(fname)
89 data = tools.ReadFile(pathname)
92 def SetEntryArgs(args):
93 """Set the value of the entry args
95 This sets up the entry_args dict which is used to supply entry arguments to
99 args: List of entry arguments, each in the format "name=value"
106 m = re.match('([^=]*)=(.*)', arg)
108 raise ValueError("Invalid entry arguemnt '%s'" % arg)
109 entry_args[m.group(1)] = m.group(2)
111 def GetEntryArg(name):
112 """Get the value of an entry argument
115 name: Name of argument to retrieve
118 String value of argument
120 return entry_args.get(name)
122 def Prepare(images, dtb):
123 """Get device tree files ready for use
125 This sets up a set of device tree files that can be retrieved by
126 GetAllFdts(). This includes U-Boot proper and any SPL device trees.
129 images: List of images being used
132 global output_fdt_files, main_dtb
133 # Import these here in case libfdt.py is not available, in which case
134 # the above help option still works.
138 # If we are updating the DTBs we need to put these updated versions
139 # where Entry_blob_dtb can find them. We can ignore 'u-boot.dtb'
140 # since it is assumed to be the one passed in with options.dt, and
141 # was handled just above.
143 output_fdt_files.clear()
144 output_fdt_files['u-boot-dtb'] = [dtb, 'u-boot.dtb']
145 output_fdt_files['u-boot-spl-dtb'] = [dtb, 'spl/u-boot-spl.dtb']
146 output_fdt_files['u-boot-tpl-dtb'] = [dtb, 'tpl/u-boot-tpl.dtb']
149 for image in images.values():
150 fdt_set.update(image.GetFdts())
151 for etype, other in fdt_set.items():
152 _, other_fname = other
153 infile = tools.GetInputFilename(other_fname)
154 other_fname_dtb = fdt_util.EnsureCompiled(infile)
155 out_fname = tools.GetOutputFilename('%s.out' %
156 os.path.split(other_fname)[1])
157 tools.WriteFile(out_fname, tools.ReadFile(other_fname_dtb))
158 other_dtb = fdt.FdtScan(out_fname)
159 output_fdt_files[etype] = [other_dtb, other_fname]
162 """Yield all device tree files being used by binman
165 Device trees being used (U-Boot proper, SPL, TPL)
168 for etype in output_fdt_files:
169 dtb = output_fdt_files[etype][0]
173 def GetUpdateNodes(node):
174 """Yield all the nodes that need to be updated in all device trees
176 The property referenced by this node is added to any device trees which
177 have the given node. Due to removable of unwanted notes, SPL and TPL may
181 node: Node object in the main device tree to look up
184 Node objects in each device tree that is in use (U-Boot proper, which
185 is node, SPL and TPL)
188 for dtb, fname in output_fdt_files.values():
189 if dtb != node.GetFdt():
190 other_node = dtb.GetNode(node.path)
194 def AddZeroProp(node, prop):
195 """Add a new property to affected device trees with an integer value of 0.
198 prop_name: Name of property
200 for n in GetUpdateNodes(node):
203 def AddSubnode(node, name):
204 """Add a new subnode to a node in affected device trees
208 name: name of node to add
211 New subnode that was created in main tree
214 for n in GetUpdateNodes(node):
215 subnode = n.AddSubnode(name)
220 def AddString(node, prop, value):
221 """Add a new string property to affected device trees
224 prop_name: Name of property
225 value: String value (which will be \0-terminated in the DT)
227 for n in GetUpdateNodes(node):
228 n.AddString(prop, value)
230 def SetInt(node, prop, value):
231 """Update an integer property in affected device trees with an integer value
233 This is not allowed to change the size of the FDT.
236 prop_name: Name of property
238 for n in GetUpdateNodes(node):
239 n.SetInt(prop, value)
241 def CheckAddHashProp(node):
242 hash_node = node.FindNode('hash')
244 algo = hash_node.props.get('algo')
246 return "Missing 'algo' property for hash node"
247 if algo.value == 'sha256':
250 return "Unknown hash algorithm '%s'" % algo
251 for n in GetUpdateNodes(hash_node):
252 n.AddEmptyProp('value', size)
254 def CheckSetHashValue(node, get_data_func):
255 hash_node = node.FindNode('hash')
257 algo = hash_node.props.get('algo').value
260 m.update(get_data_func())
262 for n in GetUpdateNodes(hash_node):
263 n.SetData('value', data)
265 def SetAllowEntryExpansion(allow):
266 """Set whether post-pack expansion of entries is allowed
269 allow: True to allow expansion, False to raise an exception
271 global allow_entry_expansion
273 allow_entry_expansion = allow
275 def AllowEntryExpansion():
276 """Check whether post-pack expansion of entries is allowed
279 True if expansion should be allowed, False if an exception should be
282 return allow_entry_expansion