The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/iokit/Kernel/IORegistryEntry.cpp

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    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 
   49 OSDefineMetaClassAndStructors(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 static IORegistryEntry * gRegistryRoot;
   64 static OSDictionary *    gIORegistryPlanes;
   65 
   66 const OSSymbol *        gIONameKey;
   67 const OSSymbol *        gIOLocationKey;
   68 
   69 enum {
   70     kParentSetIndex     = 0,
   71     kChildSetIndex      = 1,
   72     kNumSetIndex
   73 };
   74 enum {
   75     kIOMaxPlaneName     = 32
   76 };
   77 
   78 class 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 
   90 public:
   91     virtual bool serialize(OSSerialize *s) const;
   92 };
   93 
   94 OSDefineMetaClassAndStructors(IORegistryPlane, OSObject)
   95 
   96 
   97 static IORecursiveLock *        gPropertiesLock;
   98 static 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 
  121 lck_rw_t        gIORegistryLock;
  122 lck_grp_t       *gIORegistryLockGrp;
  123 lck_grp_attr_t  *gIORegistryLockGrpAttr;
  124 lck_attr_t      *gIORegistryLockAttr;
  125 
  126 
  127 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
  128 
  129 IORegistryEntry * 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 
  164 IORegistryEntry * IORegistryEntry::getRegistryRoot( void )
  165 {
  166     return( gRegistryRoot );
  167 }
  168 
  169 SInt32 IORegistryEntry::getGenerationCount( void )
  170 {
  171     return( gIORegistryGenerationCount );
  172 }
  173 
  174 
  175 const 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 
  239 const 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 
  250 bool IORegistryPlane::serialize(OSSerialize *s) const
  251 {
  252     return( nameKey->serialize(s) );
  253 }
  254 
  255 enum { kIORegCapacityIncrement = 4 };
  256 
  257 bool 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 
  298 bool 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 
  341 void 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 
  371 void 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)                                           \
  385 OSObject *                                                              \
  386 IORegistryEntry::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) \
  400 OSObject * \
  401 IORegistryEntry::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) \
  424 OSObject * \
  425 IORegistryEntry::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 
  447 bool 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 
  460 OSDictionary * 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 
  472 IOReturn IORegistryEntry::setProperties( OSObject * properties )
  473 {
  474     return( kIOReturnUnsupported );
  475 }
  476 
  477 wrap2(const OSSymbol, const)       // copyProperty() definition
  478 wrap2(const OSString, const)       // copyProperty() definition
  479 wrap2(const char, const)           // copyProperty() definition
  480 
  481 wrap4(const OSSymbol, const)       // getProperty() w/plane definition
  482 wrap4(const OSString, const)       // getProperty() w/plane definition
  483 wrap4(const char, const)           // getProperty() w/plane definition
  484 
  485 wrap5(const OSSymbol, const)       // copyProperty() w/plane definition
  486 wrap5(const OSString, const)       // copyProperty() w/plane definition
  487 wrap5(const char, const)           // copyProperty() w/plane definition
  488 
  489 
  490 OSObject *
  491 IORegistryEntry::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 
  502 void
  503 IORegistryEntry::removeProperty( const OSSymbol * aKey)
  504 {
  505     PLOCK;
  506     getPropertyTable()->removeObject( aKey );
  507     PUNLOCK;
  508 }
  509 
  510 bool
  511 IORegistryEntry::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 
  531 IOReturn IORegistryEntry::
  532 runPropertyAction(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 
  545 OSObject *
  546 IORegistryEntry::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 
  555 OSObject *
  556 IORegistryEntry::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 
  566 void
  567 IORegistryEntry::removeProperty( const OSString * aKey)
  568 {
  569     const OSSymbol * tmpKey = OSSymbol::withString( aKey );
  570     removeProperty( tmpKey );
  571     tmpKey->release();
  572 }
  573 
  574 void
  575 IORegistryEntry::removeProperty( const char * aKey)
  576 {
  577     const OSSymbol * tmpKey = OSSymbol::withCString( aKey );
  578     removeProperty( tmpKey );
  579     tmpKey->release();
  580 }
  581 
  582 bool
  583 IORegistryEntry::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 
  592 bool
  593 IORegistryEntry::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 
  602 bool
  603 IORegistryEntry::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 
  618 bool
  619 IORegistryEntry::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 
  634 bool
  635 IORegistryEntry::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 
  652 bool
  653 IORegistryEntry::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 
  674 const 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 
  691 const 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 
  711 const 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 
  728 const 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 
  741 void 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 
  758 void 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 
  768 void 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 
  785 void 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 
  795 bool
  796 IORegistryEntry::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 
  814 bool
  815 IORegistryEntry::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 
  842 bool 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 
  945 bool 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 
  977 const 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 
 1022 IORegistryEntry * 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 
 1069 const 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 
 1109 const 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 
 1149 IORegistryEntry * 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 
 1244 IORegistryEntry * 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 
 1260 inline 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 
 1277 bool 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 
 1305 void 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 
 1324 OSArray * 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 
 1334 OSIterator * 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 
 1359 IORegistryEntry * 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 
 1376 IORegistryEntry * 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 
 1387 OSArray * 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 
 1396 OSIterator * 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 
 1421 IORegistryEntry * 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 
 1439 IORegistryEntry * 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 
 1451 void 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 
 1474 void 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 
 1497 bool 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 
 1518 bool 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 
 1540 bool 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 
 1584 bool 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 
 1636 bool 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 
 1663 void 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 
 1690 void 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 
 1715 void 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 
 1725 void 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 
 1751 unsigned 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 
 1796 OSDefineMetaClassAndStructors(IORegistryIterator, OSIterator)
 1797 
 1798 enum { kIORegistryIteratorInvalidFlag = 0x80000000 };
 1799 
 1800 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
 1801 
 1802 IORegistryIterator *
 1803 IORegistryIterator::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 
 1833 IORegistryIterator *
 1834 IORegistryIterator::iterateOver( const IORegistryPlane * plane,
 1835                                  IOOptionBits options )
 1836 {
 1837     return( iterateOver( gRegistryRoot, plane, options ));
 1838 }
 1839 
 1840 bool 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 
 1861 void 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 
 1877 void IORegistryIterator::enterEntry( void )
 1878 {
 1879     enterEntry( plane );
 1880 }
 1881 
 1882 bool 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 
 1903 void 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 
 1917 void IORegistryIterator::free( void )
 1918 {
 1919     reset();
 1920 
 1921     if( root)
 1922         root->release();
 1923 
 1924     super::free();
 1925 }
 1926 
 1927 
 1928 IORegistryEntry * 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 
 1967 IORegistryEntry * 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 
 1986 IORegistryEntry * IORegistryIterator::getNextObject( void )
 1987 {
 1988     if( options & kIORegistryIterateRecursively)
 1989         return( getNextObjectRecursive());
 1990     else
 1991         return( getNextObjectFlat());
 1992 }
 1993 
 1994 IORegistryEntry * IORegistryIterator::getCurrentEntry( void )
 1995 {
 1996     if( isValid())
 1997         return( where->current);
 1998     else
 1999         return( 0);
 2000 }
 2001 
 2002 OSOrderedSet * IORegistryIterator::iterateAll( void )
 2003 {
 2004     reset();
 2005     while( getNextObjectRecursive())
 2006         {}
 2007     if( done)
 2008         done->retain();
 2009     return( done);
 2010 }
 2011 
 2012 OSMetaClassDefineReservedUsed(IORegistryEntry, 0);
 2013 OSMetaClassDefineReservedUsed(IORegistryEntry, 1);
 2014 OSMetaClassDefineReservedUsed(IORegistryEntry, 2);
 2015 OSMetaClassDefineReservedUsed(IORegistryEntry, 3);
 2016 OSMetaClassDefineReservedUsed(IORegistryEntry, 4);
 2017 OSMetaClassDefineReservedUsed(IORegistryEntry, 5);
 2018 
 2019 OSMetaClassDefineReservedUnused(IORegistryEntry, 6);
 2020 OSMetaClassDefineReservedUnused(IORegistryEntry, 7);
 2021 OSMetaClassDefineReservedUnused(IORegistryEntry, 8);
 2022 OSMetaClassDefineReservedUnused(IORegistryEntry, 9);
 2023 OSMetaClassDefineReservedUnused(IORegistryEntry, 10);
 2024 OSMetaClassDefineReservedUnused(IORegistryEntry, 11);
 2025 OSMetaClassDefineReservedUnused(IORegistryEntry, 12);
 2026 OSMetaClassDefineReservedUnused(IORegistryEntry, 13);
 2027 OSMetaClassDefineReservedUnused(IORegistryEntry, 14);
 2028 OSMetaClassDefineReservedUnused(IORegistryEntry, 15);
 2029 OSMetaClassDefineReservedUnused(IORegistryEntry, 16);
 2030 OSMetaClassDefineReservedUnused(IORegistryEntry, 17);
 2031 OSMetaClassDefineReservedUnused(IORegistryEntry, 18);
 2032 OSMetaClassDefineReservedUnused(IORegistryEntry, 19);
 2033 OSMetaClassDefineReservedUnused(IORegistryEntry, 20);
 2034 OSMetaClassDefineReservedUnused(IORegistryEntry, 21);
 2035 OSMetaClassDefineReservedUnused(IORegistryEntry, 22);
 2036 OSMetaClassDefineReservedUnused(IORegistryEntry, 23);
 2037 OSMetaClassDefineReservedUnused(IORegistryEntry, 24);
 2038 OSMetaClassDefineReservedUnused(IORegistryEntry, 25);
 2039 OSMetaClassDefineReservedUnused(IORegistryEntry, 26);
 2040 OSMetaClassDefineReservedUnused(IORegistryEntry, 27);
 2041 OSMetaClassDefineReservedUnused(IORegistryEntry, 28);
 2042 OSMetaClassDefineReservedUnused(IORegistryEntry, 29);
 2043 OSMetaClassDefineReservedUnused(IORegistryEntry, 30);
 2044 OSMetaClassDefineReservedUnused(IORegistryEntry, 31);
 2045 
 2046 /* inline function implementation */
 2047 OSDictionary * IORegistryEntry::getPropertyTable( void ) const
 2048 { return(fPropertyTable); }

Cache object: 822841ac716ce97ff8ef3774a2cdc45d


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.