|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 1998-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: * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. ! 24: * ! 25: * HISTORY ! 26: * 3 June 99 wgulland created. ! 27: * ! 28: * Useful stuff called from several different FireWire objects. ! 29: */ ! 30: #include <IOKit/assert.h> ! 31: #include <IOKit/IOLib.h> ! 32: #include <IOKit/firewire/IOFWRegs.h> ! 33: #include <IOKit/firewire/IOFireWirePriv.h> ! 34: ! 35: //////////////////////////////////////////////////////////////////////////////// ! 36: // ! 37: // FWComputeCRC16 ! 38: // ! 39: // This proc computes a CRC 16 check. ! 40: // ! 41: ! 42: UInt16 FWComputeCRC16(UInt32 *pQuads, UInt32 numQuads) ! 43: { ! 44: SInt32 shift; ! 45: UInt32 sum; ! 46: UInt32 crc16; ! 47: UInt32 quadNum; ! 48: UInt32 quad; ! 49: ! 50: // Compute CRC 16 over all quads. ! 51: crc16 = 0; ! 52: for (quadNum = 0; quadNum < numQuads; quadNum++) { ! 53: quad = *pQuads++; ! 54: for (shift = 28; shift >= 0; shift -= 4) { ! 55: sum = ((crc16 >> 12) ^ (quad >> shift)) & 0x0F; ! 56: crc16 = (crc16 << 4) ^ (sum << 12) ^ (sum << 5) ^ (sum); ! 57: } ! 58: } ! 59: ! 60: return (crc16 & 0xFFFF); ! 61: } ! 62: ! 63: ! 64: //////////////////////////////////////////////////////////////////////////////// ! 65: // ! 66: // FWCSRROMInvalidateEntryIDType ! 67: // ! 68: // Invalidate a CSR ROM entry ID. This will deallocate any memory allocated ! 69: // for the ID excluding the ID data record itself. ! 70: // ! 71: // Probably only thing needed is to release reference to the ROM. ! 72: // ! 73: ! 74: void FWCSRROMInvalidateEntryIDType(CSRROMEntryID csrROMEntryID) ! 75: { ! 76: CSRROMEntryIDDataPtr pCSRROMEntryIDData; ! 77: ! 78: if (csrROMEntryID != kInvalidCSRROMEntryID) ! 79: { ! 80: pCSRROMEntryIDData = (CSRROMEntryIDDataPtr) csrROMEntryID; ! 81: ! 82: switch (pCSRROMEntryIDData->entryType) ! 83: { ! 84: case kLocalCSRROMEntryIDType : ! 85: break; ! 86: ! 87: case kRemoteCSRROMEntryIDType : ! 88: ! 89: break; ! 90: ! 91: default : ! 92: break; ! 93: } ! 94: ! 95: // Entry is now invalid. ! 96: pCSRROMEntryIDData->entryType = kInvalidCSRROMEntryIDType; ! 97: } ! 98: } ! 99: ! 100: //////////////////////////////////////////////////////////////////////////////// ! 101: // ! 102: // FWCSRROMCreateEntryID ! 103: // ! 104: // Allocate memory for a CSR ROM entry ID. ! 105: //zzz could be a little more efficient computing allocation size. ! 106: // ! 107: ! 108: CSRROMEntryID FWCSRROMCreateEntryID(void) ! 109: { ! 110: CSRROMEntryID csrROMEntryID = kInvalidCSRROMEntryID; ! 111: CSRROMEntryIDDataPtr pCSRROMEntryIDData; ! 112: UInt32 maxSize; ! 113: ! 114: // Determine maximum size of all entry types. ! 115: // Need enough for local ID type. ! 116: maxSize = sizeof (CSRROMLocalIDData); ! 117: if (sizeof (CSRROMRemoteIDData) > maxSize) ! 118: maxSize = sizeof (CSRROMRemoteIDData); ! 119: ! 120: // Allocate the data. ! 121: pCSRROMEntryIDData = (CSRROMEntryIDDataPtr) IOMalloc (maxSize); ! 122: if (pCSRROMEntryIDData != NULL) { ! 123: pCSRROMEntryIDData->entryType = kInvalidCSRROMEntryIDType; ! 124: csrROMEntryID = (CSRROMEntryID) pCSRROMEntryIDData; ! 125: } ! 126: return (csrROMEntryID); ! 127: } ! 128: ! 129: //////////////////////////////////////////////////////////////////////////////// ! 130: // ! 131: // FWCSRROMDisposeEntryID ! 132: // ! 133: // Deallocate memory for a CSR ROM entry ID. ! 134: // ! 135: ! 136: void FWCSRROMDisposeEntryID(CSRROMEntryID csrROMEntryID) ! 137: { ! 138: CSRROMEntryIDDataPtr pCSRROMEntryIDData; ! 139: ! 140: if (csrROMEntryID != kInvalidCSRROMEntryID) { ! 141: UInt32 maxSize; ! 142: ! 143: // Determine maximum size of all entry types. ! 144: // Need enough for local ID type. ! 145: maxSize = sizeof (CSRROMLocalIDData); ! 146: if (sizeof (CSRROMRemoteIDData) > maxSize) ! 147: maxSize = sizeof (CSRROMRemoteIDData); ! 148: pCSRROMEntryIDData = (CSRROMEntryIDDataPtr) csrROMEntryID; ! 149: ! 150: // Invalidate entry. ! 151: FWCSRROMInvalidateEntryIDType (csrROMEntryID); ! 152: ! 153: // Deallocate entry. ! 154: IOFree(pCSRROMEntryIDData, maxSize); ! 155: } ! 156: } ! 157: ! 158: //////////////////////////////////////////////////////////////////////////////// ! 159: // ! 160: // FWCSRROMCreateRemoteEntryID ! 161: // ! 162: // Create a remote CSR ROM entry ID. ! 163: // ! 164: ! 165: static IOReturn FWCSRROMCreateRemoteEntryID( ! 166: CSRROMEntryID *pCSRROMEntryID, ! 167: const UInt32 * data, ! 168: UInt32 *physicalPath, ! 169: UInt32 pathSize) ! 170: { ! 171: CSRROMEntryID csrROMEntryID = *pCSRROMEntryID; ! 172: CSRROMEntryIDDataPtr pCSRROMEntryIDData; ! 173: CSRROMRemoteIDDataPtr pCSRROMRemoteIDData; ! 174: ! 175: // Allocate an entry ID if given entry ID is invalid. ! 176: if (csrROMEntryID == kInvalidCSRROMEntryID) { ! 177: csrROMEntryID = FWCSRROMCreateEntryID (); ! 178: // If entry ID is still invalid, there must have been a memory error. ! 179: if (csrROMEntryID == kInvalidCSRROMEntryID) ! 180: return kIOReturnNoMemory; ! 181: } ! 182: ! 183: ! 184: // Get data from ID. ! 185: pCSRROMEntryIDData = (CSRROMEntryIDDataPtr) csrROMEntryID; ! 186: pCSRROMRemoteIDData = (CSRROMRemoteIDDataPtr) pCSRROMEntryIDData; ! 187: ! 188: // If entry is not a remote type, invalidate its type. ! 189: if ((pCSRROMEntryIDData->entryType != kRemoteCSRROMEntryIDType) && ! 190: (pCSRROMEntryIDData->entryType != kInvalidCSRROMEntryIDType)) { ! 191: FWCSRROMInvalidateEntryIDType (csrROMEntryID); ! 192: } ! 193: ! 194: // Make entry a remote type. ! 195: pCSRROMEntryIDData->entryType = kRemoteCSRROMEntryIDType; ! 196: ! 197: ! 198: // Copy directory paths and data pointer ! 199: pCSRROMRemoteIDData->data = data; ! 200: bcopy (physicalPath, pCSRROMRemoteIDData->physicalPath, pathSize * sizeof (UInt32)); ! 201: pCSRROMRemoteIDData->pathSize = pathSize; ! 202: ! 203: // Return entry ID. ! 204: *pCSRROMEntryID = csrROMEntryID; ! 205: ! 206: return (kIOReturnSuccess); ! 207: } ! 208: ! 209: //////////////////////////////////////////////////////////////////////////////// ! 210: // ! 211: // FWCSRROMDisposeIterator ! 212: // ! 213: // Dispose of storage allocated for iterator. ! 214: // ! 215: ! 216: void FWCSRROMDisposeIterator(CSRROMEntryIterator csrROMIterator) ! 217: { ! 218: CSRROMEntryIteratorRecPtr pIteratorRec; ! 219: ! 220: // Deallocate if iterator is valid. ! 221: if (csrROMIterator != kInvalidCSRROMIterator) { ! 222: // Get iterator record. ! 223: pIteratorRec = (CSRROMEntryIteratorRecPtr) csrROMIterator; ! 224: ! 225: // Deallocate iterator record. ! 226: IOFree (pIteratorRec, sizeof (CSRROMEntryIteratorRec)); ! 227: } ! 228: } ! 229: ! 230: ! 231: //////////////////////////////////////////////////////////////////////////////// ! 232: // ! 233: // FWCSRROMSetIterator ! 234: // ! 235: // Set current path and relationship of iterator. ! 236: //zzz should support all entry ID types. ! 237: //zzz should support kIterateRoot ! 238: // ! 239: ! 240: IOReturn FWCSRROMSetIterator( ! 241: CSRROMEntryIterator csrROMIterator, ! 242: CSRROMEntryID csrROMEntryID, ! 243: CSRROMIterationOp relationship) ! 244: { ! 245: CSRROMEntryIteratorRecPtr pIteratorRec; ! 246: CSRROMEntryIDDataPtr pCSRROMEntryIDData; ! 247: CSRROMRemoteIDDataPtr pCSRROMRemoteIDData; ! 248: ! 249: // Get CSR ROM search iterator record. ! 250: pIteratorRec = (CSRROMEntryIteratorRecPtr) csrROMIterator; ! 251: ! 252: // Set to given entry. ! 253: if (csrROMEntryID != kInvalidCSRROMEntryID) { ! 254: // Get entry data from ID. ! 255: pCSRROMEntryIDData = (CSRROMEntryIDDataPtr) csrROMEntryID; ! 256: ! 257: if (pCSRROMEntryIDData->entryType == kRemoteCSRROMEntryIDType) { ! 258: // Recast entry data. ! 259: pCSRROMRemoteIDData = (CSRROMRemoteIDDataPtr) pCSRROMEntryIDData; ! 260: ! 261: // Copy physical path. ! 262: bcopy (pCSRROMRemoteIDData->physicalPath, ! 263: pIteratorRec->physicalPath, ! 264: pCSRROMRemoteIDData->pathSize * sizeof (UInt32)); ! 265: ! 266: // Copy data pointer and path depth ! 267: pIteratorRec->data = pCSRROMRemoteIDData->data; ! 268: pIteratorRec->pathSize = pCSRROMRemoteIDData->pathSize; ! 269: } ! 270: } ! 271: ! 272: // Set to given relationship. ! 273: if (relationship != kIterateContinue) ! 274: pIteratorRec->relationship = relationship; ! 275: ! 276: return (kIOReturnSuccess); ! 277: } ! 278: ! 279: ! 280: //////////////////////////////////////////////////////////////////////////////// ! 281: // ! 282: // FWCSRROMEntrySearch ! 283: // ! 284: // Search for the next ROM entry that matches the search criteria. ! 285: //zzz need to check the search type in the criteria record and the relationship ! 286: //zzz could be more efficient. should make and use more defs. ! 287: //zzz need to return information on what exactly was found ! 288: //zzz fill in entry value better ! 289: //zzz should break this up ! 290: //zzz should support all entry ID types. ! 291: // ! 292: ! 293: // zzz ! 294: // Made a quick fix here so that if we are searching for Unit Directories (key d1) ! 295: // we will ignore any Instance Directories (key d8) because they contain redundant ! 296: // pointers to Unit Directories. This is almost surely not the best soltution. ! 297: ! 298: IOReturn FWCSRROMEntrySearch( ! 299: CSRROMEntryIterator csrROMIterator, ! 300: CSRROMIterationOp relationship, ! 301: CSRROMEntryID *pCSRROMEntryID, ! 302: int *pDone, ! 303: CSRROMSearchCriteriaPtr pSearchCriteria, ! 304: UInt8 * pEntryValue, ! 305: UInt32 *pEntrySize) ! 306: { ! 307: CSRROMEntryIteratorRecPtr pIteratorRec; ! 308: UInt32 currentAddress, entryValueAddress; ! 309: UInt32 pathSize; ! 310: UInt32 directoryEnd; ! 311: UInt32 address; ! 312: UInt32 directoryHeader, directoryEntry; ! 313: UInt32 leafEntry; ! 314: UInt32 keyType, keyValue; ! 315: UInt32 keyTypeBit, keyValueBitHi, keyValueBitLo; ! 316: UInt32 returnedEntrySize; ! 317: bool found, done; ! 318: IOReturn status = kIOReturnSuccess; ! 319: ! 320: //zzz Part of the Instance Directory hack ! 321: bool unitDirSearch; ! 322: bool ignoreInstanceDir; ! 323: ! 324: // If we are searching for Unit Directories (in FWExpertLoader.c/FWUpdateDevice) ! 325: // then just don't go down any Instance Directories (key d8), because we'll find a ! 326: // redundant pointer to the Unit Directory in there. ! 327: ! 328: unitDirSearch = (pSearchCriteria->csrROMSearchType == kCSRROMSearchForKey) && ! 329: (pSearchCriteria->keyType == kCSRDirectoryKeyTypeBit) && ! 330: (pSearchCriteria->keyHi == kCSRUnitDirectoryKeyHiBit) && ! 331: (pSearchCriteria->keyLo == kCSRUnitDirectoryKeyLoBit); ! 332: ! 333: // Get CSR ROM search iterator record. ! 334: pIteratorRec = (CSRROMEntryIteratorRecPtr) csrROMIterator; ! 335: ! 336: // Read the current directory length. First, get base address of current ! 337: // directory by going up one node in the directory path. Special case ! 338: // when we're in the root directory. Second, read the directory length ! 339: // at the base address. ! 340: pathSize = pIteratorRec->pathSize; ! 341: if (pathSize > 2) { ! 342: address = pIteratorRec->physicalPath[pathSize - 2]; ! 343: directoryEntry = pIteratorRec->data[address]; ! 344: address += (directoryEntry & 0x00FFFFFF); ! 345: } ! 346: else { ! 347: address = pIteratorRec->physicalPath[0]; ! 348: } ! 349: directoryHeader = pIteratorRec->data[address]; ! 350: directoryEnd = address + ((directoryHeader >> 16) + 1); ! 351: ! 352: // Loop until we've found what we're looking for, or we've searched ! 353: // everything. ! 354: found = false; ! 355: done = false; ! 356: while ((!found) && (!done)) { ! 357: // Read our current location. ! 358: pathSize = pIteratorRec->pathSize; ! 359: currentAddress = pIteratorRec->physicalPath[pathSize - 1]; ! 360: ! 361: // Check if search was reset. ! 362: if (pIteratorRec->reset) { ! 363: pIteratorRec->reset = false; ! 364: } ! 365: else { ! 366: // Read directory entry at current address. ! 367: //zzz should have some address defs. ! 368: directoryEntry = pIteratorRec->data[currentAddress]; ! 369: // If the current directory entry is a directory, add it to ! 370: // the path. Otherwise, go to next directory entry. ! 371: keyType = (directoryEntry & 0xC0000000) >> 30; ! 372: //zzz ! 373: //The Instance Directory hack ! 374: ignoreInstanceDir = (directoryEntry >> 24) == 0xd8; ! 375: //zzz ! 376: if ((keyType == kCSRDirectoryKeyType) && !ignoreInstanceDir) { ! 377: // Go to and read directory header. ! 378: //zzz should do this the right way if offset > 1024. ! 379: currentAddress += (directoryEntry & 0x00FFFFFF); ! 380: directoryHeader = pIteratorRec->data[currentAddress]; ! 381: // Add directory to path and set location to first ! 382: // entry in directory. ! 383: pathSize++; ! 384: ! 385: directoryEnd = ! 386: currentAddress + ((directoryHeader >> 16) + 1); ! 387: ! 388: currentAddress += 1; ! 389: } ! 390: else { ! 391: currentAddress += 1; ! 392: } ! 393: } ! 394: ! 395: // If we're past the end of the current directory, take it out ! 396: // of path. ! 397: while ((currentAddress >= directoryEnd) && (!done)) { ! 398: pathSize--; ! 399: currentAddress = pIteratorRec->physicalPath[pathSize - 1] + 1; ! 400: ! 401: // Read the current directory length. ! 402: if (pathSize > 2) { ! 403: address = pIteratorRec->physicalPath[pathSize - 2]; ! 404: directoryEntry = pIteratorRec->data[address]; ! 405: address += (directoryEntry & 0x00FFFFFF); ! 406: } ! 407: else { ! 408: address = pIteratorRec->physicalPath[0]; ! 409: } ! 410: directoryHeader = pIteratorRec->data[address]; ! 411: directoryEnd = address + ((directoryHeader >> 16) + 1); ! 412: if (pathSize < 2) { ! 413: done = true; ! 414: } ! 415: } ! 416: // If we're not done searching, check the current directory entry ! 417: // against the search criteria. ! 418: if (!done) { ! 419: directoryEntry = pIteratorRec->data[currentAddress]; ! 420: // Read key type and value. ! 421: keyType = (directoryEntry & 0xC0000000) >> 30; ! 422: keyValue = (directoryEntry & 0x3F000000) >> 24; ! 423: ! 424: // Convert to bit flag. ! 425: keyTypeBit = 1 << keyType; ! 426: if (keyValue > 31) { ! 427: keyValueBitHi = 1 << (keyValue - 32); ! 428: keyValueBitLo = 0; ! 429: } ! 430: else { ! 431: keyValueBitHi = 0; ! 432: keyValueBitLo = 1 << keyValue; ! 433: } ! 434: ! 435: // Compare bit flags against search criteria. ! 436: ! 437: if ((keyTypeBit & pSearchCriteria->keyType) && ! 438: ((keyValueBitHi & pSearchCriteria->keyHi) || ! 439: (keyValueBitLo & pSearchCriteria->keyLo))) { ! 440: switch (keyType) { ! 441: case kCSRImmediateKeyType : ! 442: if ((pEntrySize != NULL) && (pEntryValue != NULL)) { ! 443: // Determine size of data. ! 444: if (*pEntrySize < 4) ! 445: returnedEntrySize = *pEntrySize; ! 446: else ! 447: returnedEntrySize = 4; ! 448: ! 449: // Copy data.//zzz not right. ! 450: //zzz need def here. ! 451: *((UInt32 *) pEntryValue) = ! 452: directoryEntry & 0x00FFFFFF; ! 453: ! 454: // Return size. ! 455: *pEntrySize = returnedEntrySize; ! 456: } ! 457: break; ! 458: ! 459: case kCSROffsetKeyType : ! 460: if ((pEntrySize != NULL) && (pEntryValue != NULL)) { ! 461: // Determine size of data. ! 462: if (*pEntrySize < 4) ! 463: returnedEntrySize = *pEntrySize; ! 464: else ! 465: returnedEntrySize = 4; ! 466: ! 467: // Copy data.//zzz not right. ! 468: //zzz need def here. ! 469: *((UInt32 *) pEntryValue) = ! 470: directoryEntry & kCSREntryValue; ! 471: ! 472: // Return size. ! 473: *pEntrySize = returnedEntrySize; ! 474: } ! 475: break; ! 476: ! 477: case kCSRLeafKeyType : ! 478: if ((pEntrySize != NULL) && (pEntryValue != NULL)) { ! 479: // Get address of leaf. ! 480: //zzz need to do indirect stuff right. ! 481: entryValueAddress = currentAddress + (directoryEntry & kCSREntryValue); ! 482: ! 483: // Get size of leaf. ! 484: leafEntry = pIteratorRec->data[entryValueAddress]; ! 485: returnedEntrySize = (leafEntry >> 16) * sizeof (UInt32); ! 486: entryValueAddress += 1; ! 487: // Determine size of data. ! 488: if (returnedEntrySize > *pEntrySize) ! 489: returnedEntrySize = *pEntrySize; ! 490: // Copy data. ! 491: bcopy(&pIteratorRec->data[entryValueAddress], pEntryValue, returnedEntrySize); ! 492: // Return size. ! 493: *pEntrySize = returnedEntrySize; ! 494: } ! 495: ! 496: break; ! 497: ! 498: case kCSRDirectoryKeyType ://zzz ! 499: break; ! 500: ! 501: default : //zzz ! 502: break; ! 503: } ! 504: ! 505: found = true; ! 506: } ! 507: } ! 508: ! 509: // Update current address. ! 510: pIteratorRec->physicalPath[pathSize - 1] = currentAddress; ! 511: pIteratorRec->pathSize = pathSize; ! 512: } ! 513: ! 514: // Return CSR ROM entry ID. ! 515: if (pCSRROMEntryID != NULL) { ! 516: if (!done) { ! 517: status = FWCSRROMCreateRemoteEntryID ! 518: (pCSRROMEntryID, ! 519: pIteratorRec->data, ! 520: pIteratorRec->physicalPath, ! 521: pIteratorRec->pathSize); ! 522: } ! 523: else { ! 524: if (*pCSRROMEntryID != kInvalidCSRROMEntryID) ! 525: FWCSRROMDisposeEntryID (*pCSRROMEntryID); ! 526: *pCSRROMEntryID = kInvalidCSRROMEntryID; ! 527: } ! 528: } ! 529: ! 530: *pDone = done; ! 531: return (status); ! 532: } ! 533: ! 534:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.