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