1 /* 2 * Copyright (c) 2000 Apple Inc. All rights reserved. 3 * 4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ 5 * 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. 14 * 15 * Please obtain a copy of the License at 16 * http://www.opensource.apple.com/apsl/ and read it before using this file. 17 * 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. 25 * 26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ 27 */ 28 extern "C" { 29 #include <mach/kmod.h> 30 #include <libkern/kernel_mach_header.h> 31 #include <libkern/prelink.h> 32 } 33 34 #include <libkern/version.h> 35 #include <libkern/c++/OSContainers.h> 36 #include <libkern/OSKextLibPrivate.h> 37 #include <libkern/c++/OSKext.h> 38 #include <IOKit/IOLib.h> 39 #include <IOKit/IORegistryEntry.h> 40 #include <IOKit/IODeviceTreeSupport.h> 41 #include <IOKit/IOCatalogue.h> 42 43 #if PRAGMA_MARK 44 #pragma mark Bootstrap Declarations 45 #endif 46 /********************************************************************* 47 * Bootstrap Declarations 48 * 49 * The ENTIRE point of the libsa/KLD segment is to isolate bootstrap 50 * code from other parts of the kernel, so function symbols are not 51 * exported; rather pointers to those functions are exported. 52 * 53 * xxx - need to think about locking for handling the 'weak' refs. 54 * xxx - do export a non-KLD function that says you've called a 55 * xxx - bootstrap function that has been removed. 56 * 57 * ALL call-ins to this segment of the kernel must be done through 58 * exported pointers. The symbols themselves are private and not to 59 * be linked against. 60 *********************************************************************/ 61 extern "C" { 62 extern void (*record_startup_extensions_function)(void); 63 extern void (*load_security_extensions_function)(void); 64 }; 65 66 static void bootstrapRecordStartupExtensions(void); 67 static void bootstrapLoadSecurityExtensions(void); 68 69 #if PRAGMA_MARK 70 #pragma mark Macros 71 #endif 72 /********************************************************************* 73 * Macros 74 *********************************************************************/ 75 #define CONST_STRLEN(str) (sizeof(str) - 1) 76 77 #if PRAGMA_MARK 78 #pragma mark Kernel Component Kext Identifiers 79 #endif 80 /********************************************************************* 81 * Kernel Component Kext Identifiers 82 * 83 * We could have each kernel resource kext automatically "load" as 84 * it's created, but it's nicer to have them listed in kextstat in 85 * the order of this list. We'll walk through this after setting up 86 * all the boot kexts and have them load up. 87 *********************************************************************/ 88 static const char * sKernelComponentNames[] = { 89 // The kexts for these IDs must have a version matching 'osrelease'. 90 "com.apple.kernel", 91 "com.apple.kpi.bsd", 92 "com.apple.kpi.dsep", 93 "com.apple.kpi.iokit", 94 "com.apple.kpi.libkern", 95 "com.apple.kpi.mach", 96 "com.apple.kpi.private", 97 "com.apple.kpi.unsupported", 98 "com.apple.iokit.IONVRAMFamily", 99 "com.apple.driver.AppleNMI", 100 "com.apple.iokit.IOSystemManagementFamily", 101 "com.apple.iokit.ApplePlatformFamily", 102 103 #if defined(__ppc__) || defined(__i386__) || defined(__arm__) 104 /* These ones are not supported on x86_64 or any newer platforms. 105 * They must be version 7.9.9; check by "com.apple.kernel.", with 106 * the trailing period; "com.apple.kernel" always represents the 107 * current kernel version. 108 */ 109 "com.apple.kernel.6.0", 110 "com.apple.kernel.bsd", 111 "com.apple.kernel.iokit", 112 "com.apple.kernel.libkern", 113 "com.apple.kernel.mach", 114 #endif 115 116 NULL 117 }; 118 119 #if PRAGMA_MARK 120 #pragma mark KLDBootstrap Class 121 #endif 122 /********************************************************************* 123 * KLDBootstrap Class 124 * 125 * We use a C++ class here so that it can be a friend of OSKext and 126 * get at private stuff. We can't hide the class itself, but we can 127 * hide the instance through which we invoke the functions. 128 *********************************************************************/ 129 class KLDBootstrap { 130 friend void bootstrapRecordStartupExtensions(void); 131 friend void bootstrapLoadSecurityExtensions(void); 132 133 private: 134 void readStartupExtensions(void); 135 136 void readPrelinkedExtensions( 137 kernel_section_t * prelinkInfoSect); 138 void readBooterExtensions(void); 139 OSReturn readMkextExtensions( 140 OSString * deviceTreeName, 141 OSData * deviceTreeData); 142 143 OSReturn loadKernelComponentKexts(void); 144 void readBuiltinPersonalities(void); 145 146 void loadSecurityExtensions(void); 147 148 public: 149 KLDBootstrap(void); 150 ~KLDBootstrap(void); 151 }; 152 153 static KLDBootstrap sBootstrapObject; 154 155 /********************************************************************* 156 * Set the function pointers for the entry points into the bootstrap 157 * segment upon C++ static constructor invocation. 158 *********************************************************************/ 159 KLDBootstrap::KLDBootstrap(void) 160 { 161 if (this != &sBootstrapObject) { 162 panic("Attempt to access bootstrap segment."); 163 } 164 record_startup_extensions_function = &bootstrapRecordStartupExtensions; 165 load_security_extensions_function = &bootstrapLoadSecurityExtensions; 166 OSKext::initialize(); 167 } 168 169 /********************************************************************* 170 * Clear the function pointers for the entry points into the bootstrap 171 * segment upon C++ static destructor invocation. 172 *********************************************************************/ 173 KLDBootstrap::~KLDBootstrap(void) 174 { 175 if (this != &sBootstrapObject) { 176 panic("Attempt to access bootstrap segment."); 177 } 178 record_startup_extensions_function = 0; 179 load_security_extensions_function = 0; 180 } 181 182 /********************************************************************* 183 *********************************************************************/ 184 void 185 KLDBootstrap::readStartupExtensions(void) 186 { 187 kernel_section_t * prelinkInfoSect = NULL; // do not free 188 189 OSKextLog(/* kext */ NULL, 190 kOSKextLogProgressLevel | 191 kOSKextLogGeneralFlag | kOSKextLogDirectoryScanFlag | 192 kOSKextLogKextBookkeepingFlag, 193 "Reading startup extensions."); 194 195 /* If the prelink info segment has a nonzero size, we are prelinked 196 * and won't have any individual kexts or mkexts to read. 197 * Otherwise, we need to read kexts or the mkext from what the booter 198 * has handed us. 199 */ 200 prelinkInfoSect = getsectbyname(kPrelinkInfoSegment, kPrelinkInfoSection); 201 if (prelinkInfoSect->size) { 202 readPrelinkedExtensions(prelinkInfoSect); 203 } else { 204 readBooterExtensions(); 205 } 206 207 loadKernelComponentKexts(); 208 readBuiltinPersonalities(); 209 OSKext::sendAllKextPersonalitiesToCatalog(); 210 211 return; 212 } 213 214 /********************************************************************* 215 *********************************************************************/ 216 void 217 KLDBootstrap::readPrelinkedExtensions( 218 kernel_section_t * prelinkInfoSect) 219 { 220 OSArray * infoDictArray = NULL; // do not release 221 OSArray * personalitiesArray = NULL; // do not release 222 OSObject * parsedXML = NULL; // must release 223 OSDictionary * prelinkInfoDict = NULL; // do not release 224 OSString * errorString = NULL; // must release 225 OSKext * theKernel = NULL; // must release 226 227 #if CONFIG_KXLD 228 kernel_section_t * kernelLinkStateSection = NULL; // see code 229 #endif 230 kernel_segment_command_t * prelinkLinkStateSegment = NULL; // see code 231 kernel_segment_command_t * prelinkTextSegment = NULL; // see code 232 kernel_segment_command_t * prelinkInfoSegment = NULL; // see code 233 234 /* We make some copies of data, but if anything fails we're basically 235 * going to fail the boot, so these won't be cleaned up on error. 236 */ 237 void * prelinkData = NULL; // see code 238 void * prelinkCopy = NULL; // see code 239 vm_size_t prelinkLength = 0; 240 #if !__LP64__ && !defined(__arm__) 241 vm_map_offset_t prelinkDataMapOffset = 0; 242 #endif 243 244 kern_return_t mem_result = KERN_SUCCESS; 245 246 OSDictionary * infoDict = NULL; // do not release 247 248 IORegistryEntry * registryRoot = NULL; // do not release 249 OSNumber * prelinkCountObj = NULL; // must release 250 251 u_int i = 0; 252 253 OSKextLog(/* kext */ NULL, 254 kOSKextLogProgressLevel | 255 kOSKextLogDirectoryScanFlag | kOSKextLogArchiveFlag, 256 "Starting from prelinked kernel."); 257 258 /***** 259 * Wrap the kernel link state in-place in an OSData. 260 * This is unnecessary (and the link state may not be present) if the kernel 261 * does not have kxld support because this information is only used for 262 * runtime linking. 263 */ 264 #if CONFIG_KXLD 265 kernelLinkStateSection = getsectbyname(kPrelinkLinkStateSegment, 266 kPrelinkKernelLinkStateSection); 267 if (!kernelLinkStateSection) { 268 OSKextLog(/* kext */ NULL, 269 kOSKextLogErrorLevel | 270 kOSKextLogArchiveFlag, 271 "Can't find prelinked kernel link state."); 272 goto finish; 273 } 274 275 theKernel = OSKext::lookupKextWithIdentifier(kOSKextKernelIdentifier); 276 if (!theKernel) { 277 OSKextLog(/* kext */ NULL, 278 kOSKextLogErrorLevel | 279 kOSKextLogArchiveFlag, 280 "Can't find kernel kext object in prelinked kernel."); 281 goto finish; 282 } 283 284 prelinkData = (void *) kernelLinkStateSection->addr; 285 prelinkLength = kernelLinkStateSection->size; 286 287 mem_result = kmem_alloc_pageable(kernel_map, 288 (vm_offset_t *) &prelinkCopy, prelinkLength); 289 if (mem_result != KERN_SUCCESS) { 290 OSKextLog(/* kext */ NULL, 291 kOSKextLogErrorLevel | 292 kOSKextLogGeneralFlag | kOSKextLogArchiveFlag, 293 "Can't copy prelinked kernel link state."); 294 goto finish; 295 } 296 memcpy(prelinkCopy, prelinkData, prelinkLength); 297 298 theKernel->linkState = OSData::withBytesNoCopy(prelinkCopy, prelinkLength); 299 if (!theKernel->linkState) { 300 OSKextLog(/* kext */ NULL, 301 kOSKextLogErrorLevel | 302 kOSKextLogGeneralFlag | kOSKextLogArchiveFlag, 303 "Can't create prelinked kernel link state wrapper."); 304 goto finish; 305 } 306 theKernel->linkState->setDeallocFunction(osdata_kmem_free); 307 #endif 308 309 prelinkTextSegment = getsegbyname(kPrelinkTextSegment); 310 if (!prelinkTextSegment) { 311 OSKextLog(/* kext */ NULL, 312 kOSKextLogErrorLevel | 313 kOSKextLogDirectoryScanFlag | kOSKextLogArchiveFlag, 314 "Can't find prelinked kexts' text segment."); 315 goto finish; 316 } 317 318 prelinkData = (void *) prelinkTextSegment->vmaddr; 319 prelinkLength = prelinkTextSegment->vmsize; 320 321 #if !__LP64__ 322 /* To enable paging and write/execute protections on the kext 323 * executables, we need to copy them out of the booter-created 324 * memory, reallocate that space with VM, then prelinkCopy them back in. 325 * This isn't necessary on LP64 because kexts have their own VM 326 * region on that architecture model. 327 */ 328 329 mem_result = kmem_alloc(kernel_map, (vm_offset_t *)&prelinkCopy, 330 prelinkLength); 331 if (mem_result != KERN_SUCCESS) { 332 OSKextLog(/* kext */ NULL, 333 kOSKextLogErrorLevel | 334 kOSKextLogGeneralFlag | kOSKextLogArchiveFlag, 335 "Can't copy prelinked kexts' text for VM reassign."); 336 goto finish; 337 } 338 339 /* Copy it out. 340 */ 341 memcpy(prelinkCopy, prelinkData, prelinkLength); 342 343 /* Dump the booter memory. 344 */ 345 ml_static_mfree((vm_offset_t)prelinkData, prelinkLength); 346 347 /* Set up the VM region. 348 */ 349 prelinkDataMapOffset = (vm_map_offset_t)(uintptr_t)prelinkData; 350 mem_result = vm_map_enter_mem_object( 351 kernel_map, 352 &prelinkDataMapOffset, 353 prelinkLength, /* mask */ 0, 354 VM_FLAGS_FIXED | VM_FLAGS_OVERWRITE, 355 (ipc_port_t)NULL, 356 (vm_object_offset_t) 0, 357 /* copy */ FALSE, 358 /* cur_protection */ VM_PROT_ALL, 359 /* max_protection */ VM_PROT_ALL, 360 /* inheritance */ VM_INHERIT_DEFAULT); 361 if ((mem_result != KERN_SUCCESS) || 362 (prelinkTextSegment->vmaddr != prelinkDataMapOffset)) 363 { 364 OSKextLog(/* kext */ NULL, 365 kOSKextLogErrorLevel | 366 kOSKextLogGeneralFlag | kOSKextLogArchiveFlag, 367 "Can't create kexts' text VM entry at 0x%llx, length 0x%x (error 0x%x).", 368 (unsigned long long) prelinkDataMapOffset, prelinkLength, mem_result); 369 goto finish; 370 } 371 prelinkData = (void *)(uintptr_t)prelinkDataMapOffset; 372 373 /* And copy it back. 374 */ 375 memcpy(prelinkData, prelinkCopy, prelinkLength); 376 377 kmem_free(kernel_map, (vm_offset_t)prelinkCopy, prelinkLength); 378 #endif /* !__LP64__ */ 379 380 /* Unserialize the info dictionary from the prelink info section. 381 */ 382 parsedXML = OSUnserializeXML((const char *)prelinkInfoSect->addr, 383 &errorString); 384 if (parsedXML) { 385 prelinkInfoDict = OSDynamicCast(OSDictionary, parsedXML); 386 } 387 if (!prelinkInfoDict) { 388 const char * errorCString = "(unknown error)"; 389 390 if (errorString && errorString->getCStringNoCopy()) { 391 errorCString = errorString->getCStringNoCopy(); 392 } else if (parsedXML) { 393 errorCString = "not a dictionary"; 394 } 395 OSKextLog(/* kext */ NULL, kOSKextLogErrorLevel | kOSKextLogArchiveFlag, 396 "Error unserializing prelink plist: %s.", errorCString); 397 goto finish; 398 } 399 400 infoDictArray = OSDynamicCast(OSArray, 401 prelinkInfoDict->getObject(kPrelinkInfoDictionaryKey)); 402 if (!infoDictArray) { 403 OSKextLog(/* kext */ NULL, kOSKextLogErrorLevel | kOSKextLogArchiveFlag, 404 "The prelinked kernel has no kext info dictionaries"); 405 goto finish; 406 } 407 408 /* Create OSKext objects for each info dictionary. 409 */ 410 for (i = 0; i < infoDictArray->getCount(); ++i) { 411 infoDict = OSDynamicCast(OSDictionary, infoDictArray->getObject(i)); 412 if (!infoDict) { 413 OSKextLog(/* kext */ NULL, 414 kOSKextLogErrorLevel | 415 kOSKextLogDirectoryScanFlag | kOSKextLogArchiveFlag, 416 "Can't find info dictionary for prelinked kext #%d.", i); 417 continue; 418 } 419 420 /* Create the kext for the entry, then release it, because the 421 * kext system keeps them around until explicitly removed. 422 * Any creation/registration failures are already logged for us. 423 */ 424 OSKext * newKext = OSKext::withPrelinkedInfoDict(infoDict); 425 OSSafeReleaseNULL(newKext); 426 } 427 428 /* Get all of the personalities for kexts that were not prelinked and 429 * add them to the catalogue. 430 */ 431 personalitiesArray = OSDynamicCast(OSArray, 432 prelinkInfoDict->getObject(kPrelinkPersonalitiesKey)); 433 if (!personalitiesArray) { 434 OSKextLog(/* kext */ NULL, kOSKextLogErrorLevel | kOSKextLogArchiveFlag, 435 "The prelinked kernel has no personalities array"); 436 goto finish; 437 } 438 439 if (personalitiesArray->getCount()) { 440 gIOCatalogue->addDrivers(personalitiesArray); 441 } 442 443 /* Store the number of prelinked kexts in the registry so we can tell 444 * when the system has been started from a prelinked kernel. 445 */ 446 registryRoot = IORegistryEntry::getRegistryRoot(); 447 assert(registryRoot); 448 449 prelinkCountObj = OSNumber::withNumber( 450 (unsigned long long)infoDictArray->getCount(), 451 8 * sizeof(uint32_t)); 452 assert(prelinkCountObj); 453 if (prelinkCountObj) { 454 registryRoot->setProperty(kOSPrelinkKextCountKey, prelinkCountObj); 455 } 456 457 OSSafeReleaseNULL(prelinkCountObj); 458 prelinkCountObj = OSNumber::withNumber( 459 (unsigned long long)personalitiesArray->getCount(), 460 8 * sizeof(uint32_t)); 461 assert(prelinkCountObj); 462 if (prelinkCountObj) { 463 registryRoot->setProperty(kOSPrelinkPersonalityCountKey, prelinkCountObj); 464 } 465 466 OSKextLog(/* kext */ NULL, 467 kOSKextLogProgressLevel | 468 kOSKextLogGeneralFlag | kOSKextLogKextBookkeepingFlag | 469 kOSKextLogDirectoryScanFlag | kOSKextLogArchiveFlag, 470 "%u prelinked kexts, and %u additional personalities.", 471 infoDictArray->getCount(), personalitiesArray->getCount()); 472 473 #if __LP64__ 474 /* On LP64 systems, kexts are copied to their own special VM region 475 * during OSKext init time, so we can free the whole segment now. 476 */ 477 ml_static_mfree((vm_offset_t) prelinkData, prelinkLength); 478 #endif /* __LP64__ */ 479 480 /* Free the link state segment, kexts have copied out what they need. 481 */ 482 prelinkLinkStateSegment = getsegbyname(kPrelinkLinkStateSegment); 483 if (prelinkLinkStateSegment) { 484 ml_static_mfree((vm_offset_t)prelinkLinkStateSegment->vmaddr, 485 (vm_size_t)prelinkLinkStateSegment->vmsize); 486 } 487 488 /* Free the prelink info segment, we're done with it. 489 */ 490 prelinkInfoSegment = getsegbyname(kPrelinkInfoSegment); 491 if (prelinkInfoSegment) { 492 ml_static_mfree((vm_offset_t)prelinkInfoSegment->vmaddr, 493 (vm_size_t)prelinkInfoSegment->vmsize); 494 } 495 496 finish: 497 OSSafeRelease(errorString); 498 OSSafeRelease(parsedXML); 499 OSSafeRelease(theKernel); 500 OSSafeRelease(prelinkCountObj); 501 return; 502 } 503 504 /********************************************************************* 505 *********************************************************************/ 506 #define BOOTER_KEXT_PREFIX "Driver-" 507 #define BOOTER_MKEXT_PREFIX "DriversPackage-" 508 509 typedef struct _DeviceTreeBuffer { 510 uint32_t paddr; 511 uint32_t length; 512 } _DeviceTreeBuffer; 513 514 void 515 KLDBootstrap::readBooterExtensions(void) 516 { 517 IORegistryEntry * booterMemoryMap = NULL; // must release 518 OSDictionary * propertyDict = NULL; // must release 519 OSCollectionIterator * keyIterator = NULL; // must release 520 OSString * deviceTreeName = NULL; // do not release 521 522 const _DeviceTreeBuffer * deviceTreeBuffer = NULL; // do not free 523 char * booterDataPtr = NULL; // do not free 524 OSData * booterData = NULL; // must release 525 526 OSKext * aKext = NULL; // must release 527 528 OSKextLog(/* kext */ NULL, 529 kOSKextLogProgressLevel | 530 kOSKextLogDirectoryScanFlag | kOSKextLogKextBookkeepingFlag, 531 "Reading startup extensions/mkexts from booter memory."); 532 533 booterMemoryMap = IORegistryEntry::fromPath( "/chosen/memory-map", gIODTPlane); 534 535 if (!booterMemoryMap) { 536 OSKextLog(/* kext */ NULL, 537 kOSKextLogErrorLevel | 538 kOSKextLogGeneralFlag | kOSKextLogDirectoryScanFlag, 539 "Can't read booter memory map."); 540 goto finish; 541 } 542 543 propertyDict = booterMemoryMap->dictionaryWithProperties(); 544 if (!propertyDict) { 545 OSKextLog(/* kext */ NULL, 546 kOSKextLogErrorLevel | 547 kOSKextLogDirectoryScanFlag, 548 "Can't get property dictionary from memory map."); 549 goto finish; 550 } 551 552 keyIterator = OSCollectionIterator::withCollection(propertyDict); 553 if (!keyIterator) { 554 OSKextLog(/* kext */ NULL, 555 kOSKextLogErrorLevel | 556 kOSKextLogGeneralFlag, 557 "Can't allocate iterator for driver images."); 558 goto finish; 559 } 560 561 while ( ( deviceTreeName = 562 OSDynamicCast(OSString, keyIterator->getNextObject() ))) { 563 564 boolean_t isMkext = FALSE; 565 const char * devTreeNameCString = deviceTreeName->getCStringNoCopy(); 566 OSData * deviceTreeEntry = OSDynamicCast(OSData, 567 propertyDict->getObject(deviceTreeName)); 568 569 /* Clear out the booterData from the prior iteration. 570 */ 571 OSSafeReleaseNULL(booterData); 572 573 /* If there is no entry for the name, we can't do much with it. */ 574 if (!deviceTreeEntry) { 575 continue; 576 } 577 578 /* Make sure it is either a kext or an mkext */ 579 if (!strncmp(devTreeNameCString, BOOTER_KEXT_PREFIX, 580 CONST_STRLEN(BOOTER_KEXT_PREFIX))) { 581 582 isMkext = FALSE; 583 584 } else if (!strncmp(devTreeNameCString, BOOTER_MKEXT_PREFIX, 585 CONST_STRLEN(BOOTER_MKEXT_PREFIX))) { 586 587 isMkext = TRUE; 588 589 } else { 590 continue; 591 } 592 593 deviceTreeBuffer = (const _DeviceTreeBuffer *) 594 deviceTreeEntry->getBytesNoCopy(0, sizeof(deviceTreeBuffer)); 595 if (!deviceTreeBuffer) { 596 /* We can't get to the data, so we can't do anything, 597 * not even free it from physical memory (if it's there). 598 */ 599 OSKextLog(/* kext */ NULL, 600 kOSKextLogErrorLevel | 601 kOSKextLogDirectoryScanFlag, 602 "Device tree entry %s has NULL pointer.", 603 devTreeNameCString); 604 goto finish; // xxx - continue, panic? 605 } 606 607 booterDataPtr = (char *)ml_static_ptovirt(deviceTreeBuffer->paddr); 608 if (!booterDataPtr) { 609 OSKextLog(/* kext */ NULL, 610 kOSKextLogErrorLevel | 611 kOSKextLogDirectoryScanFlag, 612 "Can't get virtual address for device tree mkext entry %s.", 613 devTreeNameCString); 614 goto finish; 615 } 616 617 /* Wrap the booter data buffer in an OSData and set a dealloc function 618 * so it will take care of the physical memory when freed. Kexts will 619 * retain the booterData for as long as they need it. Remove the entry 620 * from the booter memory map after this is done. 621 */ 622 booterData = OSData::withBytesNoCopy(booterDataPtr, 623 deviceTreeBuffer->length); 624 if (!booterData) { 625 OSKextLog(/* kext */ NULL, 626 kOSKextLogErrorLevel | 627 kOSKextLogGeneralFlag, 628 "Error - Can't allocate OSData wrapper for device tree entry %s.", 629 devTreeNameCString); 630 goto finish; 631 } 632 booterData->setDeallocFunction(osdata_phys_free); 633 634 if (isMkext) { 635 readMkextExtensions(deviceTreeName, booterData); 636 } else { 637 /* Create the kext for the entry, then release it, because the 638 * kext system keeps them around until explicitly removed. 639 * Any creation/registration failures are already logged for us. 640 */ 641 OSKext * newKext = OSKext::withBooterData(deviceTreeName, booterData); 642 OSSafeRelease(newKext); 643 } 644 645 booterMemoryMap->removeProperty(deviceTreeName); 646 647 } /* while ( (deviceTreeName = OSDynamicCast(OSString, ...) ) ) */ 648 649 finish: 650 651 OSSafeRelease(booterMemoryMap); 652 OSSafeRelease(propertyDict); 653 OSSafeRelease(keyIterator); 654 OSSafeRelease(booterData); 655 OSSafeRelease(aKext); 656 return; 657 } 658 659 /********************************************************************* 660 *********************************************************************/ 661 OSReturn 662 KLDBootstrap::readMkextExtensions( 663 OSString * deviceTreeName, 664 OSData * booterData) 665 { 666 OSReturn result = kOSReturnError; 667 668 uint32_t checksum; 669 IORegistryEntry * registryRoot = NULL; // do not release 670 OSData * checksumObj = NULL; // must release 671 672 OSKextLog(/* kext */ NULL, 673 kOSKextLogStepLevel | 674 kOSKextLogDirectoryScanFlag | kOSKextLogArchiveFlag, 675 "Reading startup mkext archive from device tree entry %s.", 676 deviceTreeName->getCStringNoCopy()); 677 678 /* If we successfully read the archive, 679 * then save the mkext's checksum in the IORegistry. 680 * assumes we'll only ever have one mkext to boot 681 */ 682 result = OSKext::readMkextArchive(booterData, &checksum); 683 if (result == kOSReturnSuccess) { 684 685 OSKextLog(/* kext */ NULL, 686 kOSKextLogProgressLevel | 687 kOSKextLogArchiveFlag, 688 "Startup mkext archive has checksum 0x%x.", (int)checksum); 689 690 registryRoot = IORegistryEntry::getRegistryRoot(); 691 assert(registryRoot); 692 checksumObj = OSData::withBytes((void *)&checksum, sizeof(checksum)); 693 assert(checksumObj); 694 if (checksumObj) { 695 registryRoot->setProperty(kOSStartupMkextCRC, checksumObj); 696 } 697 } 698 699 return result; 700 } 701 702 /********************************************************************* 703 *********************************************************************/ 704 #define COM_APPLE "com.apple." 705 706 void 707 KLDBootstrap::loadSecurityExtensions(void) 708 { 709 OSDictionary * extensionsDict = NULL; // must release 710 OSCollectionIterator * keyIterator = NULL; // must release 711 OSString * bundleID = NULL; // don't release 712 OSKext * theKext = NULL; // don't release 713 OSBoolean * isSecurityKext = NULL; // don't release 714 715 OSKextLog(/* kext */ NULL, 716 kOSKextLogStepLevel | 717 kOSKextLogLoadFlag, 718 "Loading security extensions."); 719 720 extensionsDict = OSKext::copyKexts(); 721 if (!extensionsDict) { 722 return; 723 } 724 725 keyIterator = OSCollectionIterator::withCollection(extensionsDict); 726 if (!keyIterator) { 727 OSKextLog(/* kext */ NULL, 728 kOSKextLogErrorLevel | 729 kOSKextLogGeneralFlag, 730 "Failed to allocate iterator for security extensions."); 731 goto finish; 732 } 733 734 while ((bundleID = OSDynamicCast(OSString, keyIterator->getNextObject()))) { 735 736 const char * bundle_id = bundleID->getCStringNoCopy(); 737 738 /* Skip extensions whose bundle IDs don't start with "com.apple.". 739 */ 740 if (!bundle_id || 741 (strncmp(bundle_id, COM_APPLE, CONST_STRLEN(COM_APPLE)) != 0)) { 742 743 continue; 744 } 745 746 theKext = OSDynamicCast(OSKext, extensionsDict->getObject(bundleID)); 747 if (!theKext) { 748 continue; 749 } 750 751 isSecurityKext = OSDynamicCast(OSBoolean, 752 theKext->getPropertyForHostArch("AppleSecurityExtension")); 753 if (isSecurityKext && isSecurityKext->isTrue()) { 754 OSKextLog(/* kext */ NULL, 755 kOSKextLogStepLevel | 756 kOSKextLogLoadFlag, 757 "Loading security extension %s.", bundleID->getCStringNoCopy()); 758 OSKext::loadKextWithIdentifier(bundleID->getCStringNoCopy(), 759 /* allowDefer */ false); 760 } 761 } 762 763 finish: 764 OSSafeRelease(keyIterator); 765 OSSafeRelease(extensionsDict); 766 767 return; 768 } 769 770 /********************************************************************* 771 * We used to require that all listed kernel components load, but 772 * nowadays we can get them from userland so we only try to load the 773 * ones we have. If an error occurs later, such is life. 774 * 775 * Note that we look the kexts up first, so we can avoid spurious 776 * (in this context, anyhow) log messages about kexts not being found. 777 * 778 * xxx - do we even need to do this any more? Check if the kernel 779 * xxx - compoonents just load in the regular paths 780 *********************************************************************/ 781 OSReturn 782 KLDBootstrap::loadKernelComponentKexts(void) 783 { 784 OSReturn result = kOSReturnSuccess; // optimistic 785 OSKext * theKext = NULL; // must release 786 const char ** kextIDPtr = NULL; // do not release 787 788 for (kextIDPtr = &sKernelComponentNames[0]; *kextIDPtr; kextIDPtr++) { 789 790 OSSafeReleaseNULL(theKext); 791 theKext = OSKext::lookupKextWithIdentifier(*kextIDPtr); 792 793 if (theKext) { 794 if (kOSReturnSuccess != OSKext::loadKextWithIdentifier( 795 *kextIDPtr, /* allowDefer */ false)) { 796 797 // xxx - check KextBookkeeping, might be redundant 798 OSKextLog(/* kext */ NULL, 799 kOSKextLogErrorLevel | 800 kOSKextLogDirectoryScanFlag | kOSKextLogKextBookkeepingFlag, 801 "Failed to initialize kernel component %s.", *kextIDPtr); 802 result = kOSReturnError; 803 } 804 } 805 } 806 807 OSSafeRelease(theKext); 808 return result; 809 } 810 811 /********************************************************************* 812 *********************************************************************/ 813 void 814 KLDBootstrap::readBuiltinPersonalities(void) 815 { 816 OSObject * parsedXML = NULL; // must release 817 OSArray * builtinExtensions = NULL; // do not release 818 OSArray * allPersonalities = NULL; // must release 819 OSString * errorString = NULL; // must release 820 kernel_section_t * infosect = NULL; // do not free 821 OSCollectionIterator * personalitiesIterator = NULL; // must release 822 unsigned int count, i; 823 824 OSKextLog(/* kext */ NULL, 825 kOSKextLogStepLevel | 826 kOSKextLogLoadFlag, 827 "Reading built-in kernel personalities for I/O Kit drivers."); 828 829 /* Look in the __BUILTIN __info segment for an array of Info.plist 830 * entries. For each one, extract the personalities dictionary, add 831 * it to our array, then push them all (without matching) to 832 * the IOCatalogue. This can be used to augment the personalities 833 * in gIOKernelConfigTables, especially when linking entire kexts into 834 * the mach_kernel image. 835 */ 836 infosect = getsectbyname("__BUILTIN", "__info"); 837 if (!infosect) { 838 // this isn't fatal 839 goto finish; 840 } 841 842 parsedXML = OSUnserializeXML((const char *) (uintptr_t)infosect->addr, 843 &errorString); 844 if (parsedXML) { 845 builtinExtensions = OSDynamicCast(OSArray, parsedXML); 846 } 847 if (!builtinExtensions) { 848 const char * errorCString = "(unknown error)"; 849 850 if (errorString && errorString->getCStringNoCopy()) { 851 errorCString = errorString->getCStringNoCopy(); 852 } else if (parsedXML) { 853 errorCString = "not an array"; 854 } 855 OSKextLog(/* kext */ NULL, 856 kOSKextLogErrorLevel | 857 kOSKextLogLoadFlag, 858 "Error unserializing built-in personalities: %s.", errorCString); 859 goto finish; 860 } 861 862 // estimate 3 personalities per Info.plist/kext 863 count = builtinExtensions->getCount(); 864 allPersonalities = OSArray::withCapacity(count * 3); 865 866 for (i = 0; i < count; i++) { 867 OSDictionary * infoDict = NULL; // do not release 868 OSString * moduleName = NULL; // do not release 869 OSDictionary * personalities; // do not release 870 OSString * personalityName; // do not release 871 872 OSSafeReleaseNULL(personalitiesIterator); 873 874 infoDict = OSDynamicCast(OSDictionary, 875 builtinExtensions->getObject(i)); 876 if (!infoDict) { 877 continue; 878 } 879 880 moduleName = OSDynamicCast(OSString, 881 infoDict->getObject(kCFBundleIdentifierKey)); 882 if (!moduleName) { 883 continue; 884 } 885 886 OSKextLog(/* kext */ NULL, 887 kOSKextLogStepLevel | 888 kOSKextLogLoadFlag, 889 "Adding personalities for built-in driver %s:", 890 moduleName->getCStringNoCopy()); 891 892 personalities = OSDynamicCast(OSDictionary, 893 infoDict->getObject("IOKitPersonalities")); 894 if (!personalities) { 895 continue; 896 } 897 898 personalitiesIterator = OSCollectionIterator::withCollection(personalities); 899 if (!personalitiesIterator) { 900 continue; // xxx - well really, what can we do? should we panic? 901 } 902 903 while ((personalityName = OSDynamicCast(OSString, 904 personalitiesIterator->getNextObject()))) { 905 906 OSDictionary * personality = OSDynamicCast(OSDictionary, 907 personalities->getObject(personalityName)); 908 909 OSKextLog(/* kext */ NULL, 910 kOSKextLogDetailLevel | 911 kOSKextLogLoadFlag, 912 "Adding built-in driver personality %s.", 913 personalityName->getCStringNoCopy()); 914 915 if (personality && !personality->getObject(kCFBundleIdentifierKey)) { 916 personality->setObject(kCFBundleIdentifierKey, moduleName); 917 } 918 allPersonalities->setObject(personality); 919 } 920 } 921 922 gIOCatalogue->addDrivers(allPersonalities, false); 923 924 finish: 925 OSSafeRelease(parsedXML); 926 OSSafeRelease(allPersonalities); 927 OSSafeRelease(errorString); 928 OSSafeRelease(personalitiesIterator); 929 return; 930 } 931 932 #if PRAGMA_MARK 933 #pragma mark Bootstrap Functions 934 #endif 935 /********************************************************************* 936 * Bootstrap Functions 937 *********************************************************************/ 938 static void bootstrapRecordStartupExtensions(void) 939 { 940 sBootstrapObject.readStartupExtensions(); 941 return; 942 } 943 944 static void bootstrapLoadSecurityExtensions(void) 945 { 946 sBootstrapObject.loadSecurityExtensions(); 947 return; 948 } 949