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