diff options
Diffstat (limited to 'scripts/dtc/livetree.c')
-rw-r--r-- | scripts/dtc/livetree.c | 308 |
1 files changed, 308 insertions, 0 deletions
diff --git a/scripts/dtc/livetree.c b/scripts/dtc/livetree.c new file mode 100644 index 000000000000..0ca3de550b3f --- /dev/null +++ b/scripts/dtc/livetree.c | |||
@@ -0,0 +1,308 @@ | |||
1 | /* | ||
2 | * (C) Copyright David Gibson <dwg@au1.ibm.com>, IBM Corporation. 2005. | ||
3 | * | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or | ||
6 | * modify it under the terms of the GNU General Public License as | ||
7 | * published by the Free Software Foundation; either version 2 of the | ||
8 | * License, or (at your option) any later version. | ||
9 | * | ||
10 | * This program is distributed in the hope that it will be useful, | ||
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | * General Public License for more details. | ||
14 | * | ||
15 | * You should have received a copy of the GNU General Public License | ||
16 | * along with this program; if not, write to the Free Software | ||
17 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 | ||
18 | * USA | ||
19 | */ | ||
20 | |||
21 | #include "dtc.h" | ||
22 | |||
23 | /* | ||
24 | * Tree building functions | ||
25 | */ | ||
26 | |||
27 | struct property *build_property(char *name, struct data val, char *label) | ||
28 | { | ||
29 | struct property *new = xmalloc(sizeof(*new)); | ||
30 | |||
31 | new->name = name; | ||
32 | new->val = val; | ||
33 | |||
34 | new->next = NULL; | ||
35 | |||
36 | new->label = label; | ||
37 | |||
38 | return new; | ||
39 | } | ||
40 | |||
41 | struct property *chain_property(struct property *first, struct property *list) | ||
42 | { | ||
43 | assert(first->next == NULL); | ||
44 | |||
45 | first->next = list; | ||
46 | return first; | ||
47 | } | ||
48 | |||
49 | struct property *reverse_properties(struct property *first) | ||
50 | { | ||
51 | struct property *p = first; | ||
52 | struct property *head = NULL; | ||
53 | struct property *next; | ||
54 | |||
55 | while (p) { | ||
56 | next = p->next; | ||
57 | p->next = head; | ||
58 | head = p; | ||
59 | p = next; | ||
60 | } | ||
61 | return head; | ||
62 | } | ||
63 | |||
64 | struct node *build_node(struct property *proplist, struct node *children) | ||
65 | { | ||
66 | struct node *new = xmalloc(sizeof(*new)); | ||
67 | struct node *child; | ||
68 | |||
69 | memset(new, 0, sizeof(*new)); | ||
70 | |||
71 | new->proplist = reverse_properties(proplist); | ||
72 | new->children = children; | ||
73 | |||
74 | for_each_child(new, child) { | ||
75 | child->parent = new; | ||
76 | } | ||
77 | |||
78 | return new; | ||
79 | } | ||
80 | |||
81 | struct node *name_node(struct node *node, char *name, char * label) | ||
82 | { | ||
83 | assert(node->name == NULL); | ||
84 | |||
85 | node->name = name; | ||
86 | |||
87 | node->label = label; | ||
88 | |||
89 | return node; | ||
90 | } | ||
91 | |||
92 | struct node *chain_node(struct node *first, struct node *list) | ||
93 | { | ||
94 | assert(first->next_sibling == NULL); | ||
95 | |||
96 | first->next_sibling = list; | ||
97 | return first; | ||
98 | } | ||
99 | |||
100 | void add_property(struct node *node, struct property *prop) | ||
101 | { | ||
102 | struct property **p; | ||
103 | |||
104 | prop->next = NULL; | ||
105 | |||
106 | p = &node->proplist; | ||
107 | while (*p) | ||
108 | p = &((*p)->next); | ||
109 | |||
110 | *p = prop; | ||
111 | } | ||
112 | |||
113 | void add_child(struct node *parent, struct node *child) | ||
114 | { | ||
115 | struct node **p; | ||
116 | |||
117 | child->next_sibling = NULL; | ||
118 | child->parent = parent; | ||
119 | |||
120 | p = &parent->children; | ||
121 | while (*p) | ||
122 | p = &((*p)->next_sibling); | ||
123 | |||
124 | *p = child; | ||
125 | } | ||
126 | |||
127 | struct reserve_info *build_reserve_entry(uint64_t address, uint64_t size, | ||
128 | char *label) | ||
129 | { | ||
130 | struct reserve_info *new = xmalloc(sizeof(*new)); | ||
131 | |||
132 | new->re.address = address; | ||
133 | new->re.size = size; | ||
134 | |||
135 | new->next = NULL; | ||
136 | |||
137 | new->label = label; | ||
138 | |||
139 | return new; | ||
140 | } | ||
141 | |||
142 | struct reserve_info *chain_reserve_entry(struct reserve_info *first, | ||
143 | struct reserve_info *list) | ||
144 | { | ||
145 | assert(first->next == NULL); | ||
146 | |||
147 | first->next = list; | ||
148 | return first; | ||
149 | } | ||
150 | |||
151 | struct reserve_info *add_reserve_entry(struct reserve_info *list, | ||
152 | struct reserve_info *new) | ||
153 | { | ||
154 | struct reserve_info *last; | ||
155 | |||
156 | new->next = NULL; | ||
157 | |||
158 | if (! list) | ||
159 | return new; | ||
160 | |||
161 | for (last = list; last->next; last = last->next) | ||
162 | ; | ||
163 | |||
164 | last->next = new; | ||
165 | |||
166 | return list; | ||
167 | } | ||
168 | |||
169 | struct boot_info *build_boot_info(struct reserve_info *reservelist, | ||
170 | struct node *tree, uint32_t boot_cpuid_phys) | ||
171 | { | ||
172 | struct boot_info *bi; | ||
173 | |||
174 | bi = xmalloc(sizeof(*bi)); | ||
175 | bi->reservelist = reservelist; | ||
176 | bi->dt = tree; | ||
177 | bi->boot_cpuid_phys = boot_cpuid_phys; | ||
178 | |||
179 | return bi; | ||
180 | } | ||
181 | |||
182 | /* | ||
183 | * Tree accessor functions | ||
184 | */ | ||
185 | |||
186 | const char *get_unitname(struct node *node) | ||
187 | { | ||
188 | if (node->name[node->basenamelen] == '\0') | ||
189 | return ""; | ||
190 | else | ||
191 | return node->name + node->basenamelen + 1; | ||
192 | } | ||
193 | |||
194 | struct property *get_property(struct node *node, const char *propname) | ||
195 | { | ||
196 | struct property *prop; | ||
197 | |||
198 | for_each_property(node, prop) | ||
199 | if (streq(prop->name, propname)) | ||
200 | return prop; | ||
201 | |||
202 | return NULL; | ||
203 | } | ||
204 | |||
205 | cell_t propval_cell(struct property *prop) | ||
206 | { | ||
207 | assert(prop->val.len == sizeof(cell_t)); | ||
208 | return fdt32_to_cpu(*((cell_t *)prop->val.val)); | ||
209 | } | ||
210 | |||
211 | struct node *get_subnode(struct node *node, const char *nodename) | ||
212 | { | ||
213 | struct node *child; | ||
214 | |||
215 | for_each_child(node, child) | ||
216 | if (streq(child->name, nodename)) | ||
217 | return child; | ||
218 | |||
219 | return NULL; | ||
220 | } | ||
221 | |||
222 | struct node *get_node_by_path(struct node *tree, const char *path) | ||
223 | { | ||
224 | const char *p; | ||
225 | struct node *child; | ||
226 | |||
227 | if (!path || ! (*path)) | ||
228 | return tree; | ||
229 | |||
230 | while (path[0] == '/') | ||
231 | path++; | ||
232 | |||
233 | p = strchr(path, '/'); | ||
234 | |||
235 | for_each_child(tree, child) { | ||
236 | if (p && strneq(path, child->name, p-path)) | ||
237 | return get_node_by_path(child, p+1); | ||
238 | else if (!p && streq(path, child->name)) | ||
239 | return child; | ||
240 | } | ||
241 | |||
242 | return NULL; | ||
243 | } | ||
244 | |||
245 | struct node *get_node_by_label(struct node *tree, const char *label) | ||
246 | { | ||
247 | struct node *child, *node; | ||
248 | |||
249 | assert(label && (strlen(label) > 0)); | ||
250 | |||
251 | if (tree->label && streq(tree->label, label)) | ||
252 | return tree; | ||
253 | |||
254 | for_each_child(tree, child) { | ||
255 | node = get_node_by_label(child, label); | ||
256 | if (node) | ||
257 | return node; | ||
258 | } | ||
259 | |||
260 | return NULL; | ||
261 | } | ||
262 | |||
263 | struct node *get_node_by_phandle(struct node *tree, cell_t phandle) | ||
264 | { | ||
265 | struct node *child, *node; | ||
266 | |||
267 | assert((phandle != 0) && (phandle != -1)); | ||
268 | |||
269 | if (tree->phandle == phandle) | ||
270 | return tree; | ||
271 | |||
272 | for_each_child(tree, child) { | ||
273 | node = get_node_by_phandle(child, phandle); | ||
274 | if (node) | ||
275 | return node; | ||
276 | } | ||
277 | |||
278 | return NULL; | ||
279 | } | ||
280 | |||
281 | struct node *get_node_by_ref(struct node *tree, const char *ref) | ||
282 | { | ||
283 | if (ref[0] == '/') | ||
284 | return get_node_by_path(tree, ref); | ||
285 | else | ||
286 | return get_node_by_label(tree, ref); | ||
287 | } | ||
288 | |||
289 | cell_t get_node_phandle(struct node *root, struct node *node) | ||
290 | { | ||
291 | static cell_t phandle = 1; /* FIXME: ick, static local */ | ||
292 | |||
293 | if ((node->phandle != 0) && (node->phandle != -1)) | ||
294 | return node->phandle; | ||
295 | |||
296 | assert(! get_property(node, "linux,phandle")); | ||
297 | |||
298 | while (get_node_by_phandle(root, phandle)) | ||
299 | phandle++; | ||
300 | |||
301 | node->phandle = phandle; | ||
302 | add_property(node, | ||
303 | build_property("linux,phandle", | ||
304 | data_append_cell(empty_data, phandle), | ||
305 | NULL)); | ||
306 | |||
307 | return node->phandle; | ||
308 | } | ||