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