2 * Copyright (c) 2000-2004 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_OSREFERENCE_HEADER_START@
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
16 * Please obtain a copy of the License at
17 * http://www.opensource.apple.com/apsl/ and read it before using this
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.
28 * @APPLE_LICENSE_OSREFERENCE_HEADER_END@
31 * @OSF_FREE_COPYRIGHT@
34 #include <pexpert/protos.h>
35 #include <pexpert/boot.h>
36 #include <pexpert/device_tree.h>
38 #include <mach/mach_types.h>
39 #include <mach/machine/vm_types.h>
40 #include <kern/kern_types.h>
41 #include <kern/kalloc.h>
43 #include <sys/types.h>
45 #include <i386/fakePPCStructs.h>
49 #define NULL ((void *) 0)
52 #define round_long(x) (((x) + 3) & -4)
53 #define next_prop(x) ((DeviceTreeNodeProperty *) (((int)x) + sizeof(DeviceTreeNodeProperty) + round_long(x->length)))
56 typedef DeviceTreeNode
*RealDTEntry
;
58 typedef struct DTSavedScope
{
59 struct DTSavedScope
* nextScope
;
66 typedef struct OpaqueDTEntryIterator
{
67 RealDTEntry outerScope
;
68 RealDTEntry currentScope
;
69 RealDTEntry currentEntry
;
70 DTSavedScopePtr savedScope
;
71 unsigned long currentIndex
;
72 } *RealDTEntryIterator
;
74 /* Property Iterator*/
75 typedef struct OpaqueDTPropertyIterator
{
77 DeviceTreeNodeProperty
*currentProperty
;
78 unsigned long currentIndex
;
79 } *RealDTPropertyIterator
;
81 static int DTInitialized
;
82 static RealDTEntry DTRootNode
;
84 void DTInit(void *base
);
90 skipProperties(RealDTEntry entry
)
92 DeviceTreeNodeProperty
*prop
;
95 if (entry
== NULL
|| entry
->nProperties
== 0) {
98 prop
= (DeviceTreeNodeProperty
*) (entry
+ 1);
99 for (k
= 0; k
< entry
->nProperties
; k
++) {
100 prop
= next_prop(prop
);
103 return ((RealDTEntry
) prop
);
107 skipTree(RealDTEntry root
)
112 entry
= skipProperties(root
);
116 for (k
= 0; k
< root
->nChildren
; k
++) {
117 entry
= skipTree(entry
);
123 GetFirstChild(RealDTEntry parent
)
125 return skipProperties(parent
);
129 GetNextChild(RealDTEntry sibling
)
131 return skipTree(sibling
);
135 GetNextComponent(const char *cp
, char *bp
)
138 if (*cp
== kDTPathNameSeparator
) {
149 FindChild(RealDTEntry cur
, char *buf
)
156 if (cur
->nChildren
== 0) {
160 child
= GetFirstChild(cur
);
162 if (DTGetProperty(child
, "name", (void **)&str
, &dummy
) != kSuccess
) {
165 if (strcmp(str
, buf
) == 0) {
168 if (index
>= cur
->nChildren
) {
171 child
= GetNextChild(child
);
184 DTRootNode
= (RealDTEntry
) base
;
185 DTInitialized
= (DTRootNode
!= 0);
189 DTEntryIsEqual(const DTEntry ref1
, const DTEntry ref2
)
191 /* equality of pointers */
192 return (ref1
== ref2
);
195 static char *startingP
; // needed for find_entry
196 int find_entry(const char *propName
, const char *propValue
, DTEntry
*entryH
);
198 int DTFindEntry(const char *propName
, const char *propValue
, DTEntry
*entryH
)
200 if (!DTInitialized
) {
204 startingP
= (char *)DTRootNode
;
205 return(find_entry(propName
, propValue
, entryH
));
208 int find_entry(const char *propName
, const char *propValue
, DTEntry
*entryH
)
210 DeviceTreeNode
*nodeP
= (DeviceTreeNode
*) startingP
;
213 if (nodeP
->nProperties
== 0) return(kError
); // End of the list of nodes
214 startingP
= (char *) (nodeP
+ 1);
216 // Search current entry
217 for (k
= 0; k
< nodeP
->nProperties
; ++k
) {
218 DeviceTreeNodeProperty
*propP
= (DeviceTreeNodeProperty
*) startingP
;
220 startingP
+= sizeof (*propP
) + ((propP
->length
+ 3) & -4);
222 if (strcmp (propP
->name
, propName
) == 0) {
223 if (strcmp( (char *)(propP
+ 1), propValue
) == 0)
225 *entryH
= (DTEntry
)nodeP
;
231 // Search child nodes
232 for (k
= 0; k
< nodeP
->nChildren
; ++k
)
234 if (find_entry(propName
, propValue
, entryH
) == kSuccess
)
241 DTLookupEntry(const DTEntry searchPoint
, const char *pathName
, DTEntry
*foundEntry
)
247 if (!DTInitialized
) {
250 if (searchPoint
== NULL
) {
256 if (*cp
== kDTPathNameSeparator
) {
264 cp
= GetNextComponent(cp
, buf
);
275 cur
= FindChild(cur
, buf
);
277 } while (cur
!= NULL
);
283 DTCreateEntryIterator(const DTEntry startEntry
, DTEntryIterator
*iterator
)
285 RealDTEntryIterator iter
;
287 if (!DTInitialized
) {
291 iter
= (RealDTEntryIterator
) kalloc(sizeof(struct OpaqueDTEntryIterator
));
292 if (startEntry
!= NULL
) {
293 iter
->outerScope
= (RealDTEntry
) startEntry
;
294 iter
->currentScope
= (RealDTEntry
) startEntry
;
296 iter
->outerScope
= DTRootNode
;
297 iter
->currentScope
= DTRootNode
;
299 iter
->currentEntry
= NULL
;
300 iter
->savedScope
= NULL
;
301 iter
->currentIndex
= 0;
308 DTDisposeEntryIterator(DTEntryIterator iterator
)
310 RealDTEntryIterator iter
= iterator
;
311 DTSavedScopePtr scope
;
313 while ((scope
= iter
->savedScope
) != NULL
) {
314 iter
->savedScope
= scope
->nextScope
;
315 kfree(scope
, sizeof(struct DTSavedScope
));
317 kfree(iterator
, sizeof(struct OpaqueDTEntryIterator
));
322 DTEnterEntry(DTEntryIterator iterator
, DTEntry childEntry
)
324 RealDTEntryIterator iter
= iterator
;
325 DTSavedScopePtr newScope
;
327 if (childEntry
== NULL
) {
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
;
336 iter
->currentScope
= childEntry
;
337 iter
->currentEntry
= NULL
;
338 iter
->savedScope
= newScope
;
339 iter
->currentIndex
= 0;
345 DTExitEntry(DTEntryIterator iterator
, DTEntry
*currentPosition
)
347 RealDTEntryIterator iter
= iterator
;
348 DTSavedScopePtr newScope
;
350 newScope
= iter
->savedScope
;
351 if (newScope
== NULL
) {
354 iter
->savedScope
= newScope
->nextScope
;
355 iter
->currentScope
= newScope
->scope
;
356 iter
->currentEntry
= newScope
->entry
;
357 iter
->currentIndex
= newScope
->index
;
358 *currentPosition
= iter
->currentEntry
;
360 kfree(newScope
, sizeof(struct DTSavedScope
));
366 DTIterateEntries(DTEntryIterator iterator
, DTEntry
*nextEntry
)
368 RealDTEntryIterator iter
= iterator
;
370 if (iter
->currentIndex
>= iter
->currentScope
->nChildren
) {
372 return kIterationDone
;
374 iter
->currentIndex
++;
375 if (iter
->currentIndex
== 1) {
376 iter
->currentEntry
= GetFirstChild(iter
->currentScope
);
378 iter
->currentEntry
= GetNextChild(iter
->currentEntry
);
380 *nextEntry
= iter
->currentEntry
;
386 DTRestartEntryIteration(DTEntryIterator iterator
)
388 RealDTEntryIterator iter
= iterator
;
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
;
396 while ((scope
= iter
->savedScope
) != NULL
) {
397 iter
->savedScope
= scope
->nextScope
;
398 kfree((vm_offset_t
) scope
, sizeof(struct DTSavedScope
));
400 iter
->currentScope
= iter
->outerScope
;
403 iter
->currentEntry
= NULL
;
404 iter
->currentIndex
= 0;
409 DTGetProperty(const DTEntry entry
, const char *propertyName
, void **propertyValue
, int *propertySize
)
411 DeviceTreeNodeProperty
*prop
;
414 if (entry
== NULL
|| entry
->nProperties
== 0) {
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
;
425 prop
= next_prop(prop
);
432 DTCreatePropertyIterator(const DTEntry entry
, DTPropertyIterator
*iterator
)
434 RealDTPropertyIterator iter
;
436 iter
= (RealDTPropertyIterator
) kalloc(sizeof(struct OpaqueDTPropertyIterator
));
438 iter
->currentProperty
= NULL
;
439 iter
->currentIndex
= 0;
446 DTDisposePropertyIterator(DTPropertyIterator iterator
)
448 kfree(iterator
, sizeof(struct OpaqueDTPropertyIterator
));
453 DTIterateProperties(DTPropertyIterator iterator
, char **foundProperty
)
455 RealDTPropertyIterator iter
= iterator
;
457 if (iter
->currentIndex
>= iter
->entry
->nProperties
) {
458 *foundProperty
= NULL
;
459 return kIterationDone
;
461 iter
->currentIndex
++;
462 if (iter
->currentIndex
== 1) {
463 iter
->currentProperty
= (DeviceTreeNodeProperty
*) (iter
->entry
+ 1);
465 iter
->currentProperty
= next_prop(iter
->currentProperty
);
467 *foundProperty
= iter
->currentProperty
->name
;
473 DTRestartPropertyIteration(DTPropertyIterator iterator
)
475 RealDTPropertyIterator iter
= iterator
;
477 iter
->currentProperty
= NULL
;
478 iter
->currentIndex
= 0;