]>
git.saurik.com Git - apple/xnu.git/blob - pexpert/gen/device_tree.c
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/debug.h>
39 #include <kern/kern_types.h>
40 #include <kern/kalloc.h>
41 #include <os/overflow.h>
43 #include <sys/types.h>
45 static int DTInitialized
;
46 static RealDTEntry DTRootNode
;
51 static inline DeviceTreeNodeProperty
*
52 next_prop(DeviceTreeNodeProperty
* prop
)
55 if (os_add3_overflow((uintptr_t)prop
, prop
->length
, sizeof(DeviceTreeNodeProperty
) + 3, &next_addr
)) {
56 panic("Device tree property overflow: prop %p, length 0x%x\n", prop
, prop
->length
);
59 return (DeviceTreeNodeProperty
*)next_addr
;
63 skipProperties(RealDTEntry entry
)
65 DeviceTreeNodeProperty
*prop
;
68 if (entry
== NULL
|| entry
->nProperties
== 0) {
71 prop
= (DeviceTreeNodeProperty
*) (entry
+ 1);
72 for (k
= 0; k
< entry
->nProperties
; k
++) {
73 prop
= next_prop(prop
);
76 return (RealDTEntry
) prop
;
80 skipTree(RealDTEntry root
)
85 entry
= skipProperties(root
);
89 for (k
= 0; k
< root
->nChildren
; k
++) {
90 entry
= skipTree(entry
);
96 GetFirstChild(RealDTEntry parent
)
98 return skipProperties(parent
);
102 GetNextChild(RealDTEntry sibling
)
104 return skipTree(sibling
);
108 GetNextComponent(const char *cp
, char *bp
)
114 if (*cp
== kDTPathNameSeparator
) {
118 if (++length
> kDTMaxEntryNameLength
) {
129 FindChild(RealDTEntry cur
, char *buf
)
136 if (cur
->nChildren
== 0) {
140 child
= GetFirstChild(cur
);
142 if (DTGetProperty(child
, "name", (void **)&str
, &dummy
) != kSuccess
) {
145 if (strcmp(str
, buf
) == 0) {
148 if (index
>= cur
->nChildren
) {
151 child
= GetNextChild(child
);
164 DTRootNode
= (RealDTEntry
) base
;
165 DTInitialized
= (DTRootNode
!= 0);
169 DTEntryIsEqual(const DTEntry ref1
, const DTEntry ref2
)
171 /* equality of pointers */
175 static char *startingP
; // needed for find_entry
176 int find_entry(const char *propName
, const char *propValue
, DTEntry
*entryH
);
179 DTFindEntry(const char *propName
, const char *propValue
, DTEntry
*entryH
)
181 if (!DTInitialized
) {
185 startingP
= (char *)DTRootNode
;
186 return find_entry(propName
, propValue
, entryH
);
190 find_entry(const char *propName
, const char *propValue
, DTEntry
*entryH
)
192 DeviceTreeNode
*nodeP
= (DeviceTreeNode
*) (void *) startingP
;
195 if (nodeP
->nProperties
== 0) {
196 return kError
; // End of the list of nodes
198 startingP
= (char *) (nodeP
+ 1);
200 // Search current entry
201 for (k
= 0; k
< nodeP
->nProperties
; ++k
) {
202 DeviceTreeNodeProperty
*propP
= (DeviceTreeNodeProperty
*) (void *) startingP
;
204 startingP
+= sizeof(*propP
) + ((propP
->length
+ 3) & -4);
206 if (strcmp(propP
->name
, propName
) == 0) {
207 if (propValue
== NULL
|| strcmp((char *)(propP
+ 1), propValue
) == 0) {
208 *entryH
= (DTEntry
)nodeP
;
214 // Search child nodes
215 for (k
= 0; k
< nodeP
->nChildren
; ++k
) {
216 if (find_entry(propName
, propValue
, entryH
) == kSuccess
) {
224 DTLookupEntry(const DTEntry searchPoint
, const char *pathName
, DTEntry
*foundEntry
)
230 if (!DTInitialized
) {
233 if (searchPoint
== NULL
) {
239 if (*cp
== kDTPathNameSeparator
) {
247 cp
= GetNextComponent(cp
, buf
);
258 cur
= FindChild(cur
, buf
);
259 } while (cur
!= NULL
);
265 DTInitEntryIterator(const DTEntry startEntry
, DTEntryIterator iter
)
267 if (!DTInitialized
) {
271 if (startEntry
!= NULL
) {
272 iter
->outerScope
= (RealDTEntry
) startEntry
;
273 iter
->currentScope
= (RealDTEntry
) startEntry
;
275 iter
->outerScope
= DTRootNode
;
276 iter
->currentScope
= DTRootNode
;
278 iter
->currentEntry
= NULL
;
279 iter
->savedScope
= NULL
;
280 iter
->currentIndex
= 0;
286 DTEnterEntry(DTEntryIterator iter
, DTEntry childEntry
)
288 DTSavedScopePtr newScope
;
290 if (childEntry
== NULL
) {
293 newScope
= (DTSavedScopePtr
) kalloc(sizeof(struct DTSavedScope
));
294 newScope
->nextScope
= iter
->savedScope
;
295 newScope
->scope
= iter
->currentScope
;
296 newScope
->entry
= iter
->currentEntry
;
297 newScope
->index
= iter
->currentIndex
;
299 iter
->currentScope
= childEntry
;
300 iter
->currentEntry
= NULL
;
301 iter
->savedScope
= newScope
;
302 iter
->currentIndex
= 0;
308 DTExitEntry(DTEntryIterator iter
, DTEntry
*currentPosition
)
310 DTSavedScopePtr newScope
;
312 newScope
= iter
->savedScope
;
313 if (newScope
== NULL
) {
316 iter
->savedScope
= newScope
->nextScope
;
317 iter
->currentScope
= newScope
->scope
;
318 iter
->currentEntry
= newScope
->entry
;
319 iter
->currentIndex
= newScope
->index
;
320 *currentPosition
= iter
->currentEntry
;
322 kfree(newScope
, sizeof(struct DTSavedScope
));
328 DTIterateEntries(DTEntryIterator iter
, DTEntry
*nextEntry
)
330 if (iter
->currentIndex
>= iter
->currentScope
->nChildren
) {
332 return kIterationDone
;
334 iter
->currentIndex
++;
335 if (iter
->currentIndex
== 1) {
336 iter
->currentEntry
= GetFirstChild(iter
->currentScope
);
338 iter
->currentEntry
= GetNextChild(iter
->currentEntry
);
340 *nextEntry
= iter
->currentEntry
;
346 DTRestartEntryIteration(DTEntryIterator iter
)
349 // This commented out code allows a second argument (outer)
350 // which (if true) causes restarting at the outer scope
351 // rather than the current scope.
352 DTSavedScopePtr scope
;
355 while ((scope
= iter
->savedScope
) != NULL
) {
356 iter
->savedScope
= scope
->nextScope
;
357 kfree((vm_offset_t
) scope
, sizeof(struct DTSavedScope
));
359 iter
->currentScope
= iter
->outerScope
;
362 iter
->currentEntry
= NULL
;
363 iter
->currentIndex
= 0;
368 DTGetProperty(const DTEntry entry
, const char *propertyName
, void **propertyValue
, unsigned int *propertySize
)
370 DeviceTreeNodeProperty
*prop
;
373 if (entry
== NULL
|| entry
->nProperties
== 0) {
376 prop
= (DeviceTreeNodeProperty
*) (entry
+ 1);
377 for (k
= 0; k
< entry
->nProperties
; k
++) {
378 if (strcmp(prop
->name
, propertyName
) == 0) {
379 *propertyValue
= (void *) (((uintptr_t)prop
)
380 + sizeof(DeviceTreeNodeProperty
));
381 *propertySize
= prop
->length
;
384 prop
= next_prop(prop
);
391 DTInitPropertyIterator(const DTEntry entry
, DTPropertyIterator iter
)
394 iter
->currentProperty
= NULL
;
395 iter
->currentIndex
= 0;
400 DTIterateProperties(DTPropertyIterator iter
, char **foundProperty
)
402 if (iter
->currentIndex
>= iter
->entry
->nProperties
) {
403 *foundProperty
= NULL
;
404 return kIterationDone
;
406 iter
->currentIndex
++;
407 if (iter
->currentIndex
== 1) {
408 iter
->currentProperty
= (DeviceTreeNodeProperty
*) (iter
->entry
+ 1);
410 iter
->currentProperty
= next_prop(iter
->currentProperty
);
412 *foundProperty
= iter
->currentProperty
->name
;
418 DTRestartPropertyIteration(DTPropertyIterator iter
)
420 iter
->currentProperty
= NULL
;
421 iter
->currentIndex
= 0;