]> git.saurik.com Git - apple/xnu.git/blame - pexpert/gen/device_tree.c
xnu-792.13.8.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 *
8ad349bb 4 * @APPLE_LICENSE_OSREFERENCE_HEADER_START@
1c79356b 5 *
8ad349bb
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
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
14 * agreement.
15 *
16 * Please obtain a copy of the License at
17 * http://www.opensource.apple.com/apsl/ and read it before using this
18 * file.
19 *
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.
27 *
28 * @APPLE_LICENSE_OSREFERENCE_HEADER_END@
1c79356b
A
29 */
30/*
31 * @OSF_FREE_COPYRIGHT@
32 */
33
34#include <pexpert/protos.h>
35#include <pexpert/boot.h>
36#include <pexpert/device_tree.h>
91447636
A
37
38#include <mach/mach_types.h>
1c79356b 39#include <mach/machine/vm_types.h>
91447636
A
40#include <kern/kern_types.h>
41#include <kern/kalloc.h>
42
1c79356b
A
43#include <sys/types.h>
44#ifdef i386
45#include <i386/fakePPCStructs.h>
46#endif
47
48#ifndef NULL
49#define NULL ((void *) 0)
50#endif
51
52#define round_long(x) (((x) + 3) & -4)
53#define next_prop(x) ((DeviceTreeNodeProperty *) (((int)x) + sizeof(DeviceTreeNodeProperty) + round_long(x->length)))
54
55/* Entry*/
56typedef DeviceTreeNode *RealDTEntry;
57
58typedef struct DTSavedScope {
59 struct DTSavedScope * nextScope;
60 RealDTEntry scope;
61 RealDTEntry entry;
62 unsigned long index;
63} *DTSavedScopePtr;
64
65/* Entry Iterator*/
66typedef struct OpaqueDTEntryIterator {
67 RealDTEntry outerScope;
68 RealDTEntry currentScope;
69 RealDTEntry currentEntry;
70 DTSavedScopePtr savedScope;
71 unsigned long currentIndex;
72} *RealDTEntryIterator;
73
74/* Property Iterator*/
75typedef struct OpaqueDTPropertyIterator {
76 RealDTEntry entry;
77 DeviceTreeNodeProperty *currentProperty;
78 unsigned long currentIndex;
79} *RealDTPropertyIterator;
80
81static int DTInitialized;
82static RealDTEntry DTRootNode;
83
84void DTInit(void *base);
85
86/*
87 * Support Routines
88 */
89static RealDTEntry
90skipProperties(RealDTEntry entry)
91{
92 DeviceTreeNodeProperty *prop;
93 int k;
94
95 if (entry == NULL || entry->nProperties == 0) {
96 return NULL;
97 } else {
98 prop = (DeviceTreeNodeProperty *) (entry + 1);
99 for (k = 0; k < entry->nProperties; k++) {
100 prop = next_prop(prop);
101 }
102 }
103 return ((RealDTEntry) prop);
104}
105
106static RealDTEntry
107skipTree(RealDTEntry root)
108{
109 RealDTEntry entry;
110 int k;
111
112 entry = skipProperties(root);
113 if (entry == NULL) {
114 return NULL;
115 }
116 for (k = 0; k < root->nChildren; k++) {
117 entry = skipTree(entry);
118 }
119 return entry;
120}
121
122static RealDTEntry
123GetFirstChild(RealDTEntry parent)
124{
125 return skipProperties(parent);
126}
127
128static RealDTEntry
129GetNextChild(RealDTEntry sibling)
130{
131 return skipTree(sibling);
132}
133
134static const char *
135GetNextComponent(const char *cp, char *bp)
136{
137 while (*cp != 0) {
138 if (*cp == kDTPathNameSeparator) {
139 cp++;
140 break;
141 }
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;
153 char * str;
154 int dummy;
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{
210 DeviceTreeNode *nodeP = (DeviceTreeNode *) startingP;
211 int k;
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) {
218 DeviceTreeNodeProperty *propP = (DeviceTreeNodeProperty *) startingP;
219
220 startingP += sizeof (*propP) + ((propP->length + 3) & -4);
221
222 if (strcmp (propP->name, propName) == 0) {
223 if (strcmp( (char *)(propP + 1), propValue) == 0)
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
409DTGetProperty(const DTEntry entry, const char *propertyName, void **propertyValue, int *propertySize)
410{
411 DeviceTreeNodeProperty *prop;
412 int k;
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) {
420 *propertyValue = (void *) (((int)prop)
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