2  * Copyright (c) 2000-2012 Apple Inc. All rights reserved. 
   4  * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ 
   6  * This file contains Original Code and/or Modifications of Original Code 
   7  * as defined in and that are subject to the Apple Public Source License 
   8  * Version 2.0 (the 'License'). You may not use this file except in 
   9  * compliance with the License. The rights granted to you under the License 
  10  * may not be used to create, or enable the creation or redistribution of, 
  11  * unlawful or unlicensed copies of an Apple operating system, or to 
  12  * circumvent, violate, or enable the circumvention or violation of, any 
  13  * terms of an Apple operating system software license agreement. 
  15  * Please obtain a copy of the License at 
  16  * http://www.opensource.apple.com/apsl/ and read it before using this file. 
  18  * The Original Code and all software distributed under the License are 
  19  * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 
  20  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 
  21  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 
  22  * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 
  23  * Please see the License for the specific language governing rights and 
  24  * limitations under the License. 
  26  * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ 
  29 #include <mach/kmod.h> 
  30 #include <libkern/kernel_mach_header.h> 
  31 #include <libkern/prelink.h> 
  35 #include <libkern/version.h> 
  36 #include <libkern/c++/OSContainers.h> 
  37 #include <libkern/OSKextLibPrivate.h> 
  38 #include <libkern/c++/OSKext.h> 
  39 #include <IOKit/IOLib.h> 
  40 #include <IOKit/IOService.h> 
  41 #include <IOKit/IODeviceTreeSupport.h> 
  42 #include <IOKit/IOCatalogue.h> 
  45 #define KASLR_KEXT_DEBUG 0 
  49 #pragma mark Bootstrap Declarations 
  51 /********************************************************************* 
  52 * Bootstrap Declarations 
  54 * The ENTIRE point of the libsa/KLD segment is to isolate bootstrap 
  55 * code from other parts of the kernel, so function symbols are not 
  56 * exported; rather pointers to those functions are exported. 
  58 * xxx - need to think about locking for handling the 'weak' refs. 
  59 * xxx - do export a non-KLD function that says you've called a 
  60 * xxx - bootstrap function that has been removed. 
  62 * ALL call-ins to this segment of the kernel must be done through 
  63 * exported pointers. The symbols themselves are private and not to 
  65 *********************************************************************/ 
  67     extern void (*record_startup_extensions_function
)(void); 
  68     extern void (*load_security_extensions_function
)(void); 
  71 static void bootstrapRecordStartupExtensions(void); 
  72 static void bootstrapLoadSecurityExtensions(void); 
  76 extern "C" bool IORamDiskBSDRoot(void); 
  82 /********************************************************************* 
  84 *********************************************************************/ 
  85 #define CONST_STRLEN(str) (sizeof(str) - 1) 
  88 #pragma mark Kernel Component Kext Identifiers 
  90 /********************************************************************* 
  91 * Kernel Component Kext Identifiers 
  93 * We could have each kernel resource kext automatically "load" as 
  94 * it's created, but it's nicer to have them listed in kextstat in 
  95 * the order of this list. We'll walk through this after setting up 
  96 * all the boot kexts and have them load up. 
  97 *********************************************************************/ 
  98 static const char * sKernelComponentNames
