|
|
1.1 root 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:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.