livetree.c revision 204431
1/*
2 * (C) Copyright David Gibson <dwg@au1.ibm.com>, IBM Corporation.  2005.
3 *
4 *
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License as
7 * published by the Free Software Foundation; either version 2 of the
8 * License, or (at your option) any later version.
9 *
10 *  This program is distributed in the hope that it will be useful,
11 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13 *  General Public License for more details.
14 *
15 *  You should have received a copy of the GNU General Public License
16 *  along with this program; if not, write to the Free Software
17 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307
18 *                                                                   USA
19 */
20
21#include "dtc.h"
22
23/*
24 * Tree building functions
25 */
26
27struct property *build_property(char *name, struct data val, char *label)
28{
29	struct property *new = xmalloc(sizeof(*new));
30
31	new->name = name;
32	new->val = val;
33
34	new->next = NULL;
35
36	new->label = label;
37
38	return new;
39}
40
41struct property *chain_property(struct property *first, struct property *list)
42{
43	assert(first->next == NULL);
44
45	first->next = list;
46	return first;
47}
48
49struct property *reverse_properties(struct property *first)
50{
51	struct property *p = first;
52	struct property *head = NULL;
53	struct property *next;
54
55	while (p) {
56		next = p->next;
57		p->next = head;
58		head = p;
59		p = next;
60	}
61	return head;
62}
63
64struct node *build_node(struct property *proplist, struct node *children)
65{
66	struct node *new = xmalloc(sizeof(*new));
67	struct node *child;
68
69	memset(new, 0, sizeof(*new));
70
71	new->proplist = reverse_properties(proplist);
72	new->children = children;
73
74	for_each_child(new, child) {
75		child->parent = new;
76	}
77
78	return new;
79}
80
81struct node *name_node(struct node *node, char *name, char * label)
82{
83	assert(node->name == NULL);
84
85	node->name = name;
86
87	node->label = label;
88
89	return node;
90}
91
92struct node *chain_node(struct node *first, struct node *list)
93{
94	assert(first->next_sibling == NULL);
95
96	first->next_sibling = list;
97	return first;
98}
99
100void add_property(struct node *node, struct property *prop)
101{
102	struct property **p;
103
104	prop->next = NULL;
105
106	p = &node->proplist;
107	while (*p)
108		p = &((*p)->next);
109
110	*p = prop;
111}
112
113void add_child(struct node *parent, struct node *child)
114{
115	struct node **p;
116
117	child->next_sibling = NULL;
118	child->parent = parent;
119
120	p = &parent->children;
121	while (*p)
122		p = &((*p)->next_sibling);
123
124	*p = child;
125}
126
127struct reserve_info *build_reserve_entry(uint64_t address, uint64_t size,
128					 char *label)
129{
130	struct reserve_info *new = xmalloc(sizeof(*new));
131
132	new->re.address = address;
133	new->re.size = size;
134
135	new->next = NULL;
136
137	new->label = label;
138
139	return new;
140}
141
142struct reserve_info *chain_reserve_entry(struct reserve_info *first,
143					struct reserve_info *list)
144{
145	assert(first->next == NULL);
146
147	first->next = list;
148	return first;
149}
150
151struct reserve_info *add_reserve_entry(struct reserve_info *list,
152				      struct reserve_info *new)
153{
154	struct reserve_info *last;
155
156	new->next = NULL;
157
158	if (! list)
159		return new;
160
161	for (last = list; last->next; last = last->next)
162		;
163
164	last->next = new;
165
166	return list;
167}
168
169struct boot_info *build_boot_info(struct reserve_info *reservelist,
170				  struct node *tree, uint32_t boot_cpuid_phys)
171{
172	struct boot_info *bi;
173
174	bi = xmalloc(sizeof(*bi));
175	bi->reservelist = reservelist;
176	bi->dt = tree;
177	bi->boot_cpuid_phys = boot_cpuid_phys;
178
179	return bi;
180}
181
182/*
183 * Tree accessor functions
184 */
185
186const char *get_unitname(struct node *node)
187{
188	if (node->name[node->basenamelen] == '\0')
189		return "";
190	else
191		return node->name + node->basenamelen + 1;
192}
193
194struct property *get_property(struct node *node, const char *propname)
195{
196	struct property *prop;
197
198	for_each_property(node, prop)
199		if (streq(prop->name, propname))
200			return prop;
201
202	return NULL;
203}
204
205cell_t propval_cell(struct property *prop)
206{
207	assert(prop->val.len == sizeof(cell_t));
208	return fdt32_to_cpu(*((cell_t *)prop->val.val));
209}
210
211struct node *get_subnode(struct node *node, const char *nodename)
212{
213	struct node *child;
214
215	for_each_child(node, child)
216		if (streq(child->name, nodename))
217			return child;
218
219	return NULL;
220}
221
222struct node *get_node_by_path(struct node *tree, const char *path)
223{
224	const char *p;
225	struct node *child;
226
227	if (!path || ! (*path))
228		return tree;
229
230	while (path[0] == '/')
231		path++;
232
233	p = strchr(path, '/');
234
235	for_each_child(tree, child) {
236		if (p && strneq(path, child->name, p-path))
237			return get_node_by_path(child, p+1);
238		else if (!p && streq(path, child->name))
239			return child;
240	}
241
242	return NULL;
243}
244
245struct node *get_node_by_label(struct node *tree, const char *label)
246{
247	struct node *child, *node;
248
249	assert(label && (strlen(label) > 0));
250
251	if (tree->label && streq(tree->label, label))
252		return tree;
253
254	for_each_child(tree, child) {
255		node = get_node_by_label(child, label);
256		if (node)
257			return node;
258	}
259
260	return NULL;
261}
262
263struct node *get_node_by_phandle(struct node *tree, cell_t phandle)
264{
265	struct node *child, *node;
266
267	assert((phandle != 0) && (phandle != -1));
268
269	if (tree->phandle == phandle)
270		return tree;
271
272	for_each_child(tree, child) {
273		node = get_node_by_phandle(child, phandle);
274		if (node)
275			return node;
276	}
277
278	return NULL;
279}
280
281struct node *get_node_by_ref(struct node *tree, const char *ref)
282{
283	if (ref[0] == '/')
284		return get_node_by_path(tree, ref);
285	else
286		return get_node_by_label(tree, ref);
287}
288
289cell_t get_node_phandle(struct node *root, struct node *node)
290{
291	static cell_t phandle = 1; /* FIXME: ick, static local */
292
293	if ((node->phandle != 0) && (node->phandle != -1))
294		return node->phandle;
295
296	assert(! get_property(node, "linux,phandle"));
297
298	while (get_node_by_phandle(root, phandle))
299		phandle++;
300
301	node->phandle = phandle;
302	add_property(node,
303		     build_property("linux,phandle",
304				    data_append_cell(empty_data, phandle),
305				    NULL));
306
307	return node->phandle;
308}
309