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 * Copyright (c) 1998 Apple Computer, Inc. All rights reserved.
32 * 12 Nov 98 sdouglas created.
36 #include <IOKit/IORegistryEntry.h>
37 #include <libkern/c++/OSContainers.h>
38 #include <IOKit/IOService.h>
39 #include <IOKit/IOKitKeys.h>
41 #include <IOKit/IOLib.h>
43 #include <IOKit/assert.h>
45 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
47 #define super OSObject
49 OSDefineMetaClassAndStructors(IORegistryEntry
, OSObject
)
51 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
53 #define kIORegPlaneParentSuffix "ParentLinks"
54 #define kIORegPlaneChildSuffix "ChildLinks"
55 #define kIORegPlaneNameSuffix "Name"
56 #define kIORegPlaneLocationSuffix "Location"
58 #define kIORegPlaneParentSuffixLen (sizeof(kIORegPlaneParentSuffix) - 1)
59 #define kIORegPlaneChildSuffixLen (sizeof(kIORegPlaneChildSuffix) - 1)
60 #define kIORegPlaneNameSuffixLen (sizeof(kIORegPlaneNameSuffix) - 1)
61 #define kIORegPlaneLocationSuffixLen (sizeof(kIORegPlaneLocationSuffix) - 1)
63 #define KASLR_IOREG_DEBUG 0
65 static IORegistryEntry
* gRegistryRoot
;
66 static OSDictionary
* gIORegistryPlanes
;
68 const OSSymbol
* gIONameKey
;
69 const OSSymbol
* gIOLocationKey
;
70 const OSSymbol
* gIORegistryEntryIDKey
;
81 enum { kIORegistryIDReserved
= (1ULL << 32) + 255 };
83 static uint64_t gIORegistryLastID
= kIORegistryIDReserved
;
85 class IORegistryPlane
: public OSObject
{
87 friend class IORegistryEntry
;
89 OSDeclareAbstractStructors(IORegistryPlane
)
91 const OSSymbol
* nameKey
;
92 const OSSymbol
* keys
[ kNumSetIndex
];
93 const OSSymbol
* pathNameKey
;
94 const OSSymbol
* pathLocationKey
;
98 virtual bool serialize(OSSerialize
*s
) const;
101 OSDefineMetaClassAndStructors(IORegistryPlane
, OSObject
)
104 static IORecursiveLock
* gPropertiesLock
;
105 static SInt32 gIORegistryGenerationCount
;
107 #define UNLOCK lck_rw_done( &gIORegistryLock )
108 #define RLOCK lck_rw_lock_shared( &gIORegistryLock )
109 #define WLOCK lck_rw_lock_exclusive( &gIORegistryLock ); \
110 gIORegistryGenerationCount++
113 #define PUNLOCK IORecursiveLockUnlock( gPropertiesLock )
114 #define PLOCK IORecursiveLockLock( gPropertiesLock )
116 #define IOREGSPLITTABLES
118 #ifdef IOREGSPLITTABLES
119 #define registryTable() fRegistryTable
121 #define registryTable() fPropertyTable
126 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
128 lck_rw_t gIORegistryLock
;
129 lck_grp_t
*gIORegistryLockGrp
;
130 lck_grp_attr_t
*gIORegistryLockGrpAttr
;
131 lck_attr_t
*gIORegistryLockAttr
;
134 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
136 IORegistryEntry
* IORegistryEntry::initialize( void )
140 if( !gRegistryRoot
) {
143 gIORegistryLockGrpAttr
= lck_grp_attr_alloc_init();
144 //lck_grp_attr_setstat(gIORegistryLockGrpAttr);
145 gIORegistryLockGrp
= lck_grp_alloc_init("IORegistryLock", gIORegistryLockGrpAttr
);
146 gIORegistryLockAttr
= lck_attr_alloc_init();
147 lck_attr_rw_shared_priority(gIORegistryLockAttr
);
148 //lck_attr_setdebug(gIORegistryLockAttr);
149 lck_rw_init( &gIORegistryLock
, gIORegistryLockGrp
, gIORegistryLockAttr
);
151 gRegistryRoot
= new IORegistryEntry
;
152 gPropertiesLock
= IORecursiveLockAlloc();
153 gIORegistryPlanes
= OSDictionary::withCapacity( 1 );
155 assert( gRegistryRoot
&& gPropertiesLock
156 && gIORegistryPlanes
);
157 ok
= gRegistryRoot
->init();
160 gRegistryRoot
->reserved
->fRegistryEntryID
= ++gIORegistryLastID
;
162 gIONameKey
= OSSymbol::withCStringNoCopy( "IOName" );
163 gIOLocationKey
= OSSymbol::withCStringNoCopy( "IOLocation" );
164 gIORegistryEntryIDKey
= OSSymbol::withCStringNoCopy( kIORegistryEntryIDKey
);
166 assert( ok
&& gIONameKey
&& gIOLocationKey
);
168 gRegistryRoot
->setName( "Root" );
169 gRegistryRoot
->setProperty( kIORegistryPlanesKey
, gIORegistryPlanes
);
172 return( gRegistryRoot
);
175 IORegistryEntry
* IORegistryEntry::getRegistryRoot( void )
177 return( gRegistryRoot
);
180 SInt32
IORegistryEntry::getGenerationCount( void )
182 return( gIORegistryGenerationCount
);
186 const IORegistryPlane
* IORegistryEntry::makePlane( const char * name
)
188 IORegistryPlane
* plane
;
189 const OSSymbol
* nameKey
;
190 const OSSymbol
* parentKey
;
191 const OSSymbol
* childKey
;
192 const OSSymbol
* pathNameKey
;
193 const OSSymbol
* pathLocationKey
;
194 char key
[ kIOMaxPlaneName
+ 16 ];
197 strlcpy( key
, name
, kIOMaxPlaneName
+ 1 );
198 end
= key
+ strlen( key
);
200 nameKey
= OSSymbol::withCString( key
);
202 strlcpy( end
, kIORegPlaneParentSuffix
, kIORegPlaneParentSuffixLen
+ 1 );
203 parentKey
= OSSymbol::withCString( key
);
205 strlcpy( end
, kIORegPlaneChildSuffix
, kIORegPlaneChildSuffixLen
+ 1 );
206 childKey
= OSSymbol::withCString( key
);
208 strlcpy( end
, kIORegPlaneNameSuffix
, kIORegPlaneNameSuffixLen
+ 1 );
209 pathNameKey
= OSSymbol::withCString( key
);
211 strlcpy( end
, kIORegPlaneLocationSuffix
, kIORegPlaneLocationSuffixLen
+ 1 );
212 pathLocationKey
= OSSymbol::withCString( key
);
214 plane
= new IORegistryPlane
;
216 if( plane
&& plane
->init()
217 && nameKey
&& parentKey
&& childKey
218 && pathNameKey
&& pathLocationKey
) {
220 plane
->nameKey
= nameKey
;
221 plane
->keys
[ kParentSetIndex
] = parentKey
;
222 plane
->keys
[ kChildSetIndex
] = childKey
;
223 plane
->pathNameKey
= pathNameKey
;
224 plane
->pathLocationKey
= pathLocationKey
;
227 gIORegistryPlanes
->setObject( nameKey
, plane
);
235 pathLocationKey
->release();
237 pathNameKey
->release();
239 parentKey
->release();
250 const IORegistryPlane
* IORegistryEntry::getPlane( const char * name
)
252 const IORegistryPlane
* plane
;
255 plane
= (const IORegistryPlane
*) gIORegistryPlanes
->getObject( name
);
261 bool IORegistryPlane::serialize(OSSerialize
*s
) const
263 return( nameKey
->serialize(s
) );
266 enum { kIORegCapacityIncrement
= 4 };
268 bool IORegistryEntry::init( OSDictionary
* dict
)
277 reserved
= IONew(ExpansionData
, 1);
280 bzero(reserved
, sizeof(ExpansionData
));
283 if (OSCollection::kImmutable
& dict
->setOptions(0, 0)) {
284 dict
= (OSDictionary
*) dict
->copyCollection();
290 fPropertyTable
->release();
291 fPropertyTable
= dict
;
293 } else if( !fPropertyTable
) {
294 fPropertyTable
= OSDictionary::withCapacity( kIORegCapacityIncrement
);
296 fPropertyTable
->setCapacityIncrement( kIORegCapacityIncrement
);
302 #ifdef IOREGSPLITTABLES
303 if( !fRegistryTable
) {
304 fRegistryTable
= OSDictionary::withCapacity( kIORegCapacityIncrement
);
306 fRegistryTable
->setCapacityIncrement( kIORegCapacityIncrement
);
309 if( (prop
= OSDynamicCast( OSString
, getProperty( gIONameKey
)))) {
310 OSSymbol
* sym
= (OSSymbol
*)OSSymbol::withString( prop
);
311 // ok for OSSymbol too
316 #endif /* IOREGSPLITTABLES */
321 bool IORegistryEntry::init( IORegistryEntry
* old
,
322 const IORegistryPlane
* plane
)
325 IORegistryEntry
* next
;
333 reserved
= old
->reserved
;
334 old
->reserved
= NULL
;
336 fPropertyTable
= old
->getPropertyTable();
337 fPropertyTable
->retain();
338 #ifdef IOREGSPLITTABLES
339 fRegistryTable
= old
->fRegistryTable
;
340 old
->fRegistryTable
= OSDictionary::withDictionary( fRegistryTable
);
341 #endif /* IOREGSPLITTABLES */
343 old
->registryTable()->removeObject( plane
->keys
[ kParentSetIndex
] );
344 old
->registryTable()->removeObject( plane
->keys
[ kChildSetIndex
] );
346 all
= getParentSetReference( plane
);
347 if( all
) for( index
= 0;
348 (next
= (IORegistryEntry
*) all
->getObject(index
));
350 next
->makeLink( this, kChildSetIndex
, plane
);
351 next
->breakLink( old
, kChildSetIndex
, plane
);
354 all
= getChildSetReference( plane
);
355 if( all
) for( index
= 0;
356 (next
= (IORegistryEntry
*) all
->getObject(index
));
358 next
->makeLink( this, kParentSetIndex
, plane
);
359 next
->breakLink( old
, kParentSetIndex
, plane
);
367 void IORegistryEntry::free( void )
370 if( registryTable() && gIOServicePlane
) {
371 if( getParentSetReference( gIOServicePlane
)
372 || getChildSetReference( gIOServicePlane
)) {
373 panic("%s: attached at free()", getName());
378 if( getPropertyTable())
379 getPropertyTable()->release();
381 #ifdef IOREGSPLITTABLES
383 registryTable()->release();
384 #endif /* IOREGSPLITTABLES */
387 IODelete(reserved
, ExpansionData
, 1);
392 void IORegistryEntry::setPropertyTable( OSDictionary
* dict
)
395 fPropertyTable
->release();
398 fPropertyTable
= dict
;
401 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
403 /* Wrappers to synchronize property table */
405 #define wrap2(type, constant) \
407 IORegistryEntry::copyProperty( type * aKey) constant \
412 obj = getProperty( aKey ); \
420 #define wrap4(type,constant) \
422 IORegistryEntry::getProperty( type * aKey, \
423 const IORegistryPlane * plane, \
424 IOOptionBits options ) constant \
426 OSObject * obj = getProperty( aKey ); \
428 if ( (0 == obj) && plane && (options & kIORegistryIterateRecursively) ) { \
429 IORegistryEntry * entry = (IORegistryEntry *) this; \
430 IORegistryIterator * iter; \
431 iter = IORegistryIterator::iterateOver( entry, plane, options ); \
434 while ( (0 == obj) && (entry = iter->getNextObject()) ) { \
435 obj = entry->getProperty( aKey ); \
444 #define wrap5(type,constant) \
446 IORegistryEntry::copyProperty( type * aKey, \
447 const IORegistryPlane * plane, \
448 IOOptionBits options ) constant \
450 OSObject * obj = copyProperty( aKey ); \
452 if ( (0 == obj) && plane && (options & kIORegistryIterateRecursively) ) { \
453 IORegistryEntry * entry = (IORegistryEntry *) this; \
454 IORegistryIterator * iter; \
455 iter = IORegistryIterator::iterateOver( entry, plane, options ); \
458 while ( (0 == obj) && (entry = iter->getNextObject()) ) { \
459 obj = entry->copyProperty( aKey ); \
468 bool IORegistryEntry::serializeProperties( OSSerialize
* s
) const
470 // setProperty( getRetainCount(), 32, "__retain" );
473 OSCollection
*snapshotProperties
= getPropertyTable()->copyCollection();
476 bool ok
= snapshotProperties
->serialize( s
);
477 snapshotProperties
->release();
481 OSDictionary
* IORegistryEntry::dictionaryWithProperties( void ) const
486 dict
= OSDictionary::withDictionary( getPropertyTable(),
487 getPropertyTable()->getCapacity() );
493 IOReturn
IORegistryEntry::setProperties( OSObject
* properties
)
495 return( kIOReturnUnsupported
);
498 wrap2(const OSSymbol
, const) // copyProperty() definition
499 wrap2(const OSString
, const) // copyProperty() definition
500 wrap2(const char, const) // copyProperty() definition
502 wrap4(const OSSymbol
, const) // getProperty() w/plane definition
503 wrap4(const OSString
, const) // getProperty() w/plane definition
504 wrap4(const char, const) // getProperty() w/plane definition
506 wrap5(const OSSymbol
, const) // copyProperty() w/plane definition
507 wrap5(const OSString
, const) // copyProperty() w/plane definition
508 wrap5(const char, const) // copyProperty() w/plane definition
512 IORegistryEntry::getProperty( const OSSymbol
* aKey
) const
517 obj
= getPropertyTable()->getObject( aKey
);
524 IORegistryEntry::removeProperty( const OSSymbol
* aKey
)
527 getPropertyTable()->removeObject( aKey
);
531 #if KASLR_IOREG_DEBUG
534 bool ScanForAddrInObject(OSObject
* theObject
,
541 IORegistryEntry::setProperty( const OSSymbol
* aKey
, OSObject
* anObject
)
545 // If we are inserting a collection class and the current entry
546 // is attached into the registry (inPlane()) then mark the collection
548 OSCollection
*coll
= OSDynamicCast(OSCollection
, anObject
);
549 bool makeImmutable
= (coll
&& inPlane());
553 coll
->setOptions( OSCollection::kMASK
, OSCollection::kImmutable
);
555 ret
= getPropertyTable()->setObject( aKey
, anObject
);
558 #if KASLR_IOREG_DEBUG
559 if ( anObject
&& strcmp(kIOKitDiagnosticsKey
, aKey
->getCStringNoCopy()) != 0 ) {
560 if (ScanForAddrInObject(anObject
, 0)) {
561 IOLog("%s: IORegistryEntry name %s with key \"%s\" \n",
564 aKey
->getCStringNoCopy() );
572 IOReturn
IORegistryEntry::
573 runPropertyAction(Action inAction
, OSObject
*target
,
574 void *arg0
, void *arg1
, void *arg2
, void *arg3
)
578 // closeGate is recursive so don't worry if we already hold the lock.
580 res
= (*inAction
)(target
, arg0
, arg1
, arg2
, arg3
);
587 IORegistryEntry::getProperty( const OSString
* aKey
) const
589 const OSSymbol
* tmpKey
= OSSymbol::withString( aKey
);
590 OSObject
* obj
= getProperty( tmpKey
);
597 IORegistryEntry::getProperty( const char * aKey
) const
599 const OSSymbol
* tmpKey
= OSSymbol::withCString( aKey
);
600 OSObject
* obj
= getProperty( tmpKey
);
608 IORegistryEntry::removeProperty( const OSString
* aKey
)
610 const OSSymbol
* tmpKey
= OSSymbol::withString( aKey
);
611 removeProperty( tmpKey
);
616 IORegistryEntry::removeProperty( const char * aKey
)
618 const OSSymbol
* tmpKey
= OSSymbol::withCString( aKey
);
619 removeProperty( tmpKey
);
624 IORegistryEntry::setProperty( const OSString
* aKey
, OSObject
* anObject
)
626 const OSSymbol
* tmpKey
= OSSymbol::withString( aKey
);
627 bool ret
= setProperty( tmpKey
, anObject
);
634 IORegistryEntry::setProperty( const char * aKey
, OSObject
* anObject
)
636 const OSSymbol
* tmpKey
= OSSymbol::withCString( aKey
);
637 bool ret
= setProperty( tmpKey
, anObject
);
644 IORegistryEntry::setProperty(const char * aKey
, const char * aString
)
647 OSSymbol
* aSymbol
= (OSSymbol
*) OSSymbol::withCString( aString
);
650 const OSSymbol
* tmpKey
= OSSymbol::withCString( aKey
);
651 ret
= setProperty( tmpKey
, aSymbol
);
660 IORegistryEntry::setProperty(const char * aKey
, bool aBoolean
)
663 OSBoolean
* aBooleanObj
= OSBoolean::withBoolean( aBoolean
);
666 const OSSymbol
* tmpKey
= OSSymbol::withCString( aKey
);
667 ret
= setProperty( tmpKey
, aBooleanObj
);
670 aBooleanObj
->release();
676 IORegistryEntry::setProperty( const char * aKey
,
677 unsigned long long aValue
,
678 unsigned int aNumberOfBits
)
681 OSNumber
* anOffset
= OSNumber::withNumber( aValue
, aNumberOfBits
);
684 const OSSymbol
* tmpKey
= OSSymbol::withCString( aKey
);
685 ret
= setProperty( tmpKey
, anOffset
);
694 IORegistryEntry::setProperty( const char * aKey
,
699 OSData
* data
= OSData::withBytes( bytes
, length
);
702 const OSSymbol
* tmpKey
= OSSymbol::withCString( aKey
);
703 ret
= setProperty( tmpKey
, data
);
711 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
713 /* Name, location, paths */
715 const char * IORegistryEntry::getName( const IORegistryPlane
* plane
) const
721 sym
= (OSSymbol
*) registryTable()->getObject( plane
->pathNameKey
);
723 sym
= (OSSymbol
*) registryTable()->getObject( gIONameKey
);
727 return( sym
->getCStringNoCopy());
729 return( (getMetaClass())->getClassName());
732 const OSSymbol
* IORegistryEntry::copyName(
733 const IORegistryPlane
* plane
) const
739 sym
= (OSSymbol
*) registryTable()->getObject( plane
->pathNameKey
);
741 sym
= (OSSymbol
*) registryTable()->getObject( gIONameKey
);
749 return( OSSymbol::withCString((getMetaClass())->getClassName()) );
752 const OSSymbol
* IORegistryEntry::copyLocation(
753 const IORegistryPlane
* plane
) const
759 sym
= (OSSymbol
*) registryTable()->getObject( plane
->pathLocationKey
);
761 sym
= (OSSymbol
*) registryTable()->getObject( gIOLocationKey
);
769 const char * IORegistryEntry::getLocation( const IORegistryPlane
* plane
) const
771 const OSSymbol
* sym
= copyLocation( plane
);
772 const char * result
= 0;
775 result
= sym
->getCStringNoCopy();
782 void IORegistryEntry::setName( const OSSymbol
* name
,
783 const IORegistryPlane
* plane
)
785 const OSSymbol
* key
;
789 key
= plane
->pathNameKey
;
794 registryTable()->setObject( key
, (OSObject
*) name
);
799 void IORegistryEntry::setName( const char * name
,
800 const IORegistryPlane
* plane
)
802 OSSymbol
* sym
= (OSSymbol
*)OSSymbol::withCString( name
);
804 setName( sym
, plane
);
809 void IORegistryEntry::setLocation( const OSSymbol
* location
,
810 const IORegistryPlane
* plane
)
812 const OSSymbol
* key
;
816 key
= plane
->pathLocationKey
;
818 key
= gIOLocationKey
;
821 registryTable()->setObject( key
, (OSObject
*) location
);
826 void IORegistryEntry::setLocation( const char * location
,
827 const IORegistryPlane
* plane
)
829 OSSymbol
* sym
= (OSSymbol
*)OSSymbol::withCString( location
);
831 setLocation( sym
, plane
);
837 IORegistryEntry::compareName( OSString
* name
, OSString
** matched
) const
839 const OSSymbol
* sym
= copyName();
842 isEqual
= sym
->isEqualTo( name
);
844 if( isEqual
&& matched
) {
856 IORegistryEntry::compareNames( OSObject
* names
, OSString
** matched
) const
859 OSCollection
* collection
;
860 OSIterator
* iter
= 0;
863 if( (collection
= OSDynamicCast( OSCollection
, names
))) {
864 iter
= OSCollectionIterator::withCollection( collection
);
867 string
= OSDynamicCast( OSString
, names
);
871 result
= compareName( string
, matched
);
873 } while( (false == result
)
874 && iter
&& (string
= OSDynamicCast( OSString
, iter
->getNextObject())));
883 bool IORegistryEntry::getPath( char * path
, int * length
,
884 const IORegistryPlane
* plane
) const
887 IORegistryEntry
* root
;
888 const IORegistryEntry
* entry
;
889 IORegistryEntry
* parent
;
890 const OSSymbol
* alias
;
892 int len
, maxLength
, compLen
, aliasLen
;
896 if( !path
|| !length
|| !plane
)
900 maxLength
= *length
- 2;
903 len
= plane
->nameKey
->getLength();
904 if( len
>= maxLength
)
906 strlcpy( nextComp
, plane
->nameKey
->getCStringNoCopy(), len
+ 1);
907 nextComp
[ len
++ ] = ':';
910 if( (alias
= hasAlias( plane
))) {
911 aliasLen
= alias
->getLength();
913 ok
= (maxLength
> len
);
916 strlcpy( nextComp
, alias
->getCStringNoCopy(), aliasLen
+ 1);
921 parent
= entry
->getParentEntry( plane
);
923 // Error if not attached in plane
926 stack
= OSArray::withCapacity( getDepth( plane
));
932 root
= gRegistryRoot
->getChildEntry( plane
);
933 while( parent
&& (entry
!= root
)) {
935 stack
->setObject( (OSObject
*) entry
);
937 parent
= entry
->getParentEntry( plane
);
940 index
= stack
->getCount();
949 } else while( ok
&& ((--index
) >= 0)) {
951 entry
= (IORegistryEntry
*) stack
->getObject((unsigned int) index
);
954 if( (alias
= entry
->hasAlias( plane
))) {
955 len
= plane
->nameKey
->getLength() + 1;
956 nextComp
= path
+ len
;
958 compLen
= alias
->getLength();
959 ok
= (maxLength
> (len
+ compLen
));
961 strlcpy( nextComp
, alias
->getCStringNoCopy(), compLen
+ 1);
963 compLen
= maxLength
- len
;
964 ok
= entry
->getPathComponent( nextComp
+ 1, &compLen
, plane
);
986 bool IORegistryEntry::getPathComponent( char * path
, int * length
,
987 const IORegistryPlane
* plane
) const
989 int len
, locLen
, maxLength
;
990 const char * compName
;
996 compName
= getName( plane
);
997 len
= strlen( compName
);
998 if( (loc
= getLocation( plane
)))
999 locLen
= 1 + strlen( loc
);
1003 ok
= ((len
+ locLen
+ 1) < maxLength
);
1005 strlcpy( path
, compName
, len
+ 1 );
1010 strlcpy( path
, loc
, locLen
);
1018 const char * IORegistryEntry::matchPathLocation( const char * cmp
,
1019 const IORegistryPlane
* plane
)
1022 const char * result
= 0;
1023 u_quad_t num1
, num2
;
1024 char lastPathChar
, lastLocationChar
;
1026 str
= getLocation( plane
);
1028 lastPathChar
= cmp
[0];
1029 lastLocationChar
= str
[0];
1032 num1
= strtouq( cmp
, (char **) &cmp
, 16 );
1033 lastPathChar
= *cmp
++;
1037 if( lastLocationChar
) {
1038 num2
= strtouq( str
, (char **) &str
, 16 );
1039 lastLocationChar
= *str
++;
1046 if (!lastPathChar
&& !lastLocationChar
) {
1051 if( (',' != lastPathChar
) && (':' != lastPathChar
))
1054 if (lastPathChar
&& lastLocationChar
&& (lastPathChar
!= lastLocationChar
))
1063 IORegistryEntry
* IORegistryEntry::getChildFromComponent( const char ** opath
,
1064 const IORegistryPlane
* plane
)
1066 IORegistryEntry
* entry
= 0;
1070 const char * cmp
= 0;
1075 set
= getChildSetReference( plane
);
1081 (entry
= (IORegistryEntry
*) set
->getObject(index
));
1087 str
= entry
->getName( plane
);
1088 len
= strlen( str
);
1089 if( strncmp( str
, cmp
, len
))
1094 if( (c
== 0) || (c
== '/') || (c
== ':'))
1100 if( (cmp
= entry
->matchPathLocation( cmp
, plane
)))
1110 const OSSymbol
* IORegistryEntry::hasAlias( const IORegistryPlane
* plane
,
1111 char * opath
, int * length
) const
1113 IORegistryEntry
* entry
;
1114 IORegistryEntry
* entry2
;
1115 const OSSymbol
* key
;
1116 const OSSymbol
* bestKey
= 0;
1119 const char * path
= "/aliases";
1121 entry
= IORegistryEntry::fromPath( path
, plane
);
1124 if( (iter
= OSCollectionIterator::withCollection(
1125 entry
->getPropertyTable() ))) {
1127 while( (key
= (OSSymbol
*) iter
->getNextObject())) {
1129 data
= (OSData
*) entry
->getProperty( key
);
1130 path
= (const char *) data
->getBytesNoCopy();
1131 if( (entry2
= IORegistryEntry::fromPath( path
, plane
,
1133 if( this == entry2
) {
1135 || (bestKey
->getLength() > key
->getLength()))
1136 // pick the smallest alias
1150 const char * IORegistryEntry::dealiasPath(
1151 const char ** opath
,
1152 const IORegistryPlane
* plane
)
1154 IORegistryEntry
* entry
;
1156 const char * path
= *opath
;
1157 const char * rpath
= 0;
1160 char temp
[ kIOMaxPlaneName
+ 1 ];
1167 while( (c
= *end
++) && (c
!= '/') && (c
!= ':'))
1170 if( (end
- path
) < kIOMaxPlaneName
) {
1171 strlcpy( temp
, path
, end
- path
+ 1 );
1174 entry
= IORegistryEntry::fromPath( "/aliases", plane
);
1176 data
= (OSData
*) entry
->getProperty( temp
);
1178 rpath
= (const char *) data
->getBytesNoCopy();
1190 IORegistryEntry
* IORegistryEntry::fromPath(
1192 const IORegistryPlane
* plane
,
1195 IORegistryEntry
* fromEntry
)
1197 IORegistryEntry
* where
= 0;
1198 IORegistryEntry
* aliasEntry
= 0;
1199 IORegistryEntry
* next
;
1205 char temp
[ kIOMaxPlaneName
+ 1 ];
1212 end
= strchr( path
, ':' );
1213 if( end
&& ((end
- path
) < kIOMaxPlaneName
)) {
1214 strlcpy( temp
, path
, end
- path
+ 1 );
1215 plane
= getPlane( temp
);
1224 if( (alias
= dealiasPath( &end
, plane
))) {
1227 aliasEntry
= IORegistryEntry::fromPath( alias
, plane
,
1228 opath
, &len
, fromEntry
);
1240 if( (0 == fromEntry
) && (*path
++ == '/'))
1241 fromEntry
= gRegistryRoot
->getChildEntry( plane
);
1248 if( c
&& (c
!= ':')) // check valid terminator
1253 next
= where
->getChildFromComponent( &path
, plane
);
1259 // check residual path
1260 if( where
!= fromEntry
)
1263 if( opath
&& length
) {
1264 // copy out residual path
1265 len2
= strlen( path
);
1266 if( (len
+ len2
) < *length
)
1267 strlcpy( opath
+ len
, path
, len2
+ 1 );
1268 *length
= (len
+ len2
);
1271 // no residual path => must be no tail for success
1278 aliasEntry
->release();
1285 IORegistryEntry
* IORegistryEntry::childFromPath(
1287 const IORegistryPlane
* plane
,
1291 return( IORegistryEntry::fromPath( path
, plane
, opath
, len
, this ));
1294 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1296 #define IOLinkIterator OSCollectionIterator
1299 #define super OSObject
1301 inline bool IORegistryEntry::arrayMember( OSArray
* set
,
1302 const IORegistryEntry
* member
,
1303 unsigned int * index
) const
1306 OSObject
* probeObject
;
1308 for( i
= 0; (probeObject
= set
->getObject(i
)); i
++) {
1309 if (probeObject
== (OSObject
*) member
) {
1318 bool IORegistryEntry::makeLink( IORegistryEntry
* to
,
1319 unsigned int relation
,
1320 const IORegistryPlane
* plane
) const
1323 bool result
= false;
1325 if( (links
= (OSArray
*)
1326 registryTable()->getObject( plane
->keys
[ relation
] ))) {
1328 result
= arrayMember( links
, to
);
1330 result
= links
->setObject( to
);
1334 links
= OSArray::withObjects( (const OSObject
**) &to
, 1, 1 );
1335 result
= (links
!= 0);
1337 result
= registryTable()->setObject( plane
->keys
[ relation
],
1346 void IORegistryEntry::breakLink( IORegistryEntry
* to
,
1347 unsigned int relation
,
1348 const IORegistryPlane
* plane
) const
1353 if( (links
= (OSArray
*)
1354 registryTable()->getObject( plane
->keys
[ relation
]))) {
1356 if( arrayMember( links
, to
, &index
)) {
1357 links
->removeObject( index
);
1358 if( 0 == links
->getCount())
1359 registryTable()->removeObject( plane
->keys
[ relation
]);
1365 OSArray
* IORegistryEntry::getParentSetReference(
1366 const IORegistryPlane
* plane
) const
1369 return( (OSArray
*) registryTable()->getObject(
1370 plane
->keys
[ kParentSetIndex
]));
1375 OSIterator
* IORegistryEntry::getParentIterator(
1376 const IORegistryPlane
* plane
) const
1385 links
= getParentSetReference( plane
);
1387 links
= OSArray::withCapacity( 1 );
1389 links
= OSArray::withArray( links
, links
->getCount() );
1392 iter
= IOLinkIterator::withCollection( links
);
1400 IORegistryEntry
* IORegistryEntry::copyParentEntry( const IORegistryPlane
* plane
) const
1402 IORegistryEntry
* entry
= 0;
1407 if( (links
= getParentSetReference( plane
))) {
1408 entry
= (IORegistryEntry
*) links
->getObject( 0 );
1417 IORegistryEntry
* IORegistryEntry::getParentEntry( const IORegistryPlane
* plane
) const
1419 IORegistryEntry
* entry
;
1421 entry
= copyParentEntry( plane
);
1428 OSArray
* IORegistryEntry::getChildSetReference( const IORegistryPlane
* plane
) const
1431 return( (OSArray
*) registryTable()->getObject(
1432 plane
->keys
[ kChildSetIndex
]));
1437 OSIterator
* IORegistryEntry::getChildIterator( const IORegistryPlane
* plane
) const
1446 links
= getChildSetReference( plane
);
1448 links
= OSArray::withCapacity( 1 );
1450 links
= OSArray::withArray( links
, links
->getCount() );
1453 iter
= IOLinkIterator::withCollection( links
);
1462 IORegistryEntry
* IORegistryEntry::copyChildEntry(
1463 const IORegistryPlane
* plane
) const
1465 IORegistryEntry
* entry
= 0;
1470 if( (links
= getChildSetReference( plane
))) {
1471 entry
= (IORegistryEntry
*) links
->getObject( 0 );
1480 IORegistryEntry
* IORegistryEntry::getChildEntry(
1481 const IORegistryPlane
* plane
) const
1483 IORegistryEntry
* entry
;
1485 entry
= copyChildEntry( plane
);
1492 void IORegistryEntry::applyToChildren( IORegistryEntryApplierFunction applier
,
1494 const IORegistryPlane
* plane
) const
1498 IORegistryEntry
* next
;
1504 array
= OSArray::withArray( getChildSetReference( plane
));
1508 (next
= (IORegistryEntry
*) array
->getObject( index
));
1510 (*applier
)(next
, context
);
1515 void IORegistryEntry::applyToParents( IORegistryEntryApplierFunction applier
,
1517 const IORegistryPlane
* plane
) const
1521 IORegistryEntry
* next
;
1527 array
= OSArray::withArray( getParentSetReference( plane
));
1531 (next
= (IORegistryEntry
*) array
->getObject( index
));
1533 (*applier
)(next
, context
);
1538 bool IORegistryEntry::isChild( IORegistryEntry
* child
,
1539 const IORegistryPlane
* plane
,
1540 bool onlyChild
) const
1547 if( (links
= getChildSetReference( plane
))) {
1548 if( (!onlyChild
) || (1 == links
->getCount()))
1549 ret
= arrayMember( links
, child
);
1551 if( ret
&& (links
= child
->getParentSetReference( plane
)))
1552 ret
= arrayMember( links
, this );
1559 bool IORegistryEntry::isParent( IORegistryEntry
* parent
,
1560 const IORegistryPlane
* plane
,
1561 bool onlyParent
) const
1569 if( (links
= getParentSetReference( plane
))) {
1570 if( (!onlyParent
) || (1 == links
->getCount()))
1571 ret
= arrayMember( links
, parent
);
1573 if( ret
&& (links
= parent
->getChildSetReference( plane
)))
1574 ret
= arrayMember( links
, this );
1581 bool IORegistryEntry::inPlane( const IORegistryPlane
* plane
) const
1588 ret
= (0 != getParentSetReference( plane
));
1591 // Check to see if this is in any plane. If it is in a plane
1592 // then the registryTable will contain a key with the ParentLinks
1593 // suffix. When we iterate over the keys looking for that suffix
1596 OSCollectionIterator
*iter
=
1597 OSCollectionIterator::withCollection( registryTable());
1599 const OSSymbol
*key
;
1601 while( (key
= (OSSymbol
*) iter
->getNextObject()) ) {
1604 // Get a pointer to this keys suffix
1605 keysuffix
= key
->getLength();
1606 if (keysuffix
<= kIORegPlaneParentSuffixLen
)
1608 keysuffix
-= kIORegPlaneParentSuffixLen
;
1609 if( !strncmp(key
->getCStringNoCopy() + keysuffix
,
1610 kIORegPlaneParentSuffix
,
1611 kIORegPlaneParentSuffixLen
+ 1) ) {
1625 bool IORegistryEntry::attachToParent( IORegistryEntry
* parent
,
1626 const IORegistryPlane
* plane
)
1637 if (!reserved
->fRegistryEntryID
)
1638 reserved
->fRegistryEntryID
= ++gIORegistryLastID
;
1640 ret
= makeLink( parent
, kParentSetIndex
, plane
);
1642 if( (links
= parent
->getChildSetReference( plane
)))
1643 needParent
= (false == arrayMember( links
, this ));
1651 // Mark any collections in the property list as immutable
1652 OSDictionary
*ptable
= getPropertyTable();
1653 OSCollectionIterator
*iter
=
1654 OSCollectionIterator::withCollection( ptable
);
1656 const OSSymbol
*key
;
1658 while( (key
= (OSSymbol
*) iter
->getNextObject( ))) {
1659 // Is object for key a collection?
1660 OSCollection
*coll
=
1661 OSDynamicCast( OSCollection
, ptable
->getObject( key
));
1664 // Yup so mark it as immutable
1665 coll
->setOptions( OSCollection::kMASK
,
1666 OSCollection::kImmutable
);
1675 ret
&= parent
->attachToChild( this, plane
);
1680 uint64_t IORegistryEntry::getRegistryEntryID( void )
1683 return (reserved
->fRegistryEntryID
);
1688 bool IORegistryEntry::attachToChild( IORegistryEntry
* child
,
1689 const IORegistryPlane
* plane
)
1700 ret
= makeLink( child
, kChildSetIndex
, plane
);
1702 if( (links
= child
->getParentSetReference( plane
)))
1703 needChild
= (false == arrayMember( links
, this ));
1710 ret
&= child
->attachToParent( this, plane
);
1715 void IORegistryEntry::detachFromParent( IORegistryEntry
* parent
,
1716 const IORegistryPlane
* plane
)
1725 breakLink( parent
, kParentSetIndex
, plane
);
1727 if( (links
= parent
->getChildSetReference( plane
)))
1728 needParent
= arrayMember( links
, this );
1732 // parent->breakLink( this, kChildSetIndex, plane );
1737 parent
->detachFromChild( this, plane
);
1742 void IORegistryEntry::detachFromChild( IORegistryEntry
* child
,
1743 const IORegistryPlane
* plane
)
1752 breakLink( child
, kChildSetIndex
, plane
);
1754 if( (links
= child
->getParentSetReference( plane
)))
1755 needChild
= arrayMember( links
, this );
1762 child
->detachFromParent( this, plane
);
1767 void IORegistryEntry::detachAbove( const IORegistryPlane
* plane
)
1769 IORegistryEntry
* parent
;
1772 while( (parent
= getParentEntry( plane
)))
1773 detachFromParent( parent
, plane
);
1777 void IORegistryEntry::detachAll( const IORegistryPlane
* plane
)
1780 IORegistryEntry
* next
;
1781 IORegistryIterator
* regIter
;
1783 regIter
= IORegistryIterator::iterateOver( this, plane
, true );
1786 all
= regIter
->iterateAll();
1789 detachAbove( plane
);
1791 while( (next
= (IORegistryEntry
*) all
->getLastObject())) {
1794 all
->removeObject(next
);
1796 next
->detachAbove( plane
);
1803 unsigned int IORegistryEntry::getDepth( const IORegistryPlane
* plane
) const
1805 unsigned int depth
= 1;
1807 unsigned int oneDepth
, maxParentDepth
, count
;
1808 IORegistryEntry
* one
;
1809 const IORegistryEntry
* next
;
1815 while( (parents
= next
->getParentSetReference( plane
))) {
1817 count
= parents
->getCount();
1822 next
= (IORegistryEntry
*) parents
->getObject( 0 );
1827 (one
= (IORegistryEntry
*) parents
->getObject( index
));
1829 oneDepth
= one
->getDepth( plane
);
1830 if( oneDepth
> maxParentDepth
)
1831 maxParentDepth
= oneDepth
;
1833 depth
+= maxParentDepth
;
1843 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1846 #define super OSIterator
1848 OSDefineMetaClassAndStructors(IORegistryIterator
, OSIterator
)
1850 enum { kIORegistryIteratorInvalidFlag
= 0x80000000 };
1852 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1854 IORegistryIterator
*
1855 IORegistryIterator::iterateOver( IORegistryEntry
* root
,
1856 const IORegistryPlane
* plane
,
1857 IOOptionBits options
)
1859 IORegistryIterator
* create
;
1866 create
= new IORegistryIterator
;
1868 if( create
->init()) {
1871 create
->root
= root
;
1872 create
->where
= &create
->start
;
1873 create
->start
.current
= root
;
1874 create
->plane
= plane
;
1875 create
->options
= options
& ~kIORegistryIteratorInvalidFlag
;
1885 IORegistryIterator
*
1886 IORegistryIterator::iterateOver( const IORegistryPlane
* plane
,
1887 IOOptionBits options
)
1889 return( iterateOver( gRegistryRoot
, plane
, options
));
1892 bool IORegistryIterator::isValid( void )
1901 ok
= (0 == (kIORegistryIteratorInvalidFlag
& options
));
1903 while( ok
&& next
) {
1905 ok
= where
->iter
->isValid();
1913 void IORegistryIterator::enterEntry( const IORegistryPlane
* enterPlane
)
1918 where
= (IORegCursor
*) IOMalloc( sizeof(IORegCursor
));
1924 where
->current
= prev
->current
;
1929 void IORegistryIterator::enterEntry( void )
1931 enterEntry( plane
);
1934 bool IORegistryIterator::exitEntry( void )
1939 where
->iter
->release();
1941 if( where
->current
)// && (where != &start))
1942 where
->current
->release();
1945 if( where
!= &start
) {
1948 IOFree( gone
, sizeof(IORegCursor
));
1955 void IORegistryIterator::reset( void )
1965 where
->current
= root
;
1966 options
&= ~kIORegistryIteratorInvalidFlag
;
1969 void IORegistryIterator::free( void )
1980 IORegistryEntry
* IORegistryIterator::getNextObjectFlat( void )
1982 IORegistryEntry
* next
= 0;
1983 OSArray
* links
= 0;
1987 if( (0 == where
->iter
)) {
1988 // just entered - create new iter
1991 && (links
= ( (options
& kIORegistryIterateParents
) ?
1992 where
->current
->getParentSetReference( plane
) :
1993 where
->current
->getChildSetReference( plane
) )) )
1995 where
->iter
= OSCollectionIterator::withCollection( links
);
1998 // next sibling - release current
2000 where
->current
->release();
2004 next
= (IORegistryEntry
*) where
->iter
->getNextObject();
2008 else if( !where
->iter
->isValid())
2009 options
|= kIORegistryIteratorInvalidFlag
;
2012 where
->current
= next
;
2019 IORegistryEntry
* IORegistryIterator::getNextObjectRecursive( void )
2021 IORegistryEntry
* next
;
2024 next
= getNextObjectFlat();
2025 while( (0 == next
) && exitEntry());
2029 done
= OSOrderedSet::withCapacity( 10 );
2030 if( done
->setObject((OSObject
*) next
)) {
2031 // done set didn't contain this one, so recurse
2038 IORegistryEntry
* IORegistryIterator::getNextObject( void )
2040 if( options
& kIORegistryIterateRecursively
)
2041 return( getNextObjectRecursive());
2043 return( getNextObjectFlat());
2046 IORegistryEntry
* IORegistryIterator::getCurrentEntry( void )
2049 return( where
->current
);
2054 OSOrderedSet
* IORegistryIterator::iterateAll( void )
2057 while( getNextObjectRecursive())
2065 OSMetaClassDefineReservedUnused(IORegistryEntry
, 0);
2066 OSMetaClassDefineReservedUnused(IORegistryEntry
, 1);
2067 OSMetaClassDefineReservedUnused(IORegistryEntry
, 2);
2068 OSMetaClassDefineReservedUnused(IORegistryEntry
, 3);
2069 OSMetaClassDefineReservedUnused(IORegistryEntry
, 4);
2070 OSMetaClassDefineReservedUnused(IORegistryEntry
, 5);
2072 OSMetaClassDefineReservedUsed(IORegistryEntry
, 0);
2073 OSMetaClassDefineReservedUsed(IORegistryEntry
, 1);
2074 OSMetaClassDefineReservedUsed(IORegistryEntry
, 2);
2075 OSMetaClassDefineReservedUsed(IORegistryEntry
, 3);
2076 OSMetaClassDefineReservedUsed(IORegistryEntry
, 4);
2077 OSMetaClassDefineReservedUsed(IORegistryEntry
, 5);
2079 OSMetaClassDefineReservedUnused(IORegistryEntry
, 6);
2080 OSMetaClassDefineReservedUnused(IORegistryEntry
, 7);
2081 OSMetaClassDefineReservedUnused(IORegistryEntry
, 8);
2082 OSMetaClassDefineReservedUnused(IORegistryEntry
, 9);
2083 OSMetaClassDefineReservedUnused(IORegistryEntry
, 10);
2084 OSMetaClassDefineReservedUnused(IORegistryEntry
, 11);
2085 OSMetaClassDefineReservedUnused(IORegistryEntry
, 12);
2086 OSMetaClassDefineReservedUnused(IORegistryEntry
, 13);
2087 OSMetaClassDefineReservedUnused(IORegistryEntry
, 14);
2088 OSMetaClassDefineReservedUnused(IORegistryEntry
, 15);
2089 OSMetaClassDefineReservedUnused(IORegistryEntry
, 16);
2090 OSMetaClassDefineReservedUnused(IORegistryEntry
, 17);
2091 OSMetaClassDefineReservedUnused(IORegistryEntry
, 18);
2092 OSMetaClassDefineReservedUnused(IORegistryEntry
, 19);
2093 OSMetaClassDefineReservedUnused(IORegistryEntry
, 20);
2094 OSMetaClassDefineReservedUnused(IORegistryEntry
, 21);
2095 OSMetaClassDefineReservedUnused(IORegistryEntry
, 22);
2096 OSMetaClassDefineReservedUnused(IORegistryEntry
, 23);
2097 OSMetaClassDefineReservedUnused(IORegistryEntry
, 24);
2098 OSMetaClassDefineReservedUnused(IORegistryEntry
, 25);
2099 OSMetaClassDefineReservedUnused(IORegistryEntry
, 26);
2100 OSMetaClassDefineReservedUnused(IORegistryEntry
, 27);
2101 OSMetaClassDefineReservedUnused(IORegistryEntry
, 28);
2102 OSMetaClassDefineReservedUnused(IORegistryEntry
, 29);
2103 OSMetaClassDefineReservedUnused(IORegistryEntry
, 30);
2104 OSMetaClassDefineReservedUnused(IORegistryEntry
, 31);
2106 /* inline function implementation */
2107 OSDictionary
* IORegistryEntry::getPropertyTable( void ) const
2108 { return(fPropertyTable
); }