diff options
author | David Gibson <david@gibson.dropbear.id.au> | 2007-12-17 23:06:42 -0500 |
---|---|---|
committer | Paul Mackerras <paulus@samba.org> | 2007-12-20 00:17:52 -0500 |
commit | a4da2e3ec84cda635ac441efbe781a38d2ee41ee (patch) | |
tree | 47fa696faaf092920ee0c0226ddc7557fa743d4d /arch/powerpc/boot/dtc-src/livetree.c | |
parent | 70e47528aa0eb5ef63fef6ee0d30065d9e09f3e5 (diff) |
[POWERPC] Merge dtc upstream source
This incorporates a copy of dtc into the kernel source, in
arch/powerpc/boot/dtc-src. This commit only imports the upstream
sources verbatim, a later commit will actually link it into the kernel
Makefiles and use the embedded code during the kernel build.
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
Signed-off-by: Paul Mackerras <paulus@samba.org>
Diffstat (limited to 'arch/powerpc/boot/dtc-src/livetree.c')
-rw-r--r-- | arch/powerpc/boot/dtc-src/livetree.c | 305 |
1 files changed, 305 insertions, 0 deletions
diff --git a/arch/powerpc/boot/dtc-src/livetree.c b/arch/powerpc/boot/dtc-src/livetree.c new file mode 100644 index 00000000000..6ba0846b431 --- /dev/null +++ b/arch/powerpc/boot/dtc-src/livetree.c | |||
@@ -0,0 +1,305 @@ | |||
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 | |||
27 | struct 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 | |||
41 | struct 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 | |||
49 | struct 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 | |||
64 | struct 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 | |||
81 | struct 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 | |||
92 | struct 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 | |||
100 | void 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 | |||
113 | void add_child(struct node *parent, struct node *child) | ||
114 | { | ||
115 | struct node **p; | ||
116 | |||
117 | child->next_sibling = NULL; | ||
118 | |||
119 | p = &parent->children; | ||
120 | while (*p) | ||
121 | p = &((*p)->next_sibling); | ||
122 | |||
123 | *p = child; | ||
124 | } | ||
125 | |||
126 | struct reserve_info *build_reserve_entry(u64 address, u64 size, char *label) | ||
127 | { | ||
128 | struct reserve_info *new = xmalloc(sizeof(*new)); | ||
129 | |||
130 | new->re.address = address; | ||
131 | new->re.size = size; | ||
132 | |||
133 | new->next = NULL; | ||
134 | |||
135 | new->label = label; | ||
136 | |||
137 | return new; | ||
138 | } | ||
139 | |||
140 | struct reserve_info *chain_reserve_entry(struct reserve_info *first, | ||
141 | struct reserve_info *list) | ||
142 | { | ||
143 | assert(first->next == NULL); | ||
144 | |||
145 | first->next = list; | ||
146 | return first; | ||
147 | } | ||
148 | |||
149 | struct reserve_info *add_reserve_entry(struct reserve_info *list, | ||
150 | struct reserve_info *new) | ||
151 | { | ||
152 | struct reserve_info *last; | ||
153 | |||
154 | new->next = NULL; | ||
155 | |||
156 | if (! list) | ||
157 | return new; | ||
158 | |||
159 | for (last = list; last->next; last = last->next) | ||
160 | ; | ||
161 | |||
162 | last->next = new; | ||
163 | |||
164 | return list; | ||
165 | } | ||
166 | |||
167 | struct boot_info *build_boot_info(struct reserve_info *reservelist, | ||
168 | struct node *tree) | ||
169 | { | ||
170 | struct boot_info *bi; | ||
171 | |||
172 | bi = xmalloc(sizeof(*bi)); | ||
173 | bi->reservelist = reservelist; | ||
174 | bi->dt = tree; | ||
175 | |||
176 | return bi; | ||
177 | } | ||
178 | |||
179 | /* | ||
180 | * Tree accessor functions | ||
181 | */ | ||
182 | |||
183 | const char *get_unitname(struct node *node) | ||
184 | { | ||
185 | if (node->name[node->basenamelen] == '\0') | ||
186 | return ""; | ||
187 | else | ||
188 | return node->name + node->basenamelen + 1; | ||
189 | } | ||
190 | |||
191 | struct property *get_property(struct node *node, const char *propname) | ||
192 | { | ||
193 | struct property *prop; | ||
194 | |||
195 | for_each_property(node, prop) | ||
196 | if (streq(prop->name, propname)) | ||
197 | return prop; | ||
198 | |||
199 | return NULL; | ||
200 | } | ||
201 | |||
202 | cell_t propval_cell(struct property *prop) | ||
203 | { | ||
204 | assert(prop->val.len == sizeof(cell_t)); | ||
205 | return be32_to_cpu(*((cell_t *)prop->val.val)); | ||
206 | } | ||
207 | |||
208 | struct node *get_subnode(struct node *node, const char *nodename) | ||
209 | { | ||
210 | struct node *child; | ||
211 | |||
212 | for_each_child(node, child) | ||
213 | if (streq(child->name, nodename)) | ||
214 | return child; | ||
215 | |||
216 | return NULL; | ||
217 | } | ||
218 | |||
219 | struct node *get_node_by_path(struct node *tree, const char *path) | ||
220 | { | ||
221 | const char *p; | ||
222 | struct node *child; | ||
223 | |||
224 | if (!path || ! (*path)) | ||
225 | return tree; | ||
226 | |||
227 | while (path[0] == '/') | ||
228 | path++; | ||
229 | |||
230 | p = strchr(path, '/'); | ||
231 | |||
232 | for_each_child(tree, child) { | ||
233 | if (p && strneq(path, child->name, p-path)) | ||
234 | return get_node_by_path(child, p+1); | ||
235 | else if (!p && streq(path, child->name)) | ||
236 | return child; | ||
237 | } | ||
238 | |||
239 | return NULL; | ||
240 | } | ||
241 | |||
242 | struct node *get_node_by_label(struct node *tree, const char *label) | ||
243 | { | ||
244 | struct node *child, *node; | ||
245 | |||
246 | assert(label && (strlen(label) > 0)); | ||
247 | |||
248 | if (tree->label && streq(tree->label, label)) | ||
249 | return tree; | ||
250 | |||
251 | for_each_child(tree, child) { | ||
252 | node = get_node_by_label(child, label); | ||
253 | if (node) | ||
254 | return node; | ||
255 | } | ||
256 | |||
257 | return NULL; | ||
258 | } | ||
259 | |||
260 | struct node *get_node_by_phandle(struct node *tree, cell_t phandle) | ||
261 | { | ||
262 | struct node *child, *node; | ||
263 | |||
264 | assert((phandle != 0) && (phandle != -1)); | ||
265 | |||
266 | if (tree->phandle == phandle) | ||
267 | return tree; | ||
268 | |||
269 | for_each_child(tree, child) { | ||
270 | node = get_node_by_phandle(child, phandle); | ||
271 | if (node) | ||
272 | return node; | ||
273 | } | ||
274 | |||
275 | return NULL; | ||
276 | } | ||
277 | |||
278 | struct node *get_node_by_ref(struct node *tree, const char *ref) | ||
279 | { | ||
280 | if (ref[0] == '/') | ||
281 | return get_node_by_path(tree, ref); | ||
282 | else | ||
283 | return get_node_by_label(tree, ref); | ||
284 | } | ||
285 | |||
286 | cell_t get_node_phandle(struct node *root, struct node *node) | ||
287 | { | ||
288 | static cell_t phandle = 1; /* FIXME: ick, static local */ | ||
289 | |||
290 | if ((node->phandle != 0) && (node->phandle != -1)) | ||
291 | return node->phandle; | ||
292 | |||
293 | assert(! get_property(node, "linux,phandle")); | ||
294 | |||
295 | while (get_node_by_phandle(root, phandle)) | ||
296 | phandle++; | ||
297 | |||
298 | node->phandle = phandle; | ||
299 | add_property(node, | ||
300 | build_property("linux,phandle", | ||
301 | data_append_cell(empty_data, phandle), | ||
302 | NULL)); | ||
303 | |||
304 | return node->phandle; | ||
305 | } | ||