|
|
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.