2 * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
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.
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
20 * @APPLE_LICENSE_HEADER_END@
23 * Copyright (c) 1997 Apple Computer, Inc.
28 * From pieces of ProtoCFM, Alan Lillich.
30 * sdouglas 22 Oct 97 - first checked in.
31 * sdouglas 21 July 98 - start IOKit
35 #include <IOKit/IOLib.h>
36 #include <IOKit/ndrvsupport/IONDRVSupport.h>
38 #include "IOPEFLibraries.h"
39 #include "IOPEFLoader.h"
40 #include "IOPEFInternals.h"
44 #define LOG if(0) IOLog
45 #define INFO if(0) IOLog
48 LogicalAddress address
;
50 ByteCount unpackedLength
;
53 typedef struct SectionVars SectionVars
;
56 BytePtr pef
; // container in memory
57 CFContHandlerRef cRef
;
58 CFContHandlerProcs
* cProcs
;
59 ItemCount numSections
;
60 SectionVars
* sections
;
61 IONDRVUndefinedSymbolHandler undefinedHandler
;
62 void * undefHandlerSelf
;
64 typedef struct InstanceVars InstanceVars
;
67 static OSStatus
LocationToAddress( InstanceVars
* inst
,
68 CFContLogicalLocation
* location
, LogicalAddress
* address
);
69 static OSStatus
SatisfyImports( InstanceVars
* inst
);
70 static OSStatus
Instantiate( InstanceVars
* inst
);
73 #define PCFM_BlockCopy(src,dst,len) memcpy(dst,src,len)
74 #define PCFM_BlockClear(dst,len) memset(dst,0,len)
75 #define PCFM_MakeExecutable(addr,len) flush_dcache((vm_offset_t)addr, len, 0); \
76 invalidate_icache((vm_offset_t)addr, len, 0)
78 extern OSStatus
CallTVector(
79 void * p1
, void * p2
, void * p3
, void * p4
, void * p5
, void * p6
,
80 LogicalAddress entry
);
83 // ===========================================================================================
88 CFContStringHash
CFContHashName ( BytePtr nameText
,
89 ByteCount nameLength
)
91 BytePtr currChar
= nameText
;
92 SInt32 hashValue
= 0; // ! Signed to match old published PEF algorithm.
95 CFContStringHash result
;
97 #define PseudoRotate(x) ( ( (x) << 1 ) - ( (x) >> (16) ) )
100 for ( limit
= nameLength
; limit
> 0; limit
-= 1 ) {
101 if ( *currChar
== NULL
) break;
102 hashValue
= (PseudoRotate ( hashValue
)) ^ *currChar
;
107 result
= (length
<< 16) | ((UInt16
) ((hashValue
^ (hashValue
>> 16)) & 0xFFFF));
112 } // CFContHashName ()
116 // ===========================================================================================
117 // PCFM_CompareBytes ()
118 // ====================
121 Boolean
PCFM_CompareBytes ( const Byte
* left
,
125 // !!! Blechola! Switch to a standard routine ASAP!
132 ByteCount leftMiss
= (UInt32
)left
& 0x00000003;
133 ByteCount rightMiss
= (UInt32
)right
& 0x00000003;
136 bLeft
= (UInt8
*) left
;
137 bRight
= (UInt8
*) right
;
139 if ( (leftMiss
!= 0) && (rightMiss
!= 0) ) {
140 ByteCount align
= leftMiss
;
141 if ( align
> count
) align
= count
;
142 while ( align
> 0 ) {
143 if ( *bLeft
++ != *bRight
++ ) goto NoMatch
;
149 wLeft
= (UInt32
*) bLeft
;
150 wRight
= (UInt32
*) bRight
;
151 while ( count
>= 4 ) {
152 if ( *wLeft
++ != *wRight
++ ) goto NoMatch
;
156 bLeft
= (UInt8
*) wLeft
;
157 bRight
= (UInt8
*) wRight
;
158 while ( count
> 0 ) {
159 if ( *bLeft
++ != *bRight
++ ) goto NoMatch
;
170 } // PCFM_CompareBytes ()
172 // ===========================================================================================
174 LogicalAddress
PCodeAllocateMem( ByteCount size
);
175 void PCodeReleaseMem( LogicalAddress address
);
176 extern void *kern_os_malloc(size_t size
);
177 extern void kern_os_free(void * addr
);
180 PCodeAllocateMem( ByteCount size
)
182 return( (LogicalAddress
) kern_os_malloc( (size_t) size
));
186 PCodeReleaseMem( LogicalAddress address
)
188 kern_os_free( (void *) address
);
191 // ===========================================================================================
194 PCodeOpen( LogicalAddress container
, ByteCount containerSize
, PCodeInstance
* instance
)
199 inst
= PCodeAllocateMem( sizeof( InstanceVars
));
202 inst
->pef
= (BytePtr
) container
;
203 // procID, name, options
204 err
= PEF_OpenContainer( container
, container
, containerSize
, 0, 0, 0,
205 PCodeAllocateMem
, PCodeReleaseMem
,
206 &inst
->cRef
, &inst
->cProcs
);
207 if( err
) LOG( "PEF_OpenContainer = %ld\n", err
);
213 PCodeInstantiate( PCodeInstance instance
,
214 IONDRVUndefinedSymbolHandler handler
, void * self
)
217 InstanceVars
* inst
= instance
;
218 CFContLogicalLocation initLocation
;
220 CFragInitBlock initInfo
;
222 inst
->undefinedHandler
= handler
;
223 inst
->undefHandlerSelf
= self
;
226 err
= Instantiate( inst
);
231 err
= PEF_GetAnonymousSymbolLocations( inst
->cRef
, NULL
, &initLocation
, NULL
);
234 err
= LocationToAddress( inst
, &initLocation
, &tv
);
235 if( err
|| (tv
== NULL
) )
237 bzero( &initInfo
, sizeof( initInfo
));
238 err
= CallTVector( &initInfo
, 0, 0, 0, 0, 0, tv
);
247 PCodeClose( PCodeInstance instance
)
250 InstanceVars
* inst
= instance
;
251 SectionVars
* section
;
257 err
= PEF_CloseContainer( inst
->cRef
, 0 );
258 if( err
) LOG( "PEF_CloseContainer = %ld\n", err
);
260 if( inst
->sections
) {
261 for( i
= 0; i
< inst
->numSections
; i
++) {
262 section
= inst
->sections
+ i
;
263 if( section
->allocSize
)
264 PCodeReleaseMem( section
->address
);
266 PCodeReleaseMem(inst
->sections
);
273 PCodeFindExport( PCodeInstance instance
, const char * symbolName
, LogicalAddress
* address
, CFragSymbolClass
* symbolClass
)
275 CFContExportedSymbolInfo symInfo
;
276 CFContHashedName hashName
;
278 InstanceVars
* inst
= instance
;
280 hashName
.nameHash
= CFContHashName( (UInt8
*) symbolName
, strlen( symbolName
) );
281 hashName
.nameText
= (UInt8
*) symbolName
;
283 err
= PEF_FindExportedSymbolInfo( inst
->cRef
, &hashName
,
284 kCFContExportedSymbolInfoVersion
, (void *) 0, &symInfo
);
286 LOG( "PEF_FindExportedSymbolInfo = %ld\n", err
);
291 err
= LocationToAddress( inst
, &symInfo
.location
, address
);
293 *symbolClass
= symInfo
.symbolClass
;
299 PCodeFindMain( PCodeInstance instance
, LogicalAddress
* mainAddress
)
301 InstanceVars
* inst
= instance
;
302 CFContLogicalLocation mainLocation
;
305 err
= PEF_GetAnonymousSymbolLocations( inst
->cRef
, &mainLocation
, NULL
, NULL
);
308 err
= LocationToAddress( inst
, &mainLocation
, mainAddress
);
315 // ===========================================================================================
318 LocationToAddress( InstanceVars
* inst
, CFContLogicalLocation
* location
,
319 LogicalAddress
* address
)
322 OSStatus err
= noErr
;
324 if ( location
->section
>= 0 ) {
325 sectionBase
= (BytePtr
) (inst
->sections
+ location
->section
)->address
;
326 *address
= (LogicalAddress
) (sectionBase
+ location
->offset
);
328 } else if ( location
->section
== kCFContAbsoluteSectionIndex
) {
329 *address
= (LogicalAddress
) location
->offset
;
331 } else if ( location
->section
== kCFContNoSectionIndex
) {
332 *address
= (LogicalAddress
) kUnresolvedCFragSymbolAddress
;
335 err
= cfragFragmentFormatErr
;
342 Instantiate( InstanceVars
* inst
)
344 CFContHandlerRef cRef
;
345 ItemCount numSects
, sectionIndex
;
346 CFContSectionInfo sectionInfo
;
347 CFContSectionInfo
* section
;
352 err
= PEF_GetSectionCount( cRef
, &numSects
);
353 if( err
) LOG( "PEF_GetSectionCount = %ld\n", err
);
354 INFO( "Num sects = %ld\n", numSects
);
356 inst
->numSections
= numSects
;
357 inst
->sections
= PCodeAllocateMem( numSects
* sizeof( SectionVars
));
359 for( sectionIndex
= 0; sectionIndex
< numSects
; sectionIndex
++ )
361 Boolean isPacked
, isMappable
;
362 Boolean needAlloc
, needCopy
, needClear
;
363 LogicalAddress sectionAddress
;
364 SectionVars
* sectionVars
;
366 sectionVars
= inst
->sections
+ sectionIndex
;
367 section
= §ionInfo
;
369 err
= PEF_GetSectionInfo( cRef
, sectionIndex
, kCFContSectionInfoVersion
, section
);
370 if( err
) LOG( "PEF_GetSectionInfo = %ld\n", err
);
373 if ( sectionInfo
.sharing
== kCFContShareSectionInClosure
) goto SectionSharingError
;
374 if ( (! (sectionInfo
.access
& kCFContMemWriteMask
)) &&
375 (sectionInfo
.options
& kRelocatedCFContSectionMask
) ) goto SectionOptionsError
;
378 isPacked
= ((section
->options
& kPackedCFContSectionMask
) != 0);
379 isMappable
= (! isPacked
) &&
380 (! (section
->options
& kRelocatedCFContSectionMask
)) &&
381 (! (section
->access
& kCFContMemWriteMask
));
383 if ( ! isMappable
) {
384 // ----------------------------------------------------------------------------------
385 // Mappable really means "fully expanded in container", so sections that are not mappable
386 // need to be allocated. The loader will do the initialization copying. This is the
387 // standard case for packed PEF data sections.
389 needCopy
= (! isPacked
);
390 needClear
= (section
->totalLength
!= section
->unpackedLength
);
392 } else if ( ! (section
->access
& kCFContMemWriteMask
) ) {
393 // -----------------------------------------------------------------------------------
394 // A "mappable" read only section. Make sure it is fully present, i.e. no zero filled
395 // extension. This is the standard case for code and literal sections.
396 if ( section
->totalLength
!= section
->unpackedLength
) {
397 err
= cfragFragmentUsageErr
; // !!! Needs error label & message.
405 // -----------------------------------------------------------------------------------
406 // A "mappable", writeable, don't use in place section. This is the standard case for
407 // unpacked data sections.
410 needClear
= (section
->totalLength
!= section
->unpackedLength
);
414 // *** Should honor the container's alignment specifications.
415 sectionAddress
= PCodeAllocateMem( section
->totalLength
); //, 4, allocMode );
417 sectionAddress
= inst
->pef
+ section
->containerOffset
;
420 // --------------------------------------------------------------------------------------
421 // !!! The copy/clear code should be moved to the loader as part of the split of the
422 // !!! unpack/relocate operations. It isn't clear at this point if both the read and
423 // !!! write sides should be touched. What if the write side pushes out pages brought in
424 // !!! by the read side? We should also have better advice to say all bytes are changed.
427 BytePtr source
= inst
->pef
+ section
->containerOffset
;
428 BytePtr dest
= sectionAddress
;
429 ByteCount length
= section
->unpackedLength
;
431 PCFM_BlockCopy ( source
, dest
, length
);
435 BytePtr dest
= (BytePtr
) sectionAddress
+ section
->unpackedLength
;
436 ByteCount length
= section
->totalLength
- section
->unpackedLength
;
438 PCFM_BlockClear ( dest
, length
);
441 // -------------------------------------------------------------------------------------
442 // If CFM was responsible for bringing the container into memory then we have to get the
443 // I&D caches in sync for the (read-only & use-in-place) code sections.
445 if ( (section
->access
& kCFContMemExecuteMask
)
446 && (! (section
->access
& kCFContMemWriteMask
)) && isMappable
) {
447 PCFM_MakeExecutable ( sectionAddress
, section
->unpackedLength
);
450 err
= PEF_SetSectionAddress( cRef
, sectionIndex
, sectionAddress
, sectionAddress
);
451 if( err
) LOG( "PEF_SetSectionAddress = %ld\n", err
);
453 sectionVars
->address
= sectionAddress
;
454 sectionVars
->unpackedLength
= section
->unpackedLength
;
455 sectionVars
->isPacked
= isPacked
;
457 sectionVars
->allocSize
= section
->totalLength
;
459 sectionVars
->allocSize
= 0;
462 // -------------------------------------------------------------------------------------
464 err
= SatisfyImports( inst
);
465 if( err
) LOG( "SatisfyImports = %ld\n", err
);
467 // -------------------------------------------------------------------------------------
469 for( sectionIndex
= 0; sectionIndex
< numSects
; sectionIndex
++ )
471 SectionVars
* sectionVars
;
473 sectionVars
= inst
->sections
+ sectionIndex
;
475 INFO("Section[%ld] ", sectionIndex
);
477 if ( sectionVars
->isPacked
) {
478 INFO("unpacking...");
479 err
= PEF_UnpackSection( cRef
,
481 0, // Unpack the whole section.
482 sectionVars
->address
,
483 sectionVars
->unpackedLength
);
484 if( err
) LOG( "PEF_UnpackSection = %ld\n", err
);
488 err
= PEF_RelocateSection( cRef
, sectionIndex
);
490 INFO(" address = 0x%08lx\n", (UInt32
) sectionVars
->address
);
493 if( err
) LOG( "Instantiate = %ld\n", err
);
498 struct StubFunction
{
503 typedef struct StubFunction StubFunction
;
505 OSStatus
IONDRVUnimplementedVector( UInt32 p1
, UInt32 p2
, UInt32 p3
, UInt32 p4
)
507 char * name
= (char *) get_R2();
509 LOG("-*- %s : %lx, %lx, %lx, %lx\n", name
, p1
, p2
, p3
, p4
);
511 set_R2( (UInt32
) name
);
517 SatisfyImports( InstanceVars
* inst
)
519 CFContImportedSymbolInfo symInfo
;
522 CFContHandlerRef cRef
;
523 ItemCount numLibs
, numSyms
, index
, i
;
525 CFContImportedLibraryInfo info
;
526 LibraryEntry
* found
;
528 struct CFLibInfo
* libInfo
;
529 struct CFLibInfo
* curLib
;
530 FunctionEntry
* funcs
;
531 const IOTVector
* symAddr
;
535 err
= PEF_GetImportCounts( cRef
, &numLibs
, &numSyms
);
536 if( err
) LOG( "PEF_GetImportCounts = %ld\n", err
);
538 libInfo
= PCodeAllocateMem( numLibs
* sizeof( struct CFLibInfo
));
539 PCFM_BlockClear( libInfo
, numLibs
* sizeof( struct CFLibInfo
));
541 for( index
= 0; index
< numLibs
; index
++ )
543 curLib
= libInfo
+ index
;
544 err
= PEF_GetImportedLibraryInfo( cRef
, index
, kCFContImportedLibraryInfoVersion
, &curLib
->info
);
545 if( err
) LOG( "PEF_GetImportCounts = %ld\n", err
);
547 for( i
= 0; i
< IONumNDRVLibraries
; i
++ ) {
548 if( strcmp( (char *) curLib
->info
.libraryName
.nameText
,
549 IONDRVLibraries
[ i
].name
) == 0) {
550 curLib
->found
= &IONDRVLibraries
[ i
];
556 for( index
= 0; index
< numSyms
; index
++ )
558 err
= PEF_GetImportedSymbolInfo( cRef
, index
, kCFContImportedSymbolInfoVersion
, &symInfo
);
559 if( err
) LOG( "PEF_GetImportedSymbolInfo = %ld\n", err
);
561 curLib
= libInfo
+ symInfo
.libraryIndex
;
565 for( i
= 0; i
< curLib
->found
->numSyms
; i
++ ) {
567 funcs
= curLib
->found
->functions
+ i
;
568 if( strcmp( (char *) symInfo
.symbolName
.nameText
, funcs
->name
) == 0) {
569 symAddr
= (IOTVector
*) &funcs
->address
;
574 } else if( inst
->undefinedHandler
)
575 symAddr
= (*inst
->undefinedHandler
)(inst
->undefHandlerSelf
,
576 curLib
->info
.libraryName
.nameText
,
577 symInfo
.symbolName
.nameText
);
578 if( symAddr
== NULL
) {
580 LOG("Undefined %s:%s ", curLib
->info
.libraryName
.nameText
, symInfo
.symbolName
.nameText
);
582 stub
= IOMalloc( sizeof( StubFunction
));
583 symAddr
= (IOTVector
*) &stub
->pc
;
584 stub
->pc
= IONDRVUnimplementedVector
;
585 stub
->toc
= &stub
->name
[0];
586 strncpy( stub
->name
, symInfo
.symbolName
.nameText
, 60);
589 err
= PEF_SetImportedSymbolAddress( cRef
, index
, (IOTVector
*) symAddr
);
590 if( err
) LOG( "PEF_SetImportedSymbolAddress = %ld\n", err
);
593 PCodeReleaseMem( libInfo
);