]> git.saurik.com Git - apple/xnu.git/blame - pexpert/gen/device_tree.c
xnu-792.10.96.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
A
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
37839358
A
6 * The contents of this file constitute Original Code as defined in and
7 * are subject to the Apple Public Source License Version 1.1 (the
8 * "License"). You may not use this file except in compliance with the
9 * License. Please obtain a copy of the License at
10 * http://www.apple.com/publicsource and read it before using this file.
1c79356b 11 *
37839358
A
12 * This Original Code and all software distributed under the License are
13 * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
1c79356b
A
14 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
15 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
37839358
A
16 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
17 * License for the specific language governing rights and limitations
18 * under the License.
1c79356b
A
19 *
20 * @APPLE_LICENSE_HEADER_END@
21 */
22/*
23 * @OSF_FREE_COPYRIGHT@
24 */
25
26#include <pexpert/protos.h>
27#include <pexpert/boot.h>
28#include <pexpert/device_tree.h>
91447636
A
29
30#include <mach/mach_types.h>
1c79356b 31#include <mach/machine/vm_types.h>
91447636
A
32#include <kern/kern_types.h>
33#include <kern/kalloc.h>
34
1c79356b
A
35#include <sys/types.h>
36#ifdef i386
37#include <i386/fakePPCStructs.h>
38#endif
39
40#ifndef NULL
41#define NULL ((void *) 0)
42#endif
43
44#define round_long(x) (((x) + 3) & -4)
45#define next_prop(x) ((DeviceTreeNodeProperty *) (((int)x) + sizeof(DeviceTreeNodeProperty) + round_long(x->length)))
46
47/* Entry*/
48typedef DeviceTreeNode *RealDTEntry;
49
50typedef struct DTSavedScope {
51 struct DTSavedScope * nextScope;
52 RealDTEntry scope;
53 RealDTEntry entry;
54 unsigned long index;
55} *DTSavedScopePtr;
56
57/* Entry Iterator*/
58typedef struct OpaqueDTEntryIterator {
59 RealDTEntry outerScope;
60 RealDTEntry currentScope;
61 RealDTEntry currentEntry;
62 DTSavedScopePtr savedScope;
63 unsigned long currentIndex;
64} *RealDTEntryIterator;
65
66/* Property Iterator*/
67typedef struct OpaqueDTPropertyIterator {
68 RealDTEntry entry;
69 DeviceTreeNodeProperty *currentProperty;
70 unsigned long currentIndex;
71} *RealDTPropertyIterator;
72
73static int DTInitialized;
74static RealDTEntry DTRootNode;
75
76void DTInit(void *base);
77
78/*
79 * Support Routines
80 */
81static RealDTEntry
82skipProperties(RealDTEntry entry)
83{
84 DeviceTreeNodeProperty *prop;
85 int k;
86
87 if (entry == NULL || entry->nProperties == 0) {
88 return NULL;
89 } else {
90 prop = (DeviceTreeNodeProperty *) (entry + 1);
91 for (k = 0; k < entry->nProperties; k++) {
92 prop = next_prop(prop);
93 }
94 }
95 return ((RealDTEntry) prop);
96}
97
98static RealDTEntry
99skipTree(RealDTEntry root)
100{
101 RealDTEntry entry;
102 int k;
103
104 entry = skipProperties(root);
105 if (entry == NULL) {
106 return NULL;
107 }
108 for (k = 0; k < root->nChildren; k++) {
109 entry = skipTree(entry);
110 }
111 return entry;
112}
113
114static RealDTEntry
115GetFirstChild(RealDTEntry parent)
116{
117 return skipProperties(parent);
118}
119
120static RealDTEntry
121GetNextChild(RealDTEntry sibling)
122{
123 return skipTree(sibling);
124}
125
126static const char *
127GetNextComponent(const char *cp, char *bp)
128{
129 while (*cp != 0) {
130 if (*cp == kDTPathNameSeparator) {
131 cp++;
132 break;
133 }
134 *bp++ = *cp++;
135 }
136 *bp = 0;
137 return cp;
138}
139
140static RealDTEntry
141FindChild(RealDTEntry cur, char *buf)
142{
143 RealDTEntry child;
144 unsigned long index;
145 char * str;
146 int dummy;
147
148 if (cur->nChildren == 0) {
149 return NULL;
150 }
151 index = 1;
152 child = GetFirstChild(cur);
153 while (1) {
154 if (DTGetProperty(child, "name", (void **)&str, &dummy) != kSuccess) {
155 break;
156 }
157 if (strcmp(str, buf) == 0) {
158 return child;
159 }
160 if (index >= cur->nChildren) {
161 break;
162 }
163 child = GetNextChild(child);
164 index++;
165 }
166 return NULL;
167}
168
169
170/*
171 * External Routines
172 */
173void
174DTInit(void *base)
175{
176 DTRootNode = (RealDTEntry) base;
177 DTInitialized = (DTRootNode != 0);
178}
179
180int
181DTEntryIsEqual(const DTEntry ref1, const DTEntry ref2)
182{
183 /* equality of pointers */
184 return (ref1 == ref2);
185}
186
187static char *startingP; // needed for find_entry
188int find_entry(const char *propName, const char *propValue, DTEntry *entryH);
189
190int DTFindEntry(const char *propName, const char *propValue, DTEntry *entryH)
191{
192 if (!DTInitialized) {
193 return kError;
194 }
195
196 startingP = (char *)DTRootNode;
197 return(find_entry(propName, propValue, entryH));
198}
199
200int find_entry(const char *propName, const char *propValue, DTEntry *entryH)
201{
202 DeviceTreeNode *nodeP = (DeviceTreeNode *) startingP;
203 int k;
204
205 if (nodeP->nProperties == 0) return(kError); // End of the list of nodes
206 startingP = (char *) (nodeP + 1);
207
208 // Search current entry
209 for (k = 0; k < nodeP->nProperties; ++k) {
210 DeviceTreeNodeProperty *propP = (DeviceTreeNodeProperty *) startingP;
211
212 startingP += sizeof (*propP) + ((propP->length + 3) & -4);
213
214 if (strcmp (propP->name, propName) == 0) {
215 if (strcmp( (char *)(propP + 1), propValue) == 0)
216 {
217 *entryH = (DTEntry)nodeP;
218 return(kSuccess);
219 }
220 }
221 }
222
223 // Search child nodes
224 for (k = 0; k < nodeP->nChildren; ++k)
225 {
226 if (find_entry(propName, propValue, entryH) == kSuccess)
227 return(kSuccess);
228 }
229 return(kError);
230}
231
232int
233DTLookupEntry(const DTEntry searchPoint, const char *pathName, DTEntry *foundEntry)
234{
235 DTEntryNameBuf buf;
236 RealDTEntry cur;
237 const char * cp;
238
239 if (!DTInitialized) {
240 return kError;
241 }
242 if (searchPoint == NULL) {
243 cur = DTRootNode;
244 } else {
245 cur = searchPoint;
246 }
247 cp = pathName;
248 if (*cp == kDTPathNameSeparator) {
249 cp++;
250 if (*cp == 0) {
251 *foundEntry = cur;
252 return kSuccess;
253 }
254 }
255 do {
256 cp = GetNextComponent(cp, buf);
257
258 /* Check for done */
259 if (*buf == 0) {
260 if (*cp == 0) {
261 *foundEntry = cur;
262 return kSuccess;
263 }
264 break;
265 }
266
267 cur = FindChild(cur, buf);
268
269 } while (cur != NULL);
270
271 return kError;
272}
273
274int
275DTCreateEntryIterator(const DTEntry startEntry, DTEntryIterator *iterator)
276{
277 RealDTEntryIterator iter;
278
279 if (!DTInitialized) {
280 return kError;
281 }
282
283 iter = (RealDTEntryIterator) kalloc(sizeof(struct OpaqueDTEntryIterator));
284 if (startEntry != NULL) {
285 iter->outerScope = (RealDTEntry) startEntry;
286 iter->currentScope = (RealDTEntry) startEntry;
287 } else {
288 iter->outerScope = DTRootNode;
289 iter->currentScope = DTRootNode;
290 }
291 iter->currentEntry = NULL;
292 iter->savedScope = NULL;
293 iter->currentIndex = 0;
294
295 *iterator = iter;
296 return kSuccess;
297}
298
299int
300DTDisposeEntryIterator(DTEntryIterator iterator)
301{
302 RealDTEntryIterator iter = iterator;
303 DTSavedScopePtr scope;
304
305 while ((scope = iter->savedScope) != NULL) {
306 iter->savedScope = scope->nextScope;
91447636 307 kfree(scope, sizeof(struct DTSavedScope));
1c79356b 308 }
91447636 309 kfree(iterator, sizeof(struct OpaqueDTEntryIterator));
1c79356b
A
310 return kSuccess;
311}
312
313int
314DTEnterEntry(DTEntryIterator iterator, DTEntry childEntry)
315{
316 RealDTEntryIterator iter = iterator;
317 DTSavedScopePtr newScope;
318
319 if (childEntry == NULL) {
320 return kError;
321 }
322 newScope = (DTSavedScopePtr) kalloc(sizeof(struct DTSavedScope));
323 newScope->nextScope = iter->savedScope;
324 newScope->scope = iter->currentScope;
325 newScope->entry = iter->currentEntry;
326 newScope->index = iter->currentIndex;
327
328 iter->currentScope = childEntry;
329 iter->currentEntry = NULL;
330 iter->savedScope = newScope;
331 iter->currentIndex = 0;
332
333 return kSuccess;
334}
335
336int
337DTExitEntry(DTEntryIterator iterator, DTEntry *currentPosition)
338{
339 RealDTEntryIterator iter = iterator;
340 DTSavedScopePtr newScope;
341
342 newScope = iter->savedScope;
343 if (newScope == NULL) {
344 return kError;
345 }
346 iter->savedScope = newScope->nextScope;
347 iter->currentScope = newScope->scope;
348 iter->currentEntry = newScope->entry;
349 iter->currentIndex = newScope->index;
350 *currentPosition = iter->currentEntry;
351
91447636 352 kfree(newScope, sizeof(struct DTSavedScope));
1c79356b
A
353
354 return kSuccess;
355}
356
357int
358DTIterateEntries(DTEntryIterator iterator, DTEntry *nextEntry)
359{
360 RealDTEntryIterator iter = iterator;
361
362 if (iter->currentIndex >= iter->currentScope->nChildren) {
363 *nextEntry = NULL;
364 return kIterationDone;
365 } else {
366 iter->currentIndex++;
367 if (iter->currentIndex == 1) {
368 iter->currentEntry = GetFirstChild(iter->currentScope);
369 } else {
370 iter->currentEntry = GetNextChild(iter->currentEntry);
371 }
372 *nextEntry = iter->currentEntry;
373 return kSuccess;
374 }
375}
376
377int
378DTRestartEntryIteration(DTEntryIterator iterator)
379{
380 RealDTEntryIterator iter = iterator;
381#if 0
382 // This commented out code allows a second argument (outer)
383 // which (if true) causes restarting at the outer scope
384 // rather than the current scope.
385 DTSavedScopePtr scope;
386
387 if (outer) {
388 while ((scope = iter->savedScope) != NULL) {
389 iter->savedScope = scope->nextScope;
390 kfree((vm_offset_t) scope, sizeof(struct DTSavedScope));
391 }
392 iter->currentScope = iter->outerScope;
393 }
394#endif
395 iter->currentEntry = NULL;
396 iter->currentIndex = 0;
397 return kSuccess;
398}
399
400int
401DTGetProperty(const DTEntry entry, const char *propertyName, void **propertyValue, int *propertySize)
402{
403 DeviceTreeNodeProperty *prop;
404 int k;
405
406 if (entry == NULL || entry->nProperties == 0) {
407 return kError;
408 } else {
409 prop = (DeviceTreeNodeProperty *) (entry + 1);
410 for (k = 0; k < entry->nProperties; k++) {
411 if (strcmp(prop->name, propertyName) == 0) {
412 *propertyValue = (void *) (((int)prop)
413 + sizeof(DeviceTreeNodeProperty));
414 *propertySize = prop->length;
415 return kSuccess;
416 }
417 prop = next_prop(prop);
418 }
419 }
420 return kError;
421}
422
423int
424DTCreatePropertyIterator(const DTEntry entry, DTPropertyIterator *iterator)
425{
426 RealDTPropertyIterator iter;
427
428 iter = (RealDTPropertyIterator) kalloc(sizeof(struct OpaqueDTPropertyIterator));
429 iter->entry = entry;
430 iter->currentProperty = NULL;
431 iter->currentIndex = 0;
432
433 *iterator = iter;
434 return kSuccess;
435}
436
437int
438DTDisposePropertyIterator(DTPropertyIterator iterator)
439{
91447636 440 kfree(iterator, sizeof(struct OpaqueDTPropertyIterator));
1c79356b
A
441 return kSuccess;
442}
443
444int
445DTIterateProperties(DTPropertyIterator iterator, char **foundProperty)
446{
447 RealDTPropertyIterator iter = iterator;
448
449 if (iter->currentIndex >= iter->entry->nProperties) {
450 *foundProperty = NULL;
451 return kIterationDone;
452 } else {
453 iter->currentIndex++;
454 if (iter->currentIndex == 1) {
455 iter->currentProperty = (DeviceTreeNodeProperty *) (iter->entry + 1);
456 } else {
457 iter->currentProperty = next_prop(iter->currentProperty);
458 }
459 *foundProperty = iter->currentProperty->name;
460 return kSuccess;
461 }
462}
463
464int
465DTRestartPropertyIteration(DTPropertyIterator iterator)
466{
467 RealDTPropertyIterator iter = iterator;
468
469 iter->currentProperty = NULL;
470 iter->currentIndex = 0;
471 return kSuccess;
472}
473