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