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->address = address;
    345 	new->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(*((fdt32_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 && (strlen(child->name) == p-path) &&
    504 				strneq(path, child->name, p-path))
    505 			return get_node_by_path(child, p+1);
    506 		else if (!p && streq(path, child->name))
    507 			return child;
    508 	}
    509 
    510 	return NULL;
    511 }
    512 
    513 struct node *get_node_by_label(struct node *tree, const char *label)
    514 {
    515 	struct node *child, *node;
    516 	struct label *l;
    517 
    518 	assert(label && (strlen(label) > 0));
    519 
    520 	for_each_label(tree->labels, l)
    521 		if (streq(l->label, label))
    522 			return tree;
    523 
    524 	for_each_child(tree, child) {
    525 		node = get_node_by_label(child, label);
    526 		if (node)
    527 			return node;
    528 	}
    529 
    530 	return NULL;
    531 }
    532 
    533 struct node *get_node_by_phandle(struct node *tree, cell_t phandle)
    534 {
    535 	struct node *child, *node;
    536 
    537 	assert((phandle != 0) && (phandle != -1));
    538 
    539 	if (tree->phandle == phandle) {
    540 		if (tree->deleted)
    541 			return NULL;
    542 		return tree;
    543 	}
    544 
    545 	for_each_child(tree, child) {
    546 		node = get_node_by_phandle(child, phandle);
    547 		if (node)
    548 			return node;
    549 	}
    550 
    551 	return NULL;
    552 }
    553 
    554 struct node *get_node_by_ref(struct node *tree, const char *ref)
    555 {
    556 	if (streq(ref, "/"))
    557 		return tree;
    558 	else if (ref[0] == '/')
    559 		return get_node_by_path(tree, ref);
    560 	else
    561 		return get_node_by_label(tree, ref);
    562 }
    563 
    564 cell_t get_node_phandle(struct node *root, struct node *node)
    565 {
    566 	static cell_t phandle = 1; /* FIXME: ick, static local */
    567 
    568 	if ((node->phandle != 0) && (node->phandle != -1))
    569 		return node->phandle;
    570 
    571 	while (get_node_by_phandle(root, phandle))
    572 		phandle++;
    573 
    574 	node->phandle = phandle;
    575 
    576 	if (!get_property(node, "linux,phandle")
    577 	    && (phandle_format & PHANDLE_LEGACY))
    578 		add_property(node,
    579 			     build_property("linux,phandle",
    580 					    data_append_cell(empty_data, phandle)));
    581 
    582 	if (!get_property(node, "phandle")
    583 	    && (phandle_format & PHANDLE_EPAPR))
    584 		add_property(node,
    585 			     build_property("phandle",
    586 					    data_append_cell(empty_data, phandle)));
    587 
    588 	/* If the node *does* have a phandle property, we must
    589 	 * be dealing with a self-referencing phandle, which will be
    590 	 * fixed up momentarily in the caller */
    591 
    592 	return node->phandle;
    593 }
    594 
    595 uint32_t guess_boot_cpuid(struct node *tree)
    596 {
    597 	struct node *cpus, *bootcpu;
    598 	struct property *reg;
    599 
    600 	cpus = get_node_by_path(tree, "/cpus");
    601 	if (!cpus)
    602 		return 0;
    603 
    604 
    605 	bootcpu = cpus->children;
    606 	if (!bootcpu)
    607 		return 0;
    608 
    609 	reg = get_property(bootcpu, "reg");
    610 	if (!reg || (reg->val.len != sizeof(uint32_t)))
    611 		return 0;
    612 
    613 	/* FIXME: Sanity check node? */
    614 
    615 	return propval_cell(reg);
    616 }
    617 
    618 static int cmp_reserve_info(const void *ax, const void *bx)
    619 {
    620 	const struct reserve_info *a, *b;
    621 
    622 	a = *((const struct reserve_info * const *)ax);
    623 	b = *((const struct reserve_info * const *)bx);
    624 
    625 	if (a->address < b->address)
    626 		return -1;
    627 	else if (a->address > b->address)
    628 		return 1;
    629 	else if (a->size < b->size)
    630 		return -1;
    631 	else if (a->size > b->size)
    632 		return 1;
    633 	else
    634 		return 0;
    635 }
    636 
    637 static void sort_reserve_entries(struct dt_info *dti)
    638 {
    639 	struct reserve_info *ri, **tbl;
    640 	int n = 0, i = 0;
    641 
    642 	for (ri = dti->reservelist;
    643 	     ri;
    644 	     ri = ri->next)
    645 		n++;
    646 
    647 	if (n == 0)
    648 		return;
    649 
    650 	tbl = xmalloc(n * sizeof(*tbl));
    651 
    652 	for (ri = dti->reservelist;
    653 	     ri;
    654 	     ri = ri->next)
    655 		tbl[i++] = ri;
    656 
    657 	qsort(tbl, n, sizeof(*tbl), cmp_reserve_info);
    658 
    659 	dti->reservelist = tbl[0];
    660 	for (i = 0; i < (n-1); i++)
    661 		tbl[i]->next = tbl[i+1];
    662 	tbl[n-1]->next = NULL;
    663 
    664 	free(tbl);
    665 }
    666 
    667 static int cmp_prop(const void *ax, const void *bx)
    668 {
    669 	const struct property *a, *b;
    670 
    671 	a = *((const struct property * const *)ax);
    672 	b = *((const struct property * const *)bx);
    673 
    674 	return strcmp(a->name, b->name);
    675 }
    676 
    677 static void sort_properties(struct node *node)
    678 {
    679 	int n = 0, i = 0;
    680 	struct property *prop, **tbl;
    681 
    682 	for_each_property_withdel(node, prop)
    683 		n++;
    684 
    685 	if (n == 0)
    686 		return;
    687 
    688 	tbl = xmalloc(n * sizeof(*tbl));
    689 
    690 	for_each_property_withdel(node, prop)
    691 		tbl[i++] = prop;
    692 
    693 	qsort(tbl, n, sizeof(*tbl), cmp_prop);
    694 
    695 	node->proplist = tbl[0];
    696 	for (i = 0; i < (n-1); i++)
    697 		tbl[i]->next = tbl[i+1];
    698 	tbl[n-1]->next = NULL;
    699 
    700 	free(tbl);
    701 }
    702 
    703 static int cmp_subnode(const void *ax, const void *bx)
    704 {
    705 	const struct node *a, *b;
    706 
    707 	a = *((const struct node * const *)ax);
    708 	b = *((const struct node * const *)bx);
    709 
    710 	return strcmp(a->name, b->name);
    711 }
    712 
    713 static void sort_subnodes(struct node *node)
    714 {
    715 	int n = 0, i = 0;
    716 	struct node *subnode, **tbl;
    717 
    718 	for_each_child_withdel(node, subnode)
    719 		n++;
    720 
    721 	if (n == 0)
    722 		return;
    723 
    724 	tbl = xmalloc(n * sizeof(*tbl));
    725 
    726 	for_each_child_withdel(node, subnode)
    727 		tbl[i++] = subnode;
    728 
    729 	qsort(tbl, n, sizeof(*tbl), cmp_subnode);
    730 
    731 	node->children = tbl[0];
    732 	for (i = 0; i < (n-1); i++)
    733 		tbl[i]->next_sibling = tbl[i+1];
    734 	tbl[n-1]->next_sibling = NULL;
    735 
    736 	free(tbl);
    737 }
    738 
    739 static void sort_node(struct node *node)
    740 {
    741 	struct node *c;
    742 
    743 	sort_properties(node);
    744 	sort_subnodes(node);
    745 	for_each_child_withdel(node, c)
    746 		sort_node(c);
    747 }
    748 
    749 void sort_tree(struct dt_info *dti)
    750 {
    751 	sort_reserve_entries(dti);
    752 	sort_node(dti->dt);
    753 }
    754 
    755 /* utility helper to avoid code duplication */
    756 static struct node *build_and_name_child_node(struct node *parent, char *name)
    757 {
    758 	struct node *node;
    759 
    760 	node = build_node(NULL, NULL);
    761 	name_node(node, xstrdup(name));
    762 	add_child(parent, node);
    763 
    764 	return node;
    765 }
    766 
    767 static struct node *build_root_node(struct node *dt, char *name)
    768 {
    769 	struct node *an;
    770 
    771 	an = get_subnode(dt, name);
    772 	if (!an)
    773 		an = build_and_name_child_node(dt, name);
    774 
    775 	if (!an)
    776 		die("Could not build root node /%s\n", name);
    777 
    778 	return an;
    779 }
    780 
    781 static bool any_label_tree(struct dt_info *dti, struct node *node)
    782 {
    783 	struct node *c;
    784 
    785 	if (node->labels)
    786 		return true;
    787 
    788 	for_each_child(node, c)
    789 		if (any_label_tree(dti, c))
    790 			return true;
    791 
    792 	return false;
    793 }
    794 
    795 static void generate_label_tree_internal(struct dt_info *dti,
    796 					 struct node *an, struct node *node,
    797 					 bool allocph)
    798 {
    799 	struct node *dt = dti->dt;
    800 	struct node *c;
    801 	struct property *p;
    802 	struct label *l;
    803 
    804 	/* if there are labels */
    805 	if (node->labels) {
    806 
    807 		/* now add the label in the node */
    808 		for_each_label(node->labels, l) {
    809 
    810 			/* check whether the label already exists */
    811 			p = get_property(an, l->label);
    812 			if (p) {
    813 				fprintf(stderr, "WARNING: label %s already"
    814 					" exists in /%s", l->label,
    815 					an->name);
    816 				continue;
    817 			}
    818 
    819 			/* insert it */
    820 			p = build_property(l->label,
    821 				data_copy_mem(node->fullpath,
    822 						strlen(node->fullpath) + 1));
    823 			add_property(an, p);
    824 		}
    825 
    826 		/* force allocation of a phandle for this node */
    827 		if (allocph)
    828 			(void)get_node_phandle(dt, node);
    829 	}
    830 
    831 	for_each_child(node, c)
    832 		generate_label_tree_internal(dti, an, c, allocph);
    833 }
    834 
    835 static bool any_fixup_tree(struct dt_info *dti, struct node *node)
    836 {
    837 	struct node *c;
    838 	struct property *prop;
    839 	struct marker *m;
    840 
    841 	for_each_property(node, prop) {
    842 		m = prop->val.markers;
    843 		for_each_marker_of_type(m, REF_PHANDLE) {
    844 			if (!get_node_by_ref(dti->dt, m->ref))
    845 				return true;
    846 		}
    847 	}
    848 
    849 	for_each_child(node, c) {
    850 		if (any_fixup_tree(dti, c))
    851 			return true;
    852 	}
    853 
    854 	return false;
    855 }
    856 
    857 static void add_fixup_entry(struct dt_info *dti, struct node *fn,
    858 			    struct node *node, struct property *prop,
    859 			    struct marker *m)
    860 {
    861 	char *entry;
    862 
    863 	/* m->ref can only be a REF_PHANDLE, but check anyway */
    864 	assert(m->type == REF_PHANDLE);
    865 
    866 	/* there shouldn't be any ':' in the arguments */
    867 	if (strchr(node->fullpath, ':') || strchr(prop->name, ':'))
    868 		die("arguments should not contain ':'\n");
    869 
    870 	xasprintf(&entry, "%s:%s:%u",
    871 			node->fullpath, prop->name, m->offset);
    872 	append_to_property(fn, m->ref, entry, strlen(entry) + 1);
    873 
    874 	free(entry);
    875 }
    876 
    877 static void generate_fixups_tree_internal(struct dt_info *dti,
    878 					  struct node *fn,
    879 					  struct node *node)
    880 {
    881 	struct node *dt = dti->dt;
    882 	struct node *c;
    883 	struct property *prop;
    884 	struct marker *m;
    885 	struct node *refnode;
    886 
    887 	for_each_property(node, prop) {
    888 		m = prop->val.markers;
    889 		for_each_marker_of_type(m, REF_PHANDLE) {
    890 			refnode = get_node_by_ref(dt, m->ref);
    891 			if (!refnode)
    892 				add_fixup_entry(dti, fn, node, prop, m);
    893 		}
    894 	}
    895 
    896 	for_each_child(node, c)
    897 		generate_fixups_tree_internal(dti, fn, c);
    898 }
    899 
    900 static bool any_local_fixup_tree(struct dt_info *dti, struct node *node)
    901 {
    902 	struct node *c;
    903 	struct property *prop;
    904 	struct marker *m;
    905 
    906 	for_each_property(node, prop) {
    907 		m = prop->val.markers;
    908 		for_each_marker_of_type(m, REF_PHANDLE) {
    909 			if (get_node_by_ref(dti->dt, m->ref))
    910 				return true;
    911 		}
    912 	}
    913 
    914 	for_each_child(node, c) {
    915 		if (any_local_fixup_tree(dti, c))
    916 			return true;
    917 	}
    918 
    919 	return false;
    920 }
    921 
    922 static void add_local_fixup_entry(struct dt_info *dti,
    923 		struct node *lfn, struct node *node,
    924 		struct property *prop, struct marker *m,
    925 		struct node *refnode)
    926 {
    927 	struct node *wn, *nwn;	/* local fixup node, walk node, new */
    928 	fdt32_t value_32;
    929 	char **compp;
    930 	int i, depth;
    931 
    932 	/* walk back retreiving depth */
    933 	depth = 0;
    934 	for (wn = node; wn; wn = wn->parent)
    935 		depth++;
    936 
    937 	/* allocate name array */
    938 	compp = xmalloc(sizeof(*compp) * depth);
    939 
    940 	/* store names in the array */
    941 	for (wn = node, i = depth - 1; wn; wn = wn->parent, i--)
    942 		compp[i] = wn->name;
    943 
    944 	/* walk the path components creating nodes if they don't exist */
    945 	for (wn = lfn, i = 1; i < depth; i++, wn = nwn) {
    946 		/* if no node exists, create it */
    947 		nwn = get_subnode(wn, compp[i]);
    948 		if (!nwn)
    949 			nwn = build_and_name_child_node(wn, compp[i]);
    950 	}
    951 
    952 	free(compp);
    953 
    954 	value_32 = cpu_to_fdt32(m->offset);
    955 	append_to_property(wn, prop->name, &value_32, sizeof(value_32));
    956 }
    957 
    958 static void generate_local_fixups_tree_internal(struct dt_info *dti,
    959 						struct node *lfn,
    960 						struct node *node)
    961 {
    962 	struct node *dt = dti->dt;
    963 	struct node *c;
    964 	struct property *prop;
    965 	struct marker *m;
    966 	struct node *refnode;
    967 
    968 	for_each_property(node, prop) {
    969 		m = prop->val.markers;
    970 		for_each_marker_of_type(m, REF_PHANDLE) {
    971 			refnode = get_node_by_ref(dt, m->ref);
    972 			if (refnode)
    973 				add_local_fixup_entry(dti, lfn, node, prop, m, refnode);
    974 		}
    975 	}
    976 
    977 	for_each_child(node, c)
    978 		generate_local_fixups_tree_internal(dti, lfn, c);
    979 }
    980 
    981 void generate_label_tree(struct dt_info *dti, char *name, bool allocph)
    982 {
    983 	if (!any_label_tree(dti, dti->dt))
    984 		return;
    985 	generate_label_tree_internal(dti, build_root_node(dti->dt, name),
    986 				     dti->dt, allocph);
    987 }
    988 
    989 void generate_fixups_tree(struct dt_info *dti, char *name)
    990 {
    991 	if (!any_fixup_tree(dti, dti->dt))
    992 		return;
    993 	generate_fixups_tree_internal(dti, build_root_node(dti->dt, name),
    994 				      dti->dt);
    995 }
    996 
    997 void generate_local_fixups_tree(struct dt_info *dti, char *name)
    998 {
    999 	if (!any_local_fixup_tree(dti, dti->dt))
   1000 		return;
   1001 	generate_local_fixups_tree_internal(dti, build_root_node(dti->dt, name),
   1002 					    dti->dt);
   1003 }
   1004