]> git.saurik.com Git - apple/xnu.git/blob - pexpert/gen/device_tree.c
ab3a1a1f5e006e1b76373ccd2ed46e27e1d7570d
[apple/xnu.git] / pexpert / gen / device_tree.c
1 /*
2 * Copyright (c) 2000-2004 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. The rights granted to you under the License
10 * may not be used to create, or enable the creation or redistribution of,
11 * unlawful or unlicensed copies of an Apple operating system, or to
12 * circumvent, violate, or enable the circumvention or violation of, any
13 * terms of an Apple operating system software license agreement.
14 *
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
17 *
18 * The Original Code and all software distributed under the License are
19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23 * Please see the License for the specific language governing rights and
24 * limitations under the License.
25 *
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27 */
28 /*
29 * @OSF_FREE_COPYRIGHT@
30 */
31
32 #include <pexpert/protos.h>
33 #include <pexpert/boot.h>
34 #include <pexpert/device_tree.h>
35
36 #include <mach/mach_types.h>
37 #include <mach/machine/vm_types.h>
38 #include <kern/kern_types.h>
39 #include <kern/kalloc.h>
40
41 #include <sys/types.h>
42 #ifdef i386
43 #include <i386/fakePPCStructs.h>
44 #endif
45
46 #ifndef NULL
47 #define NULL ((void *) 0)
48 #endif
49
50 #define round_long(x) (((x) + 3) & -4)
51 #define next_prop(x) ((DeviceTreeNodeProperty *) (((int)x) + sizeof(DeviceTreeNodeProperty) + round_long(x->length)))
52
53 /* Entry*/
54 typedef DeviceTreeNode *RealDTEntry;
55
56 typedef struct DTSavedScope {
57 struct DTSavedScope * nextScope;
58 RealDTEntry scope;
59 RealDTEntry entry;
60 unsigned long index;
61 } *DTSavedScopePtr;
62
63 /* Entry Iterator*/
64 typedef struct OpaqueDTEntryIterator {
65 RealDTEntry outerScope;
66 RealDTEntry currentScope;
67 RealDTEntry currentEntry;
68 DTSavedScopePtr savedScope;
69 unsigned long currentIndex;
70 } *RealDTEntryIterator;
71
72 /* Property Iterator*/
73 typedef struct OpaqueDTPropertyIterator {
74 RealDTEntry entry;
75 DeviceTreeNodeProperty *currentProperty;
76 unsigned long currentIndex;
77 } *RealDTPropertyIterator;
78
79 static int DTInitialized;
80 static RealDTEntry DTRootNode;
81
82 void DTInit(void *base);
83
84 /*
85 * Support Routines
86 */
87 static RealDTEntry
88 skipProperties(RealDTEntry entry)
89 {
90 DeviceTreeNodeProperty *prop;
91 int k;
92
93 if (entry == NULL || entry->nProperties == 0) {
94 return NULL;
95 } else {
96 prop = (DeviceTreeNodeProperty *) (entry + 1);
97 for (k = 0; k < entry->nProperties; k++) {
98 prop = next_prop(prop);
99 }
100 }
101 return ((RealDTEntry) prop);
102 }
103
104 static RealDTEntry
105 skipTree(RealDTEntry root)
106 {
107 RealDTEntry entry;
108 int k;
109
110 entry = skipProperties(root);
111 if (entry == NULL) {
112 return NULL;
113 }
114 for (k = 0; k < root->nChildren; k++) {
115 entry = skipTree(entry);
116 }
117 return entry;
118 }
119
120 static RealDTEntry
121 GetFirstChild(RealDTEntry parent)
122 {
123 return skipProperties(parent);
124 }
125
126 static RealDTEntry
127 GetNextChild(RealDTEntry sibling)
128 {
129 return skipTree(sibling);
130 }
131
132 static const char *
133 GetNextComponent(const char *cp, char *bp)
134 {
135 while (*cp != 0) {
136 if (*cp == kDTPathNameSeparator) {
137 cp++;
138 break;
139 }
140 *bp++ = *cp++;
141 }
142 *bp = 0;
143 return cp;
144 }
145
146 static RealDTEntry
147 FindChild(RealDTEntry cur, char *buf)
148 {
149 RealDTEntry child;
150 unsigned long index;
151 char * str;
152 int dummy;
153
154 if (cur->nChildren == 0) {
155 return NULL;
156 }
157 index = 1;
158 child = GetFirstChild(cur);
159 while (1) {
160 if (DTGetProperty(child, "name", (void **)&str, &dummy) != kSuccess) {
161 break;
162 }
163 if (strcmp(str, buf) == 0) {
164 return child;
165 }
166 if (index >= cur->nChildren) {
167 break;
168 }
169 child = GetNextChild(child);
170 index++;
171 }
172 return NULL;
173 }
174
175
176 /*
177 * External Routines
178 */
179 void
180 DTInit(void *base)
181 {
182 DTRootNode = (RealDTEntry) base;
183 DTInitialized = (DTRootNode != 0);
184 }
185
186 int
187 DTEntryIsEqual(const DTEntry ref1, const DTEntry ref2)
188 {
189 /* equality of pointers */
190 return (ref1 == ref2);
191 }
192
193 static char *startingP; // needed for find_entry
194 int find_entry(const char *propName, const char *propValue, DTEntry *entryH);
195
196 int DTFindEntry(const char *propName, const char *propValue, DTEntry *entryH)
197 {
198 if (!DTInitialized) {
199 return kError;
200 }
201
202 startingP = (char *)DTRootNode;
203 return(find_entry(propName, propValue, entryH));
204 }
205
206 int find_entry(const char *propName, const char *propValue, DTEntry *entryH)
207 {
208 DeviceTreeNode *nodeP = (DeviceTreeNode *) startingP;
209 int k;
210
211 if (nodeP->nProperties == 0) return(kError); // End of the list of nodes
212 startingP = (char *) (nodeP + 1);
213
214 // Search current entry
215 for (k = 0; k < nodeP->nProperties; ++k) {
216 DeviceTreeNodeProperty *propP = (DeviceTreeNodeProperty *) startingP;
217
218 startingP += sizeof (*propP) + ((propP->length + 3) & -4);
219
220 if (strcmp (propP->name, propName) == 0) {
221 if (strcmp( (char *)(propP + 1), propValue) == 0)
222 {
223 *entryH = (DTEntry)nodeP;
224 return(kSuccess);
225 }
226 }
227 }
228
229 // Search child nodes
230 for (k = 0; k < nodeP->nChildren; ++k)
231 {
232 if (find_entry(propName, propValue, entryH) == kSuccess)
233 return(kSuccess);
234 }
235 return(kError);
236 }
237
238 int
239 DTLookupEntry(const DTEntry searchPoint, const char *pathName, DTEntry *foundEntry)
240 {
241 DTEntryNameBuf buf;
242 RealDTEntry cur;
243 const char * cp;
244
245 if (!DTInitialized) {
246 return kError;
247 }
248 if (searchPoint == NULL) {
249 cur = DTRootNode;
250 } else {
251 cur = searchPoint;
252 }
253 cp = pathName;
254 if (*cp == kDTPathNameSeparator) {
255 cp++;
256 if (*cp == 0) {
257 *foundEntry = cur;
258 return kSuccess;
259 }
260 }
261 do {
262 cp = GetNextComponent(cp, buf);
263
264 /* Check for done */
265 if (*buf == 0) {
266 if (*cp == 0) {
267 *foundEntry = cur;
268 return kSuccess;
269 }
270 break;
271 }
272
273 cur = FindChild(cur, buf);
274
275 } while (cur != NULL);
276
277 return kError;
278 }
279
280 int
281 DTCreateEntryIterator(const DTEntry startEntry, DTEntryIterator *iterator)
282 {
283 RealDTEntryIterator iter;
284
285 if (!DTInitialized) {
286 return kError;
287 }
288
289 iter = (RealDTEntryIterator) kalloc(sizeof(struct OpaqueDTEntryIterator));
290 if (startEntry != NULL) {
291 iter->outerScope = (RealDTEntry) startEntry;
292 iter->currentScope = (RealDTEntry) startEntry;
293 } else {
294 iter->outerScope = DTRootNode;
295 iter->currentScope = DTRootNode;
296 }
297 iter->currentEntry = NULL;
298 iter->savedScope = NULL;
299 iter->currentIndex = 0;
300
301 *iterator = iter;
302 return kSuccess;
303 }
304
305 int
306 DTDisposeEntryIterator(DTEntryIterator iterator)
307 {
308 RealDTEntryIterator iter = iterator;
309 DTSavedScopePtr scope;
310
311 while ((scope = iter->savedScope) != NULL) {
312 iter->savedScope = scope->nextScope;
313 kfree(scope, sizeof(struct DTSavedScope));
314 }
315 kfree(iterator, sizeof(struct OpaqueDTEntryIterator));
316 return kSuccess;
317 }
318
319 int
320 DTEnterEntry(DTEntryIterator iterator, DTEntry childEntry)
321 {
322 RealDTEntryIterator iter = iterator;
323 DTSavedScopePtr newScope;
324
325 if (childEntry == NULL) {
326 return kError;
327 }
328 newScope = (DTSavedScopePtr) kalloc(sizeof(struct DTSavedScope));
329 newScope->nextScope = iter->savedScope;
330 newScope->scope = iter->currentScope;
331 newScope->entry = iter->currentEntry;
332 newScope->index = iter->currentIndex;
333
334 iter->currentScope = childEntry;
335 iter->currentEntry = NULL;
336 iter->savedScope = newScope;
337 iter->currentIndex = 0;
338
339 return kSuccess;
340 }
341
342 int
343 DTExitEntry(DTEntryIterator iterator, DTEntry *currentPosition)
344 {
345 RealDTEntryIterator iter = iterator;
346 DTSavedScopePtr newScope;
347
348 newScope = iter->savedScope;
349 if (newScope == NULL) {
350 return kError;
351 }
352 iter->savedScope = newScope->nextScope;
353 iter->currentScope = newScope->scope;
354 iter->currentEntry = newScope->entry;
355 iter->currentIndex = newScope->index;
356 *currentPosition = iter->currentEntry;
357
358 kfree(newScope, sizeof(struct DTSavedScope));
359
360 return kSuccess;
361 }
362
363 int
364 DTIterateEntries(DTEntryIterator iterator, DTEntry *nextEntry)
365 {
366 RealDTEntryIterator iter = iterator;
367
368 if (iter->currentIndex >= iter->currentScope->nChildren) {
369 *nextEntry = NULL;
370 return kIterationDone;
371 } else {
372 iter->currentIndex++;
373 if (iter->currentIndex == 1) {
374 iter->currentEntry = GetFirstChild(iter->currentScope);
375 } else {
376 iter->currentEntry = GetNextChild(iter->currentEntry);
377 }
378 *nextEntry = iter->currentEntry;
379 return kSuccess;
380 }
381 }
382
383 int
384 DTRestartEntryIteration(DTEntryIterator iterator)
385 {
386 RealDTEntryIterator iter = iterator;
387 #if 0
388 // This commented out code allows a second argument (outer)
389 // which (if true) causes restarting at the outer scope
390 // rather than the current scope.
391 DTSavedScopePtr scope;
392
393 if (outer) {
394 while ((scope = iter->savedScope) != NULL) {
395 iter->savedScope = scope->nextScope;
396 kfree((vm_offset_t) scope, sizeof(struct DTSavedScope));
397 }
398 iter->currentScope = iter->outerScope;
399 }
400 #endif
401 iter->currentEntry = NULL;
402 iter->currentIndex = 0;
403 return kSuccess;
404 }
405
406 int
407 DTGetProperty(const DTEntry entry, const char *propertyName, void **propertyValue, int *propertySize)
408 {
409 DeviceTreeNodeProperty *prop;
410 int k;
411
412 if (entry == NULL || entry->nProperties == 0) {
413 return kError;
414 } else {
415 prop = (DeviceTreeNodeProperty *) (entry + 1);
416 for (k = 0; k < entry->nProperties; k++) {
417 if (strcmp(prop->name, propertyName) == 0) {
418 *propertyValue = (void *) (((int)prop)
419 + sizeof(DeviceTreeNodeProperty));
420 *propertySize = prop->length;
421 return kSuccess;
422 }
423 prop = next_prop(prop);
424 }
425 }
426 return kError;
427 }
428
429 int
430 DTCreatePropertyIterator(const DTEntry entry, DTPropertyIterator *iterator)
431 {
432 RealDTPropertyIterator iter;
433
434 iter = (RealDTPropertyIterator) kalloc(sizeof(struct OpaqueDTPropertyIterator));
435 iter->entry = entry;
436 iter->currentProperty = NULL;
437 iter->currentIndex = 0;
438
439 *iterator = iter;
440 return kSuccess;
441 }
442
443 int
444 DTDisposePropertyIterator(DTPropertyIterator iterator)
445 {
446 kfree(iterator, sizeof(struct OpaqueDTPropertyIterator));
447 return kSuccess;
448 }
449
450 int
451 DTIterateProperties(DTPropertyIterator iterator, char **foundProperty)
452 {
453 RealDTPropertyIterator iter = iterator;
454
455 if (iter->currentIndex >= iter->entry->nProperties) {
456 *foundProperty = NULL;
457 return kIterationDone;
458 } else {
459 iter->currentIndex++;
460 if (iter->currentIndex == 1) {
461 iter->currentProperty = (DeviceTreeNodeProperty *) (iter->entry + 1);
462 } else {
463 iter->currentProperty = next_prop(iter->currentProperty);
464 }
465 *foundProperty = iter->currentProperty->name;
466 return kSuccess;
467 }
468 }
469
470 int
471 DTRestartPropertyIteration(DTPropertyIterator iterator)
472 {
473 RealDTPropertyIterator iter = iterator;
474
475 iter->currentProperty = NULL;
476 iter->currentIndex = 0;
477 return kSuccess;
478 }
479