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