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