Annotation of XNU/iokit/Kernel/IORegistryEntry.cpp, revision 1.1.1.1

1.1       root        1: /*
                      2:  * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved.
                      3:  *
                      4:  * @APPLE_LICENSE_HEADER_START@
                      5:  * 
                      6:  * The contents of this file constitute Original Code as defined in and
                      7:  * are subject to the Apple Public Source License Version 1.1 (the
                      8:  * "License").  You may not use this file except in compliance with the
                      9:  * License.  Please obtain a copy of the License at
                     10:  * http://www.apple.com/publicsource and read it before using this file.
                     11:  * 
                     12:  * This Original Code and all software distributed under the License are
                     13:  * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
                     14:  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
                     15:  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
                     16:  * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
                     17:  * License for the specific language governing rights and limitations
                     18:  * under the License.
                     19:  * 
                     20:  * @APPLE_LICENSE_HEADER_END@
                     21:  */
                     22: /*
                     23:  * Copyright (c) 1998 Apple Computer, Inc.  All rights reserved. 
                     24:  *
                     25:  * HISTORY
                     26:  * 12 Nov 98 sdouglas created.
                     27:  *
                     28:  */
                     29: 
                     30: #include <IOKit/IORegistryEntry.h>
                     31: #include <libkern/c++/OSContainers.h>
                     32: #include <IOKit/IOService.h>
                     33: #include <IOKit/IOKitKeys.h>
                     34: 
                     35: #include <IOKit/IOLib.h>
                     36: 
                     37: #include <IOKit/assert.h>
                     38: 
                     39: /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
                     40: 
                     41: #define super OSObject
                     42: 
                     43: OSDefineMetaClassAndStructors(IORegistryEntry, OSObject)
                     44: 
                     45: /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
                     46: 
                     47: static IORegistryEntry * gRegistryRoot;
                     48: static OSDictionary *   gIORegistryPlanes;
                     49: 
                     50: const OSSymbol *       gIONameKey;
                     51: const OSSymbol *       gIOLocationKey;
                     52: 
                     53: enum {
                     54:     kParentSetIndex    = 0,
                     55:     kChildSetIndex     = 1,
                     56:     kNumSetIndex
                     57: };
                     58: enum {
                     59:     kIOMaxPlaneName    = 32
                     60: };
                     61: 
                     62: class IORegistryPlane : public OSObject {
                     63: 
                     64:     friend IORegistryEntry;
                     65: 
                     66:     OSDeclareAbstractStructors(IORegistryPlane)
                     67: 
                     68:     const OSSymbol *   nameKey;
                     69:     const OSSymbol *   keys[ kNumSetIndex ];
                     70:     const OSSymbol *   pathNameKey;
                     71:     const OSSymbol *   pathLocationKey;
                     72:     int                        reserved[2];
                     73: 
                     74: public:
                     75:     virtual bool serialize(OSSerialize *s) const;
                     76: };
                     77: 
                     78: OSDefineMetaClassAndStructors(IORegistryPlane, OSObject)
                     79: 
                     80: 
                     81: static lock_t *                        gIORegistryLock;
                     82: static IORecursiveLock *       gPropertiesLock;
                     83: static SInt32                  gIORegistryGenerationCount;
                     84: 
                     85: #define UNLOCK lock_done( gIORegistryLock )
                     86: #define RLOCK  lock_read( gIORegistryLock )
                     87: #define WLOCK  lock_write( gIORegistryLock );  \
                     88:                gIORegistryGenerationCount++
                     89:                // make atomic
                     90: 
                     91: #define PUNLOCK        IORecursiveLockUnlock( gPropertiesLock )
                     92: #define PLOCK  IORecursiveLockLock( gPropertiesLock )
                     93: 
                     94: #define IOREGSPLITTABLES
                     95: 
                     96: #ifdef IOREGSPLITTABLES
                     97: #define registryTable()        fRegistryTable
                     98: #else
                     99: #define registryTable()        fPropertyTable
                    100: #endif
                    101: 
                    102: /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
                    103: 
                    104: IORegistryEntry * IORegistryEntry::initialize( void )
                    105: {
                    106:    bool                        ok;
                    107: 
                    108:     if( !gRegistryRoot) {
                    109: 
                    110:        gRegistryRoot = new IORegistryEntry;
                    111:         gIORegistryLock = lock_alloc(true, NULL, NULL);
                    112:        gPropertiesLock = IORecursiveLockAlloc();
                    113:        gIORegistryPlanes = OSDictionary::withCapacity( 1 );
                    114: 
                    115:        assert( gRegistryRoot && gIORegistryLock && gPropertiesLock
                    116:                && gIORegistryPlanes );
                    117:         ok = gRegistryRoot->init();
                    118: 
                    119:        gIONameKey = OSSymbol::withCStringNoCopy( "IOName" );
                    120:        gIOLocationKey = OSSymbol::withCStringNoCopy( "IOLocation" );
                    121: 
                    122:        assert( ok && gIONameKey && gIOLocationKey );
                    123: 
                    124:        gRegistryRoot->setName( "Root" );
                    125:         gRegistryRoot->setProperty( kIORegistryPlanesKey, gIORegistryPlanes );
                    126:     }
                    127: 
                    128:     return( gRegistryRoot );
                    129: }
                    130: 
                    131: IORegistryEntry * IORegistryEntry::getRegistryRoot( void )
                    132: {
                    133:     return( gRegistryRoot );
                    134: }
                    135: 
                    136: SInt32 IORegistryEntry::getGenerationCount( void )
                    137: {
                    138:     return( gIORegistryGenerationCount );
                    139: }
                    140: 
                    141: 
                    142: const IORegistryPlane * IORegistryEntry::makePlane( const char * name )
                    143: {
                    144:     IORegistryPlane *  plane;
                    145:     const OSSymbol *   nameKey;
                    146:     const OSSymbol *   parentKey;
                    147:     const OSSymbol *   childKey;
                    148:     const OSSymbol *   pathNameKey;
                    149:     const OSSymbol *   pathLocationKey;
                    150:     char               key[ kIOMaxPlaneName + 16 ];
                    151:     char *             end;
                    152: 
                    153:     strncpy( key, name, kIOMaxPlaneName );
                    154:     key[ kIOMaxPlaneName ] = 0;
                    155:     end = key + strlen( name );
                    156: 
                    157:     nameKey = OSSymbol::withCString( key);
                    158: 
                    159:     strcpy( end, "ParentLinks" );
                    160:     parentKey = OSSymbol::withCString( key);
                    161: 
                    162:     strcpy( end, "ChildLinks" );
                    163:     childKey = OSSymbol::withCString( key);
                    164: 
                    165:     strcpy( end, "Name" );
                    166:     pathNameKey = OSSymbol::withCString( key);
                    167: 
                    168:     strcpy( end, "Location" );
                    169:     pathLocationKey = OSSymbol::withCString( key);
                    170: 
                    171:     plane = new IORegistryPlane;
                    172: 
                    173:     if( plane && plane->init()
                    174:        && nameKey && parentKey && childKey
                    175:        && pathNameKey && pathLocationKey ) {
                    176: 
                    177:        plane->nameKey = nameKey;
                    178:        plane->keys[ kParentSetIndex ] = parentKey;
                    179:        plane->keys[ kChildSetIndex ] = childKey;
                    180:        plane->pathNameKey = pathNameKey;
                    181:        plane->pathLocationKey = pathLocationKey;
                    182: 
                    183:        WLOCK;
                    184:         gIORegistryPlanes->setObject( nameKey, plane );
                    185:        UNLOCK;
                    186: 
                    187:     } else {
                    188: 
                    189:        if( plane)
                    190:            plane->release();
                    191:        if( pathLocationKey)
                    192:            pathLocationKey->release();
                    193:        if( pathNameKey)
                    194:            pathNameKey->release();
                    195:        if( parentKey)
                    196:            parentKey->release();
                    197:        if( childKey)
                    198:            childKey->release();
                    199:        if( nameKey)
                    200:            nameKey->release();
                    201:        plane = 0;
                    202:     }
                    203: 
                    204:     return( plane);
                    205: }
                    206: 
                    207: const IORegistryPlane * IORegistryEntry::getPlane( const char * name )
                    208: {
                    209:     const IORegistryPlane *    plane;
                    210: 
                    211:     RLOCK;
                    212:     plane = (const IORegistryPlane *) gIORegistryPlanes->getObject( name );
                    213:     UNLOCK;
                    214: 
                    215:     return( plane );
                    216: }
                    217: 
                    218: bool IORegistryPlane::serialize(OSSerialize *s) const
                    219: {
                    220:     return( nameKey->serialize(s) );
                    221: }
                    222: 
                    223: enum { kIORegCapacityIncrement = 4 };
                    224: 
                    225: bool IORegistryEntry::init( OSDictionary * dict = 0 )
                    226: {
                    227:     OSString * prop;
                    228: 
                    229:     if( !super::init())
                    230:        return( false);
                    231: 
                    232:     if( dict) {
                    233:        dict->retain();
                    234:        fPropertyTable = dict;
                    235: 
                    236:     } else {
                    237:         fPropertyTable = OSDictionary::withCapacity( kIORegCapacityIncrement );
                    238:        if( fPropertyTable)
                    239:             fPropertyTable->setCapacityIncrement( kIORegCapacityIncrement );
                    240:     }
                    241: 
                    242:     if( !fPropertyTable)
                    243:         return( false);
                    244: 
                    245: #ifdef IOREGSPLITTABLES
                    246:     fRegistryTable = OSDictionary::withCapacity( kIORegCapacityIncrement );
                    247:     if( fRegistryTable)
                    248:         fRegistryTable->setCapacityIncrement( kIORegCapacityIncrement );
                    249: 
                    250:     if( (prop = OSDynamicCast( OSString, getProperty( gIONameKey)))) {
                    251:         OSSymbol * sym = (OSSymbol *)OSSymbol::withString( prop);
                    252:         // ok for OSSymbol too
                    253:         setName( sym);
                    254:         sym->release();
                    255:     }
                    256: 
                    257: #endif /* IOREGSPLITTABLES */
                    258: 
                    259:     return( true);
                    260: }
                    261: 
                    262: bool IORegistryEntry::init( IORegistryEntry * old,
                    263:                                const IORegistryPlane * plane )
                    264: {
                    265:     OSArray *          all;
                    266:     IORegistryEntry *          next;
                    267:     unsigned int       index;
                    268: 
                    269:     if( !super::init())
                    270:        return( false);
                    271: 
                    272:     WLOCK;
                    273: 
                    274:     fPropertyTable = old->getPropertyTable();
                    275:     old->fPropertyTable = 0;
                    276: #ifdef IOREGSPLITTABLES
                    277:     fRegistryTable = old->fRegistryTable;
                    278:     old->fRegistryTable = 0;
                    279: #endif /* IOREGSPLITTABLES */
                    280: 
                    281:     all = getParentSetReference( plane );
                    282:     if( all) for( index = 0;
                    283:               (next = (IORegistryEntry *) all->getObject(index));
                    284:               index++ ) {
                    285:            next->makeLink( this, kChildSetIndex, plane );
                    286:             next->breakLink( old, kChildSetIndex, plane );
                    287:     }
                    288: 
                    289:     all = getChildSetReference( plane );
                    290:     if( all) for( index = 0;
                    291:               (next = (IORegistryEntry *) all->getObject(index));
                    292:               index++ ) {
                    293:            next->makeLink( this, kParentSetIndex, plane );
                    294:             next->breakLink( old, kParentSetIndex, plane );
                    295:     }
                    296: 
                    297:     UNLOCK;
                    298: 
                    299:     return( true );
                    300: }
                    301: 
                    302: void IORegistryEntry::free( void )
                    303: {
                    304: 
                    305: #ifdef DEBUG
                    306:     OSArray *                  links;
                    307:     const OSSymbol *           key;
                    308:     const IORegistryPlane *    plane;
                    309:     OSCollectionIterator *     iter;
                    310: 
                    311:     if( registryTable()) {
                    312:         iter = OSCollectionIterator::withCollection( gIORegistryPlanes );
                    313:         if( iter) {
                    314:             while( (key = (const OSSymbol *) iter->getNextObject())) {
                    315:                 if( 0 == (plane = (const IORegistryPlane *)
                    316:                        OSDynamicCast( IORegistryPlane,
                    317:                                  gIORegistryPlanes->getObject( key ))))
                    318:                    continue;
                    319:                 if( (links = getParentSetReference( plane ))
                    320:                  || (links = getChildSetReference( plane )) ) {
                    321: 
                    322:                     IOLog("%s: Still attached in %s at free()\n",
                    323:                                getName(), plane->nameKey->getCStringNoCopy());
                    324:                }
                    325:             }
                    326:             iter->release();
                    327:         }
                    328:     }
                    329: #endif
                    330: 
                    331:     if( getPropertyTable())
                    332:         getPropertyTable()->release();
                    333: 
                    334: #ifdef IOREGSPLITTABLES
                    335:     if( registryTable())
                    336:         registryTable()->release();
                    337: #endif /* IOREGSPLITTABLES */
                    338: 
                    339:     super::free();
                    340: }
                    341: 
                    342: void IORegistryEntry::setPropertyTable( OSDictionary * dict )
                    343: {
                    344:     if( fPropertyTable)
                    345:        fPropertyTable->release();
                    346:     if( dict)
                    347:        dict->retain();
                    348:     fPropertyTable = dict;
                    349: }
                    350: 
                    351: /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
                    352: 
                    353: /* Wrappers to synchronize property table */
                    354: 
                    355: #define wrap1(func,type,constant)                                      \
                    356: OSObject *                                                             \
                    357: IORegistryEntry::func ## Property( type * aKey) constant               \
                    358: {                                                                      \
                    359:     OSObject * obj;                                                    \
                    360:                                                                        \
                    361:     PLOCK;                                     \
                    362:     obj = getPropertyTable()->func ## Object( aKey );                  \
                    363:     PUNLOCK;                                   \
                    364:                                                                        \
                    365:     return( obj );                                                     \
                    366: }
                    367: 
                    368: #define wrap2(func,type)                                               \
                    369: OSObject *                                                             \
                    370: IORegistryEntry::func ## Object( OSObject * anObject, type * aKey)     \
                    371: {                                                                      \
                    372:     OSObject * obj;                                                    \
                    373:                                                                        \
                    374:     PLOCK;                                     \
                    375:     obj = getPropertyTable()->func ## Object( anObject, aKey );                \
                    376:     PUNLOCK;                                   \
                    377:                                                                        \
                    378:     return( obj );                                                     \
                    379: }
                    380: 
                    381: #define wrap3(func,type,constant)                                      \
                    382: void                                                           \
                    383: IORegistryEntry::func ## Property( type * aKey) constant               \
                    384: {                                                                      \
                    385:     PLOCK;                                     \
                    386:     getPropertyTable()->func ## Object( aKey );                        \
                    387:     PUNLOCK;                                   \
                    388: }
                    389: 
                    390: bool IORegistryEntry::serializeProperties( OSSerialize * s ) const
                    391: {
                    392:     bool ok;
                    393: 
                    394: //    setProperty( getRetainCount(), 32, "__retain" );
                    395: 
                    396:     PLOCK;
                    397:     ok = getPropertyTable()->serialize( s );
                    398:     PUNLOCK;
                    399: 
                    400:     return( ok );
                    401: }
                    402: 
                    403: OSDictionary * IORegistryEntry::dictionaryWithProperties( void ) const
                    404: {
                    405:     OSDictionary *     dict;
                    406: 
                    407:     PLOCK;
                    408:     dict = OSDictionary::withDictionary( getPropertyTable(),
                    409:                             getPropertyTable()->getCapacity() );
                    410:     PUNLOCK;
                    411: 
                    412:     return( dict );
                    413: }
                    414: 
                    415: IOReturn IORegistryEntry::setProperties( OSObject * properties )
                    416: {
                    417:     return( kIOReturnUnsupported );
                    418: }
                    419: 
                    420: wrap1(get, const OSSymbol, const)  // getProperty() definition
                    421: wrap1(get, const OSString, const)  // getProperty() definition
                    422: wrap1(get, const char, const)      // getProperty() definition
                    423: 
                    424: wrap3(remove, const OSSymbol,)     // removeProperty() definition
                    425: wrap3(remove, const OSString,)     // removeProperty() definition
                    426: wrap3(remove, const char,)         // removeProperty() definition
                    427: 
                    428: bool
                    429: IORegistryEntry::setProperty( const OSSymbol * aKey, OSObject * anObject)
                    430: {
                    431:     bool ret = false;
                    432:     PLOCK;
                    433:     ret = getPropertyTable()->setObject( aKey, anObject );
                    434:     PUNLOCK;
                    435:     
                    436:     return ret;
                    437: }
                    438: 
                    439: bool
                    440: IORegistryEntry::setProperty( const OSString * aKey, OSObject * anObject)
                    441: {
                    442:     bool ret = false;
                    443:     PLOCK;
                    444:     ret = getPropertyTable()->setObject( aKey, anObject );
                    445:     PUNLOCK;
                    446: 
                    447:     return ret;
                    448: }
                    449: 
                    450: bool
                    451: IORegistryEntry::setProperty( const char * aKey,  OSObject * anObject)
                    452: {
                    453:     bool ret = false;
                    454:     PLOCK;
                    455:     ret = getPropertyTable()->setObject( aKey, anObject );
                    456:     PUNLOCK;
                    457:     
                    458:     return ret;
                    459: }
                    460: 
                    461: bool
                    462: IORegistryEntry::setProperty(const char * aKey, const char * aString)
                    463: {
                    464:     bool ret = false;
                    465:     OSSymbol * aSymbol = (OSSymbol *) OSSymbol::withCString( aString );
                    466: 
                    467:     if( aSymbol) {
                    468:         PLOCK;
                    469:         ret = getPropertyTable()->setObject( aKey, aSymbol );
                    470:         PUNLOCK;
                    471:         aSymbol->release();
                    472:     }
                    473:     return( ret );
                    474: }
                    475: 
                    476: bool
                    477: IORegistryEntry::setProperty(const char * aKey, bool aBoolean)
                    478: {
                    479:     bool ret = false;
                    480:     OSBoolean * aBooleanObj = OSBoolean::withBoolean( aBoolean );
                    481: 
                    482:     if( aBooleanObj) {
                    483:         PLOCK;
                    484:         ret = getPropertyTable()->setObject( aKey, aBooleanObj );
                    485:         PUNLOCK;
                    486:         aBooleanObj->release();
                    487:     }
                    488:     return( ret );
                    489: }
                    490: 
                    491: bool
                    492: IORegistryEntry::setProperty( const char *       aKey,
                    493:                               unsigned long long aValue,
                    494:                               unsigned int       aNumberOfBits)
                    495: {
                    496:     bool ret = false;
                    497:     OSNumber * anOffset = OSNumber::withNumber( aValue, aNumberOfBits );
                    498: 
                    499:     if( anOffset) {
                    500:         PLOCK;
                    501:         ret = getPropertyTable()->setObject( aKey, anOffset );
                    502:         PUNLOCK;
                    503:         anOffset->release();
                    504:     }
                    505:     return( ret );
                    506: }
                    507: 
                    508: bool
                    509: IORegistryEntry::setProperty( const char *      aKey,
                    510:                               void *           bytes,
                    511:                               unsigned int      length)
                    512: {
                    513:     bool ret = false;
                    514:     OSData * data = OSData::withBytes( bytes, length );
                    515: 
                    516:     if( data) {
                    517:         PLOCK;
                    518:         ret = getPropertyTable()->setObject( aKey, data );
                    519:         PUNLOCK;
                    520:         data->release();
                    521:     }
                    522:     return( ret );
                    523: }
                    524: 
                    525: /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
                    526: 
                    527: /* Name, location, paths */
                    528: 
                    529: const char * IORegistryEntry::getName( const IORegistryPlane * plane = 0 ) const
                    530: {
                    531:     OSSymbol *         sym = 0;
                    532: 
                    533:     RLOCK;
                    534:     if( plane)
                    535:        sym = (OSSymbol *) registryTable()->getObject( plane->pathNameKey );
                    536:     if( !sym)
                    537:        sym = (OSSymbol *) registryTable()->getObject( gIONameKey );
                    538:     UNLOCK;
                    539: 
                    540:     if( sym)
                    541:        return( sym->getCStringNoCopy());
                    542:     else
                    543:         return( (getMetaClass())->getClassName());
                    544: }
                    545: 
                    546: const OSSymbol * IORegistryEntry::copyName(
                    547:                        const IORegistryPlane * plane = 0 ) const
                    548: {
                    549:     OSSymbol *         sym = 0;
                    550: 
                    551:     RLOCK;
                    552:     if( plane)
                    553:        sym = (OSSymbol *) registryTable()->getObject( plane->pathNameKey );
                    554:     if( !sym)
                    555:        sym = (OSSymbol *) registryTable()->getObject( gIONameKey );
                    556:     if( sym)
                    557:        sym->retain();
                    558:     UNLOCK;
                    559: 
                    560:     if( sym)
                    561:        return( sym );
                    562:     else
                    563:         return( OSSymbol::withCString((getMetaClass())->getClassName()) );
                    564: }
                    565: 
                    566: const OSSymbol * IORegistryEntry::copyLocation(
                    567:                        const IORegistryPlane * plane = 0 ) const
                    568: {
                    569:     OSSymbol *         sym = 0;
                    570: 
                    571:     RLOCK;
                    572:     if( plane)
                    573:        sym = (OSSymbol *) registryTable()->getObject( plane->pathLocationKey );
                    574:     if( !sym)
                    575:        sym = (OSSymbol *) registryTable()->getObject( gIOLocationKey );
                    576:     if( sym)
                    577:        sym->retain();
                    578:     UNLOCK;
                    579: 
                    580:     return( sym );
                    581: }
                    582: 
                    583: const char * IORegistryEntry::getLocation( const IORegistryPlane * plane = 0 ) const
                    584: {
                    585:     const OSSymbol *   sym = copyLocation( plane );
                    586:     const char *       result = 0;
                    587: 
                    588:     if( sym) {
                    589:        result = sym->getCStringNoCopy();
                    590:        sym->release();
                    591:     }
                    592: 
                    593:     return( result );
                    594: }
                    595: 
                    596: void IORegistryEntry::setName( const OSSymbol * name,
                    597:                             const IORegistryPlane * plane = 0 )
                    598: {
                    599:     const OSSymbol *   key;
                    600: 
                    601:     if( name) {
                    602:         if( plane)
                    603:             key = plane->pathNameKey;
                    604:         else
                    605:             key = gIONameKey;
                    606: 
                    607:        WLOCK;
                    608:         registryTable()->setObject( key, (OSObject *) name);
                    609:        UNLOCK;
                    610:     }
                    611: }
                    612: 
                    613: void IORegistryEntry::setName( const char * name,
                    614:                             const IORegistryPlane * plane = 0 )
                    615: {
                    616:     OSSymbol * sym = (OSSymbol *)OSSymbol::withCString( name );
                    617:     if ( sym ) {
                    618:         setName( sym, plane );
                    619:         sym->release();
                    620:     }
                    621: }
                    622: 
                    623: void IORegistryEntry::setLocation( const OSSymbol * location,
                    624:                             const IORegistryPlane * plane = 0 )
                    625: {
                    626:     const OSSymbol *   key;
                    627: 
                    628:     if( location) {
                    629:         if( plane)
                    630:             key = plane->pathLocationKey;
                    631:         else
                    632:             key = gIOLocationKey;
                    633: 
                    634:        WLOCK;
                    635:         registryTable()->setObject( key, (OSObject *) location);
                    636:        UNLOCK;
                    637:     }
                    638: }
                    639: 
                    640: void IORegistryEntry::setLocation( const char * location,
                    641:                             const IORegistryPlane * plane = 0 )
                    642: {
                    643:     OSSymbol * sym = (OSSymbol *)OSSymbol::withCString( location );
                    644:     if ( sym ) {
                    645:         setLocation( sym, plane );
                    646:         sym->release();
                    647:     }
                    648: }
                    649: 
                    650: bool
                    651: IORegistryEntry::compareName( OSString * name, OSString ** matched = 0 ) const
                    652: {
                    653:     const OSSymbol *   sym = copyName();
                    654:     bool               isEqual;
                    655: 
                    656:     isEqual = sym->isEqualTo( name );
                    657: 
                    658:     if( isEqual && matched) {
                    659:        name->retain();
                    660:        *matched = name;
                    661:     }
                    662: 
                    663:     if( sym)
                    664:        sym->release();
                    665: 
                    666:     return( isEqual );
                    667: }
                    668: 
                    669: bool
                    670: IORegistryEntry::compareNames( OSObject * names, OSString ** matched = 0 ) const
                    671: {
                    672:     OSString *         string;
                    673:     OSCollection *     collection;
                    674:     OSIterator *       iter = 0;
                    675:     bool               result = false;
                    676: 
                    677:     if( (collection = OSDynamicCast( OSCollection, names))) {
                    678:        iter = OSCollectionIterator::withCollection( collection );
                    679:        string = 0;
                    680:     } else
                    681:        string = OSDynamicCast( OSString, names);
                    682: 
                    683:     do {
                    684:        if( string)
                    685:             result = compareName( string, matched );
                    686: 
                    687:     } while( (false == result)
                    688:        && iter && (string = OSDynamicCast( OSString, iter->getNextObject())));
                    689: 
                    690:     if( iter)
                    691:        iter->release();
                    692: 
                    693:     return( result);
                    694: }
                    695: 
                    696: 
                    697: bool IORegistryEntry::getPath( char * path, int * length,
                    698:                                const IORegistryPlane * plane ) const
                    699: {
                    700:     OSArray *          stack;
                    701:     IORegistryEntry *  root;
                    702:     const IORegistryEntry * entry;
                    703:     IORegistryEntry *  parent;
                    704:     const OSSymbol *   alias;
                    705:     int                        index;
                    706:     int                        len, maxLength, compLen;
                    707:     char *             nextComp;
                    708:     bool               ok;
                    709: 
                    710:    if( !path || !length || !plane)
                    711:        return( false);
                    712: 
                    713:     len = 0;
                    714:     maxLength = *length - 2;
                    715:     nextComp = path;
                    716: 
                    717:     len = plane->nameKey->getLength();
                    718:     if( len >= maxLength)
                    719:        return( false);
                    720:     strcpy( nextComp, plane->nameKey->getCStringNoCopy());
                    721:     nextComp[ len++ ] = ':';
                    722:     nextComp += len;
                    723: 
                    724:     if( (alias = hasAlias( plane ))) {
                    725:        len += alias->getLength();
                    726:        ok = (maxLength > len);
                    727:        *length = len;
                    728:        if( ok)
                    729:            strcpy( nextComp, alias->getCStringNoCopy());
                    730:        return( ok );
                    731:     }
                    732: 
                    733:     entry = this;
                    734:     parent = entry->getParentEntry( plane );
                    735:     if( !parent)
                    736:        // Error if not attached in plane
                    737:        return( false);
                    738: 
                    739:     stack = OSArray::withCapacity( getDepth( plane ));
                    740:     if( !stack)
                    741:        return( false);
                    742: 
                    743:     RLOCK;
                    744: 
                    745:     root = gRegistryRoot->getChildEntry( plane );
                    746:     while( parent && (entry != root)) {
                    747:        // stop below root
                    748:        stack->setObject( (OSObject *) entry );
                    749:        entry = parent;
                    750:        parent = entry->getParentEntry( plane );
                    751:     }
                    752: 
                    753:     index = stack->getCount();
                    754:     ok = true;
                    755: 
                    756:     if( 0 == index) {
                    757: 
                    758:         *nextComp++ = '/';
                    759:         *nextComp = 0;
                    760:         len++;
                    761: 
                    762:     } else while( ok && ((--index) >= 0)) {
                    763: 
                    764:         entry = (IORegistryEntry *) stack->getObject((unsigned int) index );
                    765:         assert( entry );
                    766: 
                    767:         compLen = maxLength - len;
                    768:         ok = entry->getPathComponent( nextComp + 1, &compLen, plane );
                    769: 
                    770:         if( ok && compLen) {
                    771:             compLen++;
                    772:             *nextComp = '/';
                    773:             len += compLen;
                    774:             nextComp += compLen;
                    775:        }
                    776:     }
                    777:     *length = len;
                    778: 
                    779:     UNLOCK;
                    780: 
                    781:     stack->release();
                    782: 
                    783:     return( ok );
                    784: }
                    785: 
                    786: bool IORegistryEntry::getPathComponent( char * path, int * length,
                    787:                                         const IORegistryPlane * plane ) const
                    788: {
                    789:     int                        len, locLen, maxLength;
                    790:     const char *       compName;
                    791:     const char *       loc;
                    792:     bool               ok;
                    793: 
                    794:     maxLength = *length;
                    795: 
                    796:     compName = getName( plane );
                    797:     len = strlen( compName );
                    798:     if( (loc = getLocation( plane )))
                    799:        locLen = 1 + strlen( loc );
                    800:     else
                    801:        locLen = 0;
                    802: 
                    803:     ok = ((len + locLen) < maxLength);
                    804:     if( ok) {
                    805:         strcpy( path, compName );
                    806:        if( loc) {
                    807:             path += len;
                    808:             len += locLen;
                    809:             *path++ = '@';
                    810:             strcpy( path, loc );
                    811:        }
                    812:         *length = len;
                    813:     }
                    814: 
                    815:     return( ok );
                    816: }
                    817: 
                    818: const char * IORegistryEntry::matchPathLocation( const char * cmp,
                    819:                                const IORegistryPlane * plane )
                    820: {
                    821:     const char *       str;
                    822:     const char *       result = 0;
                    823:     int                        num1, num2;
                    824:     char               c1, c2;
                    825: 
                    826:     str = getLocation( plane );
                    827:     if( str) {
                    828:        c2 = str[0];
                    829:        do {
                    830:             num1 = strtoul( cmp, (char **) &cmp, 16 );
                    831:             if( c2) {
                    832:                 num2 = strtoul( str, (char **) &str, 16 );
                    833:                 c2 = str[0];
                    834:            } else
                    835:                 num2 = 0;
                    836: 
                    837:             if( num1 != num2)
                    838:                 break;
                    839: 
                    840:             c1 = *cmp++;
                    841:             if( ',' != c1) {
                    842:                 result = cmp - 1;
                    843:                 break;
                    844:             }
                    845: 
                    846:             if( c2) {
                    847:                 if( c2 != ',')
                    848:                     break;
                    849:                 str++;
                    850:             }
                    851: 
                    852:         } while( true);
                    853:     }
                    854: 
                    855:     return( result );
                    856: }
                    857: 
                    858: IORegistryEntry * IORegistryEntry::getChildFromComponent( const char ** opath,
                    859:                                const IORegistryPlane * plane )
                    860: {
                    861:     IORegistryEntry *  entry = 0;
                    862:     OSArray *          set;
                    863:     unsigned int       index;
                    864:     const char *       path;
                    865:     const char *       cmp = 0;
                    866:     size_t             len;
                    867:     const char *       str;
                    868: 
                    869:     set = getChildSetReference( plane );
                    870:     if( set) {
                    871: 
                    872:     path = *opath;
                    873: 
                    874:        for( index = 0;
                    875:              (entry = (IORegistryEntry *) set->getObject(index));
                    876:              index++ ) {
                    877: 
                    878:             cmp = path;
                    879: 
                    880:             if( *cmp != '@') {
                    881:                 str = entry->getName( plane );
                    882:                 len = strlen( str );
                    883:                 if( strncmp( str, cmp, len ))
                    884:                     continue;
                    885:                 cmp += len;
                    886:                 if( *cmp != '@' )
                    887:                 break;
                    888:             }
                    889:             cmp++;
                    890:             if( (cmp = entry->matchPathLocation( cmp, plane )))
                    891:                 break;
                    892:         }
                    893:         if( entry)
                    894:             *opath = cmp;
                    895:     }
                    896: 
                    897:     return( entry );
                    898: }
                    899: 
                    900: const OSSymbol * IORegistryEntry::hasAlias( const IORegistryPlane * plane,
                    901:                                char * opath = 0, int * length = 0 ) const
                    902: {
                    903:     IORegistryEntry *  entry;
                    904:     IORegistryEntry *  entry2;
                    905:     const OSSymbol *   key;
                    906:     const OSSymbol *   bestKey = 0;
                    907:     OSIterator *       iter;
                    908:     OSData *           data;
                    909:     const char *       path = "/aliases";
                    910: 
                    911:     entry = IORegistryEntry::fromPath( path, plane );
                    912:     if( entry) {
                    913:         RLOCK;
                    914:         if( (iter = OSCollectionIterator::withCollection(
                    915:                                entry->getPropertyTable() ))) {
                    916: 
                    917:             while( (key = (OSSymbol *) iter->getNextObject())) {
                    918: 
                    919:                 data = (OSData *) entry->getProperty( key );
                    920:                 path = (const char *) data->getBytesNoCopy();
                    921:                 if( (entry2 = IORegistryEntry::fromPath( path, plane,
                    922:                                                opath, length ))) {
                    923:                     if( this == entry2) {
                    924:                         if( !bestKey
                    925:                         || (bestKey->getLength() > key->getLength()))
                    926:                             // pick the smallest alias
                    927:                             bestKey = key;
                    928:                     }
                    929:                    entry2->release();
                    930:                }
                    931:             }
                    932:             iter->release();
                    933:         }
                    934:        entry->release();
                    935:        UNLOCK;
                    936:     }
                    937:     return( bestKey );
                    938: }
                    939: 
                    940: const char * IORegistryEntry::dealiasPath(
                    941:                        const char **           opath,
                    942:                        const IORegistryPlane * plane )
                    943: {
                    944:     IORegistryEntry *  entry;
                    945:     OSData *           data;
                    946:     const char *       path = *opath;
                    947:     const char *       rpath = 0;
                    948:     const char *       end;
                    949:     char               c;
                    950:     char               temp[ kIOMaxPlaneName + 1 ];
                    951: 
                    952:     if( path[0] == '/')
                    953:        return( rpath );
                    954: 
                    955:     // check for alias
                    956:     end = path;
                    957:     while( (c = *end++) && (c != '/') && (c != ':'))
                    958:         {}
                    959:     end--;
                    960:     if( (end - path) < kIOMaxPlaneName) {
                    961:         strncpy( temp, path, end - path );
                    962:         temp[ end - path ] = 0;
                    963: 
                    964:         RLOCK;
                    965:         entry = IORegistryEntry::fromPath( "/aliases", plane );
                    966:         if( entry) {
                    967:             data = (OSData *) entry->getProperty( temp );
                    968:             if( data ) {
                    969:                 rpath = (const char *) data->getBytesNoCopy();
                    970:                 if( rpath)
                    971:                     *opath = end;
                    972:             }
                    973:            entry->release();
                    974:         }
                    975:         UNLOCK;
                    976:     }
                    977: 
                    978:     return( rpath );
                    979: }
                    980: 
                    981: IORegistryEntry * IORegistryEntry::fromPath(
                    982:                         const char *           path,
                    983:                         const IORegistryPlane * plane = 0,
                    984:                         char *                 opath = 0,
                    985:                        int *                   length = 0,
                    986:                         IORegistryEntry *      fromEntry = 0 )
                    987: {
                    988:     IORegistryEntry *  where = 0;
                    989:     IORegistryEntry *  next;
                    990:     const char *       alias;
                    991:     const char *       end;
                    992:     int                        len = 0;
                    993:     int                        len2;
                    994:     char               c;
                    995:     char               temp[ kIOMaxPlaneName + 1 ];
                    996: 
                    997:     if( 0 == path)
                    998:        return( 0 );
                    999: 
                   1000:     if( 0 == plane) {
                   1001:        // get plane name
                   1002:         end = strchr( path, ':' );
                   1003:        if( end && ((end - path) < kIOMaxPlaneName)) {
                   1004:            strncpy( temp, path, end - path );
                   1005:            temp[ end - path ] = 0;
                   1006:             plane = getPlane( temp );
                   1007:            path = end + 1;
                   1008:        }
                   1009:     }
                   1010:     if( 0 == plane)
                   1011:        return( 0 );
                   1012: 
                   1013:     // check for alias
                   1014:     end = path;
                   1015:     if( (alias = dealiasPath( &end, plane))) {
                   1016:         if( length)
                   1017:             len = *length;
                   1018:         where = IORegistryEntry::fromPath( alias, plane,
                   1019:                                     opath, &len, fromEntry );
                   1020:         if( where)
                   1021:             path = end;
                   1022:         else
                   1023:             len = 0;
                   1024:     }
                   1025: 
                   1026:     RLOCK;
                   1027: 
                   1028:     do {
                   1029:         if( 0 == where) {
                   1030:             if( (0 == fromEntry) && (*path++ == '/'))
                   1031:                 fromEntry = gRegistryRoot->getChildEntry( plane );
                   1032:             where = fromEntry;
                   1033:             if( 0 == where)
                   1034:                 break;
                   1035:         } else {
                   1036:             c = *path++;
                   1037:             if( c != '/') {
                   1038:                 if( c && (c != ':'))   // check valid terminator
                   1039:                     where = 0;
                   1040:                 break;
                   1041:             }
                   1042:         }
                   1043:         next = where->getChildFromComponent( &path, plane );
                   1044:         if( next)
                   1045:             where = next;
                   1046:     } while( next );
                   1047: 
                   1048:     if( where) {
                   1049:        // check residual path
                   1050:        if( where != fromEntry)
                   1051:             path--;
                   1052: 
                   1053:        if( opath && length) {
                   1054:             // copy out residual path
                   1055:            len2 = len + strlen( path );
                   1056:            if( len2 < *length)
                   1057:                 strcpy( opath + len, path );
                   1058:            *length = len2;
                   1059: 
                   1060:        } else if( path[0])
                   1061:            // no residual path => must be no tail for success
                   1062:             where = 0;
                   1063:     }
                   1064: 
                   1065:     if( where)
                   1066:        where->retain();
                   1067: 
                   1068:     UNLOCK;
                   1069: 
                   1070:     return( where );
                   1071: }
                   1072: 
                   1073: IORegistryEntry * IORegistryEntry::childFromPath(
                   1074:                        const char *            path,
                   1075:                         const IORegistryPlane * plane = 0,
                   1076:                         char *                 opath = 0,
                   1077:                         int *                  len = 0 )
                   1078: {
                   1079:     return( IORegistryEntry::fromPath( path, plane, opath, len, this ));
                   1080: }
                   1081: 
                   1082: /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
                   1083: 
                   1084: #define IOLinkIterator OSCollectionIterator
                   1085: 
                   1086: #undef super
                   1087: #define super OSObject
                   1088: 
                   1089: inline bool IORegistryEntry::arrayMember( OSArray * set,
                   1090:                                          const IORegistryEntry * member,
                   1091:                                        unsigned int * index = 0 ) const
                   1092: {
                   1093:     int                i;
                   1094:     OSObject * probeObject;
                   1095: 
                   1096:     for( i = 0; (probeObject = set->getObject(i)); i++) {
                   1097:         if (probeObject == (OSObject *) member) {
                   1098:            if( index)
                   1099:                 *index = i;
                   1100:             return( true );
                   1101:        }
                   1102:     }
                   1103:     return( false );
                   1104: }
                   1105: 
                   1106: bool IORegistryEntry::makeLink( IORegistryEntry * to,
                   1107:                                 unsigned int relation,
                   1108:                                 const IORegistryPlane * plane ) const
                   1109: {
                   1110:     OSArray *  links;
                   1111:     bool       result = false;
                   1112: 
                   1113:     if( (links = (OSArray *)
                   1114:                registryTable()->getObject( plane->keys[ relation ] ))) {
                   1115: 
                   1116:        result = arrayMember( links, to );
                   1117:        if( !result)
                   1118:             result = links->setObject( to );
                   1119: 
                   1120:     } else {
                   1121: 
                   1122:        links = OSArray::withObjects( (OSObject **) &to, 1, 1 );
                   1123:        result = (links != 0);
                   1124:        if( result) {
                   1125:            result = registryTable()->setObject( plane->keys[ relation ],
                   1126:                                           links );
                   1127:             links->release();
                   1128:        }
                   1129:     }
                   1130: 
                   1131:     return( result);
                   1132: }
                   1133: 
                   1134: void IORegistryEntry::breakLink( IORegistryEntry * to,
                   1135:                                  unsigned int relation,
                   1136:                                  const IORegistryPlane * plane ) const
                   1137: {
                   1138:     OSArray *          links;
                   1139:     unsigned int       index;
                   1140: 
                   1141:     if( (links = (OSArray *)
                   1142:                registryTable()->getObject( plane->keys[ relation ]))) {
                   1143: 
                   1144:        if( arrayMember( links, to, &index )) {
                   1145:             links->removeObject( index );
                   1146:            if( 0 == links->getCount())
                   1147:                 registryTable()->removeObject( plane->keys[ relation ]);
                   1148:            }
                   1149:     }
                   1150: }
                   1151: 
                   1152: 
                   1153: OSArray * IORegistryEntry::getParentSetReference(
                   1154:                                const IORegistryPlane * plane ) const
                   1155: {
                   1156:     if( plane)
                   1157:         return( (OSArray *) registryTable()->getObject(
                   1158:                             plane->keys[ kParentSetIndex ]));
                   1159:     else
                   1160:        return( 0 );
                   1161: }
                   1162: 
                   1163: OSIterator * IORegistryEntry::getParentIterator(
                   1164:                                const IORegistryPlane * plane ) const
                   1165: {
                   1166:     OSArray *          links;
                   1167:     OSIterator *       iter;
                   1168: 
                   1169:     if( !plane)
                   1170:        return( 0 );
                   1171: 
                   1172:     RLOCK;
                   1173:     links = getParentSetReference( plane );
                   1174:     if( 0 == links)
                   1175:        links = OSArray::withCapacity( 1 );
                   1176:     else
                   1177:        links = OSArray::withArray( links, links->getCount() );
                   1178:     UNLOCK;
                   1179: 
                   1180:     iter = IOLinkIterator::withCollection( links );
                   1181: 
                   1182:     if( links)
                   1183:         links->release();
                   1184: 
                   1185:     return( iter );
                   1186: }
                   1187: 
                   1188: IORegistryEntry * IORegistryEntry::getParentEntry( const IORegistryPlane * plane ) const
                   1189: {
                   1190:     IORegistryEntry *  entry = 0;
                   1191:     OSArray *          links;
                   1192: 
                   1193:     RLOCK;
                   1194: 
                   1195:     if( (links = getParentSetReference( plane )))
                   1196:         entry = (IORegistryEntry *) links->getObject( 0 );
                   1197: 
                   1198:     UNLOCK;
                   1199: 
                   1200:     return( entry);
                   1201: }
                   1202: 
                   1203: OSArray * IORegistryEntry::getChildSetReference( const IORegistryPlane * plane ) const
                   1204: {
                   1205:     if( plane)
                   1206:         return( (OSArray *) registryTable()->getObject(
                   1207:                             plane->keys[ kChildSetIndex ]));
                   1208:     else
                   1209:        return( 0 );
                   1210: }
                   1211: 
                   1212: OSIterator * IORegistryEntry::getChildIterator( const IORegistryPlane * plane ) const
                   1213: {
                   1214:     OSArray *          links;
                   1215:     OSIterator *       iter;
                   1216: 
                   1217:     if( !plane)
                   1218:        return( 0 );
                   1219: 
                   1220:     RLOCK;
                   1221:     links = getChildSetReference( plane );
                   1222:     if( 0 == links)
                   1223:         links = OSArray::withCapacity( 1 );
                   1224:     else
                   1225:         links = OSArray::withArray( links, links->getCount() );
                   1226:     UNLOCK;
                   1227: 
                   1228:     iter = IOLinkIterator::withCollection( links );
                   1229: 
                   1230:     if( links)
                   1231:         links->release();
                   1232: 
                   1233:     return( iter );
                   1234: }
                   1235: 
                   1236: 
                   1237: IORegistryEntry * IORegistryEntry::getChildEntry(
                   1238:                                const IORegistryPlane * plane ) const
                   1239: {
                   1240:     IORegistryEntry *  entry = 0;
                   1241:     OSArray *          links;
                   1242: 
                   1243:     RLOCK;
                   1244: 
                   1245:     if( (links = getChildSetReference( plane )))
                   1246:        entry = (IORegistryEntry *) links->getObject( 0 );
                   1247: 
                   1248:     UNLOCK;
                   1249: 
                   1250:     return( entry);
                   1251: }
                   1252: 
                   1253: void IORegistryEntry::applyToChildren( IORegistryEntryApplierFunction applier,
                   1254:                                        void * context,
                   1255:                                        const IORegistryPlane * plane ) const
                   1256: {
                   1257:     OSArray *          array;
                   1258:     unsigned int       index;
                   1259:     IORegistryEntry *  next;
                   1260: 
                   1261:     if( !plane)
                   1262:         return;
                   1263: 
                   1264:     RLOCK;
                   1265:     array = OSArray::withArray( getChildSetReference( plane ));
                   1266:     UNLOCK;
                   1267:     if( array) {
                   1268:         for( index = 0;
                   1269:              (next = (IORegistryEntry *) array->getObject( index ));
                   1270:              index++)
                   1271:             (*applier)(next, context);
                   1272:         array->release();
                   1273:     }
                   1274: }
                   1275: 
                   1276: void IORegistryEntry::applyToParents( IORegistryEntryApplierFunction applier,
                   1277:                                       void * context,
                   1278:                                       const IORegistryPlane * plane ) const
                   1279: {
                   1280:     OSArray *          array;
                   1281:     unsigned int       index;
                   1282:     IORegistryEntry *  next;
                   1283: 
                   1284:     if( !plane)
                   1285:         return;
                   1286: 
                   1287:     RLOCK;
                   1288:     array = OSArray::withArray( getParentSetReference( plane ));
                   1289:     UNLOCK;
                   1290:     if( array) {
                   1291:         for( index = 0;
                   1292:              (next = (IORegistryEntry *) array->getObject( index ));
                   1293:              index++)
                   1294:             (*applier)(next, context);
                   1295:         array->release();
                   1296:     }
                   1297: }
                   1298: 
                   1299: bool IORegistryEntry::isChild( IORegistryEntry * child,
                   1300:                                 const IORegistryPlane * plane,
                   1301:                                bool onlyChild = false ) const
                   1302: {
                   1303:     OSArray *  links;
                   1304:     bool       ret = false;
                   1305: 
                   1306:     RLOCK;
                   1307: 
                   1308:     if( (links = getChildSetReference( plane ))) {
                   1309:        if( (!onlyChild) || (1 == links->getCount()))
                   1310:             ret = arrayMember( links, child );
                   1311:     }
                   1312:     if( ret && (links = child->getParentSetReference( plane )))
                   1313:        ret = arrayMember( links, this );
                   1314: 
                   1315:     UNLOCK;
                   1316: 
                   1317:     return( ret);
                   1318: }
                   1319: 
                   1320: bool IORegistryEntry::isParent( IORegistryEntry * parent,
                   1321:                                 const IORegistryPlane * plane,
                   1322:                                bool onlyParent = false ) const
                   1323: 
                   1324: {
                   1325:     OSArray *  links;
                   1326:     bool       ret = false;
                   1327: 
                   1328:     RLOCK;
                   1329: 
                   1330:     if( (links = getParentSetReference( plane ))) {
                   1331:        if( (!onlyParent) || (1 == links->getCount()))
                   1332:             ret = arrayMember( links, parent );
                   1333:     }
                   1334:     if( ret && (links = parent->getChildSetReference( plane )))
                   1335:        ret = arrayMember( links, this );
                   1336: 
                   1337:     UNLOCK;
                   1338: 
                   1339:     return( ret);
                   1340: }
                   1341: 
                   1342: bool IORegistryEntry::inPlane( const IORegistryPlane * plane ) const
                   1343: {
                   1344:     bool ret;
                   1345: 
                   1346:     RLOCK;
                   1347: 
                   1348:     ret = (0 != getParentSetReference( plane ));
                   1349: 
                   1350:     UNLOCK;
                   1351: 
                   1352:     return( ret );
                   1353: }
                   1354: 
                   1355: bool IORegistryEntry::attachToParent( IORegistryEntry * parent,
                   1356:                                 const IORegistryPlane * plane )
                   1357: {
                   1358:     OSArray *  links;
                   1359:     bool       ret;
                   1360:     bool       needParent;
                   1361: 
                   1362:     if( this == parent)
                   1363:        return( false );
                   1364: 
                   1365:     WLOCK;
                   1366: 
                   1367:     ret = makeLink( parent, kParentSetIndex, plane );
                   1368: 
                   1369:     if( (links = parent->getChildSetReference( plane )))
                   1370:        needParent = (false == arrayMember( links, this ));
                   1371:     else
                   1372:        needParent = true;
                   1373: 
                   1374: //    ret &= parent->makeLink( this, kChildSetIndex, plane );
                   1375: 
                   1376:     UNLOCK;
                   1377: 
                   1378:     if( needParent)
                   1379:         ret &= parent->attachToChild( this, plane );
                   1380: 
                   1381:     return( ret );
                   1382: }
                   1383: 
                   1384: bool IORegistryEntry::attachToChild( IORegistryEntry * child,
                   1385:                                         const IORegistryPlane * plane )
                   1386: {
                   1387:     OSArray *  links;
                   1388:     bool       ret;
                   1389:     bool       needChild;
                   1390: 
                   1391:     if( this == child)
                   1392:        return( false );
                   1393: 
                   1394:     WLOCK;
                   1395: 
                   1396:     ret = makeLink( child, kChildSetIndex, plane );
                   1397: 
                   1398:     if( (links = child->getParentSetReference( plane )))
                   1399:        needChild = (false == arrayMember( links, this ));
                   1400:     else
                   1401:        needChild = true;
                   1402: 
                   1403:     UNLOCK;
                   1404: 
                   1405:     if( needChild)
                   1406:        ret &= child->attachToParent( this, plane );
                   1407: 
                   1408:     return( ret );
                   1409: }
                   1410: 
                   1411: void IORegistryEntry::detachFromParent( IORegistryEntry * parent,
                   1412:                                 const IORegistryPlane * plane )
                   1413: {
                   1414:     OSArray *  links;
                   1415:     bool       needParent;
                   1416: 
                   1417:     WLOCK;
                   1418: 
                   1419:     parent->retain();
                   1420: 
                   1421:     breakLink( parent, kParentSetIndex, plane );
                   1422: 
                   1423:     if( (links = parent->getChildSetReference( plane )))
                   1424:        needParent = arrayMember( links, this );
                   1425:     else
                   1426:        needParent = false;
                   1427: 
                   1428: //    parent->breakLink( this, kChildSetIndex, plane );
                   1429: 
                   1430:     UNLOCK;
                   1431: 
                   1432:     if( needParent)
                   1433:        parent->detachFromChild( this, plane );
                   1434: 
                   1435:     parent->release();
                   1436: }
                   1437: 
                   1438: void IORegistryEntry::detachFromChild( IORegistryEntry * child,
                   1439:                                 const IORegistryPlane * plane )
                   1440: {
                   1441:     OSArray *          links;
                   1442:     bool       needChild;
                   1443: 
                   1444:     WLOCK;
                   1445: 
                   1446:     child->retain();
                   1447: 
                   1448:     breakLink( child, kChildSetIndex, plane );
                   1449: 
                   1450:     if( (links = child->getParentSetReference( plane )))
                   1451:        needChild = arrayMember( links, this );
                   1452:     else
                   1453:        needChild = false;
                   1454: 
                   1455:     UNLOCK;
                   1456: 
                   1457:     if( needChild)
                   1458:        child->detachFromParent( this, plane );
                   1459: 
                   1460:     child->release();
                   1461: }
                   1462: 
                   1463: void IORegistryEntry::detachAbove( const IORegistryPlane * plane )
                   1464: {
                   1465:     IORegistryEntry *  parent;
                   1466: 
                   1467:     retain();
                   1468:     while( (parent = getParentEntry( plane )))
                   1469:        detachFromParent( parent, plane );
                   1470:     release();
                   1471: }
                   1472: 
                   1473: void IORegistryEntry::detachAll( const IORegistryPlane * plane )
                   1474: {
                   1475:     OSOrderedSet *             all;
                   1476:     IORegistryEntry *          next;
                   1477:     IORegistryIterator *       regIter;
                   1478: 
                   1479:     regIter = IORegistryIterator::iterateOver( this, plane, true );
                   1480:     if( 0 == regIter)
                   1481:        return;
                   1482:     all = regIter->iterateAll();
                   1483:     regIter->release();
                   1484: 
                   1485:     detachAbove( plane );
                   1486:     if( all) {
                   1487:        while( (next = (IORegistryEntry *) all->getLastObject())) {
                   1488: 
                   1489:             next->retain();
                   1490:             all->removeObject(next);
                   1491: 
                   1492:             next->detachAbove( plane );
                   1493:             next->release();
                   1494:         }
                   1495:         all->release();
                   1496:     }
                   1497: }
                   1498: 
                   1499: unsigned int IORegistryEntry::getDepth( const IORegistryPlane * plane ) const
                   1500: {
                   1501:     unsigned int               depth = 1;
                   1502:     OSArray *                  parents;
                   1503:     unsigned int               oneDepth, maxParentDepth, count;
                   1504:     IORegistryEntry *          one;
                   1505:     const IORegistryEntry *    next;
                   1506:     unsigned int               index;
                   1507: 
                   1508:     RLOCK;
                   1509: 
                   1510:     next = this;
                   1511:     while( (parents = next->getParentSetReference( plane ))) {
                   1512: 
                   1513:        count = parents->getCount();
                   1514:        if( 0 == count)
                   1515:            break;
                   1516:        if( 1 == count) {
                   1517:             depth++;
                   1518:             next = (IORegistryEntry *) parents->getObject( 0 );
                   1519:        } else {
                   1520:            // painful
                   1521:            maxParentDepth = 0;
                   1522:            for( index = 0;
                   1523:                 (one = (IORegistryEntry *) parents->getObject( index ));
                   1524:                 index++ ) {
                   1525:                 oneDepth = one->getDepth( plane );
                   1526:                 if( oneDepth > maxParentDepth)
                   1527:                     maxParentDepth = oneDepth;
                   1528:             }
                   1529:             depth += maxParentDepth;
                   1530:            break;
                   1531:        }
                   1532:     }
                   1533: 
                   1534:     UNLOCK;
                   1535: 
                   1536:     return( depth);
                   1537: }
                   1538: 
                   1539: /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
                   1540: 
                   1541: #undef super
                   1542: #define super OSIterator
                   1543: 
                   1544: OSDefineMetaClassAndStructors(IORegistryIterator, OSIterator)
                   1545: 
                   1546: /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
                   1547: 
                   1548: IORegistryIterator *
                   1549: IORegistryIterator::iterateOver( IORegistryEntry * root,
                   1550:                                  const IORegistryPlane * plane,
                   1551:                                  IOOptionBits options = 0 )
                   1552: {
                   1553:     IORegistryIterator *       create;
                   1554: 
                   1555:     if( 0 == root)
                   1556:        return( 0);
                   1557:     if( 0 == plane)
                   1558:        return( 0);
                   1559: 
                   1560:     create = new IORegistryIterator;
                   1561:     if( create) {
                   1562:         if( create->init()) {
                   1563: 
                   1564:             root->retain();
                   1565:             create->root = root;
                   1566:             create->where = &create->start;
                   1567:             create->start.current = root;
                   1568:             create->plane = plane;
                   1569:             create->options = options;
                   1570: 
                   1571:        } else {
                   1572:            create->release();
                   1573:            create = 0;
                   1574:        }
                   1575:     }
                   1576:     return( create);
                   1577: }
                   1578: 
                   1579: IORegistryIterator *
                   1580: IORegistryIterator::iterateOver( const IORegistryPlane * plane,
                   1581:                                 IOOptionBits options = 0 )
                   1582: {
                   1583:     return( iterateOver( gRegistryRoot, plane, options ));
                   1584: }
                   1585: 
                   1586: bool IORegistryIterator::isValid( void )
                   1587: {
                   1588:     bool               ok;
                   1589:     IORegCursor *      next;
                   1590: 
                   1591:     ok = true;
                   1592:     next = where;
                   1593: 
                   1594:     RLOCK;
                   1595:     while( ok && next) {
                   1596:        if( where->iter)
                   1597:             ok = where->iter->isValid();
                   1598:        next = next->next;
                   1599:     }
                   1600:     UNLOCK;
                   1601: 
                   1602:     return( ok);
                   1603: }
                   1604: 
                   1605: void IORegistryIterator::enterEntry( const IORegistryPlane * enterPlane )
                   1606: {
                   1607:     IORegCursor *      prev;
                   1608: 
                   1609:     prev = where;
                   1610:     where = (IORegCursor *) IOMalloc( sizeof( IORegCursor));
                   1611:     assert( where);
                   1612: 
                   1613:     if( where) {
                   1614:         where->iter = 0;
                   1615:         where->next = prev;
                   1616:         where->current = prev->current;
                   1617:         plane = enterPlane;
                   1618:     }
                   1619: }
                   1620: 
                   1621: void IORegistryIterator::enterEntry( void )
                   1622: {
                   1623:     enterEntry( plane );
                   1624: }
                   1625: 
                   1626: bool IORegistryIterator::exitEntry( void )
                   1627: {
                   1628:     IORegCursor *      gone;
                   1629: 
                   1630:     if( where->iter) {
                   1631:        where->iter->release();
                   1632:        where->iter = 0;
                   1633:         if( where->current)// && (where != &start))
                   1634:             where->current->release();
                   1635:     }
                   1636: 
                   1637:     if( where != &start) {
                   1638:        gone = where;
                   1639:         where = gone->next;
                   1640:         IOFree( gone, sizeof( IORegCursor));
                   1641:        return( true);
                   1642: 
                   1643:     } else
                   1644:         return( false);
                   1645: }
                   1646: 
                   1647: void IORegistryIterator::reset( void )
                   1648: {
                   1649:     while( exitEntry())
                   1650:        {}
                   1651: 
                   1652:     if( done) {
                   1653:        done->release();
                   1654:        done = 0;
                   1655:     }
                   1656: 
                   1657:     where->current = root;
                   1658: }
                   1659: 
                   1660: void IORegistryIterator::free( void )
                   1661: {
                   1662:     reset();
                   1663: 
                   1664:     if( root)
                   1665:         root->release();
                   1666: 
                   1667:     super::free();
                   1668: }
                   1669: 
                   1670: 
                   1671: IORegistryEntry * IORegistryIterator::getNextObjectFlat( void )
                   1672: {
                   1673:     IORegistryEntry *  next = 0;
                   1674:     OSArray *          links = 0;
                   1675: 
                   1676:     RLOCK;
                   1677: 
                   1678:     if( (0 == where->iter)) {
                   1679:        // just entered - create new iter
                   1680:        if( isValid()
                   1681:         &&  where->current
                   1682:         &&  (links = ( (options & kIORegistryIterateParents) ?
                   1683:                         where->current->getParentSetReference( plane ) :
                   1684:                         where->current->getChildSetReference( plane ) )) )
                   1685: 
                   1686:             where->iter = OSCollectionIterator::withCollection( links );
                   1687: 
                   1688:     } else
                   1689:        // next sibling - release current
                   1690:         if( where->current)
                   1691:             where->current->release();
                   1692: 
                   1693:     if( where->iter)
                   1694:         next = (IORegistryEntry *) where->iter->getNextObject();
                   1695: 
                   1696:     if( next)
                   1697:        next->retain();
                   1698: 
                   1699:     where->current = next;
                   1700: 
                   1701:     UNLOCK;
                   1702: 
                   1703:     return( next);
                   1704: }
                   1705: 
                   1706: IORegistryEntry * IORegistryIterator::getNextObjectRecursive( void )
                   1707: {
                   1708:     IORegistryEntry *  next;
                   1709: 
                   1710:     do
                   1711:         next = getNextObjectFlat();
                   1712:     while( (0 == next) && exitEntry());
                   1713: 
                   1714:     if( next) {
                   1715:        if( 0 == done)
                   1716:             done = OSOrderedSet::withCapacity( 10 );
                   1717:        if( done->setObject((OSObject *) next)) {
                   1718:                    // done set didn't contain this one, so recurse
                   1719:             enterEntry();
                   1720:        }
                   1721:     }
                   1722:     return( next);
                   1723: }
                   1724: 
                   1725: IORegistryEntry * IORegistryIterator::getNextObject( void )
                   1726: {
                   1727:     if( options & kIORegistryIterateRecursively)
                   1728:        return( getNextObjectRecursive());
                   1729:     else
                   1730:        return( getNextObjectFlat());
                   1731: }
                   1732: 
                   1733: IORegistryEntry * IORegistryIterator::getCurrentEntry( void )
                   1734: {
                   1735:     if( isValid())
                   1736:        return( where->current);
                   1737:     else
                   1738:        return( 0);
                   1739: }
                   1740: 
                   1741: OSOrderedSet * IORegistryIterator::iterateAll( void )
                   1742: {
                   1743:     reset();
                   1744:     while( getNextObjectRecursive())
                   1745:         {}
                   1746:     if( done)
                   1747:         done->retain();
                   1748:     return( done);
                   1749: }
                   1750: 
                   1751: 

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.