]>
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
);
58 return (DeviceTreeNodeProperty
*)next_addr
;
62 skipProperties(RealDTEntry entry
)
64 DeviceTreeNodeProperty
*prop
;
67 if (entry
== NULL
|| entry
->nProperties
== 0) {
70 prop
= (DeviceTreeNodeProperty
*) (entry
+ 1);
71 for (k
= 0; k
< entry
->nProperties
; k
++) {
72 prop
= next_prop(prop
);
75 return ((RealDTEntry
) prop
);
79 skipTree(RealDTEntry root
)
84 entry
= skipProperties(root
);
88 for (k
= 0; k
< root
->nChildren
; k
++) {
89 entry
= skipTree(entry
);
95 GetFirstChild(RealDTEntry parent
)
97 return skipProperties(parent
);
101 GetNextChild(RealDTEntry sibling
)
103 return skipTree(sibling
);
107 GetNextComponent(const char *cp
, char *bp
)
113 if (*cp
== kDTPathNameSeparator
) {
117 if (++length
> kDTMaxEntryNameLength
) {
128 FindChild(RealDTEntry cur
, char *buf
)
135 if (cur
->nChildren
== 0) {
139 child
= GetFirstChild(cur
);
141 if (DTGetProperty(child
, "name", (void **)&str
, &dummy
) != kSuccess
) {
144 if (strcmp(str
, buf
) == 0) {
147 if (index
>= cur
->nChildren
) {
150 child
= GetNextChild(child
);
163 DTRootNode
= (RealDTEntry
) base
;
164 DTInitialized
= (DTRootNode
!= 0);
168 DTEntryIsEqual(const DTEntry ref1
, const DTEntry ref2
)
170 /* equality of pointers */
171 return (ref1
== ref2
);
174 static char *startingP
; // needed for find_entry
175 int find_entry(const char *propName
, const char *propValue
, DTEntry
*entryH
);
177 int DTFindEntry(const char *propName
, const char *propValue
, DTEntry
*entryH
)
179 if (!DTInitialized
) {
183 startingP
= (char *)DTRootNode
;
184 return(find_entry(propName
, propValue
, entryH
));
187 int find_entry(const char *propName
, const char *propValue
, DTEntry
*entryH
)
189 DeviceTreeNode
*nodeP
= (DeviceTreeNode
*) (void *) startingP
;
192 if (nodeP
->nProperties
== 0) return(kError
); // End of the list of nodes
193 startingP
= (char *) (nodeP
+ 1);
195 // Search current entry
196 for (k
= 0; k
< nodeP
->nProperties
; ++k
) {
197 DeviceTreeNodeProperty
*propP
= (DeviceTreeNodeProperty
*) (void *) startingP
;
199 startingP
+= sizeof (*propP
) + ((propP
->length
+ 3) & -4);
201 if (strcmp (propP
->name
, propName
) == 0) {
202 if (propValue
== NULL
|| strcmp( (char *)(propP
+ 1), propValue
) == 0)
204 *entryH
= (DTEntry
)nodeP
;
210 // Search child nodes
211 for (k
= 0; k
< nodeP
->nChildren
; ++k
)
213 if (find_entry(propName
, propValue
, entryH
) == kSuccess
)
220 DTLookupEntry(const DTEntry searchPoint
, const char *pathName
, DTEntry
*foundEntry
)
226 if (!DTInitialized
) {
229 if (searchPoint
== NULL
) {
235 if (*cp
== kDTPathNameSeparator
) {
243 cp
= GetNextComponent(cp
, buf
);
254 cur
= FindChild(cur
, buf
);
256 } while (cur
!= NULL
);
262 DTInitEntryIterator(const DTEntry startEntry
, DTEntryIterator iter
)
264 if (!DTInitialized
) {
268 if (startEntry
!= NULL
) {
269 iter
->outerScope
= (RealDTEntry
) startEntry
;
270 iter
->currentScope
= (RealDTEntry
) startEntry
;
272 iter
->outerScope
= DTRootNode
;
273 iter
->currentScope
= DTRootNode
;
275 iter
->currentEntry
= NULL
;
276 iter
->savedScope
= NULL
;
277 iter
->currentIndex
= 0;
283 DTEnterEntry(DTEntryIterator iter
, DTEntry childEntry
)
285 DTSavedScopePtr newScope
;
287 if (childEntry
== NULL
) {
290 newScope
= (DTSavedScopePtr
) kalloc(sizeof(struct DTSavedScope
));
291 newScope
->nextScope
= iter
->savedScope
;
292 newScope
->scope
= iter
->currentScope
;
293 newScope
->entry
= iter
->currentEntry
;
294 newScope
->index
= iter
->currentIndex
;
296 iter
->currentScope
= childEntry
;
297 iter
->currentEntry
= NULL
;
298 iter
->savedScope
= newScope
;
299 iter
->currentIndex
= 0;
305 DTExitEntry(DTEntryIterator iter
, DTEntry
*currentPosition
)
307 DTSavedScopePtr newScope
;
309 newScope
= iter
->savedScope
;
310 if (newScope
== NULL
) {
313 iter
->savedScope
= newScope
->nextScope
;
314 iter
->currentScope
= newScope
->scope
;
315 iter
->currentEntry
= newScope
->entry
;
316 iter
->currentIndex
= newScope
->index
;
317 *currentPosition
= iter
->currentEntry
;
319 kfree(newScope
, sizeof(struct DTSavedScope
));
325 DTIterateEntries(DTEntryIterator iter
, DTEntry
*nextEntry
)
327 if (iter
->currentIndex
>= iter
->currentScope
->nChildren
) {
329 return kIterationDone
;
331 iter
->currentIndex
++;
332 if (iter
->currentIndex
== 1) {
333 iter
->currentEntry
= GetFirstChild(iter
->currentScope
);
335 iter
->currentEntry
= GetNextChild(iter
->currentEntry
);
337 *nextEntry
= iter
->currentEntry
;
343 DTRestartEntryIteration(DTEntryIterator iter
)
346 // This commented out code allows a second argument (outer)
347 // which (if true) causes restarting at the outer scope
348 // rather than the current scope.
349 DTSavedScopePtr scope
;
352 while ((scope
= iter
->savedScope
) != NULL
) {
353 iter
->savedScope
= scope
->nextScope
;
354 kfree((vm_offset_t
) scope
, sizeof(struct DTSavedScope
));
356 iter
->currentScope
= iter
->outerScope
;
359 iter
->currentEntry
= NULL
;
360 iter
->currentIndex
= 0;
365 DTGetProperty(const DTEntry entry
, const char *propertyName
, void **propertyValue
, unsigned int *propertySize
)
367 DeviceTreeNodeProperty
*prop
;
370 if (entry
== NULL
|| entry
->nProperties
== 0) {
373 prop
= (DeviceTreeNodeProperty
*) (entry
+ 1);
374 for (k
= 0; k
< entry
->nProperties
; k
++) {
375 if (strcmp(prop
->name
, propertyName
) == 0) {
376 *propertyValue
= (void *) (((uintptr_t)prop
)
377 + sizeof(DeviceTreeNodeProperty
));
378 *propertySize
= prop
->length
;
381 prop
= next_prop(prop
);
388 DTInitPropertyIterator(const DTEntry entry
, DTPropertyIterator iter
)
392 iter
->currentProperty
= NULL
;
393 iter
->currentIndex
= 0;
398 DTIterateProperties(DTPropertyIterator iter
, char **foundProperty
)
400 if (iter
->currentIndex
>= iter
->entry
->nProperties
) {
401 *foundProperty
= NULL
;
402 return kIterationDone
;
404 iter
->currentIndex
++;
405 if (iter
->currentIndex
== 1) {
406 iter
->currentProperty
= (DeviceTreeNodeProperty
*) (iter
->entry
+ 1);
408 iter
->currentProperty
= next_prop(iter
->currentProperty
);
410 *foundProperty
= iter
->currentProperty
->name
;
416 DTRestartPropertyIteration(DTPropertyIterator iter
)
418 iter
->currentProperty
= NULL
;
419 iter
->currentIndex
= 0;