2 * Copyright (c) 1998-2000 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"
57 #define kIORegPlaneParentSuffixLen (sizeof(kIORegPlaneParentSuffix) - 1)
59 static IORegistryEntry
* gRegistryRoot
;
60 static OSDictionary
* gIORegistryPlanes
;
62 const OSSymbol
* gIONameKey
;
63 const OSSymbol
* gIOLocationKey
;
74 class IORegistryPlane
: public OSObject
{
76 friend class IORegistryEntry
;
78 OSDeclareAbstractStructors(IORegistryPlane
)
80 const OSSymbol
* nameKey
;
81 const OSSymbol
* keys
[ kNumSetIndex
];
82 const OSSymbol
* pathNameKey
;
83 const OSSymbol
* pathLocationKey
;
87 virtual bool serialize(OSSerialize
*s
) const;
90 OSDefineMetaClassAndStructors(IORegistryPlane
, OSObject
)
93 static IORecursiveLock
* gPropertiesLock
;
94 static SInt32 gIORegistryGenerationCount
;
96 #define UNLOCK lck_rw_done( &gIORegistryLock )
97 #define RLOCK lck_rw_lock_shared( &gIORegistryLock )
98 #define WLOCK lck_rw_lock_exclusive( &gIORegistryLock ); \
99 gIORegistryGenerationCount++
102 #define PUNLOCK IORecursiveLockUnlock( gPropertiesLock )
103 #define PLOCK IORecursiveLockLock( gPropertiesLock )
105 #define IOREGSPLITTABLES
107 #ifdef IOREGSPLITTABLES
108 #define registryTable() fRegistryTable
110 #define registryTable() fPropertyTable
115 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
117 lck_rw_t gIORegistryLock
;
118 lck_grp_t
*gIORegistryLockGrp
;
119 lck_grp_attr_t
*gIORegistryLockGrpAttr
;
120 lck_attr_t
*gIORegistryLockAttr
;
123 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
125 IORegistryEntry
* IORegistryEntry::initialize( void )
129 if( !gRegistryRoot
) {
132 gIORegistryLockGrpAttr
= lck_grp_attr_alloc_init();
133 //lck_grp_attr_setstat(gIORegistryLockGrpAttr);
134 gIORegistryLockGrp
= lck_grp_alloc_init("IORegistryLock", gIORegistryLockGrpAttr
);
135 gIORegistryLockAttr
= lck_attr_alloc_init();
136 lck_attr_rw_shared_priority(gIORegistryLockAttr
);
137 //lck_attr_setdebug(gIORegistryLockAttr);
138 lck_rw_init( &gIORegistryLock
, gIORegistryLockGrp
, gIORegistryLockAttr
);
140 gRegistryRoot
= new IORegistryEntry
;
141 gPropertiesLock
= IORecursiveLockAlloc();
142 gIORegistryPlanes
= OSDictionary::withCapacity( 1 );
144 assert( gRegistryRoot
&& gPropertiesLock
145 && gIORegistryPlanes
);
146 ok
= gRegistryRoot
->init();
148 gIONameKey
= OSSymbol::withCStringNoCopy( "IOName" );
149 gIOLocationKey
= OSSymbol::withCStringNoCopy( "IOLocation" );
151 assert( ok
&& gIONameKey
&& gIOLocationKey
);
153 gRegistryRoot
->setName( "Root" );
154 gRegistryRoot
->setProperty( kIORegistryPlanesKey
, gIORegistryPlanes
);
157 return( gRegistryRoot
);
160 IORegistryEntry
* IORegistryEntry::getRegistryRoot( void )
162 return( gRegistryRoot
);
165 SInt32
IORegistryEntry::getGenerationCount( void )
167 return( gIORegistryGenerationCount
);
171 const IORegistryPlane
* IORegistryEntry::makePlane( const char * name
)
173 IORegistryPlane
* plane
;
174 const OSSymbol
* nameKey
;
175 const OSSymbol
* parentKey
;
176 const OSSymbol
* childKey
;
177 const OSSymbol
* pathNameKey
;
178 const OSSymbol
* pathLocationKey
;
179 char key
[ kIOMaxPlaneName
+ 16 ];
182 strncpy( key
, name
, kIOMaxPlaneName
);
183 key
[ kIOMaxPlaneName
] = 0;
184 end
= key
+ strlen( name
);
186 nameKey
= OSSymbol::withCString( key
);
188 strcpy( end
, kIORegPlaneParentSuffix
);
189 parentKey
= OSSymbol::withCString( key
);
191 strcpy( end
, kIORegPlaneChildSuffix
);
192 childKey
= OSSymbol::withCString( key
);
194 strcpy( end
, kIORegPlaneNameSuffix
);
195 pathNameKey
= OSSymbol::withCString( key
);
197 strcpy( end
, kIORegPlaneLocationSuffix
);
198 pathLocationKey
= OSSymbol::withCString( key
);
200 plane
= new IORegistryPlane
;
202 if( plane
&& plane
->init()
203 && nameKey
&& parentKey
&& childKey
204 && pathNameKey
&& pathLocationKey
) {
206 plane
->nameKey
= nameKey
;
207 plane
->keys
[ kParentSetIndex
] = parentKey
;
208 plane
->keys
[ kChildSetIndex
] = childKey
;
209 plane
->pathNameKey
= pathNameKey
;
210 plane
->pathLocationKey
= pathLocationKey
;
213 gIORegistryPlanes
->setObject( nameKey
, plane
);
221 pathLocationKey
->release();
223 pathNameKey
->release();
225 parentKey
->release();
236 const IORegistryPlane
* IORegistryEntry::getPlane( const char * name
)
238 const IORegistryPlane
* plane
;
241 plane
= (const IORegistryPlane
*) gIORegistryPlanes
->getObject( name
);
247 bool IORegistryPlane::serialize(OSSerialize
*s
) const
249 return( nameKey
->serialize(s
) );
252 enum { kIORegCapacityIncrement
= 4 };
254 bool IORegistryEntry::init( OSDictionary
* dict
)
264 fPropertyTable
->release();
265 fPropertyTable
= dict
;
267 } else if( !fPropertyTable
) {
268 fPropertyTable
= OSDictionary::withCapacity( kIORegCapacityIncrement
);
270 fPropertyTable
->setCapacityIncrement( kIORegCapacityIncrement
);
276 #ifdef IOREGSPLITTABLES
277 if( !fRegistryTable
) {
278 fRegistryTable
= OSDictionary::withCapacity( kIORegCapacityIncrement
);
280 fRegistryTable
->setCapacityIncrement( kIORegCapacityIncrement
);
283 if( (prop
= OSDynamicCast( OSString
, getProperty( gIONameKey
)))) {
284 OSSymbol
* sym
= (OSSymbol
*)OSSymbol::withString( prop
);
285 // ok for OSSymbol too
290 #endif /* IOREGSPLITTABLES */
295 bool IORegistryEntry::init( IORegistryEntry
* old
,
296 const IORegistryPlane
* plane
)
299 IORegistryEntry
* next
;
307 fPropertyTable
= old
->getPropertyTable();
308 fPropertyTable
->retain();
309 #ifdef IOREGSPLITTABLES
310 fRegistryTable
= old
->fRegistryTable
;
311 old
->fRegistryTable
= OSDictionary::withDictionary( fRegistryTable
);
312 #endif /* IOREGSPLITTABLES */
314 old
->registryTable()->removeObject( plane
->keys
[ kParentSetIndex
] );
315 old
->registryTable()->removeObject( plane
->keys
[ kChildSetIndex
] );
317 all
= getParentSetReference( plane
);
318 if( all
) for( index
= 0;
319 (next
= (IORegistryEntry
*) all
->getObject(index
));
321 next
->makeLink( this, kChildSetIndex
, plane
);
322 next
->breakLink( old
, kChildSetIndex
, plane
);
325 all
= getChildSetReference( plane
);
326 if( all
) for( index
= 0;
327 (next
= (IORegistryEntry
*) all
->getObject(index
));
329 next
->makeLink( this, kParentSetIndex
, plane
);
330 next
->breakLink( old
, kParentSetIndex
, plane
);
338 void IORegistryEntry::free( void )
342 #define msg ": attached at free()"
343 char buf
[ strlen(msg
) + 40 ];
345 if( registryTable() && gIOServicePlane
) {
346 if( getParentSetReference( gIOServicePlane
)
347 || getChildSetReference( gIOServicePlane
)) {
349 strncpy( buf
, getName(), 32);
357 if( getPropertyTable())
358 getPropertyTable()->release();
360 #ifdef IOREGSPLITTABLES
362 registryTable()->release();
363 #endif /* IOREGSPLITTABLES */
368 void IORegistryEntry::setPropertyTable( OSDictionary
* dict
)
371 fPropertyTable
->release();
374 fPropertyTable
= dict
;
377 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
379 /* Wrappers to synchronize property table */
381 #define wrap2(type, constant) \
383 IORegistryEntry::copyProperty( type * aKey) constant \
388 obj = getProperty( aKey ); \
396 #define wrap4(type,constant) \
398 IORegistryEntry::getProperty( type * aKey, \
399 const IORegistryPlane * plane, \
400 IOOptionBits options ) constant \
402 OSObject * obj = getProperty( aKey ); \
404 if ( (0 == obj) && plane && (options & kIORegistryIterateRecursively) ) { \
405 IORegistryEntry * entry = (IORegistryEntry *) this; \
406 IORegistryIterator * iter; \
407 iter = IORegistryIterator::iterateOver( entry, plane, options ); \
410 while ( (0 == obj) && (entry = iter->getNextObject()) ) { \
411 obj = entry->getProperty( aKey ); \
420 #define wrap5(type,constant) \
422 IORegistryEntry::copyProperty( type * aKey, \
423 const IORegistryPlane * plane, \
424 IOOptionBits options ) constant \
426 OSObject * obj = copyProperty( 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->copyProperty( aKey ); \
444 bool IORegistryEntry::serializeProperties( OSSerialize
* s
) const
446 // setProperty( getRetainCount(), 32, "__retain" );
449 OSCollection
*snapshotProperties
= getPropertyTable()->copyCollection();
452 bool ok
= snapshotProperties
->serialize( s
);
453 snapshotProperties
->release();
457 OSDictionary
* IORegistryEntry::dictionaryWithProperties( void ) const
462 dict
= OSDictionary::withDictionary( getPropertyTable(),
463 getPropertyTable()->getCapacity() );
469 IOReturn
IORegistryEntry::setProperties( OSObject
* properties
)
471 return( kIOReturnUnsupported
);
474 wrap2(const OSSymbol
, const) // copyProperty() definition
475 wrap2(const OSString
, const) // copyProperty() definition
476 wrap2(const char, const) // copyProperty() definition
478 wrap4(const OSSymbol
, const) // getProperty() w/plane definition
479 wrap4(const OSString
, const) // getProperty() w/plane definition
480 wrap4(const char, const) // getProperty() w/plane definition
482 wrap5(const OSSymbol
, const) // copyProperty() w/plane definition
483 wrap5(const OSString
, const) // copyProperty() w/plane definition
484 wrap5(const char, const) // copyProperty() w/plane definition
488 IORegistryEntry::getProperty( const OSSymbol
* aKey
) const
493 obj
= getPropertyTable()->getObject( aKey
);
500 IORegistryEntry::removeProperty( const OSSymbol
* aKey
)
503 getPropertyTable()->removeObject( aKey
);
508 IORegistryEntry::setProperty( const OSSymbol
* aKey
, OSObject
* anObject
)
512 // If we are inserting a collection class and the current entry
513 // is attached into the registry (inPlane()) then mark the collection
515 OSCollection
*coll
= OSDynamicCast(OSCollection
, anObject
);
516 bool makeImmutable
= (coll
&& inPlane());
520 coll
->setOptions( OSCollection::kMASK
, OSCollection::kImmutable
);
522 ret
= getPropertyTable()->setObject( aKey
, anObject
);
528 IOReturn
IORegistryEntry::
529 runPropertyAction(Action inAction
, OSObject
*target
,
530 void *arg0
, void *arg1
, void *arg2
, void *arg3
)
534 // closeGate is recursive so don't worry if we already hold the lock.
536 res
= (*inAction
)(target
, arg0
, arg1
, arg2
, arg3
);
543 IORegistryEntry::getProperty( const OSString
* aKey
) const
545 const OSSymbol
* tmpKey
= OSSymbol::withString( aKey
);
546 OSObject
* obj
= getProperty( tmpKey
);
553 IORegistryEntry::getProperty( const char * aKey
) const
555 const OSSymbol
* tmpKey
= OSSymbol::withCString( aKey
);
556 OSObject
* obj
= getProperty( tmpKey
);
564 IORegistryEntry::removeProperty( const OSString
* aKey
)
566 const OSSymbol
* tmpKey
= OSSymbol::withString( aKey
);
567 removeProperty( tmpKey
);
572 IORegistryEntry::removeProperty( const char * aKey
)
574 const OSSymbol
* tmpKey
= OSSymbol::withCString( aKey
);
575 removeProperty( tmpKey
);
580 IORegistryEntry::setProperty( const OSString
* aKey
, OSObject
* anObject
)
582 const OSSymbol
* tmpKey
= OSSymbol::withString( aKey
);
583 bool ret
= setProperty( tmpKey
, anObject
);
590 IORegistryEntry::setProperty( const char * aKey
, OSObject
* anObject
)
592 const OSSymbol
* tmpKey
= OSSymbol::withCString( aKey
);
593 bool ret
= setProperty( tmpKey
, anObject
);
600 IORegistryEntry::setProperty(const char * aKey
, const char * aString
)
603 OSSymbol
* aSymbol
= (OSSymbol
*) OSSymbol::withCString( aString
);
606 const OSSymbol
* tmpKey
= OSSymbol::withCString( aKey
);
607 ret
= setProperty( tmpKey
, aSymbol
);
616 IORegistryEntry::setProperty(const char * aKey
, bool aBoolean
)
619 OSBoolean
* aBooleanObj
= OSBoolean::withBoolean( aBoolean
);
622 const OSSymbol
* tmpKey
= OSSymbol::withCString( aKey
);
623 ret
= setProperty( tmpKey
, aBooleanObj
);
626 aBooleanObj
->release();
632 IORegistryEntry::setProperty( const char * aKey
,
633 unsigned long long aValue
,
634 unsigned int aNumberOfBits
)
637 OSNumber
* anOffset
= OSNumber::withNumber( aValue
, aNumberOfBits
);
640 const OSSymbol
* tmpKey
= OSSymbol::withCString( aKey
);
641 ret
= setProperty( tmpKey
, anOffset
);
650 IORegistryEntry::setProperty( const char * aKey
,
655 OSData
* data
= OSData::withBytes( bytes
, length
);
658 const OSSymbol
* tmpKey
= OSSymbol::withCString( aKey
);
659 ret
= setProperty( tmpKey
, data
);
667 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
669 /* Name, location, paths */
671 const char * IORegistryEntry::getName( const IORegistryPlane
* plane
) const
677 sym
= (OSSymbol
*) registryTable()->getObject( plane
->pathNameKey
);
679 sym
= (OSSymbol
*) registryTable()->getObject( gIONameKey
);
683 return( sym
->getCStringNoCopy());
685 return( (getMetaClass())->getClassName());
688 const OSSymbol
* IORegistryEntry::copyName(
689 const IORegistryPlane
* plane
) const
695 sym
= (OSSymbol
*) registryTable()->getObject( plane
->pathNameKey
);
697 sym
= (OSSymbol
*) registryTable()->getObject( gIONameKey
);
705 return( OSSymbol::withCString((getMetaClass())->getClassName()) );
708 const OSSymbol
* IORegistryEntry::copyLocation(
709 const IORegistryPlane
* plane
) const
715 sym
= (OSSymbol
*) registryTable()->getObject( plane
->pathLocationKey
);
717 sym
= (OSSymbol
*) registryTable()->getObject( gIOLocationKey
);
725 const char * IORegistryEntry::getLocation( const IORegistryPlane
* plane
) const
727 const OSSymbol
* sym
= copyLocation( plane
);
728 const char * result
= 0;
731 result
= sym
->getCStringNoCopy();
738 void IORegistryEntry::setName( const OSSymbol
* name
,
739 const IORegistryPlane
* plane
)
741 const OSSymbol
* key
;
745 key
= plane
->pathNameKey
;
750 registryTable()->setObject( key
, (OSObject
*) name
);
755 void IORegistryEntry::setName( const char * name
,
756 const IORegistryPlane
* plane
)
758 OSSymbol
* sym
= (OSSymbol
*)OSSymbol::withCString( name
);
760 setName( sym
, plane
);
765 void IORegistryEntry::setLocation( const OSSymbol
* location
,
766 const IORegistryPlane
* plane
)
768 const OSSymbol
* key
;
772 key
= plane
->pathLocationKey
;
774 key
= gIOLocationKey
;
777 registryTable()->setObject( key
, (OSObject
*) location
);
782 void IORegistryEntry::setLocation( const char * location
,
783 const IORegistryPlane
* plane
)
785 OSSymbol
* sym
= (OSSymbol
*)OSSymbol::withCString( location
);
787 setLocation( sym
, plane
);
793 IORegistryEntry::compareName( OSString
* name
, OSString
** matched
) const
795 const OSSymbol
* sym
= copyName();
798 isEqual
= sym
->isEqualTo( name
);
800 if( isEqual
&& matched
) {
812 IORegistryEntry::compareNames( OSObject
* names
, OSString
** matched
) const
815 OSCollection
* collection
;
816 OSIterator
* iter
= 0;
819 if( (collection
= OSDynamicCast( OSCollection
, names
))) {
820 iter
= OSCollectionIterator::withCollection( collection
);
823 string
= OSDynamicCast( OSString
, names
);
827 result
= compareName( string
, matched
);
829 } while( (false == result
)
830 && iter
&& (string
= OSDynamicCast( OSString
, iter
->getNextObject())));
839 bool IORegistryEntry::getPath( char * path
, int * length
,
840 const IORegistryPlane
* plane
) const
843 IORegistryEntry
* root
;
844 const IORegistryEntry
* entry
;
845 IORegistryEntry
* parent
;
846 const OSSymbol
* alias
;
848 int len
, maxLength
, compLen
;
852 if( !path
|| !length
|| !plane
)
856 maxLength
= *length
- 2;
859 len
= plane
->nameKey
->getLength();
860 if( len
>= maxLength
)
862 strcpy( nextComp
, plane
->nameKey
->getCStringNoCopy());
863 nextComp
[ len
++ ] = ':';
866 if( (alias
= hasAlias( plane
))) {
867 len
+= alias
->getLength();
868 ok
= (maxLength
> len
);
871 strcpy( nextComp
, alias
->getCStringNoCopy());
876 parent
= entry
->getParentEntry( plane
);
878 // Error if not attached in plane
881 stack
= OSArray::withCapacity( getDepth( plane
));
887 root
= gRegistryRoot
->getChildEntry( plane
);
888 while( parent
&& (entry
!= root
)) {
890 stack
->setObject( (OSObject
*) entry
);
892 parent
= entry
->getParentEntry( plane
);
895 index
= stack
->getCount();
904 } else while( ok
&& ((--index
) >= 0)) {
906 entry
= (IORegistryEntry
*) stack
->getObject((unsigned int) index
);
909 if( (alias
= entry
->hasAlias( plane
))) {
910 len
= plane
->nameKey
->getLength() + 1;
911 nextComp
= path
+ len
;
913 compLen
= alias
->getLength();
914 ok
= (maxLength
> len
+ compLen
);
916 strcpy( nextComp
, alias
->getCStringNoCopy());
918 compLen
= maxLength
- len
;
919 ok
= entry
->getPathComponent( nextComp
+ 1, &compLen
, plane
);
941 bool IORegistryEntry::getPathComponent( char * path
, int * length
,
942 const IORegistryPlane
* plane
) const
944 int len
, locLen
, maxLength
;
945 const char * compName
;
951 compName
= getName( plane
);
952 len
= strlen( compName
);
953 if( (loc
= getLocation( plane
)))
954 locLen
= 1 + strlen( loc
);
958 ok
= ((len
+ locLen
) < maxLength
);
960 strcpy( path
, compName
);
973 const char * IORegistryEntry::matchPathLocation( const char * cmp
,
974 const IORegistryPlane
* plane
)
977 const char * result
= 0;
979 char lastPathChar
, lastLocationChar
;
981 str
= getLocation( plane
);
983 lastPathChar
= cmp
[0];
984 lastLocationChar
= str
[0];
987 num1
= strtouq( cmp
, (char **) &cmp
, 16 );
988 lastPathChar
= *cmp
++;
992 if( lastLocationChar
) {
993 num2
= strtouq( str
, (char **) &str
, 16 );
994 lastLocationChar
= *str
++;
1001 if (!lastPathChar
&& !lastLocationChar
) {
1006 if( (',' != lastPathChar
) && (':' != lastPathChar
))
1009 if (lastPathChar
&& lastLocationChar
&& (lastPathChar
!= lastLocationChar
))
1018 IORegistryEntry
* IORegistryEntry::getChildFromComponent( const char ** opath
,
1019 const IORegistryPlane
* plane
)
1021 IORegistryEntry
* entry
= 0;
1025 const char * cmp
= 0;
1030 set
= getChildSetReference( plane
);
1036 (entry
= (IORegistryEntry
*) set
->getObject(index
));
1042 str
= entry
->getName( plane
);
1043 len
= strlen( str
);
1044 if( strncmp( str
, cmp
, len
))
1049 if( (c
== 0) || (c
== '/') || (c
== ':'))
1055 if( (cmp
= entry
->matchPathLocation( cmp
, plane
)))
1065 const OSSymbol
* IORegistryEntry::hasAlias( const IORegistryPlane
* plane
,
1066 char * opath
, int * length
) const
1068 IORegistryEntry
* entry
;
1069 IORegistryEntry
* entry2
;
1070 const OSSymbol
* key
;
1071 const OSSymbol
* bestKey
= 0;
1074 const char * path
= "/aliases";
1076 entry
= IORegistryEntry::fromPath( path
, plane
);
1079 if( (iter
= OSCollectionIterator::withCollection(
1080 entry
->getPropertyTable() ))) {
1082 while( (key
= (OSSymbol
*) iter
->getNextObject())) {
1084 data
= (OSData
*) entry
->getProperty( key
);
1085 path
= (const char *) data
->getBytesNoCopy();
1086 if( (entry2
= IORegistryEntry::fromPath( path
, plane
,
1088 if( this == entry2
) {
1090 || (bestKey
->getLength() > key
->getLength()))
1091 // pick the smallest alias
1105 const char * IORegistryEntry::dealiasPath(
1106 const char ** opath
,
1107 const IORegistryPlane
* plane
)
1109 IORegistryEntry
* entry
;
1111 const char * path
= *opath
;
1112 const char * rpath
= 0;
1115 char temp
[ kIOMaxPlaneName
+ 1 ];
1122 while( (c
= *end
++) && (c
!= '/') && (c
!= ':'))
1125 if( (end
- path
) < kIOMaxPlaneName
) {
1126 strncpy( temp
, path
, end
- path
);
1127 temp
[ end
- path
] = 0;
1130 entry
= IORegistryEntry::fromPath( "/aliases", plane
);
1132 data
= (OSData
*) entry
->getProperty( temp
);
1134 rpath
= (const char *) data
->getBytesNoCopy();
1146 IORegistryEntry
* IORegistryEntry::fromPath(
1148 const IORegistryPlane
* plane
,
1151 IORegistryEntry
* fromEntry
)
1153 IORegistryEntry
* where
= 0;
1154 IORegistryEntry
* aliasEntry
= 0;
1155 IORegistryEntry
* next
;
1161 char temp
[ kIOMaxPlaneName
+ 1 ];
1168 end
= strchr( path
, ':' );
1169 if( end
&& ((end
- path
) < kIOMaxPlaneName
)) {
1170 strncpy( temp
, path
, end
- path
);
1171 temp
[ end
- path
] = 0;
1172 plane
= getPlane( temp
);
1181 if( (alias
= dealiasPath( &end
, plane
))) {
1184 aliasEntry
= IORegistryEntry::fromPath( alias
, plane
,
1185 opath
, &len
, fromEntry
);
1197 if( (0 == fromEntry
) && (*path
++ == '/'))
1198 fromEntry
= gRegistryRoot
->getChildEntry( plane
);
1205 if( c
&& (c
!= ':')) // check valid terminator
1210 next
= where
->getChildFromComponent( &path
, plane
);
1216 // check residual path
1217 if( where
!= fromEntry
)
1220 if( opath
&& length
) {
1221 // copy out residual path
1222 len2
= len
+ strlen( path
);
1224 strcpy( opath
+ len
, path
);
1228 // no residual path => must be no tail for success
1235 aliasEntry
->release();
1242 IORegistryEntry
* IORegistryEntry::childFromPath(
1244 const IORegistryPlane
* plane
,
1248 return( IORegistryEntry::fromPath( path
, plane
, opath
, len
, this ));
1251 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1253 #define IOLinkIterator OSCollectionIterator
1256 #define super OSObject
1258 inline bool IORegistryEntry::arrayMember( OSArray
* set
,
1259 const IORegistryEntry
* member
,
1260 unsigned int * index
) const
1263 OSObject
* probeObject
;
1265 for( i
= 0; (probeObject
= set
->getObject(i
)); i
++) {
1266 if (probeObject
== (OSObject
*) member
) {
1275 bool IORegistryEntry::makeLink( IORegistryEntry
* to
,
1276 unsigned int relation
,
1277 const IORegistryPlane
* plane
) const
1280 bool result
= false;
1282 if( (links
= (OSArray
*)
1283 registryTable()->getObject( plane
->keys
[ relation
] ))) {
1285 result
= arrayMember( links
, to
);
1287 result
= links
->setObject( to
);
1291 links
= OSArray::withObjects( (const OSObject
**) &to
, 1, 1 );
1292 result
= (links
!= 0);
1294 result
= registryTable()->setObject( plane
->keys
[ relation
],
1303 void IORegistryEntry::breakLink( IORegistryEntry
* to
,
1304 unsigned int relation
,
1305 const IORegistryPlane
* plane
) const
1310 if( (links
= (OSArray
*)
1311 registryTable()->getObject( plane
->keys
[ relation
]))) {
1313 if( arrayMember( links
, to
, &index
)) {
1314 links
->removeObject( index
);
1315 if( 0 == links
->getCount())
1316 registryTable()->removeObject( plane
->keys
[ relation
]);
1322 OSArray
* IORegistryEntry::getParentSetReference(
1323 const IORegistryPlane
* plane
) const
1326 return( (OSArray
*) registryTable()->getObject(
1327 plane
->keys
[ kParentSetIndex
]));
1332 OSIterator
* IORegistryEntry::getParentIterator(
1333 const IORegistryPlane
* plane
) const
1342 links
= getParentSetReference( plane
);
1344 links
= OSArray::withCapacity( 1 );
1346 links
= OSArray::withArray( links
, links
->getCount() );
1349 iter
= IOLinkIterator::withCollection( links
);
1357 IORegistryEntry
* IORegistryEntry::copyParentEntry( const IORegistryPlane
* plane
) const
1359 IORegistryEntry
* entry
= 0;
1364 if( (links
= getParentSetReference( plane
))) {
1365 entry
= (IORegistryEntry
*) links
->getObject( 0 );
1374 IORegistryEntry
* IORegistryEntry::getParentEntry( const IORegistryPlane
* plane
) const
1376 IORegistryEntry
* entry
;
1378 entry
= copyParentEntry( plane
);
1385 OSArray
* IORegistryEntry::getChildSetReference( const IORegistryPlane
* plane
) const
1388 return( (OSArray
*) registryTable()->getObject(
1389 plane
->keys
[ kChildSetIndex
]));
1394 OSIterator
* IORegistryEntry::getChildIterator( const IORegistryPlane
* plane
) const
1403 links
= getChildSetReference( plane
);
1405 links
= OSArray::withCapacity( 1 );
1407 links
= OSArray::withArray( links
, links
->getCount() );
1410 iter
= IOLinkIterator::withCollection( links
);
1419 IORegistryEntry
* IORegistryEntry::copyChildEntry(
1420 const IORegistryPlane
* plane
) const
1422 IORegistryEntry
* entry
= 0;
1427 if( (links
= getChildSetReference( plane
))) {
1428 entry
= (IORegistryEntry
*) links
->getObject( 0 );
1437 IORegistryEntry
* IORegistryEntry::getChildEntry(
1438 const IORegistryPlane
* plane
) const
1440 IORegistryEntry
* entry
;
1442 entry
= copyChildEntry( plane
);
1449 void IORegistryEntry::applyToChildren( IORegistryEntryApplierFunction applier
,
1451 const IORegistryPlane
* plane
) const
1455 IORegistryEntry
* next
;
1461 array
= OSArray::withArray( getChildSetReference( plane
));
1465 (next
= (IORegistryEntry
*) array
->getObject( index
));
1467 (*applier
)(next
, context
);
1472 void IORegistryEntry::applyToParents( IORegistryEntryApplierFunction applier
,
1474 const IORegistryPlane
* plane
) const
1478 IORegistryEntry
* next
;
1484 array
= OSArray::withArray( getParentSetReference( plane
));
1488 (next
= (IORegistryEntry
*) array
->getObject( index
));
1490 (*applier
)(next
, context
);
1495 bool IORegistryEntry::isChild( IORegistryEntry
* child
,
1496 const IORegistryPlane
* plane
,
1497 bool onlyChild
) const
1504 if( (links
= getChildSetReference( plane
))) {
1505 if( (!onlyChild
) || (1 == links
->getCount()))
1506 ret
= arrayMember( links
, child
);
1508 if( ret
&& (links
= child
->getParentSetReference( plane
)))
1509 ret
= arrayMember( links
, this );
1516 bool IORegistryEntry::isParent( IORegistryEntry
* parent
,
1517 const IORegistryPlane
* plane
,
1518 bool onlyParent
) const
1526 if( (links
= getParentSetReference( plane
))) {
1527 if( (!onlyParent
) || (1 == links
->getCount()))
1528 ret
= arrayMember( links
, parent
);
1530 if( ret
&& (links
= parent
->getChildSetReference( plane
)))
1531 ret
= arrayMember( links
, this );
1538 bool IORegistryEntry::inPlane( const IORegistryPlane
* plane
) const
1545 ret
= (0 != getParentSetReference( plane
));
1548 // Check to see if this is in any plane. If it is in a plane
1549 // then the registryTable will contain a key with the ParentLinks
1550 // suffix. When we iterate over the keys looking for that suffix
1553 OSCollectionIterator
*iter
=
1554 OSCollectionIterator::withCollection( registryTable());
1556 const OSSymbol
*key
;
1558 while( (key
= (OSSymbol
*) iter
->getNextObject()) ) {
1559 const char *keysuffix
;
1561 // Get a pointer to this keys suffix
1562 keysuffix
= key
->getCStringNoCopy()
1563 + key
->getLength() - kIORegPlaneParentSuffixLen
;
1564 if( !strcmp(keysuffix
, kIORegPlaneParentSuffix
) ) {
1578 bool IORegistryEntry::attachToParent( IORegistryEntry
* parent
,
1579 const IORegistryPlane
* plane
)
1590 ret
= makeLink( parent
, kParentSetIndex
, plane
);
1592 if( (links
= parent
->getChildSetReference( plane
)))
1593 needParent
= (false == arrayMember( links
, this ));
1601 // Mark any collections in the property list as immutable
1602 OSDictionary
*ptable
= getPropertyTable();
1603 OSCollectionIterator
*iter
=
1604 OSCollectionIterator::withCollection( ptable
);
1606 const OSSymbol
*key
;
1608 while( (key
= (OSSymbol
*) iter
->getNextObject( ))) {
1609 // Is object for key a collection?
1610 OSCollection
*coll
=
1611 OSDynamicCast( OSCollection
, ptable
->getObject( key
));
1614 // Yup so mark it as immutable
1615 coll
->setOptions( OSCollection::kMASK
,
1616 OSCollection::kImmutable
);
1625 ret
&= parent
->attachToChild( this, plane
);
1630 bool IORegistryEntry::attachToChild( IORegistryEntry
* child
,
1631 const IORegistryPlane
* plane
)
1642 ret
= makeLink( child
, kChildSetIndex
, plane
);
1644 if( (links
= child
->getParentSetReference( plane
)))
1645 needChild
= (false == arrayMember( links
, this ));
1652 ret
&= child
->attachToParent( this, plane
);
1657 void IORegistryEntry::detachFromParent( IORegistryEntry
* parent
,
1658 const IORegistryPlane
* plane
)
1667 breakLink( parent
, kParentSetIndex
, plane
);
1669 if( (links
= parent
->getChildSetReference( plane
)))
1670 needParent
= arrayMember( links
, this );
1674 // parent->breakLink( this, kChildSetIndex, plane );
1679 parent
->detachFromChild( this, plane
);
1684 void IORegistryEntry::detachFromChild( IORegistryEntry
* child
,
1685 const IORegistryPlane
* plane
)
1694 breakLink( child
, kChildSetIndex
, plane
);
1696 if( (links
= child
->getParentSetReference( plane
)))
1697 needChild
= arrayMember( links
, this );
1704 child
->detachFromParent( this, plane
);
1709 void IORegistryEntry::detachAbove( const IORegistryPlane
* plane
)
1711 IORegistryEntry
* parent
;
1714 while( (parent
= getParentEntry( plane
)))
1715 detachFromParent( parent
, plane
);
1719 void IORegistryEntry::detachAll( const IORegistryPlane
* plane
)
1722 IORegistryEntry
* next
;
1723 IORegistryIterator
* regIter
;
1725 regIter
= IORegistryIterator::iterateOver( this, plane
, true );
1728 all
= regIter
->iterateAll();
1731 detachAbove( plane
);
1733 while( (next
= (IORegistryEntry
*) all
->getLastObject())) {
1736 all
->removeObject(next
);
1738 next
->detachAbove( plane
);
1745 unsigned int IORegistryEntry::getDepth( const IORegistryPlane
* plane
) const
1747 unsigned int depth
= 1;
1749 unsigned int oneDepth
, maxParentDepth
, count
;
1750 IORegistryEntry
* one
;
1751 const IORegistryEntry
* next
;
1757 while( (parents
= next
->getParentSetReference( plane
))) {
1759 count
= parents
->getCount();
1764 next
= (IORegistryEntry
*) parents
->getObject( 0 );
1769 (one
= (IORegistryEntry
*) parents
->getObject( index
));
1771 oneDepth
= one
->getDepth( plane
);
1772 if( oneDepth
> maxParentDepth
)
1773 maxParentDepth
= oneDepth
;
1775 depth
+= maxParentDepth
;
1785 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1788 #define super OSIterator
1790 OSDefineMetaClassAndStructors(IORegistryIterator
, OSIterator
)
1792 enum { kIORegistryIteratorInvalidFlag
= 0x80000000 };
1794 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1796 IORegistryIterator
*
1797 IORegistryIterator::iterateOver( IORegistryEntry
* root
,
1798 const IORegistryPlane
* plane
,
1799 IOOptionBits options
)
1801 IORegistryIterator
* create
;
1808 create
= new IORegistryIterator
;
1810 if( create
->init()) {
1813 create
->root
= root
;
1814 create
->where
= &create
->start
;
1815 create
->start
.current
= root
;
1816 create
->plane
= plane
;
1817 create
->options
= options
& ~kIORegistryIteratorInvalidFlag
;
1827 IORegistryIterator
*
1828 IORegistryIterator::iterateOver( const IORegistryPlane
* plane
,
1829 IOOptionBits options
)
1831 return( iterateOver( gRegistryRoot
, plane
, options
));
1834 bool IORegistryIterator::isValid( void )
1843 ok
= (0 == (kIORegistryIteratorInvalidFlag
& options
));
1845 while( ok
&& next
) {
1847 ok
= where
->iter
->isValid();
1855 void IORegistryIterator::enterEntry( const IORegistryPlane
* enterPlane
)
1860 where
= (IORegCursor
*) IOMalloc( sizeof( IORegCursor
));
1866 where
->current
= prev
->current
;
1871 void IORegistryIterator::enterEntry( void )
1873 enterEntry( plane
);
1876 bool IORegistryIterator::exitEntry( void )
1881 where
->iter
->release();
1883 if( where
->current
)// && (where != &start))
1884 where
->current
->release();
1887 if( where
!= &start
) {
1890 IOFree( gone
, sizeof( IORegCursor
));
1897 void IORegistryIterator::reset( void )
1907 where
->current
= root
;
1908 options
&= ~kIORegistryIteratorInvalidFlag
;
1911 void IORegistryIterator::free( void )
1922 IORegistryEntry
* IORegistryIterator::getNextObjectFlat( void )
1924 IORegistryEntry
* next
= 0;
1925 OSArray
* links
= 0;
1929 if( (0 == where
->iter
)) {
1930 // just entered - create new iter
1933 && (links
= ( (options
& kIORegistryIterateParents
) ?
1934 where
->current
->getParentSetReference( plane
) :
1935 where
->current
->getChildSetReference( plane
) )) )
1937 where
->iter
= OSCollectionIterator::withCollection( links
);
1940 // next sibling - release current
1942 where
->current
->release();
1946 next
= (IORegistryEntry
*) where
->iter
->getNextObject();
1950 else if( !where
->iter
->isValid())
1951 options
|= kIORegistryIteratorInvalidFlag
;
1954 where
->current
= next
;
1961 IORegistryEntry
* IORegistryIterator::getNextObjectRecursive( void )
1963 IORegistryEntry
* next
;
1966 next
= getNextObjectFlat();
1967 while( (0 == next
) && exitEntry());
1971 done
= OSOrderedSet::withCapacity( 10 );
1972 if( done
->setObject((OSObject
*) next
)) {
1973 // done set didn't contain this one, so recurse
1980 IORegistryEntry
* IORegistryIterator::getNextObject( void )
1982 if( options
& kIORegistryIterateRecursively
)
1983 return( getNextObjectRecursive());
1985 return( getNextObjectFlat());
1988 IORegistryEntry
* IORegistryIterator::getCurrentEntry( void )
1991 return( where
->current
);
1996 OSOrderedSet
* IORegistryIterator::iterateAll( void )
1999 while( getNextObjectRecursive())
2006 OSMetaClassDefineReservedUsed(IORegistryEntry
, 0);
2007 OSMetaClassDefineReservedUsed(IORegistryEntry
, 1);
2008 OSMetaClassDefineReservedUsed(IORegistryEntry
, 2);
2009 OSMetaClassDefineReservedUsed(IORegistryEntry
, 3);
2010 OSMetaClassDefineReservedUsed(IORegistryEntry
, 4);
2011 OSMetaClassDefineReservedUsed(IORegistryEntry
, 5);
2013 OSMetaClassDefineReservedUnused(IORegistryEntry
, 6);
2014 OSMetaClassDefineReservedUnused(IORegistryEntry
, 7);
2015 OSMetaClassDefineReservedUnused(IORegistryEntry
, 8);
2016 OSMetaClassDefineReservedUnused(IORegistryEntry
, 9);
2017 OSMetaClassDefineReservedUnused(IORegistryEntry
, 10);
2018 OSMetaClassDefineReservedUnused(IORegistryEntry
, 11);
2019 OSMetaClassDefineReservedUnused(IORegistryEntry
, 12);
2020 OSMetaClassDefineReservedUnused(IORegistryEntry
, 13);
2021 OSMetaClassDefineReservedUnused(IORegistryEntry
, 14);
2022 OSMetaClassDefineReservedUnused(IORegistryEntry
, 15);
2023 OSMetaClassDefineReservedUnused(IORegistryEntry
, 16);
2024 OSMetaClassDefineReservedUnused(IORegistryEntry
, 17);
2025 OSMetaClassDefineReservedUnused(IORegistryEntry
, 18);
2026 OSMetaClassDefineReservedUnused(IORegistryEntry
, 19);
2027 OSMetaClassDefineReservedUnused(IORegistryEntry
, 20);
2028 OSMetaClassDefineReservedUnused(IORegistryEntry
, 21);
2029 OSMetaClassDefineReservedUnused(IORegistryEntry
, 22);
2030 OSMetaClassDefineReservedUnused(IORegistryEntry
, 23);
2031 OSMetaClassDefineReservedUnused(IORegistryEntry
, 24);
2032 OSMetaClassDefineReservedUnused(IORegistryEntry
, 25);
2033 OSMetaClassDefineReservedUnused(IORegistryEntry
, 26);
2034 OSMetaClassDefineReservedUnused(IORegistryEntry
, 27);
2035 OSMetaClassDefineReservedUnused(IORegistryEntry
, 28);
2036 OSMetaClassDefineReservedUnused(IORegistryEntry
, 29);
2037 OSMetaClassDefineReservedUnused(IORegistryEntry
, 30);
2038 OSMetaClassDefineReservedUnused(IORegistryEntry
, 31);
2040 /* inline function implementation */
2041 OSDictionary
* IORegistryEntry::getPropertyTable( void ) const
2042 { return(fPropertyTable
); }