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::withDictionary( fRegistryTable ); 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 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 entry = this; 921 parent = entry->getParentEntry( plane ); 922 if( !parent) 923 // Error if not attached in plane 924 return( false); 925 926 stack = OSArray::withCapacity( getDepth( plane )); 927 if( !stack) 928 return( false); 929 930 RLOCK; 931 932 root = gRegistryRoot->getChildEntry( plane ); 933 while( parent && (entry != root)) { 934 // stop below root 935 stack->setObject( (OSObject *) entry ); 936 entry = parent; 937 parent = entry->getParentEntry( plane ); 938 } 939 940 index = stack->getCount(); 941 ok = true; 942 943 if( 0 == index) { 944 945 *nextComp++ = '/'; 946 *nextComp = 0; 947 len++; 948 949 } else while( ok && ((--index) >= 0)) { 950 951 entry = (IORegistryEntry *) stack->getObject((unsigned int) index ); 952 assert( entry ); 953 954 if( (alias = entry->hasAlias( plane ))) { 955 len = plane->nameKey->getLength() + 1; 956 nextComp = path + len; 957 958 compLen = alias->getLength(); 959 ok = (maxLength > (len + compLen)); 960 if( ok) 961 strlcpy( nextComp, alias->getCStringNoCopy(), compLen + 1); 962 } else { 963 compLen = maxLength - len; 964 ok = entry->getPathComponent( nextComp + 1, &compLen, plane ); 965 966 if( ok && compLen) { 967 compLen++; 968 *nextComp = '/'; 969 } 970 } 971 972 if( ok) { 973 len += compLen; 974 nextComp += compLen; 975 } 976 } 977 *length = len; 978 979 UNLOCK; 980 981 stack->release(); 982 983 return( ok ); 984} 985 986bool IORegistryEntry::getPathComponent( char * path, int * length, 987 const IORegistryPlane * plane ) const 988{ 989 int len, locLen, maxLength; 990 const char * compName; 991 const char * loc; 992 bool ok; 993 994 maxLength = *length; 995 996 compName = getName( plane ); 997 len = strlen( compName ); 998 if( (loc = getLocation( plane ))) 999 locLen = 1 + strlen( loc ); 1000 else 1001 locLen = 0; 1002 1003 ok = ((len + locLen + 1) < maxLength); 1004 if( ok) { 1005 strlcpy( path, compName, len + 1 ); 1006 if( loc) { 1007 path += len; 1008 len += locLen; 1009 *path++ = '@'; 1010 strlcpy( path, loc, locLen ); 1011 } 1012 *length = len; 1013 } 1014 1015 return( ok ); 1016} 1017 1018const char * IORegistryEntry::matchPathLocation( const char * cmp, 1019 const IORegistryPlane * plane ) 1020{ 1021 const char * str; 1022 const char * result = 0; 1023 u_quad_t num1, num2; 1024 char lastPathChar, lastLocationChar; 1025 1026 str = getLocation( plane ); 1027 if( str) { 1028 lastPathChar = cmp[0]; 1029 lastLocationChar = str[0]; 1030 do { 1031 if( lastPathChar) { 1032 num1 = strtouq( cmp, (char **) &cmp, 16 ); 1033 lastPathChar = *cmp++; 1034 } else 1035 num1 = 0; 1036 1037 if( lastLocationChar) { 1038 num2 = strtouq( str, (char **) &str, 16 ); 1039 lastLocationChar = *str++; 1040 } else 1041 num2 = 0; 1042 1043 if( num1 != num2) 1044 break; 1045 1046 if (!lastPathChar && !lastLocationChar) { 1047 result = cmp - 1; 1048 break; 1049 } 1050 1051 if( (',' != lastPathChar) && (':' != lastPathChar)) 1052 lastPathChar = 0; 1053 1054 if (lastPathChar && lastLocationChar && (lastPathChar != lastLocationChar)) 1055 break; 1056 1057 } while( true); 1058 } 1059 1060 return( result ); 1061} 1062 1063IORegistryEntry * IORegistryEntry::getChildFromComponent( const char ** opath, 1064 const IORegistryPlane * plane ) 1065{ 1066 IORegistryEntry * entry = 0; 1067 OSArray * set; 1068 unsigned int index; 1069 const char * path; 1070 const char * cmp = 0; 1071 char c; 1072 size_t len; 1073 const char * str; 1074 1075 set = getChildSetReference( plane ); 1076 if( set) { 1077 1078 path = *opath; 1079 1080 for( index = 0; 1081 (entry = (IORegistryEntry *) set->getObject(index)); 1082 index++ ) { 1083 1084 cmp = path; 1085 1086 if( *cmp != '@') { 1087 str = entry->getName( plane ); 1088 len = strlen( str ); 1089 if( strncmp( str, cmp, len )) 1090 continue; 1091 cmp += len; 1092 1093 c = *cmp; 1094 if( (c == 0) || (c == '/') || (c == ':')) 1095 break; 1096 if( c != '@') 1097 continue; 1098 } 1099 cmp++; 1100 if( (cmp = entry->matchPathLocation( cmp, plane ))) 1101 break; 1102 } 1103 if( entry) 1104 *opath = cmp; 1105 } 1106 1107 return( entry ); 1108} 1109 1110const OSSymbol * IORegistryEntry::hasAlias( const IORegistryPlane * plane, 1111 char * opath, int * length ) const 1112{ 1113 IORegistryEntry * entry; 1114 IORegistryEntry * entry2; 1115 const OSSymbol * key; 1116 const OSSymbol * bestKey = 0; 1117 OSIterator * iter; 1118 OSData * data; 1119 const char * path = "/aliases"; 1120 1121 entry = IORegistryEntry::fromPath( path, plane ); 1122 if( entry) { 1123 RLOCK; 1124 if( (iter = OSCollectionIterator::withCollection( 1125 entry->getPropertyTable() ))) { 1126 1127 while( (key = (OSSymbol *) iter->getNextObject())) { 1128 1129 data = (OSData *) entry->getProperty( key ); 1130 path = (const char *) data->getBytesNoCopy(); 1131 if( (entry2 = IORegistryEntry::fromPath( path, plane, 1132 opath, length ))) { 1133 if( this == entry2) { 1134 if( !bestKey 1135 || (bestKey->getLength() > key->getLength())) 1136 // pick the smallest alias 1137 bestKey = key; 1138 } 1139 entry2->release(); 1140 } 1141 } 1142 iter->release(); 1143 } 1144 entry->release(); 1145 UNLOCK; 1146 } 1147 return( bestKey ); 1148} 1149 1150const char * IORegistryEntry::dealiasPath( 1151 const char ** opath, 1152 const IORegistryPlane * plane ) 1153{ 1154 IORegistryEntry * entry; 1155 OSData * data; 1156 const char * path = *opath; 1157 const char * rpath = 0; 1158 const char * end; 1159 char c; 1160 char temp[ kIOMaxPlaneName + 1 ]; 1161 1162 if( path[0] == '/') 1163 return( rpath ); 1164 1165 // check for alias 1166 end = path; 1167 while( (c = *end++) && (c != '/') && (c != ':')) 1168 {} 1169 end--; 1170 if( (end - path) < kIOMaxPlaneName) { 1171 strlcpy( temp, path, end - path + 1 ); 1172 1173 RLOCK; 1174 entry = IORegistryEntry::fromPath( "/aliases", plane ); 1175 if( entry) { 1176 data = (OSData *) entry->getProperty( temp ); 1177 if( data ) { 1178 rpath = (const char *) data->getBytesNoCopy(); 1179 if( rpath) 1180 *opath = end; 1181 } 1182 entry->release(); 1183 } 1184 UNLOCK; 1185 } 1186 1187 return( rpath ); 1188} 1189 1190IORegistryEntry * IORegistryEntry::fromPath( 1191 const char * path, 1192 const IORegistryPlane * plane, 1193 char * opath, 1194 int * length, 1195 IORegistryEntry * fromEntry ) 1196{ 1197 IORegistryEntry * where = 0; 1198 IORegistryEntry * aliasEntry = 0; 1199 IORegistryEntry * next; 1200 const char * alias; 1201 const char * end; 1202 int len = 0; 1203 int len2; 1204 char c; 1205 char temp[ kIOMaxPlaneName + 1 ]; 1206 1207 if( 0 == path) 1208 return( 0 ); 1209 1210 if( 0 == plane) { 1211 // get plane name 1212 end = strchr( path, ':' ); 1213 if( end && ((end - path) < kIOMaxPlaneName)) { 1214 strlcpy( temp, path, end - path + 1 ); 1215 plane = getPlane( temp ); 1216 path = end + 1; 1217 } 1218 } 1219 if( 0 == plane) 1220 return( 0 ); 1221 1222 // check for alias 1223 end = path; 1224 if( (alias = dealiasPath( &end, plane))) { 1225 if( length) 1226 len = *length; 1227 aliasEntry = IORegistryEntry::fromPath( alias, plane, 1228 opath, &len, fromEntry ); 1229 where = aliasEntry; 1230 if( where) 1231 path = end; 1232 else 1233 len = 0; 1234 } 1235 1236 RLOCK; 1237 1238 do { 1239 if( 0 == where) { 1240 if( (0 == fromEntry) && (*path++ == '/')) 1241 fromEntry = gRegistryRoot->getChildEntry( plane ); 1242 where = fromEntry; 1243 if( 0 == where) 1244 break; 1245 } else { 1246 c = *path++; 1247 if( c != '/') { 1248 if( c && (c != ':')) // check valid terminator 1249 where = 0; 1250 break; 1251 } 1252 } 1253 next = where->getChildFromComponent( &path, plane ); 1254 if( next) 1255 where = next; 1256 } while( next ); 1257 1258 if( where) { 1259 // check residual path 1260 if( where != fromEntry) 1261 path--; 1262 1263 if( opath && length) { 1264 // copy out residual path 1265 len2 = strlen( path ); 1266 if( (len + len2) < *length) 1267 strlcpy( opath + len, path, len2 + 1 ); 1268 *length = (len + len2); 1269 1270 } else if( path[0]) 1271 // no residual path => must be no tail for success 1272 where = 0; 1273 } 1274 1275 if( where) 1276 where->retain(); 1277 if( aliasEntry) 1278 aliasEntry->release(); 1279 1280 UNLOCK; 1281 1282 return( where ); 1283} 1284 1285IORegistryEntry * IORegistryEntry::childFromPath( 1286 const char * path, 1287 const IORegistryPlane * plane, 1288 char * opath, 1289 int * len ) 1290{ 1291 return( IORegistryEntry::fromPath( path, plane, opath, len, this )); 1292} 1293 1294/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 1295 1296#define IOLinkIterator OSCollectionIterator 1297 1298#undef super 1299#define super OSObject 1300 1301inline bool IORegistryEntry::arrayMember( OSArray * set, 1302 const IORegistryEntry * member, 1303 unsigned int * index ) const 1304{ 1305 int i; 1306 OSObject * probeObject; 1307 1308 for( i = 0; (probeObject = set->getObject(i)); i++) { 1309 if (probeObject == (OSObject *) member) { 1310 if( index) 1311 *index = i; 1312 return( true ); 1313 } 1314 } 1315 return( false ); 1316} 1317 1318bool IORegistryEntry::makeLink( IORegistryEntry * to, 1319 unsigned int relation, 1320 const IORegistryPlane * plane ) const 1321{ 1322 OSArray * links; 1323 bool result = false; 1324 1325 if( (links = (OSArray *) 1326 registryTable()->getObject( plane->keys[ relation ] ))) { 1327 1328 result = arrayMember( links, to ); 1329 if( !result) 1330 result = links->setObject( to ); 1331 1332 } else { 1333 1334 links = OSArray::withObjects( (const OSObject **) &to, 1, 1 ); 1335 result = (links != 0); 1336 if( result) { 1337 result = registryTable()->setObject( plane->keys[ relation ], 1338 links ); 1339 links->release(); 1340 } 1341 } 1342 1343 return( result); 1344} 1345 1346void IORegistryEntry::breakLink( IORegistryEntry * to, 1347 unsigned int relation, 1348 const IORegistryPlane * plane ) const 1349{ 1350 OSArray * links; 1351 unsigned int index; 1352 1353 if( (links = (OSArray *) 1354 registryTable()->getObject( plane->keys[ relation ]))) { 1355 1356 if( arrayMember( links, to, &index )) { 1357 links->removeObject( index ); 1358 if( 0 == links->getCount()) 1359 registryTable()->removeObject( plane->keys[ relation ]); 1360 } 1361 } 1362} 1363 1364 1365OSArray * IORegistryEntry::getParentSetReference( 1366 const IORegistryPlane * plane ) const 1367{ 1368 if( plane) 1369 return( (OSArray *) registryTable()->getObject( 1370 plane->keys[ kParentSetIndex ])); 1371 else 1372 return( 0 ); 1373} 1374 1375OSIterator * IORegistryEntry::getParentIterator( 1376 const IORegistryPlane * plane ) const 1377{ 1378 OSArray * links; 1379 OSIterator * iter; 1380 1381 if( !plane) 1382 return( 0 ); 1383 1384 RLOCK; 1385 links = getParentSetReference( plane ); 1386 if( 0 == links) 1387 links = OSArray::withCapacity( 1 ); 1388 else 1389 links = OSArray::withArray( links, links->getCount() ); 1390 UNLOCK; 1391 1392 iter = IOLinkIterator::withCollection( links ); 1393 1394 if( links) 1395 links->release(); 1396 1397 return( iter ); 1398} 1399 1400IORegistryEntry * IORegistryEntry::copyParentEntry( const IORegistryPlane * plane ) const 1401{ 1402 IORegistryEntry * entry = 0; 1403 OSArray * links; 1404 1405 RLOCK; 1406 1407 if( (links = getParentSetReference( plane ))) { 1408 entry = (IORegistryEntry *) links->getObject( 0 ); 1409 entry->retain(); 1410 } 1411 1412 UNLOCK; 1413 1414 return( entry); 1415} 1416 1417IORegistryEntry * IORegistryEntry::getParentEntry( const IORegistryPlane * plane ) const 1418{ 1419 IORegistryEntry * entry; 1420 1421 entry = copyParentEntry( plane ); 1422 if( entry) 1423 entry->release(); 1424 1425 return( entry ); 1426} 1427 1428OSArray * IORegistryEntry::getChildSetReference( const IORegistryPlane * plane ) const 1429{ 1430 if( plane) 1431 return( (OSArray *) registryTable()->getObject( 1432 plane->keys[ kChildSetIndex ])); 1433 else 1434 return( 0 ); 1435} 1436 1437OSIterator * IORegistryEntry::getChildIterator( const IORegistryPlane * plane ) const 1438{ 1439 OSArray * links; 1440 OSIterator * iter; 1441 1442 if( !plane) 1443 return( 0 ); 1444 1445 RLOCK; 1446 links = getChildSetReference( plane ); 1447 if( 0 == links) 1448 links = OSArray::withCapacity( 1 ); 1449 else 1450 links = OSArray::withArray( links, links->getCount() ); 1451 UNLOCK; 1452 1453 iter = IOLinkIterator::withCollection( links ); 1454 1455 if( links) 1456 links->release(); 1457 1458 return( iter ); 1459} 1460 1461 1462IORegistryEntry * IORegistryEntry::copyChildEntry( 1463 const IORegistryPlane * plane ) const 1464{ 1465 IORegistryEntry * entry = 0; 1466 OSArray * links; 1467 1468 RLOCK; 1469 1470 if( (links = getChildSetReference( plane ))) { 1471 entry = (IORegistryEntry *) links->getObject( 0 ); 1472 entry->retain(); 1473 } 1474 1475 UNLOCK; 1476 1477 return( entry); 1478} 1479 1480IORegistryEntry * IORegistryEntry::getChildEntry( 1481 const IORegistryPlane * plane ) const 1482{ 1483 IORegistryEntry * entry; 1484 1485 entry = copyChildEntry( plane ); 1486 if( entry) 1487 entry->release(); 1488 1489 return( entry ); 1490} 1491 1492void IORegistryEntry::applyToChildren( IORegistryEntryApplierFunction applier, 1493 void * context, 1494 const IORegistryPlane * plane ) const 1495{ 1496 OSArray * array; 1497 unsigned int index; 1498 IORegistryEntry * next; 1499 1500 if( !plane) 1501 return; 1502 1503 RLOCK; 1504 array = OSArray::withArray( getChildSetReference( plane )); 1505 UNLOCK; 1506 if( array) { 1507 for( index = 0; 1508 (next = (IORegistryEntry *) array->getObject( index )); 1509 index++) 1510 (*applier)(next, context); 1511 array->release(); 1512 } 1513} 1514 1515void IORegistryEntry::applyToParents( IORegistryEntryApplierFunction applier, 1516 void * context, 1517 const IORegistryPlane * plane ) const 1518{ 1519 OSArray * array; 1520 unsigned int index; 1521 IORegistryEntry * next; 1522 1523 if( !plane) 1524 return; 1525 1526 RLOCK; 1527 array = OSArray::withArray( getParentSetReference( plane )); 1528 UNLOCK; 1529 if( array) { 1530 for( index = 0; 1531 (next = (IORegistryEntry *) array->getObject( index )); 1532 index++) 1533 (*applier)(next, context); 1534 array->release(); 1535 } 1536} 1537 1538bool IORegistryEntry::isChild( IORegistryEntry * child, 1539 const IORegistryPlane * plane, 1540 bool onlyChild ) const 1541{ 1542 OSArray * links; 1543 bool ret = false; 1544 1545 RLOCK; 1546 1547 if( (links = getChildSetReference( plane ))) { 1548 if( (!onlyChild) || (1 == links->getCount())) 1549 ret = arrayMember( links, child ); 1550 } 1551 if( ret && (links = child->getParentSetReference( plane ))) 1552 ret = arrayMember( links, this ); 1553 1554 UNLOCK; 1555 1556 return( ret); 1557} 1558 1559bool IORegistryEntry::isParent( IORegistryEntry * parent, 1560 const IORegistryPlane * plane, 1561 bool onlyParent ) const 1562 1563{ 1564 OSArray * links; 1565 bool ret = false; 1566 1567 RLOCK; 1568 1569 if( (links = getParentSetReference( plane ))) { 1570 if( (!onlyParent) || (1 == links->getCount())) 1571 ret = arrayMember( links, parent ); 1572 } 1573 if( ret && (links = parent->getChildSetReference( plane ))) 1574 ret = arrayMember( links, this ); 1575 1576 UNLOCK; 1577 1578 return( ret); 1579} 1580 1581bool IORegistryEntry::inPlane( const IORegistryPlane * plane ) const 1582{ 1583 bool ret; 1584 1585 RLOCK; 1586 1587 if( plane) 1588 ret = (0 != getParentSetReference( plane )); 1589 else { 1590 1591 // Check to see if this is in any plane. If it is in a plane 1592 // then the registryTable will contain a key with the ParentLinks 1593 // suffix. When we iterate over the keys looking for that suffix 1594 ret = false; 1595 1596 OSCollectionIterator *iter = 1597 OSCollectionIterator::withCollection( registryTable()); 1598 if( iter) { 1599 const OSSymbol *key; 1600 1601 while( (key = (OSSymbol *) iter->getNextObject()) ) { 1602 size_t keysuffix; 1603 1604 // Get a pointer to this keys suffix 1605 keysuffix = key->getLength(); 1606 if (keysuffix <= kIORegPlaneParentSuffixLen) 1607 continue; 1608 keysuffix -= kIORegPlaneParentSuffixLen; 1609 if( !strncmp(key->getCStringNoCopy() + keysuffix, 1610 kIORegPlaneParentSuffix, 1611 kIORegPlaneParentSuffixLen + 1) ) { 1612 ret = true; 1613 break; 1614 } 1615 } 1616 iter->release(); 1617 } 1618 } 1619 1620 UNLOCK; 1621 1622 return( ret ); 1623} 1624 1625bool IORegistryEntry::attachToParent( IORegistryEntry * parent, 1626 const IORegistryPlane * plane ) 1627{ 1628 OSArray * links; 1629 bool ret; 1630 bool needParent; 1631 1632 if( this == parent) 1633 return( false ); 1634 1635 WLOCK; 1636 1637 if (!reserved->fRegistryEntryID) 1638 reserved->fRegistryEntryID = ++gIORegistryLastID; 1639 1640 ret = makeLink( parent, kParentSetIndex, plane ); 1641 1642 if( (links = parent->getChildSetReference( plane ))) 1643 needParent = (false == arrayMember( links, this )); 1644 else 1645 needParent = true; 1646 1647 UNLOCK; 1648 1649 PLOCK; 1650 1651 // Mark any collections in the property list as immutable 1652 OSDictionary *ptable = getPropertyTable(); 1653 OSCollectionIterator *iter = 1654 OSCollectionIterator::withCollection( ptable ); 1655 if( iter) { 1656 const OSSymbol *key; 1657 1658 while( (key = (OSSymbol *) iter->getNextObject( ))) { 1659 // Is object for key a collection? 1660 OSCollection *coll = 1661 OSDynamicCast( OSCollection, ptable->getObject( key )); 1662 1663 if( coll) { 1664 // Yup so mark it as immutable 1665 coll->setOptions( OSCollection::kMASK, 1666 OSCollection::kImmutable ); 1667 } 1668 } 1669 iter->release(); 1670 } 1671 1672 PUNLOCK; 1673 1674 if( needParent) 1675 ret &= parent->attachToChild( this, plane ); 1676 1677 return( ret ); 1678} 1679 1680uint64_t IORegistryEntry::getRegistryEntryID( void ) 1681{ 1682 if (reserved) 1683 return (reserved->fRegistryEntryID); 1684 else 1685 return (0); 1686} 1687 1688bool IORegistryEntry::attachToChild( IORegistryEntry * child, 1689 const IORegistryPlane * plane ) 1690{ 1691 OSArray * links; 1692 bool ret; 1693 bool needChild; 1694 1695 if( this == child) 1696 return( false ); 1697 1698 WLOCK; 1699 1700 ret = makeLink( child, kChildSetIndex, plane ); 1701 1702 if( (links = child->getParentSetReference( plane ))) 1703 needChild = (false == arrayMember( links, this )); 1704 else 1705 needChild = true; 1706 1707 UNLOCK; 1708 1709 if( needChild) 1710 ret &= child->attachToParent( this, plane ); 1711 1712 return( ret ); 1713} 1714 1715void IORegistryEntry::detachFromParent( IORegistryEntry * parent, 1716 const IORegistryPlane * plane ) 1717{ 1718 OSArray * links; 1719 bool needParent; 1720 1721 WLOCK; 1722 1723 parent->retain(); 1724 1725 breakLink( parent, kParentSetIndex, plane ); 1726 1727 if( (links = parent->getChildSetReference( plane ))) 1728 needParent = arrayMember( links, this ); 1729 else 1730 needParent = false; 1731 1732// parent->breakLink( this, kChildSetIndex, plane ); 1733 1734 UNLOCK; 1735 1736 if( needParent) 1737 parent->detachFromChild( this, plane ); 1738 1739 parent->release(); 1740} 1741 1742void IORegistryEntry::detachFromChild( IORegistryEntry * child, 1743 const IORegistryPlane * plane ) 1744{ 1745 OSArray * links; 1746 bool needChild; 1747 1748 WLOCK; 1749 1750 child->retain(); 1751 1752 breakLink( child, kChildSetIndex, plane ); 1753 1754 if( (links = child->getParentSetReference( plane ))) 1755 needChild = arrayMember( links, this ); 1756 else 1757 needChild = false; 1758 1759 UNLOCK; 1760 1761 if( needChild) 1762 child->detachFromParent( this, plane ); 1763 1764 child->release(); 1765} 1766 1767void IORegistryEntry::detachAbove( const IORegistryPlane * plane ) 1768{ 1769 IORegistryEntry * parent; 1770 1771 retain(); 1772 while( (parent = getParentEntry( plane ))) 1773 detachFromParent( parent, plane ); 1774 release(); 1775} 1776 1777void IORegistryEntry::detachAll( const IORegistryPlane * plane ) 1778{ 1779 OSOrderedSet * all; 1780 IORegistryEntry * next; 1781 IORegistryIterator * regIter; 1782 1783 regIter = IORegistryIterator::iterateOver( this, plane, true ); 1784 if( 0 == regIter) 1785 return; 1786 all = regIter->iterateAll(); 1787 regIter->release(); 1788 1789 detachAbove( plane ); 1790 if( all) { 1791 while( (next = (IORegistryEntry *) all->getLastObject())) { 1792 1793 next->retain(); 1794 all->removeObject(next); 1795 1796 next->detachAbove( plane ); 1797 next->release(); 1798 } 1799 all->release(); 1800 } 1801} 1802 1803unsigned int IORegistryEntry::getDepth( const IORegistryPlane * plane ) const 1804{ 1805 unsigned int depth = 1; 1806 OSArray * parents; 1807 unsigned int oneDepth, maxParentDepth, count; 1808 IORegistryEntry * one; 1809 const IORegistryEntry * next; 1810 unsigned int index; 1811 1812 RLOCK; 1813 1814 next = this; 1815 while( (parents = next->getParentSetReference( plane ))) { 1816 1817 count = parents->getCount(); 1818 if( 0 == count) 1819 break; 1820 if( 1 == count) { 1821 depth++; 1822 next = (IORegistryEntry *) parents->getObject( 0 ); 1823 } else { 1824 // painful 1825 maxParentDepth = 0; 1826 for( index = 0; 1827 (one = (IORegistryEntry *) parents->getObject( index )); 1828 index++ ) { 1829 oneDepth = one->getDepth( plane ); 1830 if( oneDepth > maxParentDepth) 1831 maxParentDepth = oneDepth; 1832 } 1833 depth += maxParentDepth; 1834 break; 1835 } 1836 } 1837 1838 UNLOCK; 1839 1840 return( depth); 1841} 1842 1843/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 1844 1845#undef super 1846#define super OSIterator 1847 1848OSDefineMetaClassAndStructors(IORegistryIterator, OSIterator) 1849 1850enum { kIORegistryIteratorInvalidFlag = 0x80000000 }; 1851 1852/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 1853 1854IORegistryIterator * 1855IORegistryIterator::iterateOver( IORegistryEntry * root, 1856 const IORegistryPlane * plane, 1857 IOOptionBits options ) 1858{ 1859 IORegistryIterator * create; 1860 1861 if( 0 == root) 1862 return( 0); 1863 if( 0 == plane) 1864 return( 0); 1865 1866 create = new IORegistryIterator; 1867 if( create) { 1868 if( create->init()) { 1869 1870 root->retain(); 1871 create->root = root; 1872 create->where = &create->start; 1873 create->start.current = root; 1874 create->plane = plane; 1875 create->options = options & ~kIORegistryIteratorInvalidFlag; 1876 1877 } else { 1878 create->release(); 1879 create = 0; 1880 } 1881 } 1882 return( create); 1883} 1884 1885IORegistryIterator * 1886IORegistryIterator::iterateOver( const IORegistryPlane * plane, 1887 IOOptionBits options ) 1888{ 1889 return( iterateOver( gRegistryRoot, plane, options )); 1890} 1891 1892bool IORegistryIterator::isValid( void ) 1893{ 1894 bool ok; 1895 IORegCursor * next; 1896 1897 next = where; 1898 1899 RLOCK; 1900 1901 ok = (0 == (kIORegistryIteratorInvalidFlag & options)); 1902 1903 while( ok && next) { 1904 if( where->iter) 1905 ok = where->iter->isValid(); 1906 next = next->next; 1907 } 1908 UNLOCK; 1909 1910 return( ok); 1911} 1912 1913void IORegistryIterator::enterEntry( const IORegistryPlane * enterPlane ) 1914{ 1915 IORegCursor * prev; 1916 1917 prev = where; 1918 where = (IORegCursor *) IOMalloc( sizeof(IORegCursor)); 1919 assert( where); 1920 1921 if( where) { 1922 where->iter = 0; 1923 where->next = prev; 1924 where->current = prev->current; 1925 plane = enterPlane; 1926 } 1927} 1928 1929void IORegistryIterator::enterEntry( void ) 1930{ 1931 enterEntry( plane ); 1932} 1933 1934bool IORegistryIterator::exitEntry( void ) 1935{ 1936 IORegCursor * gone; 1937 1938 if( where->iter) { 1939 where->iter->release(); 1940 where->iter = 0; 1941 if( where->current)// && (where != &start)) 1942 where->current->release(); 1943 } 1944 1945 if( where != &start) { 1946 gone = where; 1947 where = gone->next; 1948 IOFree( gone, sizeof(IORegCursor)); 1949 return( true); 1950 1951 } else 1952 return( false); 1953} 1954 1955void IORegistryIterator::reset( void ) 1956{ 1957 while( exitEntry()) 1958 {} 1959 1960 if( done) { 1961 done->release(); 1962 done = 0; 1963 } 1964 1965 where->current = root; 1966 options &= ~kIORegistryIteratorInvalidFlag; 1967} 1968 1969void IORegistryIterator::free( void ) 1970{ 1971 reset(); 1972 1973 if( root) 1974 root->release(); 1975 1976 super::free(); 1977} 1978 1979 1980IORegistryEntry * IORegistryIterator::getNextObjectFlat( void ) 1981{ 1982 IORegistryEntry * next = 0; 1983 OSArray * links = 0; 1984 1985 RLOCK; 1986 1987 if( (0 == where->iter)) { 1988 // just entered - create new iter 1989 if( isValid() 1990 && where->current 1991 && (links = ( (options & kIORegistryIterateParents) ? 1992 where->current->getParentSetReference( plane ) : 1993 where->current->getChildSetReference( plane ) )) ) 1994 1995 where->iter = OSCollectionIterator::withCollection( links ); 1996 1997 } else 1998 // next sibling - release current 1999 if( where->current) 2000 where->current->release(); 2001 2002 if( where->iter) { 2003 2004 next = (IORegistryEntry *) where->iter->getNextObject(); 2005 2006 if( next) 2007 next->retain(); 2008 else if( !where->iter->isValid()) 2009 options |= kIORegistryIteratorInvalidFlag; 2010 } 2011 2012 where->current = next; 2013 2014 UNLOCK; 2015 2016 return( next); 2017} 2018 2019IORegistryEntry * IORegistryIterator::getNextObjectRecursive( void ) 2020{ 2021 IORegistryEntry * next; 2022 2023 do 2024 next = getNextObjectFlat(); 2025 while( (0 == next) && exitEntry()); 2026 2027 if( next) { 2028 if( 0 == done) 2029 done = OSOrderedSet::withCapacity( 10 ); 2030 if( done->setObject((OSObject *) next)) { 2031 // done set didn't contain this one, so recurse 2032 enterEntry(); 2033 } 2034 } 2035 return( next); 2036} 2037 2038IORegistryEntry * IORegistryIterator::getNextObject( void ) 2039{ 2040 if( options & kIORegistryIterateRecursively) 2041 return( getNextObjectRecursive()); 2042 else 2043 return( getNextObjectFlat()); 2044} 2045 2046IORegistryEntry * IORegistryIterator::getCurrentEntry( void ) 2047{ 2048 if( isValid()) 2049 return( where->current); 2050 else 2051 return( 0); 2052} 2053 2054OSOrderedSet * IORegistryIterator::iterateAll( void ) 2055{ 2056 reset(); 2057 while( getNextObjectRecursive()) 2058 {} 2059 if( done) 2060 done->retain(); 2061 return( done); 2062} 2063 2064#if __LP64__ 2065OSMetaClassDefineReservedUnused(IORegistryEntry, 0); 2066OSMetaClassDefineReservedUnused(IORegistryEntry, 1); 2067OSMetaClassDefineReservedUnused(IORegistryEntry, 2); 2068OSMetaClassDefineReservedUnused(IORegistryEntry, 3); 2069OSMetaClassDefineReservedUnused(IORegistryEntry, 4); 2070OSMetaClassDefineReservedUnused(IORegistryEntry, 5); 2071#else 2072OSMetaClassDefineReservedUsed(IORegistryEntry, 0); 2073OSMetaClassDefineReservedUsed(IORegistryEntry, 1); 2074OSMetaClassDefineReservedUsed(IORegistryEntry, 2); 2075OSMetaClassDefineReservedUsed(IORegistryEntry, 3); 2076OSMetaClassDefineReservedUsed(IORegistryEntry, 4); 2077OSMetaClassDefineReservedUsed(IORegistryEntry, 5); 2078#endif 2079OSMetaClassDefineReservedUnused(IORegistryEntry, 6); 2080OSMetaClassDefineReservedUnused(IORegistryEntry, 7); 2081OSMetaClassDefineReservedUnused(IORegistryEntry, 8); 2082OSMetaClassDefineReservedUnused(IORegistryEntry, 9); 2083OSMetaClassDefineReservedUnused(IORegistryEntry, 10); 2084OSMetaClassDefineReservedUnused(IORegistryEntry, 11); 2085OSMetaClassDefineReservedUnused(IORegistryEntry, 12); 2086OSMetaClassDefineReservedUnused(IORegistryEntry, 13); 2087OSMetaClassDefineReservedUnused(IORegistryEntry, 14); 2088OSMetaClassDefineReservedUnused(IORegistryEntry, 15); 2089OSMetaClassDefineReservedUnused(IORegistryEntry, 16); 2090OSMetaClassDefineReservedUnused(IORegistryEntry, 17); 2091OSMetaClassDefineReservedUnused(IORegistryEntry, 18); 2092OSMetaClassDefineReservedUnused(IORegistryEntry, 19); 2093OSMetaClassDefineReservedUnused(IORegistryEntry, 20); 2094OSMetaClassDefineReservedUnused(IORegistryEntry, 21); 2095OSMetaClassDefineReservedUnused(IORegistryEntry, 22); 2096OSMetaClassDefineReservedUnused(IORegistryEntry, 23); 2097OSMetaClassDefineReservedUnused(IORegistryEntry, 24); 2098OSMetaClassDefineReservedUnused(IORegistryEntry, 25); 2099OSMetaClassDefineReservedUnused(IORegistryEntry, 26); 2100OSMetaClassDefineReservedUnused(IORegistryEntry, 27); 2101OSMetaClassDefineReservedUnused(IORegistryEntry, 28); 2102OSMetaClassDefineReservedUnused(IORegistryEntry, 29); 2103OSMetaClassDefineReservedUnused(IORegistryEntry, 30); 2104OSMetaClassDefineReservedUnused(IORegistryEntry, 31); 2105 2106/* inline function implementation */ 2107OSDictionary * IORegistryEntry::getPropertyTable( void ) const 2108{ return(fPropertyTable); } 2109