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 void 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 }
    240 
    241 struct node *chain_node(struct node *first, struct node *list)
    242 {
    243 	assert(first->next_sibling == NULL);
    244 
    245 	first->next_sibling = list;
    246 	return first;
    247 }
    248 
    249 void add_property(struct node *node, struct property *prop)
    250 {
    251 	struct property **p;
    252 
    253 	prop->next = NULL;
    254 
    255 	p = &node->proplist;
    256 	while (*p)
    257 		p = &((*p)->next);
    258 
    259 	*p = prop;
    260 }
    261 
    262 void delete_property_by_name(struct node *node, char *name)
    263 {
    264 	struct property *prop = node->proplist;
    265 
    266 	while (prop) {
    267 		if (streq(prop->name, name)) {
    268 			delete_property(prop);
    269 			return;
    270 		}
    271 		prop = prop->next;
    272 	}
    273 }
    274 
    275 void delete_property(struct property *prop)
    276 {
    277 	prop->deleted = 1;
    278 	delete_labels(&prop->labels);
    279 }
    280 
    281 void add_child(struct node *parent, struct node *child)
    282 {
    283 	struct node **p;
    284 
    285 	child->next_sibling = NULL;
    286 	child->parent = parent;
    287 
    288 	p = &parent->children;
    289 	while (*p)
    290 		p = &((*p)->next_sibling);
    291 
    292 	*p = child;
    293 }
    294 
    295 void delete_node_by_name(struct node *parent, char *name)
    296 {
    297 	struct node *node = parent->children;
    298 
    299 	while (node) {
    300 		if (streq(node->name, name)) {
    301 			delete_node(node);
    302 			return;
    303 		}
    304 		node = node->next_sibling;
    305 	}
    306 }
    307 
    308 void delete_node(struct node *node)
    309 {
    310 	struct property *prop;
    311 	struct node *child;
    312 
    313 	node->deleted = 1;
    314 	for_each_child(node, child)
    315 		delete_node(child);
    316 	for_each_property(node, prop)
    317 		delete_property(prop);
    318 	delete_labels(&node->labels);
    319 }
    320 
    321 void append_to_property(struct node *node,
    322 				    char *name, const void *data, int len)
    323 {
    324 	struct data d;
    325 	struct property *p;
    326 
    327 	p = get_property(node, name);
    328 	if (p) {
    329 		d = data_append_data(p->val, data, len);
    330 		p->val = d;
    331 	} else {
    332 		d = data_append_data(empty_data, data, len);
    333 		p = build_property(name, d);
    334 		add_property(node, p);
    335 	}
    336 }
    337 
    338 struct reserve_info *build_reserve_entry(uint64_t address, uint64_t size)
    339 {
    340 	struct reserve_info *new = xmalloc(sizeof(*new));
    341 
    342 	memset(new, 0, sizeof(*new));
    343 
    344 	new->re.address = address;
    345 	new->re.size = size;
    346 
    347 	return new;
    348 }
    349 
    350 struct reserve_info *chain_reserve_entry(struct reserve_info *first,
    351 					struct reserve_info *list)
    352 {
    353 	assert(first->next == NULL);
    354 
    355 	first->next = list;
    356 	return first;
    357 }
    358 
    359 struct reserve_info *add_reserve_entry(struct reserve_info *list,
    360 				      struct reserve_info *new)
    361 {
    362 	struct reserve_info *last;
    363 
    364 	new->next = NULL;
    365 
    366 	if (! list)
    367 		return new;
    368 
    369 	for (last = list; last->next; last = last->next)
    370 		;
    371 
    372 	last->next = new;
    373 
    374 	return list;
    375 }
    376 
    377 struct dt_info *build_dt_info(unsigned int dtsflags,
    378 			      struct reserve_info *reservelist,
    379 			      struct node *tree, uint32_t boot_cpuid_phys)
    380 {
    381 	struct dt_info *dti;
    382 
    383 	dti = xmalloc(sizeof(*dti));
    384 	dti->dtsflags = dtsflags;
    385 	dti->reservelist = reservelist;
    386 	dti->dt = tree;
    387 	dti->boot_cpuid_phys = boot_cpuid_phys;
    388 
    389 	return dti;
    390 }
    391 
    392 /*
    393  * Tree accessor functions
    394  */
    395 
    396 const char *get_unitname(struct node *node)
    397 {
    398 	if (node->name[node->basenamelen] == '\0')
    399 		return "";
    400 	else
    401 		return node->name + node->basenamelen + 1;
    402 }
    403 
    404 struct property *get_property(struct node *node, const char *propname)
    405 {
    406 	struct property *prop;
    407 
    408 	for_each_property(node, prop)
    409 		if (streq(prop->name, propname))
    410 			return prop;
    411 
    412 	return NULL;
    413 }
    414 
    415 cell_t propval_cell(struct property *prop)
    416 {
    417 	assert(prop->val.len == sizeof(cell_t));
    418 	return fdt32_to_cpu(*((cell_t *)prop->val.val));
    419 }
    420 
    421 struct property *get_property_by_label(struct node *tree, const char *label,
    422 				       struct node **node)
    423 {
    424 	struct property *prop;
    425 	struct node *c;
    426 
    427 	*node = tree;
    428 
    429 	for_each_property(tree, prop) {
    430 		struct label *l;
    431 
    432 		for_each_label(prop->labels, l)
    433 			if (streq(l->label, label))
    434 				return prop;
    435 	}
    436 
    437 	for_each_child(tree, c) {
    438 		prop = get_property_by_label(c, label, node);
    439 		if (prop)
    440 			return prop;
    441 	}
    442 
    443 	*node = NULL;
    444 	return NULL;
    445 }
    446 
    447 struct marker *get_marker_label(struct node *tree, const char *label,
    448 				struct node **node, struct property **prop)
    449 {
    450 	struct marker *m;
    451 	struct property *p;
    452 	struct node *c;
    453 
    454 	*node = tree;
    455 
    456 	for_each_property(tree, p) {
    457 		*prop = p;
    458 		m = p->val.markers;
    459 		for_each_marker_of_type(m, LABEL)
    460 			if (streq(m->ref, label))
    461 				return m;
    462 	}
    463 
    464 	for_each_child(tree, c) {
    465 		m = get_marker_label(c, label, node, prop);
    466 		if (m)
    467 			return m;
    468 	}
    469 
    470 	*prop = NULL;
    471 	*node = NULL;
    472 	return NULL;
    473 }
    474 
    475 struct node *get_subnode(struct node *node, const char *nodename)
    476 {
    477 	struct node *child;
    478 
    479 	for_each_child(node, child)
    480 		if (streq(child->name, nodename))
    481 			return child;
    482 
    483 	return NULL;
    484 }
    485 
    486 struct node *get_node_by_path(struct node *tree, const char *path)
    487 {
    488 	const char *p;
    489 	struct node *child;
    490 
    491 	if (!path || ! (*path)) {
    492 		if (tree->deleted)
    493 			return NULL;
    494 		return tree;
    495 	}
    496 
    497 	while (path[0] == '/')
    498 		path++;
    499 
    500 	p = strchr(path, '/');
    501 
    502 	for_each_child(tree, child) {
    503 		if (p && strneq(path, child->name, p-path))
    504 			return get_node_by_path(child, p+1);
    505 		else if (!p && streq(path, child->name))
    506 			return child;
    507 	}
    508 
    509 	return NULL;
    510 }
    511 
    512 struct node *get_node_by_label(struct node *tree, const char *label)
    513 {
    514 	struct node *child, *node;
    515 	struct label *l;
    516 
    517 	assert(label && (strlen(label) > 0));
    518 
    519 	for_each_label(tree->labels, l)
    520 		if (streq(l->label, label))
    521 			return tree;
    522 
    523 	for_each_child(tree, child) {
    524 		node = get_node_by_label(child, label);
    525 		if (node)
    526 			return node;
    527 	}
    528 
    529 	return NULL;
    530 }
    531 
    532 struct node *get_node_by_phandle(struct node *tree, cell_t phandle)
    533 {
    534 	struct node *child, *node;
    535 
    536 	assert((phandle != 0) && (phandle != -1));
    537 
    538 	if (tree->phandle == phandle) {
    539 		if (tree->deleted)
    540 			return NULL;
    541 		return tree;
    542 	}
    543 
    544 	for_each_child(tree, child) {
    545 		node = get_node_by_phandle(child, phandle);
    546 		if (node)
    547 			return node;
    548 	}
    549 
    550 	return NULL;
    551 }
    552 
    553 struct node *get_node_by_ref(struct node *tree, const char *ref)
    554 {
    555 	if (streq(ref, "/"))
    556 		return tree;
    557 	else if (ref[0] == '/')
    558 		return get_node_by_path(tree, ref);
    559 	else
    560 		return get_node_by_label(tree, ref);
    561 }
    562 
    563 cell_t get_node_phandle(struct node *root, struct node *node)
    564 {
    565 	static cell_t phandle = 1; /* FIXME: ick, static local */
    566 
    567 	if ((node->phandle != 0) && (node->phandle != -1))
    568 		return node->phandle;
    569 
    570 	while (get_node_by_phandle(root, phandle))
    571 		phandle++;
    572 
    573 	node->phandle = phandle;
    574 
    575 	if (!get_property(node, "linux,phandle")
    576 	    && (phandle_format & PHANDLE_LEGACY))
    577 		add_property(node,
    578 			     build_property("linux,phandle",
    579 					    data_append_cell(empty_data, phandle)));
    580 
    581 	if (!get_property(node, "phandle")
    582 	    && (phandle_format & PHANDLE_EPAPR))
    583 		add_property(node,
    584 			     build_property("phandle",
    585 					    data_append_cell(empty_data, phandle)));
    586 
    587 	/* If the node *does* have a phandle property, we must
    588 	 * be dealing with a self-referencing phandle, which will be
    589 	 * fixed up momentarily in the caller */
    590 
    591 	return node->phandle;
    592 }
    593 
    594 uint32_t guess_boot_cpuid(struct node *tree)
    595 {
    596 	struct node *cpus, *bootcpu;
    597 	struct property *reg;
    598 
    599 	cpus = get_node_by_path(tree, "/cpus");
    600 	if (!cpus)
    601 		return 0;
    602 
    603 
    604 	bootcpu = cpus->children;
    605 	if (!bootcpu)
    606 		return 0;
    607 
    608 	reg = get_property(bootcpu, "reg");
    609 	if (!reg || (reg->val.len != sizeof(uint32_t)))
    610 		return 0;
    611 
    612 	/* FIXME: Sanity check node? */
    613 
    614 	return propval_cell(reg);
    615 }
    616 
    617 static int cmp_reserve_info(const void *ax, const void *bx)
    618 {
    619 	const struct reserve_info *a, *b;
    620 
    621 	a = *((const struct reserve_info * const *)ax);
    622 	b = *((const struct reserve_info * const *)bx);
    623 
    624 	if (a->re.address < b->re.address)
    625 		return -1;
    626 	else if (a->re.address > b->re.address)
    627 		return 1;
    628 	else if (a->re.size < b->re.size)
    629 		return -1;
    630 	else if (a->re.size > b->re.size)
    631 		return 1;
    632 	else
    633 		return 0;
    634 }
    635 
    636 static void sort_reserve_entries(struct dt_info *dti)
    637 {
    638 	struct reserve_info *ri, **tbl;
    639 	int n = 0, i = 0;
    640 
    641 	for (ri = dti->reservelist;
    642 	     ri;
    643 	     ri = ri->next)
    644 		n++;
    645 
    646 	if (n == 0)
    647 		return;
    648 
    649 	tbl = xmalloc(n * sizeof(*tbl));
    650 
    651 	for (ri = dti->reservelist;
    652 	     ri;
    653 	     ri = ri->next)
    654 		tbl[i++] = ri;
    655 
    656 	qsort(tbl, n, sizeof(*tbl), cmp_reserve_info);
    657 
    658 	dti->reservelist = tbl[0];
    659 	for (i = 0; i < (n-1); i++)
    660 		tbl[i]->next = tbl[i+1];
    661 	tbl[n-1]->next = NULL;
    662 
    663 	free(tbl);
    664 }
    665 
    666 static int cmp_prop(const void *ax, const void *bx)
    667 {
    668 	const struct property *a, *b;
    669 
    670 	a = *((const struct property * const *)ax);
    671 	b = *((const struct property * const *)bx);
    672 
    673 	return strcmp(a->name, b->name);
    674 }
    675 
    676 static void sort_properties(struct node *node)
    677 {
    678 	int n = 0, i = 0;
    679 	struct property *prop, **tbl;
    680 
    681 	for_each_property_withdel(node, prop)
    682 		n++;
    683 
    684 	if (n == 0)
    685 		return;
    686 
    687 	tbl = xmalloc(n * sizeof(*tbl));
    688 
    689 	for_each_property_withdel(node, prop)
    690 		tbl[i++] = prop;
    691 
    692 	qsort(tbl, n, sizeof(*tbl), cmp_prop);
    693 
    694 	node->proplist = tbl[0];
    695 	for (i = 0; i < (n-1); i++)
    696 		tbl[i]->next = tbl[i+1];
    697 	tbl[n-1]->next = NULL;
    698 
    699 	free(tbl);
    700 }
    701 
    702 static int cmp_subnode(const void *ax, const void *bx)
    703 {
    704 	const struct node *a, *b;
    705 
    706 	a = *((const struct node * const *)ax);
    707 	b = *((const struct node * const *)bx);
    708 
    709 	return strcmp(a->name, b->name);
    710 }
    711 
    712 static void sort_subnodes(struct node *node)
    713 {
    714 	int n = 0, i = 0;
    715 	struct node *subnode, **tbl;
    716 
    717 	for_each_child_withdel(node, subnode)
    718 		n++;
    719 
    720 	if (n == 0)
    721 		return;
    722 
    723 	tbl = xmalloc(n * sizeof(*tbl));
    724 
    725 	for_each_child_withdel(node, subnode)
    726 		tbl[i++] = subnode;
    727 
    728 	qsort(tbl, n, sizeof(*tbl), cmp_subnode);
    729 
    730 	node->children = tbl[0];
    731 	for (i = 0; i < (n-1); i++)
    732 		tbl[i]->next_sibling = tbl[i+1];
    733 	tbl[n-1]->next_sibling = NULL;
    734 
    735 	free(tbl);
    736 }
    737 
    738 static void sort_node(struct node *node)
    739 {
    740 	struct node *c;
    741 
    742 	sort_properties(node);
    743 	sort_subnodes(node);
    744 	for_each_child_withdel(node, c)
    745 		sort_node(c);
    746 }
    747 
    748 void sort_tree(struct dt_info *dti)
    749 {
    750 	sort_reserve_entries(dti);
    751 	sort_node(dti->dt);
    752 }
    753 
    754 /* utility helper to avoid code duplication */
    755 static struct node *build_and_name_child_node(struct node *parent, char *name)
    756 {
    757 	struct node *node;
    758 
    759 	node = build_node(NULL, NULL);
    760 	name_node(node, xstrdup(name));
    761 	add_child(parent, node);
    762 
    763 	return node;
    764 }
    765 
    766 static struct node *build_root_node(struct node *dt, char *name)
    767 {
    768 	struct node *an;
    769 
    770 	an = get_subnode(dt, name);
    771 	if (!an)
    772 		an = build_and_name_child_node(dt, name);
    773 
    774 	if (!an)
    775 		die("Could not build root node /%s\n", name);
    776 
    777 	return an;
    778 }
    779 
    780 static bool any_label_tree(struct dt_info *dti, struct node *node)
    781 {
    782 	struct node *c;
    783 
    784 	if (node->labels)
    785 		return true;
    786 
    787 	for_each_child(node, c)
    788 		if (any_label_tree(dti, c))
    789 			return true;
    790 
    791 	return false;
    792 }
    793 
    794 static void generate_label_tree_internal(struct dt_info *dti,
    795 					 struct node *an, struct node *node,
    796 					 bool allocph)
    797 {
    798 	struct node *dt = dti->dt;
    799 	struct node *c;
    800 	struct property *p;
    801 	struct label *l;
    802 
    803 	/* if there are labels */
    804 	if (node->labels) {
    805 
    806 		/* now add the label in the node */
    807 		for_each_label(node->labels, l) {
    808 
    809 			/* check whether the label already exists */
    810 			p = get_property(an, l->label);
    811 			if (p) {
    812 				fprintf(stderr, "WARNING: label %s already"
    813 					" exists in /%s", l->label,
    814 					an->name);
    815 				continue;
    816 			}
    817 
    818 			/* insert it */
    819 			p = build_property(l->label,
    820 				data_copy_mem(node->fullpath,
    821 						strlen(node->fullpath) + 1));
    822 			add_property(an, p);
    823 		}
    824 
    825 		/* force allocation of a phandle for this node */
    826 		if (allocph)
    827 			(void)get_node_phandle(dt, node);
    828 	}
    829 
    830 	for_each_child(node, c)
    831 		generate_label_tree_internal(dti, an, c, allocph);
    832 }
    833 
    834 static bool any_fixup_tree(struct dt_info *dti, struct node *node)
    835 {
    836 	struct node *c;
    837 	struct property *prop;
    838 	struct marker *m;
    839 
    840 	for_each_property(node, prop) {
    841 		m = prop->val.markers;
    842 		for_each_marker_of_type(m, REF_PHANDLE) {
    843 			if (!get_node_by_ref(dti->dt, m->ref))
    844 				return true;
    845 		}
    846 	}
    847 
    848 	for_each_child(node, c) {
    849 		if (any_fixup_tree(dti, c))
    850 			return true;
    851 	}
    852 
    853 	return false;
    854 }
    855 
    856 static void add_fixup_entry(struct dt_info *dti, struct node *fn,
    857 			    struct node *node, struct property *prop,
    858 			    struct marker *m)
    859 {
    860 	char *entry;
    861 
    862 	/* m->ref can only be a REF_PHANDLE, but check anyway */
    863 	assert(m->type == REF_PHANDLE);
    864 
    865 	/* there shouldn't be any ':' in the arguments */
    866 	if (strchr(node->fullpath, ':') || strchr(prop->name, ':'))
    867 		die("arguments should not contain ':'\n");
    868 
    869 	xasprintf(&entry, "%s:%s:%u",
    870 			node->fullpath, prop->name, m->offset);
    871 	append_to_property(fn, m->ref, entry, strlen(entry) + 1);
    872 
    873 	free(entry);
    874 }
    875 
    876 static void generate_fixups_tree_internal(struct dt_info *dti,
    877 					  struct node *fn,
    878 					  struct node *node)
    879 {
    880 	struct node *dt = dti->dt;
    881 	struct node *c;
    882 	struct property *prop;
    883 	struct marker *m;
    884 	struct node *refnode;
    885 
    886 	for_each_property(node, prop) {
    887 		m = prop->val.markers;
    888 		for_each_marker_of_type(m, REF_PHANDLE) {
    889 			refnode = get_node_by_ref(dt, m->ref);
    890 			if (!refnode)
    891 				add_fixup_entry(dti, fn, node, prop, m);
    892 		}
    893 	}
    894 
    895 	for_each_child(node, c)
    896 		generate_fixups_tree_internal(dti, fn, c);
    897 }
    898 
    899 static bool any_local_fixup_tree(struct dt_info *dti, struct node *node)
    900 {
    901 	struct node *c;
    902 	struct property *prop;
    903 	struct marker *m;
    904 
    905 	for_each_property(node, prop) {
    906 		m = prop->val.markers;
    907 		for_each_marker_of_type(m, REF_PHANDLE) {
    908 			if (get_node_by_ref(dti->dt, m->ref))
    909 				return true;
    910 		}
    911 	}
    912 
    913 	for_each_child(node, c) {
    914 		if (any_local_fixup_tree(dti, c))
    915 			return true;
    916 	}
    917 
    918 	return false;
    919 }
    920 
    921 static void add_local_fixup_entry(struct dt_info *dti,
    922 		struct node *lfn, struct node *node,
    923 		struct property *prop, struct marker *m,
    924 		struct node *refnode)
    925 {
    926 	struct node *wn, *nwn;	/* local fixup node, walk node, new */
    927 	uint32_t value_32;
    928 	char **compp;
    929 	int i, depth;
    930 
    931 	/* walk back retreiving depth */
    932 	depth = 0;
    933 	for (wn = node; wn; wn = wn->parent)
    934 		depth++;
    935 
    936 	/* allocate name array */
    937 	compp = xmalloc(sizeof(*compp) * depth);
    938 
    939 	/* store names in the array */
    940 	for (wn = node, i = depth - 1; wn; wn = wn->parent, i--)
    941 		compp[i] = wn->name;
    942 
    943 	/* walk the path components creating nodes if they don't exist */
    944 	for (wn = lfn, i = 1; i < depth; i++, wn = nwn) {
    945 		/* if no node exists, create it */
    946 		nwn = get_subnode(wn, compp[i]);
    947 		if (!nwn)
    948 			nwn = build_and_name_child_node(wn, compp[i]);
    949 	}
    950 
    951 	free(compp);
    952 
    953 	value_32 = cpu_to_fdt32(m->offset);
    954 	append_to_property(wn, prop->name, &value_32, sizeof(value_32));
    955 }
    956 
    957 static void generate_local_fixups_tree_internal(struct dt_info *dti,
    958 						struct node *lfn,
    959 						struct node *node)
    960 {
    961 	struct node *dt = dti->dt;
    962 	struct node *c;
    963 	struct property *prop;
    964 	struct marker *m;
    965 	struct node *refnode;
    966 
    967 	for_each_property(node, prop) {
    968 		m = prop->val.markers;
    969 		for_each_marker_of_type(m, REF_PHANDLE) {
    970 			refnode = get_node_by_ref(dt, m->ref);
    971 			if (refnode)
    972 				add_local_fixup_entry(dti, lfn, node, prop, m, refnode);
    973 		}
    974 	}
    975 
    976 	for_each_child(node, c)
    977 		generate_local_fixups_tree_internal(dti, lfn, c);
    978 }
    979 
    980 void generate_label_tree(struct dt_info *dti, char *name, bool allocph)
    981 {
    982 	if (!any_label_tree(dti, dti->dt))
    983 		return;
    984 	generate_label_tree_internal(dti, build_root_node(dti->dt, name),
    985 				     dti->dt, allocph);
    986 }
    987 
    988 void generate_fixups_tree(struct dt_info *dti, char *name)
    989 {
    990 	if (!any_fixup_tree(dti, dti->dt))
    991 		return;
    992 	generate_fixups_tree_internal(dti, build_root_node(dti->dt, name),
    993 				      dti->dt);
    994 }
    995 
    996 void generate_local_fixups_tree(struct dt_info *dti, char *name)
    997 {
    998 	if (!any_local_fixup_tree(dti, dti->dt))
    999 		return;
   1000 	generate_local_fixups_tree_internal(dti, build_root_node(dti->dt, name),
   1001 					    dti->dt);
   1002 }
   1003