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