1/* 2 * Copyright (c) 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#include <libkern/c++/OSContainers.h> 23#include <IOKit/IODeviceTreeSupport.h> 24#include <IOKit/IORegistryEntry.h> 25#include <IOKit/IOCatalogue.h> 26#include <libkern/c++/OSUnserialize.h> 27#include <libkern/OSByteOrder.h> 28#include <libsa/catalogue.h> 29 30extern "C" { 31#include <machine/machine_routines.h> 32#include <mach/host_info.h> 33#include <mach/kmod.h> 34#include <libsa/mkext.h> 35#include <libsa/vers_rsrc.h> 36#include <mach-o/loader.h> 37}; 38 39#include <IOKit/IOLib.h> 40 41#include <IOKit/assert.h> 42 43extern "C" { 44extern void IODTFreeLoaderInfo( char *key, void *infoAddr, int infoSize ); 45// extern kern_return_t host_info(host_t host, 46// host_flavor_t flavor, 47// host_info_t info, 48// mach_msg_type_number_t *count); 49extern int grade_binary(cpu_type_t exectype, cpu_subtype_t execsubtype); 50// Return the address of the named Mach-O segment from the currently 51// executing 32 bit kernel, or NULL. 52extern struct segment_command *getsegbyname(char *seg_name); 53// Return the address of the named section from the named Mach-O segment 54// from the currently executing 32 bit kernel, or NULL. 55extern struct section *getsectbyname(char *segname, char *sectname); 56}; 57 58#define LOG_DELAY() 59 60#if 0 61#define VTYELLOW "\033[33m" 62#define VTRESET "\033[0m" 63#else 64#define VTYELLOW "" 65#define VTRESET "" 66#endif 67 68/********************************************************************* 69*********************************************************************/ 70static OSDictionary * gStartupExtensions = 0; 71static OSArray * gBootLoaderObjects = 0; 72extern OSArray * gIOPrelinkedModules; 73 74OSDictionary * getStartupExtensions(void) { 75 if (gStartupExtensions) { 76 return gStartupExtensions; 77 } 78 gStartupExtensions = OSDictionary::withCapacity(1); 79 assert (gStartupExtensions); 80 81 return gStartupExtensions; 82} 83 84/* This array holds objects that are needed to be held around during 85 * boot before kextd starts up. Currently it contains OSData objects 86 * copied from OF entries for mkext archives in device ROMs. Because 87 * the Device Tree support code dumps these after initially handing 88 * them to us, we have to be able to clean them up later. 89 */ 90OSArray * getBootLoaderObjects(void) { 91 if (gBootLoaderObjects) { 92 return gBootLoaderObjects; 93 } 94 gBootLoaderObjects = OSArray::withCapacity(1); 95 assert (gBootLoaderObjects); 96 97 return gBootLoaderObjects; 98} 99 100/********************************************************************* 101* This function checks that a driver dict has all the required 102* entries and does a little bit of value checking too. 103* 104* index is nonnegative if the index of an entry from an mkext 105* archive. 106*********************************************************************/ 107bool validateExtensionDict(OSDictionary * extension, int index) { 108 109 bool result = true; 110 bool not_a_dict = false; 111 bool id_missing = false; 112 bool is_kernel_resource = false; 113 bool has_executable = false; 114 OSString * bundleIdentifier = NULL; // do not release 115 OSObject * rawValue = NULL; // do not release 116 OSString * stringValue = NULL; // do not release 117 OSBoolean * booleanValue = NULL; // do not release 118 OSDictionary * personalities = NULL; // do not release 119 OSDictionary * libraries = NULL; // do not release 120 OSCollectionIterator * keyIterator = NULL; // must release 121 OSString * key = NULL; // do not release 122 VERS_version vers; 123 VERS_version compatible_vers; 124 125 // Info dict is a dictionary 126 if (!OSDynamicCast(OSDictionary, extension)) { 127 not_a_dict = true; 128 result = false; 129 goto finish; 130 } 131 132 // CFBundleIdentifier is a string - REQUIRED 133 bundleIdentifier = OSDynamicCast(OSString, 134 extension->getObject("CFBundleIdentifier")); 135 if (!bundleIdentifier) { 136 id_missing = true; 137 result = false; 138 goto finish; 139 } 140 141 // Length of CFBundleIdentifier is not >= KMOD_MAX_NAME 142 if (bundleIdentifier->getLength() >= KMOD_MAX_NAME) { 143 result = false; 144 goto finish; 145 } 146 147 // CFBundlePackageType is "KEXT" - REQUIRED 148 stringValue = OSDynamicCast(OSString, 149 extension->getObject("CFBundlePackageType")); 150 if (!stringValue) { 151 result = false; 152 goto finish; 153 } 154 if (!stringValue->isEqualTo("KEXT")) { 155 result = false; 156 goto finish; 157 } 158 159 // CFBundleVersion is a string - REQUIRED 160 stringValue = OSDynamicCast(OSString, 161 extension->getObject("CFBundleVersion")); 162 if (!stringValue) { 163 result = false; 164 goto finish; 165 } 166 // CFBundleVersion is of valid form 167 vers = VERS_parse_string(stringValue->getCStringNoCopy()); 168 if (vers < 0) { 169 result = false; 170 goto finish; 171 } 172 173 // OSBundleCompatibleVersion is a string - OPTIONAL 174 rawValue = extension->getObject("OSBundleCompatibleVersion"); 175 if (rawValue) { 176 stringValue = OSDynamicCast(OSString, rawValue); 177 if (!stringValue) { 178 result = false; 179 goto finish; 180 } 181 182 // OSBundleCompatibleVersion is of valid form 183 compatible_vers = VERS_parse_string(stringValue->getCStringNoCopy()); 184 if (compatible_vers < 0) { 185 result = false; 186 goto finish; 187 } 188 189 // OSBundleCompatibleVersion <= CFBundleVersion 190 if (compatible_vers > vers) { 191 result = false; 192 goto finish; 193 } 194 } 195 196 // CFBundleExecutable is a string - OPTIONAL 197 rawValue = extension->getObject("CFBundleExecutable"); 198 if (rawValue) { 199 stringValue = OSDynamicCast(OSString, rawValue); 200 if (!stringValue || stringValue->getLength() == 0) { 201 result = false; 202 goto finish; 203 } 204 has_executable = true; 205 } 206 207 // OSKernelResource is a boolean value - OPTIONAL 208 rawValue = extension->getObject("OSKernelResource"); 209 if (rawValue) { 210 booleanValue = OSDynamicCast(OSBoolean, rawValue); 211 if (!booleanValue) { 212 result = false; 213 goto finish; 214 } 215 is_kernel_resource = booleanValue->isTrue(); 216 } 217 218 // IOKitPersonalities is a dictionary - OPTIONAL 219 rawValue = extension->getObject("IOKitPersonalities"); 220 if (rawValue) { 221 personalities = OSDynamicCast(OSDictionary, rawValue); 222 if (!personalities) { 223 result = false; 224 goto finish; 225 } 226 227 keyIterator = OSCollectionIterator::withCollection(personalities); 228 if (!keyIterator) { 229 IOLog("Error: Failed to allocate iterator for personalities.\n"); 230 LOG_DELAY(); 231 result = false; 232 goto finish; 233 } 234 235 while ((key = OSDynamicCast(OSString, keyIterator->getNextObject()))) { 236 OSDictionary * personality = NULL; // do not release 237 238 // Each personality is a dictionary 239 personality = OSDynamicCast(OSDictionary, 240 personalities->getObject(key)); 241 if (!personality) { 242 result = false; 243 goto finish; 244 } 245 246 // IOClass exists as a string - REQUIRED 247 if (!OSDynamicCast(OSString, personality->getObject("IOClass"))) { 248 result = false; 249 goto finish; 250 } 251 252 // IOProviderClass exists as a string - REQUIRED 253 if (!OSDynamicCast(OSString, 254 personality->getObject("IOProviderClass"))) { 255 256 result = false; 257 goto finish; 258 } 259 260 // CFBundleIdentifier is a string - OPTIONAL - INSERT IF ABSENT! 261 rawValue = personality->getObject("CFBundleIdentifier"); 262 if (!rawValue) { 263 personality->setObject("CFBundleIdentifier", bundleIdentifier); 264 } else { 265 OSString * personalityID = NULL; // do not release 266 personalityID = OSDynamicCast(OSString, rawValue); 267 if (!personalityID) { 268 result = false; 269 goto finish; 270 } else { 271 // Length of CFBundleIdentifier is not >= KMOD_MAX_NAME 272 if (personalityID->getLength() >= KMOD_MAX_NAME) { 273 result = false; 274 goto finish; 275 } 276 } 277 } 278 279 // IOKitDebug is a number - OPTIONAL 280 rawValue = personality->getObject("IOKitDebug"); 281 if (rawValue && !OSDynamicCast(OSNumber, rawValue)) { 282 result = false; 283 goto finish; 284 } 285 } 286 287 keyIterator->release(); 288 keyIterator = NULL; 289 } 290 291 292 // OSBundleLibraries is a dictionary - REQUIRED if 293 // not kernel resource & has executable 294 // 295 rawValue = extension->getObject("OSBundleLibraries"); 296 if (!rawValue && !is_kernel_resource && has_executable) { 297 result = false; 298 goto finish; 299 } 300 301 if (rawValue) { 302 libraries = OSDynamicCast(OSDictionary, rawValue); 303 if (!libraries) { 304 result = false; 305 goto finish; 306 } 307 308 keyIterator = OSCollectionIterator::withCollection(libraries); 309 if (!keyIterator) { 310 IOLog("Error: Failed to allocate iterator for libraries.\n"); 311 LOG_DELAY(); 312 result = false; 313 goto finish; 314 } 315 316 while ((key = OSDynamicCast(OSString, 317 keyIterator->getNextObject()))) { 318 319 OSString * libraryVersion = NULL; // do not release 320 321 // Each key's length is not >= KMOD_MAX_NAME 322 if (key->getLength() >= KMOD_MAX_NAME) { 323 result = false; 324 goto finish; 325 } 326 327 libraryVersion = OSDynamicCast(OSString, 328 libraries->getObject(key)); 329 if (!libraryVersion) { 330 result = false; 331 goto finish; 332 } 333 334 // Each value is a valid version string 335 vers = VERS_parse_string(libraryVersion->getCStringNoCopy()); 336 if (vers < 0) { 337 result = false; 338 goto finish; 339 } 340 } 341 342 keyIterator->release(); 343 keyIterator = NULL; 344 } 345 346 // OSBundleRequired is a legal value - *not* required at boot time 347 // so we can do install CDs and the like with mkext files containing 348 // all normally-used drivers. 349 rawValue = extension->getObject("OSBundleRequired"); 350 if (rawValue) { 351 stringValue = OSDynamicCast(OSString, rawValue); 352 if (!stringValue) { 353 result = false; 354 goto finish; 355 } 356 if (!stringValue->isEqualTo("Root") && 357 !stringValue->isEqualTo("Local-Root") && 358 !stringValue->isEqualTo("Network-Root") && 359 !stringValue->isEqualTo("Safe Boot") && 360 !stringValue->isEqualTo("Console")) { 361 362 result = false; 363 goto finish; 364 } 365 366 } 367 368 369finish: 370 if (keyIterator) keyIterator->release(); 371 372 if (!result) { 373 if (not_a_dict) { 374 if (index > -1) { 375 IOLog(VTYELLOW "mkext entry %d:." VTRESET, index); 376 } else { 377 IOLog(VTYELLOW "kernel extension" VTRESET); 378 } 379 IOLog(VTYELLOW "info dictionary isn't a dictionary\n" 380 VTRESET); 381 } else if (id_missing) { 382 if (index > -1) { 383 IOLog(VTYELLOW "mkext entry %d:." VTRESET, index); 384 } else { 385 IOLog(VTYELLOW "kernel extension" VTRESET); 386 } 387 IOLog(VTYELLOW "\"CFBundleIdentifier\" property is " 388 "missing or not a string\n" 389 VTRESET); 390 } else { 391 IOLog(VTYELLOW "kernel extension \"%s\": info dictionary is invalid\n" 392 VTRESET, bundleIdentifier->getCStringNoCopy()); 393 } 394 LOG_DELAY(); 395 } 396 397 return result; 398} 399 400 401/********************************************************************* 402*********************************************************************/ 403OSDictionary * compareExtensionVersions( 404 OSDictionary * incumbent, 405 OSDictionary * candidate) { 406 407 OSDictionary * winner = NULL; 408 409 OSDictionary * incumbentPlist = NULL; 410 OSDictionary * candidatePlist = NULL; 411 OSString * incumbentName = NULL; 412 OSString * candidateName = NULL; 413 OSString * incumbentVersionString = NULL; 414 OSString * candidateVersionString = NULL; 415 VERS_version incumbent_vers = 0; 416 VERS_version candidate_vers = 0; 417 418 incumbentPlist = OSDynamicCast(OSDictionary, 419 incumbent->getObject("plist")); 420 candidatePlist = OSDynamicCast(OSDictionary, 421 candidate->getObject("plist")); 422 423 if (!incumbentPlist || !candidatePlist) { 424 IOLog("compareExtensionVersions() called with invalid " 425 "extension dictionaries.\n"); 426 LOG_DELAY(); 427 winner = NULL; 428 goto finish; 429 } 430 431 incumbentName = OSDynamicCast(OSString, 432 incumbentPlist->getObject("CFBundleIdentifier")); 433 candidateName = OSDynamicCast(OSString, 434 candidatePlist->getObject("CFBundleIdentifier")); 435 incumbentVersionString = OSDynamicCast(OSString, 436 incumbentPlist->getObject("CFBundleVersion")); 437 candidateVersionString = OSDynamicCast(OSString, 438 candidatePlist->getObject("CFBundleVersion")); 439 440 if (!incumbentName || !candidateName || 441 !incumbentVersionString || !candidateVersionString) { 442 443 IOLog("compareExtensionVersions() called with invalid " 444 "extension dictionaries.\n"); 445 LOG_DELAY(); 446 winner = NULL; 447 goto finish; 448 } 449 450 if (strcmp(incumbentName->getCStringNoCopy(), 451 candidateName->getCStringNoCopy())) { 452 453 IOLog("compareExtensionVersions() called with different " 454 "extension names (%s and %s).\n", 455 incumbentName->getCStringNoCopy(), 456 candidateName->getCStringNoCopy()); 457 LOG_DELAY(); 458 winner = NULL; 459 goto finish; 460 } 461 462 incumbent_vers = VERS_parse_string(incumbentVersionString->getCStringNoCopy()); 463 if (incumbent_vers < 0) { 464 465 IOLog(VTYELLOW "Error parsing version string for extension %s (%s)\n" 466 VTRESET, 467 incumbentName->getCStringNoCopy(), 468 incumbentVersionString->getCStringNoCopy()); 469 LOG_DELAY(); 470 winner = NULL; 471 goto finish; 472 } 473 474 candidate_vers = VERS_parse_string(candidateVersionString->getCStringNoCopy()); 475 if (candidate_vers < 0) { 476 477 IOLog(VTYELLOW "Error parsing version string for extension %s (%s)\n" 478 VTRESET, 479 candidateName->getCStringNoCopy(), 480 candidateVersionString->getCStringNoCopy()); 481 LOG_DELAY(); 482 winner = NULL; 483 goto finish; 484 } 485 486 if (candidate_vers > incumbent_vers) { 487 IOLog(VTYELLOW "Replacing extension \"%s\" with newer version " 488 "(%s -> %s).\n" VTRESET, 489 incumbentName->getCStringNoCopy(), 490 incumbentVersionString->getCStringNoCopy(), 491 candidateVersionString->getCStringNoCopy()); 492 LOG_DELAY(); 493 winner = candidate; 494 goto finish; 495 } else { 496 IOLog(VTYELLOW "Skipping duplicate extension \"%s\" with older/same " 497 " version (%s -> %s).\n" VTRESET, 498 candidateName->getCStringNoCopy(), 499 candidateVersionString->getCStringNoCopy(), 500 incumbentVersionString->getCStringNoCopy()); 501 LOG_DELAY(); 502 winner = incumbent; 503 goto finish; 504 } 505 506finish: 507 508 // no cleanup, how nice 509 return winner; 510} 511 512 513/********************************************************************* 514* This function merges entries in the mergeFrom dictionary into the 515* mergeInto dictionary. If it returns false, the two dictionaries are 516* not altered. If it returns true, then mergeInto may have new 517* entries; any keys that were already present in mergeInto are 518* removed from mergeFrom, so that the caller can see what was 519* actually merged. 520*********************************************************************/ 521bool mergeExtensionDictionaries(OSDictionary * mergeInto, 522 OSDictionary * mergeFrom) { 523 524 bool result = true; 525 OSDictionary * mergeIntoCopy = NULL; // must release 526 OSDictionary * mergeFromCopy = NULL; // must release 527 OSCollectionIterator * keyIterator = NULL; // must release 528 OSString * key; // don't release 529 530 /* Add 1 to count to guarantee copy can grow (grr). 531 */ 532 mergeIntoCopy = OSDictionary::withDictionary(mergeInto, 533 mergeInto->getCount() + 1); 534 if (!mergeIntoCopy) { 535 IOLog("Error: Failed to copy 'into' extensions dictionary " 536 "for merge.\n"); 537 LOG_DELAY(); 538 result = false; 539 goto finish; 540 } 541 542 /* Add 1 to count to guarantee copy can grow (grr). 543 */ 544 mergeFromCopy = OSDictionary::withDictionary(mergeFrom, 545 mergeFrom->getCount() + 1); 546 if (!mergeFromCopy) { 547 IOLog("Error: Failed to copy 'from' extensions dictionary " 548 "for merge.\n"); 549 LOG_DELAY(); 550 result = false; 551 goto finish; 552 } 553 554 keyIterator = OSCollectionIterator::withCollection(mergeFrom); 555 if (!keyIterator) { 556 IOLog("Error: Failed to allocate iterator for extensions.\n"); 557 LOG_DELAY(); 558 result = false; 559 goto finish; 560 } 561 562 563 /***** 564 * Loop through "from" dictionary, checking if the identifier already 565 * exists in the "into" dictionary and checking versions if it does. 566 */ 567 while ((key = OSDynamicCast(OSString, keyIterator->getNextObject()))) { 568 OSDictionary * incumbentExt = OSDynamicCast(OSDictionary, 569 mergeIntoCopy->getObject(key)); 570 OSDictionary * candidateExt = OSDynamicCast(OSDictionary, 571 mergeFrom->getObject(key)); 572 573 if (!incumbentExt) { 574 if (!mergeIntoCopy->setObject(key, candidateExt)) { 575 576 /* This is a fatal error, so bail. 577 */ 578 IOLog("mergeExtensionDictionaries(): Failed to add " 579 "identifier %s\n", 580 key->getCStringNoCopy()); 581 LOG_DELAY(); 582 result = false; 583 goto finish; 584 } 585 } else { 586 OSDictionary * mostRecentExtension = 587 compareExtensionVersions(incumbentExt, candidateExt); 588 589 if (mostRecentExtension == incumbentExt) { 590 mergeFromCopy->removeObject(key); 591 } else if (mostRecentExtension == candidateExt) { 592 593 if (!mergeIntoCopy->setObject(key, candidateExt)) { 594 595 /* This is a fatal error, so bail. 596 */ 597 IOLog("mergeExtensionDictionaries(): Failed to add " 598 "identifier %s\n", 599 key->getCStringNoCopy()); 600 LOG_DELAY(); 601 result = false; 602 goto finish; 603 } 604 } else /* should be NULL */ { 605 606 /* This is a nonfatal error, so continue doing others. 607 */ 608 IOLog("mergeExtensionDictionaries(): Error comparing " 609 "versions of duplicate extensions %s.\n", 610 key->getCStringNoCopy()); 611 LOG_DELAY(); 612 continue; 613 } 614 } 615 } 616 617finish: 618 619 /* If successful, replace the contents of the original 620 * dictionaries with those of the modified copies. 621 */ 622 if (result) { 623 mergeInto->flushCollection(); 624 mergeInto->merge(mergeIntoCopy); 625 mergeFrom->flushCollection(); 626 mergeFrom->merge(mergeFromCopy); 627 } 628 629 if (mergeIntoCopy) mergeIntoCopy->release(); 630 if (mergeFromCopy) mergeFromCopy->release(); 631 if (keyIterator) keyIterator->release(); 632 633 return result; 634} 635 636 637/**** 638 * These bits are used to parse data made available by bootx. 639 */ 640#define BOOTX_KEXT_PREFIX "Driver-" 641#define BOOTX_MULTIKEXT_PREFIX "DriversPackage-" 642 643typedef struct MemoryMapFileInfo { 644 UInt32 paddr; 645 UInt32 length; 646} MemoryMapFileInfo; 647 648typedef struct BootxDriverInfo { 649 char *plistAddr; 650 long plistLength; 651 void *moduleAddr; 652 long moduleLength; 653} BootxDriverInfo; 654 655typedef struct MkextEntryInfo { 656 vm_address_t base_address; 657 mkext_file * fileinfo; 658} MkextEntryInfo; 659 660 661/********************************************************************* 662* This private function reads the data for a single extension from 663* the bootx memory-map's propery dict, returning a dictionary with 664* keys "plist" for the extension's Info.plist as a parsed OSDictionary 665* and "code" for the extension's executable code as an OSData. 666*********************************************************************/ 667OSDictionary * readExtension(OSDictionary * propertyDict, 668 const char * memory_map_name) { 669 670 int error = 0; 671 OSData * bootxDriverDataObject = NULL; 672 OSDictionary * driverPlist = NULL; 673 OSString * driverName = NULL; 674 OSData * driverCode = NULL; 675 OSString * errorString = NULL; 676 OSDictionary * driverDict = NULL; 677 678 MemoryMapFileInfo * driverInfo = 0; 679 BootxDriverInfo * dataBuffer; 680 681 kmod_info_t * loaded_kmod = NULL; 682 683 bootxDriverDataObject = OSDynamicCast(OSData, 684 propertyDict->getObject(memory_map_name)); 685 // don't release bootxDriverDataObject 686 687 if (!bootxDriverDataObject) { 688 IOLog("Error: No driver data object " 689 "for device tree entry \"%s\".\n", 690 memory_map_name); 691 LOG_DELAY(); 692 error = 1; 693 goto finish; 694 } 695 696 driverDict = OSDictionary::withCapacity(2); 697 if (!driverDict) { 698 IOLog("Error: Couldn't allocate dictionary " 699 "for device tree entry \"%s\".\n", memory_map_name); 700 LOG_DELAY(); 701 error = 1; 702 goto finish; 703 } 704 705 driverInfo = (MemoryMapFileInfo *) 706 bootxDriverDataObject->getBytesNoCopy(0, 707 sizeof(MemoryMapFileInfo)); 708#if defined (__ppc__) 709 dataBuffer = (BootxDriverInfo *)ml_static_ptovirt( 710 driverInfo->paddr); 711#elif defined (__i386__) 712 dataBuffer = (BootxDriverInfo *)driverInfo->paddr; 713 dataBuffer->plistAddr = ml_static_ptovirt(dataBuffer->plistAddr); 714 if (dataBuffer->moduleAddr) 715 dataBuffer->moduleAddr = ml_static_ptovirt(dataBuffer->moduleAddr); 716#else 717#error unsupported architecture 718#endif 719 if (!dataBuffer) { 720 IOLog("Error: No data buffer " 721 "for device tree entry \"%s\".\n", memory_map_name); 722 LOG_DELAY(); 723 error = 1; 724 goto finish; 725 } 726 727 driverPlist = OSDynamicCast(OSDictionary, 728 OSUnserializeXML(dataBuffer->plistAddr, &errorString)); 729 if (!driverPlist) { 730 IOLog("Error: Couldn't read XML property list " 731 "for device tree entry \"%s\".\n", memory_map_name); 732 LOG_DELAY(); 733 if (errorString) { 734 IOLog("XML parse error: %s.\n", 735 errorString->getCStringNoCopy()); 736 LOG_DELAY(); 737 } 738 error = 1; 739 goto finish; 740 } 741 742 743 driverName = OSDynamicCast(OSString, 744 driverPlist->getObject("CFBundleIdentifier")); // do not release 745 if (!driverName) { 746 IOLog("Error: Device tree entry \"%s\" has " 747 "no \"CFBundleIdentifier\" property.\n", memory_map_name); 748 LOG_DELAY(); 749 error = 1; 750 goto finish; 751 } 752 753 /* Check if kmod is already loaded and is a real loadable one (has 754 * an address). 755 */ 756 loaded_kmod = kmod_lookupbyname_locked(driverName->getCStringNoCopy()); 757 if (loaded_kmod && loaded_kmod->address) { 758 IOLog("Skipping new extension \"%s\"; an extension named " 759 "\"%s\" is already loaded.\n", 760 driverName->getCStringNoCopy(), 761 loaded_kmod->name); 762 LOG_DELAY(); 763 error = 1; 764 goto finish; 765 } 766 767 if (!validateExtensionDict(driverPlist, -1)) { 768 // validateExtensionsDict() logs an error 769 error = 1; 770 goto finish; 771 } 772 773 driverDict->setObject("plist", driverPlist); 774 775 /* It's perfectly okay for a KEXT to have no executable. 776 * Check that moduleAddr is nonzero before attempting to 777 * get one. 778 * 779 * NOTE: The driverCode object is created "no-copy", so 780 * it doesn't own that memory. The memory must be freed 781 * separately from the OSData object (see 782 * clearStartupExtensionsAndLoaderInfo() at the end of this file). 783 */ 784 if (dataBuffer->moduleAddr && dataBuffer->moduleLength) { 785 driverCode = OSData::withBytesNoCopy(dataBuffer->moduleAddr, 786 dataBuffer->moduleLength); 787 if (!driverCode) { 788 IOLog("Error: Couldn't allocate data object " 789 "to hold code for device tree entry \"%s\".\n", 790 memory_map_name); 791 LOG_DELAY(); 792 error = 1; 793 goto finish; 794 } 795 796 if (driverCode) { 797 driverDict->setObject("code", driverCode); 798 } 799 } 800 801finish: 802 803 if (loaded_kmod) { 804 kfree((unsigned int)loaded_kmod, sizeof(kmod_info_t)); 805 } 806 807 // do not release bootxDriverDataObject 808 // do not release driverName 809 810 if (driverPlist) { 811 driverPlist->release(); 812 } 813 if (errorString) { 814 errorString->release(); 815 } 816 if (driverCode) { 817 driverCode->release(); 818 } 819 if (error) { 820 if (driverDict) { 821 driverDict->release(); 822 driverDict = NULL; 823 } 824 } 825 return driverDict; 826} 827 828 829/********************************************************************* 830* Used to uncompress a single file entry in an mkext archive. 831* 832* The OSData returned does not own its memory! You must deallocate 833* that memory using kmem_free() before releasing the OSData(). 834*********************************************************************/ 835static bool uncompressFile(u_int8_t *base_address, mkext_file * fileinfo, 836 /* out */ OSData ** file) { 837 838 bool result = true; 839 kern_return_t kern_result; 840 u_int8_t * uncompressed_file = 0; // kmem_free() on error 841 OSData * uncompressedFile = 0; // returned 842 size_t uncompressed_size = 0; 843 844 size_t offset = OSSwapBigToHostInt32(fileinfo->offset); 845 size_t compsize = OSSwapBigToHostInt32(fileinfo->compsize); 846 size_t realsize = OSSwapBigToHostInt32(fileinfo->realsize); 847 time_t modifiedsecs = OSSwapBigToHostInt32(fileinfo->modifiedsecs); 848 849 *file = 0; 850 851 /* If these four fields are zero there's no file, but that isn't 852 * an error. 853 */ 854 if (offset == 0 && compsize == 0 && 855 realsize == 0 && modifiedsecs == 0) { 856 goto finish; 857 } 858 859 // Add 1 for '\0' to terminate XML string! 860 kern_result = kmem_alloc(kernel_map, (vm_offset_t *)&uncompressed_file, 861 realsize + 1); 862 if (kern_result != KERN_SUCCESS) { 863 IOLog("Error: Couldn't allocate data buffer " 864 "to uncompress file.\n"); 865 LOG_DELAY(); 866 result = false; 867 goto finish; 868 } 869 870 uncompressedFile = OSData::withBytesNoCopy(uncompressed_file, 871 realsize + 1); 872 if (!uncompressedFile) { 873 IOLog("Error: Couldn't allocate data object " 874 "to uncompress file.\n"); 875 LOG_DELAY(); 876 result = false; 877 goto finish; 878 } 879 880 if (compsize != 0) { 881 uncompressed_size = decompress_lzss(uncompressed_file, 882 base_address + offset, 883 compsize); 884 if (uncompressed_size != realsize) { 885 IOLog("Error: Uncompressed file is not the length " 886 "recorded.\n"); 887 LOG_DELAY(); 888 result = false; 889 goto finish; 890 } 891 uncompressed_file[uncompressed_size] = '\0'; 892 } else { 893 bcopy(base_address + offset, uncompressed_file, 894 realsize); 895 uncompressed_file[realsize] = '\0'; 896 } 897 898 *file = uncompressedFile; 899 900finish: 901 if (!result) { 902 if (uncompressed_file) { 903 kmem_free(kernel_map, (vm_address_t)uncompressed_file, 904 realsize + 1); 905 } 906 if (uncompressedFile) { 907 uncompressedFile->release(); 908 *file = 0; 909 } 910 } 911 return result; 912} 913 914bool uncompressModule(OSData *compData, /* out */ OSData ** file) { 915 916 MkextEntryInfo *info = (MkextEntryInfo *) compData->getBytesNoCopy(); 917 918 return uncompressFile((u_int8_t *) info->base_address, 919 info->fileinfo, file); 920} 921 922 923/********************************************************************* 924* Does the work of pulling extensions out of an mkext archive located 925* in memory. 926*********************************************************************/ 927bool extractExtensionsFromArchive(MemoryMapFileInfo * mkext_file_info, 928 OSDictionary * extensions) { 929 930 bool result = true; 931 932 u_int8_t * crc_address = 0; 933 u_int32_t checksum; 934 mkext_header * mkext_data = 0; // don't free 935 mkext_kext * onekext_data = 0; // don't free 936 mkext_file * plist_file = 0; // don't free 937 mkext_file * module_file = 0; // don't free 938 kmod_info_t * loaded_kmod = 0; // must free 939 940 OSData * driverPlistDataObject = 0; // must release 941 OSDictionary * driverPlist = 0; // must release 942 OSData * driverCode = 0; // must release 943 OSDictionary * driverDict = 0; // must release 944 OSString * moduleName = 0; // don't release 945 OSString * errorString = NULL; // must release 946 947 OSData * moduleInfo = 0; // must release 948 MkextEntryInfo module_info; 949 950 951#if defined (__ppc__) 952 mkext_data = (mkext_header *)mkext_file_info->paddr; 953#elif defined (__i386__) 954 mkext_data = (mkext_header *)ml_static_ptovirt(mkext_file_info->paddr); 955#else 956#error unsupported architecture 957#endif 958 if (OSSwapBigToHostInt32(mkext_data->magic) != MKEXT_MAGIC || 959 OSSwapBigToHostInt32(mkext_data->signature) != MKEXT_SIGN) { 960 IOLog("Error: Extension archive has invalid magic or signature.\n"); 961 LOG_DELAY(); 962 result = false; 963 goto finish; 964 } 965 966 if (OSSwapBigToHostInt32(mkext_data->length) != mkext_file_info->length) { 967 IOLog("Error: Mismatch between extension archive & " 968 "recorded length.\n"); 969 LOG_DELAY(); 970 result = false; 971 goto finish; 972 } 973 974 crc_address = (u_int8_t *)&mkext_data->version; 975 checksum = adler32(crc_address, 976 (unsigned int)mkext_data + 977 OSSwapBigToHostInt32(mkext_data->length) - (unsigned int)crc_address); 978 979 if (OSSwapBigToHostInt32(mkext_data->adler32) != checksum) { 980 IOLog("Error: Extension archive has a bad checksum.\n"); 981 LOG_DELAY(); 982 result = false; 983 goto finish; 984 } 985 986 /* If the MKEXT archive isn't fat, check that the CPU type & subtype 987 * match that of the running kernel. 988 */ 989 if (OSSwapBigToHostInt32(mkext_data->cputype) != (UInt32)CPU_TYPE_ANY) { 990 kern_return_t kresult = KERN_FAILURE; 991 host_basic_info_data_t hostinfo; 992 host_info_t hostinfo_ptr = (host_info_t)&hostinfo; 993 mach_msg_type_number_t count = sizeof(hostinfo)/sizeof(integer_t); 994 995 kresult = host_info((host_t)1, HOST_BASIC_INFO, 996 hostinfo_ptr, &count); 997 if (kresult != KERN_SUCCESS) { 998 IOLog("Error: Couldn't get current host info.\n"); 999 LOG_DELAY(); 1000 result = false;
1001 goto finish; 1002 } 1003 if ((UInt32)hostinfo.cpu_type != 1004 OSSwapBigToHostInt32(mkext_data->cputype)) { 1005 1006 IOLog("Error: Extension archive doesn't contain software " 1007 "for this computer's CPU type.\n"); 1008 LOG_DELAY(); 1009 result = false; 1010 goto finish; 1011 } 1012 if (!grade_binary(OSSwapBigToHostInt32(mkext_data->cputype), 1013 OSSwapBigToHostInt32(mkext_data->cpusubtype))) { 1014 IOLog("Error: Extension archive doesn't contain software " 1015 "for this computer's CPU subtype.\n"); 1016 LOG_DELAY(); 1017 result = false; 1018 goto finish; 1019 } 1020 } 1021 1022 for (unsigned int i = 0; 1023 i < OSSwapBigToHostInt32(mkext_data->numkexts); 1024 i++) { 1025 1026 if (loaded_kmod) { 1027 kfree((unsigned int)loaded_kmod, sizeof(kmod_info_t)); 1028 loaded_kmod = 0; 1029 } 1030 1031 if (driverPlistDataObject) { 1032 kmem_free(kernel_map, 1033 (unsigned int)driverPlistDataObject->getBytesNoCopy(), 1034 driverPlistDataObject->getLength()); 1035 1036 driverPlistDataObject->release(); 1037 driverPlistDataObject = NULL; 1038 } 1039 if (driverPlist) { 1040 driverPlist->release(); 1041 driverPlist = NULL; 1042 } 1043 if (driverCode) { 1044 driverCode->release(); 1045 driverCode = NULL; 1046 } 1047 if (driverDict) { 1048 driverDict->release(); 1049 driverDict = NULL; 1050 } 1051 if (errorString) { 1052 errorString->release(); 1053 errorString = NULL; 1054 } 1055 1056 onekext_data = &mkext_data->kext[i]; 1057 plist_file = &onekext_data->plist; 1058 module_file = &onekext_data->module; 1059 1060 if (!uncompressFile((u_int8_t *)mkext_data, plist_file, 1061 &driverPlistDataObject)) { 1062 1063 IOLog("Error: couldn't uncompress plist file " 1064 "from multikext archive entry %d.\n", i); 1065 LOG_DELAY(); 1066 continue; 1067 } 1068 1069 if (!driverPlistDataObject) { 1070 IOLog("Error: No property list present " 1071 "for multikext archive entry %d.\n", i); 1072 LOG_DELAY(); 1073 continue; 1074 } else { 1075 driverPlist = OSDynamicCast(OSDictionary, 1076 OSUnserializeXML( 1077 (char *)driverPlistDataObject->getBytesNoCopy(), 1078 &errorString)); 1079 if (!driverPlist) { 1080 IOLog("Error: Couldn't read XML property list " 1081 "for multikext archive entry %d.\n", i); 1082 LOG_DELAY(); 1083 if (errorString) { 1084 IOLog("XML parse error: %s.\n", 1085 errorString->getCStringNoCopy()); 1086 LOG_DELAY(); 1087 } 1088 continue; 1089 } 1090 1091 if (!validateExtensionDict(driverPlist, i)) { 1092 // validateExtensionsDict() logs an error 1093 continue; 1094 } 1095 1096 } 1097 1098 /* Get the extension's module name. This is used to record 1099 * the extension. 1100 */ 1101 moduleName = OSDynamicCast(OSString, 1102 driverPlist->getObject("CFBundleIdentifier")); // do not release 1103 if (!moduleName) { 1104 IOLog("Error: Multikext archive entry %d has " 1105 "no \"CFBundleIdentifier\" property.\n", i); 1106 LOG_DELAY(); 1107 continue; // assume a kext config error & continue 1108 } 1109 1110 /* Check if kmod is already loaded and is a real loadable one (has 1111 * an address). 1112 */ 1113 loaded_kmod = kmod_lookupbyname_locked(moduleName->getCStringNoCopy()); 1114 if (loaded_kmod && loaded_kmod->address) { 1115 IOLog("Skipping new extension \"%s\"; an extension named " 1116 "\"%s\" is already loaded.\n", 1117 moduleName->getCStringNoCopy(), 1118 loaded_kmod->name); 1119 continue; 1120 } 1121 1122 1123 driverDict = OSDictionary::withCapacity(2); 1124 if (!driverDict) { 1125 IOLog("Error: Couldn't allocate dictionary " 1126 "for multikext archive entry %d.\n", i); 1127 LOG_DELAY(); 1128 result = false; 1129 goto finish; 1130 } 1131 1132 driverDict->setObject("plist", driverPlist); 1133 1134 /***** 1135 * Prepare an entry to hold the mkext entry info for the 1136 * compressed binary module, if there is one. If all four fields 1137 * of the module entry are zero, there isn't one. 1138 */ 1139 if (!(loaded_kmod && loaded_kmod->address) && (OSSwapBigToHostInt32(module_file->offset) || 1140 OSSwapBigToHostInt32(module_file->compsize) || 1141 OSSwapBigToHostInt32(module_file->realsize) || 1142 OSSwapBigToHostInt32(module_file->modifiedsecs))) { 1143 1144 moduleInfo = OSData::withCapacity(sizeof(MkextEntryInfo)); 1145 if (!moduleInfo) { 1146 IOLog("Error: Couldn't allocate data object " 1147 "for multikext archive entry %d.\n", i); 1148 LOG_DELAY(); 1149 result = false; 1150 goto finish; 1151 } 1152 1153 module_info.base_address = (vm_address_t)mkext_data; 1154 module_info.fileinfo = module_file; 1155 1156 if (!moduleInfo->appendBytes(&module_info, sizeof(module_info))) { 1157 IOLog("Error: Couldn't record info " 1158 "for multikext archive entry %d.\n", i); 1159 LOG_DELAY(); 1160 result = false; 1161 goto finish; 1162 } 1163 1164 driverDict->setObject("compressedCode", moduleInfo); 1165 } 1166 1167 OSDictionary * incumbentExt = OSDynamicCast(OSDictionary, 1168 extensions->getObject(moduleName)); 1169 1170 if (!incumbentExt) { 1171 extensions->setObject(moduleName, driverDict); 1172 } else { 1173 OSDictionary * mostRecentExtension = 1174 compareExtensionVersions(incumbentExt, driverDict); 1175 1176 if (mostRecentExtension == incumbentExt) { 1177 /* Do nothing, we've got the most recent. */ 1178 } else if (mostRecentExtension == driverDict) { 1179 if (!extensions->setObject(moduleName, driverDict)) { 1180 1181 /* This is a fatal error, so bail. 1182 */ 1183 IOLog("extractExtensionsFromArchive(): Failed to add " 1184 "identifier %s\n", 1185 moduleName->getCStringNoCopy()); 1186 LOG_DELAY(); 1187 result = false; 1188 goto finish; 1189 } 1190 } else /* should be NULL */ { 1191 1192 /* This is a nonfatal error, so continue. 1193 */ 1194 IOLog("extractExtensionsFromArchive(): Error comparing " 1195 "versions of duplicate extensions %s.\n", 1196 moduleName->getCStringNoCopy()); 1197 LOG_DELAY(); 1198 continue; 1199 } 1200 } 1201 } 1202 1203finish: 1204 1205 if (loaded_kmod) kfree((unsigned int)loaded_kmod, sizeof(kmod_info_t)); 1206 if (driverPlistDataObject) { 1207 kmem_free(kernel_map, 1208 (unsigned int)driverPlistDataObject->getBytesNoCopy(), 1209 driverPlistDataObject->getLength()); 1210 driverPlistDataObject->release(); 1211 } 1212 if (driverPlist) driverPlist->release(); 1213 if (driverCode) driverCode->release(); 1214 if (moduleInfo) moduleInfo->release(); 1215 if (driverDict) driverDict->release(); 1216 if (errorString) errorString->release(); 1217 1218 return result; 1219} 1220 1221/********************************************************************* 1222* 1223*********************************************************************/ 1224bool readExtensions(OSDictionary * propertyDict, 1225 const char * memory_map_name, 1226 OSDictionary * extensions) { 1227 1228 bool result = true; 1229 OSData * mkextDataObject = 0; // don't release 1230 MemoryMapFileInfo * mkext_file_info = 0; // don't free 1231 1232 mkextDataObject = OSDynamicCast(OSData, 1233 propertyDict->getObject(memory_map_name)); 1234 // don't release mkextDataObject 1235 1236 if (!mkextDataObject) { 1237 IOLog("Error: No mkext data object " 1238 "for device tree entry \"%s\".\n", 1239 memory_map_name); 1240 LOG_DELAY(); 1241 result = false; 1242 goto finish; 1243 } 1244 1245 mkext_file_info = (MemoryMapFileInfo *)mkextDataObject->getBytesNoCopy(); 1246 if (!mkext_file_info) { 1247 result = false; 1248 goto finish; 1249 } 1250 1251 result = extractExtensionsFromArchive(mkext_file_info, extensions); 1252 1253finish: 1254 1255 if (!result && extensions) { 1256 extensions->flushCollection(); 1257 } 1258 1259 return result; 1260} 1261 1262 1263/********************************************************************* 1264* Adds the personalities for an extensions dictionary to the global 1265* IOCatalogue. 1266*********************************************************************/ 1267bool addPersonalities(OSDictionary * extensions) { 1268 bool result = true; 1269 OSCollectionIterator * keyIterator = NULL; // must release 1270 OSString * key; // don't release 1271 OSDictionary * driverDict = NULL; // don't release 1272 OSDictionary * driverPlist = NULL; // don't release 1273 OSDictionary * thisDriverPersonalities = NULL; // don't release 1274 OSArray * allDriverPersonalities = NULL; // must release 1275 1276 allDriverPersonalities = OSArray::withCapacity(1); 1277 if (!allDriverPersonalities) { 1278 IOLog("Error: Couldn't allocate personality dictionary.\n"); 1279 LOG_DELAY(); 1280 result = false; 1281 goto finish; 1282 } 1283 1284 /* Record all personalities found so that they can be 1285 * added to the catalogue. 1286 * Note: Not all extensions have personalities. 1287 */ 1288 1289 keyIterator = OSCollectionIterator::withCollection(extensions); 1290 if (!keyIterator) { 1291 IOLog("Error: Couldn't allocate iterator to record personalities.\n"); 1292 LOG_DELAY(); 1293 result = false; 1294 goto finish; 1295 } 1296 1297 while ( ( key = OSDynamicCast(OSString, 1298 keyIterator->getNextObject() ))) { 1299 1300 driverDict = OSDynamicCast(OSDictionary, 1301 extensions->getObject(key)); 1302 driverPlist = OSDynamicCast(OSDictionary, 1303 driverDict->getObject("plist")); 1304 thisDriverPersonalities = OSDynamicCast(OSDictionary, 1305 driverPlist->getObject("IOKitPersonalities")); 1306 1307 if (thisDriverPersonalities) { 1308 OSCollectionIterator * pIterator; 1309 OSString * locakKey; 1310 pIterator = OSCollectionIterator::withCollection( 1311 thisDriverPersonalities); 1312 if (!pIterator) { 1313 IOLog("Error: Couldn't allocate iterator " 1314 "to record extension personalities.\n"); 1315 LOG_DELAY(); 1316 continue; 1317 } 1318 while ( (locakKey = OSDynamicCast(OSString, 1319 pIterator->getNextObject())) ) { 1320 1321 OSDictionary * personality = OSDynamicCast( 1322 OSDictionary, 1323 thisDriverPersonalities->getObject(locakKey)); 1324 if (personality) { 1325 allDriverPersonalities->setObject(personality); 1326 } 1327 } 1328 pIterator->release(); 1329 } 1330 } /* extract personalities */ 1331 1332 1333 /* Add all personalities found to the IOCatalogue, 1334 * but don't start matching. 1335 */ 1336 gIOCatalogue->addDrivers(allDriverPersonalities, false); 1337 1338finish: 1339 1340 if (allDriverPersonalities) allDriverPersonalities->release(); 1341 if (keyIterator) keyIterator->release(); 1342 1343 return result; 1344} 1345 1346 1347/********************************************************************* 1348* Called from IOCatalogue to add extensions from an mkext archive. 1349* This function makes a copy of the mkext object passed in because 1350* the device tree support code dumps it after calling us (indirectly 1351* through the IOCatalogue). 1352*********************************************************************/ 1353bool addExtensionsFromArchive(OSData * mkextDataObject) { 1354 bool result = true; 1355 1356 OSDictionary * startupExtensions = NULL; // don't release 1357 OSArray * bootLoaderObjects = NULL; // don't release 1358 OSDictionary * extensions = NULL; // must release 1359 MemoryMapFileInfo mkext_file_info; 1360 OSCollectionIterator * keyIterator = NULL; // must release 1361 OSString * key = NULL; // don't release 1362 1363 startupExtensions = getStartupExtensions(); 1364 if (!startupExtensions) { 1365 IOLog("Can't record extension archive; there is no" 1366 " extensions dictionary.\n"); 1367 LOG_DELAY(); 1368 result = false; 1369 goto finish; 1370 } 1371 1372 bootLoaderObjects = getBootLoaderObjects(); 1373 if (! bootLoaderObjects) { 1374 IOLog("Error: Couldn't allocate array to hold temporary objects.\n"); 1375 LOG_DELAY(); 1376 result = false; 1377 goto finish; 1378 } 1379 1380 extensions = OSDictionary::withCapacity(2); 1381 if (!extensions) { 1382 IOLog("Error: Couldn't allocate dictionary to unpack " 1383 "extension archive.\n"); 1384 LOG_DELAY(); 1385 result = false; 1386 goto finish; 1387 } 1388 1389 mkext_file_info.paddr = (UInt32)mkextDataObject->getBytesNoCopy(); 1390 mkext_file_info.length = mkextDataObject->getLength(); 1391 1392 /* Save the local mkext data object so that we can deallocate it later. 1393 */ 1394 bootLoaderObjects->setObject(mkextDataObject); 1395 1396 result = extractExtensionsFromArchive(&mkext_file_info, extensions); 1397 if (!result) { 1398 IOLog("Error: Failed to extract extensions from archive.\n"); 1399 LOG_DELAY(); 1400 result = false; 1401 goto finish; 1402 } 1403 1404 result = mergeExtensionDictionaries(startupExtensions, extensions); 1405 if (!result) { 1406 IOLog("Error: Failed to merge new extensions into existing set.\n"); 1407 LOG_DELAY(); 1408 goto finish; 1409 } 1410 1411 result = addPersonalities(extensions); 1412 if (!result) { 1413 IOLog("Error: Failed to add personalities for extensions extracted " 1414 "from archive.\n"); 1415 LOG_DELAY(); 1416 result = false; 1417 goto finish; 1418 } 1419 1420finish: 1421 1422 if (!result) { 1423 IOLog("Error: Failed to record extensions from archive.\n"); 1424 LOG_DELAY(); 1425 } else { 1426 keyIterator = OSCollectionIterator::withCollection( 1427 extensions); 1428 1429 if (keyIterator) { 1430 while ( (key = OSDynamicCast(OSString, 1431 keyIterator->getNextObject())) ) { 1432 1433 IOLog("Added extension \"%s\" from archive.\n", 1434 key->getCStringNoCopy()); 1435 LOG_DELAY(); 1436 } 1437 keyIterator->release(); 1438 } 1439 } 1440 1441 if (extensions) extensions->release(); 1442 1443 return result; 1444} 1445 1446 1447/********************************************************************* 1448* This function builds dictionaries for the startup extensions 1449* put into memory by bootx, recording each in the startup extensions 1450* dictionary. The dictionary format is this: 1451* 1452* { 1453* "plist" = (the extension's Info.plist as an OSDictionary) 1454* "code" = (an OSData containing the executable file) 1455* } 1456* 1457* This function returns true if any extensions were found and 1458* recorded successfully, or if there are no start extensions, 1459* and false if an unrecoverable error occurred. An error reading 1460* a single extension is not considered fatal, and this function 1461* will simply skip the problematic extension to try the next one. 1462*********************************************************************/ 1463 1464bool recordStartupExtensions(void) { 1465 bool result = true; 1466 OSDictionary * startupExtensions = NULL; // must release 1467 OSDictionary * existingExtensions = NULL; // don't release 1468 OSDictionary * mkextExtensions = NULL; // must release 1469 IORegistryEntry * bootxMemoryMap = NULL; // must release 1470 OSDictionary * propertyDict = NULL; // must release 1471 OSCollectionIterator * keyIterator = NULL; // must release 1472 OSString * key = NULL; // don't release 1473 1474 OSDictionary * newDriverDict = NULL; // must release 1475 OSDictionary * driverPlist = NULL; // don't release 1476 1477 struct section * infosect; 1478 struct section * symsect; 1479 unsigned int prelinkedCount = 0; 1480 1481 existingExtensions = getStartupExtensions(); 1482 if (!existingExtensions) { 1483 IOLog("Error: There is no dictionary for startup extensions.\n"); 1484 LOG_DELAY(); 1485 result = false; 1486 goto finish; 1487 } 1488 1489 startupExtensions = OSDictionary::withCapacity(1); 1490 if (!startupExtensions) { 1491 IOLog("Error: Couldn't allocate dictionary " 1492 "to record startup extensions.\n"); 1493 LOG_DELAY(); 1494 result = false; 1495 goto finish; 1496 } 1497 1498 // -- 1499 // add any prelinked modules as startup extensions 1500 1501 infosect = getsectbyname("__PRELINK", "__info"); 1502 symsect = getsectbyname("__PRELINK", "__symtab"); 1503 if (infosect && infosect->addr && infosect->size 1504 && symsect && symsect->addr && symsect->size) do 1505 { 1506 gIOPrelinkedModules = OSDynamicCast(OSArray, 1507 OSUnserializeXML((const char *) infosect->addr, NULL)); 1508 1509 if (!gIOPrelinkedModules) 1510 break; 1511 for( unsigned int idx = 0; 1512 (propertyDict = OSDynamicCast(OSDictionary, gIOPrelinkedModules->getObject(idx))); 1513 idx++) 1514 { 1515 enum { kPrelinkReservedCount = 4 }; 1516 1517 /* Get the extension's module name. This is used to record 1518 * the extension. Do *not* release the moduleName. 1519 */ 1520 OSString * moduleName = OSDynamicCast(OSString, 1521 propertyDict->getObject("CFBundleIdentifier")); 1522 if (!moduleName) { 1523 IOLog("Error: Prelinked module entry has " 1524 "no \"CFBundleIdentifier\" property.\n"); 1525 LOG_DELAY(); 1526 continue; 1527 } 1528 1529 /* Add the kext, & its plist. 1530 */ 1531 newDriverDict = OSDictionary::withCapacity(4); 1532 assert(newDriverDict); 1533 newDriverDict->setObject("plist", propertyDict); 1534 startupExtensions->setObject(moduleName, newDriverDict); 1535 newDriverDict->release(); 1536 1537 /* Add the code if present. 1538 */ 1539 OSData * data = OSDynamicCast(OSData, propertyDict->getObject("OSBundlePrelink")); 1540 if (data) { 1541 if (data->getLength() < (kPrelinkReservedCount * sizeof(UInt32))) { 1542 IOLog("Error: Prelinked module entry has " 1543 "invalid \"OSBundlePrelink\" property.\n"); 1544 LOG_DELAY(); 1545 continue; 1546 } 1547 UInt32 * prelink; 1548 prelink = (UInt32 *) data->getBytesNoCopy(); 1549 kmod_info_t * kmod_info = (kmod_info_t *) OSReadBigInt32(prelink, 0); 1550 // end of "file" is end of symbol sect 1551 data = OSData::withBytesNoCopy((void *) kmod_info->address, 1552 symsect->addr + symsect->size - kmod_info->address); 1553 newDriverDict->setObject("code", data); 1554 data->release(); 1555 prelinkedCount++; 1556 continue; 1557 } 1558 /* Add the symbols if present. 1559 */ 1560 OSNumber * num = OSDynamicCast(OSNumber, propertyDict->getObject("OSBundlePrelinkSymbols")); 1561 if (num) { 1562 UInt32 offset = num->unsigned32BitValue(); 1563 data = OSData::withBytesNoCopy((void *) (symsect->addr + offset), symsect->size - offset); 1564 newDriverDict->setObject("code", data); 1565 data->release(); 1566 prelinkedCount++; 1567 continue; 1568 } 1569 } 1570 if (gIOPrelinkedModules) 1571 IOLog("%d prelinked modules\n", prelinkedCount); 1572 1573 // free __info 1574 vm_offset_t 1575 virt = ml_static_ptovirt(infosect->addr); 1576 if( virt) { 1577 ml_static_mfree(virt, infosect->size); 1578 } 1579 newDriverDict = NULL; 1580 } 1581 while (false); 1582 // -- 1583 1584 bootxMemoryMap = 1585 IORegistryEntry::fromPath( 1586 "/chosen/memory-map", // path 1587 gIODTPlane // plane 1588 ); 1589 // return value is retained so be sure to release it 1590 1591 if (!bootxMemoryMap) { 1592 IOLog("Error: Couldn't read booter memory map.\n"); 1593 LOG_DELAY(); 1594 result = false; 1595 goto finish; 1596 } 1597 1598 propertyDict = bootxMemoryMap->dictionaryWithProperties(); 1599 if (!propertyDict) { 1600 IOLog("Error: Couldn't get property dictionary " 1601 "from memory map.\n"); 1602 LOG_DELAY(); 1603 result = false; 1604 goto finish; 1605 } 1606 1607 keyIterator = OSCollectionIterator::withCollection(propertyDict); 1608 if (!keyIterator) { 1609 IOLog("Error: Couldn't allocate iterator for driver images.\n"); 1610 LOG_DELAY(); 1611 result = false; 1612 goto finish; 1613 } 1614 1615 while ( (key = OSDynamicCast(OSString, 1616 keyIterator->getNextObject())) ) { 1617 /* Clear newDriverDict & mkextExtensions upon entry to the loop, 1618 * handling both successful and unsuccessful iterations. 1619 */ 1620 if (newDriverDict) { 1621 newDriverDict->release(); 1622 newDriverDict = NULL; 1623 } 1624 if (mkextExtensions) { 1625 mkextExtensions->release(); 1626 mkextExtensions = NULL; 1627 } 1628 1629 const char * keyValue = key->getCStringNoCopy(); 1630 1631 if ( !strncmp(keyValue, BOOTX_KEXT_PREFIX, 1632 strlen(BOOTX_KEXT_PREFIX)) ) { 1633 1634 /* Read the extension from the bootx-supplied memory. 1635 */ 1636 newDriverDict = readExtension(propertyDict, keyValue); 1637 if (!newDriverDict) { 1638 IOLog("Error: Couldn't read data " 1639 "for device tree entry \"%s\".\n", keyValue); 1640 LOG_DELAY(); 1641 continue; 1642 } 1643 1644 1645 /* Preprare to record the extension by getting its info plist. 1646 */ 1647 driverPlist = OSDynamicCast(OSDictionary, 1648 newDriverDict->getObject("plist")); 1649 if (!driverPlist) { 1650 IOLog("Error: Extension in device tree entry \"%s\" " 1651 "has no property list.\n", keyValue); 1652 LOG_DELAY(); 1653 continue; 1654 } 1655 1656 1657 /* Get the extension's module name. This is used to record 1658 * the extension. Do *not* release the moduleName. 1659 */ 1660 OSString * moduleName = OSDynamicCast(OSString, 1661 driverPlist->getObject("CFBundleIdentifier")); 1662 if (!moduleName) { 1663 IOLog("Error: Device tree entry \"%s\" has " 1664 "no \"CFBundleIdentifier\" property.\n", keyValue); 1665 LOG_DELAY(); 1666 continue; 1667 } 1668 1669 1670 /* All has gone well so far, so record the extension under 1671 * its module name, checking for an existing duplicate. 1672 * 1673 * Do not release moduleName, as it's part of the extension's 1674 * plist. 1675 */ 1676 OSDictionary * incumbentExt = OSDynamicCast(OSDictionary, 1677 startupExtensions->getObject(moduleName)); 1678 1679 if (!incumbentExt) { 1680 startupExtensions->setObject(moduleName, newDriverDict); 1681 } else { 1682 OSDictionary * mostRecentExtension = 1683 compareExtensionVersions(incumbentExt, newDriverDict); 1684 1685 if (mostRecentExtension == incumbentExt) { 1686 /* Do nothing, we've got the most recent. */ 1687 } else if (mostRecentExtension == newDriverDict) { 1688 if (!startupExtensions->setObject(moduleName, 1689 newDriverDict)) { 1690 1691 /* This is a fatal error, so bail. 1692 */ 1693 IOLog("recordStartupExtensions(): Failed to add " 1694 "identifier %s\n", 1695 moduleName->getCStringNoCopy()); 1696 LOG_DELAY(); 1697 result = false; 1698 goto finish; 1699 } 1700 } else /* should be NULL */ { 1701 1702 /* This is a nonfatal error, so continue. 1703 */ 1704 IOLog("recordStartupExtensions(): Error comparing " 1705 "versions of duplicate extensions %s.\n", 1706 moduleName->getCStringNoCopy()); 1707 LOG_DELAY(); 1708 continue; 1709 } 1710 } 1711 1712 1713 } else if ( !strncmp(keyValue, BOOTX_MULTIKEXT_PREFIX, 1714 strlen(BOOTX_MULTIKEXT_PREFIX)) ) { 1715 1716 mkextExtensions = OSDictionary::withCapacity(10); 1717 if (!mkextExtensions) { 1718 IOLog("Error: Couldn't allocate dictionary to unpack " 1719 "multi-extension archive.\n"); 1720 LOG_DELAY(); 1721 result = false; 1722 goto finish; // allocation failure is fatal for this routine 1723 } 1724 if (!readExtensions(propertyDict, keyValue, mkextExtensions)) { 1725 IOLog("Error: Couldn't unpack multi-extension archive.\n"); 1726 LOG_DELAY(); 1727 continue; 1728 } else { 1729 if (!mergeExtensionDictionaries(startupExtensions, 1730 mkextExtensions)) { 1731 1732 IOLog("Error: Failed to merge new extensions into " 1733 "existing set.\n"); 1734 LOG_DELAY(); 1735 result = false; 1736 goto finish; // merge error is fatal for this routine 1737 } 1738 } 1739 } 1740 1741 // Do not release key. 1742 1743 } /* while ( (key = OSDynamicCast(OSString, ...) ) ) */ 1744 1745 if (!mergeExtensionDictionaries(existingExtensions, startupExtensions)) { 1746 IOLog("Error: Failed to merge new extensions into existing set.\n"); 1747 LOG_DELAY(); 1748 result = false; 1749 goto finish; 1750 } 1751 1752 result = addPersonalities(startupExtensions); 1753 if (!result) { 1754 IOLog("Error: Failed to add personalities for extensions extracted " 1755 "from archive.\n"); 1756 LOG_DELAY(); 1757 result = false; 1758 goto finish; 1759 } 1760 1761finish: 1762 1763 // reused so clear first! 1764 if (keyIterator) { 1765 keyIterator->release(); 1766 keyIterator = 0; 1767 } 1768 1769 if (!result) { 1770 IOLog("Error: Failed to record startup extensions.\n"); 1771 LOG_DELAY(); 1772 } else { 1773#if DEBUG 1774 keyIterator = OSCollectionIterator::withCollection( 1775 startupExtensions); 1776 1777 if (keyIterator) { 1778 while ( (key = OSDynamicCast(OSString, 1779 keyIterator->getNextObject())) ) { 1780 1781 IOLog("Found extension \"%s\".\n", 1782 key->getCStringNoCopy()); 1783 LOG_DELAY(); 1784 } 1785 keyIterator->release(); 1786 keyIterator = 0; 1787 } 1788#endif /* DEBUG */ 1789 } 1790 1791 if (newDriverDict) newDriverDict->release(); 1792 if (propertyDict) propertyDict->release(); 1793 if (bootxMemoryMap) bootxMemoryMap->release(); 1794 if (mkextExtensions) mkextExtensions->release(); 1795 if (startupExtensions) startupExtensions->release(); 1796 1797 return result; 1798} 1799 1800 1801/********************************************************************* 1802* This function removes an entry from the dictionary of startup 1803* extensions. It's used when an extension can't be loaded, for 1804* whatever reason. For drivers, this allows another matching driver 1805* to be loaded, so that, for example, a driver for the root device 1806* can be found. 1807*********************************************************************/ 1808void removeStartupExtension(const char * extensionName) { 1809 OSDictionary * startupExtensions = NULL; // don't release 1810 OSDictionary * extensionDict = NULL; // don't release 1811 OSDictionary * extensionPlist = NULL; // don't release 1812 OSDictionary * extensionPersonalities = NULL; // don't release 1813 OSDictionary * personality = NULL; // don't release 1814 OSCollectionIterator * keyIterator = NULL; // must release 1815 OSString * key = NULL; // don't release 1816 1817 startupExtensions = getStartupExtensions(); 1818 if (!startupExtensions) goto finish; 1819 1820 1821 /* Find the extension's entry in the dictionary of 1822 * startup extensions. 1823 */ 1824 extensionDict = OSDynamicCast(OSDictionary, 1825 startupExtensions->getObject(extensionName)); 1826 if (!extensionDict) goto finish; 1827 1828 extensionPlist = OSDynamicCast(OSDictionary, 1829 extensionDict->getObject("plist")); 1830 if (!extensionPlist) goto finish; 1831 1832 extensionPersonalities = OSDynamicCast(OSDictionary, 1833 extensionPlist->getObject("IOKitPersonalities")); 1834 if (!extensionPersonalities) goto finish; 1835 1836 /* If it was there, remove it from the catalogue proper 1837 * by calling removeDrivers(). Pass true for the second 1838 * argument to trigger a new round of matching, and 1839 * then remove the extension from the dictionary of startup 1840 * extensions. 1841 */ 1842 keyIterator = OSCollectionIterator::withCollection( 1843 extensionPersonalities); 1844 if (!keyIterator) { 1845 IOLog("Error: Couldn't allocate iterator to scan" 1846 " personalities for %s.\n", extensionName); 1847 LOG_DELAY(); 1848 } 1849 1850 while ((key = OSDynamicCast(OSString, keyIterator->getNextObject()))) { 1851 personality = OSDynamicCast(OSDictionary, 1852 extensionPersonalities->getObject(key)); 1853 1854 1855 if (personality) { 1856 gIOCatalogue->removeDrivers(personality, true); 1857 } 1858 } 1859 1860 startupExtensions->removeObject(extensionName); 1861 1862finish: 1863 1864 if (keyIterator) keyIterator->release(); 1865 return; 1866} 1867 1868/********************************************************************* 1869* FIXME: This function invalidates the globals gStartupExtensions and 1870* FIXME: ...gBootLoaderObjects without setting them to NULL. Since 1871* FIXME: ...the code itself is immediately unloaded, there may not be 1872* FIXME: ...any reason to worry about that! 1873*********************************************************************/ 1874void clearStartupExtensionsAndLoaderInfo(void) 1875{ 1876 OSDictionary * startupExtensions = NULL; // must release 1877 OSArray * bootLoaderObjects = NULL; // must release 1878 1879 IORegistryEntry * bootxMemoryMap = NULL; // must release 1880 OSDictionary * propertyDict = NULL; // must release 1881 OSCollectionIterator * keyIterator = NULL; // must release 1882 OSString * key = NULL; // don't release 1883 1884 /***** 1885 * Drop any temporarily held data objects. 1886 */ 1887 bootLoaderObjects = getBootLoaderObjects(); 1888 if (bootLoaderObjects) { 1889 bootLoaderObjects->release(); 1890 } 1891 1892 /**** 1893 * If any "code" entries in driver dictionaries are accompanied 1894 * by "compressedCode" entries, then those data objects were 1895 * created based of of kmem_alloc()'ed memory, which must be 1896 * freed specially. 1897 */ 1898 startupExtensions = getStartupExtensions(); 1899 if (startupExtensions) { 1900 keyIterator = 1901 OSCollectionIterator::withCollection(startupExtensions); 1902 if (!keyIterator) { 1903 IOLog("Error: Couldn't allocate iterator for startup " 1904 "extensions.\n"); 1905 LOG_DELAY(); 1906 goto memory_map; // bail to the memory_map label 1907 } 1908 1909 while ( (key = OSDynamicCast(OSString, 1910 keyIterator->getNextObject())) ) { 1911 1912 OSDictionary * driverDict = 0; 1913 OSData * codeData = 0; 1914 1915 driverDict = OSDynamicCast(OSDictionary, 1916 startupExtensions->getObject(key)); 1917 if (driverDict) { 1918 codeData = OSDynamicCast(OSData, 1919 driverDict->getObject("code")); 1920 1921 if (codeData && 1922 driverDict->getObject("compressedCode")) { 1923 1924 kmem_free(kernel_map, 1925 (unsigned int)codeData->getBytesNoCopy(), 1926 codeData->getLength()); 1927 } 1928 } 1929 } 1930 1931 keyIterator->release(); 1932 startupExtensions->release(); 1933 } 1934 1935memory_map: 1936 1937 /**** 1938 * Go through the device tree's memory map and remove any driver 1939 * data entries. 1940 */ 1941 bootxMemoryMap = 1942 IORegistryEntry::fromPath( 1943 "/chosen/memory-map", // path 1944 gIODTPlane // plane 1945 ); 1946 // return value is retained so be sure to release it 1947 1948 if (!bootxMemoryMap) { 1949 IOLog("Error: Couldn't read booter memory map.\n"); 1950 LOG_DELAY(); 1951 goto finish; 1952 } 1953 1954 propertyDict = bootxMemoryMap->dictionaryWithProperties(); 1955 if (!propertyDict) { 1956 IOLog("Error: Couldn't get property dictionary " 1957 "from memory map.\n"); 1958 LOG_DELAY(); 1959 goto finish; 1960 } 1961 1962 keyIterator = OSCollectionIterator::withCollection(propertyDict); 1963 if (!keyIterator) { 1964 IOLog("Error: Couldn't allocate iterator for driver images.\n"); 1965 LOG_DELAY(); 1966 goto finish; 1967 } 1968 1969 while ( (key = OSDynamicCast(OSString, 1970 keyIterator->getNextObject())) ) { 1971 1972 const char * keyValue = key->getCStringNoCopy(); 1973 1974 if ( !strncmp(keyValue, BOOTX_KEXT_PREFIX, 1975 strlen(BOOTX_KEXT_PREFIX)) || 1976 !strncmp(keyValue, BOOTX_MULTIKEXT_PREFIX, 1977 strlen(BOOTX_MULTIKEXT_PREFIX)) ) { 1978 1979 OSData * bootxDriverDataObject = NULL; 1980 MemoryMapFileInfo * driverInfo = 0; 1981 1982 bootxDriverDataObject = OSDynamicCast(OSData, 1983 propertyDict->getObject(keyValue)); 1984 // don't release bootxDriverDataObject 1985 1986 if (!bootxDriverDataObject) { 1987 continue; 1988 } 1989 driverInfo = (MemoryMapFileInfo *) 1990 bootxDriverDataObject->getBytesNoCopy(0, 1991 sizeof(MemoryMapFileInfo)); 1992 IODTFreeLoaderInfo((char *)keyValue, 1993 (void *)driverInfo->paddr, 1994 (int)driverInfo->length); 1995 } 1996 } 1997 1998finish: 1999 if (bootxMemoryMap) bootxMemoryMap->release(); 2000 if (propertyDict) propertyDict->release();
2001 if (keyIterator) keyIterator->release(); 2002 2003 return; 2004} 2005

