]> Git Repo - J-u-boot.git/blame - tools/binman/state.py
binman: Drop unnecessary field in output_fdt_info
[J-u-boot.git] / tools / binman / state.py
CommitLineData
c55a50f5
SG
1# SPDX-License-Identifier: GPL-2.0+
2# Copyright 2018 Google, Inc
3# Written by Simon Glass <[email protected]>
4#
5# Holds and modifies the state information held by binman
6#
7
e0e5df93 8import hashlib
c55a50f5 9import re
c55a50f5 10
16287933 11from dtoc import fdt
c55a50f5 12import os
bf776679
SG
13from patman import tools
14from patman import tout
c55a50f5 15
7697170e
SG
16# Map an dtb etype to its expected filename
17DTB_TYPE_FNAME = {
18 'u-boot-spl-dtb': 'spl/u-boot-spl.dtb',
19 'u-boot-tpl-dtb': 'tpl/u-boot-tpl.dtb',
20 }
21
fb5e8b16
SG
22# Records the device-tree files known to binman, keyed by entry type (e.g.
23# 'u-boot-spl-dtb'). These are the output FDT files, which can be updated by
24# binman. They have been copied to <xxx>.out files.
25#
cb8bebbd 26# key: entry type (e.g. 'u-boot-dtb)
fb5e8b16
SG
27# value: tuple:
28# Fdt object
29# Filename
6ca0dcba 30output_fdt_info = {}
c55a50f5 31
10f9d006
SG
32# Prefix to add to an fdtmap path to turn it into a path to the /binman node
33fdt_path_prefix = ''
34
c55a50f5
SG
35# Arguments passed to binman to provide arguments to entries
36entry_args = {}
37
539aece5
SG
38# True to use fake device-tree files for testing (see U_BOOT_DTB_DATA in
39# ftest.py)
93d17413 40use_fake_dtb = False
539aece5 41
2a72cc72
SG
42# The DTB which contains the full image information
43main_dtb = None
44
bf6906ba
SG
45# Allow entries to expand after they have been packed. This is detected and
46# forces a re-pack. If not allowed, any attempted expansion causes an error in
47# Entry.ProcessContentsUpdate()
48allow_entry_expansion = True
49
61ec04f9
SG
50# Don't allow entries to contract after they have been packed. Instead just
51# leave some wasted space. If allowed, this is detected and forces a re-pack,
52# but may result in entries that oscillate in size, thus causing a pack error.
53# An example is a compressed device tree where the original offset values
54# result in a larger compressed size than the new ones, but then after updating
55# to the new ones, the compressed size increases, etc.
56allow_entry_contraction = False
57
fb5e8b16
SG
58def GetFdtForEtype(etype):
59 """Get the Fdt object for a particular device-tree entry
c55a50f5
SG
60
61 Binman keeps track of at least one device-tree file called u-boot.dtb but
62 can also have others (e.g. for SPL). This function looks up the given
fb5e8b16 63 entry and returns the associated Fdt object.
c55a50f5
SG
64
65 Args:
fb5e8b16 66 etype: Entry type of device tree (e.g. 'u-boot-dtb')
c55a50f5
SG
67
68 Returns:
fb5e8b16 69 Fdt object associated with the entry type
c55a50f5 70 """
6ca0dcba 71 value = output_fdt_info.get(etype);
6a3b5b54
SG
72 if not value:
73 return None
74 return value[0]
c55a50f5 75
fb5e8b16 76def GetFdtPath(etype):
c55a50f5
SG
77 """Get the full pathname of a particular Fdt object
78
726e2961
SG
79 Similar to GetFdtForEtype() but returns the pathname associated with the
80 Fdt.
c55a50f5
SG
81
82 Args:
fb5e8b16 83 etype: Entry type of device tree (e.g. 'u-boot-dtb')
c55a50f5
SG
84
85 Returns:
86 Full path name to the associated Fdt
87 """
6ca0dcba 88 return output_fdt_info[etype][0]._fname
c55a50f5 89
fb5e8b16 90def GetFdtContents(etype='u-boot-dtb'):
6ed45ba0
SG
91 """Looks up the FDT pathname and contents
92
93 This is used to obtain the Fdt pathname and contents when needed by an
94 entry. It supports a 'fake' dtb, allowing tests to substitute test data for
95 the real dtb.
96
97 Args:
fb5e8b16 98 etype: Entry type to look up (e.g. 'u-boot.dtb').
6ed45ba0
SG
99
100 Returns:
101 tuple:
102 pathname to Fdt
103 Fdt data (as bytes)
104 """
6ca0dcba 105 if etype not in output_fdt_info:
6a3b5b54
SG
106 return None, None
107 if not use_fake_dtb:
fb5e8b16
SG
108 pathname = GetFdtPath(etype)
109 data = GetFdtForEtype(etype).GetContents()
6ed45ba0 110 else:
6ca0dcba 111 fname = output_fdt_info[etype][1]
6ed45ba0
SG
112 pathname = tools.GetInputFilename(fname)
113 data = tools.ReadFile(pathname)
114 return pathname, data
115
f6e02497
SG
116def UpdateFdtContents(etype, data):
117 """Update the contents of a particular device tree
118
119 The device tree is updated and written back to its file. This affects what
120 is returned from future called to GetFdtContents(), etc.
121
122 Args:
123 etype: Entry type (e.g. 'u-boot-dtb')
124 data: Data to replace the DTB with
125 """
cb8bebbd 126 dtb, fname = output_fdt_info[etype]
f6e02497
SG
127 dtb_fname = dtb.GetFilename()
128 tools.WriteFile(dtb_fname, data)
129 dtb = fdt.FdtScan(dtb_fname)
cb8bebbd 130 output_fdt_info[etype] = [dtb, fname]
f6e02497 131
c55a50f5
SG
132def SetEntryArgs(args):
133 """Set the value of the entry args
134
135 This sets up the entry_args dict which is used to supply entry arguments to
136 entries.
137
138 Args:
139 args: List of entry arguments, each in the format "name=value"
140 """
141 global entry_args
142
143 entry_args = {}
144 if args:
145 for arg in args:
146 m = re.match('([^=]*)=(.*)', arg)
147 if not m:
148 raise ValueError("Invalid entry arguemnt '%s'" % arg)
149 entry_args[m.group(1)] = m.group(2)
150
151def GetEntryArg(name):
152 """Get the value of an entry argument
153
154 Args:
155 name: Name of argument to retrieve
156
157 Returns:
158 String value of argument
159 """
160 return entry_args.get(name)
2a72cc72 161
539aece5 162def Prepare(images, dtb):
2a72cc72
SG
163 """Get device tree files ready for use
164
4bdd1159
SG
165 This sets up a set of device tree files that can be retrieved by
166 GetAllFdts(). This includes U-Boot proper and any SPL device trees.
2a72cc72
SG
167
168 Args:
539aece5 169 images: List of images being used
2a72cc72
SG
170 dtb: Main dtb
171 """
10f9d006 172 global output_fdt_info, main_dtb, fdt_path_prefix
2a72cc72
SG
173 # Import these here in case libfdt.py is not available, in which case
174 # the above help option still works.
16287933
SG
175 from dtoc import fdt
176 from dtoc import fdt_util
2a72cc72
SG
177
178 # If we are updating the DTBs we need to put these updated versions
179 # where Entry_blob_dtb can find them. We can ignore 'u-boot.dtb'
180 # since it is assumed to be the one passed in with options.dt, and
181 # was handled just above.
182 main_dtb = dtb
6ca0dcba 183 output_fdt_info.clear()
10f9d006 184 fdt_path_prefix = ''
cb8bebbd 185 output_fdt_info['u-boot-dtb'] = [dtb, 'u-boot.dtb']
7697170e
SG
186 if use_fake_dtb:
187 for etype, fname in DTB_TYPE_FNAME.items():
cb8bebbd 188 output_fdt_info[etype] = [dtb, fname]
7697170e 189 else:
f49462e5 190 fdt_set = {}
539aece5 191 for image in images.values():
77e4ef1b
SG
192 fdt_set.update(image.GetFdts())
193 for etype, other in fdt_set.items():
7697170e
SG
194 entry, fname = other
195 infile = tools.GetInputFilename(fname)
196 fname_dtb = fdt_util.EnsureCompiled(infile)
539aece5 197 out_fname = tools.GetOutputFilename('%s.out' %
7697170e
SG
198 os.path.split(fname)[1])
199 tools.WriteFile(out_fname, tools.ReadFile(fname_dtb))
539aece5 200 other_dtb = fdt.FdtScan(out_fname)
cb8bebbd 201 output_fdt_info[etype] = [other_dtb, out_fname]
2a72cc72 202
10f9d006
SG
203def PrepareFromLoadedData(image):
204 """Get device tree files ready for use with a loaded image
205
206 Loaded images are different from images that are being created by binman,
207 since there is generally already an fdtmap and we read the description from
208 that. This provides the position and size of every entry in the image with
209 no calculation required.
210
211 This function uses the same output_fdt_info[] as Prepare(). It finds the
212 device tree files, adds a reference to the fdtmap and sets the FDT path
213 prefix to translate from the fdtmap (where the root node is the image node)
214 to the normal device tree (where the image node is under a /binman node).
215
216 Args:
217 images: List of images being used
218 """
219 global output_fdt_info, main_dtb, fdt_path_prefix
220
221 tout.Info('Preparing device trees')
222 output_fdt_info.clear()
223 fdt_path_prefix = ''
cb8bebbd 224 output_fdt_info['fdtmap'] = [image.fdtmap_dtb, 'u-boot.dtb']
10f9d006
SG
225 main_dtb = None
226 tout.Info(" Found device tree type 'fdtmap' '%s'" % image.fdtmap_dtb.name)
227 for etype, value in image.GetFdts().items():
228 entry, fname = value
229 out_fname = tools.GetOutputFilename('%s.dtb' % entry.etype)
230 tout.Info(" Found device tree type '%s' at '%s' path '%s'" %
231 (etype, out_fname, entry.GetPath()))
232 entry._filename = entry.GetDefaultFilename()
233 data = entry.ReadData()
234
235 tools.WriteFile(out_fname, data)
236 dtb = fdt.Fdt(out_fname)
237 dtb.Scan()
238 image_node = dtb.GetNode('/binman')
239 if 'multiple-images' in image_node.props:
240 image_node = dtb.GetNode('/binman/%s' % image.image_node)
241 fdt_path_prefix = image_node.path
cb8bebbd 242 output_fdt_info[etype] = [dtb, None]
10f9d006
SG
243 tout.Info(" FDT path prefix '%s'" % fdt_path_prefix)
244
245
4bdd1159 246def GetAllFdts():
2a72cc72
SG
247 """Yield all device tree files being used by binman
248
249 Yields:
250 Device trees being used (U-Boot proper, SPL, TPL)
251 """
10f9d006
SG
252 if main_dtb:
253 yield main_dtb
6ca0dcba
SG
254 for etype in output_fdt_info:
255 dtb = output_fdt_info[etype][0]
77e4ef1b
SG
256 if dtb != main_dtb:
257 yield dtb
2a72cc72 258
12bb1a99 259def GetUpdateNodes(node, for_repack=False):
f46621d2
SG
260 """Yield all the nodes that need to be updated in all device trees
261
262 The property referenced by this node is added to any device trees which
263 have the given node. Due to removable of unwanted notes, SPL and TPL may
264 not have this node.
265
266 Args:
267 node: Node object in the main device tree to look up
12bb1a99
SG
268 for_repack: True if we want only nodes which need 'repack' properties
269 added to them (e.g. 'orig-offset'), False to return all nodes. We
270 don't add repack properties to SPL/TPL device trees.
f46621d2
SG
271
272 Yields:
273 Node objects in each device tree that is in use (U-Boot proper, which
274 is node, SPL and TPL)
275 """
276 yield node
cb8bebbd 277 for entry_type, (dtb, fname) in output_fdt_info.items():
6ed45ba0 278 if dtb != node.GetFdt():
cb8bebbd 279 if for_repack and entry_type != 'u-boot-dtb':
12bb1a99 280 continue
10f9d006 281 other_node = dtb.GetNode(fdt_path_prefix + node.path)
6ed45ba0
SG
282 if other_node:
283 yield other_node
f46621d2 284
12bb1a99 285def AddZeroProp(node, prop, for_repack=False):
f46621d2
SG
286 """Add a new property to affected device trees with an integer value of 0.
287
288 Args:
289 prop_name: Name of property
12bb1a99 290 for_repack: True is this property is only needed for repacking
f46621d2 291 """
12bb1a99 292 for n in GetUpdateNodes(node, for_repack):
f46621d2
SG
293 n.AddZeroProp(prop)
294
0a98b28b
SG
295def AddSubnode(node, name):
296 """Add a new subnode to a node in affected device trees
297
298 Args:
299 node: Node to add to
300 name: name of node to add
301
302 Returns:
303 New subnode that was created in main tree
304 """
305 first = None
306 for n in GetUpdateNodes(node):
307 subnode = n.AddSubnode(name)
308 if not first:
309 first = subnode
310 return first
311
312def AddString(node, prop, value):
313 """Add a new string property to affected device trees
314
315 Args:
316 prop_name: Name of property
317 value: String value (which will be \0-terminated in the DT)
318 """
319 for n in GetUpdateNodes(node):
320 n.AddString(prop, value)
321
6eb99326
SG
322def AddInt(node, prop, value):
323 """Add a new string property to affected device trees
324
325 Args:
326 prop_name: Name of property
327 val: Integer value of property
328 """
329 for n in GetUpdateNodes(node):
330 n.AddInt(prop, value)
331
12bb1a99 332def SetInt(node, prop, value, for_repack=False):
f46621d2
SG
333 """Update an integer property in affected device trees with an integer value
334
335 This is not allowed to change the size of the FDT.
336
337 Args:
338 prop_name: Name of property
12bb1a99 339 for_repack: True is this property is only needed for repacking
f46621d2 340 """
12bb1a99
SG
341 for n in GetUpdateNodes(node, for_repack):
342 tout.Detail("File %s: Update node '%s' prop '%s' to %#x" %
51014aab 343 (n.GetFdt().name, n.path, prop, value))
f46621d2 344 n.SetInt(prop, value)
e0e5df93
SG
345
346def CheckAddHashProp(node):
347 hash_node = node.FindNode('hash')
348 if hash_node:
349 algo = hash_node.props.get('algo')
350 if not algo:
351 return "Missing 'algo' property for hash node"
352 if algo.value == 'sha256':
353 size = 32
354 else:
355 return "Unknown hash algorithm '%s'" % algo
356 for n in GetUpdateNodes(hash_node):
357 n.AddEmptyProp('value', size)
358
359def CheckSetHashValue(node, get_data_func):
360 hash_node = node.FindNode('hash')
361 if hash_node:
362 algo = hash_node.props.get('algo').value
363 if algo == 'sha256':
364 m = hashlib.sha256()
365 m.update(get_data_func())
366 data = m.digest()
367 for n in GetUpdateNodes(hash_node):
368 n.SetData('value', data)
bf6906ba
SG
369
370def SetAllowEntryExpansion(allow):
371 """Set whether post-pack expansion of entries is allowed
372
373 Args:
374 allow: True to allow expansion, False to raise an exception
375 """
376 global allow_entry_expansion
377
378 allow_entry_expansion = allow
379
380def AllowEntryExpansion():
381 """Check whether post-pack expansion of entries is allowed
382
383 Returns:
384 True if expansion should be allowed, False if an exception should be
385 raised
386 """
387 return allow_entry_expansion
61ec04f9
SG
388
389def SetAllowEntryContraction(allow):
390 """Set whether post-pack contraction of entries is allowed
391
392 Args:
393 allow: True to allow contraction, False to raise an exception
394 """
395 global allow_entry_contraction
396
397 allow_entry_contraction = allow
398
399def AllowEntryContraction():
400 """Check whether post-pack contraction of entries is allowed
401
402 Returns:
403 True if contraction should be allowed, False if an exception should be
404 raised
405 """
406 return allow_entry_contraction
This page took 0.147091 seconds and 4 git commands to generate.