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