2 * Copyright (c) 1998-2006 Apple Computer, Inc. All rights reserved.
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
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.
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
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.
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
29 #include <IOKit/IORegistryEntry.h>
30 #include <libkern/c++/OSContainers.h>
31 #include <IOKit/IOService.h>
32 #include <IOKit/IOKitKeys.h>
34 #include <IOKit/IOLib.h>
36 #include <IOKit/assert.h>
38 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
40 #define super OSObject
42 OSDefineMetaClassAndStructors(IORegistryEntry
, OSObject
)
44 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
46 #define kIORegPlaneParentSuffix "ParentLinks"
47 #define kIORegPlaneChildSuffix "ChildLinks"
48 #define kIORegPlaneNameSuffix "Name"
49 #define kIORegPlaneLocationSuffix "Location"
51 #define kIORegPlaneParentSuffixLen (sizeof(kIORegPlaneParentSuffix) - 1)
52 #define kIORegPlaneChildSuffixLen (sizeof(kIORegPlaneChildSuffix) - 1)
53 #define kIORegPlaneNameSuffixLen (sizeof(kIORegPlaneNameSuffix) - 1)
54 #define kIORegPlaneLocationSuffixLen (sizeof(kIORegPlaneLocationSuffix) - 1)
56 #define KASLR_IOREG_DEBUG 0
58 struct IORegistryEntry::ExpansionData
60 IORecursiveLock
* fLock
;
61 uint64_t fRegistryEntryID
;
62 SInt32 fRegistryEntryGenerationCount
;
66 static IORegistryEntry
* gRegistryRoot
;
67 static OSDictionary
* gIORegistryPlanes
;
69 const OSSymbol
* gIONameKey
;
70 const OSSymbol
* gIOLocationKey
;
71 const OSSymbol
* gIORegistryEntryIDKey
;
72 const OSSymbol
* gIORegistryEntryPropertyKeysKey
;
83 enum { kIORegistryIDReserved
= (1ULL << 32) + 255 };
85 static uint64_t gIORegistryLastID
= kIORegistryIDReserved
;
87 class IORegistryPlane
: public OSObject
{
89 friend class IORegistryEntry
;
91 OSDeclareAbstractStructors(IORegistryPlane
)
93 const OSSymbol
* nameKey
;
94 const OSSymbol
* keys
[ kNumSetIndex
];
95 const OSSymbol
* pathNameKey
;
96 const OSSymbol
* pathLocationKey
;
100 virtual bool serialize(OSSerialize
*s
) const APPLE_KEXT_OVERRIDE
;
103 OSDefineMetaClassAndStructors(IORegistryPlane
, OSObject
)
106 static IORecursiveLock
* gPropertiesLock
;
107 static SInt32 gIORegistryGenerationCount
;
109 #define UNLOCK lck_rw_done( &gIORegistryLock )
110 #define RLOCK lck_rw_lock_shared( &gIORegistryLock )
111 #define WLOCK lck_rw_lock_exclusive( &gIORegistryLock ); \
112 gIORegistryGenerationCount++
115 #define PUNLOCK IORecursiveLockUnlock( reserved->fLock )
116 #define PLOCK IORecursiveLockLock( reserved->fLock )
118 #define IOREGSPLITTABLES
120 #ifdef IOREGSPLITTABLES
121 #define registryTable() fRegistryTable
123 #define registryTable() fPropertyTable
128 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
130 lck_rw_t gIORegistryLock
;
131 lck_grp_t
*gIORegistryLockGrp
;
132 lck_grp_attr_t
*gIORegistryLockGrpAttr
;
133 lck_attr_t
*gIORegistryLockAttr
;
136 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
138 IORegistryEntry
* IORegistryEntry::initialize( void )
142 if( !gRegistryRoot
) {
145 gIORegistryLockGrpAttr
= lck_grp_attr_alloc_init();
146 //lck_grp_attr_setstat(gIORegistryLockGrpAttr);
147 gIORegistryLockGrp
= lck_grp_alloc_init("IORegistryLock", gIORegistryLockGrpAttr
);
148 gIORegistryLockAttr
= lck_attr_alloc_init();
149 lck_attr_rw_shared_priority(gIORegistryLockAttr
);
150 //lck_attr_setdebug(gIORegistryLockAttr);
151 lck_rw_init( &gIORegistryLock
, gIORegistryLockGrp
, gIORegistryLockAttr
);
153 gRegistryRoot
= new IORegistryEntry
;
154 gPropertiesLock
= IORecursiveLockAlloc();
155 gIORegistryPlanes
= OSDictionary::withCapacity( 1 );
157 assert( gRegistryRoot
&& gPropertiesLock
158 && gIORegistryPlanes
);
159 ok
= gRegistryRoot
->init();
162 gRegistryRoot
->reserved
->fRegistryEntryID
= ++gIORegistryLastID
;
164 gIONameKey
= OSSymbol::withCStringNoCopy( "IOName" );
165 gIOLocationKey
= OSSymbol::withCStringNoCopy( "IOLocation" );
166 gIORegistryEntryIDKey
= OSSymbol::withCStringNoCopy( kIORegistryEntryIDKey
);
167 gIORegistryEntryPropertyKeysKey
= OSSymbol::withCStringNoCopy( kIORegistryEntryPropertyKeysKey
);
169 assert( ok
&& gIONameKey
&& gIOLocationKey
);
171 gRegistryRoot
->setName( "Root" );
172 gRegistryRoot
->setProperty( kIORegistryPlanesKey
, gIORegistryPlanes
);
175 return( gRegistryRoot
);
178 IORegistryEntry
* IORegistryEntry::getRegistryRoot( void )
180 return( gRegistryRoot
);
183 SInt32
IORegistryEntry::getGenerationCount( void )
185 return( gIORegistryGenerationCount
);
188 SInt32
IORegistryEntry::getRegistryEntryGenerationCount(void) const
190 return (reserved
->fRegistryEntryGenerationCount
);
193 const IORegistryPlane
* IORegistryEntry::makePlane( const char * name
)
195 IORegistryPlane
* plane
;
196 const OSSymbol
* nameKey
;
197 const OSSymbol
* parentKey
;
198 const OSSymbol
* childKey
;
199 const OSSymbol
* pathNameKey
;
200 const OSSymbol
* pathLocationKey
;
201 char key
[ kIOMaxPlaneName
+ 16 ];
204 strlcpy( key
, name
, kIOMaxPlaneName
+ 1 );
205 end
= key
+ strlen( key
);
207 nameKey
= OSSymbol::withCString( key
);
209 strlcpy( end
, kIORegPlaneParentSuffix
, kIORegPlaneParentSuffixLen
+ 1 );
210 parentKey
= OSSymbol::withCString( key
);
212 strlcpy( end
, kIORegPlaneChildSuffix
, kIORegPlaneChildSuffixLen
+ 1 );
213 childKey
= OSSymbol::withCString( key
);
215 strlcpy( end
, kIORegPlaneNameSuffix
, kIORegPlaneNameSuffixLen
+ 1 );
216 pathNameKey
= OSSymbol::withCString( key
);
218 strlcpy( end
, kIORegPlaneLocationSuffix
, kIORegPlaneLocationSuffixLen
+ 1 );
219 pathLocationKey
= OSSymbol::withCString( key
);
221 plane
= new IORegistryPlane
;
223 if( plane
&& plane
->init()
224 && nameKey
&& parentKey
&& childKey
225 && pathNameKey
&& pathLocationKey
) {
227 plane
->nameKey
= nameKey
;
228 plane
->keys
[ kParentSetIndex
] = parentKey
;
229 plane
->keys
[ kChildSetIndex
] = childKey
;
230 plane
->pathNameKey
= pathNameKey
;
231 plane
->pathLocationKey
= pathLocationKey
;
234 gIORegistryPlanes
->setObject( nameKey
, plane
);
242 pathLocationKey
->release();
244 pathNameKey
->release();
246 parentKey
->release();
257 const IORegistryPlane
* IORegistryEntry::getPlane( const char * name
)
259 const IORegistryPlane
* plane
;
262 plane
= (const IORegistryPlane
*) gIORegistryPlanes
->getObject( name
);
268 bool IORegistryPlane::serialize(OSSerialize
*s
) const
270 return( nameKey
->serialize(s
) );
273 enum { kIORegCapacityIncrement
= 4 };
275 bool IORegistryEntry::init( OSDictionary
* dict
)
284 reserved
= IONew(ExpansionData
, 1);
287 bzero(reserved
, sizeof(ExpansionData
));
288 reserved
->fLock
= IORecursiveLockAlloc();
289 if (!reserved
->fLock
) return (false);
292 if (OSCollection::kImmutable
& dict
->setOptions(0, 0)) {
293 dict
= (OSDictionary
*) dict
->copyCollection();
299 fPropertyTable
->release();
300 fPropertyTable
= dict
;
302 } else if( !fPropertyTable
) {
303 fPropertyTable
= OSDictionary::withCapacity( kIORegCapacityIncrement
);
305 fPropertyTable
->setCapacityIncrement( kIORegCapacityIncrement
);
311 #ifdef IOREGSPLITTABLES
312 if( !fRegistryTable
) {
313 fRegistryTable
= OSDictionary::withCapacity( kIORegCapacityIncrement
);
315 fRegistryTable
->setCapacityIncrement( kIORegCapacityIncrement
);
318 if( (prop
= OSDynamicCast( OSString
, getProperty( gIONameKey
)))) {
319 OSSymbol
* sym
= (OSSymbol
*)OSSymbol::withString( prop
);
320 // ok for OSSymbol too
325 #endif /* IOREGSPLITTABLES */
330 bool IORegistryEntry::init( IORegistryEntry
* old
,
331 const IORegistryPlane
* plane
)
334 IORegistryEntry
* next
;
342 reserved
= IONew(ExpansionData
, 1);
343 if (!reserved
) return (false);
344 bzero(reserved
, sizeof(ExpansionData
));
345 reserved
->fLock
= IORecursiveLockAlloc();
346 if (!reserved
->fLock
) return (false);
351 reserved
->fRegistryEntryID
= old
->reserved
->fRegistryEntryID
;
353 fPropertyTable
= old
->dictionaryWithProperties();
354 #ifdef IOREGSPLITTABLES
355 fRegistryTable
= old
->fRegistryTable
;
356 old
->fRegistryTable
= (OSDictionary
*) fRegistryTable
->copyCollection();
357 #endif /* IOREGSPLITTABLES */
359 old
->registryTable()->removeObject( plane
->keys
[ kParentSetIndex
] );
360 old
->registryTable()->removeObject( plane
->keys
[ kChildSetIndex
] );
362 all
= getParentSetReference( plane
);
363 if( all
) for( index
= 0;
364 (next
= (IORegistryEntry
*) all
->getObject(index
));
366 next
->makeLink( this, kChildSetIndex
, plane
);
367 next
->breakLink( old
, kChildSetIndex
, plane
);
370 all
= getChildSetReference( plane
);
371 if( all
) for( index
= 0;
372 (next
= (IORegistryEntry
*) all
->getObject(index
));
374 next
->makeLink( this, kParentSetIndex
, plane
);
375 next
->breakLink( old
, kParentSetIndex
, plane
);
383 void IORegistryEntry::free( void )
386 if( registryTable() && gIOServicePlane
) {
387 if( getParentSetReference( gIOServicePlane
)
388 || getChildSetReference( gIOServicePlane
)) {
389 panic("%s: attached at free()", getName());
394 if( getPropertyTable())
395 getPropertyTable()->release();
397 #ifdef IOREGSPLITTABLES
399 registryTable()->release();
400 #endif /* IOREGSPLITTABLES */
404 if (reserved
->fLock
) IORecursiveLockFree(reserved
->fLock
);
405 IODelete(reserved
, ExpansionData
, 1);
411 void IORegistryEntry::setPropertyTable( OSDictionary
* dict
)
416 fPropertyTable
->release();
418 fPropertyTable
= dict
;
421 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
423 /* Wrappers to synchronize property table */
425 #define wrap2(type, constant) \
427 IORegistryEntry::copyProperty( type * aKey) constant \
432 obj = getProperty( aKey ); \
440 #define wrap4(type,constant) \
442 IORegistryEntry::getProperty( type * aKey, \
443 const IORegistryPlane * plane, \
444 IOOptionBits options ) constant \
446 OSObject * obj = getProperty( aKey ); \
448 if ( (0 == obj) && plane && (options & kIORegistryIterateRecursively) ) { \
449 IORegistryEntry * entry = (IORegistryEntry *) this; \
450 IORegistryIterator * iter; \
451 iter = IORegistryIterator::iterateOver( entry, plane, options ); \
454 while ( (0 == obj) && (entry = iter->getNextObject()) ) { \
455 obj = entry->getProperty( aKey ); \
464 #define wrap5(type,constant) \
466 IORegistryEntry::copyProperty( type * aKey, \
467 const IORegistryPlane * plane, \
468 IOOptionBits options ) constant \
470 OSObject * obj = copyProperty( aKey ); \
472 if ( (0 == obj) && plane && (options & kIORegistryIterateRecursively) ) { \
473 IORegistryEntry * entry = (IORegistryEntry *) this; \
474 IORegistryIterator * iter; \
475 iter = IORegistryIterator::iterateOver( entry, plane, options ); \
478 while ( (0 == obj) && (entry = iter->getNextObject()) ) { \
479 obj = entry->copyProperty( aKey ); \
488 bool IORegistryEntry::serializeProperties( OSSerialize
* s
) const
490 // setProperty( getRetainCount(), 32, "__retain" );
493 OSCollection
*snapshotProperties
= getPropertyTable()->copyCollection();
496 if (!snapshotProperties
) return (false);
498 bool ok
= snapshotProperties
->serialize( s
);
499 snapshotProperties
->release();
503 OSArray
* IORegistryEntry::copyPropertyKeys(void) const
506 OSArray
* keys
= getPropertyTable()->copyKeys();
512 OSDictionary
* IORegistryEntry::dictionaryWithProperties( void ) const
517 dict
= OSDictionary::withDictionary( getPropertyTable(),
518 getPropertyTable()->getCapacity() );
524 IOReturn
IORegistryEntry::setProperties( OSObject
* properties
)
526 return( kIOReturnUnsupported
);
529 wrap2(const OSSymbol
, const) // copyProperty() definition
530 wrap2(const OSString
, const) // copyProperty() definition
531 wrap2(const char, const) // copyProperty() definition
533 wrap4(const OSSymbol
, const) // getProperty() w/plane definition
534 wrap4(const OSString
, const) // getProperty() w/plane definition
535 wrap4(const char, const) // getProperty() w/plane definition
537 wrap5(const OSSymbol
, const) // copyProperty() w/plane definition
538 wrap5(const OSString
, const) // copyProperty() w/plane definition
539 wrap5(const char, const) // copyProperty() w/plane definition
543 IORegistryEntry::getProperty( const OSSymbol
* aKey
) const
548 obj
= getPropertyTable()->getObject( aKey
);
555 IORegistryEntry::removeProperty( const OSSymbol
* aKey
)
558 getPropertyTable()->removeObject( aKey
);
562 #if KASLR_IOREG_DEBUG
565 bool ScanForAddrInObject(OSObject
* theObject
,
572 IORegistryEntry::setProperty( const OSSymbol
* aKey
, OSObject
* anObject
)
576 // If we are inserting a collection class and the current entry
577 // is attached into the registry (inPlane()) then mark the collection
579 OSCollection
*coll
= OSDynamicCast(OSCollection
, anObject
);
580 bool makeImmutable
= (coll
&& inPlane());
584 coll
->setOptions( OSCollection::kMASK
, OSCollection::kImmutable
);
586 ret
= getPropertyTable()->setObject( aKey
, anObject
);
589 #if KASLR_IOREG_DEBUG
590 if ( anObject
&& strcmp(kIOKitDiagnosticsKey
, aKey
->getCStringNoCopy()) != 0 ) {
591 if (ScanForAddrInObject(anObject
, 0)) {
592 IOLog("%s: IORegistryEntry name %s with key \"%s\" \n",
595 aKey
->getCStringNoCopy() );
603 IOReturn
IORegistryEntry::
604 runPropertyAction(Action inAction
, OSObject
*target
,
605 void *arg0
, void *arg1
, void *arg2
, void *arg3
)
609 // closeGate is recursive so don't worry if we already hold the lock.
611 res
= (*inAction
)(target
, arg0
, arg1
, arg2
, arg3
);
618 IORegistryEntry::getProperty( const OSString
* aKey
) const
620 const OSSymbol
* tmpKey
= OSSymbol::withString( aKey
);
621 OSObject
* obj
= getProperty( tmpKey
);
628 IORegistryEntry::getProperty( const char * aKey
) const
630 const OSSymbol
* tmpKey
= OSSymbol::withCString( aKey
);
631 OSObject
* obj
= getProperty( tmpKey
);
639 IORegistryEntry::removeProperty( const OSString
* aKey
)
641 const OSSymbol
* tmpKey
= OSSymbol::withString( aKey
);
642 removeProperty( tmpKey
);
647 IORegistryEntry::removeProperty( const char * aKey
)
649 const OSSymbol
* tmpKey
= OSSymbol::withCString( aKey
);
650 removeProperty( tmpKey
);
655 IORegistryEntry::setProperty( const OSString
* aKey
, OSObject
* anObject
)
657 const OSSymbol
* tmpKey
= OSSymbol::withString( aKey
);
658 bool ret
= setProperty( tmpKey
, anObject
);
665 IORegistryEntry::setProperty( const char * aKey
, OSObject
* anObject
)
667 const OSSymbol
* tmpKey
= OSSymbol::withCString( aKey
);
668 bool ret
= setProperty( tmpKey
, anObject
);
675 IORegistryEntry::setProperty(const char * aKey
, const char * aString
)
678 OSSymbol
* aSymbol
= (OSSymbol
*) OSSymbol::withCString( aString
);
681 const OSSymbol
* tmpKey
= OSSymbol::withCString( aKey
);
682 ret
= setProperty( tmpKey
, aSymbol
);
691 IORegistryEntry::setProperty(const char * aKey
, bool aBoolean
)
694 OSBoolean
* aBooleanObj
= OSBoolean::withBoolean( aBoolean
);
697 const OSSymbol
* tmpKey
= OSSymbol::withCString( aKey
);
698 ret
= setProperty( tmpKey
, aBooleanObj
);
701 aBooleanObj
->release();
707 IORegistryEntry::setProperty( const char * aKey
,
708 unsigned long long aValue
,
709 unsigned int aNumberOfBits
)
712 OSNumber
* anOffset
= OSNumber::withNumber( aValue
, aNumberOfBits
);
715 const OSSymbol
* tmpKey
= OSSymbol::withCString( aKey
);
716 ret
= setProperty( tmpKey
, anOffset
);
725 IORegistryEntry::setProperty( const char * aKey
,
730 OSData
* data
= OSData::withBytes( bytes
, length
);
733 const OSSymbol
* tmpKey
= OSSymbol::withCString( aKey
);
734 ret
= setProperty( tmpKey
, data
);
742 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
744 /* Name, location, paths */
746 const char * IORegistryEntry::getName( const IORegistryPlane
* plane
) const
752 sym
= (OSSymbol
*) registryTable()->getObject( plane
->pathNameKey
);
754 sym
= (OSSymbol
*) registryTable()->getObject( gIONameKey
);
758 return( sym
->getCStringNoCopy());
760 return( (getMetaClass())->getClassName());
763 const OSSymbol
* IORegistryEntry::copyName(
764 const IORegistryPlane
* plane
) const
770 sym
= (OSSymbol
*) registryTable()->getObject( plane
->pathNameKey
);
772 sym
= (OSSymbol
*) registryTable()->getObject( gIONameKey
);
780 return( OSSymbol::withCString((getMetaClass())->getClassName()) );
783 const OSSymbol
* IORegistryEntry::copyLocation(
784 const IORegistryPlane
* plane
) const
790 sym
= (OSSymbol
*) registryTable()->getObject( plane
->pathLocationKey
);
792 sym
= (OSSymbol
*) registryTable()->getObject( gIOLocationKey
);
800 const char * IORegistryEntry::getLocation( const IORegistryPlane
* plane
) const
802 const OSSymbol
* sym
= copyLocation( plane
);
803 const char * result
= 0;
806 result
= sym
->getCStringNoCopy();
813 void IORegistryEntry::setName( const OSSymbol
* name
,
814 const IORegistryPlane
* plane
)
816 const OSSymbol
* key
;
820 key
= plane
->pathNameKey
;
825 registryTable()->setObject( key
, (OSObject
*) name
);
830 void IORegistryEntry::setName( const char * name
,
831 const IORegistryPlane
* plane
)
833 OSSymbol
* sym
= (OSSymbol
*)OSSymbol::withCString( name
);
835 setName( sym
, plane
);
840 void IORegistryEntry::setLocation( const OSSymbol
* location
,
841 const IORegistryPlane
* plane
)
843 const OSSymbol
* key
;
847 key
= plane
->pathLocationKey
;
849 key
= gIOLocationKey
;
852 registryTable()->setObject( key
, (OSObject
*) location
);
857 void IORegistryEntry::setLocation( const char * location
,
858 const IORegistryPlane
* plane
)
860 OSSymbol
* sym
= (OSSymbol
*)OSSymbol::withCString( location
);
862 setLocation( sym
, plane
);
868 IORegistryEntry::compareName( OSString
* name
, OSString
** matched
) const
870 const OSSymbol
* sym
= copyName();
873 isEqual
= sym
->isEqualTo( name
);
875 if( isEqual
&& matched
) {
887 IORegistryEntry::compareNames( OSObject
* names
, OSString
** matched
) const
890 OSCollection
* collection
;
891 OSIterator
* iter
= 0;
894 if( (collection
= OSDynamicCast( OSCollection
, names
))) {
895 iter
= OSCollectionIterator::withCollection( collection
);
898 string
= OSDynamicCast( OSString
, names
);
902 result
= compareName( string
, matched
);
904 } while( (false == result
)
905 && iter
&& (string
= OSDynamicCast( OSString
, iter
->getNextObject())));
914 bool IORegistryEntry::getPath( char * path
, int * length
,
915 const IORegistryPlane
* plane
) const
918 IORegistryEntry
* root
;
919 const IORegistryEntry
* entry
;
920 const IORegistryEntry
* parent
;
921 const OSSymbol
* alias
;
923 int len
, maxLength
, compLen
, aliasLen
;
927 if( !path
|| !length
|| !plane
)
931 maxLength
= *length
- 2;
934 len
= plane
->nameKey
->getLength();
935 if( len
>= maxLength
)
937 strlcpy( nextComp
, plane
->nameKey
->getCStringNoCopy(), len
+ 1);
938 nextComp
[ len
++ ] = ':';
941 if( (alias
= hasAlias( plane
))) {
942 aliasLen
= alias
->getLength();
944 ok
= (maxLength
> len
);
947 strlcpy( nextComp
, alias
->getCStringNoCopy(), aliasLen
+ 1);
951 stack
= OSArray::withCapacity( getDepth( plane
));
952 if (!stack
) return( false);
956 parent
= entry
= this;
957 root
= gRegistryRoot
->getChildEntry( plane
);
958 while (parent
&& (parent
!= root
))
962 parent
= entry
->getParentEntry( plane
);
963 stack
->setObject( (OSObject
*) entry
);
969 index
= stack
->getCount();
976 } else while( ok
&& ((--index
) >= 0)) {
978 entry
= (IORegistryEntry
*) stack
->getObject((unsigned int) index
);
981 if( (alias
= entry
->hasAlias( plane
))) {
982 len
= plane
->nameKey
->getLength() + 1;
983 nextComp
= path
+ len
;
985 compLen
= alias
->getLength();
986 ok
= (maxLength
> (len
+ compLen
));
988 strlcpy( nextComp
, alias
->getCStringNoCopy(), compLen
+ 1);
990 compLen
= maxLength
- len
;
991 ok
= entry
->getPathComponent( nextComp
+ 1, &compLen
, plane
);
1001 nextComp
+= compLen
;
1012 bool IORegistryEntry::getPathComponent( char * path
, int * length
,
1013 const IORegistryPlane
* plane
) const
1015 int len
, locLen
, maxLength
;
1016 const char * compName
;
1020 maxLength
= *length
;
1022 compName
= getName( plane
);
1023 len
= strlen( compName
);
1024 if( (loc
= getLocation( plane
)))
1025 locLen
= 1 + strlen( loc
);
1029 ok
= ((len
+ locLen
+ 1) < maxLength
);
1031 strlcpy( path
, compName
, len
+ 1 );
1036 strlcpy( path
, loc
, locLen
);
1044 const char * IORegistryEntry::matchPathLocation( const char * cmp
,
1045 const IORegistryPlane
* plane
)
1048 const char * result
= 0;
1049 u_quad_t num1
, num2
;
1050 char lastPathChar
, lastLocationChar
;
1052 str
= getLocation( plane
);
1054 lastPathChar
= cmp
[0];
1055 lastLocationChar
= str
[0];
1058 num1
= strtouq( cmp
, (char **) &cmp
, 16 );
1059 lastPathChar
= *cmp
++;
1063 if( lastLocationChar
) {
1064 num2
= strtouq( str
, (char **) &str
, 16 );
1065 lastLocationChar
= *str
++;
1072 if (!lastPathChar
&& !lastLocationChar
) {
1077 if( (',' != lastPathChar
) && (':' != lastPathChar
))
1080 if (lastPathChar
&& lastLocationChar
&& (lastPathChar
!= lastLocationChar
))
1089 IORegistryEntry
* IORegistryEntry::getChildFromComponent( const char ** opath
,
1090 const IORegistryPlane
* plane
)
1092 IORegistryEntry
* entry
= 0;
1096 const char * cmp
= 0;
1101 set
= getChildSetReference( plane
);
1107 (entry
= (IORegistryEntry
*) set
->getObject(index
));
1113 str
= entry
->getName( plane
);
1114 len
= strlen( str
);
1115 if( strncmp( str
, cmp
, len
))
1120 if( (c
== 0) || (c
== '/') || (c
== ':'))
1126 if( (cmp
= entry
->matchPathLocation( cmp
, plane
)))
1136 const OSSymbol
* IORegistryEntry::hasAlias( const IORegistryPlane
* plane
,
1137 char * opath
, int * length
) const
1139 IORegistryEntry
* entry
;
1140 IORegistryEntry
* entry2
;
1141 const OSSymbol
* key
;
1142 const OSSymbol
* bestKey
= 0;
1145 const char * path
= "/aliases";
1147 entry
= IORegistryEntry::fromPath( path
, plane
);
1150 if( (iter
= OSCollectionIterator::withCollection(
1151 entry
->getPropertyTable() ))) {
1153 while( (key
= (OSSymbol
*) iter
->getNextObject())) {
1155 data
= (OSData
*) entry
->getProperty( key
);
1156 path
= (const char *) data
->getBytesNoCopy();
1157 if( (entry2
= IORegistryEntry::fromPath( path
, plane
,
1159 if( this == entry2
) {
1161 || (bestKey
->getLength() > key
->getLength()))
1162 // pick the smallest alias
1176 const char * IORegistryEntry::dealiasPath(
1177 const char ** opath
,
1178 const IORegistryPlane
* plane
)
1180 IORegistryEntry
* entry
;
1182 const char * path
= *opath
;
1183 const char * rpath
= 0;
1186 char temp
[ kIOMaxPlaneName
+ 1 ];
1193 while( (c
= *end
++) && (c
!= '/') && (c
!= ':'))
1196 if( (end
- path
) < kIOMaxPlaneName
) {
1197 strlcpy( temp
, path
, end
- path
+ 1 );
1200 entry
= IORegistryEntry::fromPath( "/aliases", plane
);
1202 data
= (OSData
*) entry
->getProperty( temp
);
1204 rpath
= (const char *) data
->getBytesNoCopy();
1216 IORegistryEntry
* IORegistryEntry::fromPath(
1218 const IORegistryPlane
* plane
,
1221 IORegistryEntry
* fromEntry
)
1223 IORegistryEntry
* where
= 0;
1224 IORegistryEntry
* aliasEntry
= 0;
1225 IORegistryEntry
* next
;
1231 char temp
[ kIOMaxPlaneName
+ 1 ];
1238 end
= strchr( path
, ':' );
1239 if( end
&& ((end
- path
) < kIOMaxPlaneName
)) {
1240 strlcpy( temp
, path
, end
- path
+ 1 );
1241 plane
= getPlane( temp
);
1250 if( (alias
= dealiasPath( &end
, plane
))) {
1253 aliasEntry
= IORegistryEntry::fromPath( alias
, plane
,
1254 opath
, &len
, fromEntry
);
1266 if( (0 == fromEntry
) && (*path
++ == '/'))
1267 fromEntry
= gRegistryRoot
->getChildEntry( plane
);
1274 if( c
&& (c
!= ':')) // check valid terminator
1279 next
= where
->getChildFromComponent( &path
, plane
);
1285 // check residual path
1286 if( where
!= fromEntry
)
1289 if( opath
&& length
) {
1290 // copy out residual path
1291 len2
= strlen( path
);
1292 if( (len
+ len2
) < *length
)
1293 strlcpy( opath
+ len
, path
, len2
+ 1 );
1294 *length
= (len
+ len2
);
1297 // no residual path => must be no tail for success
1304 aliasEntry
->release();
1311 IORegistryEntry
* IORegistryEntry::childFromPath(
1313 const IORegistryPlane
* plane
,
1317 return( IORegistryEntry::fromPath( path
, plane
, opath
, len
, this ));
1320 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1322 #define IOLinkIterator OSCollectionIterator
1325 #define super OSObject
1327 inline bool IORegistryEntry::arrayMember( OSArray
* set
,
1328 const IORegistryEntry
* member
,
1329 unsigned int * index
) const
1332 OSObject
* probeObject
;
1334 for( i
= 0; (probeObject
= set
->getObject(i
)); i
++) {
1335 if (probeObject
== (OSObject
*) member
) {
1344 bool IORegistryEntry::makeLink( IORegistryEntry
* to
,
1345 unsigned int relation
,
1346 const IORegistryPlane
* plane
) const
1349 bool result
= false;
1351 if( (links
= (OSArray
*)
1352 registryTable()->getObject( plane
->keys
[ relation
] ))) {
1354 result
= arrayMember( links
, to
);
1356 result
= links
->setObject( to
);
1360 links
= OSArray::withObjects( (const OSObject
**) &to
, 1, 1 );
1361 result
= (links
!= 0);
1363 result
= registryTable()->setObject( plane
->keys
[ relation
],
1368 reserved
->fRegistryEntryGenerationCount
++;
1373 void IORegistryEntry::breakLink( IORegistryEntry
* to
,
1374 unsigned int relation
,
1375 const IORegistryPlane
* plane
) const
1380 if( (links
= (OSArray
*)
1381 registryTable()->getObject( plane
->keys
[ relation
]))) {
1383 if( arrayMember( links
, to
, &index
)) {
1384 links
->removeObject( index
);
1385 if( 0 == links
->getCount())
1386 registryTable()->removeObject( plane
->keys
[ relation
]);
1389 reserved
->fRegistryEntryGenerationCount
++;
1393 OSArray
* IORegistryEntry::getParentSetReference(
1394 const IORegistryPlane
* plane
) const
1397 return( (OSArray
*) registryTable()->getObject(
1398 plane
->keys
[ kParentSetIndex
]));
1403 OSIterator
* IORegistryEntry::getParentIterator(
1404 const IORegistryPlane
* plane
) const
1413 links
= getParentSetReference( plane
);
1415 links
= OSArray::withCapacity( 1 );
1417 links
= OSArray::withArray( links
, links
->getCount() );
1420 iter
= IOLinkIterator::withCollection( links
);
1428 IORegistryEntry
* IORegistryEntry::copyParentEntry( const IORegistryPlane
* plane
) const
1430 IORegistryEntry
* entry
= 0;
1435 if( (links
= getParentSetReference( plane
))) {
1436 entry
= (IORegistryEntry
*) links
->getObject( 0 );
1445 IORegistryEntry
* IORegistryEntry::getParentEntry( const IORegistryPlane
* plane
) const
1447 IORegistryEntry
* entry
;
1449 entry
= copyParentEntry( plane
);
1456 OSArray
* IORegistryEntry::getChildSetReference( const IORegistryPlane
* plane
) const
1459 return( (OSArray
*) registryTable()->getObject(
1460 plane
->keys
[ kChildSetIndex
]));
1465 OSIterator
* IORegistryEntry::getChildIterator( const IORegistryPlane
* plane
) const
1474 links
= getChildSetReference( plane
);
1476 links
= OSArray::withCapacity( 1 );
1478 links
= OSArray::withArray( links
, links
->getCount() );
1481 iter
= IOLinkIterator::withCollection( links
);
1489 uint32_t IORegistryEntry::getChildCount( const IORegistryPlane
* plane
) const
1495 links
= getChildSetReference( plane
);
1496 if (links
) count
= links
->getCount();
1502 IORegistryEntry
* IORegistryEntry::copyChildEntry(
1503 const IORegistryPlane
* plane
) const
1505 IORegistryEntry
* entry
= 0;
1510 if( (links
= getChildSetReference( plane
))) {
1511 entry
= (IORegistryEntry
*) links
->getObject( 0 );
1520 IORegistryEntry
* IORegistryEntry::getChildEntry(
1521 const IORegistryPlane
* plane
) const
1523 IORegistryEntry
* entry
;
1525 entry
= copyChildEntry( plane
);
1532 void IORegistryEntry::applyToChildren( IORegistryEntryApplierFunction applier
,
1534 const IORegistryPlane
* plane
) const
1538 IORegistryEntry
* next
;
1544 array
= OSArray::withArray( getChildSetReference( plane
));
1548 (next
= (IORegistryEntry
*) array
->getObject( index
));
1550 (*applier
)(next
, context
);
1555 void IORegistryEntry::applyToParents( IORegistryEntryApplierFunction applier
,
1557 const IORegistryPlane
* plane
) const
1561 IORegistryEntry
* next
;
1567 array
= OSArray::withArray( getParentSetReference( plane
));
1571 (next
= (IORegistryEntry
*) array
->getObject( index
));
1573 (*applier
)(next
, context
);
1578 bool IORegistryEntry::isChild( IORegistryEntry
* child
,
1579 const IORegistryPlane
* plane
,
1580 bool onlyChild
) const
1587 if( (links
= getChildSetReference( plane
))) {
1588 if( (!onlyChild
) || (1 == links
->getCount()))
1589 ret
= arrayMember( links
, child
);
1591 if( ret
&& (links
= child
->getParentSetReference( plane
)))
1592 ret
= arrayMember( links
, this );
1599 bool IORegistryEntry::isParent( IORegistryEntry
* parent
,
1600 const IORegistryPlane
* plane
,
1601 bool onlyParent
) const
1609 if( (links
= getParentSetReference( plane
))) {
1610 if( (!onlyParent
) || (1 == links
->getCount()))
1611 ret
= arrayMember( links
, parent
);
1613 if( ret
&& (links
= parent
->getChildSetReference( plane
)))
1614 ret
= arrayMember( links
, this );
1621 bool IORegistryEntry::inPlane( const IORegistryPlane
* plane
) const
1628 ret
= (0 != getParentSetReference( plane
));
1631 // Check to see if this is in any plane. If it is in a plane
1632 // then the registryTable will contain a key with the ParentLinks
1633 // suffix. When we iterate over the keys looking for that suffix
1636 OSCollectionIterator
*iter
=
1637 OSCollectionIterator::withCollection( registryTable());
1639 const OSSymbol
*key
;
1641 while( (key
= (OSSymbol
*) iter
->getNextObject()) ) {
1644 // Get a pointer to this keys suffix
1645 keysuffix
= key
->getLength();
1646 if (keysuffix
<= kIORegPlaneParentSuffixLen
)
1648 keysuffix
-= kIORegPlaneParentSuffixLen
;
1649 if( !strncmp(key
->getCStringNoCopy() + keysuffix
,
1650 kIORegPlaneParentSuffix
,
1651 kIORegPlaneParentSuffixLen
+ 1) ) {
1665 bool IORegistryEntry::attachToParent( IORegistryEntry
* parent
,
1666 const IORegistryPlane
* plane
)
1677 if (!reserved
->fRegistryEntryID
)
1678 reserved
->fRegistryEntryID
= ++gIORegistryLastID
;
1680 ret
= makeLink( parent
, kParentSetIndex
, plane
);
1682 if( (links
= parent
->getChildSetReference( plane
)))
1683 needParent
= (false == arrayMember( links
, this ));
1691 // Mark any collections in the property list as immutable
1692 OSDictionary
*ptable
= getPropertyTable();
1693 OSCollectionIterator
*iter
=
1694 OSCollectionIterator::withCollection( ptable
);
1696 const OSSymbol
*key
;
1698 while( (key
= (OSSymbol
*) iter
->getNextObject( ))) {
1699 // Is object for key a collection?
1700 OSCollection
*coll
=
1701 OSDynamicCast( OSCollection
, ptable
->getObject( key
));
1704 // Yup so mark it as immutable
1705 coll
->setOptions( OSCollection::kMASK
,
1706 OSCollection::kImmutable
);
1715 ret
&= parent
->attachToChild( this, plane
);
1720 uint64_t IORegistryEntry::getRegistryEntryID( void )
1723 return (reserved
->fRegistryEntryID
);
1728 bool IORegistryEntry::attachToChild( IORegistryEntry
* child
,
1729 const IORegistryPlane
* plane
)
1740 ret
= makeLink( child
, kChildSetIndex
, plane
);
1742 if( (links
= child
->getParentSetReference( plane
)))
1743 needChild
= (false == arrayMember( links
, this ));
1750 ret
&= child
->attachToParent( this, plane
);
1755 void IORegistryEntry::detachFromParent( IORegistryEntry
* parent
,
1756 const IORegistryPlane
* plane
)
1765 breakLink( parent
, kParentSetIndex
, plane
);
1767 if( (links
= parent
->getChildSetReference( plane
)))
1768 needParent
= arrayMember( links
, this );
1772 // parent->breakLink( this, kChildSetIndex, plane );
1777 parent
->detachFromChild( this, plane
);
1782 void IORegistryEntry::detachFromChild( IORegistryEntry
* child
,
1783 const IORegistryPlane
* plane
)
1792 breakLink( child
, kChildSetIndex
, plane
);
1794 if( (links
= child
->getParentSetReference( plane
)))
1795 needChild
= arrayMember( links
, this );
1802 child
->detachFromParent( this, plane
);
1807 void IORegistryEntry::detachAbove( const IORegistryPlane
* plane
)
1809 IORegistryEntry
* parent
;
1812 while( (parent
= copyParentEntry( plane
)))
1814 detachFromParent( parent
, plane
);
1820 void IORegistryEntry::detachAll( const IORegistryPlane
* plane
)
1823 IORegistryEntry
* next
;
1824 IORegistryIterator
* regIter
;
1826 regIter
= IORegistryIterator::iterateOver( this, plane
, true );
1829 all
= regIter
->iterateAll();
1832 detachAbove( plane
);
1834 while( (next
= (IORegistryEntry
*) all
->getLastObject())) {
1837 all
->removeObject(next
);
1839 next
->detachAbove( plane
);
1846 unsigned int IORegistryEntry::getDepth( const IORegistryPlane
* plane
) const
1848 unsigned int depth
= 1;
1850 unsigned int oneDepth
, maxParentDepth
, count
;
1851 IORegistryEntry
* one
;
1852 const IORegistryEntry
* next
;
1858 while( (parents
= next
->getParentSetReference( plane
))) {
1860 count
= parents
->getCount();
1865 next
= (IORegistryEntry
*) parents
->getObject( 0 );
1870 (one
= (IORegistryEntry
*) parents
->getObject( index
));
1872 oneDepth
= one
->getDepth( plane
);
1873 if( oneDepth
> maxParentDepth
)
1874 maxParentDepth
= oneDepth
;
1876 depth
+= maxParentDepth
;
1886 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1889 #define super OSIterator
1891 OSDefineMetaClassAndStructors(IORegistryIterator
, OSIterator
)
1893 enum { kIORegistryIteratorInvalidFlag
= 0x80000000 };
1895 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1897 IORegistryIterator
*
1898 IORegistryIterator::iterateOver( IORegistryEntry
* root
,
1899 const IORegistryPlane
* plane
,
1900 IOOptionBits options
)
1902 IORegistryIterator
* create
;
1909 create
= new IORegistryIterator
;
1911 if( create
->init()) {
1914 create
->root
= root
;
1915 create
->where
= &create
->start
;
1916 create
->start
.current
= root
;
1917 create
->plane
= plane
;
1918 create
->options
= options
& ~kIORegistryIteratorInvalidFlag
;
1928 IORegistryIterator
*
1929 IORegistryIterator::iterateOver( const IORegistryPlane
* plane
,
1930 IOOptionBits options
)
1932 return( iterateOver( gRegistryRoot
, plane
, options
));
1935 bool IORegistryIterator::isValid( void )
1944 ok
= (0 == (kIORegistryIteratorInvalidFlag
& options
));
1946 while( ok
&& next
) {
1948 ok
= where
->iter
->isValid();
1956 void IORegistryIterator::enterEntry( const IORegistryPlane
* enterPlane
)
1961 where
= (IORegCursor
*) IOMalloc( sizeof(IORegCursor
));
1967 where
->current
= prev
->current
;
1972 void IORegistryIterator::enterEntry( void )
1974 enterEntry( plane
);
1977 bool IORegistryIterator::exitEntry( void )
1982 where
->iter
->release();
1984 if( where
->current
)// && (where != &start))
1985 where
->current
->release();
1988 if( where
!= &start
) {
1991 IOFree( gone
, sizeof(IORegCursor
));
1998 void IORegistryIterator::reset( void )
2008 where
->current
= root
;
2009 options
&= ~kIORegistryIteratorInvalidFlag
;
2012 void IORegistryIterator::free( void )
2023 IORegistryEntry
* IORegistryIterator::getNextObjectFlat( void )
2025 IORegistryEntry
* next
= 0;
2026 OSArray
* links
= 0;
2030 if( (0 == where
->iter
)) {
2031 // just entered - create new iter
2034 && (links
= ( (options
& kIORegistryIterateParents
) ?
2035 where
->current
->getParentSetReference( plane
) :
2036 where
->current
->getChildSetReference( plane
) )) )
2038 where
->iter
= OSCollectionIterator::withCollection( links
);
2041 // next sibling - release current
2043 where
->current
->release();
2047 next
= (IORegistryEntry
*) where
->iter
->getNextObject();
2051 else if( !where
->iter
->isValid())
2052 options
|= kIORegistryIteratorInvalidFlag
;
2055 where
->current
= next
;
2062 IORegistryEntry
* IORegistryIterator::getNextObjectRecursive( void )
2064 IORegistryEntry
* next
;
2067 next
= getNextObjectFlat();
2068 while( (0 == next
) && exitEntry());
2072 done
= OSOrderedSet::withCapacity( 10 );
2073 if( done
->setObject((OSObject
*) next
)) {
2074 // done set didn't contain this one, so recurse
2081 IORegistryEntry
* IORegistryIterator::getNextObject( void )
2083 if( options
& kIORegistryIterateRecursively
)
2084 return( getNextObjectRecursive());
2086 return( getNextObjectFlat());
2089 IORegistryEntry
* IORegistryIterator::getCurrentEntry( void )
2092 return( where
->current
);
2097 OSOrderedSet
* IORegistryIterator::iterateAll( void )
2100 while( getNextObjectRecursive())
2108 OSMetaClassDefineReservedUnused(IORegistryEntry
, 0);
2109 OSMetaClassDefineReservedUnused(IORegistryEntry
, 1);
2110 OSMetaClassDefineReservedUnused(IORegistryEntry
, 2);
2111 OSMetaClassDefineReservedUnused(IORegistryEntry
, 3);
2112 OSMetaClassDefineReservedUnused(IORegistryEntry
, 4);
2113 OSMetaClassDefineReservedUnused(IORegistryEntry
, 5);
2115 OSMetaClassDefineReservedUsed(IORegistryEntry
, 0);
2116 OSMetaClassDefineReservedUsed(IORegistryEntry
, 1);
2117 OSMetaClassDefineReservedUsed(IORegistryEntry
, 2);
2118 OSMetaClassDefineReservedUsed(IORegistryEntry
, 3);
2119 OSMetaClassDefineReservedUsed(IORegistryEntry
, 4);
2120 OSMetaClassDefineReservedUsed(IORegistryEntry
, 5);
2122 OSMetaClassDefineReservedUnused(IORegistryEntry
, 6);
2123 OSMetaClassDefineReservedUnused(IORegistryEntry
, 7);
2124 OSMetaClassDefineReservedUnused(IORegistryEntry
, 8);
2125 OSMetaClassDefineReservedUnused(IORegistryEntry
, 9);
2126 OSMetaClassDefineReservedUnused(IORegistryEntry
, 10);
2127 OSMetaClassDefineReservedUnused(IORegistryEntry
, 11);
2128 OSMetaClassDefineReservedUnused(IORegistryEntry
, 12);
2129 OSMetaClassDefineReservedUnused(IORegistryEntry
, 13);
2130 OSMetaClassDefineReservedUnused(IORegistryEntry
, 14);
2131 OSMetaClassDefineReservedUnused(IORegistryEntry
, 15);
2132 OSMetaClassDefineReservedUnused(IORegistryEntry
, 16);
2133 OSMetaClassDefineReservedUnused(IORegistryEntry
, 17);
2134 OSMetaClassDefineReservedUnused(IORegistryEntry
, 18);
2135 OSMetaClassDefineReservedUnused(IORegistryEntry
, 19);
2136 OSMetaClassDefineReservedUnused(IORegistryEntry
, 20);
2137 OSMetaClassDefineReservedUnused(IORegistryEntry
, 21);
2138 OSMetaClassDefineReservedUnused(IORegistryEntry
, 22);
2139 OSMetaClassDefineReservedUnused(IORegistryEntry
, 23);
2140 OSMetaClassDefineReservedUnused(IORegistryEntry
, 24);
2141 OSMetaClassDefineReservedUnused(IORegistryEntry
, 25);
2142 OSMetaClassDefineReservedUnused(IORegistryEntry
, 26);
2143 OSMetaClassDefineReservedUnused(IORegistryEntry
, 27);
2144 OSMetaClassDefineReservedUnused(IORegistryEntry
, 28);
2145 OSMetaClassDefineReservedUnused(IORegistryEntry
, 29);
2146 OSMetaClassDefineReservedUnused(IORegistryEntry
, 30);
2147 OSMetaClassDefineReservedUnused(IORegistryEntry
, 31);
2149 /* inline function implementation */
2150 OSDictionary
* IORegistryEntry::getPropertyTable( void ) const
2151 { return(fPropertyTable
); }