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 
add_label(struct label ** labels,char * label)27 void add_label(struct label **labels, char *label)
28 {
29 	struct label *new;
30 
31 	/* Make sure the label isn't already there */
32 	for_each_label(*labels, new)
33 		if (streq(new->label, label))
34 			return;
35 
36 	new = xmalloc(sizeof(*new));
37 	new->label = label;
38 	new->next = *labels;
39 	*labels = new;
40 }
41 
build_property(char * name,struct data val)42 struct property *build_property(char *name, struct data val)
43 {
44 	struct property *new = xmalloc(sizeof(*new));
45 
46 	memset(new, 0, sizeof(*new));
47 
48 	new->name = name;
49 	new->val = val;
50 
51 	return new;
52 }
53 
chain_property(struct property * first,struct property * list)54 struct property *chain_property(struct property *first, struct property *list)
55 {
56 	assert(first->next == NULL);
57 
58 	first->next = list;
59 	return first;
60 }
61 
reverse_properties(struct property * first)62 struct property *reverse_properties(struct property *first)
63 {
64 	struct property *p = first;
65 	struct property *head = NULL;
66 	struct property *next;
67 
68 	while (p) {
69 		next = p->next;
70 		p->next = head;
71 		head = p;
72 		p = next;
73 	}
74 	return head;
75 }
76 
build_node(struct property * proplist,struct node * children)77 struct node *build_node(struct property *proplist, struct node *children)
78 {
79 	struct node *new = xmalloc(sizeof(*new));
80 	struct node *child;
81 
82 	memset(new, 0, sizeof(*new));
83 
84 	new->proplist = reverse_properties(proplist);
85 	new->children = children;
86 
87 	for_each_child(new, child) {
88 		child->parent = new;
89 	}
90 
91 	return new;
92 }
93 
name_node(struct node * node,char * name)94 struct node *name_node(struct node *node, char *name)
95 {
96 	assert(node->name == NULL);
97 
98 	node->name = name;
99 
100 	return node;
101 }
102 
merge_nodes(struct node * old_node,struct node * new_node)103 struct node *merge_nodes(struct node *old_node, struct node *new_node)
104 {
105 	struct property *new_prop, *old_prop;
106 	struct node *new_child, *old_child;
107 	struct label *l;
108 
109 	/* Add new node labels to old node */
110 	for_each_label(new_node->labels, l)
111 		add_label(&old_node->labels, l->label);
112 
113 	/* Move properties from the new node to the old node.  If there
114 	 * is a collision, replace the old value with the new */
115 	while (new_node->proplist) {
116 		/* Pop the property off the list */
117 		new_prop = new_node->proplist;
118 		new_node->proplist = new_prop->next;
119 		new_prop->next = NULL;
120 
121 		/* Look for a collision, set new value if there is */
122 		for_each_property(old_node, old_prop) {
123 			if (streq(old_prop->name, new_prop->name)) {
124 				/* Add new labels to old property */
125 				for_each_label(new_prop->labels, l)
126 					add_label(&old_prop->labels, l->label);
127 
128 				old_prop->val = new_prop->val;
129 				free(new_prop);
130 				new_prop = NULL;
131 				break;
132 			}
133 		}
134 
135 		/* if no collision occurred, add property to the old node. */
136 		if (new_prop)
137 			add_property(old_node, new_prop);
138 	}
139 
140 	/* Move the override child nodes into the primary node.  If
141 	 * there is a collision, then merge the nodes. */
142 	while (new_node->children) {
143 		/* Pop the child node off the list */
144 		new_child = new_node->children;
145 		new_node->children = new_child->next_sibling;
146 		new_child->parent = NULL;
147 		new_child->next_sibling = NULL;
148 
149 		/* Search for a collision.  Merge if there is */
150 		for_each_child(old_node, old_child) {
151 			if (streq(old_child->name, new_child->name)) {
152 				merge_nodes(old_child, new_child);
153 				new_child = NULL;
154 				break;
155 			}
156 		}
157 
158 		/* if no collision occurred, add child to the old node. */
159 		if (new_child)
160 			add_child(old_node, new_child);
161 	}
162 
163 	/* The new node contents are now merged into the old node.  Free
164 	 * the new node. */
165 	free(new_node);
166 
167 	return old_node;
168 }
169 
chain_node(struct node * first,struct node * list)170 struct node *chain_node(struct node *first, struct node *list)
171 {
172 	assert(first->next_sibling == NULL);
173 
174 	first->next_sibling = list;
175 	return first;
176 }
177 
add_property(struct node * node,struct property * prop)178 void add_property(struct node *node, struct property *prop)
179 {
180 	struct property **p;
181 
182 	prop->next = NULL;
183 
184 	p = &node->proplist;
185 	while (*p)
186 		p = &((*p)->next);
187 
188 	*p = prop;
189 }
190 
add_child(struct node * parent,struct node * child)191 void add_child(struct node *parent, struct node *child)
192 {
193 	struct node **p;
194 
195 	child->next_sibling = NULL;
196 	child->parent = parent;
197 
198 	p = &parent->children;
199 	while (*p)
200 		p = &((*p)->next_sibling);
201 
202 	*p = child;
203 }
204 
build_reserve_entry(uint64_t address,uint64_t size)205 struct reserve_info *build_reserve_entry(uint64_t address, uint64_t size)
206 {
207 	struct reserve_info *new = xmalloc(sizeof(*new));
208 
209 	memset(new, 0, sizeof(*new));
210 
211 	new->re.address = address;
212 	new->re.size = size;
213 
214 	return new;
215 }
216 
chain_reserve_entry(struct reserve_info * first,struct reserve_info * list)217 struct reserve_info *chain_reserve_entry(struct reserve_info *first,
218 					struct reserve_info *list)
219 {
220 	assert(first->next == NULL);
221 
222 	first->next = list;
223 	return first;
224 }
225 
add_reserve_entry(struct reserve_info * list,struct reserve_info * new)226 struct reserve_info *add_reserve_entry(struct reserve_info *list,
227 				      struct reserve_info *new)
228 {
229 	struct reserve_info *last;
230 
231 	new->next = NULL;
232 
233 	if (! list)
234 		return new;
235 
236 	for (last = list; last->next; last = last->next)
237 		;
238 
239 	last->next = new;
240 
241 	return list;
242 }
243 
build_boot_info(struct reserve_info * reservelist,struct node * tree,uint32_t boot_cpuid_phys)244 struct boot_info *build_boot_info(struct reserve_info *reservelist,
245 				  struct node *tree, uint32_t boot_cpuid_phys)
246 {
247 	struct boot_info *bi;
248 
249 	bi = xmalloc(sizeof(*bi));
250 	bi->reservelist = reservelist;
251 	bi->dt = tree;
252 	bi->boot_cpuid_phys = boot_cpuid_phys;
253 
254 	return bi;
255 }
256 
257 /*
258  * Tree accessor functions
259  */
260 
get_unitname(struct node * node)261 const char *get_unitname(struct node *node)
262 {
263 	if (node->name[node->basenamelen] == '\0')
264 		return "";
265 	else
266 		return node->name + node->basenamelen + 1;
267 }
268 
get_property(struct node * node,const char * propname)269 struct property *get_property(struct node *node, const char *propname)
270 {
271 	struct property *prop;
272 
273 	for_each_property(node, prop)
274 		if (streq(prop->name, propname))
275 			return prop;
276 
277 	return NULL;
278 }
279 
propval_cell(struct property * prop)280 cell_t propval_cell(struct property *prop)
281 {
282 	assert(prop->val.len == sizeof(cell_t));
283 	return fdt32_to_cpu(*((cell_t *)prop->val.val));
284 }
285 
get_property_by_label(struct node * tree,const char * label,struct node ** node)286 struct property *get_property_by_label(struct node *tree, const char *label,
287 				       struct node **node)
288 {
289 	struct property *prop;
290 	struct node *c;
291 
292 	*node = tree;
293 
294 	for_each_property(tree, prop) {
295 		struct label *l;
296 
297 		for_each_label(prop->labels, l)
298 			if (streq(l->label, label))
299 				return prop;
300 	}
301 
302 	for_each_child(tree, c) {
303 		prop = get_property_by_label(c, label, node);
304 		if (prop)
305 			return prop;
306 	}
307 
308 	*node = NULL;
309 	return NULL;
310 }
311 
get_marker_label(struct node * tree,const char * label,struct node ** node,struct property ** prop)312 struct marker *get_marker_label(struct node *tree, const char *label,
313 				struct node **node, struct property **prop)
314 {
315 	struct marker *m;
316 	struct property *p;
317 	struct node *c;
318 
319 	*node = tree;
320 
321 	for_each_property(tree, p) {
322 		*prop = p;
323 		m = p->val.markers;
324 		for_each_marker_of_type(m, LABEL)
325 			if (streq(m->ref, label))
326 				return m;
327 	}
328 
329 	for_each_child(tree, c) {
330 		m = get_marker_label(c, label, node, prop);
331 		if (m)
332 			return m;
333 	}
334 
335 	*prop = NULL;
336 	*node = NULL;
337 	return NULL;
338 }
339 
get_subnode(struct node * node,const char * nodename)340 struct node *get_subnode(struct node *node, const char *nodename)
341 {
342 	struct node *child;
343 
344 	for_each_child(node, child)
345 		if (streq(child->name, nodename))
346 			return child;
347 
348 	return NULL;
349 }
350 
get_node_by_path(struct node * tree,const char * path)351 struct node *get_node_by_path(struct node *tree, const char *path)
352 {
353 	const char *p;
354 	struct node *child;
355 
356 	if (!path || ! (*path))
357 		return tree;
358 
359 	while (path[0] == '/')
360 		path++;
361 
362 	p = strchr(path, '/');
363 
364 	for_each_child(tree, child) {
365 		if (p && strneq(path, child->name, p-path))
366 			return get_node_by_path(child, p+1);
367 		else if (!p && streq(path, child->name))
368 			return child;
369 	}
370 
371 	return NULL;
372 }
373 
get_node_by_label(struct node * tree,const char * label)374 struct node *get_node_by_label(struct node *tree, const char *label)
375 {
376 	struct node *child, *node;
377 	struct label *l;
378 
379 	assert(label && (strlen(label) > 0));
380 
381 	for_each_label(tree->labels, l)
382 		if (streq(l->label, label))
383 			return tree;
384 
385 	for_each_child(tree, child) {
386 		node = get_node_by_label(child, label);
387 		if (node)
388 			return node;
389 	}
390 
391 	return NULL;
392 }
393 
get_node_by_phandle(struct node * tree,cell_t phandle)394 struct node *get_node_by_phandle(struct node *tree, cell_t phandle)
395 {
396 	struct node *child, *node;
397 
398 	assert((phandle != 0) && (phandle != -1));
399 
400 	if (tree->phandle == phandle)
401 		return tree;
402 
403 	for_each_child(tree, child) {
404 		node = get_node_by_phandle(child, phandle);
405 		if (node)
406 			return node;
407 	}
408 
409 	return NULL;
410 }
411 
get_node_by_ref(struct node * tree,const char * ref)412 struct node *get_node_by_ref(struct node *tree, const char *ref)
413 {
414 	if (ref[0] == '/')
415 		return get_node_by_path(tree, ref);
416 	else
417 		return get_node_by_label(tree, ref);
418 }
419 
get_node_phandle(struct node * root,struct node * node)420 cell_t get_node_phandle(struct node *root, struct node *node)
421 {
422 	static cell_t phandle = 1; /* FIXME: ick, static local */
423 
424 	if ((node->phandle != 0) && (node->phandle != -1))
425 		return node->phandle;
426 
427 	while (get_node_by_phandle(root, phandle))
428 		phandle++;
429 
430 	node->phandle = phandle;
431 
432 	if (!get_property(node, "linux,phandle")
433 	    && (phandle_format & PHANDLE_LEGACY))
434 		add_property(node,
435 			     build_property("linux,phandle",
436 					    data_append_cell(empty_data, phandle)));
437 
438 	if (!get_property(node, "phandle")
439 	    && (phandle_format & PHANDLE_EPAPR))
440 		add_property(node,
441 			     build_property("phandle",
442 					    data_append_cell(empty_data, phandle)));
443 
444 	/* If the node *does* have a phandle property, we must
445 	 * be dealing with a self-referencing phandle, which will be
446 	 * fixed up momentarily in the caller */
447 
448 	return node->phandle;
449 }
450 
guess_boot_cpuid(struct node * tree)451 uint32_t guess_boot_cpuid(struct node *tree)
452 {
453 	struct node *cpus, *bootcpu;
454 	struct property *reg;
455 
456 	cpus = get_node_by_path(tree, "/cpus");
457 	if (!cpus)
458 		return 0;
459 
460 
461 	bootcpu = cpus->children;
462 	if (!bootcpu)
463 		return 0;
464 
465 	reg = get_property(bootcpu, "reg");
466 	if (!reg || (reg->val.len != sizeof(uint32_t)))
467 		return 0;
468 
469 	/* FIXME: Sanity check node? */
470 
471 	return propval_cell(reg);
472 }
473 
cmp_reserve_info(const void * ax,const void * bx)474 static int cmp_reserve_info(const void *ax, const void *bx)
475 {
476 	const struct reserve_info *a, *b;
477 
478 	a = *((const struct reserve_info * const *)ax);
479 	b = *((const struct reserve_info * const *)bx);
480 
481 	if (a->re.address < b->re.address)
482 		return -1;
483 	else if (a->re.address > b->re.address)
484 		return 1;
485 	else if (a->re.size < b->re.size)
486 		return -1;
487 	else if (a->re.size > b->re.size)
488 		return 1;
489 	else
490 		return 0;
491 }
492 
sort_reserve_entries(struct boot_info * bi)493 static void sort_reserve_entries(struct boot_info *bi)
494 {
495 	struct reserve_info *ri, **tbl;
496 	int n = 0, i = 0;
497 
498 	for (ri = bi->reservelist;
499 	     ri;
500 	     ri = ri->next)
501 		n++;
502 
503 	if (n == 0)
504 		return;
505 
506 	tbl = xmalloc(n * sizeof(*tbl));
507 
508 	for (ri = bi->reservelist;
509 	     ri;
510 	     ri = ri->next)
511 		tbl[i++] = ri;
512 
513 	qsort(tbl, n, sizeof(*tbl), cmp_reserve_info);
514 
515 	bi->reservelist = tbl[0];
516 	for (i = 0; i < (n-1); i++)
517 		tbl[i]->next = tbl[i+1];
518 	tbl[n-1]->next = NULL;
519 
520 	free(tbl);
521 }
522 
cmp_prop(const void * ax,const void * bx)523 static int cmp_prop(const void *ax, const void *bx)
524 {
525 	const struct property *a, *b;
526 
527 	a = *((const struct property * const *)ax);
528 	b = *((const struct property * const *)bx);
529 
530 	return strcmp(a->name, b->name);
531 }
532 
sort_properties(struct node * node)533 static void sort_properties(struct node *node)
534 {
535 	int n = 0, i = 0;
536 	struct property *prop, **tbl;
537 
538 	for_each_property(node, prop)
539 		n++;
540 
541 	if (n == 0)
542 		return;
543 
544 	tbl = xmalloc(n * sizeof(*tbl));
545 
546 	for_each_property(node, prop)
547 		tbl[i++] = prop;
548 
549 	qsort(tbl, n, sizeof(*tbl), cmp_prop);
550 
551 	node->proplist = tbl[0];
552 	for (i = 0; i < (n-1); i++)
553 		tbl[i]->next = tbl[i+1];
554 	tbl[n-1]->next = NULL;
555 
556 	free(tbl);
557 }
558 
cmp_subnode(const void * ax,const void * bx)559 static int cmp_subnode(const void *ax, const void *bx)
560 {
561 	const struct node *a, *b;
562 
563 	a = *((const struct node * const *)ax);
564 	b = *((const struct node * const *)bx);
565 
566 	return strcmp(a->name, b->name);
567 }
568 
sort_subnodes(struct node * node)569 static void sort_subnodes(struct node *node)
570 {
571 	int n = 0, i = 0;
572 	struct node *subnode, **tbl;
573 
574 	for_each_child(node, subnode)
575 		n++;
576 
577 	if (n == 0)
578 		return;
579 
580 	tbl = xmalloc(n * sizeof(*tbl));
581 
582 	for_each_child(node, subnode)
583 		tbl[i++] = subnode;
584 
585 	qsort(tbl, n, sizeof(*tbl), cmp_subnode);
586 
587 	node->children = tbl[0];
588 	for (i = 0; i < (n-1); i++)
589 		tbl[i]->next_sibling = tbl[i+1];
590 	tbl[n-1]->next_sibling = NULL;
591 
592 	free(tbl);
593 }
594 
sort_node(struct node * node)595 static void sort_node(struct node *node)
596 {
597 	struct node *c;
598 
599 	sort_properties(node);
600 	sort_subnodes(node);
601 	for_each_child(node, c)
602 		sort_node(c);
603 }
604 
sort_tree(struct boot_info * bi)605 void sort_tree(struct boot_info *bi)
606 {
607 	sort_reserve_entries(bi);
608 	sort_node(bi->dt);
609 }
610