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