2 * Copyright (c) 2000-2004 Apple Computer, Inc. All rights reserved.
4 * @APPLE_OSREFERENCE_LICENSE_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 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.
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
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.
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
29 * @OSF_FREE_COPYRIGHT@
32 #include <pexpert/protos.h>
33 #include <pexpert/boot.h>
34 #include <pexpert/device_tree.h>
36 #include <mach/mach_types.h>
37 #include <mach/machine/vm_types.h>
38 #include <kern/kern_types.h>
39 #include <kern/kalloc.h>
41 #include <sys/types.h>
44 #define NULL ((void *) 0)
47 #define round_long(x) (((x) + 3UL) & ~(3UL))
48 #define next_prop(x) ((DeviceTreeNodeProperty *) (((uintptr_t)x) + sizeof(DeviceTreeNodeProperty) + round_long(x->length)))
51 typedef DeviceTreeNode
*RealDTEntry
;
53 typedef struct DTSavedScope
{
54 struct DTSavedScope
* nextScope
;
61 typedef struct OpaqueDTEntryIterator
{
62 RealDTEntry outerScope
;
63 RealDTEntry currentScope
;
64 RealDTEntry currentEntry
;
65 DTSavedScopePtr savedScope
;
66 unsigned long currentIndex
;
67 } *RealDTEntryIterator
;
69 /* Property Iterator*/
70 typedef struct OpaqueDTPropertyIterator
{
72 DeviceTreeNodeProperty
*currentProperty
;
73 unsigned long currentIndex
;
74 } *RealDTPropertyIterator
;
76 static int DTInitialized
;
77 static RealDTEntry DTRootNode
;
83 skipProperties(RealDTEntry entry
)
85 DeviceTreeNodeProperty
*prop
;
88 if (entry
== NULL
|| entry
->nProperties
== 0) {
91 prop
= (DeviceTreeNodeProperty
*) (entry
+ 1);
92 for (k
= 0; k
< entry
->nProperties
; k
++) {
93 prop
= next_prop(prop
);
96 return ((RealDTEntry
) prop
);
100 skipTree(RealDTEntry root
)
105 entry
= skipProperties(root
);
109 for (k
= 0; k
< root
->nChildren
; k
++) {
110 entry
= skipTree(entry
);
116 GetFirstChild(RealDTEntry parent
)
118 return skipProperties(parent
);
122 GetNextChild(RealDTEntry sibling
)
124 return skipTree(sibling
);
128 GetNextComponent(const char *cp
, char *bp
)
131 if (*cp
== kDTPathNameSeparator
) {
142 FindChild(RealDTEntry cur
, char *buf
)
149 if (cur
->nChildren
== 0) {
153 child
= GetFirstChild(cur
);
155 if (DTGetProperty(child
, "name", (void **)&str
, &dummy
) != kSuccess
) {
158 if (strcmp(str
, buf
) == 0) {
161 if (index
>= cur
->nChildren
) {
164 child
= GetNextChild(child
);
177 DTRootNode
= (RealDTEntry
) base
;
178 DTInitialized
= (DTRootNode
!= 0);
182 DTEntryIsEqual(const DTEntry ref1
, const DTEntry ref2
)
184 /* equality of pointers */
185 return (ref1
== ref2
);
188 static char *startingP
; // needed for find_entry
189 int find_entry(const char *propName
, const char *propValue
, DTEntry
*entryH
);
191 int DTFindEntry(const char *propName
, const char *propValue
, DTEntry
*entryH
)
193 if (!DTInitialized
) {
197 startingP
= (char *)DTRootNode
;
198 return(find_entry(propName
, propValue
, entryH
));
201 int find_entry(const char *propName
, const char *propValue
, DTEntry
*entryH
)
203 DeviceTreeNode
*nodeP
= (DeviceTreeNode
*) (void *) startingP
;
206 if (nodeP
->nProperties
== 0) return(kError
); // End of the list of nodes
207 startingP
= (char *) (nodeP
+ 1);
209 // Search current entry
210 for (k
= 0; k
< nodeP
->nProperties
; ++k
) {
211 DeviceTreeNodeProperty
*propP
= (DeviceTreeNodeProperty
*) (void *) startingP
;
213 startingP
+= sizeof (*propP
) + ((propP
->length
+ 3) & -4);
215 if (strcmp (propP
->name
, propName
) == 0) {
216 if (propValue
== NULL
|| strcmp( (char *)(propP
+ 1), propValue
) == 0)
218 *entryH
= (DTEntry
)nodeP
;
224 // Search child nodes
225 for (k
= 0; k
< nodeP
->nChildren
; ++k
)
227 if (find_entry(propName
, propValue
, entryH
) == kSuccess
)
234 DTLookupEntry(const DTEntry searchPoint
, const char *pathName
, DTEntry
*foundEntry
)
240 if (!DTInitialized
) {
243 if (searchPoint
== NULL
) {
249 if (*cp
== kDTPathNameSeparator
) {
257 cp
= GetNextComponent(cp
, buf
);
268 cur
= FindChild(cur
, buf
);
270 } while (cur
!= NULL
);
276 DTCreateEntryIterator(const DTEntry startEntry
, DTEntryIterator
*iterator
)
278 RealDTEntryIterator iter
;
280 if (!DTInitialized
) {
284 iter
= (RealDTEntryIterator
) kalloc(sizeof(struct OpaqueDTEntryIterator
));
285 if (startEntry
!= NULL
) {
286 iter
->outerScope
= (RealDTEntry
) startEntry
;
287 iter
->currentScope
= (RealDTEntry
) startEntry
;
289 iter
->outerScope
= DTRootNode
;
290 iter
->currentScope
= DTRootNode
;
292 iter
->currentEntry
= NULL
;
293 iter
->savedScope
= NULL
;
294 iter
->currentIndex
= 0;
301 DTDisposeEntryIterator(DTEntryIterator iterator
)
303 RealDTEntryIterator iter
= iterator
;
304 DTSavedScopePtr scope
;
306 while ((scope
= iter
->savedScope
) != NULL
) {
307 iter
->savedScope
= scope
->nextScope
;
308 kfree(scope
, sizeof(struct DTSavedScope
));
310 kfree(iterator
, sizeof(struct OpaqueDTEntryIterator
));
315 DTEnterEntry(DTEntryIterator iterator
, DTEntry childEntry
)
317 RealDTEntryIterator iter
= iterator
;
318 DTSavedScopePtr newScope
;
320 if (childEntry
== NULL
) {
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
;
329 iter
->currentScope
= childEntry
;
330 iter
->currentEntry
= NULL
;
331 iter
->savedScope
= newScope
;
332 iter
->currentIndex
= 0;
338 DTExitEntry(DTEntryIterator iterator
, DTEntry
*currentPosition
)
340 RealDTEntryIterator iter
= iterator
;
341 DTSavedScopePtr newScope
;
343 newScope
= iter
->savedScope
;
344 if (newScope
== NULL
) {
347 iter
->savedScope
= newScope
->nextScope
;
348 iter
->currentScope
= newScope
->scope
;
349 iter
->currentEntry
= newScope
->entry
;
350 iter
->currentIndex
= newScope
->index
;
351 *currentPosition
= iter
->currentEntry
;
353 kfree(newScope
, sizeof(struct DTSavedScope
));
359 DTIterateEntries(DTEntryIterator iterator
, DTEntry
*nextEntry
)
361 RealDTEntryIterator iter
= iterator
;
363 if (iter
->currentIndex
>= iter
->currentScope
->nChildren
) {
365 return kIterationDone
;
367 iter
->currentIndex
++;
368 if (iter
->currentIndex
== 1) {
369 iter
->currentEntry
= GetFirstChild(iter
->currentScope
);
371 iter
->currentEntry
= GetNextChild(iter
->currentEntry
);
373 *nextEntry
= iter
->currentEntry
;
379 DTRestartEntryIteration(DTEntryIterator iterator
)
381 RealDTEntryIterator iter
= iterator
;
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
;
389 while ((scope
= iter
->savedScope
) != NULL
) {
390 iter
->savedScope
= scope
->nextScope
;
391 kfree((vm_offset_t
) scope
, sizeof(struct DTSavedScope
));
393 iter
->currentScope
= iter
->outerScope
;
396 iter
->currentEntry
= NULL
;
397 iter
->currentIndex
= 0;
402 DTGetProperty(const DTEntry entry
, const char *propertyName
, void **propertyValue
, unsigned int *propertySize
)
404 DeviceTreeNodeProperty
*prop
;
407 if (entry
== NULL
|| entry
->nProperties
== 0) {
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
;
418 prop
= next_prop(prop
);
425 DTCreatePropertyIterator(const DTEntry entry
, DTPropertyIterator
*iterator
)
427 RealDTPropertyIterator iter
;
429 iter
= (RealDTPropertyIterator
) kalloc(sizeof(struct OpaqueDTPropertyIterator
));
431 iter
->currentProperty
= NULL
;
432 iter
->currentIndex
= 0;
439 DTDisposePropertyIterator(DTPropertyIterator iterator
)
441 kfree(iterator
, sizeof(struct OpaqueDTPropertyIterator
));
446 DTIterateProperties(DTPropertyIterator iterator
, char **foundProperty
)
448 RealDTPropertyIterator iter
= iterator
;
450 if (iter
->currentIndex
>= iter
->entry
->nProperties
) {
451 *foundProperty
= NULL
;
452 return kIterationDone
;
454 iter
->currentIndex
++;
455 if (iter
->currentIndex
== 1) {
456 iter
->currentProperty
= (DeviceTreeNodeProperty
*) (iter
->entry
+ 1);
458 iter
->currentProperty
= next_prop(iter
->currentProperty
);
460 *foundProperty
= iter
->currentProperty
->name
;
466 DTRestartPropertyIteration(DTPropertyIterator iterator
)
468 RealDTPropertyIterator iter
= iterator
;
470 iter
->currentProperty
= NULL
;
471 iter
->currentIndex
= 0;