1 /* 2 * Copyright (c) 1998-2019 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 #include <IOKit/IORegistryEntry.h> 30 #include <libkern/c++/OSContainers.h> 31 #include <IOKit/IOService.h> 32 #include <IOKit/IOKitKeys.h> 33 #include <IOKit/IOTimeStamp.h> 34 #include <libkern/c++/OSSharedPtr.h> 35 #include <libkern/c++/OSBoundedPtr.h> 36 37 #include <IOKit/IOLib.h> 38 #include <stdatomic.h> 39 #include <IOKit/assert.h> 40 #include <machine/atomic.h> 41 42 #include "IOKitKernelInternal.h" 43 44 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 45 46 #define super OSObject 47 48 OSDefineMetaClassAndStructors(IORegistryEntry, OSObject) 49 50 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 51 52 #define kIORegPlaneParentSuffix "ParentLinks" 53 #define kIORegPlaneChildSuffix "ChildLinks" 54 #define kIORegPlaneNameSuffix "Name" 55 #define kIORegPlaneLocationSuffix "Location" 56 57 #define kIORegPlaneParentSuffixLen (sizeof(kIORegPlaneParentSuffix) - 1) 58 #define kIORegPlaneChildSuffixLen (sizeof(kIORegPlaneChildSuffix) - 1) 59 #define kIORegPlaneNameSuffixLen (sizeof(kIORegPlaneNameSuffix) - 1) 60 #define kIORegPlaneLocationSuffixLen (sizeof(kIORegPlaneLocationSuffix) - 1) 61 62 #define KASLR_IOREG_DEBUG 0 63 64 struct IORegistryEntry::ExpansionData { 65 IORecursiveLock * fLock; 66 uint64_t fRegistryEntryID; 67 SInt32 fRegistryEntryParentGenerationCount; 68 OSObject **_Atomic fIndexedProperties; 69 }; 70 71 72 static IORegistryEntry * gRegistryRoot; 73 static OSDictionary * gIORegistryPlanes; 74 75 const OSSymbol * gIONameKey; 76 const OSSymbol * gIOLocationKey; 77 const OSSymbol * gIORegistryEntryIDKey; 78 const OSSymbol * gIORegistryEntryPropertyKeysKey; 79 const OSSymbol * gIORegistryEntryAllowableSetPropertiesKey; 80 const OSSymbol * gIORegistryEntryDefaultLockingSetPropertiesKey; 81 82 enum { 83 kParentSetIndex = 0, 84 kChildSetIndex = 1, 85 kNumSetIndex 86 }; 87 enum { 88 kIOMaxPlaneName = 32 89 }; 90 91 enum { kIORegistryIDReserved = (1ULL << 32) + 255 }; 92 93 static uint64_t gIORegistryLastID = kIORegistryIDReserved; 94 95 class IORegistryPlane : public OSObject { 96 friend class IORegistryEntry; 97 98 OSDeclareAbstractStructors(IORegistryPlane); 99 100 const OSSymbol * nameKey; 101 const OSSymbol * keys[kNumSetIndex]; 102 const OSSymbol * pathNameKey; 103 const OSSymbol * pathLocationKey; 104 int reserved[2]; 105 106 public: 107 virtual bool serialize(OSSerialize *s) const APPLE_KEXT_OVERRIDE; 108 }; 109 110 OSDefineMetaClassAndStructors(IORegistryPlane, OSObject) 111 112 113 static SInt32 gIORegistryGenerationCount; 114 115 #define UNLOCK lck_rw_done( &gIORegistryLock ) 116 #define RLOCK lck_rw_lock_shared( &gIORegistryLock ) 117 #define WLOCK lck_rw_lock_exclusive( &gIORegistryLock ); \ 118 gIORegistryGenerationCount++ 119 // make atomic 120 121 #define PUNLOCK IORecursiveLockUnlock( reserved->fLock ) 122 #define PLOCK IORecursiveLockLock( reserved->fLock ) 123 124 #define IOREGSPLITTABLES 125 126 #ifdef IOREGSPLITTABLES 127 #define registryTable() fRegistryTable 128 #else 129 #define registryTable() fPropertyTable 130 #endif 131 132 #define DEBUG_FREE 1 133 134 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 135 136 lck_rw_t gIORegistryLock; 137 lck_grp_t *gIORegistryLockGrp; 138 lck_grp_attr_t *gIORegistryLockGrpAttr; 139 lck_attr_t *gIORegistryLockAttr; 140 141 142 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 143 144 IORegistryEntry * 145 IORegistryEntry::initialize( void ) 146 { 147 bool ok; 148 149 if (!gRegistryRoot) { 150 gIORegistryLockGrpAttr = lck_grp_attr_alloc_init(); 151 gIORegistryLockGrp = lck_grp_alloc_init("IORegistryLock", gIORegistryLockGrpAttr); 152 gIORegistryLockAttr = lck_attr_alloc_init(); 153 lck_attr_rw_shared_priority(gIORegistryLockAttr); 154 lck_rw_init( &gIORegistryLock, gIORegistryLockGrp, gIORegistryLockAttr); 155 156 gRegistryRoot = new IORegistryEntry; 157 gIORegistryPlanes = OSDictionary::withCapacity( 1 ); 158 159 assert( gRegistryRoot && gIORegistryPlanes ); 160 ok = gRegistryRoot->init(); 161 162 if (ok) { 163 gRegistryRoot->reserved->fRegistryEntryID = ++gIORegistryLastID; 164 } 165 166 gIONameKey = OSSymbol::withCStringNoCopy( "IOName" ); 167 gIOLocationKey = OSSymbol::withCStringNoCopy( "IOLocation" ); 168 gIORegistryEntryIDKey = OSSymbol::withCStringNoCopy( kIORegistryEntryIDKey ); 169 gIORegistryEntryPropertyKeysKey = OSSymbol::withCStringNoCopy( kIORegistryEntryPropertyKeysKey ); 170 gIORegistryEntryAllowableSetPropertiesKey = OSSymbol::withCStringNoCopy( kIORegistryEntryAllowableSetPropertiesKey ); 171 gIORegistryEntryDefaultLockingSetPropertiesKey = OSSymbol::withCStringNoCopy( kIORegistryEntryDefaultLockingSetPropertiesKey ); 172 173 assert( ok && gIONameKey && gIOLocationKey ); 174 175 gRegistryRoot->setName( "Root" ); 176 gRegistryRoot->setProperty( kIORegistryPlanesKey, gIORegistryPlanes ); 177 } 178 179 return gRegistryRoot; 180 } 181 182 IORegistryEntry * 183 IORegistryEntry::getRegistryRoot( void ) 184 { 185 return gRegistryRoot; 186 } 187 188 SInt32 189 IORegistryEntry::getGenerationCount( void ) 190 { 191 return gIORegistryGenerationCount; 192 } 193 194 SInt32 195 IORegistryEntry::getRegistryEntryParentGenerationCount(void) const 196 { 197 return reserved->fRegistryEntryParentGenerationCount; 198 } 199 200 const IORegistryPlane * 201 IORegistryEntry::makePlane( const char * name ) 202 { 203 IORegistryPlane * plane; 204 const OSSymbol * nameKey; 205 const OSSymbol * parentKey; 206 const OSSymbol * childKey; 207 const OSSymbol * pathNameKey; 208 const OSSymbol * pathLocationKey; 209 char key[kIOMaxPlaneName + 16]; 210 char * end; 211 212 strlcpy( key, name, kIOMaxPlaneName + 1 ); 213 end = key + strlen( key ); 214 215 nameKey = OSSymbol::withCString( key); 216 217 strlcpy( end, kIORegPlaneParentSuffix, kIORegPlaneParentSuffixLen + 1 ); 218 parentKey = OSSymbol::withCString( key); 219 220 strlcpy( end, kIORegPlaneChildSuffix, kIORegPlaneChildSuffixLen + 1 ); 221 childKey = OSSymbol::withCString( key); 222 223 strlcpy( end, kIORegPlaneNameSuffix, kIORegPlaneNameSuffixLen + 1 ); 224 pathNameKey = OSSymbol::withCString( key); 225 226 strlcpy( end, kIORegPlaneLocationSuffix, kIORegPlaneLocationSuffixLen + 1 ); 227 pathLocationKey = OSSymbol::withCString( key); 228 229 plane = new IORegistryPlane; 230 231 if (plane && plane->init() 232 && nameKey && parentKey && childKey 233 && pathNameKey && pathLocationKey) { 234 plane->nameKey = nameKey; 235 plane->keys[kParentSetIndex] = parentKey; 236 plane->keys[kChildSetIndex] = childKey; 237 plane->pathNameKey = pathNameKey; 238 plane->pathLocationKey = pathLocationKey; 239 240 WLOCK; 241 gIORegistryPlanes->setObject( nameKey, plane ); 242 UNLOCK; 243 } else { 244 if (plane) { 245 plane->release(); 246 } 247 if (pathLocationKey) { 248 pathLocationKey->release(); 249 } 250 if (pathNameKey) { 251 pathNameKey->release(); 252 } 253 if (parentKey) { 254 parentKey->release(); 255 } 256 if (childKey) { 257 childKey->release(); 258 } 259 if (nameKey) { 260 nameKey->release(); 261 } 262 plane = NULL; 263 } 264 265 return plane; 266 } 267 268 const IORegistryPlane * 269 IORegistryEntry::getPlane( const char * name ) 270 { 271 const IORegistryPlane * plane; 272 273 RLOCK; 274 plane = (const IORegistryPlane *) gIORegistryPlanes->getObject( name ); 275 UNLOCK; 276 277 return plane; 278 } 279 280 bool 281 IORegistryPlane::serialize(OSSerialize *s) const 282 { 283 return nameKey->serialize(s); 284 } 285 286 enum { kIORegCapacityIncrement = 4 }; 287 288 bool 289 IORegistryEntry::init( OSDictionary * dict ) 290 { 291 OSString * prop; 292 293 if (!super::init()) { 294 return false; 295 } 296 297 if (!reserved) { 298 reserved = IOMallocType(ExpansionData); 299 reserved->fLock = IORecursiveLockAlloc(); 300 if (!reserved->fLock) { 301 return false; 302 } 303 } 304 if (dict) { 305 if (OSCollection::kImmutable & dict->setOptions(0, 0)) { 306 dict = (OSDictionary *) dict->copyCollection(); 307 if (!dict) { 308 return false; 309 } 310 } else { 311 dict->retain(); 312 } 313 if (fPropertyTable) { 314 fPropertyTable->release(); 315 } 316 fPropertyTable = dict; 317 } else if (!fPropertyTable) { 318 fPropertyTable = OSDictionary::withCapacity( kIORegCapacityIncrement ); 319 if (fPropertyTable) { 320 fPropertyTable->setCapacityIncrement( kIORegCapacityIncrement ); 321 } 322 } 323 324 if (!fPropertyTable) { 325 return false; 326 } 327 328 #ifdef IOREGSPLITTABLES 329 if (!fRegistryTable) { 330 fRegistryTable = OSDictionary::withCapacity( kIORegCapacityIncrement ); 331 assertf(fRegistryTable, "Unable to allocate small capacity"); 332 fRegistryTable->setCapacityIncrement( kIORegCapacityIncrement ); 333 } 334 335 if ((prop = OSDynamicCast( OSString, getProperty( gIONameKey)))) { 336 OSSymbol * sym = (OSSymbol *)OSSymbol::withString( prop); 337 // ok for OSSymbol too 338 setName( sym); 339 sym->release(); 340 } 341 342 #endif /* IOREGSPLITTABLES */ 343 344 return true; 345 } 346 347 bool 348 IORegistryEntry::init( IORegistryEntry * old, 349 const IORegistryPlane * plane ) 350 { 351 OSArray * all; 352 IORegistryEntry * next; 353 unsigned int index; 354 355 if (!super::init()) { 356 return false; 357 } 358 359 if (!reserved) { 360 reserved = IOMallocType(ExpansionData); 361 reserved->fLock = IORecursiveLockAlloc(); 362 if (!reserved->fLock) { 363 return false; 364 } 365 } 366 367 WLOCK; 368 369 reserved->fRegistryEntryID = ++gIORegistryLastID; 370 371 fPropertyTable = old->dictionaryWithProperties(); 372 #ifdef IOREGSPLITTABLES 373 fRegistryTable = OSDictionary::withCapacity( kIORegCapacityIncrement ); 374 assertf(fRegistryTable, "Unable to allocate small capacity"); 375 fRegistryTable->setCapacityIncrement( kIORegCapacityIncrement ); 376 377 fRegistryTable->setObject(gIONameKey, old->fRegistryTable->getObject(gIONameKey)); 378 fRegistryTable->setObject(gIOLocationKey, old->fRegistryTable->getObject(gIOLocationKey)); 379 fRegistryTable->setObject(plane->nameKey, old->fRegistryTable->getObject(plane->nameKey)); 380 fRegistryTable->setObject(plane->pathNameKey, old->fRegistryTable->getObject(plane->pathNameKey)); 381 fRegistryTable->setObject(plane->pathLocationKey, old->fRegistryTable->getObject(plane->pathLocationKey)); 382 fRegistryTable->setObject(plane->keys[kParentSetIndex], old->fRegistryTable->getObject(plane->keys[kParentSetIndex])); 383 fRegistryTable->setObject(plane->keys[kChildSetIndex], old->fRegistryTable->getObject(plane->keys[kChildSetIndex])); 384 #endif /* IOREGSPLITTABLES */ 385 386 old->registryTable()->removeObject( plane->keys[kParentSetIndex] ); 387 old->registryTable()->removeObject( plane->keys[kChildSetIndex] ); 388 389 all = getParentSetReference( plane ); 390 if (all) { 391 for (index = 0; 392 (next = (IORegistryEntry *) all->getObject(index)); 393 index++) { 394 next->makeLink( this, kChildSetIndex, plane ); 395 next->breakLink( old, kChildSetIndex, plane ); 396 } 397 } 398 399 all = getChildSetReference( plane ); 400 if (all) { 401 for (index = 0; 402 (next = (IORegistryEntry *) all->getObject(index)); 403 index++) { 404 next->makeLink( this, kParentSetIndex, plane ); 405 next->breakLink( old, kParentSetIndex, plane ); 406 } 407 } 408 409 UNLOCK; 410 411 return true; 412 } 413 414 void 415 IORegistryEntry::free( void ) 416 { 417 #if DEBUG_FREE 418 if (registryTable() && gIOServicePlane) { 419 if (getParentSetReference( gIOServicePlane ) 420 || getChildSetReference( gIOServicePlane )) { 421 RLOCK; 422 if (getParentSetReference( gIOServicePlane ) 423 || getChildSetReference( gIOServicePlane )) { 424 panic("%s: attached at free()", getName()); 425 } 426 UNLOCK; 427 } 428 } 429 #endif 430 431 if (getPropertyTable()) { 432 getPropertyTable()->release(); 433 } 434 435 #ifdef IOREGSPLITTABLES 436 if (registryTable()) { 437 registryTable()->release(); 438 } 439 #endif /* IOREGSPLITTABLES */ 440 441 if (reserved) { 442 OSObject ** array = os_atomic_load(&reserved->fIndexedProperties, acquire); 443 if (array) { 444 for (int idx = 0; idx < kIORegistryEntryIndexedPropertyCount; idx++) { 445 if (array[idx]) { 446 array[idx]->release(); 447 } 448 } 449 IODelete(array, OSObject *, kIORegistryEntryIndexedPropertyCount); 450 } 451 if (reserved->fLock) { 452 IORecursiveLockFree(reserved->fLock); 453 } 454 IOFreeType(reserved, ExpansionData); 455 } 456 457 super::free(); 458 } 459 460 void 461 IORegistryEntry::setPropertyTable( OSDictionary * dict ) 462 { 463 PLOCK; 464 if (dict) { 465 dict->retain(); 466 } 467 if (fPropertyTable) { 468 fPropertyTable->release(); 469 } 470 471 fPropertyTable = dict; 472 PUNLOCK; 473 } 474 475 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 476 477 /* Wrappers to synchronize property table */ 478 479 #define wrap2(type, constant) \ 480 OSObject * \ 481 IORegistryEntry::copyProperty( type * aKey) constant \ 482 { \ 483 OSObject * obj; \ 484 \ 485 PLOCK; \ 486 obj = getProperty( aKey ); \ 487 if( obj) \ 488 obj->retain(); \ 489 PUNLOCK; \ 490 \ 491 return( obj ); \ 492 } 493 494 #define wrap4(type, constant) \ 495 OSObject * \ 496 IORegistryEntry::getProperty( type * aKey, \ 497 const IORegistryPlane * plane, \ 498 IOOptionBits options ) constant \ 499 { \ 500 OSObject * obj = getProperty( aKey ); \ 501 \ 502 if ( (NULL == obj) && plane && (options & kIORegistryIterateRecursively) ) { \ 503 IORegistryEntry * entry = (IORegistryEntry *) this; \ 504 IORegistryIterator * iter; \ 505 iter = IORegistryIterator::iterateOver( entry, plane, options ); \ 506 \ 507 if(iter) { \ 508 while ( (NULL == obj) && (entry = iter->getNextObject()) ) { \ 509 obj = entry->getProperty( aKey ); \ 510 } \ 511 iter->release(); \ 512 } \ 513 } \ 514 \ 515 return( obj ); \ 516 } 517 518 #define wrap5(type, constant) \ 519 OSObject * \ 520 IORegistryEntry::copyProperty( type * aKey, \ 521 const IORegistryPlane * plane, \ 522 IOOptionBits options ) constant \ 523 { \ 524 OSObject * obj = copyProperty( aKey ); \ 525 \ 526 if ( (NULL == obj) && plane && (options & kIORegistryIterateRecursively) ) { \ 527 IORegistryEntry * entry = (IORegistryEntry *) this; \ 528 IORegistryIterator * iter; \ 529 iter = IORegistryIterator::iterateOver( entry, plane, options ); \ 530 \ 531 if(iter) { \ 532 while ( (NULL == obj) && (entry = iter->getNextObject()) ) { \ 533 obj = entry->copyProperty( aKey ); \ 534 } \ 535 iter->release(); \ 536 } \ 537 } \ 538 \ 539 return( obj ); \ 540 } 541 542 bool 543 IORegistryEntry::serializeProperties( OSSerialize * s ) const 544 { 545 // setProperty( getRetainCount(), 32, "__retain" ); 546 547 PLOCK; 548 OSCollection *snapshotProperties = getPropertyTable()->copyCollection(); 549 PUNLOCK; 550 551 if (!snapshotProperties) { 552 return false; 553 } 554 555 bool ok = snapshotProperties->serialize( s ); 556 snapshotProperties->release(); 557 return ok; 558 } 559 560 OSArray * 561 IORegistryEntry::copyPropertyKeys(void) const 562 { 563 PLOCK; 564 OSArray * keys = getPropertyTable()->copyKeys(); 565 PUNLOCK; 566 567 return keys; 568 } 569 570 OSDictionary * 571 IORegistryEntry::dictionaryWithProperties( void ) const 572 { 573 OSDictionary * dict; 574 575 PLOCK; 576 dict = OSDictionary::withDictionary( getPropertyTable(), 577 getPropertyTable()->getCapacity()); 578 PUNLOCK; 579 580 return dict; 581 } 582 583 IOReturn 584 IORegistryEntry::setProperties( OSObject * properties ) 585 { 586 return kIOReturnUnsupported; 587 } 588 589 wrap2(const OSSymbol, const) // copyProperty() definition 590 wrap2(const OSString, const) // copyProperty() definition 591 wrap2(const char, const) // copyProperty() definition 592 593 wrap4(const OSSymbol, const) // getProperty() w/plane definition 594 wrap4(const OSString, const) // getProperty() w/plane definition 595 wrap4(const char, const) // getProperty() w/plane definition 596 597 wrap5(const OSSymbol, const) // copyProperty() w/plane definition 598 wrap5(const OSString, const) // copyProperty() w/plane definition 599 wrap5(const char, const) // copyProperty() w/plane definition 600 601 602 bool 603 IORegistryEntry::propertyExists(const OSSymbol * aKey) 604 { 605 return NULL != getProperty(aKey); 606 } 607 608 bool 609 IORegistryEntry::propertyExists(const OSString * aKey) 610 { 611 return NULL != getProperty(aKey); 612 } 613 614 bool 615 IORegistryEntry::propertyExists(const char * aKey) 616 { 617 return NULL != getProperty(aKey); 618 } 619 620 621 bool 622 IORegistryEntry::propertyHasValue(const OSSymbol * aKey, 623 const OSObject * value) 624 { 625 const OSObject * found; 626 bool result; 627 628 found = copyProperty(aKey); 629 result = (!found && !value) || (found && value && value->isEqualTo(found)); 630 OSSafeReleaseNULL(found); 631 return result; 632 } 633 634 bool 635 IORegistryEntry::propertyHasValue(const OSString * aKey, 636 const OSObject * value) 637 { 638 const OSObject * found; 639 bool result; 640 641 found = copyProperty(aKey); 642 result = (!found && !value) || (found && value && value->isEqualTo(found)); 643 OSSafeReleaseNULL(found); 644 return result; 645 } 646 647 bool 648 IORegistryEntry::propertyHasValue(const char * aKey, 649 const OSObject * value) 650 { 651 const OSObject * found; 652 bool result; 653 654 found = copyProperty(aKey); 655 result = (!found && !value) || (found && value && value->isEqualTo(found)); 656 OSSafeReleaseNULL(found); 657 return result; 658 } 659 660 661 bool 662 IORegistryEntry::propertyExists(const OSSymbol * aKey, 663 const IORegistryPlane * plane, 664 uint32_t options) const 665 { 666 return NULL != getProperty(aKey, plane, options); 667 } 668 669 bool 670 IORegistryEntry::propertyExists(const OSString * aKey, 671 const IORegistryPlane * plane, 672 uint32_t options) const 673 { 674 return NULL != getProperty(aKey, plane, options); 675 } 676 bool 677 IORegistryEntry::propertyExists(const char * aKey, 678 const IORegistryPlane * plane, 679 uint32_t options) const 680 { 681 return NULL != getProperty(aKey, plane, options); 682 } 683 684 685 bool 686 IORegistryEntry::propertyHasValue(const OSSymbol * aKey, 687 const OSObject * value, 688 const IORegistryPlane * plane, 689 uint32_t options) const 690 { 691 const OSObject * found; 692 bool result; 693 694 found = copyProperty(aKey, plane, options); 695 result = (!found && !value) || (found && value && value->isEqualTo(found)); 696 OSSafeReleaseNULL(found); 697 return result; 698 } 699 700 bool 701 IORegistryEntry::propertyHasValue(const OSString * aKey, 702 const OSObject * value, 703 const IORegistryPlane * plane, 704 uint32_t options) const 705 { 706 const OSObject * found; 707 bool result; 708 709 found = copyProperty(aKey, plane, options); 710 result = (!found && !value) || (found && value && value->isEqualTo(found)); 711 OSSafeReleaseNULL(found); 712 return result; 713 } 714 715 bool 716 IORegistryEntry::propertyHasValue(const char * aKey, 717 const OSObject * value, 718 const IORegistryPlane * plane, 719 uint32_t options) const 720 { 721 const OSObject * found; 722 bool result; 723 724 found = copyProperty(aKey, plane, options); 725 result = (!found && !value) || (found && value && value->isEqualTo(found)); 726 OSSafeReleaseNULL(found); 727 return result; 728 } 729 730 731 OSObject * 732 IORegistryEntry::getProperty( const OSSymbol * aKey) const 733 { 734 OSObject * obj; 735 736 PLOCK; 737 obj = getPropertyTable()->getObject( aKey ); 738 PUNLOCK; 739 740 return obj; 741 } 742 743 void 744 IORegistryEntry::removeProperty( const OSSymbol * aKey) 745 { 746 PLOCK; 747 getPropertyTable()->removeObject( aKey ); 748 PUNLOCK; 749 } 750 751 #if KASLR_IOREG_DEBUG 752 extern "C" { 753 bool ScanForAddrInObject(OSObject * theObject, 754 int indent); 755 }; /* extern "C" */ 756 #endif 757 758 bool 759 IORegistryEntry::setProperty( const OSSymbol * aKey, OSObject * anObject) 760 { 761 bool ret = false; 762 763 // If we are inserting a collection class and the current entry 764 // is attached into the registry (inPlane()) then mark the collection 765 // as immutable. 766 OSCollection *coll = OSDynamicCast(OSCollection, anObject); 767 bool makeImmutable = (coll && inPlane()); 768 769 PLOCK; 770 if (makeImmutable) { 771 coll->setOptions( OSCollection::kMASK, OSCollection::kImmutable ); 772 } 773 774 ret = getPropertyTable()->setObject( aKey, anObject ); 775 PUNLOCK; 776 777 #if KASLR_IOREG_DEBUG 778 if (anObject && strcmp(kIOKitDiagnosticsKey, aKey->getCStringNoCopy()) != 0) { 779 if (ScanForAddrInObject(anObject, 0)) { 780 IOLog("%s: IORegistryEntry name %s with key \"%s\" \n", 781 __FUNCTION__, 782 getName(0), 783 aKey->getCStringNoCopy()); 784 } 785 } 786 #endif 787 788 return ret; 789 } 790 791 IOReturn 792 IORegistryEntry:: 793 runPropertyAction(Action inAction, OSObject *target, 794 void *arg0, void *arg1, void *arg2, void *arg3) 795 { 796 IOReturn res; 797 798 // closeGate is recursive so don't worry if we already hold the lock. 799 PLOCK; 800 res = (*inAction)(target, arg0, arg1, arg2, arg3); 801 PUNLOCK; 802 803 return res; 804 } 805 806 static IOReturn 807 IORegistryEntryActionToBlock(OSObject *target, 808 void *arg0, void *arg1, 809 void *arg2, void *arg3) 810 { 811 IORegistryEntry::ActionBlock block = (typeof(block))arg0; 812 return block(); 813 } 814 815 IOReturn 816 IORegistryEntry::runPropertyActionBlock(ActionBlock block) 817 { 818 IOReturn res; 819 820 res = runPropertyAction(&IORegistryEntryActionToBlock, this, block); 821 822 return res; 823 } 824 825 OSObject * 826 IORegistryEntry::getProperty( const OSString * aKey) const 827 { 828 const OSSymbol * tmpKey = OSSymbol::withString( aKey ); 829 OSObject * obj = getProperty( tmpKey ); 830 831 tmpKey->release(); 832 return obj; 833 } 834 835 OSObject * 836 IORegistryEntry::getProperty( const char * aKey) const 837 { 838 const OSSymbol * tmpKey = OSSymbol::withCString( aKey ); 839 OSObject * obj = getProperty( tmpKey ); 840 841 tmpKey->release(); 842 return obj; 843 } 844 845 846 void 847 IORegistryEntry::removeProperty( const OSString * aKey) 848 { 849 const OSSymbol * tmpKey = OSSymbol::withString( aKey ); 850 removeProperty( tmpKey ); 851 tmpKey->release(); 852 } 853 854 void 855 IORegistryEntry::removeProperty( const char * aKey) 856 { 857 const OSSymbol * tmpKey = OSSymbol::withCString( aKey ); 858 removeProperty( tmpKey ); 859 tmpKey->release(); 860 } 861 862 bool 863 IORegistryEntry::setProperty( const OSString * aKey, OSObject * anObject) 864 { 865 const OSSymbol * tmpKey = OSSymbol::withString( aKey ); 866 bool ret = setProperty( tmpKey, anObject ); 867 868 tmpKey->release(); 869 return ret; 870 } 871 872 bool 873 IORegistryEntry::setProperty( const char * aKey, OSObject * anObject) 874 { 875 const OSSymbol * tmpKey = OSSymbol::withCString( aKey ); 876 bool ret = setProperty( tmpKey, anObject ); 877 878 tmpKey->release(); 879 return ret; 880 } 881 882 bool 883 IORegistryEntry::setProperty(const char * aKey, const char * aString) 884 { 885 bool ret = false; 886 OSSymbol * aSymbol = (OSSymbol *) OSSymbol::withCString( aString ); 887 888 if (aSymbol) { 889 const OSSymbol * tmpKey = OSSymbol::withCString( aKey ); 890 ret = setProperty( tmpKey, aSymbol ); 891 892 tmpKey->release(); 893 aSymbol->release(); 894 } 895 return ret; 896 } 897 898 bool 899 IORegistryEntry::setProperty(const char * aKey, bool aBoolean) 900 { 901 bool ret = false; 902 OSBoolean * aBooleanObj = OSBoolean::withBoolean( aBoolean ); 903 904 if (aBooleanObj) { 905 const OSSymbol * tmpKey = OSSymbol::withCString( aKey ); 906 ret = setProperty( tmpKey, aBooleanObj ); 907 908 tmpKey->release(); 909 aBooleanObj->release(); 910 } 911 return ret; 912 } 913 914 bool 915 IORegistryEntry::setProperty( const char * aKey, 916 unsigned long long aValue, 917 unsigned int aNumberOfBits) 918 { 919 bool ret = false; 920 OSNumber * anOffset = OSNumber::withNumber( aValue, aNumberOfBits ); 921 922 if (anOffset) { 923 const OSSymbol * tmpKey = OSSymbol::withCString( aKey ); 924 ret = setProperty( tmpKey, anOffset ); 925 926 tmpKey->release(); 927 anOffset->release(); 928 } 929 return ret; 930 } 931 932 bool 933 IORegistryEntry::setProperty( const char * aKey, 934 void * bytes, 935 unsigned int length) 936 { 937 bool ret = false; 938 OSData * data = OSData::withBytes( bytes, length ); 939 940 if (data) { 941 const OSSymbol * tmpKey = OSSymbol::withCString( aKey ); 942 ret = setProperty( tmpKey, data ); 943 944 tmpKey->release(); 945 data->release(); 946 } 947 return ret; 948 } 949 950 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 951 952 OSObject * 953 IORegistryEntry::setIndexedProperty(uint32_t index, OSObject * anObject) 954 { 955 OSObject ** array; 956 OSObject * prior; 957 958 if (index >= kIORegistryEntryIndexedPropertyCount) { 959 return NULL; 960 } 961 962 array = os_atomic_load(&reserved->fIndexedProperties, acquire); 963 if (!array) { 964 array = IONew(OSObject *, kIORegistryEntryIndexedPropertyCount); 965 if (!array) { 966 return NULL; 967 } 968 bzero(array, kIORegistryEntryIndexedPropertyCount * sizeof(array[0])); 969 if (!os_atomic_cmpxchg(&reserved->fIndexedProperties, NULL, array, release)) { 970 IODelete(array, OSObject *, kIORegistryEntryIndexedPropertyCount); 971 array = os_atomic_load(&reserved->fIndexedProperties, acquire); 972 } 973 } 974 975 if (!array) { 976 return NULL; 977 } 978 979 prior = array[index]; 980 if (anObject) { 981 anObject->retain(); 982 } 983 array[index] = anObject; 984 985 return prior; 986 } 987 988 OSObject * 989 IORegistryEntry::getIndexedProperty(uint32_t index) const 990 { 991 if (index >= kIORegistryEntryIndexedPropertyCount) { 992 return NULL; 993 } 994 995 OSObject ** array = os_atomic_load(&reserved->fIndexedProperties, acquire); 996 if (!array) { 997 return NULL; 998 } 999 1000 return array[index]; 1001 } 1002 1003 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 1004 1005 /* Name, location, paths */ 1006 1007 const char * 1008 IORegistryEntry::getName( const IORegistryPlane * plane ) const 1009 { 1010 OSSymbol * sym = NULL; 1011 1012 RLOCK; 1013 if (plane) { 1014 sym = (OSSymbol *) registryTable()->getObject( plane->pathNameKey ); 1015 } 1016 if (!sym) { 1017 sym = (OSSymbol *) registryTable()->getObject( gIONameKey ); 1018 } 1019 UNLOCK; 1020 1021 if (sym) { 1022 return sym->getCStringNoCopy(); 1023 } else { 1024 return (getMetaClass())->getClassName(); 1025 } 1026 } 1027 1028 const OSSymbol * 1029 IORegistryEntry::copyName( 1030 const IORegistryPlane * plane ) const 1031 { 1032 OSSymbol * sym = NULL; 1033 1034 RLOCK; 1035 if (plane) { 1036 sym = (OSSymbol *) registryTable()->getObject( plane->pathNameKey ); 1037 } 1038 if (!sym) { 1039 sym = (OSSymbol *) registryTable()->getObject( gIONameKey ); 1040 } 1041 if (sym) { 1042 sym->retain(); 1043 } 1044 UNLOCK; 1045 1046 if (sym) { 1047 return sym; 1048 } else { 1049 return OSSymbol::withCString((getMetaClass())->getClassName()); 1050 } 1051 } 1052 1053 const OSSymbol * 1054 IORegistryEntry::copyLocation( 1055 const IORegistryPlane * plane ) const 1056 { 1057 OSSymbol * sym = NULL; 1058 1059 RLOCK; 1060 if (plane) { 1061 sym = (OSSymbol *) registryTable()->getObject( plane->pathLocationKey ); 1062 } 1063 if (!sym) { 1064 sym = (OSSymbol *) registryTable()->getObject( gIOLocationKey ); 1065 } 1066 if (sym) { 1067 sym->retain(); 1068 } 1069 UNLOCK; 1070 1071 return sym; 1072 } 1073 1074 const char * 1075 IORegistryEntry::getLocation( const IORegistryPlane * plane ) const 1076 { 1077 const OSSymbol * sym = copyLocation( plane ); 1078 const char * result = NULL; 1079 1080 if (sym) { 1081 result = sym->getCStringNoCopy(); 1082 sym->release(); 1083 } 1084 1085 return result; 1086 } 1087 1088 void 1089 IORegistryEntry::setName( const OSSymbol * name, 1090 const IORegistryPlane * plane ) 1091 { 1092 const OSSymbol * key; 1093 1094 if (name) { 1095 if (plane) { 1096 key = plane->pathNameKey; 1097 } else { 1098 key = gIONameKey; 1099 } 1100 1101 if (gIOKitTrace && reserved && reserved->fRegistryEntryID) { 1102 uint64_t str_id = 0; 1103 uint64_t __unused regID = getRegistryEntryID(); 1104 kernel_debug_string(IODBG_IOREGISTRY(IOREGISTRYENTRY_NAME_STRING), &str_id, name->getCStringNoCopy()); 1105 KERNEL_DEBUG_CONSTANT(IODBG_IOREGISTRY(IOREGISTRYENTRY_NAME), 1106 (uintptr_t) regID, 1107 (uintptr_t) (regID >> 32), 1108 (uintptr_t) str_id, 1109 (uintptr_t) (str_id >> 32), 1110 0); 1111 } 1112 1113 WLOCK; 1114 registryTable()->setObject( key, (OSObject *) name); 1115 UNLOCK; 1116 } 1117 } 1118 1119 void 1120 IORegistryEntry::setName( const char * name, 1121 const IORegistryPlane * plane ) 1122 { 1123 OSSymbol * sym = (OSSymbol *)OSSymbol::withCString( name ); 1124 if (sym) { 1125 setName( sym, plane ); 1126 sym->release(); 1127 } 1128 } 1129 1130 void 1131 IORegistryEntry::setName( const OSString * name, 1132 const IORegistryPlane * plane ) 1133 { 1134 const OSSymbol * sym = OSSymbol::withString( name ); 1135 if (sym) { 1136 setName( sym, plane ); 1137 sym->release(); 1138 } 1139 } 1140 1141 void 1142 IORegistryEntry::setLocation( const OSSymbol * location, 1143 const IORegistryPlane * plane ) 1144 { 1145 const OSSymbol * key; 1146 1147 if (location) { 1148 if (plane) { 1149 key = plane->pathLocationKey; 1150 } else { 1151 key = gIOLocationKey; 1152 } 1153 1154 WLOCK; 1155 registryTable()->setObject( key, (OSObject *) location); 1156 UNLOCK; 1157 } 1158 } 1159 1160 void 1161 IORegistryEntry::setLocation( const char * location, 1162 const IORegistryPlane * plane ) 1163 { 1164 OSSymbol * sym = (OSSymbol *)OSSymbol::withCString( location ); 1165 if (sym) { 1166 setLocation( sym, plane ); 1167 sym->release(); 1168 } 1169 } 1170 1171 1172 bool 1173 IORegistryEntry::compareName( OSString * name, OSString ** matched ) const 1174 { 1175 const OSSymbol * sym = copyName(); 1176 bool isEqual; 1177 1178 isEqual = (sym && sym->isEqualTo(name)); 1179 1180 if (isEqual && matched) { 1181 name->retain(); 1182 *matched = name; 1183 } 1184 1185 if (sym) { 1186 sym->release(); 1187 } 1188 1189 return isEqual; 1190 } 1191 1192 bool 1193 IORegistryEntry::compareNames( OSObject * names, OSString ** matched ) const 1194 { 1195 OSString * string; 1196 OSCollection * collection; 1197 OSIterator * iter = NULL; 1198 bool result = false; 1199 1200 if ((collection = OSDynamicCast( OSCollection, names))) { 1201 iter = OSCollectionIterator::withCollection( collection ); 1202 string = NULL; 1203 } else { 1204 string = OSDynamicCast( OSString, names); 1205 } 1206 1207 do { 1208 if (string) { 1209 result = compareName( string, matched ); 1210 } 1211 } while ((false == result) 1212 && iter && (string = OSDynamicCast( OSString, iter->getNextObject()))); 1213 1214 if (iter) { 1215 iter->release(); 1216 } 1217 1218 return result; 1219 } 1220 1221 bool 1222 IORegistryEntry::compareName( OSString * name, OSSharedPtr<OSString>& matched ) const 1223 { 1224 OSString* matchedRaw = NULL; 1225 bool result = compareName(name, &matchedRaw); 1226 matched.reset(matchedRaw, OSNoRetain); 1227 return result; 1228 } 1229 1230 bool 1231 IORegistryEntry::compareNames( OSObject * names, OSSharedPtr<OSString>& matched ) const 1232 { 1233 OSString* matchedRaw = NULL; 1234 bool result = compareNames(names, &matchedRaw); 1235 matched.reset(matchedRaw, OSNoRetain); 1236 return result; 1237 } 1238 1239 bool 1240 IORegistryEntry::getPath( char * path, int * length, 1241 const IORegistryPlane * plane ) const 1242 { 1243 OSArray * stack; 1244 IORegistryEntry * root; 1245 const IORegistryEntry * entry; 1246 const IORegistryEntry * parent; 1247 const OSSymbol * alias; 1248 int index; 1249 int len, maxLength, compLen, aliasLen; 1250 OSBoundedPtr<char> nextComp; 1251 bool ok; 1252 size_t init_length; 1253 1254 if (!path || !length || !plane) { 1255 return false; 1256 } 1257 1258 len = 0; 1259 init_length = *length; 1260 maxLength = *length - 2; 1261 nextComp = OSBoundedPtr<char>(path, path, path + init_length); 1262 1263 len = plane->nameKey->getLength(); 1264 if (len >= maxLength) { 1265 return false; 1266 } 1267 strlcpy( nextComp.discard_bounds(), plane->nameKey->getCStringNoCopy(), len + 1); 1268 nextComp[len++] = ':'; 1269 nextComp += len; 1270 1271 if ((alias = hasAlias( plane ))) { 1272 aliasLen = alias->getLength(); 1273 len += aliasLen; 1274 ok = (maxLength > len); 1275 *length = len; 1276 if (ok) { 1277 strlcpy( nextComp.discard_bounds(), alias->getCStringNoCopy(), aliasLen + 1); 1278 } 1279 return ok; 1280 } 1281 1282 stack = OSArray::withCapacity( getDepth( plane )); 1283 if (!stack) { 1284 return false; 1285 } 1286 1287 RLOCK; 1288 1289 parent = entry = this; 1290 root = gRegistryRoot->getChildEntry( plane ); 1291 while (parent && (parent != root)) { 1292 // stop below root 1293 entry = parent; 1294 parent = entry->getParentEntry( plane ); 1295 stack->setObject((OSObject *) entry ); 1296 } 1297 1298 ok = (NULL != parent); 1299 if (ok) { 1300 index = stack->getCount(); 1301 if (0 == index) { 1302 *nextComp++ = '/'; 1303 *nextComp = 0; 1304 len++; 1305 } else { 1306 while (ok && ((--index) >= 0)) { 1307 entry = (IORegistryEntry *) stack->getObject((unsigned int) index ); 1308 assert( entry ); 1309 1310 if ((alias = entry->hasAlias( plane ))) { 1311 len = plane->nameKey->getLength() + 1; 1312 //pointer is to the first argument, with next 2 arguments describing the start and end bounds 1313 nextComp = OSBoundedPtr<char>(path + len, path, path + init_length); 1314 1315 compLen = alias->getLength(); 1316 ok = (maxLength > (len + compLen)); 1317 if (ok) { 1318 strlcpy( nextComp.discard_bounds(), alias->getCStringNoCopy(), compLen + 1); 1319 } 1320 } else { 1321 compLen = maxLength - len; 1322 ok = entry->getPathComponent( nextComp.discard_bounds() + 1, &compLen, plane ); 1323 1324 if (ok && compLen) { 1325 compLen++; 1326 *nextComp = '/'; 1327 } 1328 } 1329 1330 if (ok) { 1331 len += compLen; 1332 nextComp += compLen; 1333 } 1334 } 1335 } 1336 *length = len; 1337 } 1338 UNLOCK; 1339 stack->release(); 1340 1341 return ok; 1342 } 1343 1344 bool 1345 IORegistryEntry::getPathComponent( char * path, int * length, 1346 const IORegistryPlane * plane ) const 1347 { 1348 int len, locLen, maxLength; 1349 const char * compName; 1350 const char * loc; 1351 bool ok; 1352 1353 maxLength = *length; 1354 1355 compName = getName( plane ); 1356 len = (int) strnlen( compName, sizeof(io_name_t)); 1357 if ((loc = getLocation( plane ))) { 1358 locLen = 1 + ((int) strnlen( loc, sizeof(io_name_t))); 1359 } else { 1360 locLen = 0; 1361 } 1362 1363 ok = ((len + locLen + 1) < maxLength); 1364 if (ok) { 1365 strlcpy( path, compName, len + 1 ); 1366 if (loc) { 1367 path += len; 1368 len += locLen; 1369 *path++ = '@'; 1370 strlcpy( path, loc, locLen ); 1371 } 1372 *length = len; 1373 } 1374 1375 return ok; 1376 } 1377 1378 const char * 1379 IORegistryEntry::matchPathLocation( const char * cmp, 1380 const IORegistryPlane * plane ) 1381 { 1382 const char * str; 1383 const char * result = NULL; 1384 u_quad_t num1, num2; 1385 char lastPathChar, lastLocationChar; 1386 1387 str = getLocation( plane ); 1388 if (str) { 1389 lastPathChar = cmp[0]; 1390 lastLocationChar = str[0]; 1391 do { 1392 if (lastPathChar) { 1393 num1 = strtouq( cmp, (char **) &cmp, 16 ); 1394 lastPathChar = *cmp++; 1395 } else { 1396 num1 = 0; 1397 } 1398 1399 if (lastLocationChar) { 1400 num2 = strtouq( str, (char **) &str, 16 ); 1401 lastLocationChar = *str++; 1402 } else { 1403 num2 = 0; 1404 } 1405 1406 if (num1 != num2) { 1407 break; 1408 } 1409 1410 if (!lastPathChar && !lastLocationChar) { 1411 result = cmp - 1; 1412 break; 1413 } 1414 1415 if ((',' != lastPathChar) && (':' != lastPathChar)) { 1416 lastPathChar = 0; 1417 } 1418 1419 if (lastPathChar && lastLocationChar && (lastPathChar != lastLocationChar)) { 1420 break; 1421 } 1422 } while (true); 1423 } 1424 1425 return result; 1426 } 1427 1428 IORegistryEntry * 1429 IORegistryEntry::getChildFromComponent( const char ** opath, 1430 const IORegistryPlane * plane ) 1431 { 1432 IORegistryEntry * entry = NULL; 1433 OSArray * set; 1434 unsigned int index; 1435 const char * path; 1436 const char * cmp = NULL; 1437 char c; 1438 size_t len; 1439 const char * str; 1440 1441 set = getChildSetReference( plane ); 1442 if (set) { 1443 path = *opath; 1444 1445 for (index = 0; 1446 (entry = (IORegistryEntry *) set->getObject(index)); 1447 index++) { 1448 cmp = path; 1449 1450 if (*cmp != '@') { 1451 str = entry->getName( plane ); 1452 len = strlen( str ); 1453 if (strncmp( str, cmp, len )) { 1454 continue; 1455 } 1456 cmp += len; 1457 1458 c = *cmp; 1459 if ((c == 0) || (c == '/') || (c == ':')) { 1460 break; 1461 } 1462 if (c != '@') { 1463 continue; 1464 } 1465 } 1466 cmp++; 1467 if ((cmp = entry->matchPathLocation( cmp, plane ))) { 1468 break; 1469 } 1470 } 1471 if (entry) { 1472 *opath = cmp; 1473 } 1474 } 1475 1476 return entry; 1477 } 1478 1479 const OSSymbol * 1480 IORegistryEntry::hasAlias( const IORegistryPlane * plane, 1481 char * opath, int * length ) const 1482 { 1483 IORegistryEntry * entry; 1484 IORegistryEntry * entry2; 1485 const OSSymbol * key; 1486 const OSSymbol * bestKey = NULL; 1487 OSIterator * iter; 1488 OSData * data; 1489 const char * path = "/aliases"; 1490 1491 entry = IORegistryEntry::fromPath( path, plane ); 1492 if (entry) { 1493 RLOCK; 1494 if ((iter = OSCollectionIterator::withCollection( 1495 entry->getPropertyTable()))) { 1496 while ((key = (OSSymbol *) iter->getNextObject())) { 1497 data = (OSData *) entry->getProperty( key ); 1498 path = (const char *) data->getBytesNoCopy(); 1499 if ((entry2 = IORegistryEntry::fromPath( path, plane, 1500 opath, length ))) { 1501 if (this == entry2) { 1502 if (!bestKey 1503 || (bestKey->getLength() > key->getLength())) { 1504 // pick the smallest alias 1505 bestKey = key; 1506 } 1507 } 1508 entry2->release(); 1509 } 1510 } 1511 iter->release(); 1512 } 1513 entry->release(); 1514 UNLOCK; 1515 } 1516 return bestKey; 1517 } 1518 1519 const char * 1520 IORegistryEntry::dealiasPath( 1521 const char ** opath, 1522 const IORegistryPlane * plane ) 1523 { 1524 IORegistryEntry * entry; 1525 OSData * data; 1526 const char * path = *opath; 1527 const char * rpath = NULL; 1528 const char * end; 1529 char c; 1530 char temp[kIOMaxPlaneName + 1]; 1531 1532 if (path[0] == '/') { 1533 return rpath; 1534 } 1535 1536 // check for alias 1537 end = path; 1538 while ((c = *end++) && (c != '/') && (c != ':')) { 1539 } 1540 end--; 1541 if ((end - path) < kIOMaxPlaneName) { 1542 strlcpy( temp, path, end - path + 1 ); 1543 1544 RLOCK; 1545 entry = IORegistryEntry::fromPath( "/aliases", plane ); 1546 if (entry) { 1547 data = (OSData *) entry->getProperty( temp ); 1548 if (data) { 1549 rpath = (const char *) data->getBytesNoCopy(); 1550 if (rpath) { 1551 *opath = end; 1552 } 1553 } 1554 entry->release(); 1555 } 1556 UNLOCK; 1557 } 1558 1559 return rpath; 1560 } 1561 1562 IORegistryEntry * 1563 IORegistryEntry::fromPath( 1564 const char * path, 1565 const IORegistryPlane * plane, 1566 char * opath, 1567 int * length, 1568 IORegistryEntry * fromEntry ) 1569 { 1570 IORegistryEntry * where = NULL; 1571 IORegistryEntry * aliasEntry = NULL; 1572 IORegistryEntry * next; 1573 const char * alias; 1574 const char * end; 1575 int len = 0; 1576 int len2; 1577 char c; 1578 char temp[kIOMaxPlaneName + 1]; 1579 1580 if (NULL == path) { 1581 return NULL; 1582 } 1583 1584 if (NULL == plane) { 1585 // get plane name 1586 end = strchr( path, ':' ); 1587 if (end && ((end - path) < kIOMaxPlaneName)) { 1588 strlcpy( temp, path, end - path + 1 ); 1589 plane = getPlane( temp ); 1590 path = end + 1; 1591 } 1592 } 1593 if (NULL == plane) { 1594 return NULL; 1595 } 1596 1597 // check for alias 1598 end = path; 1599 if ((alias = dealiasPath( &end, plane))) { 1600 if (length) { 1601 len = *length; 1602 } 1603 aliasEntry = IORegistryEntry::fromPath( alias, plane, 1604 opath, &len, fromEntry ); 1605 where = aliasEntry; 1606 if (where) { 1607 path = end; 1608 } else { 1609 len = 0; 1610 } 1611 } 1612 1613 RLOCK; 1614 1615 do { 1616 if (NULL == where) { 1617 if ((NULL == fromEntry) && (*path++ == '/')) { 1618 fromEntry = gRegistryRoot->getChildEntry( plane ); 1619 } 1620 where = fromEntry; 1621 if (NULL == where) { 1622 break; 1623 } 1624 } else { 1625 c = *path++; 1626 if (c != '/') { 1627 if (c && (c != ':')) { // check valid terminator 1628 where = NULL; 1629 } 1630 break; 1631 } 1632 } 1633 next = where->getChildFromComponent( &path, plane ); 1634 if (next) { 1635 where = next; 1636 } 1637 } while (next); 1638 1639 if (where) { 1640 // check residual path 1641 if (where != fromEntry) { 1642 path--; 1643 } 1644 1645 if (opath && length) { 1646 // copy out residual path 1647 len2 = (int) strnlen(path, 65536); 1648 if ((len + len2) < *length) { 1649 strlcpy( opath + len, path, len2 + 1 ); 1650 } 1651 *length = (len + len2); 1652 } else if (path[0]) { 1653 // no residual path => must be no tail for success 1654 where = NULL; 1655 } 1656 } 1657 1658 if (where) { 1659 where->retain(); 1660 } 1661 if (aliasEntry) { 1662 aliasEntry->release(); 1663 } 1664 1665 UNLOCK; 1666 1667 return where; 1668 } 1669 1670 IORegistryEntry * 1671 IORegistryEntry::childFromPath( 1672 const char * path, 1673 const IORegistryPlane * plane, 1674 char * opath, 1675 int * len ) 1676 { 1677 return IORegistryEntry::fromPath( path, plane, opath, len, this ); 1678 } 1679 1680 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 1681 1682 #define IOLinkIterator OSCollectionIterator 1683 1684 #undef super 1685 #define super OSObject 1686 1687 inline bool 1688 IORegistryEntry::arrayMember( OSArray * set, 1689 const IORegistryEntry * member, 1690 unsigned int * index ) const 1691 { 1692 int i; 1693 OSObject * probeObject; 1694 1695 for (i = 0; (probeObject = set->getObject(i)); i++) { 1696 if (probeObject == (OSObject *) member) { 1697 if (index) { 1698 *index = i; 1699 } 1700 return true; 1701 } 1702 } 1703 return false; 1704 } 1705 1706 bool 1707 IORegistryEntry::makeLink( IORegistryEntry * to, 1708 unsigned int relation, 1709 const IORegistryPlane * plane ) const 1710 { 1711 OSArray * links; 1712 bool result = false; 1713 1714 if ((links = (OSArray *) 1715 registryTable()->getObject( plane->keys[relation] ))) { 1716 result = arrayMember( links, to ); 1717 if (!result) { 1718 result = links->setObject( to ); 1719 } 1720 } else { 1721 links = OSArray::withObjects((const OSObject **) &to, 1, 1 ); 1722 result = (links != NULL); 1723 if (result) { 1724 result = registryTable()->setObject( plane->keys[relation], 1725 links ); 1726 links->release(); 1727 } 1728 } 1729 if (kParentSetIndex == relation) { 1730 reserved->fRegistryEntryParentGenerationCount++; 1731 } 1732 1733 return result; 1734 } 1735 1736 void 1737 IORegistryEntry::breakLink( IORegistryEntry * to, 1738 unsigned int relation, 1739 const IORegistryPlane * plane ) const 1740 { 1741 OSArray * links; 1742 unsigned int index; 1743 1744 if ((links = (OSArray *) 1745 registryTable()->getObject( plane->keys[relation]))) { 1746 if (arrayMember( links, to, &index )) { 1747 links->removeObject( index ); 1748 if (0 == links->getCount()) { 1749 registryTable()->removeObject( plane->keys[relation]); 1750 } 1751 } 1752 } 1753 if (kParentSetIndex == relation) { 1754 reserved->fRegistryEntryParentGenerationCount++; 1755 } 1756 } 1757 1758 1759 OSArray * 1760 IORegistryEntry::getParentSetReference( 1761 const IORegistryPlane * plane ) const 1762 { 1763 if (plane) { 1764 return (OSArray *) registryTable()->getObject( 1765 plane->keys[kParentSetIndex]); 1766 } else { 1767 return NULL; 1768 } 1769 } 1770 1771 OSIterator * 1772 IORegistryEntry::getParentIterator( 1773 const IORegistryPlane * plane ) const 1774 { 1775 OSArray * links; 1776 OSIterator * iter; 1777 1778 if (!plane) { 1779 return NULL; 1780 } 1781 1782 RLOCK; 1783 links = getParentSetReference( plane ); 1784 if (NULL == links) { 1785 links = OSArray::withCapacity( 1 ); 1786 } else { 1787 links = OSArray::withArray( links, links->getCount()); 1788 } 1789 UNLOCK; 1790 1791 iter = IOLinkIterator::withCollection( links ); 1792 1793 if (links) { 1794 links->release(); 1795 } 1796 1797 return iter; 1798 } 1799 1800 IORegistryEntry * 1801 IORegistryEntry::copyParentEntry( const IORegistryPlane * plane ) const 1802 { 1803 IORegistryEntry * entry = NULL; 1804 OSArray * links; 1805 1806 RLOCK; 1807 1808 if ((links = getParentSetReference( plane ))) { 1809 entry = (IORegistryEntry *) links->getObject( 0 ); 1810 entry->retain(); 1811 } 1812 1813 UNLOCK; 1814 1815 return entry; 1816 } 1817 1818 IORegistryEntry * 1819 IORegistryEntry::getParentEntry( const IORegistryPlane * plane ) const 1820 { 1821 IORegistryEntry * entry; 1822 1823 entry = copyParentEntry( plane ); 1824 if (entry) { 1825 entry->release(); 1826 } 1827 1828 return entry; 1829 } 1830 1831 OSArray * 1832 IORegistryEntry::getChildSetReference( const IORegistryPlane * plane ) const 1833 { 1834 if (plane) { 1835 return (OSArray *) registryTable()->getObject( 1836 plane->keys[kChildSetIndex]); 1837 } else { 1838 return NULL; 1839 } 1840 } 1841 1842 OSIterator * 1843 IORegistryEntry::getChildIterator( const IORegistryPlane * plane ) const 1844 { 1845 OSArray * links; 1846 OSIterator * iter; 1847 1848 if (!plane) { 1849 return NULL; 1850 } 1851 1852 RLOCK; 1853 links = getChildSetReference( plane ); 1854 if (NULL == links) { 1855 links = OSArray::withCapacity( 1 ); 1856 } else { 1857 links = OSArray::withArray( links, links->getCount()); 1858 } 1859 UNLOCK; 1860 1861 iter = IOLinkIterator::withCollection( links ); 1862 1863 if (links) { 1864 links->release(); 1865 } 1866 1867 return iter; 1868 } 1869 1870 uint32_t 1871 IORegistryEntry::getChildCount( const IORegistryPlane * plane ) const 1872 { 1873 OSArray * links; 1874 uint32_t count = 0; 1875 1876 RLOCK; 1877 links = getChildSetReference( plane ); 1878 if (links) { 1879 count = links->getCount(); 1880 } 1881 UNLOCK; 1882 1883 return count; 1884 } 1885 1886 IORegistryEntry * 1887 IORegistryEntry::copyChildEntry( 1888 const IORegistryPlane * plane ) const 1889 { 1890 IORegistryEntry * entry = NULL; 1891 OSArray * links; 1892 1893 RLOCK; 1894 1895 if ((links = getChildSetReference( plane ))) { 1896 entry = (IORegistryEntry *) links->getObject( 0 ); 1897 entry->retain(); 1898 } 1899 1900 UNLOCK; 1901 1902 return entry; 1903 } 1904 1905 // FIXME: Implementation of this function is hidden from the static analyzer. 1906 // The analyzer is worried that this release might as well be the last release. 1907 // Feel free to remove the #ifndef and address the warning! 1908 // See also rdar://problem/63023165. 1909 #ifndef __clang_analyzer__ 1910 IORegistryEntry * 1911 IORegistryEntry::getChildEntry( 1912 const IORegistryPlane * plane ) const 1913 { 1914 IORegistryEntry * entry; 1915 1916 entry = copyChildEntry( plane ); 1917 if (entry) { 1918 entry->release(); 1919 } 1920 1921 return entry; 1922 } 1923 #endif // __clang_analyzer__ 1924 1925 void 1926 IORegistryEntry::applyToChildren( IORegistryEntryApplierFunction applier, 1927 void * context, 1928 const IORegistryPlane * plane ) const 1929 { 1930 OSArray * array; 1931 unsigned int index; 1932 IORegistryEntry * next; 1933 1934 if (!plane) { 1935 return; 1936 } 1937 1938 RLOCK; 1939 array = OSArray::withArray( getChildSetReference( plane )); 1940 UNLOCK; 1941 if (array) { 1942 for (index = 0; 1943 (next = (IORegistryEntry *) array->getObject( index )); 1944 index++) { 1945 (*applier)(next, context); 1946 } 1947 array->release(); 1948 } 1949 } 1950 1951 void 1952 IORegistryEntry::applyToParents( IORegistryEntryApplierFunction applier, 1953 void * context, 1954 const IORegistryPlane * plane ) const 1955 { 1956 OSArray * array; 1957 unsigned int index; 1958 IORegistryEntry * next; 1959 1960 if (!plane) { 1961 return; 1962 } 1963 1964 RLOCK; 1965 array = OSArray::withArray( getParentSetReference( plane )); 1966 UNLOCK; 1967 if (array) { 1968 for (index = 0; 1969 (next = (IORegistryEntry *) array->getObject( index )); 1970 index++) { 1971 (*applier)(next, context); 1972 } 1973 array->release(); 1974 } 1975 } 1976 1977 bool 1978 IORegistryEntry::isChild( IORegistryEntry * child, 1979 const IORegistryPlane * plane, 1980 bool onlyChild ) const 1981 { 1982 OSArray * links; 1983 bool ret = false; 1984 1985 RLOCK; 1986 1987 if ((links = getChildSetReference( plane ))) { 1988 if ((!onlyChild) || (1 == links->getCount())) { 1989 ret = arrayMember( links, child ); 1990 } 1991 } 1992 if (ret && (links = child->getParentSetReference( plane ))) { 1993 ret = arrayMember( links, this ); 1994 } 1995 1996 UNLOCK; 1997 1998 return ret; 1999 } 2000 2001 bool 2002 IORegistryEntry::isParent( IORegistryEntry * parent, 2003 const IORegistryPlane * plane, 2004 bool onlyParent ) const 2005 { 2006 OSArray * links; 2007 bool ret = false; 2008 2009 RLOCK; 2010 2011 if ((links = getParentSetReference( plane ))) { 2012 if ((!onlyParent) || (1 == links->getCount())) { 2013 ret = arrayMember( links, parent ); 2014 } 2015 } 2016 if (ret && (links = parent->getChildSetReference( plane ))) { 2017 ret = arrayMember( links, this ); 2018 } 2019 2020 UNLOCK; 2021 2022 return ret; 2023 } 2024 2025 bool 2026 IORegistryEntry::inPlane( const IORegistryPlane * plane ) const 2027 { 2028 bool ret; 2029 2030 RLOCK; 2031 2032 if (plane) { 2033 ret = (NULL != getParentSetReference( plane )); 2034 } else { 2035 // Check to see if this is in any plane. If it is in a plane 2036 // then the registryTable will contain a key with the ParentLinks 2037 // suffix. When we iterate over the keys looking for that suffix 2038 ret = false; 2039 2040 OSCollectionIterator *iter = 2041 OSCollectionIterator::withCollection( registryTable()); 2042 if (iter) { 2043 const OSSymbol *key; 2044 2045 while ((key = (OSSymbol *) iter->getNextObject())) { 2046 size_t keysuffix; 2047 2048 // Get a pointer to this keys suffix 2049 keysuffix = key->getLength(); 2050 if (keysuffix <= kIORegPlaneParentSuffixLen) { 2051 continue; 2052 } 2053 keysuffix -= kIORegPlaneParentSuffixLen; 2054 if (!strncmp(key->getCStringNoCopy() + keysuffix, 2055 kIORegPlaneParentSuffix, 2056 kIORegPlaneParentSuffixLen + 1)) { 2057 ret = true; 2058 break; 2059 } 2060 } 2061 iter->release(); 2062 } 2063 } 2064 2065 UNLOCK; 2066 2067 return ret; 2068 } 2069 2070 bool 2071 IORegistryEntry::attachToParent( IORegistryEntry * parent, 2072 const IORegistryPlane * plane ) 2073 { 2074 OSArray * links; 2075 bool ret; 2076 bool needParent; 2077 bool traceName = false; 2078 2079 if (this == parent) { 2080 return false; 2081 } 2082 2083 WLOCK; 2084 2085 if (!reserved->fRegistryEntryID) { 2086 reserved->fRegistryEntryID = ++gIORegistryLastID; 2087 traceName = (0 != gIOKitTrace); 2088 } 2089 2090 ret = makeLink( parent, kParentSetIndex, plane ); 2091 2092 if ((links = parent->getChildSetReference( plane ))) { 2093 needParent = (false == arrayMember( links, this )); 2094 } else { 2095 needParent = true; 2096 } 2097 if (needParent) { 2098 ret &= parent->makeLink(this, kChildSetIndex, plane); 2099 } 2100 2101 UNLOCK; 2102 2103 if (traceName) { 2104 uint64_t str_id = 0; 2105 uint64_t __unused regID = getRegistryEntryID(); 2106 kernel_debug_string(IODBG_IOREGISTRY(IOREGISTRYENTRY_NAME_STRING), &str_id, getName()); 2107 KERNEL_DEBUG_CONSTANT(IODBG_IOREGISTRY(IOREGISTRYENTRY_NAME), 2108 (uintptr_t) regID, 2109 (uintptr_t) (regID >> 32), 2110 (uintptr_t) str_id, 2111 (uintptr_t) (str_id >> 32), 2112 0); 2113 } 2114 2115 PLOCK; 2116 2117 // Mark any collections in the property list as immutable 2118 OSDictionary *ptable = getPropertyTable(); 2119 OSCollectionIterator *iter = 2120 OSCollectionIterator::withCollection( ptable ); 2121 if (iter) { 2122 const OSSymbol *key; 2123 2124 while ((key = (OSSymbol *) iter->getNextObject())) { 2125 // Is object for key a collection? 2126 OSCollection *coll = 2127 OSDynamicCast( OSCollection, ptable->getObject( key )); 2128 2129 if (coll) { 2130 // Yup so mark it as immutable 2131 coll->setOptions( OSCollection::kMASK, 2132 OSCollection::kImmutable ); 2133 } 2134 } 2135 iter->release(); 2136 } 2137 2138 PUNLOCK; 2139 2140 if (needParent) { 2141 ret &= parent->attachToChild( this, plane ); 2142 } 2143 2144 return ret; 2145 } 2146 2147 uint64_t 2148 IORegistryEntry::getRegistryEntryID( void ) 2149 { 2150 if (reserved) { 2151 return reserved->fRegistryEntryID; 2152 } else { 2153 return 0; 2154 } 2155 } 2156 2157 bool 2158 IORegistryEntry::attachToChild( IORegistryEntry * child, 2159 const IORegistryPlane * plane ) 2160 { 2161 OSArray * links; 2162 bool ret; 2163 bool needChild; 2164 2165 if (this == child) { 2166 return false; 2167 } 2168 2169 WLOCK; 2170 2171 ret = makeLink( child, kChildSetIndex, plane ); 2172 2173 if ((links = child->getParentSetReference( plane ))) { 2174 needChild = (false == arrayMember( links, this )); 2175 } else { 2176 needChild = true; 2177 } 2178 if (needChild) { 2179 ret &= child->makeLink(this, kParentSetIndex, plane); 2180 } 2181 2182 UNLOCK; 2183 2184 if (needChild) { 2185 ret &= child->attachToParent( this, plane ); 2186 } 2187 2188 return ret; 2189 } 2190 2191 void 2192 IORegistryEntry::detachFromParent( IORegistryEntry * parent, 2193 const IORegistryPlane * plane ) 2194 { 2195 OSArray * links; 2196 bool needParent; 2197 2198 WLOCK; 2199 2200 parent->retain(); 2201 2202 breakLink( parent, kParentSetIndex, plane ); 2203 2204 if ((links = parent->getChildSetReference( plane ))) { 2205 needParent = arrayMember( links, this ); 2206 } else { 2207 needParent = false; 2208 } 2209 if (needParent) { 2210 parent->breakLink( this, kChildSetIndex, plane ); 2211 } 2212 2213 UNLOCK; 2214 2215 if (needParent) { 2216 parent->detachFromChild( this, plane ); 2217 } 2218 2219 parent->release(); 2220 } 2221 2222 void 2223 IORegistryEntry::detachFromChild( IORegistryEntry * child, 2224 const IORegistryPlane * plane ) 2225 { 2226 OSArray * links; 2227 bool needChild; 2228 2229 WLOCK; 2230 2231 child->retain(); 2232 2233 breakLink( child, kChildSetIndex, plane ); 2234 2235 if ((links = child->getParentSetReference( plane ))) { 2236 needChild = arrayMember( links, this ); 2237 } else { 2238 needChild = false; 2239 } 2240 if (needChild) { 2241 child->breakLink( this, kParentSetIndex, plane ); 2242 } 2243 2244 UNLOCK; 2245 2246 if (needChild) { 2247 child->detachFromParent( this, plane ); 2248 } 2249 2250 child->release(); 2251 } 2252 2253 void 2254 IORegistryEntry::detachAbove( const IORegistryPlane * plane ) 2255 { 2256 IORegistryEntry * parent; 2257 2258 retain(); 2259 while ((parent = copyParentEntry( plane ))) { 2260 detachFromParent( parent, plane ); 2261 parent->release(); 2262 } 2263 release(); 2264 } 2265 2266 void 2267 IORegistryEntry::detachAll( const IORegistryPlane * plane ) 2268 { 2269 OSOrderedSet * all; 2270 IORegistryEntry * next; 2271 IORegistryIterator * regIter; 2272 2273 regIter = IORegistryIterator::iterateOver( this, plane, true ); 2274 if (NULL == regIter) { 2275 return; 2276 } 2277 all = regIter->iterateAll(); 2278 regIter->release(); 2279 2280 detachAbove( plane ); 2281 if (all) { 2282 while ((next = (IORegistryEntry *) all->getLastObject())) { 2283 next->retain(); 2284 all->removeObject(next); 2285 2286 next->detachAbove( plane ); 2287 next->release(); 2288 } 2289 all->release(); 2290 } 2291 } 2292 2293 unsigned int 2294 IORegistryEntry::getDepth( const IORegistryPlane * plane ) const 2295 { 2296 unsigned int depth = 1; 2297 OSArray * parents; 2298 unsigned int oneDepth, maxParentDepth, count; 2299 IORegistryEntry * one; 2300 const IORegistryEntry * next; 2301 unsigned int index; 2302 2303 RLOCK; 2304 2305 next = this; 2306 while ((parents = next->getParentSetReference( plane ))) { 2307 count = parents->getCount(); 2308 if (0 == count) { 2309 break; 2310 } 2311 if (1 == count) { 2312 depth++; 2313 next = (IORegistryEntry *) parents->getObject( 0 ); 2314 } else { 2315 // painful 2316 maxParentDepth = 0; 2317 for (index = 0; 2318 (one = (IORegistryEntry *) parents->getObject( index )); 2319 index++) { 2320 oneDepth = one->getDepth( plane ); 2321 if (oneDepth > maxParentDepth) { 2322 maxParentDepth = oneDepth; 2323 } 2324 } 2325 depth += maxParentDepth; 2326 break; 2327 } 2328 } 2329 2330 UNLOCK; 2331 2332 return depth; 2333 } 2334 2335 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 2336 2337 #undef super 2338 #define super OSIterator 2339 2340 OSDefineMetaClassAndStructors(IORegistryIterator, OSIterator) 2341 2342 enum { kIORegistryIteratorInvalidFlag = 0x80000000 }; 2343 2344 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 2345 2346 IORegistryIterator * 2347 IORegistryIterator::iterateOver( IORegistryEntry * root, 2348 const IORegistryPlane * plane, 2349 IOOptionBits options ) 2350 { 2351 IORegistryIterator * create; 2352 2353 if (NULL == root) { 2354 return NULL; 2355 } 2356 if (NULL == plane) { 2357 return NULL; 2358 } 2359 2360 create = new IORegistryIterator; 2361 if (create) { 2362 if (create->init()) { 2363 root->retain(); 2364 create->root = root; 2365 create->where = &create->start; 2366 create->start.current = root; 2367 create->plane = plane; 2368 create->options = options & ~kIORegistryIteratorInvalidFlag; 2369 } else { 2370 create->release(); 2371 create = NULL; 2372 } 2373 } 2374 return create; 2375 } 2376 2377 IORegistryIterator * 2378 IORegistryIterator::iterateOver( const IORegistryPlane * plane, 2379 IOOptionBits options ) 2380 { 2381 return iterateOver( gRegistryRoot, plane, options ); 2382 } 2383 2384 bool 2385 IORegistryIterator::isValid( void ) 2386 { 2387 bool ok; 2388 IORegCursor * next; 2389 2390 next = where; 2391 2392 RLOCK; 2393 2394 ok = (0 == (kIORegistryIteratorInvalidFlag & options)); 2395 2396 while (ok && next) { 2397 if (where->iter) { 2398 ok = where->iter->isValid(); 2399 } 2400 next = next->next; 2401 } 2402 UNLOCK; 2403 2404 return ok; 2405 } 2406 2407 void 2408 IORegistryIterator::enterEntry( const IORegistryPlane * enterPlane ) 2409 { 2410 IORegCursor * prev; 2411 2412 prev = where; 2413 where = IOMallocType(IORegCursor); 2414 assert( where); 2415 2416 if (where) { 2417 where->iter = NULL; 2418 where->next = prev; 2419 where->current = prev->current; 2420 plane = enterPlane; 2421 } 2422 } 2423 2424 void 2425 IORegistryIterator::enterEntry( void ) 2426 { 2427 enterEntry( plane ); 2428 } 2429 2430 bool 2431 IORegistryIterator::exitEntry( void ) 2432 { 2433 IORegCursor * gone; 2434 2435 if (where->iter) { 2436 where->iter->release(); 2437 where->iter = NULL; 2438 if (where->current) {// && (where != &start)) 2439 where->current->release(); 2440 } 2441 } 2442 2443 if (where != &start) { 2444 gone = where; 2445 where = gone->next; 2446 IOFreeType(gone, IORegCursor); 2447 return true; 2448 } else { 2449 return false; 2450 } 2451 } 2452 2453 void 2454 IORegistryIterator::reset( void ) 2455 { 2456 while (exitEntry()) { 2457 } 2458 2459 if (done) { 2460 done->release(); 2461 done = NULL; 2462 } 2463 2464 where->current = root; 2465 options &= ~kIORegistryIteratorInvalidFlag; 2466 } 2467 2468 void 2469 IORegistryIterator::free( void ) 2470 { 2471 reset(); 2472 2473 if (root) { 2474 root->release(); 2475 } 2476 2477 super::free(); 2478 } 2479 2480 2481 IORegistryEntry * 2482 IORegistryIterator::getNextObjectFlat( void ) 2483 { 2484 IORegistryEntry * next = NULL; 2485 OSArray * links = NULL; 2486 2487 RLOCK; 2488 2489 if ((NULL == where->iter)) { 2490 // just entered - create new iter 2491 if (isValid() 2492 && where->current 2493 && (links = ((options & kIORegistryIterateParents) ? 2494 where->current->getParentSetReference( plane ) : 2495 where->current->getChildSetReference( plane )))) { 2496 where->iter = OSCollectionIterator::withCollection( links ); 2497 } 2498 } else 2499 // next sibling - release current 2500 if (where->current) { 2501 where->current->release(); 2502 } 2503 2504 if (where->iter) { 2505 next = (IORegistryEntry *) where->iter->getNextObject(); 2506 2507 if (next) { 2508 next->retain(); 2509 } else if (!where->iter->isValid()) { 2510 options |= kIORegistryIteratorInvalidFlag; 2511 } 2512 } 2513 2514 where->current = next; 2515 2516 UNLOCK; 2517 2518 return next; 2519 } 2520 2521 IORegistryEntry * 2522 IORegistryIterator::getNextObjectRecursive( void ) 2523 { 2524 IORegistryEntry * next; 2525 2526 do{ 2527 next = getNextObjectFlat(); 2528 } while ((NULL == next) && exitEntry()); 2529 2530 if (next) { 2531 if (NULL == done) { 2532 done = OSOrderedSet::withCapacity( 10 ); 2533 } 2534 if (done->setObject((OSObject *) next)) { 2535 // done set didn't contain this one, so recurse 2536 enterEntry(); 2537 } 2538 } 2539 return next; 2540 } 2541 2542 IORegistryEntry * 2543 IORegistryIterator::getNextObject( void ) 2544 { 2545 if (options & kIORegistryIterateRecursively) { 2546 return getNextObjectRecursive(); 2547 } else { 2548 return getNextObjectFlat(); 2549 } 2550 } 2551 2552 IORegistryEntry * 2553 IORegistryIterator::getCurrentEntry( void ) 2554 { 2555 if (isValid()) { 2556 return where->current; 2557 } else { 2558 return NULL; 2559 } 2560 } 2561 2562 OSOrderedSet * 2563 IORegistryIterator::iterateAll( void ) 2564 { 2565 reset(); 2566 while (getNextObjectRecursive()) { 2567 } 2568 if (done) { 2569 done->retain(); 2570 } 2571 return done; 2572 } 2573 2574 #if __LP64__ 2575 OSMetaClassDefineReservedUnused(IORegistryEntry, 0); 2576 OSMetaClassDefineReservedUnused(IORegistryEntry, 1); 2577 OSMetaClassDefineReservedUnused(IORegistryEntry, 2); 2578 OSMetaClassDefineReservedUnused(IORegistryEntry, 3); 2579 OSMetaClassDefineReservedUnused(IORegistryEntry, 4); 2580 OSMetaClassDefineReservedUnused(IORegistryEntry, 5); 2581 #else 2582 OSMetaClassDefineReservedUsedX86(IORegistryEntry, 0); 2583 OSMetaClassDefineReservedUsedX86(IORegistryEntry, 1); 2584 OSMetaClassDefineReservedUsedX86(IORegistryEntry, 2); 2585 OSMetaClassDefineReservedUsedX86(IORegistryEntry, 3); 2586 OSMetaClassDefineReservedUsedX86(IORegistryEntry, 4); 2587 OSMetaClassDefineReservedUsedX86(IORegistryEntry, 5); 2588 #endif 2589 OSMetaClassDefineReservedUnused(IORegistryEntry, 6); 2590 OSMetaClassDefineReservedUnused(IORegistryEntry, 7); 2591 OSMetaClassDefineReservedUnused(IORegistryEntry, 8); 2592 OSMetaClassDefineReservedUnused(IORegistryEntry, 9); 2593 OSMetaClassDefineReservedUnused(IORegistryEntry, 10); 2594 OSMetaClassDefineReservedUnused(IORegistryEntry, 11); 2595 OSMetaClassDefineReservedUnused(IORegistryEntry, 12); 2596 OSMetaClassDefineReservedUnused(IORegistryEntry, 13); 2597 OSMetaClassDefineReservedUnused(IORegistryEntry, 14); 2598 OSMetaClassDefineReservedUnused(IORegistryEntry, 15); 2599 OSMetaClassDefineReservedUnused(IORegistryEntry, 16); 2600 OSMetaClassDefineReservedUnused(IORegistryEntry, 17); 2601 OSMetaClassDefineReservedUnused(IORegistryEntry, 18); 2602 OSMetaClassDefineReservedUnused(IORegistryEntry, 19); 2603 OSMetaClassDefineReservedUnused(IORegistryEntry, 20); 2604 OSMetaClassDefineReservedUnused(IORegistryEntry, 21); 2605 OSMetaClassDefineReservedUnused(IORegistryEntry, 22); 2606 OSMetaClassDefineReservedUnused(IORegistryEntry, 23); 2607 OSMetaClassDefineReservedUnused(IORegistryEntry, 24); 2608 OSMetaClassDefineReservedUnused(IORegistryEntry, 25); 2609 OSMetaClassDefineReservedUnused(IORegistryEntry, 26); 2610 OSMetaClassDefineReservedUnused(IORegistryEntry, 27); 2611 OSMetaClassDefineReservedUnused(IORegistryEntry, 28); 2612 OSMetaClassDefineReservedUnused(IORegistryEntry, 29); 2613 OSMetaClassDefineReservedUnused(IORegistryEntry, 30); 2614 OSMetaClassDefineReservedUnused(IORegistryEntry, 31); 2615 2616 /* inline function implementation */ 2617 OSDictionary * 2618 IORegistryEntry::getPropertyTable( void ) const 2619 { 2620 return fPropertyTable; 2621 } 2622