|
|
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) 1997 Apple Computer, Inc. ! 24: * ! 25: * ! 26: * HISTORY ! 27: * ! 28: * From pieces of ProtoCFM, Alan Lillich. ! 29: * ! 30: * sdouglas 22 Oct 97 - first checked in. ! 31: * sdouglas 21 July 98 - start IOKit ! 32: */ ! 33: ! 34: ! 35: #include <IOKit/IOLib.h> ! 36: ! 37: #include "IOPEFLibraries.h" ! 38: #include "IOPEFLoader.h" ! 39: #include "IOPEFInternals.h" ! 40: ! 41: ! 42: ! 43: #define LOG if(1) kprintf ! 44: #define INFO if(0) kprintf ! 45: ! 46: struct SectionVars { ! 47: LogicalAddress address; ! 48: ByteCount unpackedLength; ! 49: Boolean isPacked; ! 50: }; ! 51: typedef struct SectionVars SectionVars; ! 52: ! 53: struct InstanceVars { ! 54: BytePtr pef; // container in memory ! 55: CFContHandlerRef cRef; ! 56: CFContHandlerProcs * cProcs; ! 57: ItemCount numSections; ! 58: SectionVars * sections; ! 59: }; ! 60: typedef struct InstanceVars InstanceVars; ! 61: ! 62: ! 63: static OSStatus LocationToAddress( InstanceVars * inst, ! 64: CFContLogicalLocation * location, LogicalAddress * address ); ! 65: static OSStatus SatisfyImports( InstanceVars * inst ); ! 66: static OSStatus Instantiate( InstanceVars * inst ); ! 67: ! 68: ! 69: #define PCFM_BlockCopy(src,dst,len) memcpy(dst,src,len) ! 70: #define PCFM_BlockClear(dst,len) memset(dst,0,len) ! 71: #define PCFM_MakeExecutable(addr,len) flush_dcache((vm_offset_t)addr, len, 0); \ ! 72: invalidate_icache((vm_offset_t)addr, len, 0) ! 73: ! 74: extern OSStatus CallTVector( ! 75: void * p1, void * p2, void * p3, void * p4, void * p5, void * p6, ! 76: LogicalAddress entry ); ! 77: ! 78: // � ! 79: // =========================================================================================== ! 80: // CFContHashName () ! 81: // ================= ! 82: ! 83: ! 84: CFContStringHash CFContHashName ( BytePtr nameText, ! 85: ByteCount nameLength ) ! 86: { ! 87: BytePtr currChar = nameText; ! 88: SInt32 hashValue = 0; // ! Signed to match old published PEF algorithm. ! 89: ByteCount length = 0; ! 90: ByteCount limit; ! 91: CFContStringHash result; ! 92: ! 93: #define PseudoRotate(x) ( ( (x) << 1 ) - ( (x) >> (16) ) ) ! 94: ! 95: ! 96: for ( limit = nameLength; limit > 0; limit -= 1 ) { ! 97: if ( *currChar == NULL ) break; ! 98: hashValue = (PseudoRotate ( hashValue )) ^ *currChar; ! 99: currChar += 1; ! 100: length += 1; ! 101: } ! 102: ! 103: result = (length << 16) | ((UInt16) ((hashValue ^ (hashValue >> 16)) & 0xFFFF)); ! 104: ! 105: return result; ! 106: ! 107: ! 108: } // CFContHashName () ! 109: ! 110: ! 111: // � ! 112: // =========================================================================================== ! 113: // PCFM_CompareBytes () ! 114: // ==================== ! 115: ! 116: ! 117: Boolean PCFM_CompareBytes ( const Byte * left, ! 118: const Byte * right, ! 119: ByteCount count ) ! 120: { ! 121: // !!! Blechola! Switch to a standard routine ASAP! ! 122: ! 123: UInt32 * wLeft; ! 124: UInt32 * wRight; ! 125: UInt8 * bLeft; ! 126: UInt8 * bRight; ! 127: ! 128: ByteCount leftMiss = (UInt32)left & 0x00000003; ! 129: ByteCount rightMiss = (UInt32)right & 0x00000003; ! 130: ! 131: ! 132: bLeft = (UInt8 *) left; ! 133: bRight = (UInt8 *) right; ! 134: ! 135: if ( (leftMiss != 0) && (rightMiss != 0) ) { ! 136: ByteCount align = leftMiss; ! 137: if ( align > count ) align = count; ! 138: while ( align > 0 ) { ! 139: if ( *bLeft++ != *bRight++ ) goto NoMatch; ! 140: align -= 1; ! 141: count -= 1; ! 142: } ! 143: } ! 144: ! 145: wLeft = (UInt32 *) bLeft; ! 146: wRight = (UInt32 *) bRight; ! 147: while ( count >= 4 ) { ! 148: if ( *wLeft++ != *wRight++ ) goto NoMatch; ! 149: count -= 4; ! 150: } ! 151: ! 152: bLeft = (UInt8 *) wLeft; ! 153: bRight = (UInt8 *) wRight; ! 154: while ( count > 0 ) { ! 155: if ( *bLeft++ != *bRight++ ) goto NoMatch; ! 156: count -= 1; ! 157: } ! 158: ! 159: return true; ! 160: ! 161: ! 162: NoMatch: ! 163: return false; ! 164: ! 165: ! 166: } // PCFM_CompareBytes () ! 167: ! 168: // =========================================================================================== ! 169: ! 170: LogicalAddress PCodeAllocateMem( ByteCount size ); ! 171: void PCodeReleaseMem( LogicalAddress address ); ! 172: extern void *kern_os_malloc(size_t size); ! 173: extern void kern_os_free(void * addr); ! 174: ! 175: LogicalAddress ! 176: PCodeAllocateMem( ByteCount size ) ! 177: { ! 178: return( (LogicalAddress) kern_os_malloc( (size_t) size )); ! 179: } ! 180: ! 181: void ! 182: PCodeReleaseMem( LogicalAddress address ) ! 183: { ! 184: kern_os_free( (void *) address ); ! 185: } ! 186: ! 187: // =========================================================================================== ! 188: ! 189: OSStatus ! 190: PCodeOpen( LogicalAddress container, ByteCount containerSize, PCodeInstance * instance ) ! 191: { ! 192: OSStatus err; ! 193: InstanceVars * inst; ! 194: ! 195: inst = PCodeAllocateMem( sizeof( InstanceVars)); ! 196: *instance = inst; ! 197: ! 198: inst->pef = (BytePtr) container; ! 199: // procID, name, options ! 200: err = PEF_OpenContainer( container, container, containerSize, 0, 0, 0, ! 201: PCodeAllocateMem, PCodeReleaseMem, ! 202: &inst->cRef, &inst->cProcs ); ! 203: if( err) LOG( "PEF_OpenContainer = %d\n", err ); ! 204: ! 205: return( err); ! 206: } ! 207: ! 208: ! 209: OSStatus ! 210: PCodeInstantiate( PCodeInstance instance ) ! 211: { ! 212: OSStatus err; ! 213: InstanceVars * inst = instance; ! 214: CFContLogicalLocation initLocation; ! 215: LogicalAddress tv; ! 216: CFragInitBlock initInfo; ! 217: ! 218: do { ! 219: err = Instantiate( inst ); ! 220: if( err) ! 221: continue; ! 222: ! 223: // call INIT ! 224: err = PEF_GetAnonymousSymbolLocations( inst->cRef, NULL, &initLocation, NULL ); ! 225: if( err) ! 226: continue; ! 227: err = LocationToAddress( inst, &initLocation, &tv ); ! 228: if( err || (tv == NULL) ) ! 229: continue; ! 230: bzero( &initInfo, sizeof( initInfo)); ! 231: err = CallTVector( &initInfo, 0, 0, 0, 0, 0, tv ); ! 232: ! 233: } while( false); ! 234: ! 235: return( err); ! 236: } ! 237: ! 238: ! 239: OSStatus ! 240: PCodeClose( PCodeInstance instance ) ! 241: { ! 242: OSStatus err; ! 243: InstanceVars * inst = instance; ! 244: ! 245: err = PEF_CloseContainer( inst->cRef, 0 ); ! 246: if( err) LOG( "PEF_CloseContainer = %d\n", err ); ! 247: ! 248: return( err); ! 249: } ! 250: ! 251: OSStatus ! 252: PCodeFindExport( PCodeInstance instance, const char * symbolName, LogicalAddress * address, CFragSymbolClass * symbolClass ) ! 253: { ! 254: CFContExportedSymbolInfo symInfo; ! 255: CFContHashedName hashName; ! 256: OSStatus err; ! 257: InstanceVars * inst = instance; ! 258: ! 259: hashName.nameHash = CFContHashName( (UInt8 *) symbolName, strlen( symbolName) ); ! 260: hashName.nameText = (UInt8 *) symbolName; ! 261: ! 262: err = PEF_FindExportedSymbolInfo( inst->cRef, &hashName, ! 263: kCFContExportedSymbolInfoVersion, (void *) 0, &symInfo ); ! 264: if( err) { ! 265: LOG( "PEF_FindExportedSymbolInfo = %d\n", err ); ! 266: return( err); ! 267: } ! 268: ! 269: if( address); ! 270: err = LocationToAddress( inst, &symInfo.location, address ); ! 271: if( symbolClass) ! 272: *symbolClass = symInfo.symbolClass; ! 273: ! 274: return( err); ! 275: } ! 276: ! 277: OSStatus ! 278: PCodeFindMain( PCodeInstance instance, LogicalAddress * mainAddress ) ! 279: { ! 280: InstanceVars * inst = instance; ! 281: CFContLogicalLocation mainLocation; ! 282: OSStatus err; ! 283: ! 284: err = PEF_GetAnonymousSymbolLocations( inst->cRef, &mainLocation, NULL, NULL ); ! 285: ! 286: if( err == noErr) ! 287: err = LocationToAddress( inst, &mainLocation, mainAddress ); ! 288: ! 289: return( err); ! 290: } ! 291: ! 292: ! 293: ! 294: // =========================================================================================== ! 295: ! 296: static OSStatus ! 297: LocationToAddress( InstanceVars * inst, CFContLogicalLocation * location, ! 298: LogicalAddress * address ) ! 299: { ! 300: BytePtr sectionBase; ! 301: OSStatus err = noErr; ! 302: ! 303: if ( location->section >= 0 ) { ! 304: sectionBase = (BytePtr) (inst->sections + location->section)->address; ! 305: *address = (LogicalAddress) (sectionBase + location->offset); ! 306: ! 307: } else if ( location->section == kCFContAbsoluteSectionIndex ) { ! 308: *address = (LogicalAddress) location->offset; ! 309: ! 310: } else if ( location->section == kCFContNoSectionIndex ) { ! 311: *address = (LogicalAddress) kUnresolvedCFragSymbolAddress; ! 312: ! 313: } else ! 314: err = cfragFragmentFormatErr; ! 315: ! 316: return( err); ! 317: } ! 318: ! 319: ! 320: static OSStatus ! 321: Instantiate( InstanceVars * inst ) ! 322: { ! 323: CFContHandlerRef cRef; ! 324: ItemCount numSects, sectionIndex; ! 325: CFContSectionInfo sectionInfo; ! 326: CFContSectionInfo * section; ! 327: OSStatus err; ! 328: ! 329: cRef = inst->cRef; ! 330: ! 331: err = PEF_GetSectionCount( cRef, &numSects ); ! 332: if( err) LOG( "PEF_GetSectionCount = %d\n", err ); ! 333: INFO( "Num sects = %d\n", numSects ); ! 334: ! 335: inst->numSections = numSects; ! 336: inst->sections = PCodeAllocateMem( numSects * sizeof( SectionVars )); ! 337: ! 338: for( sectionIndex = 0; sectionIndex < numSects; sectionIndex++ ) ! 339: { ! 340: Boolean isPacked, isMappable; ! 341: Boolean needAlloc, needCopy, needClear; ! 342: LogicalAddress sectionAddress; ! 343: SectionVars * sectionVars; ! 344: ! 345: sectionVars = inst->sections + sectionIndex; ! 346: section = §ionInfo; ! 347: ! 348: err = PEF_GetSectionInfo( cRef, sectionIndex, kCFContSectionInfoVersion, section ); ! 349: if( err) LOG( "PEF_GetSectionInfo = %d\n", err ); ! 350: ! 351: #if 0 ! 352: if ( sectionInfo.sharing == kCFContShareSectionInClosure ) goto SectionSharingError; ! 353: if ( (! (sectionInfo.access & kCFContMemWriteMask)) && ! 354: (sectionInfo.options & kRelocatedCFContSectionMask) ) goto SectionOptionsError; ! 355: #endif ! 356: ! 357: isPacked = ((section->options & kPackedCFContSectionMask) != 0); ! 358: isMappable = (! isPacked) && ! 359: (! (section->options & kRelocatedCFContSectionMask)) && ! 360: (! (section->access & kCFContMemWriteMask)); ! 361: ! 362: if ( ! isMappable ) { ! 363: // ---------------------------------------------------------------------------------- ! 364: // Mappable really means "fully expanded in container", so sections that are not mappable ! 365: // need to be allocated. The loader will do the initialization copying. This is the ! 366: // standard case for packed PEF data sections. ! 367: needAlloc = true; ! 368: needCopy = (! isPacked); ! 369: needClear = (section->totalLength != section->unpackedLength); ! 370: ! 371: } else if ( ! (section->access & kCFContMemWriteMask) ) { ! 372: // ----------------------------------------------------------------------------------- ! 373: // A "mappable" read only section. Make sure it is fully present, i.e. no zero filled ! 374: // extension. This is the standard case for code and literal sections. ! 375: if ( section->totalLength != section->unpackedLength ) { ! 376: err = cfragFragmentUsageErr; // !!! Needs error label & message. ! 377: // goto ERROR; ! 378: } ! 379: needAlloc = false; ! 380: needCopy = false; ! 381: needClear = false; ! 382: ! 383: } else { ! 384: // ----------------------------------------------------------------------------------- ! 385: // A "mappable", writeable, don't use in place section. This is the standard case for ! 386: // unpacked data sections. ! 387: needAlloc = true; ! 388: needCopy = true; ! 389: needClear = (section->totalLength != section->unpackedLength); ! 390: } ! 391: ! 392: if ( needAlloc ) { ! 393: // *** Should honor the container's alignment specifications. ! 394: sectionAddress = PCodeAllocateMem( section->totalLength ); //, 4, allocMode ); ! 395: } else { ! 396: sectionAddress = inst->pef + section->containerOffset; ! 397: } ! 398: ! 399: // -------------------------------------------------------------------------------------- ! 400: // !!! The copy/clear code should be moved to the loader as part of the split of the ! 401: // !!! unpack/relocate operations. It isn't clear at this point if both the read and ! 402: // !!! write sides should be touched. What if the write side pushes out pages brought in ! 403: // !!! by the read side? We should also have better advice to say all bytes are changed. ! 404: ! 405: if ( needCopy ) { ! 406: BytePtr source = inst->pef + section->containerOffset; ! 407: BytePtr dest = sectionAddress; ! 408: ByteCount length = section->unpackedLength; ! 409: ! 410: PCFM_BlockCopy ( source, dest, length ); ! 411: } ! 412: ! 413: if ( needClear ) { ! 414: BytePtr dest = (BytePtr) sectionAddress + section->unpackedLength; ! 415: ByteCount length = section->totalLength - section->unpackedLength; ! 416: ! 417: PCFM_BlockClear ( dest, length ); ! 418: } ! 419: ! 420: // ------------------------------------------------------------------------------------- ! 421: // If CFM was responsible for bringing the container into memory then we have to get the ! 422: // I&D caches in sync for the (read-only & use-in-place) code sections. ! 423: ! 424: if ( (section->access & kCFContMemExecuteMask) && (! (section->access & kCFContMemWriteMask)) && isMappable ) { ! 425: PCFM_MakeExecutable ( sectionAddress, section->unpackedLength ); ! 426: } ! 427: ! 428: err = PEF_SetSectionAddress( cRef, sectionIndex, sectionAddress, sectionAddress ); ! 429: if( err) LOG( "PEF_SetSectionAddress = %d\n", err ); ! 430: ! 431: sectionVars->address = sectionAddress; ! 432: sectionVars->unpackedLength = section->unpackedLength; ! 433: sectionVars->isPacked = isPacked; ! 434: } ! 435: ! 436: // ------------------------------------------------------------------------------------- ! 437: ! 438: err = SatisfyImports( inst ); ! 439: if( err) LOG( "SatisfyImports = %d\n", err ); ! 440: ! 441: // ------------------------------------------------------------------------------------- ! 442: ! 443: for( sectionIndex = 0; sectionIndex < numSects; sectionIndex++ ) ! 444: { ! 445: SectionVars * sectionVars; ! 446: ! 447: sectionVars = inst->sections + sectionIndex; ! 448: ! 449: INFO("Section[%d] ", sectionIndex ); ! 450: ! 451: if ( sectionVars->isPacked ) { ! 452: INFO("unpacking..."); ! 453: err = PEF_UnpackSection( cRef, ! 454: sectionIndex, ! 455: 0, // Unpack the whole section. ! 456: sectionVars->address, ! 457: sectionVars->unpackedLength ); ! 458: if( err) LOG( "PEF_UnpackSection = %d\n", err ); ! 459: } ! 460: ! 461: INFO("reloc..."); ! 462: err = PEF_RelocateSection( cRef, sectionIndex ); ! 463: ! 464: INFO(" address = 0x%08x\n", sectionVars->address ); ! 465: } ! 466: ! 467: if( err) LOG( "Instantiate = %d\n", err ); ! 468: ! 469: return( err); ! 470: } ! 471: ! 472: struct StubFunction { ! 473: LogicalAddress pc; ! 474: LogicalAddress toc; ! 475: char name[64]; ! 476: }; ! 477: typedef struct StubFunction StubFunction; ! 478: ! 479: OSStatus IONDRVUnimplementedVector( UInt32 p1, UInt32 p2, UInt32 p3, UInt32 p4 ) ! 480: { ! 481: char * name = (char *) get_R2(); ! 482: ! 483: LOG("-*- %s : %x, %x, %x\n", name, p1, p2, p3, p4); ! 484: ! 485: set_R2( (UInt32) name); ! 486: ! 487: return( -53); ! 488: } ! 489: ! 490: static OSStatus ! 491: SatisfyImports( InstanceVars * inst ) ! 492: { ! 493: CFContImportedSymbolInfo symInfo; ! 494: ! 495: OSStatus err = 0; ! 496: CFContHandlerRef cRef; ! 497: ItemCount numLibs, numSyms, index, i; ! 498: struct CFLibInfo { ! 499: CFContImportedLibraryInfo info; ! 500: LibraryEntry * found; ! 501: }; ! 502: struct CFLibInfo * libInfo; ! 503: struct CFLibInfo * curLib; ! 504: FunctionEntry * funcs; ! 505: TVector * symAddr; ! 506: StubFunction * stub; ! 507: ! 508: cRef = inst->cRef; ! 509: err = PEF_GetImportCounts( cRef, &numLibs, &numSyms ); ! 510: if( err) LOG( "PEF_GetImportCounts = %d\n", err ); ! 511: ! 512: libInfo = PCodeAllocateMem( numLibs * sizeof( struct CFLibInfo)); ! 513: PCFM_BlockClear( libInfo, numLibs * sizeof( struct CFLibInfo)); ! 514: ! 515: for( index = 0; index < numLibs; index++ ) ! 516: { ! 517: curLib = libInfo + index; ! 518: err = PEF_GetImportedLibraryInfo( cRef, index, kCFContImportedLibraryInfoVersion, &curLib->info); ! 519: if( err) LOG( "PEF_GetImportCounts = %d\n", err ); ! 520: ! 521: for( i = 0; i < IONumNDRVLibraries; i++ ) { ! 522: if( strcmp( (char *) curLib->info.libraryName.nameText, ! 523: IONDRVLibraries[ i ].name) == 0) { ! 524: curLib->found = &IONDRVLibraries[ i ]; ! 525: break; ! 526: } ! 527: } ! 528: } ! 529: ! 530: for( index = 0; index < numSyms; index++ ) ! 531: { ! 532: err = PEF_GetImportedSymbolInfo( cRef, index, kCFContImportedSymbolInfoVersion, &symInfo ); ! 533: if( err) LOG( "PEF_GetImportedSymbolInfo = %d\n", err ); ! 534: ! 535: curLib = libInfo + symInfo.libraryIndex; ! 536: ! 537: symAddr = NULL; ! 538: if( curLib->found) { ! 539: for( i = 0; i < curLib->found->numSyms; i++ ) { ! 540: ! 541: funcs = curLib->found->functions + i; ! 542: if( strcmp( (char *) symInfo.symbolName.nameText, funcs->name ) == 0) { ! 543: symAddr = (TVector *) &funcs->address; ! 544: break; ! 545: } ! 546: } ! 547: } ! 548: ! 549: if( symAddr == NULL) { ! 550: ! 551: LOG("Undefined %s:%s ", curLib->info.libraryName.nameText, symInfo.symbolName.nameText ); ! 552: ! 553: stub = IOMalloc( sizeof( StubFunction)); ! 554: symAddr = (TVector *) &stub->pc; ! 555: stub->pc = IONDRVUnimplementedVector; ! 556: stub->toc = &stub->name[0]; ! 557: strncpy( stub->name, symInfo.symbolName.nameText, 60); ! 558: } ! 559: ! 560: err = PEF_SetImportedSymbolAddress( cRef, index, symAddr ); ! 561: if( err) LOG( "PEF_SetImportedSymbolAddress = %d\n", err ); ! 562: } ! 563: ! 564: PCodeReleaseMem( libInfo); ! 565: ! 566: return( err); ! 567: } ! 568: ! 569: ! 570: ! 571:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.