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