]> git.saurik.com Git - apple/xnu.git/blob - pexpert/gen/device_tree.c
dc3ea9ddc05f7d0a6a3830b13cbc4c1bb7a38143
[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
43 #ifndef NULL
44 #define NULL ((void *) 0)
45 #endif
46
47 #define round_long(x) (((x) + 3UL) & ~(3UL))
48 #define next_prop(x) ((DeviceTreeNodeProperty *) (((uintptr_t)x) + sizeof(DeviceTreeNodeProperty) + round_long(x->length)))
49
50 /* Entry*/
51 typedef DeviceTreeNode *RealDTEntry;
52
53 typedef struct DTSavedScope {
54 struct DTSavedScope * nextScope;
55 RealDTEntry scope;
56 RealDTEntry entry;
57 unsigned long index;
58 } *DTSavedScopePtr;
59
60 /* Entry Iterator*/
61 typedef struct OpaqueDTEntryIterator {
62 RealDTEntry outerScope;
63 RealDTEntry currentScope;
64 RealDTEntry currentEntry;
65 DTSavedScopePtr savedScope;
66 unsigned long currentIndex;
67 } *RealDTEntryIterator;
68
69 /* Property Iterator*/
70 typedef struct OpaqueDTPropertyIterator {
71 RealDTEntry entry;
72 DeviceTreeNodeProperty *currentProperty;
73 unsigned long currentIndex;
74 } *RealDTPropertyIterator;
75
76 static int DTInitialized;
77 static RealDTEntry DTRootNode;
78
79 /*
80 * Support Routines
81 */
82 static RealDTEntry
83 skipProperties(RealDTEntry entry)
84 {
85 DeviceTreeNodeProperty *prop;
86 unsigned int k;
87
88 if (entry == NULL || entry->nProperties == 0) {
89 return NULL;
90 } else {
91 prop = (DeviceTreeNodeProperty *) (entry + 1);
92 for (k = 0; k < entry->nProperties; k++) {
93 prop = next_prop(prop);
94 }
95 }
96 return ((RealDTEntry) prop);
97 }
98
99 static RealDTEntry
100 skipTree(RealDTEntry root)
101 {
102 RealDTEntry entry;
103 unsigned int k;
104
105 entry = skipProperties(root);
106 if (entry == NULL) {
107 return NULL;
108 }
109 for (k = 0; k < root->nChildren; k++) {
110 entry = skipTree(entry);
111 }
112 return entry;
113 }
114
115 static RealDTEntry
116 GetFirstChild(RealDTEntry parent)
117 {
118 return skipProperties(parent);
119 }
120
121 static RealDTEntry
122 GetNextChild(RealDTEntry sibling)
123 {
124 return skipTree(sibling);
125 }
126
127 static const char *
128 GetNextComponent(const char *cp, char *bp)
129 {
130 while (*cp != 0) {
131 if (*cp == kDTPathNameSeparator) {
132 cp++;
133 break;
134 }
135 *bp++ = *cp++;
136 }
137 *bp = 0;
138 return cp;
139 }
140
141 static RealDTEntry
142 FindChild(RealDTEntry cur, char *buf)
143 {
144 RealDTEntry child;
145 unsigned long index;
146 char * str;
147 unsigned int dummy;
148
149 if (cur->nChildren == 0) {
150 return NULL;
151 }
152 index = 1;
153 child = GetFirstChild(cur);
154 while (1) {
155 if (DTGetProperty(child, "name", (void **)&str, &dummy) != kSuccess) {
156 break;
157 }
158 if (strcmp(str, buf) == 0) {
159 return child;
160 }
161 if (index >= cur->nChildren) {
162 break;
163 }
164 child = GetNextChild(child);
165 index++;
166 }
167 return NULL;
168 }
169
170
171 /*
172 * External Routines
173 */
174 void
175 DTInit(void *base)
176 {
177 DTRootNode = (RealDTEntry) base;
178 DTInitialized = (DTRootNode != 0);
179 }
180
181 int
182 DTEntryIsEqual(const DTEntry ref1, const DTEntry ref2)
183 {
184 /* equality of pointers */
185 return (ref1 == ref2);
186 }
187
188 static char *startingP; // needed for find_entry
189 int find_entry(const char *propName, const char *propValue, DTEntry *entryH);
190
191 int DTFindEntry(const char *propName, const char *propValue, DTEntry *entryH)
192 {
193 if (!DTInitialized) {
194 return kError;
195 }
196
197 startingP = (char *)DTRootNode;
198 return(find_entry(propName, propValue, entryH));
199 }
200
201 int find_entry(const char *propName, const char *propValue, DTEntry *entryH)
202 {
203 DeviceTreeNode *nodeP = (DeviceTreeNode *) (void *) startingP;
204 unsigned int k;
205
206 if (nodeP->nProperties == 0) return(kError); // End of the list of nodes
207 startingP = (char *) (nodeP + 1);
208
209 // Search current entry
210 for (k = 0; k < nodeP->nProperties; ++k) {
211 DeviceTreeNodeProperty *propP = (DeviceTreeNodeProperty *) (void *) startingP;
212
213 startingP += sizeof (*propP) + ((propP->length + 3) & -4);
214
215 if (strcmp (propP->name, propName) == 0) {
216 if (propValue == NULL || strcmp( (char *)(propP + 1), propValue) == 0)
217 {
218 *entryH = (DTEntry)nodeP;
219 return(kSuccess);
220 }
221 }
222 }
223
224 // Search child nodes
225 for (k = 0; k < nodeP->nChildren; ++k)
226 {
227 if (find_entry(propName, propValue, entryH) == kSuccess)
228 return(kSuccess);
229 }
230 return(kError);
231 }
232
233 int
234 DTLookupEntry(const DTEntry searchPoint, const char *pathName, DTEntry *foundEntry)
235 {
236 DTEntryNameBuf buf;
237 RealDTEntry cur;
238 const char * cp;
239
240 if (!DTInitialized) {
241 return kError;
242 }
243 if (searchPoint == NULL) {
244 cur = DTRootNode;
245 } else {
246 cur = searchPoint;
247 }
248 cp = pathName;
249 if (*cp == kDTPathNameSeparator) {
250 cp++;
251 if (*cp == 0) {
252 *foundEntry = cur;
253 return kSuccess;
254 }
255 }
256 do {
257 cp = GetNextComponent(cp, buf);
258
259 /* Check for done */
260 if (*buf == 0) {
261 if (*cp == 0) {
262 *foundEntry = cur;
263 return kSuccess;
264 }
265 break;
266 }
267
268 cur = FindChild(cur, buf);
269
270 } while (cur != NULL);
271
272 return kError;
273 }
274
275 int
276 DTCreateEntryIterator(const DTEntry startEntry, DTEntryIterator *iterator)
277 {
278 RealDTEntryIterator iter;
279
280 if (!DTInitialized) {
281 return kError;
282 }
283
284 iter = (RealDTEntryIterator) kalloc(sizeof(struct OpaqueDTEntryIterator));
285 if (startEntry != NULL) {
286 iter->outerScope = (RealDTEntry) startEntry;
287 iter->currentScope = (RealDTEntry) startEntry;
288 } else {
289 iter->outerScope = DTRootNode;
290 iter->currentScope = DTRootNode;
291 }
292 iter->currentEntry = NULL;
293 iter->savedScope = NULL;
294 iter->currentIndex = 0;
295
296 *iterator = iter;
297 return kSuccess;
298 }
299
300 int
301 DTDisposeEntryIterator(DTEntryIterator iterator)
302 {
303 RealDTEntryIterator iter = iterator;
304 DTSavedScopePtr scope;
305
306 while ((scope = iter->savedScope) != NULL) {
307 iter->savedScope = scope->nextScope;
308 kfree(scope, sizeof(struct DTSavedScope));
309 }
310 kfree(iterator, sizeof(struct OpaqueDTEntryIterator));
311 return kSuccess;
312 }
313
314 int
315 DTEnterEntry(DTEntryIterator iterator, DTEntry childEntry)
316 {
317 RealDTEntryIterator iter = iterator;
318 DTSavedScopePtr newScope;
319
320 if (childEntry == NULL) {
321 return kError;
322 }
323 newScope = (DTSavedScopePtr) kalloc(sizeof(struct DTSavedScope));
324 newScope->nextScope = iter->savedScope;
325 newScope->scope = iter->currentScope;
326 newScope->entry = iter->currentEntry;
327 newScope->index = iter->currentIndex;
328
329 iter->currentScope = childEntry;
330 iter->currentEntry = NULL;
331 iter->savedScope = newScope;
332 iter->currentIndex = 0;
333
334 return kSuccess;
335 }
336
337 int
338 DTExitEntry(DTEntryIterator iterator, DTEntry *currentPosition)
339 {
340 RealDTEntryIterator iter = iterator;
341 DTSavedScopePtr newScope;
342
343 newScope = iter->savedScope;
344 if (newScope == NULL) {
345 return kError;
346 }
347 iter->savedScope = newScope->nextScope;
348 iter->currentScope = newScope->scope;
349 iter->currentEntry = newScope->entry;
350 iter->currentIndex = newScope->index;
351 *currentPosition = iter->currentEntry;
352
353 kfree(newScope, sizeof(struct DTSavedScope));
354
355 return kSuccess;
356 }
357
358 int
359 DTIterateEntries(DTEntryIterator iterator, DTEntry *nextEntry)
360 {
361 RealDTEntryIterator iter = iterator;
362
363 if (iter->currentIndex >= iter->currentScope->nChildren) {
364 *nextEntry = NULL;
365 return kIterationDone;
366 } else {
367 iter->currentIndex++;
368 if (iter->currentIndex == 1) {
369 iter->currentEntry = GetFirstChild(iter->currentScope);
370 } else {
371 iter->currentEntry = GetNextChild(iter->currentEntry);
372 }
373 *nextEntry = iter->currentEntry;
374 return kSuccess;
375 }
376 }
377
378 int
379 DTRestartEntryIteration(DTEntryIterator iterator)
380 {
381 RealDTEntryIterator iter = iterator;
382 #if 0
383 // This commented out code allows a second argument (outer)
384 // which (if true) causes restarting at the outer scope
385 // rather than the current scope.
386 DTSavedScopePtr scope;
387
388 if (outer) {
389 while ((scope = iter->savedScope) != NULL) {
390 iter->savedScope = scope->nextScope;
391 kfree((vm_offset_t) scope, sizeof(struct DTSavedScope));
392 }
393 iter->currentScope = iter->outerScope;
394 }
395 #endif
396 iter->currentEntry = NULL;
397 iter->currentIndex = 0;
398 return kSuccess;
399 }
400
401 int
402 DTGetProperty(const DTEntry entry, const char *propertyName, void **propertyValue, unsigned int *propertySize)
403 {
404 DeviceTreeNodeProperty *prop;
405 unsigned int k;
406
407 if (entry == NULL || entry->nProperties == 0) {
408 return kError;
409 } else {
410 prop = (DeviceTreeNodeProperty *) (entry + 1);
411 for (k = 0; k < entry->nProperties; k++) {
412 if (strcmp(prop->name, propertyName) == 0) {
413 *propertyValue = (void *) (((uintptr_t)prop)
414 + sizeof(DeviceTreeNodeProperty));
415 *propertySize = prop->length;
416 return kSuccess;
417 }
418 prop = next_prop(prop);
419 }
420 }
421 return kError;
422 }
423
424 int
425 DTCreatePropertyIterator(const DTEntry entry, DTPropertyIterator *iterator)
426 {
427 RealDTPropertyIterator iter;
428
429 iter = (RealDTPropertyIterator) kalloc(sizeof(struct OpaqueDTPropertyIterator));
430 iter->entry = entry;
431 iter->currentProperty = NULL;
432 iter->currentIndex = 0;
433
434 *iterator = iter;
435 return kSuccess;
436 }
437
438 int
439 DTDisposePropertyIterator(DTPropertyIterator iterator)
440 {
441 kfree(iterator, sizeof(struct OpaqueDTPropertyIterator));
442 return kSuccess;
443 }
444
445 int
446 DTIterateProperties(DTPropertyIterator iterator, char **foundProperty)
447 {
448 RealDTPropertyIterator iter = iterator;
449
450 if (iter->currentIndex >= iter->entry->nProperties) {
451 *foundProperty = NULL;
452 return kIterationDone;
453 } else {
454 iter->currentIndex++;
455 if (iter->currentIndex == 1) {
456 iter->currentProperty = (DeviceTreeNodeProperty *) (iter->entry + 1);
457 } else {
458 iter->currentProperty = next_prop(iter->currentProperty);
459 }
460 *foundProperty = iter->currentProperty->name;
461 return kSuccess;
462 }
463 }
464
465 int
466 DTRestartPropertyIteration(DTPropertyIterator iterator)
467 {
468 RealDTPropertyIterator iter = iterator;
469
470 iter->currentProperty = NULL;
471 iter->currentIndex = 0;
472 return kSuccess;
473 }
474