Home | History | Annotate | Download | only in dtc
      1 /*
      2  * (C) Copyright David Gibson <dwg (at) 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 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_withdel(*labels, new)
     33 		if (streq(new->label, label)) {
     34 			new->deleted = 0;
     35 			return;
     36 		}
     37 
     38 	new = xmalloc(sizeof(*new));
     39 	memset(new, 0, sizeof(*new));
     40 	new->label = label;
     41 	new->next = *labels;
     42 	*labels = new;
     43 }
     44 
     45 void delete_labels(struct label **labels)
     46 {
     47 	struct label *label;
     48 
     49 	for_each_label(*labels, label)
     50 		label->deleted = 1;
     51 }
     52 
     53 struct property *build_property(char *name, struct data val)
     54 {
     55 	struct property *new = xmalloc(sizeof(*new));
     56 
     57 	memset(new, 0, sizeof(*new));
     58 
     59 	new->name = name;
     60 	new->val = val;
     61 
     62 	return new;
     63 }
     64 
     65 struct property *build_property_delete(char *name)
     66 {
     67 	struct property *new = xmalloc(sizeof(*new));
     68 
     69 	memset(new, 0, sizeof(*new));
     70 
     71 	new->name = name;
     72 	new->deleted = 1;
     73 
     74 	return new;
     75 }
     76 
     77 struct property *chain_property(struct property *first, struct property *list)
     78 {
     79 	assert(first->next == NULL);
     80 
     81 	first->next = list;
     82 	return first;
     83 }
     84 
     85 struct property *reverse_properties(struct property *first)
     86 {
     87 	struct property *p = first;
     88 	struct property *head = NULL;
     89 	struct property *next;
     90 
     91 	while (p) {
     92 		next = p->next;
     93 		p->next = head;
     94 		head = p;
     95 		p = next;
     96 	}
     97 	return head;
     98 }
     99 
    100 struct node *build_node(struct property *proplist, struct node *children)
    101 {
    102 	struct node *new = xmalloc(sizeof(*new));
    103 	struct node *child;
    104 
    105 	memset(new, 0, sizeof(*new));
    106 
    107 	new->proplist = reverse_properties(proplist);
    108 	new->children = children;
    109 
    110 	for_each_child(new, child) {
    111 		child->parent = new;
    112 	}
    113 
    114 	return new;
    115 }
    116 
    117 struct node *build_node_delete(void)
    118 {
    119 	struct node *new = xmalloc(sizeof(*new));
    120 
    121 	memset(new, 0, sizeof(*new));
    122 
    123 	new->deleted = 1;
    124 
    125 	return new;
    126 }
    127 
    128 struct node *name_node(struct node *node, char *name)
    129 {
    130 	assert(node->name == NULL);
    131 
    132 	node->name = name;
    133 
    134 	return node;
    135 }
    136 
    137 struct node *merge_nodes(struct node *old_node, struct node *new_node)
    138 {
    139 	struct property *new_prop, *old_prop;
    140 	struct node *new_child, *old_child;
    141 	struct label *l;
    142 
    143 	old_node->deleted = 0;
    144 
    145 	/* Add new node labels to old node */
    146 	for_each_label_withdel(new_node->labels, l)
    147 		add_label(&old_node->labels, l->label);
    148 
    149 	/* Move properties from the new node to the old node.  If there
    150 	 * is a collision, replace the old value with the new */
    151 	while (new_node->proplist) {
    152 		/* Pop the property off the list */
    153 		new_prop = new_node->proplist;
    154 		new_node->proplist = new_prop->next;
    155 		new_prop->next = NULL;
    156 
    157 		if (new_prop->deleted) {
    158 			delete_property_by_name(old_node, new_prop->name);
    159 			free(new_prop);
    160 			continue;
    161 		}
    162 
    163 		/* Look for a collision, set new value if there is */
    164 		for_each_property_withdel(old_node, old_prop) {
    165 			if (streq(old_prop->name, new_prop->name)) {
    166 				/* Add new labels to old property */
    167 				for_each_label_withdel(new_prop->labels, l)
    168 					add_label(&old_prop->labels, l->label);
    169 
    170 				old_prop->val = new_prop->val;
    171 				old_prop->deleted = 0;
    172 				free(new_prop);
    173 				new_prop = NULL;
    174 				break;
    175 			}
    176 		}
    177 
    178 		/* if no collision occurred, add property to the old node. */
    179 		if (new_prop)
    180 			add_property(old_node, new_prop);
    181 	}
    182 
    183 	/* Move the override child nodes into the primary node.  If
    184 	 * there is a collision, then merge the nodes. */
    185 	while (new_node->children) {
    186 		/* Pop the child node off the list */
    187 		new_child = new_node->children;
    188 		new_node->children = new_child->next_sibling;
    189 		new_child->parent = NULL;
    190 		new_child->next_sibling = NULL;
    191 
    192 		if (new_child->deleted) {
    193 			delete_node_by_name(old_node, new_child->name);
    194 			free(new_child);
    195 			continue;
    196 		}
    197 
    198 		/* Search for a collision.  Merge if there is */
    199 		for_each_child_withdel(old_node, old_child) {
    200 			if (streq(old_child->name, new_child->name)) {
    201 				merge_nodes(old_child, new_child);
    202 				new_child = NULL;
    203 				break;
    204 			}
    205 		}
    206 
    207 		/* if no collision occurred, add child to the old node. */
    208 		if (new_child)
    209 			add_child(old_node, new_child);
    210 	}
    211 
    212 	/* The new node contents are now merged into the old node.  Free
    213 	 * the new node. */
    214 	free(new_node);
    215 
    216 	return old_node;
    217 }
    218 
    219 struct node * add_orphan_node(struct node *dt, struct node *new_node, char *ref)
    220 {
    221 	static unsigned int next_orphan_fragment = 0;
    222 	struct node *node;
    223 	struct property *p;
    224 	struct data d = empty_data;
    225 	char *name;
    226 
    227 	d = data_add_marker(d, REF_PHANDLE, ref);
    228 	d = data_append_integer(d, 0xffffffff, 32);
    229 
    230 	p = build_property("target", d);
    231 
    232 	xasprintf(&name, "fragment@%u",
    233 			next_orphan_fragment++);
    234 	name_node(new_node, "__overlay__");
    235 	node = build_node(p, new_node);
    236 	name_node(node, name);
    237 
    238 	add_child(dt, node);
    239 	return dt;
    240 }
    241 
    242 struct node *chain_node(struct node *first, struct node *list)
    243 {
    244 	assert(first->next_sibling == NULL);
    245 
    246 	first->next_sibling = list;
    247 	return first;
    248 }
    249 
    250 void add_property(struct node *node, struct property *prop)
    251 {
    252 	struct property **p;
    253 
    254 	prop->next = NULL;
    255 
    256 	p = &node->proplist;
    257 	while (*p)
    258 		p = &((*p)->next);
    259 
    260 	*p = prop;
    261 }
    262 
    263 void delete_property_by_name(struct node *node, char *name)
    264 {
    265 	struct property *prop = node->proplist;
    266 
    267 	while (prop) {
    268 		if (streq(prop->name, name)) {
    269 			delete_property(prop);
    270 			return;
    271 		}
    272 		prop = prop->next;
    273 	}
    274 }
    275 
    276 void delete_property(struct property *prop)
    277 {
    278 	prop->deleted = 1;
    279 	delete_labels(&prop->labels);
    280 }
    281 
    282 void add_child(struct node *parent, struct node *child)
    283 {
    284 	struct node **p;
    285 
    286 	child->next_sibling = NULL;
    287 	child->parent = parent;
    288 
    289 	p = &parent->children;
    290 	while (*p)
    291 		p = &((*p)->next_sibling);
    292 
    293 	*p = child;
    294 }
    295 
    296 void delete_node_by_name(struct node *parent, char *name)
    297 {
    298 	struct node *node = parent->children;
    299 
    300 	while (node) {
    301 		if (streq(node->name, name)) {
    302 			delete_node(node);
    303 			return;
    304 		}
    305 		node = node->next_sibling;
    306 	}
    307 }
    308 
    309 void delete_node(struct node *node)
    310 {
    311 	struct property *prop;
    312 	struct node *child;
    313 
    314 	node->deleted = 1;
    315 	for_each_child(node, child)
    316 		delete_node(child);
    317 	for_each_property(node, prop)
    318 		delete_property(prop);
    319 	delete_labels(&node->labels);
    320 }
    321 
    322 void append_to_property(struct node *node,
    323 				    char *name, const void *data, int len)
    324 {
    325 	struct data d;
    326 	struct property *p;
    327 
    328 	p = get_property(node, name);
    329 	if (p) {
    330 		d = data_append_data(p->val, data, len);
    331 		p->val = d;
    332 	} else {
    333 		d = data_append_data(empty_data, data, len);
    334 		p = build_property(name, d);
    335 		add_property(node, p);
    336 	}
    337 }
    338 
    339 struct reserve_info *build_reserve_entry(uint64_t address, uint64_t size)
    340 {
    341 	struct reserve_info *new = xmalloc(sizeof(*new));
    342 
    343 	memset(new, 0, sizeof(*new));
    344 
    345 	new->address = address;
    346 	new->size = size;
    347 
    348 	return new;
    349 }
    350 
    351 struct reserve_info *chain_reserve_entry(struct reserve_info *first,
    352 					struct reserve_info *list)
    353 {
    354 	assert(first->next == NULL);
    355 
    356 	first->next = list;
    357 	return first;
    358 }
    359 
    360 struct reserve_info *add_reserve_entry(struct reserve_info *list,
    361 				      struct reserve_info *new)
    362 {
    363 	struct reserve_info *last;
    364 
    365 	new->next = NULL;
    366 
    367 	if (! list)
    368 		return new;
    369 
    370 	for (last = list; last->next; last = last->next)
    371 		;
    372 
    373 	last->next = new;
    374 
    375 	return list;
    376 }
    377 
    378 struct dt_info *build_dt_info(unsigned int dtsflags,
    379 			      struct reserve_info *reservelist,
    380 			      struct node *tree, uint32_t boot_cpuid_phys)
    381 {
    382 	struct dt_info *dti;
    383 
    384 	dti = xmalloc(sizeof(*dti));
    385 	dti->dtsflags = dtsflags;
    386 	dti->reservelist = reservelist;
    387 	dti->dt = tree;
    388 	dti->boot_cpuid_phys = boot_cpuid_phys;
    389 
    390 	return dti;
    391 }
    392 
    393 /*
    394  * Tree accessor functions
    395  */
    396 
    397 const char *get_unitname(struct node *node)
    398 {
    399 	if (node->name[node->basenamelen] == '\0')
    400 		return "";
    401 	else
    402 		return node->name + node->basenamelen + 1;
    403 }
    404 
    405 struct property *get_property(struct node *node, const char *propname)
    406 {
    407 	struct property *prop;
    408 
    409 	for_each_property(node, prop)
    410 		if (streq(prop->name, propname))
    411 			return prop;
    412 
    413 	return NULL;
    414 }
    415 
    416 cell_t propval_cell(struct property *prop)
    417 {
    418 	assert(prop->val.len == sizeof(cell_t));
    419 	return fdt32_to_cpu(*((fdt32_t *)prop->val.val));
    420 }
    421 
    422 cell_t propval_cell_n(struct property *prop, int n)
    423 {
    424 	assert(prop->val.len / sizeof(cell_t) >= n);
    425 	return fdt32_to_cpu(*((fdt32_t *)prop->val.val + n));
    426 }
    427 
    428 struct property *get_property_by_label(struct node *tree, const char *label,
    429 				       struct node **node)
    430 {
    431 	struct property *prop;
    432 	struct node *c;
    433 
    434 	*node = tree;
    435 
    436 	for_each_property(tree, prop) {
    437 		struct label *l;
    438 
    439 		for_each_label(prop->labels, l)
    440 			if (streq(l->label, label))
    441 				return prop;
    442 	}
    443 
    444 	for_each_child(tree, c) {
    445 		prop = get_property_by_label(c, label, node);
    446 		if (prop)
    447 			return prop;
    448 	}
    449 
    450 	*node = NULL;
    451 	return NULL;
    452 }
    453 
    454 struct marker *get_marker_label(struct node *tree, const char *label,
    455 				struct node **node, struct property **prop)
    456 {
    457 	struct marker *m;
    458 	struct property *p;
    459 	struct node *c;
    460 
    461 	*node = tree;
    462 
    463 	for_each_property(tree, p) {
    464 		*prop = p;
    465 		m = p->val.markers;
    466 		for_each_marker_of_type(m, LABEL)
    467 			if (streq(m->ref, label))
    468 				return m;
    469 	}
    470 
    471 	for_each_child(tree, c) {
    472 		m = get_marker_label(c, label, node, prop);
    473 		if (m)
    474 			return m;
    475 	}
    476 
    477 	*prop = NULL;
    478 	*node = NULL;
    479 	return NULL;
    480 }
    481 
    482 struct node *get_subnode(struct node *node, const char *nodename)
    483 {
    484 	struct node *child;
    485 
    486 	for_each_child(node, child)
    487 		if (streq(child->name, nodename))
    488 			return child;
    489 
    490 	return NULL;
    491 }
    492 
    493 struct node *get_node_by_path(struct node *tree, const char *path)
    494 {
    495 	const char *p;
    496 	struct node *child;
    497 
    498 	if (!path || ! (*path)) {
    499 		if (tree->deleted)
    500 			return NULL;
    501 		return tree;
    502 	}
    503 
    504 	while (path[0] == '/')
    505 		path++;
    506 
    507 	p = strchr(path, '/');
    508 
    509 	for_each_child(tree, child) {
    510 		if (p && (strlen(child->name) == p-path) &&
    511 		    strprefixeq(path, p - path, child->name))
    512 			return get_node_by_path(child, p+1);
    513 		else if (!p && streq(path, child->name))
    514 			return child;
    515 	}
    516 
    517 	return NULL;
    518 }
    519 
    520 struct node *get_node_by_label(struct node *tree, const char *label)
    521 {
    522 	struct node *child, *node;
    523 	struct label *l;
    524 
    525 	assert(label && (strlen(label) > 0));
    526 
    527 	for_each_label(tree->labels, l)
    528 		if (streq(l->label, label))
    529 			return tree;
    530 
    531 	for_each_child(tree, child) {
    532 		node = get_node_by_label(child, label);
    533 		if (node)
    534 			return node;
    535 	}
    536 
    537 	return NULL;
    538 }
    539 
    540 struct node *get_node_by_phandle(struct node *tree, cell_t phandle)
    541 {
    542 	struct node *child, *node;
    543 
    544 	if ((phandle == 0) || (phandle == -1)) {
    545 		assert(generate_fixups);
    546 		return NULL;
    547 	}
    548 
    549 	if (tree->phandle == phandle) {
    550 		if (tree->deleted)
    551 			return NULL;
    552 		return tree;
    553 	}
    554 
    555 	for_each_child(tree, child) {
    556 		node = get_node_by_phandle(child, phandle);
    557 		if (node)
    558 			return node;
    559 	}
    560 
    561 	return NULL;
    562 }
    563 
    564 struct node *get_node_by_ref(struct node *tree, const char *ref)
    565 {
    566 	if (streq(ref, "/"))
    567 		return tree;
    568 	else if (ref[0] == '/')
    569 		return get_node_by_path(tree, ref);
    570 	else
    571 		return get_node_by_label(tree, ref);
    572 }
    573 
    574 cell_t get_node_phandle(struct node *root, struct node *node)
    575 {
    576 	static cell_t phandle = 1; /* FIXME: ick, static local */
    577 
    578 	if ((node->phandle != 0) && (node->phandle != -1))
    579 		return node->phandle;
    580 
    581 	while (get_node_by_phandle(root, phandle))
    582 		phandle++;
    583 
    584 	node->phandle = phandle;
    585 
    586 	if (!get_property(node, "linux,phandle")
    587 	    && (phandle_format & PHANDLE_LEGACY))
    588 		add_property(node,
    589 			     build_property("linux,phandle",
    590 					    data_append_cell(empty_data, phandle)));
    591 
    592 	if (!get_property(node, "phandle")
    593 	    && (phandle_format & PHANDLE_EPAPR))
    594 		add_property(node,
    595 			     build_property("phandle",
    596 					    data_append_cell(empty_data, phandle)));
    597 
    598 	/* If the node *does* have a phandle property, we must
    599 	 * be dealing with a self-referencing phandle, which will be
    600 	 * fixed up momentarily in the caller */
    601 
    602 	return node->phandle;
    603 }
    604 
    605 uint32_t guess_boot_cpuid(struct node *tree)
    606 {
    607 	struct node *cpus, *bootcpu;
    608 	struct property *reg;
    609 
    610 	cpus = get_node_by_path(tree, "/cpus");
    611 	if (!cpus)
    612 		return 0;
    613 
    614 
    615 	bootcpu = cpus->children;
    616 	if (!bootcpu)
    617 		return 0;
    618 
    619 	reg = get_property(bootcpu, "reg");
    620 	if (!reg || (reg->val.len != sizeof(uint32_t)))
    621 		return 0;
    622 
    623 	/* FIXME: Sanity check node? */
    624 
    625 	return propval_cell(reg);
    626 }
    627 
    628 static int cmp_reserve_info(const void *ax, const void *bx)
    629 {
    630 	const struct reserve_info *a, *b;
    631 
    632 	a = *((const struct reserve_info * const *)ax);
    633 	b = *((const struct reserve_info * const *)bx);
    634 
    635 	if (a->address < b->address)
    636 		return -1;
    637 	else if (a->address > b->address)
    638 		return 1;
    639 	else if (a->size < b->size)
    640 		return -1;
    641 	else if (a->size > b->size)
    642 		return 1;
    643 	else
    644 		return 0;
    645 }
    646 
    647 static void sort_reserve_entries(struct dt_info *dti)
    648 {
    649 	struct reserve_info *ri, **tbl;
    650 	int n = 0, i = 0;
    651 
    652 	for (ri = dti->reservelist;
    653 	     ri;
    654 	     ri = ri->next)
    655 		n++;
    656 
    657 	if (n == 0)
    658 		return;
    659 
    660 	tbl = xmalloc(n * sizeof(*tbl));
    661 
    662 	for (ri = dti->reservelist;
    663 	     ri;
    664 	     ri = ri->next)
    665 		tbl[i++] = ri;
    666 
    667 	qsort(tbl, n, sizeof(*tbl), cmp_reserve_info);
    668 
    669 	dti->reservelist = tbl[0];
    670 	for (i = 0; i < (n-1); i++)
    671 		tbl[i]->next = tbl[i+1];
    672 	tbl[n-1]->next = NULL;
    673 
    674 	free(tbl);
    675 }
    676 
    677 static int cmp_prop(const void *ax, const void *bx)
    678 {
    679 	const struct property *a, *b;
    680 
    681 	a = *((const struct property * const *)ax);
    682 	b = *((const struct property * const *)bx);
    683 
    684 	return strcmp(a->name, b->name);
    685 }
    686 
    687 static void sort_properties(struct node *node)
    688 {
    689 	int n = 0, i = 0;
    690 	struct property *prop, **tbl;
    691 
    692 	for_each_property_withdel(node, prop)
    693 		n++;
    694 
    695 	if (n == 0)
    696 		return;
    697 
    698 	tbl = xmalloc(n * sizeof(*tbl));
    699 
    700 	for_each_property_withdel(node, prop)
    701 		tbl[i++] = prop;
    702 
    703 	qsort(tbl, n, sizeof(*tbl), cmp_prop);
    704 
    705 	node->proplist = tbl[0];
    706 	for (i = 0; i < (n-1); i++)
    707 		tbl[i]->next = tbl[i+1];
    708 	tbl[n-1]->next = NULL;
    709 
    710 	free(tbl);
    711 }
    712 
    713 static int cmp_subnode(const void *ax, const void *bx)
    714 {
    715 	const struct node *a, *b;
    716 
    717 	a = *((const struct node * const *)ax);
    718 	b = *((const struct node * const *)bx);
    719 
    720 	return strcmp(a->name, b->name);
    721 }
    722 
    723 static void sort_subnodes(struct node *node)
    724 {
    725 	int n = 0, i = 0;
    726 	struct node *subnode, **tbl;
    727 
    728 	for_each_child_withdel(node, subnode)
    729 		n++;
    730 
    731 	if (n == 0)
    732 		return;
    733 
    734 	tbl = xmalloc(n * sizeof(*tbl));
    735 
    736 	for_each_child_withdel(node, subnode)
    737 		tbl[i++] = subnode;
    738 
    739 	qsort(tbl, n, sizeof(*tbl), cmp_subnode);
    740 
    741 	node->children = tbl[0];
    742 	for (i = 0; i < (n-1); i++)
    743 		tbl[i]->next_sibling = tbl[i+1];
    744 	tbl[n-1]->next_sibling = NULL;
    745 
    746 	free(tbl);
    747 }
    748 
    749 static void sort_node(struct node *node)
    750 {
    751 	struct node *c;
    752 
    753 	sort_properties(node);
    754 	sort_subnodes(node);
    755 	for_each_child_withdel(node, c)
    756 		sort_node(c);
    757 }
    758 
    759 void sort_tree(struct dt_info *dti)
    760 {
    761 	sort_reserve_entries(dti);
    762 	sort_node(dti->dt);
    763 }
    764 
    765 /* utility helper to avoid code duplication */
    766 static struct node *build_and_name_child_node(struct node *parent, char *name)
    767 {
    768 	struct node *node;
    769 
    770 	node = build_node(NULL, NULL);
    771 	name_node(node, xstrdup(name));
    772 	add_child(parent, node);
    773 
    774 	return node;
    775 }
    776 
    777 static struct node *build_root_node(struct node *dt, char *name)
    778 {
    779 	struct node *an;
    780 
    781 	an = get_subnode(dt, name);
    782 	if (!an)
    783 		an = build_and_name_child_node(dt, name);
    784 
    785 	if (!an)
    786 		die("Could not build root node /%s\n", name);
    787 
    788 	return an;
    789 }
    790 
    791 static bool any_label_tree(struct dt_info *dti, struct node *node)
    792 {
    793 	struct node *c;
    794 
    795 	if (node->labels)
    796 		return true;
    797 
    798 	for_each_child(node, c)
    799 		if (any_label_tree(dti, c))
    800 			return true;
    801 
    802 	return false;
    803 }
    804 
    805 static void generate_label_tree_internal(struct dt_info *dti,
    806 					 struct node *an, struct node *node,
    807 					 bool allocph)
    808 {
    809 	struct node *dt = dti->dt;
    810 	struct node *c;
    811 	struct property *p;
    812 	struct label *l;
    813 
    814 	/* if there are labels */
    815 	if (node->labels) {
    816 
    817 		/* now add the label in the node */
    818 		for_each_label(node->labels, l) {
    819 
    820 			/* check whether the label already exists */
    821 			p = get_property(an, l->label);
    822 			if (p) {
    823 				fprintf(stderr, "WARNING: label %s already"
    824 					" exists in /%s", l->label,
    825 					an->name);
    826 				continue;
    827 			}
    828 
    829 			/* insert it */
    830 			p = build_property(l->label,
    831 				data_copy_mem(node->fullpath,
    832 						strlen(node->fullpath) + 1));
    833 			add_property(an, p);
    834 		}
    835 
    836 		/* force allocation of a phandle for this node */
    837 		if (allocph)
    838 			(void)get_node_phandle(dt, node);
    839 	}
    840 
    841 	for_each_child(node, c)
    842 		generate_label_tree_internal(dti, an, c, allocph);
    843 }
    844 
    845 static bool any_fixup_tree(struct dt_info *dti, struct node *node)
    846 {
    847 	struct node *c;
    848 	struct property *prop;
    849 	struct marker *m;
    850 
    851 	for_each_property(node, prop) {
    852 		m = prop->val.markers;
    853 		for_each_marker_of_type(m, REF_PHANDLE) {
    854 			if (!get_node_by_ref(dti->dt, m->ref))
    855 				return true;
    856 		}
    857 	}
    858 
    859 	for_each_child(node, c) {
    860 		if (any_fixup_tree(dti, c))
    861 			return true;
    862 	}
    863 
    864 	return false;
    865 }
    866 
    867 static void add_fixup_entry(struct dt_info *dti, struct node *fn,
    868 			    struct node *node, struct property *prop,
    869 			    struct marker *m)
    870 {
    871 	char *entry;
    872 
    873 	/* m->ref can only be a REF_PHANDLE, but check anyway */
    874 	assert(m->type == REF_PHANDLE);
    875 
    876 	/* there shouldn't be any ':' in the arguments */
    877 	if (strchr(node->fullpath, ':') || strchr(prop->name, ':'))
    878 		die("arguments should not contain ':'\n");
    879 
    880 	xasprintf(&entry, "%s:%s:%u",
    881 			node->fullpath, prop->name, m->offset);
    882 	append_to_property(fn, m->ref, entry, strlen(entry) + 1);
    883 
    884 	free(entry);
    885 }
    886 
    887 static void generate_fixups_tree_internal(struct dt_info *dti,
    888 					  struct node *fn,
    889 					  struct node *node)
    890 {
    891 	struct node *dt = dti->dt;
    892 	struct node *c;
    893 	struct property *prop;
    894 	struct marker *m;
    895 	struct node *refnode;
    896 
    897 	for_each_property(node, prop) {
    898 		m = prop->val.markers;
    899 		for_each_marker_of_type(m, REF_PHANDLE) {
    900 			refnode = get_node_by_ref(dt, m->ref);
    901 			if (!refnode)
    902 				add_fixup_entry(dti, fn, node, prop, m);
    903 		}
    904 	}
    905 
    906 	for_each_child(node, c)
    907 		generate_fixups_tree_internal(dti, fn, c);
    908 }
    909 
    910 static bool any_local_fixup_tree(struct dt_info *dti, struct node *node)
    911 {
    912 	struct node *c;
    913 	struct property *prop;
    914 	struct marker *m;
    915 
    916 	for_each_property(node, prop) {
    917 		m = prop->val.markers;
    918 		for_each_marker_of_type(m, REF_PHANDLE) {
    919 			if (get_node_by_ref(dti->dt, m->ref))
    920 				return true;
    921 		}
    922 	}
    923 
    924 	for_each_child(node, c) {
    925 		if (any_local_fixup_tree(dti, c))
    926 			return true;
    927 	}
    928 
    929 	return false;
    930 }
    931 
    932 static void add_local_fixup_entry(struct dt_info *dti,
    933 		struct node *lfn, struct node *node,
    934 		struct property *prop, struct marker *m,
    935 		struct node *refnode)
    936 {
    937 	struct node *wn, *nwn;	/* local fixup node, walk node, new */
    938 	fdt32_t value_32;
    939 	char **compp;
    940 	int i, depth;
    941 
    942 	/* walk back retreiving depth */
    943 	depth = 0;
    944 	for (wn = node; wn; wn = wn->parent)
    945 		depth++;
    946 
    947 	/* allocate name array */
    948 	compp = xmalloc(sizeof(*compp) * depth);
    949 
    950 	/* store names in the array */
    951 	for (wn = node, i = depth - 1; wn; wn = wn->parent, i--)
    952 		compp[i] = wn->name;
    953 
    954 	/* walk the path components creating nodes if they don't exist */
    955 	for (wn = lfn, i = 1; i < depth; i++, wn = nwn) {
    956 		/* if no node exists, create it */
    957 		nwn = get_subnode(wn, compp[i]);
    958 		if (!nwn)
    959 			nwn = build_and_name_child_node(wn, compp[i]);
    960 	}
    961 
    962 	free(compp);
    963 
    964 	value_32 = cpu_to_fdt32(m->offset);
    965 	append_to_property(wn, prop->name, &value_32, sizeof(value_32));
    966 }
    967 
    968 static void generate_local_fixups_tree_internal(struct dt_info *dti,
    969 						struct node *lfn,
    970 						struct node *node)
    971 {
    972 	struct node *dt = dti->dt;
    973 	struct node *c;
    974 	struct property *prop;
    975 	struct marker *m;
    976 	struct node *refnode;
    977 
    978 	for_each_property(node, prop) {
    979 		m = prop->val.markers;
    980 		for_each_marker_of_type(m, REF_PHANDLE) {
    981 			refnode = get_node_by_ref(dt, m->ref);
    982 			if (refnode)
    983 				add_local_fixup_entry(dti, lfn, node, prop, m, refnode);
    984 		}
    985 	}
    986 
    987 	for_each_child(node, c)
    988 		generate_local_fixups_tree_internal(dti, lfn, c);
    989 }
    990 
    991 void generate_label_tree(struct dt_info *dti, char *name, bool allocph)
    992 {
    993 	if (!any_label_tree(dti, dti->dt))
    994 		return;
    995 	generate_label_tree_internal(dti, build_root_node(dti->dt, name),
    996 				     dti->dt, allocph);
    997 }
    998 
    999 void generate_fixups_tree(struct dt_info *dti, char *name)
   1000 {
   1001 	if (!any_fixup_tree(dti, dti->dt))
   1002 		return;
   1003 	generate_fixups_tree_internal(dti, build_root_node(dti->dt, name),
   1004 				      dti->dt);
   1005 }
   1006 
   1007 void generate_local_fixups_tree(struct dt_info *dti, char *name)
   1008 {
   1009 	if (!any_local_fixup_tree(dti, dti->dt))
   1010 		return;
   1011 	generate_local_fixups_tree_internal(dti, build_root_node(dti->dt, name),
   1012 					    dti->dt);
   1013 }
   1014