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 static IORegistryEntry
* gRegistryRoot
;
64 static OSDictionary
* gIORegistryPlanes
;
66 const OSSymbol
* gIONameKey
;
67 const OSSymbol
* gIOLocationKey
;
78 class IORegistryPlane
: public OSObject
{
80 friend class IORegistryEntry
;
82 OSDeclareAbstractStructors(IORegistryPlane
)
84 const OSSymbol
* nameKey
;
85 const OSSymbol
* keys
[ kNumSetIndex
];
86 const OSSymbol
* pathNameKey
;
87 const OSSymbol
* pathLocationKey
;
91 virtual bool serialize(OSSerialize
*s
) const;
94 OSDefineMetaClassAndStructors(IORegistryPlane
, OSObject
)
97 static IORecursiveLock
* gPropertiesLock
;
98 static SInt32 gIORegistryGenerationCount
;
100 #define UNLOCK lck_rw_done( &gIORegistryLock )
101 #define RLOCK lck_rw_lock_shared( &gIORegistryLock )
102 #define WLOCK lck_rw_lock_exclusive( &gIORegistryLock ); \
103 gIORegistryGenerationCount++
106 #define PUNLOCK IORecursiveLockUnlock( gPropertiesLock )
107 #define PLOCK IORecursiveLockLock( gPropertiesLock )
109 #define IOREGSPLITTABLES
111 #ifdef IOREGSPLITTABLES
112 #define registryTable() fRegistryTable
114 #define registryTable() fPropertyTable
119 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
121 lck_rw_t gIORegistryLock
;
122 lck_grp_t
*gIORegistryLockGrp
;
123 lck_grp_attr_t
*gIORegistryLockGrpAttr
;
124 lck_attr_t
*gIORegistryLockAttr
;
127 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
129 IORegistryEntry
* IORegistryEntry::initialize( void )
133 if( !gRegistryRoot
) {
136 gIORegistryLockGrpAttr
= lck_grp_attr_alloc_init();
137 //lck_grp_attr_setstat(gIORegistryLockGrpAttr);
138 gIORegistryLockGrp
= lck_grp_alloc_init("IORegistryLock", gIORegistryLockGrpAttr
);
139 gIORegistryLockAttr
= lck_attr_alloc_init();
140 lck_attr_rw_shared_priority(gIORegistryLockAttr
);
141 //lck_attr_setdebug(gIORegistryLockAttr);
142 lck_rw_init( &gIORegistryLock
, gIORegistryLockGrp
, gIORegistryLockAttr
);
144 gRegistryRoot
= new IORegistryEntry
;
145 gPropertiesLock
= IORecursiveLockAlloc();
146 gIORegistryPlanes
= OSDictionary::withCapacity( 1 );
148 assert( gRegistryRoot
&& gPropertiesLock
149 && gIORegistryPlanes
);
150 ok
= gRegistryRoot
->init();
152 gIONameKey
= OSSymbol::withCStringNoCopy( "IOName" );
153 gIOLocationKey
= OSSymbol::withCStringNoCopy( "IOLocation" );
155 assert( ok
&& gIONameKey
&& gIOLocationKey
);
157 gRegistryRoot
->setName( "Root" );
158 gRegistryRoot
->setProperty( kIORegistryPlanesKey
, gIORegistryPlanes
);
161 return( gRegistryRoot
);
164 IORegistryEntry
* IORegistryEntry::getRegistryRoot( void )
166 return( gRegistryRoot
);
169 SInt32
IORegistryEntry::getGenerationCount( void )
171 return( gIORegistryGenerationCount
);
175 const IORegistryPlane
* IORegistryEntry::makePlane( const char * name
)
177 IORegistryPlane
* plane
;
178 const OSSymbol
* nameKey
;
179 const OSSymbol
* parentKey
;
180 const OSSymbol
* childKey
;
181 const OSSymbol
* pathNameKey
;
182 const OSSymbol
* pathLocationKey
;
183 char key
[ kIOMaxPlaneName
+ 16 ];
186 strlcpy( key
, name
, kIOMaxPlaneName
+ 1 );
187 end
= key
+ strlen( key
);
189 nameKey
= OSSymbol::withCString( key
);
191 strlcpy( end
, kIORegPlaneParentSuffix
, kIORegPlaneParentSuffixLen
+ 1 );
192 parentKey
= OSSymbol::withCString( key
);
194 strlcpy( end
, kIORegPlaneChildSuffix
, kIORegPlaneChildSuffixLen
+ 1 );
195 childKey
= OSSymbol::withCString( key
);
197 strlcpy( end
, kIORegPlaneNameSuffix
, kIORegPlaneNameSuffixLen
+ 1 );
198 pathNameKey
= OSSymbol::withCString( key
);
200 strlcpy( end
, kIORegPlaneLocationSuffix
, kIORegPlaneLocationSuffixLen
+ 1 );
201 pathLocationKey
= OSSymbol::withCString( key
);
203 plane
= new IORegistryPlane
;
205 if( plane
&& plane
->init()
206 && nameKey
&& parentKey
&& childKey
207 && pathNameKey
&& pathLocationKey
) {
209 plane
->nameKey
= nameKey
;
210 plane
->keys
[ kParentSetIndex
] = parentKey
;
211 plane
->keys
[ kChildSetIndex
] = childKey
;
212 plane
->pathNameKey
= pathNameKey
;
213 plane
->pathLocationKey
= pathLocationKey
;
216 gIORegistryPlanes
->setObject( nameKey
, plane
);
224 pathLocationKey
->release();
226 pathNameKey
->release();
228 parentKey
->release();
239 const IORegistryPlane
* IORegistryEntry::getPlane( const char * name
)
241 const IORegistryPlane
* plane
;
244 plane
= (const IORegistryPlane
*) gIORegistryPlanes
->getObject( name
);
250 bool IORegistryPlane::serialize(OSSerialize
*s
) const
252 return( nameKey
->serialize(s
) );
255 enum { kIORegCapacityIncrement
= 4 };
257 bool IORegistryEntry::init( OSDictionary
* dict
)
267 fPropertyTable
->release();
268 fPropertyTable
= dict
;
270 } else if( !fPropertyTable
) {
271 fPropertyTable
= OSDictionary::withCapacity( kIORegCapacityIncrement
);
273 fPropertyTable
->setCapacityIncrement( kIORegCapacityIncrement
);
279 #ifdef IOREGSPLITTABLES
280 if( !fRegistryTable
) {
281 fRegistryTable
= OSDictionary::withCapacity( kIORegCapacityIncrement
);
283 fRegistryTable
->setCapacityIncrement( kIORegCapacityIncrement
);
286 if( (prop
= OSDynamicCast( OSString
, getProperty( gIONameKey
)))) {
287 OSSymbol
* sym
= (OSSymbol
*)OSSymbol::withString( prop
);
288 // ok for OSSymbol too
293 #endif /* IOREGSPLITTABLES */
298 bool IORegistryEntry::init( IORegistryEntry
* old
,
299 const IORegistryPlane
* plane
)
302 IORegistryEntry
* next
;
310 fPropertyTable
= old
->getPropertyTable();
311 fPropertyTable
->retain();
312 #ifdef IOREGSPLITTABLES
313 fRegistryTable
= old
->fRegistryTable
;
314 old
->fRegistryTable
= OSDictionary::withDictionary( fRegistryTable
);
315 #endif /* IOREGSPLITTABLES */
317 old
->registryTable()->removeObject( plane
->keys
[ kParentSetIndex
] );
318 old
->registryTable()->removeObject( plane
->keys
[ kChildSetIndex
] );
320 all
= getParentSetReference( plane
);
321 if( all
) for( index
= 0;
322 (next
= (IORegistryEntry
*) all
->getObject(index
));
324 next
->makeLink( this, kChildSetIndex
, plane
);
325 next
->breakLink( old
, kChildSetIndex
, plane
);
328 all
= getChildSetReference( plane
);
329 if( all
) for( index
= 0;
330 (next
= (IORegistryEntry
*) all
->getObject(index
));
332 next
->makeLink( this, kParentSetIndex
, plane
);
333 next
->breakLink( old
, kParentSetIndex
, plane
);
341 void IORegistryEntry::free( void )
345 #define msg ": attached at free()"
346 int len
= strlen(msg
) + 40;
349 if( registryTable() && gIOServicePlane
) {
350 if( getParentSetReference( gIOServicePlane
)
351 || getChildSetReference( gIOServicePlane
)) {
353 strlcpy( buf
, getName(), 32);
354 strlcat( buf
, msg
, len
);
360 if( getPropertyTable())
361 getPropertyTable()->release();
363 #ifdef IOREGSPLITTABLES
365 registryTable()->release();
366 #endif /* IOREGSPLITTABLES */
371 void IORegistryEntry::setPropertyTable( OSDictionary
* dict
)
374 fPropertyTable
->release();
377 fPropertyTable
= dict
;
380 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
382 /* Wrappers to synchronize property table */
384 #define wrap2(type, constant) \
386 IORegistryEntry::copyProperty( type * aKey) constant \
391 obj = getProperty( aKey ); \
399 #define wrap4(type,constant) \
401 IORegistryEntry::getProperty( type * aKey, \
402 const IORegistryPlane * plane, \
403 IOOptionBits options ) constant \
405 OSObject * obj = getProperty( aKey ); \
407 if ( (0 == obj) && plane && (options & kIORegistryIterateRecursively) ) { \
408 IORegistryEntry * entry = (IORegistryEntry *) this; \
409 IORegistryIterator * iter; \
410 iter = IORegistryIterator::iterateOver( entry, plane, options ); \
413 while ( (0 == obj) && (entry = iter->getNextObject()) ) { \
414 obj = entry->getProperty( aKey ); \
423 #define wrap5(type,constant) \
425 IORegistryEntry::copyProperty( type * aKey, \
426 const IORegistryPlane * plane, \
427 IOOptionBits options ) constant \
429 OSObject * obj = copyProperty( aKey ); \
431 if ( (0 == obj) && plane && (options & kIORegistryIterateRecursively) ) { \
432 IORegistryEntry * entry = (IORegistryEntry *) this; \
433 IORegistryIterator * iter; \
434 iter = IORegistryIterator::iterateOver( entry, plane, options ); \
437 while ( (0 == obj) && (entry = iter->getNextObject()) ) { \
438 obj = entry->copyProperty( aKey ); \
447 bool IORegistryEntry::serializeProperties( OSSerialize
* s
) const
449 // setProperty( getRetainCount(), 32, "__retain" );
452 OSCollection
*snapshotProperties
= getPropertyTable()->copyCollection();
455 bool ok
= snapshotProperties
->serialize( s
);
456 snapshotProperties
->release();
460 OSDictionary
* IORegistryEntry::dictionaryWithProperties( void ) const
465 dict
= OSDictionary::withDictionary( getPropertyTable(),
466 getPropertyTable()->getCapacity() );
472 IOReturn
IORegistryEntry::setProperties( OSObject
* properties
)
474 return( kIOReturnUnsupported
);
477 wrap2(const OSSymbol
, const) // copyProperty() definition
478 wrap2(const OSString
, const) // copyProperty() definition
479 wrap2(const char, const) // copyProperty() definition
481 wrap4(const OSSymbol
, const) // getProperty() w/plane definition
482 wrap4(const OSString
, const) // getProperty() w/plane definition
483 wrap4(const char, const) // getProperty() w/plane definition
485 wrap5(const OSSymbol
, const) // copyProperty() w/plane definition
486 wrap5(const OSString
, const) // copyProperty() w/plane definition
487 wrap5(const char, const) // copyProperty() w/plane definition
491 IORegistryEntry::getProperty( const OSSymbol
* aKey
) const
496 obj
= getPropertyTable()->getObject( aKey
);
503 IORegistryEntry::removeProperty( const OSSymbol
* aKey
)
506 getPropertyTable()->removeObject( aKey
);
511 IORegistryEntry::setProperty( const OSSymbol
* aKey
, OSObject
* anObject
)
515 // If we are inserting a collection class and the current entry
516 // is attached into the registry (inPlane()) then mark the collection
518 OSCollection
*coll
= OSDynamicCast(OSCollection
, anObject
);
519 bool makeImmutable
= (coll
&& inPlane());
523 coll
->setOptions( OSCollection::kMASK
, OSCollection::kImmutable
);
525 ret
= getPropertyTable()->setObject( aKey
, anObject
);
531 IOReturn
IORegistryEntry::
532 runPropertyAction(Action inAction
, OSObject
*target
,
533 void *arg0
, void *arg1
, void *arg2
, void *arg3
)
537 // closeGate is recursive so don't worry if we already hold the lock.
539 res
= (*inAction
)(target
, arg0
, arg1
, arg2
, arg3
);
546 IORegistryEntry::getProperty( const OSString
* aKey
) const
548 const OSSymbol
* tmpKey
= OSSymbol::withString( aKey
);
549 OSObject
* obj
= getProperty( tmpKey
);
556 IORegistryEntry::getProperty( const char * aKey
) const
558 const OSSymbol
* tmpKey
= OSSymbol::withCString( aKey
);
559 OSObject
* obj
= getProperty( tmpKey
);
567 IORegistryEntry::removeProperty( const OSString
* aKey
)
569 const OSSymbol
* tmpKey
= OSSymbol::withString( aKey
);
570 removeProperty( tmpKey
);
575 IORegistryEntry::removeProperty( const char * aKey
)
577 const OSSymbol
* tmpKey
= OSSymbol::withCString( aKey
);
578 removeProperty( tmpKey
);
583 IORegistryEntry::setProperty( const OSString
* aKey
, OSObject
* anObject
)
585 const OSSymbol
* tmpKey
= OSSymbol::withString( aKey
);
586 bool ret
= setProperty( tmpKey
, anObject
);
593 IORegistryEntry::setProperty( const char * aKey
, OSObject
* anObject
)
595 const OSSymbol
* tmpKey
= OSSymbol::withCString( aKey
);
596 bool ret
= setProperty( tmpKey
, anObject
);
603 IORegistryEntry::setProperty(const char * aKey
, const char * aString
)
606 OSSymbol
* aSymbol
= (OSSymbol
*) OSSymbol::withCString( aString
);
609 const OSSymbol
* tmpKey
= OSSymbol::withCString( aKey
);
610 ret
= setProperty( tmpKey
, aSymbol
);
619 IORegistryEntry::setProperty(const char * aKey
, bool aBoolean
)
622 OSBoolean
* aBooleanObj
= OSBoolean::withBoolean( aBoolean
);
625 const OSSymbol
* tmpKey
= OSSymbol::withCString( aKey
);
626 ret
= setProperty( tmpKey
, aBooleanObj
);
629 aBooleanObj
->release();
635 IORegistryEntry::setProperty( const char * aKey
,
636 unsigned long long aValue
,
637 unsigned int aNumberOfBits
)
640 OSNumber
* anOffset
= OSNumber::withNumber( aValue
, aNumberOfBits
);
643 const OSSymbol
* tmpKey
= OSSymbol::withCString( aKey
);
644 ret
= setProperty( tmpKey
, anOffset
);
653 IORegistryEntry::setProperty( const char * aKey
,
658 OSData
* data
= OSData::withBytes( bytes
, length
);
661 const OSSymbol
* tmpKey
= OSSymbol::withCString( aKey
);
662 ret
= setProperty( tmpKey
, data
);
670 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
672 /* Name, location, paths */
674 const char * IORegistryEntry::getName( const IORegistryPlane
* plane
) const
680 sym
= (OSSymbol
*) registryTable()->getObject( plane
->pathNameKey
);
682 sym
= (OSSymbol
*) registryTable()->getObject( gIONameKey
);
686 return( sym
->getCStringNoCopy());
688 return( (getMetaClass())->getClassName());
691 const OSSymbol
* IORegistryEntry::copyName(
692 const IORegistryPlane
* plane
) const
698 sym
= (OSSymbol
*) registryTable()->getObject( plane
->pathNameKey
);
700 sym
= (OSSymbol
*) registryTable()->getObject( gIONameKey
);
708 return( OSSymbol::withCString((getMetaClass())->getClassName()) );
711 const OSSymbol
* IORegistryEntry::copyLocation(
712 const IORegistryPlane
* plane
) const
718 sym
= (OSSymbol
*) registryTable()->getObject( plane
->pathLocationKey
);
720 sym
= (OSSymbol
*) registryTable()->getObject( gIOLocationKey
);
728 const char * IORegistryEntry::getLocation( const IORegistryPlane
* plane
) const
730 const OSSymbol
* sym
= copyLocation( plane
);
731 const char * result
= 0;
734 result
= sym
->getCStringNoCopy();
741 void IORegistryEntry::setName( const OSSymbol
* name
,
742 const IORegistryPlane
* plane
)
744 const OSSymbol
* key
;
748 key
= plane
->pathNameKey
;
753 registryTable()->setObject( key
, (OSObject
*) name
);
758 void IORegistryEntry::setName( const char * name
,
759 const IORegistryPlane
* plane
)
761 OSSymbol
* sym
= (OSSymbol
*)OSSymbol::withCString( name
);
763 setName( sym
, plane
);
768 void IORegistryEntry::setLocation( const OSSymbol
* location
,
769 const IORegistryPlane
* plane
)
771 const OSSymbol
* key
;
775 key
= plane
->pathLocationKey
;
777 key
= gIOLocationKey
;
780 registryTable()->setObject( key
, (OSObject
*) location
);
785 void IORegistryEntry::setLocation( const char * location
,
786 const IORegistryPlane
* plane
)
788 OSSymbol
* sym
= (OSSymbol
*)OSSymbol::withCString( location
);
790 setLocation( sym
, plane
);
796 IORegistryEntry::compareName( OSString
* name
, OSString
** matched
) const
798 const OSSymbol
* sym
= copyName();
801 isEqual
= sym
->isEqualTo( name
);
803 if( isEqual
&& matched
) {
815 IORegistryEntry::compareNames( OSObject
* names
, OSString
** matched
) const
818 OSCollection
* collection
;
819 OSIterator
* iter
= 0;
822 if( (collection
= OSDynamicCast( OSCollection
, names
))) {
823 iter
= OSCollectionIterator::withCollection( collection
);
826 string
= OSDynamicCast( OSString
, names
);
830 result
= compareName( string
, matched
);
832 } while( (false == result
)
833 && iter
&& (string
= OSDynamicCast( OSString
, iter
->getNextObject())));
842 bool IORegistryEntry::getPath( char * path
, int * length
,
843 const IORegistryPlane
* plane
) const
846 IORegistryEntry
* root
;
847 const IORegistryEntry
* entry
;
848 IORegistryEntry
* parent
;
849 const OSSymbol
* alias
;
851 int len
, maxLength
, compLen
, aliasLen
;
855 if( !path
|| !length
|| !plane
)
859 maxLength
= *length
- 2;
862 len
= plane
->nameKey
->getLength();
863 if( len
>= maxLength
)
865 strlcpy( nextComp
, plane
->nameKey
->getCStringNoCopy(), len
+ 1);
866 nextComp
[ len
++ ] = ':';
869 if( (alias
= hasAlias( plane
))) {
870 aliasLen
= alias
->getLength();
872 ok
= (maxLength
> len
);
875 strlcpy( nextComp
, alias
->getCStringNoCopy(), aliasLen
+ 1);
880 parent
= entry
->getParentEntry( plane
);
882 // Error if not attached in plane
885 stack
= OSArray::withCapacity( getDepth( plane
));
891 root
= gRegistryRoot
->getChildEntry( plane
);
892 while( parent
&& (entry
!= root
)) {
894 stack
->setObject( (OSObject
*) entry
);
896 parent
= entry
->getParentEntry( plane
);
899 index
= stack
->getCount();
908 } else while( ok
&& ((--index
) >= 0)) {
910 entry
= (IORegistryEntry
*) stack
->getObject((unsigned int) index
);
913 if( (alias
= entry
->hasAlias( plane
))) {
914 len
= plane
->nameKey
->getLength() + 1;
915 nextComp
= path
+ len
;
917 compLen
= alias
->getLength();
918 ok
= (maxLength
> (len
+ compLen
));
920 strlcpy( nextComp
, alias
->getCStringNoCopy(), compLen
+ 1);
922 compLen
= maxLength
- len
;
923 ok
= entry
->getPathComponent( nextComp
+ 1, &compLen
, plane
);
945 bool IORegistryEntry::getPathComponent( char * path
, int * length
,
946 const IORegistryPlane
* plane
) const
948 int len
, locLen
, maxLength
;
949 const char * compName
;
955 compName
= getName( plane
);
956 len
= strlen( compName
);
957 if( (loc
= getLocation( plane
)))
958 locLen
= 1 + strlen( loc
);
962 ok
= ((len
+ locLen
+ 1) < maxLength
);
964 strlcpy( path
, compName
, len
+ 1 );
969 strlcpy( path
, loc
, locLen
);
977 const char * IORegistryEntry::matchPathLocation( const char * cmp
,
978 const IORegistryPlane
* plane
)
981 const char * result
= 0;
983 char lastPathChar
, lastLocationChar
;
985 str
= getLocation( plane
);
987 lastPathChar
= cmp
[0];
988 lastLocationChar
= str
[0];
991 num1
= strtouq( cmp
, (char **) &cmp
, 16 );
992 lastPathChar
= *cmp
++;
996 if( lastLocationChar
) {
997 num2
= strtouq( str
, (char **) &str
, 16 );
998 lastLocationChar
= *str
++;
1005 if (!lastPathChar
&& !lastLocationChar
) {
1010 if( (',' != lastPathChar
) && (':' != lastPathChar
))
1013 if (lastPathChar
&& lastLocationChar
&& (lastPathChar
!= lastLocationChar
))
1022 IORegistryEntry
* IORegistryEntry::getChildFromComponent( const char ** opath
,
1023 const IORegistryPlane
* plane
)
1025 IORegistryEntry
* entry
= 0;
1029 const char * cmp
= 0;
1034 set
= getChildSetReference( plane
);
1040 (entry
= (IORegistryEntry
*) set
->getObject(index
));
1046 str
= entry
->getName( plane
);
1047 len
= strlen( str
);
1048 if( strncmp( str
, cmp
, len
))
1053 if( (c
== 0) || (c
== '/') || (c
== ':'))
1059 if( (cmp
= entry
->matchPathLocation( cmp
, plane
)))
1069 const OSSymbol
* IORegistryEntry::hasAlias( const IORegistryPlane
* plane
,
1070 char * opath
, int * length
) const
1072 IORegistryEntry
* entry
;
1073 IORegistryEntry
* entry2
;
1074 const OSSymbol
* key
;
1075 const OSSymbol
* bestKey
= 0;
1078 const char * path
= "/aliases";
1080 entry
= IORegistryEntry::fromPath( path
, plane
);
1083 if( (iter
= OSCollectionIterator::withCollection(
1084 entry
->getPropertyTable() ))) {
1086 while( (key
= (OSSymbol
*) iter
->getNextObject())) {
1088 data
= (OSData
*) entry
->getProperty( key
);
1089 path
= (const char *) data
->getBytesNoCopy();
1090 if( (entry2
= IORegistryEntry::fromPath( path
, plane
,
1092 if( this == entry2
) {
1094 || (bestKey
->getLength() > key
->getLength()))
1095 // pick the smallest alias
1109 const char * IORegistryEntry::dealiasPath(
1110 const char ** opath
,
1111 const IORegistryPlane
* plane
)
1113 IORegistryEntry
* entry
;
1115 const char * path
= *opath
;
1116 const char * rpath
= 0;
1119 char temp
[ kIOMaxPlaneName
+ 1 ];
1126 while( (c
= *end
++) && (c
!= '/') && (c
!= ':'))
1129 if( (end
- path
) < kIOMaxPlaneName
) {
1130 strlcpy( temp
, path
, end
- path
+ 1 );
1133 entry
= IORegistryEntry::fromPath( "/aliases", plane
);
1135 data
= (OSData
*) entry
->getProperty( temp
);
1137 rpath
= (const char *) data
->getBytesNoCopy();
1149 IORegistryEntry
* IORegistryEntry::fromPath(
1151 const IORegistryPlane
* plane
,
1154 IORegistryEntry
* fromEntry
)
1156 IORegistryEntry
* where
= 0;
1157 IORegistryEntry
* aliasEntry
= 0;
1158 IORegistryEntry
* next
;
1164 char temp
[ kIOMaxPlaneName
+ 1 ];
1171 end
= strchr( path
, ':' );
1172 if( end
&& ((end
- path
) < kIOMaxPlaneName
)) {
1173 strlcpy( temp
, path
, end
- path
+ 1 );
1174 plane
= getPlane( temp
);
1183 if( (alias
= dealiasPath( &end
, plane
))) {
1186 aliasEntry
= IORegistryEntry::fromPath( alias
, plane
,
1187 opath
, &len
, fromEntry
);
1199 if( (0 == fromEntry
) && (*path
++ == '/'))
1200 fromEntry
= gRegistryRoot
->getChildEntry( plane
);
1207 if( c
&& (c
!= ':')) // check valid terminator
1212 next
= where
->getChildFromComponent( &path
, plane
);
1218 // check residual path
1219 if( where
!= fromEntry
)
1222 if( opath
&& length
) {
1223 // copy out residual path
1224 len2
= strlen( path
);
1225 if( (len
+ len2
) < *length
)
1226 strlcpy( opath
+ len
, path
, len2
+ 1 );
1227 *length
= (len
+ len2
);
1230 // no residual path => must be no tail for success
1237 aliasEntry
->release();
1244 IORegistryEntry
* IORegistryEntry::childFromPath(
1246 const IORegistryPlane
* plane
,
1250 return( IORegistryEntry::fromPath( path
, plane
, opath
, len
, this ));
1253 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1255 #define IOLinkIterator OSCollectionIterator
1258 #define super OSObject
1260 inline bool IORegistryEntry::arrayMember( OSArray
* set
,
1261 const IORegistryEntry
* member
,
1262 unsigned int * index
) const
1265 OSObject
* probeObject
;
1267 for( i
= 0; (probeObject
= set
->getObject(i
)); i
++) {
1268 if (probeObject
== (OSObject
*) member
) {
1277 bool IORegistryEntry::makeLink( IORegistryEntry
* to
,
1278 unsigned int relation
,
1279 const IORegistryPlane
* plane
) const
1282 bool result
= false;
1284 if( (links
= (OSArray
*)
1285 registryTable()->getObject( plane
->keys
[ relation
] ))) {
1287 result
= arrayMember( links
, to
);
1289 result
= links
->setObject( to
);
1293 links
= OSArray::withObjects( (const OSObject
**) &to
, 1, 1 );
1294 result
= (links
!= 0);
1296 result
= registryTable()->setObject( plane
->keys
[ relation
],
1305 void IORegistryEntry::breakLink( IORegistryEntry
* to
,
1306 unsigned int relation
,
1307 const IORegistryPlane
* plane
) const
1312 if( (links
= (OSArray
*)
1313 registryTable()->getObject( plane
->keys
[ relation
]))) {
1315 if( arrayMember( links
, to
, &index
)) {
1316 links
->removeObject( index
);
1317 if( 0 == links
->getCount())
1318 registryTable()->removeObject( plane
->keys
[ relation
]);
1324 OSArray
* IORegistryEntry::getParentSetReference(
1325 const IORegistryPlane
* plane
) const
1328 return( (OSArray
*) registryTable()->getObject(
1329 plane
->keys
[ kParentSetIndex
]));
1334 OSIterator
* IORegistryEntry::getParentIterator(
1335 const IORegistryPlane
* plane
) const
1344 links
= getParentSetReference( plane
);
1346 links
= OSArray::withCapacity( 1 );
1348 links
= OSArray::withArray( links
, links
->getCount() );
1351 iter
= IOLinkIterator::withCollection( links
);
1359 IORegistryEntry
* IORegistryEntry::copyParentEntry( const IORegistryPlane
* plane
) const
1361 IORegistryEntry
* entry
= 0;
1366 if( (links
= getParentSetReference( plane
))) {
1367 entry
= (IORegistryEntry
*) links
->getObject( 0 );
1376 IORegistryEntry
* IORegistryEntry::getParentEntry( const IORegistryPlane
* plane
) const
1378 IORegistryEntry
* entry
;
1380 entry
= copyParentEntry( plane
);
1387 OSArray
* IORegistryEntry::getChildSetReference( const IORegistryPlane
* plane
) const
1390 return( (OSArray
*) registryTable()->getObject(
1391 plane
->keys
[ kChildSetIndex
]));
1396 OSIterator
* IORegistryEntry::getChildIterator( const IORegistryPlane
* plane
) const
1405 links
= getChildSetReference( plane
);
1407 links
= OSArray::withCapacity( 1 );
1409 links
= OSArray::withArray( links
, links
->getCount() );
1412 iter
= IOLinkIterator::withCollection( links
);
1421 IORegistryEntry
* IORegistryEntry::copyChildEntry(
1422 const IORegistryPlane
* plane
) const
1424 IORegistryEntry
* entry
= 0;
1429 if( (links
= getChildSetReference( plane
))) {
1430 entry
= (IORegistryEntry
*) links
->getObject( 0 );
1439 IORegistryEntry
* IORegistryEntry::getChildEntry(
1440 const IORegistryPlane
* plane
) const
1442 IORegistryEntry
* entry
;
1444 entry
= copyChildEntry( plane
);
1451 void IORegistryEntry::applyToChildren( IORegistryEntryApplierFunction applier
,
1453 const IORegistryPlane
* plane
) const
1457 IORegistryEntry
* next
;
1463 array
= OSArray::withArray( getChildSetReference( plane
));
1467 (next
= (IORegistryEntry
*) array
->getObject( index
));
1469 (*applier
)(next
, context
);
1474 void IORegistryEntry::applyToParents( IORegistryEntryApplierFunction applier
,
1476 const IORegistryPlane
* plane
) const
1480 IORegistryEntry
* next
;
1486 array
= OSArray::withArray( getParentSetReference( plane
));
1490 (next
= (IORegistryEntry
*) array
->getObject( index
));
1492 (*applier
)(next
, context
);
1497 bool IORegistryEntry::isChild( IORegistryEntry
* child
,
1498 const IORegistryPlane
* plane
,
1499 bool onlyChild
) const
1506 if( (links
= getChildSetReference( plane
))) {
1507 if( (!onlyChild
) || (1 == links
->getCount()))
1508 ret
= arrayMember( links
, child
);
1510 if( ret
&& (links
= child
->getParentSetReference( plane
)))
1511 ret
= arrayMember( links
, this );
1518 bool IORegistryEntry::isParent( IORegistryEntry
* parent
,
1519 const IORegistryPlane
* plane
,
1520 bool onlyParent
) const
1528 if( (links
= getParentSetReference( plane
))) {
1529 if( (!onlyParent
) || (1 == links
->getCount()))
1530 ret
= arrayMember( links
, parent
);
1532 if( ret
&& (links
= parent
->getChildSetReference( plane
)))
1533 ret
= arrayMember( links
, this );
1540 bool IORegistryEntry::inPlane( const IORegistryPlane
* plane
) const
1547 ret
= (0 != getParentSetReference( plane
));
1550 // Check to see if this is in any plane. If it is in a plane
1551 // then the registryTable will contain a key with the ParentLinks
1552 // suffix. When we iterate over the keys looking for that suffix
1555 OSCollectionIterator
*iter
=
1556 OSCollectionIterator::withCollection( registryTable());
1558 const OSSymbol
*key
;
1560 while( (key
= (OSSymbol
*) iter
->getNextObject()) ) {
1563 // Get a pointer to this keys suffix
1564 keysuffix
= key
->getLength();
1565 if (keysuffix
<= kIORegPlaneParentSuffixLen
)
1567 keysuffix
-= kIORegPlaneParentSuffixLen
;
1568 if( !strncmp(key
->getCStringNoCopy() + keysuffix
,
1569 kIORegPlaneParentSuffix
,
1570 kIORegPlaneParentSuffixLen
+ 1) ) {
1584 bool IORegistryEntry::attachToParent( IORegistryEntry
* parent
,
1585 const IORegistryPlane
* plane
)
1596 ret
= makeLink( parent
, kParentSetIndex
, plane
);
1598 if( (links
= parent
->getChildSetReference( plane
)))
1599 needParent
= (false == arrayMember( links
, this ));
1607 // Mark any collections in the property list as immutable
1608 OSDictionary
*ptable
= getPropertyTable();
1609 OSCollectionIterator
*iter
=
1610 OSCollectionIterator::withCollection( ptable
);
1612 const OSSymbol
*key
;
1614 while( (key
= (OSSymbol
*) iter
->getNextObject( ))) {
1615 // Is object for key a collection?
1616 OSCollection
*coll
=
1617 OSDynamicCast( OSCollection
, ptable
->getObject( key
));
1620 // Yup so mark it as immutable
1621 coll
->setOptions( OSCollection::kMASK
,
1622 OSCollection::kImmutable
);
1631 ret
&= parent
->attachToChild( this, plane
);
1636 bool IORegistryEntry::attachToChild( IORegistryEntry
* child
,
1637 const IORegistryPlane
* plane
)
1648 ret
= makeLink( child
, kChildSetIndex
, plane
);
1650 if( (links
= child
->getParentSetReference( plane
)))
1651 needChild
= (false == arrayMember( links
, this ));
1658 ret
&= child
->attachToParent( this, plane
);
1663 void IORegistryEntry::detachFromParent( IORegistryEntry
* parent
,
1664 const IORegistryPlane
* plane
)
1673 breakLink( parent
, kParentSetIndex
, plane
);
1675 if( (links
= parent
->getChildSetReference( plane
)))
1676 needParent
= arrayMember( links
, this );
1680 // parent->breakLink( this, kChildSetIndex, plane );
1685 parent
->detachFromChild( this, plane
);
1690 void IORegistryEntry::detachFromChild( IORegistryEntry
* child
,
1691 const IORegistryPlane
* plane
)
1700 breakLink( child
, kChildSetIndex
, plane
);
1702 if( (links
= child
->getParentSetReference( plane
)))
1703 needChild
= arrayMember( links
, this );
1710 child
->detachFromParent( this, plane
);
1715 void IORegistryEntry::detachAbove( const IORegistryPlane
* plane
)
1717 IORegistryEntry
* parent
;
1720 while( (parent
= getParentEntry( plane
)))
1721 detachFromParent( parent
, plane
);
1725 void IORegistryEntry::detachAll( const IORegistryPlane
* plane
)
1728 IORegistryEntry
* next
;
1729 IORegistryIterator
* regIter
;
1731 regIter
= IORegistryIterator::iterateOver( this, plane
, true );
1734 all
= regIter
->iterateAll();
1737 detachAbove( plane
);
1739 while( (next
= (IORegistryEntry
*) all
->getLastObject())) {
1742 all
->removeObject(next
);
1744 next
->detachAbove( plane
);
1751 unsigned int IORegistryEntry::getDepth( const IORegistryPlane
* plane
) const
1753 unsigned int depth
= 1;
1755 unsigned int oneDepth
, maxParentDepth
, count
;
1756 IORegistryEntry
* one
;
1757 const IORegistryEntry
* next
;
1763 while( (parents
= next
->getParentSetReference( plane
))) {
1765 count
= parents
->getCount();
1770 next
= (IORegistryEntry
*) parents
->getObject( 0 );
1775 (one
= (IORegistryEntry
*) parents
->getObject( index
));
1777 oneDepth
= one
->getDepth( plane
);
1778 if( oneDepth
> maxParentDepth
)
1779 maxParentDepth
= oneDepth
;
1781 depth
+= maxParentDepth
;
1791 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1794 #define super OSIterator
1796 OSDefineMetaClassAndStructors(IORegistryIterator
, OSIterator
)
1798 enum { kIORegistryIteratorInvalidFlag
= 0x80000000 };
1800 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1802 IORegistryIterator
*
1803 IORegistryIterator::iterateOver( IORegistryEntry
* root
,
1804 const IORegistryPlane
* plane
,
1805 IOOptionBits options
)
1807 IORegistryIterator
* create
;
1814 create
= new IORegistryIterator
;
1816 if( create
->init()) {
1819 create
->root
= root
;
1820 create
->where
= &create
->start
;
1821 create
->start
.current
= root
;
1822 create
->plane
= plane
;
1823 create
->options
= options
& ~kIORegistryIteratorInvalidFlag
;
1833 IORegistryIterator
*
1834 IORegistryIterator::iterateOver( const IORegistryPlane
* plane
,
1835 IOOptionBits options
)
1837 return( iterateOver( gRegistryRoot
, plane
, options
));
1840 bool IORegistryIterator::isValid( void )
1849 ok
= (0 == (kIORegistryIteratorInvalidFlag
& options
));
1851 while( ok
&& next
) {
1853 ok
= where
->iter
->isValid();
1861 void IORegistryIterator::enterEntry( const IORegistryPlane
* enterPlane
)
1866 where
= (IORegCursor
*) IOMalloc( sizeof(IORegCursor
));
1872 where
->current
= prev
->current
;
1877 void IORegistryIterator::enterEntry( void )
1879 enterEntry( plane
);
1882 bool IORegistryIterator::exitEntry( void )
1887 where
->iter
->release();
1889 if( where
->current
)// && (where != &start))
1890 where
->current
->release();
1893 if( where
!= &start
) {
1896 IOFree( gone
, sizeof(IORegCursor
));
1903 void IORegistryIterator::reset( void )
1913 where
->current
= root
;
1914 options
&= ~kIORegistryIteratorInvalidFlag
;
1917 void IORegistryIterator::free( void )
1928 IORegistryEntry
* IORegistryIterator::getNextObjectFlat( void )
1930 IORegistryEntry
* next
= 0;
1931 OSArray
* links
= 0;
1935 if( (0 == where
->iter
)) {
1936 // just entered - create new iter
1939 && (links
= ( (options
& kIORegistryIterateParents
) ?
1940 where
->current
->getParentSetReference( plane
) :
1941 where
->current
->getChildSetReference( plane
) )) )
1943 where
->iter
= OSCollectionIterator::withCollection( links
);
1946 // next sibling - release current
1948 where
->current
->release();
1952 next
= (IORegistryEntry
*) where
->iter
->getNextObject();
1956 else if( !where
->iter
->isValid())
1957 options
|= kIORegistryIteratorInvalidFlag
;
1960 where
->current
= next
;
1967 IORegistryEntry
* IORegistryIterator::getNextObjectRecursive( void )
1969 IORegistryEntry
* next
;
1972 next
= getNextObjectFlat();
1973 while( (0 == next
) && exitEntry());
1977 done
= OSOrderedSet::withCapacity( 10 );
1978 if( done
->setObject((OSObject
*) next
)) {
1979 // done set didn't contain this one, so recurse
1986 IORegistryEntry
* IORegistryIterator::getNextObject( void )
1988 if( options
& kIORegistryIterateRecursively
)
1989 return( getNextObjectRecursive());
1991 return( getNextObjectFlat());
1994 IORegistryEntry
* IORegistryIterator::getCurrentEntry( void )
1997 return( where
->current
);
2002 OSOrderedSet
* IORegistryIterator::iterateAll( void )
2005 while( getNextObjectRecursive())
2012 OSMetaClassDefineReservedUsed(IORegistryEntry
, 0);
2013 OSMetaClassDefineReservedUsed(IORegistryEntry
, 1);
2014 OSMetaClassDefineReservedUsed(IORegistryEntry
, 2);
2015 OSMetaClassDefineReservedUsed(IORegistryEntry
, 3);
2016 OSMetaClassDefineReservedUsed(IORegistryEntry
, 4);
2017 OSMetaClassDefineReservedUsed(IORegistryEntry
, 5);
2019 OSMetaClassDefineReservedUnused(IORegistryEntry
, 6);
2020 OSMetaClassDefineReservedUnused(IORegistryEntry
, 7);
2021 OSMetaClassDefineReservedUnused(IORegistryEntry
, 8);
2022 OSMetaClassDefineReservedUnused(IORegistryEntry
, 9);
2023 OSMetaClassDefineReservedUnused(IORegistryEntry
, 10);
2024 OSMetaClassDefineReservedUnused(IORegistryEntry
, 11);
2025 OSMetaClassDefineReservedUnused(IORegistryEntry
, 12);
2026 OSMetaClassDefineReservedUnused(IORegistryEntry
, 13);
2027 OSMetaClassDefineReservedUnused(IORegistryEntry
, 14);
2028 OSMetaClassDefineReservedUnused(IORegistryEntry
, 15);
2029 OSMetaClassDefineReservedUnused(IORegistryEntry
, 16);
2030 OSMetaClassDefineReservedUnused(IORegistryEntry
, 17);
2031 OSMetaClassDefineReservedUnused(IORegistryEntry
, 18);
2032 OSMetaClassDefineReservedUnused(IORegistryEntry
, 19);
2033 OSMetaClassDefineReservedUnused(IORegistryEntry
, 20);
2034 OSMetaClassDefineReservedUnused(IORegistryEntry
, 21);
2035 OSMetaClassDefineReservedUnused(IORegistryEntry
, 22);
2036 OSMetaClassDefineReservedUnused(IORegistryEntry
, 23);
2037 OSMetaClassDefineReservedUnused(IORegistryEntry
, 24);
2038 OSMetaClassDefineReservedUnused(IORegistryEntry
, 25);
2039 OSMetaClassDefineReservedUnused(IORegistryEntry
, 26);
2040 OSMetaClassDefineReservedUnused(IORegistryEntry
, 27);
2041 OSMetaClassDefineReservedUnused(IORegistryEntry
, 28);
2042 OSMetaClassDefineReservedUnused(IORegistryEntry
, 29);
2043 OSMetaClassDefineReservedUnused(IORegistryEntry
, 30);
2044 OSMetaClassDefineReservedUnused(IORegistryEntry
, 31);
2046 /* inline function implementation */
2047 OSDictionary
* IORegistryEntry::getPropertyTable( void ) const
2048 { return(fPropertyTable
); }