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