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