1/* 2 * Copyright (c) 1998-2012 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/* 29 * Copyright (c) 1998 Apple Inc. All rights reserved. 30 * 31 * HISTORY 32 * 33 */ 34/* 35 * NOTICE: This file was modified by SPARTA, Inc. in 2005 to introduce 36 * support for mandatory and extensible security protections. This notice 37 * is included in support of clause 2.2 (b) of the Apple Public License, 38 * Version 2.0. 39 */ 40 41extern "C" { 42#include <machine/machine_routines.h> 43#include <libkern/kernel_mach_header.h> 44#include <kern/host.h> 45#include <security/mac_data.h> 46}; 47 48#include <libkern/c++/OSContainers.h> 49#include <libkern/c++/OSUnserialize.h> 50#include <libkern/c++/OSKext.h> 51#include <libkern/OSKextLibPrivate.h> 52#include <libkern/OSDebug.h> 53 54#include <IOKit/IODeviceTreeSupport.h> 55#include <IOKit/IOService.h> 56#include <IOKit/IOCatalogue.h> 57 58#include <IOKit/IOLib.h> 59#include <IOKit/assert.h> 60 61#if PRAGMA_MARK 62#pragma mark Internal Declarations 63#endif 64/********************************************************************* 65*********************************************************************/ 66 67IOCatalogue * gIOCatalogue; 68const OSSymbol * gIOClassKey; 69const OSSymbol * gIOProbeScoreKey; 70const OSSymbol * gIOModuleIdentifierKey; 71IORWLock * gIOCatalogLock; 72 73#if PRAGMA_MARK 74#pragma mark Utility functions 75#endif 76 77#if PRAGMA_MARK 78#pragma mark IOCatalogue class implementation 79#endif 80/********************************************************************* 81*********************************************************************/ 82 83#define super OSObject 84OSDefineMetaClassAndStructors(IOCatalogue, OSObject) 85 86static bool isModuleLoadedNoOSKextLock(OSDictionary *theKexts, 87 OSDictionary *theModuleDict); 88 89 90/********************************************************************* 91*********************************************************************/ 92void IOCatalogue::initialize(void) 93{ 94 OSArray * array; 95 OSString * errorString; 96 bool rc; 97 98 extern const char * gIOKernelConfigTables; 99 100 array = OSDynamicCast(OSArray, OSUnserialize(gIOKernelConfigTables, &errorString)); 101 if (!array && errorString) { 102 IOLog("KernelConfigTables syntax error: %s\n", 103 errorString->getCStringNoCopy()); 104 errorString->release(); 105 } 106 107 gIOClassKey = OSSymbol::withCStringNoCopy( kIOClassKey ); 108 gIOProbeScoreKey = OSSymbol::withCStringNoCopy( kIOProbeScoreKey ); 109 gIOModuleIdentifierKey = OSSymbol::withCStringNoCopy( kCFBundleIdentifierKey ); 110 111 assert( array && gIOClassKey && gIOProbeScoreKey 112 && gIOModuleIdentifierKey); 113 114 gIOCatalogue = new IOCatalogue; 115 assert(gIOCatalogue); 116 rc = gIOCatalogue->init(array); 117 assert(rc); 118 array->release(); 119} 120 121/********************************************************************* 122* Initialize the IOCatalog object. 123*********************************************************************/ 124OSArray * IOCatalogue::arrayForPersonality(OSDictionary * dict) 125{ 126 const OSSymbol * sym; 127 128 sym = OSDynamicCast(OSSymbol, dict->getObject(gIOProviderClassKey)); 129 if (!sym) return (0); 130 131 return ((OSArray *) personalities->getObject(sym)); 132} 133 134void IOCatalogue::addPersonality(OSDictionary * dict) 135{ 136 const OSSymbol * sym; 137 OSArray * arr; 138 139 sym = OSDynamicCast(OSSymbol, dict->getObject(gIOProviderClassKey)); 140 if (!sym) return; 141 arr = (OSArray *) personalities->getObject(sym); 142 if (arr) arr->setObject(dict); 143 else 144 { 145 arr = OSArray::withObjects((const OSObject **)&dict, 1, 2); 146 personalities->setObject(sym, arr); 147 arr->release(); 148 } 149} 150 151/********************************************************************* 152* Initialize the IOCatalog object. 153*********************************************************************/ 154bool IOCatalogue::init(OSArray * initArray) 155{ 156 OSDictionary * dict; 157 OSObject * obj; 158 159 if ( !super::init() ) 160 return false; 161 162 generation = 1; 163 164 personalities = OSDictionary::withCapacity(32); 165 personalities->setOptions(OSCollection::kSort, OSCollection::kSort); 166 for (unsigned int idx = 0; (obj = initArray->getObject(idx)); idx++) 167 { 168 dict = OSDynamicCast(OSDictionary, obj); 169 if (!dict) continue; 170 OSKext::uniquePersonalityProperties(dict); 171 if( 0 == dict->getObject( gIOClassKey )) 172 { 173 IOLog("Missing or bad \"%s\" key\n", 174 gIOClassKey->getCStringNoCopy()); 175 continue; 176 } 177 dict->setObject("KernelConfigTable", kOSBooleanTrue); 178 addPersonality(dict); 179 } 180 181 gIOCatalogLock = IORWLockAlloc(); 182 lock = gIOCatalogLock; 183 184 return true; 185} 186 187/********************************************************************* 188* Release all resources used by IOCatalogue and deallocate. 189* This will probably never be called. 190*********************************************************************/ 191void IOCatalogue::free( void ) 192{ 193 panic(""); 194} 195 196/********************************************************************* 197*********************************************************************/ 198OSOrderedSet * 199IOCatalogue::findDrivers( 200 IOService * service, 201 SInt32 * generationCount) 202{ 203 OSDictionary * nextTable; 204 OSOrderedSet * set; 205 OSArray * array; 206 const OSMetaClass * meta; 207 unsigned int idx; 208 209 set = OSOrderedSet::withCapacity( 1, IOServiceOrdering, 210 (void *)gIOProbeScoreKey ); 211 if( !set ) 212 return( 0 ); 213 214 IORWLockRead(lock); 215 216 meta = service->getMetaClass(); 217 while (meta) 218 { 219 array = (OSArray *) personalities->getObject(meta->getClassNameSymbol()); 220 if (array) for (idx = 0; (nextTable = (OSDictionary *) array->getObject(idx)); idx++) 221 { 222 set->setObject(nextTable); 223 } 224 if (meta == &IOService::gMetaClass) break; 225 meta = meta->getSuperClass(); 226 } 227 228 *generationCount = getGenerationCount(); 229 230 IORWLockUnlock(lock); 231 232 return( set ); 233} 234 235/********************************************************************* 236* Is personality already in the catalog? 237*********************************************************************/ 238OSOrderedSet * 239IOCatalogue::findDrivers( 240 OSDictionary * matching, 241 SInt32 * generationCount) 242{ 243 OSCollectionIterator * iter; 244 OSDictionary * dict; 245 OSOrderedSet * set; 246 OSArray * array; 247 const OSSymbol * key; 248 unsigned int idx; 249 250 OSKext::uniquePersonalityProperties(matching); 251 252 set = OSOrderedSet::withCapacity( 1, IOServiceOrdering, 253 (void *)gIOProbeScoreKey ); 254 if (!set) return (0); 255 iter = OSCollectionIterator::withCollection(personalities); 256 if (!iter) 257 { 258 set->release(); 259 return (0); 260 } 261 262 IORWLockRead(lock); 263 while ((key = (const OSSymbol *) iter->getNextObject())) 264 { 265 array = (OSArray *) personalities->getObject(key); 266 if (array) for (idx = 0; (dict = (OSDictionary *) array->getObject(idx)); idx++) 267 { 268 /* This comparison must be done with only the keys in the 269 * "matching" dict to enable general searches. 270 */ 271 if ( dict->isEqualTo(matching, matching) ) 272 set->setObject(dict); 273 } 274 } 275 *generationCount = getGenerationCount(); 276 IORWLockUnlock(lock); 277 278 iter->release(); 279 return set; 280} 281 282/********************************************************************* 283* Add driver config tables to catalog and start matching process. 284* 285* Important that existing personalities are kept (not replaced) 286* if duplicates found. Personalities can come from OSKext objects 287* or from userland kext library. We want to minimize distinct 288* copies between OSKext & IOCatalogue. 289* 290* xxx - userlib used to refuse to send personalities with IOKitDebug 291* xxx - during safe boot. That would be better implemented here. 292*********************************************************************/ 293 294bool IOCatalogue::addDrivers( 295 OSArray * drivers, 296 bool doNubMatching) 297{ 298 bool result = false; 299 OSCollectionIterator * iter = NULL; // must release 300 OSOrderedSet * set = NULL; // must release 301 OSObject * object = NULL; // do not release 302 OSArray * persons = NULL; // do not release 303 304 persons = OSDynamicCast(OSArray, drivers); 305 if (!persons) { 306 goto finish; 307 } 308 309 set = OSOrderedSet::withCapacity( 10, IOServiceOrdering, 310 (void *)gIOProbeScoreKey ); 311 if (!set) { 312 goto finish; 313 } 314 315 iter = OSCollectionIterator::withCollection(persons); 316 if (!iter) { 317 goto finish; 318 } 319 320 /* Start with success; clear it on an error. 321 */ 322 result = true; 323 324 IORWLockWrite(lock); 325 while ( (object = iter->getNextObject()) ) { 326 327 // xxx Deleted OSBundleModuleDemand check; will handle in other ways for SL 328 329 OSDictionary * personality = OSDynamicCast(OSDictionary, object); 330 331 SInt count; 332 333 if (!personality) { 334 IOLog("IOCatalogue::addDrivers() encountered non-dictionary; bailing.\n"); 335 result = false; 336 break; 337 } 338 339 OSKext::uniquePersonalityProperties(personality); 340 341 // Add driver personality to catalogue. 342 343 OSArray * array = arrayForPersonality(personality); 344 if (!array) addPersonality(personality); 345 else 346 { 347 count = array->getCount(); 348 while (count--) { 349 OSDictionary * driver; 350 351 // Be sure not to double up on personalities. 352 driver = (OSDictionary *)array->getObject(count); 353 354 /* Unlike in other functions, this comparison must be exact! 355 * The catalogue must be able to contain personalities that 356 * are proper supersets of others. 357 * Do not compare just the properties present in one driver 358 * personality or the other. 359 */ 360 if (personality->isEqualTo(driver)) { 361 break; 362 } 363 } 364 if (count >= 0) { 365 // its a dup 366 continue; 367 } 368 result = array->setObject(personality); 369 if (!result) { 370 break; 371 } 372 } 373 374 set->setObject(personality); 375 } 376 // Start device matching. 377 if (result && doNubMatching && (set->getCount() > 0)) { 378 IOService::catalogNewDrivers(set); 379 generation++; 380 } 381 IORWLockUnlock(lock); 382 383finish: 384 if (set) set->release(); 385 if (iter) iter->release(); 386 387 return result; 388} 389 390/********************************************************************* 391* Remove drivers from the catalog which match the 392* properties in the matching dictionary. 393*********************************************************************/ 394bool 395IOCatalogue::removeDrivers( 396 OSDictionary * matching, 397 bool doNubMatching) 398{ 399 OSOrderedSet * set; 400 OSCollectionIterator * iter; 401 OSDictionary * dict; 402 OSArray * array; 403 const OSSymbol * key; 404 unsigned int idx; 405 406 if ( !matching ) 407 return false; 408 409 set = OSOrderedSet::withCapacity(10, 410 IOServiceOrdering, 411 (void *)gIOProbeScoreKey); 412 if ( !set ) 413 return false; 414 iter = OSCollectionIterator::withCollection(personalities); 415 if (!iter) 416 { 417 set->release(); 418 return (false); 419 } 420 421 IORWLockWrite(lock); 422 while ((key = (const OSSymbol *) iter->getNextObject())) 423 { 424 array = (OSArray *) personalities->getObject(key); 425 if (array) for (idx = 0; (dict = (OSDictionary *) array->getObject(idx)); idx++) 426 { 427 /* This comparison must be done with only the keys in the 428 * "matching" dict to enable general searches. 429 */ 430 if ( dict->isEqualTo(matching, matching) ) { 431 set->setObject(dict); 432 array->removeObject(idx); 433 idx--; 434 } 435 } 436 // Start device matching. 437 if ( doNubMatching && (set->getCount() > 0) ) { 438 IOService::catalogNewDrivers(set); 439 generation++; 440 } 441 } 442 IORWLockUnlock(lock); 443 444 set->release(); 445 iter->release(); 446 447 return true; 448} 449 450// Return the generation count. 451SInt32 IOCatalogue::getGenerationCount(void) const 452{ 453 return( generation ); 454} 455 456bool IOCatalogue::isModuleLoaded(OSString * moduleName) const 457{ 458 return isModuleLoaded(moduleName->getCStringNoCopy()); 459} 460 461bool IOCatalogue::isModuleLoaded(const char * moduleName) const 462{ 463 OSReturn ret; 464 ret = OSKext::loadKextWithIdentifier(moduleName); 465 if (kOSKextReturnDeferred == ret) { 466 // a request has been queued but the module isn't necessarily 467 // loaded yet, so stall. 468 return false; 469 } 470 // module is present or never will be 471 return true; 472} 473 474// Check to see if module has been loaded already. 475bool IOCatalogue::isModuleLoaded(OSDictionary * driver) const 476{ 477 OSString * moduleName = NULL; 478 OSString * publisherName = NULL; 479 480 if ( !driver ) 481 return false; 482 483 /* The personalities of codeless kexts often contain the bundle ID of the 484 * kext they reference, and not the bundle ID of the codeless kext itself. 485 * The prelinked kernel needs to know the bundle ID of the codeless kext 486 * so it can include these personalities, so OSKext stores that bundle ID 487 * in the IOPersonalityPublisher key, and we record it as requested here. 488 */ 489 publisherName = OSDynamicCast(OSString, 490 driver->getObject(kIOPersonalityPublisherKey)); 491 OSKext::recordIdentifierRequest(publisherName); 492 493 moduleName = OSDynamicCast(OSString, driver->getObject(gIOModuleIdentifierKey)); 494 if ( moduleName ) 495 return isModuleLoaded(moduleName); 496 497 /* If a personality doesn't hold the "CFBundleIdentifier" key 498 * it is assumed to be an "in-kernel" driver. 499 */ 500 return true; 501} 502 503/* This function is called after a module has been loaded. 504 * Is invoked from user client call, ultimately from IOKitLib's 505 * IOCatalogueModuleLoaded(). Sent from kextd. 506 */ 507void IOCatalogue::moduleHasLoaded(OSString * moduleName) 508{ 509 OSDictionary * dict; 510 511 dict = OSDictionary::withCapacity(2); 512 dict->setObject(gIOModuleIdentifierKey, moduleName); 513 startMatching(dict); 514 dict->release(); 515 516 (void) OSKext::setDeferredLoadSucceeded(); 517 (void) OSKext::considerRebuildOfPrelinkedKernel(); 518} 519 520void IOCatalogue::moduleHasLoaded(const char * moduleName) 521{ 522 OSString * name; 523 524 name = OSString::withCString(moduleName); 525 moduleHasLoaded(name); 526 name->release(); 527} 528 529// xxx - return is really OSReturn/kern_return_t 530IOReturn IOCatalogue::unloadModule(OSString * moduleName) const 531{ 532 return OSKext::removeKextWithIdentifier(moduleName->getCStringNoCopy()); 533} 534 535IOReturn IOCatalogue::_terminateDrivers(OSDictionary * matching) 536{ 537 OSDictionary * dict; 538 OSIterator * iter; 539 IOService * service; 540 IOReturn ret; 541 542 if ( !matching ) 543 return kIOReturnBadArgument; 544 545 ret = kIOReturnSuccess; 546 dict = 0; 547 iter = IORegistryIterator::iterateOver(gIOServicePlane, 548 kIORegistryIterateRecursively); 549 if ( !iter ) 550 return kIOReturnNoMemory; 551 552 OSKext::uniquePersonalityProperties( matching ); 553 554 // terminate instances. 555 do { 556 iter->reset(); 557 while( (service = (IOService *)iter->getNextObject()) ) { 558 dict = service->getPropertyTable(); 559 if ( !dict ) 560 continue; 561 562 /* Terminate only for personalities that match the matching dictionary. 563 * This comparison must be done with only the keys in the 564 * "matching" dict to enable general matching. 565 */ 566 if ( !dict->isEqualTo(matching, matching) ) 567 continue; 568 569 if ( !service->terminate(kIOServiceRequired|kIOServiceSynchronous) ) { 570 ret = kIOReturnUnsupported; 571 break; 572 } 573 } 574 } while( !service && !iter->isValid()); 575 iter->release(); 576 577 return ret; 578} 579 580IOReturn IOCatalogue::_removeDrivers(OSDictionary * matching) 581{ 582 IOReturn ret = kIOReturnSuccess; 583 OSCollectionIterator * iter; 584 OSDictionary * dict; 585 OSArray * array; 586 const OSSymbol * key; 587 unsigned int idx; 588 589 // remove configs from catalog. 590 591 iter = OSCollectionIterator::withCollection(personalities); 592 if (!iter) return (kIOReturnNoMemory); 593 594 while ((key = (const OSSymbol *) iter->getNextObject())) 595 { 596 array = (OSArray *) personalities->getObject(key); 597 if (array) for (idx = 0; (dict = (OSDictionary *) array->getObject(idx)); idx++) 598 { 599 600 /* Remove from the catalogue's array any personalities 601 * that match the matching dictionary. 602 * This comparison must be done with only the keys in the 603 * "matching" dict to enable general matching. 604 */ 605 if (dict->isEqualTo(matching, matching)) 606 { 607 array->removeObject(idx); 608 idx--; 609 } 610 } 611 } 612 iter->release(); 613 614 return ret; 615} 616 617IOReturn IOCatalogue::terminateDrivers(OSDictionary * matching) 618{ 619 IOReturn ret; 620 621 ret = _terminateDrivers(matching); 622 IORWLockWrite(lock); 623 if (kIOReturnSuccess == ret) 624 ret = _removeDrivers(matching); 625 IORWLockUnlock(lock); 626 627 return ret; 628} 629 630IOReturn IOCatalogue::terminateDriversForModule( 631 OSString * moduleName, 632 bool unload) 633{ 634 IOReturn ret; 635 OSDictionary * dict; 636 bool isLoaded = false; 637 638 /* Check first if the kext currently has any linkage dependents; 639 * in such a case the unload would fail so let's not terminate any 640 * IOServices (since doing so typically results in a panic when there 641 * are loaded dependencies). Note that we aren't locking the kext here 642 * so it might lose or gain dependents by the time we call unloadModule(); 643 * I think that's ok, our unload can fail if a kext comes in on top of 644 * this one even after we've torn down IOService objects. Conversely, 645 * if we fail the unload here and then lose a library, the autounload 646 * thread will get us in short order. 647 */ 648 if (OSKext::isKextWithIdentifierLoaded(moduleName->getCStringNoCopy())) { 649 650 isLoaded = true; 651 652 if (!OSKext::canUnloadKextWithIdentifier(moduleName, 653 /* checkClasses */ false)) { 654 ret = kOSKextReturnInUse; 655 goto finish; 656 } 657 } 658 dict = OSDictionary::withCapacity(1); 659 if (!dict) { 660 ret = kIOReturnNoMemory; 661 goto finish; 662 } 663 664 dict->setObject(gIOModuleIdentifierKey, moduleName); 665 666 ret = _terminateDrivers(dict); 667 668 /* No goto between IOLock calls! 669 */ 670 IORWLockWrite(lock); 671 if (kIOReturnSuccess == ret) { 672 ret = _removeDrivers(dict); 673 } 674 675 // Unload the module itself. 676 if (unload && isLoaded && ret == kIOReturnSuccess) { 677 ret = unloadModule(moduleName); 678 } 679 680 IORWLockUnlock(lock); 681 682 dict->release(); 683 684finish: 685 return ret; 686} 687 688IOReturn IOCatalogue::terminateDriversForModule( 689 const char * moduleName, 690 bool unload) 691{ 692 OSString * name; 693 IOReturn ret; 694 695 name = OSString::withCString(moduleName); 696 if ( !name ) 697 return kIOReturnNoMemory; 698 699 ret = terminateDriversForModule(name, unload); 700 name->release(); 701 702 return ret; 703} 704 705bool IOCatalogue::startMatching( OSDictionary * matching ) 706{ 707 OSCollectionIterator * iter; 708 OSDictionary * dict; 709 OSOrderedSet * set; 710 OSArray * array; 711 const OSSymbol * key; 712 unsigned int idx; 713 714 if ( !matching ) 715 return false; 716 717 set = OSOrderedSet::withCapacity(10, IOServiceOrdering, 718 (void *)gIOProbeScoreKey); 719 if ( !set ) 720 return false; 721 722 iter = OSCollectionIterator::withCollection(personalities); 723 if (!iter) 724 { 725 set->release(); 726 return false; 727 } 728 729 IORWLockRead(lock); 730 731 while ((key = (const OSSymbol *) iter->getNextObject())) 732 { 733 array = (OSArray *) personalities->getObject(key); 734 if (array) for (idx = 0; (dict = (OSDictionary *) array->getObject(idx)); idx++) 735 { 736 /* This comparison must be done with only the keys in the 737 * "matching" dict to enable general matching. 738 */ 739 if (dict->isEqualTo(matching, matching)) { 740 set->setObject(dict); 741 } 742 } 743 } 744 745 // Start device matching. 746 if ( set->getCount() > 0 ) { 747 IOService::catalogNewDrivers(set); 748 generation++; 749 } 750 751 IORWLockUnlock(lock); 752 753 set->release(); 754 iter->release(); 755 756 return true; 757} 758 759void IOCatalogue::reset(void) 760{ 761 IOCatalogue::resetAndAddDrivers(/* no drivers; true reset */ NULL, 762 /* doMatching */ false); 763 return; 764} 765 766bool IOCatalogue::resetAndAddDrivers(OSArray * drivers, bool doNubMatching) 767{ 768 bool result = false; 769 OSArray * newPersonalities = NULL; // do not release 770 OSCollectionIterator * iter = NULL; // must release 771 OSOrderedSet * matchSet = NULL; // must release 772 const OSSymbol * key; 773 OSArray * array; 774 OSDictionary * thisNewPersonality = NULL; // do not release 775 OSDictionary * thisOldPersonality = NULL; // do not release 776 OSDictionary * myKexts = NULL; // must release 777 signed int idx, newIdx; 778 779 if (drivers) { 780 newPersonalities = OSDynamicCast(OSArray, drivers); 781 if (!newPersonalities) { 782 goto finish; 783 } 784 } 785 matchSet = OSOrderedSet::withCapacity(10, IOServiceOrdering, 786 (void *)gIOProbeScoreKey); 787 if (!matchSet) { 788 goto finish; 789 } 790 iter = OSCollectionIterator::withCollection(personalities); 791 if (!iter) { 792 goto finish; 793 } 794 795 /* need copy of loaded kexts so we can check if for loaded modules without 796 * taking the OSKext lock. There is a potential of deadlocking if we get 797 * an OSKext via the normal path. See 14672140. 798 */ 799 myKexts = OSKext::copyKexts(); 800 801 result = true; 802 803 IOLog("Resetting IOCatalogue.\n"); 804 805 /* No goto finish from here to unlock. 806 */ 807 IORWLockWrite(lock); 808 809 while ((key = (const OSSymbol *) iter->getNextObject())) 810 { 811 array = (OSArray *) personalities->getObject(key); 812 if (!array) continue; 813 814 for (idx = 0; 815 (thisOldPersonality = (OSDictionary *) array->getObject(idx)); 816 idx++) 817 { 818 if (thisOldPersonality->getObject("KernelConfigTable")) continue; 819 thisNewPersonality = NULL; 820 821 if (newPersonalities) { 822 for (newIdx = 0; 823 (thisNewPersonality = (OSDictionary *) newPersonalities->getObject(newIdx)); 824 newIdx++) 825 { 826 /* Unlike in other functions, this comparison must be exact! 827 * The catalogue must be able to contain personalities that 828 * are proper supersets of others. 829 * Do not compare just the properties present in one driver 830 * personality or the other. 831 */ 832 if (OSDynamicCast(OSDictionary, thisNewPersonality) == NULL) { 833 /* skip thisNewPersonality if it is not an OSDictionary */ 834 continue; 835 } 836 if (thisNewPersonality->isEqualTo(thisOldPersonality)) 837 break; 838 } 839 } 840 if (thisNewPersonality) { 841 // dup, ignore 842 newPersonalities->removeObject(newIdx); 843 } 844 else { 845 // not in new set - remove 846 // only remove dictionary if this module in not loaded - 9953845 847 if ( isModuleLoadedNoOSKextLock(myKexts, thisOldPersonality) == false ) { 848 if (matchSet) { 849 matchSet->setObject(thisOldPersonality); 850 } 851 array->removeObject(idx); 852 idx--; 853 } 854 } 855 } // for... 856 } // while... 857 858 // add new 859 if (newPersonalities) { 860 for (newIdx = 0; 861 (thisNewPersonality = (OSDictionary *) newPersonalities->getObject(newIdx)); 862 newIdx++) 863 { 864 if (OSDynamicCast(OSDictionary, thisNewPersonality) == NULL) { 865 /* skip thisNewPersonality if it is not an OSDictionary */ 866 continue; 867 } 868 869 OSKext::uniquePersonalityProperties(thisNewPersonality); 870 addPersonality(thisNewPersonality); 871 matchSet->setObject(thisNewPersonality); 872 } 873 } 874 875 /* Finally, start device matching on all new & removed personalities. 876 */ 877 if (result && doNubMatching && (matchSet->getCount() > 0)) { 878 IOService::catalogNewDrivers(matchSet); 879 generation++; 880 } 881 882 IORWLockUnlock(lock); 883 884finish: 885 if (matchSet) matchSet->release(); 886 if (iter) iter->release(); 887 if (myKexts) myKexts->release(); 888 889 return result; 890} 891 892bool IOCatalogue::serialize(OSSerialize * s) const 893{ 894 if ( !s ) 895 return false; 896 897 return super::serialize(s); 898} 899 900bool IOCatalogue::serializeData(IOOptionBits kind, OSSerialize * s) const 901{ 902 kern_return_t kr = kIOReturnSuccess; 903 904 switch ( kind ) 905 { 906 case kIOCatalogGetContents: 907 kr = KERN_NOT_SUPPORTED; 908 break; 909 910 case kIOCatalogGetModuleDemandList: 911 kr = KERN_NOT_SUPPORTED; 912 break; 913 914 case kIOCatalogGetCacheMissList: 915 kr = KERN_NOT_SUPPORTED; 916 break; 917 918 case kIOCatalogGetROMMkextList: 919 kr = KERN_NOT_SUPPORTED; 920 break; 921 922 default: 923 kr = kIOReturnBadArgument; 924 break; 925 } 926 927 return kr; 928} 929 930/* isModuleLoadedNoOSKextLock - used to check to see if a kext is loaded 931 * without taking the OSKext lock. We use this to avoid the problem 932 * where taking the IOCatalog lock then the OSKext lock will dealock when 933 * a kext load or unload is happening at the same time as IOCatalog changing. 934 * 935 * theKexts - is a dictionary of current kexts (from OSKext::copyKexts) with 936 * key set to the kext bundle ID and value set to an OSKext object 937 * theModuleDict - is an IOKit personality dictionary for a given module (kext) 938 */ 939static bool isModuleLoadedNoOSKextLock(OSDictionary *theKexts, 940 OSDictionary *theModuleDict) 941{ 942 bool myResult = false; 943 const OSString * myBundleID = NULL; // do not release 944 OSKext * myKext = NULL; // do not release 945 946 if (theKexts == NULL || theModuleDict == NULL) { 947 return( myResult ); 948 } 949 950 // gIOModuleIdentifierKey is "CFBundleIdentifier" 951 myBundleID = OSDynamicCast(OSString, 952 theModuleDict->getObject(gIOModuleIdentifierKey)); 953 if (myBundleID == NULL) { 954 return( myResult ); 955 } 956 957 myKext = OSDynamicCast(OSKext, theKexts->getObject(myBundleID->getCStringNoCopy())); 958 if (myKext) { 959 myResult = myKext->isLoaded(); 960 } 961 962 return( myResult ); 963} 964 965 966#if PRAGMA_MARK 967#pragma mark Obsolete Kext Loading Stuff 968#endif 969/********************************************************************* 970********************************************************************** 971*** BINARY COMPATIBILITY SECTION *** 972********************************************************************** 973********************************************************************** 974* These functions are no longer used are necessary for C++ binary 975* compatibility on i386. 976**********************************************************************/ 977