[] = { 
  99    // The kexts for these IDs must have a version matching 'osrelease'. 
 102    "com.apple.kpi.dsep", 
 103    "com.apple.kpi.iokit", 
 104    "com.apple.kpi.libkern", 
 105    "com.apple.kpi.mach", 
 106    "com.apple.kpi.private", 
 107    "com.apple.kpi.unsupported", 
 108    "com.apple.iokit.IONVRAMFamily", 
 109    "com.apple.driver.AppleNMI", 
 110    "com.apple.iokit.IOSystemManagementFamily", 
 111    "com.apple.iokit.ApplePlatformFamily", 
 115 static int __whereIsAddr(vm_offset_t theAddr
, unsigned long * segSizes
, vm_offset_t 
*segAddrs
, int segCount 
); 
 117 #define PLK_SEGMENTS 11 
 119 static const char * plk_segNames
[] = { 
 135 #pragma mark KLDBootstrap Class 
 137 /********************************************************************* 
 140 * We use a C++ class here so that it can be a friend of OSKext and 
 141 * get at private stuff. We can't hide the class itself, but we can 
 142 * hide the instance through which we invoke the functions. 
 143 *********************************************************************/ 
 145     friend void bootstrapRecordStartupExtensions(void); 
 146     friend void bootstrapLoadSecurityExtensions(void); 
 149     void readStartupExtensions(void); 
 151     void readPrelinkedExtensions( 
 152         kernel_section_t 
* prelinkInfoSect
); 
 153     void readBooterExtensions(void); 
 155     OSReturn 
loadKernelComponentKexts(void); 
 156     void     loadKernelExternalComponents(void); 
 157     void     readBuiltinPersonalities(void); 
 159     void     loadSecurityExtensions(void); 
 166 static KLDBootstrap sBootstrapObject
; 
 168 /********************************************************************* 
 169 * Set the function pointers for the entry points into the bootstrap 
 170 * segment upon C++ static constructor invocation. 
 171 *********************************************************************/ 
 172 KLDBootstrap::KLDBootstrap(void) 
 174     if (this != &sBootstrapObject
) { 
 175         panic("Attempt to access bootstrap segment."); 
 177     record_startup_extensions_function 
= &bootstrapRecordStartupExtensions
; 
 178     load_security_extensions_function 
= &bootstrapLoadSecurityExtensions
; 
 181 /********************************************************************* 
 182 * Clear the function pointers for the entry points into the bootstrap 
 183 * segment upon C++ static destructor invocation. 
 184 *********************************************************************/ 
 185 KLDBootstrap::~KLDBootstrap(void) 
 187     if (this != &sBootstrapObject
) { 
 188         panic("Attempt to access bootstrap segment."); 
 192     record_startup_extensions_function 
= 0; 
 193     load_security_extensions_function 
= 0; 
 196 /********************************************************************* 
 197 *********************************************************************/ 
 199 KLDBootstrap::readStartupExtensions(void) 
 201     kernel_section_t 
* prelinkInfoSect 
= NULL
;  // do not free 
 203     OSKextLog(/* kext */ NULL
, 
 204         kOSKextLogProgressLevel 
| 
 205         kOSKextLogGeneralFlag 
| kOSKextLogDirectoryScanFlag 
| 
 206         kOSKextLogKextBookkeepingFlag
, 
 207         "Reading startup extensions."); 
 209    /* If the prelink info segment has a nonzero size, we are prelinked 
 210     * and won't have any individual kexts or mkexts to read. 
 211     * Otherwise, we need to read kexts or the mkext from what the booter 
 214     prelinkInfoSect 
= getsectbyname(kPrelinkInfoSegment
, kPrelinkInfoSection
); 
 215     if (prelinkInfoSect
->size
) { 
 216         readPrelinkedExtensions(prelinkInfoSect
); 
 218         readBooterExtensions(); 
 221     loadKernelComponentKexts(); 
 222     loadKernelExternalComponents(); 
 223     readBuiltinPersonalities(); 
 224     OSKext::sendAllKextPersonalitiesToCatalog(); 
 229 typedef struct kaslrPackedOffsets 
{ 
 230     uint32_t    count
;              /* number of offsets */ 
 231     uint32_t    offsetsArray
[];     /* offsets to slide */ 
 232 } kaslrPackedOffsets
; 
 234 /********************************************************************* 
 235 *********************************************************************/ 
 237 KLDBootstrap::readPrelinkedExtensions( 
 238     kernel_section_t 
* prelinkInfoSect
) 
 240     OSArray                   
* infoDictArray           
= NULL
;  // do not release 
 241     OSObject                  
* parsedXML       
= NULL
;  // must release 
 242     OSDictionary              
* prelinkInfoDict         
= NULL
;  // do not release 
 243     OSString                  
* errorString             
= NULL
;  // must release 
 244     OSKext                    
* theKernel               
= NULL
;  // must release 
 246     kernel_segment_command_t  
* prelinkTextSegment      
= NULL
;  // see code 
 247     kernel_segment_command_t  
* prelinkInfoSegment      
= NULL
;  // see code 
 249    /* We make some copies of data, but if anything fails we're basically 
 250     * going to fail the boot, so these won't be cleaned up on error. 
 252     void                      * prelinkData             
= NULL
;  // see code 
 253     vm_size_t                   prelinkLength           
= 0; 
 256     OSDictionary              
* infoDict                
= NULL
;  // do not release 
 258     IORegistryEntry           
* registryRoot            
= NULL
;  // do not release 
 259     OSNumber                  
* prelinkCountObj         
= NULL
;  // must release 
 264     bool                        developerDevice
; 
 267     OSData                     
* kaslrOffsets 
= NULL
; 
 268     unsigned long               plk_segSizes
[PLK_SEGMENTS
]; 
 269     vm_offset_t                 plk_segAddrs
[PLK_SEGMENTS
]; 
 271     OSKextLog(/* kext */ NULL
, 
 272         kOSKextLogProgressLevel 
| 
 273         kOSKextLogDirectoryScanFlag 
| kOSKextLogArchiveFlag
, 
 274         "Starting from prelinked kernel."); 
 276     prelinkTextSegment 
= getsegbyname(kPrelinkTextSegment
); 
 277     if (!prelinkTextSegment
) { 
 278         OSKextLog(/* kext */ NULL
, 
 279             kOSKextLogErrorLevel 
| 
 280             kOSKextLogDirectoryScanFlag 
| kOSKextLogArchiveFlag
, 
 281             "Can't find prelinked kexts' text segment."); 
 286     unsigned long   scratchSize
; 
 287     vm_offset_t     scratchAddr
; 
 289     IOLog("kaslr: prelinked kernel address info: \n"); 
 291     scratchAddr 
= (vm_offset_t
) getsegdatafromheader(&_mh_execute_header
, "__TEXT", &scratchSize
); 
 292     IOLog("kaslr: start 0x%lx end 0x%lx length %lu for __TEXT \n",  
 293           (unsigned long)scratchAddr
,  
 294           (unsigned long)(scratchAddr 
+ scratchSize
), 
 297     scratchAddr 
= (vm_offset_t
) getsegdatafromheader(&_mh_execute_header
, "__DATA", &scratchSize
); 
 298     IOLog("kaslr: start 0x%lx end 0x%lx length %lu for __DATA \n",  
 299           (unsigned long)scratchAddr
,  
 300           (unsigned long)(scratchAddr 
+ scratchSize
), 
 303     scratchAddr 
= (vm_offset_t
) getsegdatafromheader(&_mh_execute_header
, "__LINKEDIT", &scratchSize
); 
 304     IOLog("kaslr: start 0x%lx end 0x%lx length %lu for __LINKEDIT \n",  
 305           (unsigned long)scratchAddr
,  
 306           (unsigned long)(scratchAddr 
+ scratchSize
), 
 309     scratchAddr 
= (vm_offset_t
) getsegdatafromheader(&_mh_execute_header
, "__KLD", &scratchSize
); 
 310     IOLog("kaslr: start 0x%lx end 0x%lx length %lu for __KLD \n",  
 311           (unsigned long)scratchAddr
,  
 312           (unsigned long)(scratchAddr 
+ scratchSize
), 
 315     scratchAddr 
= (vm_offset_t
) getsegdatafromheader(&_mh_execute_header
, "__PRELINK_TEXT", &scratchSize
); 
 316     IOLog("kaslr: start 0x%lx end 0x%lx length %lu for __PRELINK_TEXT \n",  
 317           (unsigned long)scratchAddr
,  
 318           (unsigned long)(scratchAddr 
+ scratchSize
), 
 321     scratchAddr 
= (vm_offset_t
) getsegdatafromheader(&_mh_execute_header
, "__PRELINK_INFO", &scratchSize
); 
 322     IOLog("kaslr: start 0x%lx end 0x%lx length %lu for __PRELINK_INFO \n",  
 323           (unsigned long)scratchAddr
,  
 324           (unsigned long)(scratchAddr 
+ scratchSize
), 
 328     prelinkData 
= (void *) prelinkTextSegment
->vmaddr
; 
 329     prelinkLength 
= prelinkTextSegment
->vmsize
; 
 331     /* build arrays of plk info for later use */ 
 332     const char ** segNamePtr
; 
 334     for (segNamePtr 
= &plk_segNames
[0], i 
= 0; *segNamePtr 
&& i 
< PLK_SEGMENTS
; segNamePtr
++, i
++) { 
 336         plk_segAddrs
[i
] = (vm_offset_t
)getsegdatafromheader(&_mh_execute_header
, *segNamePtr
, &plk_segSizes
[i
]); 
 340    /* Unserialize the info dictionary from the prelink info section. 
 342     parsedXML 
= OSUnserializeXML((const char *)prelinkInfoSect
->addr
, 
 345         prelinkInfoDict 
= OSDynamicCast(OSDictionary
, parsedXML
); 
 347     if (!prelinkInfoDict
) { 
 348         const char * errorCString 
= "(unknown error)"; 
 350         if (errorString 
&& errorString
->getCStringNoCopy()) { 
 351             errorCString 
= errorString
->getCStringNoCopy(); 
 352         } else if (parsedXML
) { 
 353             errorCString 
= "not a dictionary"; 
 355         OSKextLog(/* kext */ NULL
, kOSKextLogErrorLevel 
| kOSKextLogArchiveFlag
, 
 356             "Error unserializing prelink plist: %s.", errorCString
); 
 361     /* Check if we should keep developer kexts around. 
 362      * TODO: Check DeviceTree instead of a boot-arg <rdar://problem/10604201> 
 364     developerDevice 
= true; 
 365     PE_parse_boot_argn("developer", &developerDevice
, sizeof(developerDevice
)); 
 367     ramDiskBoot 
= IORamDiskBSDRoot(); 
 368 #endif /* NO_KEXTD */ 
 371     infoDictArray 
= OSDynamicCast(OSArray
,  
 372         prelinkInfoDict
->getObject(kPrelinkInfoDictionaryKey
)); 
 373     if (!infoDictArray
) { 
 374         OSKextLog(/* kext */ NULL
, kOSKextLogErrorLevel 
| kOSKextLogArchiveFlag
, 
 375             "The prelinked kernel has no kext info dictionaries"); 
 379     /* kaslrOffsets are available use them to slide local relocations */ 
 380     kaslrOffsets 
= OSDynamicCast(OSData
, 
 381                                  prelinkInfoDict
->getObject(kPrelinkLinkKASLROffsetsKey
)); 
 383     /* Create dictionary of excluded kexts 
 385     OSKext::createExcludeListFromPrelinkInfo(infoDictArray
); 
 386     /* Create OSKext objects for each info dictionary.  
 388     for (i 
= 0; i 
< infoDictArray
->getCount(); ++i
) { 
 389         infoDict 
= OSDynamicCast(OSDictionary
, infoDictArray
->getObject(i
)); 
 391             OSKextLog(/* kext */ NULL
, 
 392                 kOSKextLogErrorLevel 
| 
 393                 kOSKextLogDirectoryScanFlag 
| kOSKextLogArchiveFlag
, 
 394                 "Can't find info dictionary for prelinked kext #%d.", i
); 
 401         /* If we're not on a developer device, skip and free developer kexts. 
 403         if (developerDevice 
== false) { 
 404             OSBoolean 
*devOnlyBool 
= OSDynamicCast(OSBoolean
, 
 405                 infoDict
->getObject(kOSBundleDeveloperOnlyKey
)); 
 406             if (devOnlyBool 
== kOSBooleanTrue
) { 
 411         /* Skip and free kexts that are only needed when booted from a ram disk. 
 413         if (ramDiskBoot 
== false) { 
 414             OSBoolean 
*ramDiskOnlyBool 
= OSDynamicCast(OSBoolean
, 
 415                 infoDict
->getObject(kOSBundleRamDiskOnlyKey
)); 
 416             if (ramDiskOnlyBool 
== kOSBooleanTrue
) { 
 421         if (dontLoad 
== true) { 
 422             OSString 
*bundleID 
= OSDynamicCast(OSString
, 
 423                 infoDict
->getObject(kCFBundleIdentifierKey
)); 
 425                 OSKextLog(NULL
, kOSKextLogWarningLevel 
| kOSKextLogGeneralFlag
, 
 426                     "Kext %s not loading.", bundleID
->getCStringNoCopy()); 
 429             OSNumber 
*addressNum 
= OSDynamicCast(OSNumber
, 
 430                 infoDict
->getObject(kPrelinkExecutableLoadKey
)); 
 431             OSNumber 
*lengthNum 
= OSDynamicCast(OSNumber
, 
 432                 infoDict
->getObject(kPrelinkExecutableSizeKey
)); 
 433             if (addressNum 
&& lengthNum
) { 
 434 #error Pick the right way to free prelinked data on this arch 
 437             infoDictArray
->removeObject(i
--); 
 440 #endif /* NO_KEXTD */ 
 442        /* Create the kext for the entry, then release it, because the 
 443         * kext system keeps them around until explicitly removed. 
 444         * Any creation/registration failures are already logged for us. 
 446         OSKext 
* newKext 
= OSKext::withPrelinkedInfoDict(infoDict
, (kaslrOffsets 
? TRUE 
: FALSE
)); 
 447         OSSafeReleaseNULL(newKext
); 
 450     /* slide kxld relocations */ 
 451     if (kaslrOffsets 
&& vm_kernel_slide 
> 0) { 
 452             int slidKextAddrCount 
= 0; 
 453             int badSlideAddr 
= 0; 
 454             int badSlideTarget 
= 0; 
 456         kaslrPackedOffsets 
* myOffsets 
= NULL
; 
 457             myOffsets 
= (kaslrPackedOffsets 
*) kaslrOffsets
->getBytesNoCopy(); 
 459             for (uint32_t j 
= 0; j 
< myOffsets
->count
; j
++) { 
 461                     uint64_t        slideOffset 
= (uint64_t) myOffsets
->offsetsArray
[j
]; 
 462                     uintptr_t *     slideAddr 
= (uintptr_t *) ((uint64_t)prelinkData 
+ slideOffset
); 
 463                     int             slideAddrSegIndex 
= -1; 
 464                     int             addrToSlideSegIndex 
= -1; 
 466                     slideAddrSegIndex 
= __whereIsAddr( (vm_offset_t
)slideAddr
, &plk_segSizes
[0], &plk_segAddrs
[0], PLK_SEGMENTS 
); 
 467                     if (slideAddrSegIndex 
>= 0) { 
 468                             addrToSlideSegIndex 
= __whereIsAddr( (vm_offset_t
)(*slideAddr 
+ vm_kernel_slide
), &plk_segSizes
[0], &plk_segAddrs
[0], PLK_SEGMENTS 
); 
 469                             if (addrToSlideSegIndex 
< 0) { 
 480                     *(slideAddr
) += vm_kernel_slide
; 
 483             /* All kexts are now slid, set VM protections for them */ 
 484             OSKext::setAllVMAttributes(); 
 487    /* Store the number of prelinked kexts in the registry so we can tell 
 488     * when the system has been started from a prelinked kernel. 
 490     registryRoot 
= IORegistryEntry::getRegistryRoot(); 
 491     assert(registryRoot
); 
 493     prelinkCountObj 
= OSNumber::withNumber( 
 494         (unsigned long long)infoDictArray
->getCount(), 
 495         8 * sizeof(uint32_t)); 
 496     assert(prelinkCountObj
); 
 497     if (prelinkCountObj
) { 
 498         registryRoot
->setProperty(kOSPrelinkKextCountKey
, prelinkCountObj
); 
 501     OSKextLog(/* kext */ NULL
, 
 502         kOSKextLogProgressLevel 
| 
 503         kOSKextLogGeneralFlag 
| kOSKextLogKextBookkeepingFlag 
| 
 504         kOSKextLogDirectoryScanFlag 
| kOSKextLogArchiveFlag
, 
 505         "%u prelinked kexts",  
 506         infoDictArray
->getCount()); 
 508 #if CONFIG_KEXT_BASEMENT 
 509         /* On CONFIG_KEXT_BASEMENT systems, kexts are copied to their own  
 510          * special VM region during OSKext init time, so we can free the whole  
 513         ml_static_mfree((vm_offset_t
) prelinkData
, prelinkLength
); 
 514 #endif /* __x86_64__ */ 
 516    /* Free the prelink info segment, we're done with it. 
 518     prelinkInfoSegment 
= getsegbyname(kPrelinkInfoSegment
); 
 519     if (prelinkInfoSegment
) { 
 520         ml_static_mfree((vm_offset_t
)prelinkInfoSegment
->vmaddr
, 
 521             (vm_size_t
)prelinkInfoSegment
->vmsize
); 
 525     OSSafeReleaseNULL(errorString
); 
 526     OSSafeReleaseNULL(parsedXML
); 
 527     OSSafeReleaseNULL(theKernel
); 
 528     OSSafeReleaseNULL(prelinkCountObj
); 
 532 static int __whereIsAddr(vm_offset_t theAddr
, unsigned long * segSizes
, vm_offset_t 
*segAddrs
, int segCount
) 
 536         for (i 
= 0; i 
< segCount
; i
++) { 
 537                 vm_offset_t         myAddr 
= *(segAddrs 
+ i
); 
 538                 unsigned long       mySize 
= *(segSizes 
+ i
); 
 540                 if (theAddr 
>= myAddr 
&& theAddr 
< (myAddr 
+ mySize
)) { 
 549 /********************************************************************* 
 550 *********************************************************************/ 
 551 #define BOOTER_KEXT_PREFIX   "Driver-" 
 553 typedef struct _DeviceTreeBuffer 
{ 
 559 KLDBootstrap::readBooterExtensions(void) 
 561     IORegistryEntry           
* booterMemoryMap         
= NULL
;  // must release 
 562     OSDictionary              
* propertyDict            
= NULL
;  // must release 
 563     OSCollectionIterator      
* keyIterator             
= NULL
;  // must release 
 564     OSString                  
* deviceTreeName          
= NULL
;  // do not release 
 566     const _DeviceTreeBuffer   
* deviceTreeBuffer        
= NULL
;  // do not free 
 567     char                      * booterDataPtr           
= NULL
;  // do not free 
 568     OSData                    
* booterData              
= NULL
;  // must release 
 570     OSKext                    
* aKext                   
= NULL
;  // must release 
 572     OSKextLog(/* kext */ NULL
, 
 573         kOSKextLogProgressLevel 
| 
 574         kOSKextLogDirectoryScanFlag 
| kOSKextLogKextBookkeepingFlag
, 
 575         "Reading startup extensions from booter memory."); 
 577     booterMemoryMap 
= IORegistryEntry::fromPath( "/chosen/memory-map", gIODTPlane
); 
 579     if (!booterMemoryMap
) { 
 580         OSKextLog(/* kext */ NULL
, 
 581             kOSKextLogErrorLevel 
| 
 582             kOSKextLogGeneralFlag 
| kOSKextLogDirectoryScanFlag
, 
 583             "Can't read booter memory map."); 
 587     propertyDict 
= booterMemoryMap
->dictionaryWithProperties(); 
 589         OSKextLog(/* kext */ NULL
, 
 590             kOSKextLogErrorLevel 
| 
 591             kOSKextLogDirectoryScanFlag
, 
 592             "Can't get property dictionary from memory map."); 
 596     keyIterator 
= OSCollectionIterator::withCollection(propertyDict
); 
 598         OSKextLog(/* kext */ NULL
, 
 599             kOSKextLogErrorLevel 
| 
 600             kOSKextLogGeneralFlag
, 
 601             "Can't allocate iterator for driver images."); 
 605     /* Create dictionary of excluded kexts 
 607     OSKext::createExcludeListFromBooterData(propertyDict
, keyIterator
); 
 608     keyIterator
->reset(); 
 610     while ( ( deviceTreeName 
= 
 611         OSDynamicCast(OSString
, keyIterator
->getNextObject() ))) { 
 613         const char * devTreeNameCString 
= deviceTreeName
->getCStringNoCopy(); 
 614         OSData 
* deviceTreeEntry 
= OSDynamicCast(OSData
, 
 615             propertyDict
->getObject(deviceTreeName
)); 
 617        /* Clear out the booterData from the prior iteration. 
 619         OSSafeReleaseNULL(booterData
); 
 621         /* If there is no entry for the name, we can't do much with it. */ 
 622         if (!deviceTreeEntry
) { 
 626         /* Make sure it is a kext */ 
 627         if (strncmp(devTreeNameCString
, 
 629                     CONST_STRLEN(BOOTER_KEXT_PREFIX
))) { 
 633         deviceTreeBuffer 
= (const _DeviceTreeBuffer 
*) 
 634             deviceTreeEntry
->getBytesNoCopy(0, sizeof(deviceTreeBuffer
)); 
 635         if (!deviceTreeBuffer
) { 
 636            /* We can't get to the data, so we can't do anything, 
 637             * not even free it from physical memory (if it's there). 
 639             OSKextLog(/* kext */ NULL
, 
 640                 kOSKextLogErrorLevel 
| 
 641                 kOSKextLogDirectoryScanFlag
, 
 642                 "Device tree entry %s has NULL pointer.", 
 644             goto finish
;  // xxx - continue, panic? 
 647         booterDataPtr 
= (char *)ml_static_ptovirt(deviceTreeBuffer
->paddr
); 
 648         if (!booterDataPtr
) { 
 649             OSKextLog(/* kext */ NULL
, 
 650                 kOSKextLogErrorLevel 
| 
 651                 kOSKextLogDirectoryScanFlag
, 
 652                 "Can't get virtual address for device tree entry %s.", 
 657        /* Wrap the booter data buffer in an OSData and set a dealloc function 
 658         * so it will take care of the physical memory when freed. Kexts will 
 659         * retain the booterData for as long as they need it. Remove the entry 
 660         * from the booter memory map after this is done. 
 662         booterData 
= OSData::withBytesNoCopy(booterDataPtr
, 
 663             deviceTreeBuffer
->length
); 
 665             OSKextLog(/* kext */ NULL
, 
 666                 kOSKextLogErrorLevel 
| 
 667                 kOSKextLogGeneralFlag
, 
 668                 "Error - Can't allocate OSData wrapper for device tree entry %s.", 
 672         booterData
->setDeallocFunction(osdata_phys_free
); 
 674         /* Create the kext for the entry, then release it, because the 
 675          * kext system keeps them around until explicitly removed. 
 676          * Any creation/registration failures are already logged for us. 
 678         OSKext 
* newKext 
= OSKext::withBooterData(deviceTreeName
, booterData
); 
 679         OSSafeReleaseNULL(newKext
); 
 681         booterMemoryMap
->removeProperty(deviceTreeName
); 
 683     } /* while ( (deviceTreeName = OSDynamicCast(OSString, ...) ) ) */ 
 687     OSSafeReleaseNULL(booterMemoryMap
); 
 688     OSSafeReleaseNULL(propertyDict
); 
 689     OSSafeReleaseNULL(keyIterator
); 
 690     OSSafeReleaseNULL(booterData
); 
 691     OSSafeReleaseNULL(aKext
); 
 695 /********************************************************************* 
 696 *********************************************************************/ 
 697 #define COM_APPLE  "com.apple." 
 700 KLDBootstrap::loadSecurityExtensions(void) 
 702     OSDictionary         
* extensionsDict 
= NULL
;  // must release 
 703     OSCollectionIterator 
* keyIterator    
= NULL
;  // must release 
 704     OSString             
* bundleID       
= NULL
;  // don't release 
 705     OSKext               
* theKext        
= NULL
;  // don't release 
 706     OSBoolean            
* isSecurityKext 
= NULL
;  // don't release 
 708     OSKextLog(/* kext */ NULL
, 
 709         kOSKextLogStepLevel 
| 
 711         "Loading security extensions."); 
 713     extensionsDict 
= OSKext::copyKexts(); 
 714     if (!extensionsDict
) { 
 718     keyIterator 
= OSCollectionIterator::withCollection(extensionsDict
); 
 720         OSKextLog(/* kext */ NULL
, 
 721             kOSKextLogErrorLevel 
| 
 722             kOSKextLogGeneralFlag
, 
 723             "Failed to allocate iterator for security extensions."); 
 727     while ((bundleID 
= OSDynamicCast(OSString
, keyIterator
->getNextObject()))) { 
 729         const char * bundle_id 
= bundleID
->getCStringNoCopy(); 
 731        /* Skip extensions whose bundle IDs don't start with "com.apple.". 
 734             (strncmp(bundle_id
, COM_APPLE
, CONST_STRLEN(COM_APPLE
)) != 0)) { 
 739         theKext 
= OSDynamicCast(OSKext
, extensionsDict
->getObject(bundleID
)); 
 744         isSecurityKext 
= OSDynamicCast(OSBoolean
, 
 745             theKext
->getPropertyForHostArch(kAppleSecurityExtensionKey
)); 
 746         if (isSecurityKext 
&& isSecurityKext
->isTrue()) { 
 747             OSKextLog(/* kext */ NULL
, 
 748                 kOSKextLogStepLevel 
| 
 750                 "Loading security extension %s.", bundleID
->getCStringNoCopy()); 
 751             OSKext::loadKextWithIdentifier(bundleID
->getCStringNoCopy(), 
 752                 /* allowDefer */ false); 
 757     OSSafeReleaseNULL(keyIterator
); 
 758     OSSafeReleaseNULL(extensionsDict
); 
 763 /********************************************************************* 
 764 * We used to require that all listed kernel components load, but 
 765 * nowadays we can get them from userland so we only try to load the 
 766 * ones we have. If an error occurs later, such is life. 
 768 * Note that we look the kexts up first, so we can avoid spurious 
 769 * (in this context, anyhow) log messages about kexts not being found. 
 771 * xxx - do we even need to do this any more? Check if the kernel 
 772 * xxx - compoonents just load in the regular paths 
 773 *********************************************************************/ 
 775 KLDBootstrap::loadKernelComponentKexts(void) 
 777     OSReturn      result      
= kOSReturnSuccess
;  // optimistic 
 778     OSKext      
* theKext     
= NULL
;              // must release 
 779     const char ** kextIDPtr   
= NULL
;              // do not release 
 781     for (kextIDPtr 
= &sKernelComponentNames
[0]; *kextIDPtr
; kextIDPtr
++) { 
 783         OSSafeReleaseNULL(theKext
); 
 784         theKext 
= OSKext::lookupKextWithIdentifier(*kextIDPtr
); 
 787             if (kOSReturnSuccess 
!= OSKext::loadKextWithIdentifier( 
 788                 *kextIDPtr
, /* allowDefer */ false)) { 
 790                 // xxx - check KextBookkeeping, might be redundant 
 791                 OSKextLog(/* kext */ NULL
, 
 792                     kOSKextLogErrorLevel 
| 
 793                     kOSKextLogDirectoryScanFlag 
| kOSKextLogKextBookkeepingFlag
, 
 794                     "Failed to initialize kernel component %s.", *kextIDPtr
); 
 795                 result 
= kOSReturnError
; 
 800     OSSafeReleaseNULL(theKext
); 
 804 /********************************************************************* 
 805 * Ensure that Kernel External Components are loaded early in boot, 
 806 * before other kext personalities get sent to the IOCatalogue. These 
 807 * kexts are treated specially because they may provide the implementation 
 808 * for kernel-vended KPI, so they must register themselves before 
 809 * general purpose IOKit probing begins. 
 810 *********************************************************************/ 
 812 #define COM_APPLE_KEC  "com.apple.kec." 
 815 KLDBootstrap::loadKernelExternalComponents(void) 
 817     OSDictionary         
* extensionsDict 
= NULL
;  // must release 
 818     OSCollectionIterator 
* keyIterator    
= NULL
;  // must release 
 819     OSString             
* bundleID       
= NULL
;  // don't release 
 820     OSKext               
* theKext        
= NULL
;  // don't release 
 821     OSBoolean            
* isKernelExternalComponent 
= NULL
;  // don't release 
 823     OSKextLog(/* kext */ NULL
, 
 824         kOSKextLogStepLevel 
| 
 826         "Loading Kernel External Components."); 
 828     extensionsDict 
= OSKext::copyKexts(); 
 829     if (!extensionsDict
) { 
 833     keyIterator 
= OSCollectionIterator::withCollection(extensionsDict
); 
 835         OSKextLog(/* kext */ NULL
, 
 836             kOSKextLogErrorLevel 
| 
 837             kOSKextLogGeneralFlag
, 
 838             "Failed to allocate iterator for Kernel External Components."); 
 842     while ((bundleID 
= OSDynamicCast(OSString
, keyIterator
->getNextObject()))) { 
 844         const char * bundle_id 
= bundleID
->getCStringNoCopy(); 
 846        /* Skip extensions whose bundle IDs don't start with "com.apple.kec.". 
 849             (strncmp(bundle_id
, COM_APPLE_KEC
, CONST_STRLEN(COM_APPLE_KEC
)) != 0)) { 
 854         theKext 
= OSDynamicCast(OSKext
, extensionsDict
->getObject(bundleID
)); 
 859         isKernelExternalComponent 
= OSDynamicCast(OSBoolean
, 
 860             theKext
->getPropertyForHostArch(kAppleKernelExternalComponentKey
)); 
 861         if (isKernelExternalComponent 
&& isKernelExternalComponent
->isTrue()) { 
 862             OSKextLog(/* kext */ NULL
, 
 863                 kOSKextLogStepLevel 
| 
 865                 "Loading kernel external component %s.", bundleID
->getCStringNoCopy()); 
 866             OSKext::loadKextWithIdentifier(bundleID
->getCStringNoCopy(), 
 867                 /* allowDefer */ false); 
 872     OSSafeReleaseNULL(keyIterator
); 
 873     OSSafeReleaseNULL(extensionsDict
); 
 878 /********************************************************************* 
 879  *********************************************************************/ 
 881 KLDBootstrap::readBuiltinPersonalities(void) 
 883     OSObject              
* parsedXML             
= NULL
;  // must release 
 884     OSArray               
* builtinExtensions     
= NULL
;  // do not release 
 885     OSArray               
* allPersonalities      
= NULL
;  // must release 
 886     OSString              
* errorString           
= NULL
;  // must release 
 887     kernel_section_t      
* infosect              
= NULL
;  // do not free 
 888     OSCollectionIterator  
* personalitiesIterator 
= NULL
;  // must release 
 889     unsigned int            count
, i
; 
 891     OSKextLog(/* kext */ NULL
, 
 892         kOSKextLogStepLevel 
| 
 894         "Reading built-in kernel personalities for I/O Kit drivers."); 
 896    /* Look in the __BUILTIN __info segment for an array of Info.plist 
 897     * entries. For each one, extract the personalities dictionary, add 
 898     * it to our array, then push them all (without matching) to 
 899     * the IOCatalogue. This can be used to augment the personalities 
 900     * in gIOKernelConfigTables, especially when linking entire kexts into 
 901     * the mach_kernel image. 
 903     infosect   
= getsectbyname("__BUILTIN", "__info"); 
 909     parsedXML 
= OSUnserializeXML((const char *) (uintptr_t)infosect
->addr
, 
 912         builtinExtensions 
= OSDynamicCast(OSArray
, parsedXML
); 
 914     if (!builtinExtensions
) { 
 915         const char * errorCString 
= "(unknown error)"; 
 917         if (errorString 
&& errorString
->getCStringNoCopy()) { 
 918             errorCString 
= errorString
->getCStringNoCopy(); 
 919         } else if (parsedXML
) { 
 920             errorCString 
= "not an array"; 
 922         OSKextLog(/* kext */ NULL
, 
 923             kOSKextLogErrorLevel 
| 
 925             "Error unserializing built-in personalities: %s.", errorCString
); 
 929     // estimate 3 personalities per Info.plist/kext 
 930     count 
= builtinExtensions
->getCount(); 
 931     allPersonalities 
= OSArray::withCapacity(count 
* 3); 
 933     for (i 
= 0; i 
< count
; i
++) { 
 934         OSDictionary            
* infoDict 
= NULL
;      // do not release 
 935         OSString                
* moduleName 
= NULL
;    // do not release 
 936         OSDictionary            
* personalities
;        // do not release 
 937         OSString                
* personalityName
;      // do not release     
 939         OSSafeReleaseNULL(personalitiesIterator
); 
 941         infoDict 
= OSDynamicCast(OSDictionary
, 
 942             builtinExtensions
->getObject(i
)); 
 947         moduleName 
= OSDynamicCast(OSString
, 
 948             infoDict
->getObject(kCFBundleIdentifierKey
)); 
 953         OSKextLog(/* kext */ NULL
, 
 954             kOSKextLogStepLevel 
| 
 956             "Adding personalities for built-in driver %s:", 
 957             moduleName
->getCStringNoCopy()); 
 959         personalities 
= OSDynamicCast(OSDictionary
, 
 960             infoDict
->getObject("IOKitPersonalities")); 
 961         if (!personalities
) { 
 965         personalitiesIterator 
= OSCollectionIterator::withCollection(personalities
); 
 966         if (!personalitiesIterator
) { 
 967             continue;  // xxx - well really, what can we do? should we panic? 
 970         while ((personalityName 
= OSDynamicCast(OSString
, 
 971             personalitiesIterator
->getNextObject()))) { 
 973             OSDictionary 
* personality 
= OSDynamicCast(OSDictionary
, 
 974                 personalities
->getObject(personalityName
)); 
 976             OSKextLog(/* kext */ NULL
, 
 977                 kOSKextLogDetailLevel 
| 
 979                 "Adding built-in driver personality %s.", 
 980                 personalityName
->getCStringNoCopy()); 
 982                         if (personality 
&& !personality
->getObject(kCFBundleIdentifierKey
)) { 
 983                                 personality
->setObject(kCFBundleIdentifierKey
, moduleName
); 
 985             allPersonalities
->setObject(personality
); 
 989     gIOCatalogue
->addDrivers(allPersonalities
, false); 
 992     OSSafeReleaseNULL(parsedXML
); 
 993     OSSafeReleaseNULL(allPersonalities
); 
 994     OSSafeReleaseNULL(errorString
); 
 995     OSSafeReleaseNULL(personalitiesIterator
); 
1000 #pragma mark Bootstrap Functions 
1002 /********************************************************************* 
1003 * Bootstrap Functions 
1004 *********************************************************************/ 
1005 static void bootstrapRecordStartupExtensions(void) 
1007     sBootstrapObject
.readStartupExtensions(); 
1011 static void bootstrapLoadSecurityExtensions(void) 
1013     sBootstrapObject
.loadSecurityExtensions();