]>
Commit | Line | Data |
---|---|---|
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 | ||
8 | import re | |
9 | from sets import Set | |
10 | ||
11 | import os | |
12 | import tools | |
13 | ||
14 | # Records the device-tree files known to binman, keyed by filename (e.g. | |
15 | # 'u-boot-spl.dtb') | |
16 | fdt_files = {} | |
17 | ||
18 | # Arguments passed to binman to provide arguments to entries | |
19 | entry_args = {} | |
20 | ||
539aece5 SG |
21 | # True to use fake device-tree files for testing (see U_BOOT_DTB_DATA in |
22 | # ftest.py) | |
93d17413 | 23 | use_fake_dtb = False |
539aece5 | 24 | |
2a72cc72 SG |
25 | # Set of all device tree files references by images |
26 | fdt_set = Set() | |
27 | ||
28 | # Same as above, but excluding the main one | |
29 | fdt_subset = Set() | |
30 | ||
31 | # The DTB which contains the full image information | |
32 | main_dtb = None | |
33 | ||
c55a50f5 SG |
34 | def GetFdt(fname): |
35 | """Get the Fdt object for a particular device-tree filename | |
36 | ||
37 | Binman keeps track of at least one device-tree file called u-boot.dtb but | |
38 | can also have others (e.g. for SPL). This function looks up the given | |
39 | filename and returns the associated Fdt object. | |
40 | ||
41 | Args: | |
42 | fname: Filename to look up (e.g. 'u-boot.dtb'). | |
43 | ||
44 | Returns: | |
45 | Fdt object associated with the filename | |
46 | """ | |
47 | return fdt_files[fname] | |
48 | ||
49 | def GetFdtPath(fname): | |
50 | """Get the full pathname of a particular Fdt object | |
51 | ||
52 | Similar to GetFdt() but returns the pathname associated with the Fdt. | |
53 | ||
54 | Args: | |
55 | fname: Filename to look up (e.g. 'u-boot.dtb'). | |
56 | ||
57 | Returns: | |
58 | Full path name to the associated Fdt | |
59 | """ | |
60 | return fdt_files[fname]._fname | |
61 | ||
6ed45ba0 SG |
62 | def GetFdtContents(fname): |
63 | """Looks up the FDT pathname and contents | |
64 | ||
65 | This is used to obtain the Fdt pathname and contents when needed by an | |
66 | entry. It supports a 'fake' dtb, allowing tests to substitute test data for | |
67 | the real dtb. | |
68 | ||
69 | Args: | |
70 | fname: Filename to look up (e.g. 'u-boot.dtb'). | |
71 | ||
72 | Returns: | |
73 | tuple: | |
74 | pathname to Fdt | |
75 | Fdt data (as bytes) | |
76 | """ | |
77 | if fname in fdt_files and not use_fake_dtb: | |
78 | pathname = GetFdtPath(fname) | |
79 | data = GetFdt(fname).GetContents() | |
80 | else: | |
81 | pathname = tools.GetInputFilename(fname) | |
82 | data = tools.ReadFile(pathname) | |
83 | return pathname, data | |
84 | ||
c55a50f5 SG |
85 | def SetEntryArgs(args): |
86 | """Set the value of the entry args | |
87 | ||
88 | This sets up the entry_args dict which is used to supply entry arguments to | |
89 | entries. | |
90 | ||
91 | Args: | |
92 | args: List of entry arguments, each in the format "name=value" | |
93 | """ | |
94 | global entry_args | |
95 | ||
96 | entry_args = {} | |
97 | if args: | |
98 | for arg in args: | |
99 | m = re.match('([^=]*)=(.*)', arg) | |
100 | if not m: | |
101 | raise ValueError("Invalid entry arguemnt '%s'" % arg) | |
102 | entry_args[m.group(1)] = m.group(2) | |
103 | ||
104 | def GetEntryArg(name): | |
105 | """Get the value of an entry argument | |
106 | ||
107 | Args: | |
108 | name: Name of argument to retrieve | |
109 | ||
110 | Returns: | |
111 | String value of argument | |
112 | """ | |
113 | return entry_args.get(name) | |
2a72cc72 | 114 | |
539aece5 | 115 | def Prepare(images, dtb): |
2a72cc72 SG |
116 | """Get device tree files ready for use |
117 | ||
118 | This sets up a set of device tree files that can be retrieved by GetFdts(). | |
119 | At present there is only one, that for U-Boot proper. | |
120 | ||
121 | Args: | |
539aece5 | 122 | images: List of images being used |
2a72cc72 SG |
123 | dtb: Main dtb |
124 | """ | |
125 | global fdt_set, fdt_subset, fdt_files, main_dtb | |
126 | # Import these here in case libfdt.py is not available, in which case | |
127 | # the above help option still works. | |
128 | import fdt | |
129 | import fdt_util | |
130 | ||
131 | # If we are updating the DTBs we need to put these updated versions | |
132 | # where Entry_blob_dtb can find them. We can ignore 'u-boot.dtb' | |
133 | # since it is assumed to be the one passed in with options.dt, and | |
134 | # was handled just above. | |
135 | main_dtb = dtb | |
136 | fdt_files.clear() | |
137 | fdt_files['u-boot.dtb'] = dtb | |
2a72cc72 | 138 | fdt_subset = Set() |
539aece5 SG |
139 | if not use_fake_dtb: |
140 | for image in images.values(): | |
141 | fdt_subset.update(image.GetFdtSet()) | |
142 | fdt_subset.discard('u-boot.dtb') | |
143 | for other_fname in fdt_subset: | |
144 | infile = tools.GetInputFilename(other_fname) | |
145 | other_fname_dtb = fdt_util.EnsureCompiled(infile) | |
146 | out_fname = tools.GetOutputFilename('%s.out' % | |
147 | os.path.split(other_fname)[1]) | |
148 | tools.WriteFile(out_fname, tools.ReadFile(other_fname_dtb)) | |
149 | other_dtb = fdt.FdtScan(out_fname) | |
150 | fdt_files[other_fname] = other_dtb | |
2a72cc72 SG |
151 | |
152 | def GetFdts(): | |
153 | """Yield all device tree files being used by binman | |
154 | ||
155 | Yields: | |
156 | Device trees being used (U-Boot proper, SPL, TPL) | |
157 | """ | |
158 | yield main_dtb | |
6ed45ba0 SG |
159 | for other_fname in fdt_subset: |
160 | yield fdt_files[other_fname] | |
2a72cc72 | 161 | |
f46621d2 SG |
162 | def GetUpdateNodes(node): |
163 | """Yield all the nodes that need to be updated in all device trees | |
164 | ||
165 | The property referenced by this node is added to any device trees which | |
166 | have the given node. Due to removable of unwanted notes, SPL and TPL may | |
167 | not have this node. | |
168 | ||
169 | Args: | |
170 | node: Node object in the main device tree to look up | |
171 | ||
172 | Yields: | |
173 | Node objects in each device tree that is in use (U-Boot proper, which | |
174 | is node, SPL and TPL) | |
175 | """ | |
176 | yield node | |
6ed45ba0 SG |
177 | for dtb in fdt_files.values(): |
178 | if dtb != node.GetFdt(): | |
179 | other_node = dtb.GetNode(node.path) | |
180 | if other_node: | |
181 | yield other_node | |
f46621d2 SG |
182 | |
183 | def AddZeroProp(node, prop): | |
184 | """Add a new property to affected device trees with an integer value of 0. | |
185 | ||
186 | Args: | |
187 | prop_name: Name of property | |
188 | """ | |
189 | for n in GetUpdateNodes(node): | |
190 | n.AddZeroProp(prop) | |
191 | ||
0a98b28b SG |
192 | def AddSubnode(node, name): |
193 | """Add a new subnode to a node in affected device trees | |
194 | ||
195 | Args: | |
196 | node: Node to add to | |
197 | name: name of node to add | |
198 | ||
199 | Returns: | |
200 | New subnode that was created in main tree | |
201 | """ | |
202 | first = None | |
203 | for n in GetUpdateNodes(node): | |
204 | subnode = n.AddSubnode(name) | |
205 | if not first: | |
206 | first = subnode | |
207 | return first | |
208 | ||
209 | def AddString(node, prop, value): | |
210 | """Add a new string property to affected device trees | |
211 | ||
212 | Args: | |
213 | prop_name: Name of property | |
214 | value: String value (which will be \0-terminated in the DT) | |
215 | """ | |
216 | for n in GetUpdateNodes(node): | |
217 | n.AddString(prop, value) | |
218 | ||
f46621d2 SG |
219 | def SetInt(node, prop, value): |
220 | """Update an integer property in affected device trees with an integer value | |
221 | ||
222 | This is not allowed to change the size of the FDT. | |
223 | ||
224 | Args: | |
225 | prop_name: Name of property | |
226 | """ | |
227 | for n in GetUpdateNodes(node): | |
228 | n.SetInt(prop, value) |