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