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
36 def GetFdtForEtype(fname):
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 GetFdtForEtype() but returns the pathname associated with the
58 fname: Filename to look up (e.g. 'u-boot.dtb').
61 Full path name to the associated Fdt
63 return fdt_files[fname]._fname
65 def GetFdtContents(fname='u-boot.dtb'):
66 """Looks up the FDT pathname and contents
68 This is used to obtain the Fdt pathname and contents when needed by an
69 entry. It supports a 'fake' dtb, allowing tests to substitute test data for
73 fname: Filename to look up (e.g. 'u-boot.dtb').
80 if fname in fdt_files and not use_fake_dtb:
81 pathname = GetFdtPath(fname)
82 data = GetFdtForEtype(fname).GetContents()
84 pathname = tools.GetInputFilename(fname)
85 data = tools.ReadFile(pathname)
88 def SetEntryArgs(args):
89 """Set the value of the entry args
91 This sets up the entry_args dict which is used to supply entry arguments to
95 args: List of entry arguments, each in the format "name=value"
102 m = re.match('([^=]*)=(.*)', arg)
104 raise ValueError("Invalid entry arguemnt '%s'" % arg)
105 entry_args[m.group(1)] = m.group(2)
107 def GetEntryArg(name):
108 """Get the value of an entry argument
111 name: Name of argument to retrieve
114 String value of argument
116 return entry_args.get(name)
118 def Prepare(images, dtb):
119 """Get device tree files ready for use
121 This sets up a set of device tree files that can be retrieved by
122 GetAllFdts(). This includes U-Boot proper and any SPL device trees.
125 images: List of images being used
128 global fdt_set, fdt_subset, fdt_files, main_dtb
129 # Import these here in case libfdt.py is not available, in which case
130 # the above help option still works.
134 # If we are updating the DTBs we need to put these updated versions
135 # where Entry_blob_dtb can find them. We can ignore 'u-boot.dtb'
136 # since it is assumed to be the one passed in with options.dt, and
137 # was handled just above.
140 fdt_files['u-boot.dtb'] = dtb
143 for image in images.values():
144 fdt_subset.update(image.GetFdts())
145 if 'u-boot.dtb' in fdt_subset:
146 del fdt_subset['u-boot.dtb']
147 for other_fname in fdt_subset:
148 infile = tools.GetInputFilename(other_fname)
149 other_fname_dtb = fdt_util.EnsureCompiled(infile)
150 out_fname = tools.GetOutputFilename('%s.out' %
151 os.path.split(other_fname)[1])
152 tools.WriteFile(out_fname, tools.ReadFile(other_fname_dtb))
153 other_dtb = fdt.FdtScan(out_fname)
154 fdt_files[other_fname] = other_dtb
157 """Yield all device tree files being used by binman
160 Device trees being used (U-Boot proper, SPL, TPL)
163 for other_fname in fdt_subset:
164 yield fdt_files[other_fname]
166 def GetUpdateNodes(node):
167 """Yield all the nodes that need to be updated in all device trees
169 The property referenced by this node is added to any device trees which
170 have the given node. Due to removable of unwanted notes, SPL and TPL may
174 node: Node object in the main device tree to look up
177 Node objects in each device tree that is in use (U-Boot proper, which
178 is node, SPL and TPL)
181 for dtb in fdt_files.values():
182 if dtb != node.GetFdt():
183 other_node = dtb.GetNode(node.path)
187 def AddZeroProp(node, prop):
188 """Add a new property to affected device trees with an integer value of 0.
191 prop_name: Name of property
193 for n in GetUpdateNodes(node):
196 def AddSubnode(node, name):
197 """Add a new subnode to a node in affected device trees
201 name: name of node to add
204 New subnode that was created in main tree
207 for n in GetUpdateNodes(node):
208 subnode = n.AddSubnode(name)
213 def AddString(node, prop, value):
214 """Add a new string property to affected device trees
217 prop_name: Name of property
218 value: String value (which will be \0-terminated in the DT)
220 for n in GetUpdateNodes(node):
221 n.AddString(prop, value)
223 def SetInt(node, prop, value):
224 """Update an integer property in affected device trees with an integer value
226 This is not allowed to change the size of the FDT.
229 prop_name: Name of property
231 for n in GetUpdateNodes(node):
232 n.SetInt(prop, value)
234 def CheckAddHashProp(node):
235 hash_node = node.FindNode('hash')
237 algo = hash_node.props.get('algo')
239 return "Missing 'algo' property for hash node"
240 if algo.value == 'sha256':
243 return "Unknown hash algorithm '%s'" % algo
244 for n in GetUpdateNodes(hash_node):
245 n.AddEmptyProp('value', size)
247 def CheckSetHashValue(node, get_data_func):
248 hash_node = node.FindNode('hash')
250 algo = hash_node.props.get('algo').value
253 m.update(get_data_func())
255 for n in GetUpdateNodes(hash_node):
256 n.SetData('value', data)
258 def SetAllowEntryExpansion(allow):
259 """Set whether post-pack expansion of entries is allowed
262 allow: True to allow expansion, False to raise an exception
264 global allow_entry_expansion
266 allow_entry_expansion = allow
268 def AllowEntryExpansion():
269 """Check whether post-pack expansion of entries is allowed
272 True if expansion should be allowed, False if an exception should be
275 return allow_entry_expansion