2 * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * The contents of this file constitute Original Code as defined in and
7 * are subject to the Apple Public Source License Version 1.1 (the
8 * "License"). You may not use this file except in compliance with the
9 * License. Please obtain a copy of the License at
10 * http://www.apple.com/publicsource and read it before using this file.
12 * This Original Code and all software distributed under the License are
13 * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
14 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
15 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
17 * License for the specific language governing rights and limitations
20 * @APPLE_LICENSE_HEADER_END@
23 * Copyright (c) 1998 Apple Computer, Inc. All rights reserved.
26 * 12 Nov 98 sdouglas created.
30 #include <IOKit/IORegistryEntry.h>
31 #include <libkern/c++/OSContainers.h>
32 #include <IOKit/IOService.h>
33 #include <IOKit/IOKitKeys.h>
35 #include <IOKit/IOLib.h>
37 #include <IOKit/assert.h>
39 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
41 #define super OSObject
43 OSDefineMetaClassAndStructors(IORegistryEntry
, OSObject
)
45 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
47 #define kIORegPlaneParentSuffix "ParentLinks"
48 #define kIORegPlaneChildSuffix "ChildLinks"
49 #define kIORegPlaneNameSuffix "Name"
50 #define kIORegPlaneLocationSuffix "Location"
51 #define kIORegPlaneParentSuffixLen (sizeof(kIORegPlaneParentSuffix) - 1)
53 static IORegistryEntry
* gRegistryRoot
;
54 static OSDictionary
* gIORegistryPlanes
;
56 const OSSymbol
* gIONameKey
;
57 const OSSymbol
* gIOLocationKey
;
68 class IORegistryPlane
: public OSObject
{
70 friend class IORegistryEntry
;
72 OSDeclareAbstractStructors(IORegistryPlane
)
74 const OSSymbol
* nameKey
;
75 const OSSymbol
* keys
[ kNumSetIndex
];
76 const OSSymbol
* pathNameKey
;
77 const OSSymbol
* pathLocationKey
;
81 virtual bool serialize(OSSerialize
*s
) const;
84 OSDefineMetaClassAndStructors(IORegistryPlane
, OSObject
)
87 static IORecursiveLock
* gPropertiesLock
;
88 static SInt32 gIORegistryGenerationCount
;
90 #define UNLOCK lck_rw_done( &gIORegistryLock )
91 #define RLOCK lck_rw_lock_shared( &gIORegistryLock )
92 #define WLOCK lck_rw_lock_exclusive( &gIORegistryLock ); \
93 gIORegistryGenerationCount++
96 #define PUNLOCK IORecursiveLockUnlock( gPropertiesLock )
97 #define PLOCK IORecursiveLockLock( gPropertiesLock )
99 #define IOREGSPLITTABLES
101 #ifdef IOREGSPLITTABLES
102 #define registryTable() fRegistryTable
104 #define registryTable() fPropertyTable
109 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
111 lck_rw_t gIORegistryLock
;
112 lck_grp_t
*gIORegistryLockGrp
;
113 lck_grp_attr_t
*gIORegistryLockGrpAttr
;
114 lck_attr_t
*gIORegistryLockAttr
;
117 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
119 IORegistryEntry
* IORegistryEntry::initialize( void )
123 if( !gRegistryRoot
) {
126 gIORegistryLockGrpAttr
= lck_grp_attr_alloc_init();
127 //lck_grp_attr_setstat(gIORegistryLockGrpAttr);
128 gIORegistryLockGrp
= lck_grp_alloc_init("IORegistryLock", gIORegistryLockGrpAttr
);
129 gIORegistryLockAttr
= lck_attr_alloc_init();
130 lck_attr_rw_shared_priority(gIORegistryLockAttr
);
131 //lck_attr_setdebug(gIORegistryLockAttr);
132 lck_rw_init( &gIORegistryLock
, gIORegistryLockGrp
, gIORegistryLockAttr
);
134 gRegistryRoot
= new IORegistryEntry
;
135 gPropertiesLock
= IORecursiveLockAlloc();
136 gIORegistryPlanes
= OSDictionary::withCapacity( 1 );
138 assert( gRegistryRoot
&& gPropertiesLock
139 && gIORegistryPlanes
);
140 ok
= gRegistryRoot
->init();
142 gIONameKey
= OSSymbol::withCStringNoCopy( "IOName" );
143 gIOLocationKey
= OSSymbol::withCStringNoCopy( "IOLocation" );
145 assert( ok
&& gIONameKey
&& gIOLocationKey
);
147 gRegistryRoot
->setName( "Root" );
148 gRegistryRoot
->setProperty( kIORegistryPlanesKey
, gIORegistryPlanes
);
151 return( gRegistryRoot
);
154 IORegistryEntry
* IORegistryEntry::getRegistryRoot( void )
156 return( gRegistryRoot
);
159 SInt32
IORegistryEntry::getGenerationCount( void )
161 return( gIORegistryGenerationCount
);
165 const IORegistryPlane
* IORegistryEntry::makePlane( const char * name
)
167 IORegistryPlane
* plane
;
168 const OSSymbol
* nameKey
;
169 const OSSymbol
* parentKey
;
170 const OSSymbol
* childKey
;
171 const OSSymbol
* pathNameKey
;
172 const OSSymbol
* pathLocationKey
;
173 char key
[ kIOMaxPlaneName
+ 16 ];
176 strncpy( key
, name
, kIOMaxPlaneName
);
177 key
[ kIOMaxPlaneName
] = 0;
178 end
= key
+ strlen( name
);
180 nameKey
= OSSymbol::withCString( key
);
182 strcpy( end
, kIORegPlaneParentSuffix
);
183 parentKey
= OSSymbol::withCString( key
);
185 strcpy( end
, kIORegPlaneChildSuffix
);
186 childKey
= OSSymbol::withCString( key
);
188 strcpy( end
, kIORegPlaneNameSuffix
);
189 pathNameKey
= OSSymbol::withCString( key
);
191 strcpy( end
, kIORegPlaneLocationSuffix
);
192 pathLocationKey
= OSSymbol::withCString( key
);
194 plane
= new IORegistryPlane
;
196 if( plane
&& plane
->init()
197 && nameKey
&& parentKey
&& childKey
198 && pathNameKey
&& pathLocationKey
) {
200 plane
->nameKey
= nameKey
;
201 plane
->keys
[ kParentSetIndex
] = parentKey
;
202 plane
->keys
[ kChildSetIndex
] = childKey
;
203 plane
->pathNameKey
= pathNameKey
;
204 plane
->pathLocationKey
= pathLocationKey
;
207 gIORegistryPlanes
->setObject( nameKey
, plane
);
215 pathLocationKey
->release();
217 pathNameKey
->release();
219 parentKey
->release();
230 const IORegistryPlane
* IORegistryEntry::getPlane( const char * name
)
232 const IORegistryPlane
* plane
;
235 plane
= (const IORegistryPlane
*) gIORegistryPlanes
->getObject( name
);
241 bool IORegistryPlane::serialize(OSSerialize
*s
) const
243 return( nameKey
->serialize(s
) );
246 enum { kIORegCapacityIncrement
= 4 };
248 bool IORegistryEntry::init( OSDictionary
* dict
)
258 fPropertyTable
->release();
259 fPropertyTable
= dict
;
261 } else if( !fPropertyTable
) {
262 fPropertyTable
= OSDictionary::withCapacity( kIORegCapacityIncrement
);
264 fPropertyTable
->setCapacityIncrement( kIORegCapacityIncrement
);
270 #ifdef IOREGSPLITTABLES
271 if( !fRegistryTable
) {
272 fRegistryTable
= OSDictionary::withCapacity( kIORegCapacityIncrement
);
274 fRegistryTable
->setCapacityIncrement( kIORegCapacityIncrement
);
277 if( (prop
= OSDynamicCast( OSString
, getProperty( gIONameKey
)))) {
278 OSSymbol
* sym
= (OSSymbol
*)OSSymbol::withString( prop
);
279 // ok for OSSymbol too
284 #endif /* IOREGSPLITTABLES */
289 bool IORegistryEntry::init( IORegistryEntry
* old
,
290 const IORegistryPlane
* plane
)
293 IORegistryEntry
* next
;
301 fPropertyTable
= old
->getPropertyTable();
302 fPropertyTable
->retain();
303 #ifdef IOREGSPLITTABLES
304 fRegistryTable
= old
->fRegistryTable
;
305 old
->fRegistryTable
= OSDictionary::withDictionary( fRegistryTable
);
306 #endif /* IOREGSPLITTABLES */
308 old
->registryTable()->removeObject( plane
->keys
[ kParentSetIndex
] );
309 old
->registryTable()->removeObject( plane
->keys
[ kChildSetIndex
] );
311 all
= getParentSetReference( plane
);
312 if( all
) for( index
= 0;
313 (next
= (IORegistryEntry
*) all
->getObject(index
));
315 next
->makeLink( this, kChildSetIndex
, plane
);
316 next
->breakLink( old
, kChildSetIndex
, plane
);
319 all
= getChildSetReference( plane
);
320 if( all
) for( index
= 0;
321 (next
= (IORegistryEntry
*) all
->getObject(index
));
323 next
->makeLink( this, kParentSetIndex
, plane
);
324 next
->breakLink( old
, kParentSetIndex
, plane
);
332 void IORegistryEntry::free( void )
336 #define msg ": attached at free()"
337 char buf
[ strlen(msg
) + 40 ];
339 if( registryTable() && gIOServicePlane
) {
340 if( getParentSetReference( gIOServicePlane
)
341 || getChildSetReference( gIOServicePlane
)) {
343 strncpy( buf
, getName(), 32);
351 if( getPropertyTable())
352 getPropertyTable()->release();
354 #ifdef IOREGSPLITTABLES
356 registryTable()->release();
357 #endif /* IOREGSPLITTABLES */
362 void IORegistryEntry::setPropertyTable( OSDictionary
* dict
)
365 fPropertyTable
->release();
368 fPropertyTable
= dict
;
371 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
373 /* Wrappers to synchronize property table */
375 #define wrap2(type, constant) \
377 IORegistryEntry::copyProperty( type * aKey) constant \
382 obj = getProperty( aKey ); \
390 #define wrap4(type,constant) \
392 IORegistryEntry::getProperty( type * aKey, \
393 const IORegistryPlane * plane, \
394 IOOptionBits options ) constant \
396 OSObject * obj = getProperty( aKey ); \
398 if ( (0 == obj) && plane && (options & kIORegistryIterateRecursively) ) { \
399 IORegistryEntry * entry = (IORegistryEntry *) this; \
400 IORegistryIterator * iter; \
401 iter = IORegistryIterator::iterateOver( entry, plane, options ); \
404 while ( (0 == obj) && (entry = iter->getNextObject()) ) { \
405 obj = entry->getProperty( aKey ); \
414 #define wrap5(type,constant) \
416 IORegistryEntry::copyProperty( type * aKey, \
417 const IORegistryPlane * plane, \
418 IOOptionBits options ) constant \
420 OSObject * obj = copyProperty( aKey ); \
422 if ( (0 == obj) && plane && (options & kIORegistryIterateRecursively) ) { \
423 IORegistryEntry * entry = (IORegistryEntry *) this; \
424 IORegistryIterator * iter; \
425 iter = IORegistryIterator::iterateOver( entry, plane, options ); \
428 while ( (0 == obj) && (entry = iter->getNextObject()) ) { \
429 obj = entry->copyProperty( aKey ); \
438 bool IORegistryEntry::serializeProperties( OSSerialize
* s
) const
440 // setProperty( getRetainCount(), 32, "__retain" );
443 OSCollection
*snapshotProperties
= getPropertyTable()->copyCollection();
446 bool ok
= snapshotProperties
->serialize( s
);
447 snapshotProperties
->release();
451 OSDictionary
* IORegistryEntry::dictionaryWithProperties( void ) const
456 dict
= OSDictionary::withDictionary( getPropertyTable(),
457 getPropertyTable()->getCapacity() );
463 IOReturn
IORegistryEntry::setProperties( OSObject
* properties
)
465 return( kIOReturnUnsupported
);
468 wrap2(const OSSymbol
, const) // copyProperty() definition
469 wrap2(const OSString
, const) // copyProperty() definition
470 wrap2(const char, const) // copyProperty() definition
472 wrap4(const OSSymbol
, const) // getProperty() w/plane definition
473 wrap4(const OSString
, const) // getProperty() w/plane definition
474 wrap4(const char, const) // getProperty() w/plane definition
476 wrap5(const OSSymbol
, const) // copyProperty() w/plane definition
477 wrap5(const OSString
, const) // copyProperty() w/plane definition
478 wrap5(const char, const) // copyProperty() w/plane definition
482 IORegistryEntry::getProperty( const OSSymbol
* aKey
) const
487 obj
= getPropertyTable()->getObject( aKey
);
494 IORegistryEntry::removeProperty( const OSSymbol
* aKey
)
497 getPropertyTable()->removeObject( aKey
);
502 IORegistryEntry::setProperty( const OSSymbol
* aKey
, OSObject
* anObject
)
506 // If we are inserting a collection class and the current entry
507 // is attached into the registry (inPlane()) then mark the collection
509 OSCollection
*coll
= OSDynamicCast(OSCollection
, anObject
);
510 bool makeImmutable
= (coll
&& inPlane());
514 coll
->setOptions( OSCollection::kMASK
, OSCollection::kImmutable
);
516 ret
= getPropertyTable()->setObject( aKey
, anObject
);
522 IOReturn
IORegistryEntry::
523 runPropertyAction(Action inAction
, OSObject
*target
,
524 void *arg0
, void *arg1
, void *arg2
, void *arg3
)
528 // closeGate is recursive so don't worry if we already hold the lock.
530 res
= (*inAction
)(target
, arg0
, arg1
, arg2
, arg3
);
537 IORegistryEntry::getProperty( const OSString
* aKey
) const
539 const OSSymbol
* tmpKey
= OSSymbol::withString( aKey
);
540 OSObject
* obj
= getProperty( tmpKey
);
547 IORegistryEntry::getProperty( const char * aKey
) const
549 const OSSymbol
* tmpKey
= OSSymbol::withCString( aKey
);
550 OSObject
* obj
= getProperty( tmpKey
);
558 IORegistryEntry::removeProperty( const OSString
* aKey
)
560 const OSSymbol
* tmpKey
= OSSymbol::withString( aKey
);
561 removeProperty( tmpKey
);
566 IORegistryEntry::removeProperty( const char * aKey
)
568 const OSSymbol
* tmpKey
= OSSymbol::withCString( aKey
);
569 removeProperty( tmpKey
);
574 IORegistryEntry::setProperty( const OSString
* aKey
, OSObject
* anObject
)
576 const OSSymbol
* tmpKey
= OSSymbol::withString( aKey
);
577 bool ret
= setProperty( tmpKey
, anObject
);
584 IORegistryEntry::setProperty( const char * aKey
, OSObject
* anObject
)
586 const OSSymbol
* tmpKey
= OSSymbol::withCString( aKey
);
587 bool ret
= setProperty( tmpKey
, anObject
);
594 IORegistryEntry::setProperty(const char * aKey
, const char * aString
)
597 OSSymbol
* aSymbol
= (OSSymbol
*) OSSymbol::withCString( aString
);
600 const OSSymbol
* tmpKey
= OSSymbol::withCString( aKey
);
601 ret
= setProperty( tmpKey
, aSymbol
);
610 IORegistryEntry::setProperty(const char * aKey
, bool aBoolean
)
613 OSBoolean
* aBooleanObj
= OSBoolean::withBoolean( aBoolean
);
616 const OSSymbol
* tmpKey
= OSSymbol::withCString( aKey
);
617 ret
= setProperty( tmpKey
, aBooleanObj
);
620 aBooleanObj
->release();
626 IORegistryEntry::setProperty( const char * aKey
,
627 unsigned long long aValue
,
628 unsigned int aNumberOfBits
)
631 OSNumber
* anOffset
= OSNumber::withNumber( aValue
, aNumberOfBits
);
634 const OSSymbol
* tmpKey
= OSSymbol::withCString( aKey
);
635 ret
= setProperty( tmpKey
, anOffset
);
644 IORegistryEntry::setProperty( const char * aKey
,
649 OSData
* data
= OSData::withBytes( bytes
, length
);
652 const OSSymbol
* tmpKey
= OSSymbol::withCString( aKey
);
653 ret
= setProperty( tmpKey
, data
);
661 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
663 /* Name, location, paths */
665 const char * IORegistryEntry::getName( const IORegistryPlane
* plane
) const
671 sym
= (OSSymbol
*) registryTable()->getObject( plane
->pathNameKey
);
673 sym
= (OSSymbol
*) registryTable()->getObject( gIONameKey
);
677 return( sym
->getCStringNoCopy());
679 return( (getMetaClass())->getClassName());
682 const OSSymbol
* IORegistryEntry::copyName(
683 const IORegistryPlane
* plane
) const
689 sym
= (OSSymbol
*) registryTable()->getObject( plane
->pathNameKey
);
691 sym
= (OSSymbol
*) registryTable()->getObject( gIONameKey
);
699 return( OSSymbol::withCString((getMetaClass())->getClassName()) );
702 const OSSymbol
* IORegistryEntry::copyLocation(
703 const IORegistryPlane
* plane
) const
709 sym
= (OSSymbol
*) registryTable()->getObject( plane
->pathLocationKey
);
711 sym
= (OSSymbol
*) registryTable()->getObject( gIOLocationKey
);
719 const char * IORegistryEntry::getLocation( const IORegistryPlane
* plane
) const
721 const OSSymbol
* sym
= copyLocation( plane
);
722 const char * result
= 0;
725 result
= sym
->getCStringNoCopy();
732 void IORegistryEntry::setName( const OSSymbol
* name
,
733 const IORegistryPlane
* plane
)
735 const OSSymbol
* key
;
739 key
= plane
->pathNameKey
;
744 registryTable()->setObject( key
, (OSObject
*) name
);
749 void IORegistryEntry::setName( const char * name
,
750 const IORegistryPlane
* plane
)
752 OSSymbol
* sym
= (OSSymbol
*)OSSymbol::withCString( name
);
754 setName( sym
, plane
);
759 void IORegistryEntry::setLocation( const OSSymbol
* location
,
760 const IORegistryPlane
* plane
)
762 const OSSymbol
* key
;
766 key
= plane
->pathLocationKey
;
768 key
= gIOLocationKey
;
771 registryTable()->setObject( key
, (OSObject
*) location
);
776 void IORegistryEntry::setLocation( const char * location
,
777 const IORegistryPlane
* plane
)
779 OSSymbol
* sym
= (OSSymbol
*)OSSymbol::withCString( location
);
781 setLocation( sym
, plane
);
787 IORegistryEntry::compareName( OSString
* name
, OSString
** matched
) const
789 const OSSymbol
* sym
= copyName();
792 isEqual
= sym
->isEqualTo( name
);
794 if( isEqual
&& matched
) {
806 IORegistryEntry::compareNames( OSObject
* names
, OSString
** matched
) const
809 OSCollection
* collection
;
810 OSIterator
* iter
= 0;
813 if( (collection
= OSDynamicCast( OSCollection
, names
))) {
814 iter
= OSCollectionIterator::withCollection( collection
);
817 string
= OSDynamicCast( OSString
, names
);
821 result
= compareName( string
, matched
);
823 } while( (false == result
)
824 && iter
&& (string
= OSDynamicCast( OSString
, iter
->getNextObject())));
833 bool IORegistryEntry::getPath( char * path
, int * length
,
834 const IORegistryPlane
* plane
) const
837 IORegistryEntry
* root
;
838 const IORegistryEntry
* entry
;
839 IORegistryEntry
* parent
;
840 const OSSymbol
* alias
;
842 int len
, maxLength
, compLen
;
846 if( !path
|| !length
|| !plane
)
850 maxLength
= *length
- 2;
853 len
= plane
->nameKey
->getLength();
854 if( len
>= maxLength
)
856 strcpy( nextComp
, plane
->nameKey
->getCStringNoCopy());
857 nextComp
[ len
++ ] = ':';
860 if( (alias
= hasAlias( plane
))) {
861 len
+= alias
->getLength();
862 ok
= (maxLength
> len
);
865 strcpy( nextComp
, alias
->getCStringNoCopy());
870 parent
= entry
->getParentEntry( plane
);
872 // Error if not attached in plane
875 stack
= OSArray::withCapacity( getDepth( plane
));
881 root
= gRegistryRoot
->getChildEntry( plane
);
882 while( parent
&& (entry
!= root
)) {
884 stack
->setObject( (OSObject
*) entry
);
886 parent
= entry
->getParentEntry( plane
);
889 index
= stack
->getCount();
898 } else while( ok
&& ((--index
) >= 0)) {
900 entry
= (IORegistryEntry
*) stack
->getObject((unsigned int) index
);
903 if( (alias
= entry
->hasAlias( plane
))) {
904 len
= plane
->nameKey
->getLength() + 1;
905 nextComp
= path
+ len
;
907 compLen
= alias
->getLength();
908 ok
= (maxLength
> len
+ compLen
);
910 strcpy( nextComp
, alias
->getCStringNoCopy());
912 compLen
= maxLength
- len
;
913 ok
= entry
->getPathComponent( nextComp
+ 1, &compLen
, plane
);
935 bool IORegistryEntry::getPathComponent( char * path
, int * length
,
936 const IORegistryPlane
* plane
) const
938 int len
, locLen
, maxLength
;
939 const char * compName
;
945 compName
= getName( plane
);
946 len
= strlen( compName
);
947 if( (loc
= getLocation( plane
)))
948 locLen
= 1 + strlen( loc
);
952 ok
= ((len
+ locLen
) < maxLength
);
954 strcpy( path
, compName
);
967 const char * IORegistryEntry::matchPathLocation( const char * cmp
,
968 const IORegistryPlane
* plane
)
971 const char * result
= 0;
973 char lastPathChar
, lastLocationChar
;
975 str
= getLocation( plane
);
977 lastPathChar
= cmp
[0];
978 lastLocationChar
= str
[0];
981 num1
= strtouq( cmp
, (char **) &cmp
, 16 );
982 lastPathChar
= *cmp
++;
986 if( lastLocationChar
) {
987 num2
= strtouq( str
, (char **) &str
, 16 );
988 lastLocationChar
= *str
++;
995 if (!lastPathChar
&& !lastLocationChar
) {
1000 if( (',' != lastPathChar
) && (':' != lastPathChar
))
1003 if (lastPathChar
&& lastLocationChar
&& (lastPathChar
!= lastLocationChar
))
1012 IORegistryEntry
* IORegistryEntry::getChildFromComponent( const char ** opath
,
1013 const IORegistryPlane
* plane
)
1015 IORegistryEntry
* entry
= 0;
1019 const char * cmp
= 0;
1024 set
= getChildSetReference( plane
);
1030 (entry
= (IORegistryEntry
*) set
->getObject(index
));
1036 str
= entry
->getName( plane
);
1037 len
= strlen( str
);
1038 if( strncmp( str
, cmp
, len
))
1043 if( (c
== 0) || (c
== '/') || (c
== ':'))
1049 if( (cmp
= entry
->matchPathLocation( cmp
, plane
)))
1059 const OSSymbol
* IORegistryEntry::hasAlias( const IORegistryPlane
* plane
,
1060 char * opath
, int * length
) const
1062 IORegistryEntry
* entry
;
1063 IORegistryEntry
* entry2
;
1064 const OSSymbol
* key
;
1065 const OSSymbol
* bestKey
= 0;
1068 const char * path
= "/aliases";
1070 entry
= IORegistryEntry::fromPath( path
, plane
);
1073 if( (iter
= OSCollectionIterator::withCollection(
1074 entry
->getPropertyTable() ))) {
1076 while( (key
= (OSSymbol
*) iter
->getNextObject())) {
1078 data
= (OSData
*) entry
->getProperty( key
);
1079 path
= (const char *) data
->getBytesNoCopy();
1080 if( (entry2
= IORegistryEntry::fromPath( path
, plane
,
1082 if( this == entry2
) {
1084 || (bestKey
->getLength() > key
->getLength()))
1085 // pick the smallest alias
1099 const char * IORegistryEntry::dealiasPath(
1100 const char ** opath
,
1101 const IORegistryPlane
* plane
)
1103 IORegistryEntry
* entry
;
1105 const char * path
= *opath
;
1106 const char * rpath
= 0;
1109 char temp
[ kIOMaxPlaneName
+ 1 ];
1116 while( (c
= *end
++) && (c
!= '/') && (c
!= ':'))
1119 if( (end
- path
) < kIOMaxPlaneName
) {
1120 strncpy( temp
, path
, end
- path
);
1121 temp
[ end
- path
] = 0;
1124 entry
= IORegistryEntry::fromPath( "/aliases", plane
);
1126 data
= (OSData
*) entry
->getProperty( temp
);
1128 rpath
= (const char *) data
->getBytesNoCopy();
1140 IORegistryEntry
* IORegistryEntry::fromPath(
1142 const IORegistryPlane
* plane
,
1145 IORegistryEntry
* fromEntry
)
1147 IORegistryEntry
* where
= 0;
1148 IORegistryEntry
* aliasEntry
= 0;
1149 IORegistryEntry
* next
;
1155 char temp
[ kIOMaxPlaneName
+ 1 ];
1162 end
= strchr( path
, ':' );
1163 if( end
&& ((end
- path
) < kIOMaxPlaneName
)) {
1164 strncpy( temp
, path
, end
- path
);
1165 temp
[ end
- path
] = 0;
1166 plane
= getPlane( temp
);
1175 if( (alias
= dealiasPath( &end
, plane
))) {
1178 aliasEntry
= IORegistryEntry::fromPath( alias
, plane
,
1179 opath
, &len
, fromEntry
);
1191 if( (0 == fromEntry
) && (*path
++ == '/'))
1192 fromEntry
= gRegistryRoot
->getChildEntry( plane
);
1199 if( c
&& (c
!= ':')) // check valid terminator
1204 next
= where
->getChildFromComponent( &path
, plane
);
1210 // check residual path
1211 if( where
!= fromEntry
)
1214 if( opath
&& length
) {
1215 // copy out residual path
1216 len2
= len
+ strlen( path
);
1218 strcpy( opath
+ len
, path
);
1222 // no residual path => must be no tail for success
1229 aliasEntry
->release();
1236 IORegistryEntry
* IORegistryEntry::childFromPath(
1238 const IORegistryPlane
* plane
,
1242 return( IORegistryEntry::fromPath( path
, plane
, opath
, len
, this ));
1245 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1247 #define IOLinkIterator OSCollectionIterator
1250 #define super OSObject
1252 inline bool IORegistryEntry::arrayMember( OSArray
* set
,
1253 const IORegistryEntry
* member
,
1254 unsigned int * index
) const
1257 OSObject
* probeObject
;
1259 for( i
= 0; (probeObject
= set
->getObject(i
)); i
++) {
1260 if (probeObject
== (OSObject
*) member
) {
1269 bool IORegistryEntry::makeLink( IORegistryEntry
* to
,
1270 unsigned int relation
,
1271 const IORegistryPlane
* plane
) const
1274 bool result
= false;
1276 if( (links
= (OSArray
*)
1277 registryTable()->getObject( plane
->keys
[ relation
] ))) {
1279 result
= arrayMember( links
, to
);
1281 result
= links
->setObject( to
);
1285 links
= OSArray::withObjects( (const OSObject
**) &to
, 1, 1 );
1286 result
= (links
!= 0);
1288 result
= registryTable()->setObject( plane
->keys
[ relation
],
1297 void IORegistryEntry::breakLink( IORegistryEntry
* to
,
1298 unsigned int relation
,
1299 const IORegistryPlane
* plane
) const
1304 if( (links
= (OSArray
*)
1305 registryTable()->getObject( plane
->keys
[ relation
]))) {
1307 if( arrayMember( links
, to
, &index
)) {
1308 links
->removeObject( index
);
1309 if( 0 == links
->getCount())
1310 registryTable()->removeObject( plane
->keys
[ relation
]);
1316 OSArray
* IORegistryEntry::getParentSetReference(
1317 const IORegistryPlane
* plane
) const
1320 return( (OSArray
*) registryTable()->getObject(
1321 plane
->keys
[ kParentSetIndex
]));
1326 OSIterator
* IORegistryEntry::getParentIterator(
1327 const IORegistryPlane
* plane
) const
1336 links
= getParentSetReference( plane
);
1338 links
= OSArray::withCapacity( 1 );
1340 links
= OSArray::withArray( links
, links
->getCount() );
1343 iter
= IOLinkIterator::withCollection( links
);
1351 IORegistryEntry
* IORegistryEntry::copyParentEntry( const IORegistryPlane
* plane
) const
1353 IORegistryEntry
* entry
= 0;
1358 if( (links
= getParentSetReference( plane
))) {
1359 entry
= (IORegistryEntry
*) links
->getObject( 0 );
1368 IORegistryEntry
* IORegistryEntry::getParentEntry( const IORegistryPlane
* plane
) const
1370 IORegistryEntry
* entry
;
1372 entry
= copyParentEntry( plane
);
1379 OSArray
* IORegistryEntry::getChildSetReference( const IORegistryPlane
* plane
) const
1382 return( (OSArray
*) registryTable()->getObject(
1383 plane
->keys
[ kChildSetIndex
]));
1388 OSIterator
* IORegistryEntry::getChildIterator( const IORegistryPlane
* plane
) const
1397 links
= getChildSetReference( plane
);
1399 links
= OSArray::withCapacity( 1 );
1401 links
= OSArray::withArray( links
, links
->getCount() );
1404 iter
= IOLinkIterator::withCollection( links
);
1413 IORegistryEntry
* IORegistryEntry::copyChildEntry(
1414 const IORegistryPlane
* plane
) const
1416 IORegistryEntry
* entry
= 0;
1421 if( (links
= getChildSetReference( plane
))) {
1422 entry
= (IORegistryEntry
*) links
->getObject( 0 );
1431 IORegistryEntry
* IORegistryEntry::getChildEntry(
1432 const IORegistryPlane
* plane
) const
1434 IORegistryEntry
* entry
;
1436 entry
= copyChildEntry( plane
);
1443 void IORegistryEntry::applyToChildren( IORegistryEntryApplierFunction applier
,
1445 const IORegistryPlane
* plane
) const
1449 IORegistryEntry
* next
;
1455 array
= OSArray::withArray( getChildSetReference( plane
));
1459 (next
= (IORegistryEntry
*) array
->getObject( index
));
1461 (*applier
)(next
, context
);
1466 void IORegistryEntry::applyToParents( IORegistryEntryApplierFunction applier
,
1468 const IORegistryPlane
* plane
) const
1472 IORegistryEntry
* next
;
1478 array
= OSArray::withArray( getParentSetReference( plane
));
1482 (next
= (IORegistryEntry
*) array
->getObject( index
));
1484 (*applier
)(next
, context
);
1489 bool IORegistryEntry::isChild( IORegistryEntry
* child
,
1490 const IORegistryPlane
* plane
,
1491 bool onlyChild
) const
1498 if( (links
= getChildSetReference( plane
))) {
1499 if( (!onlyChild
) || (1 == links
->getCount()))
1500 ret
= arrayMember( links
, child
);
1502 if( ret
&& (links
= child
->getParentSetReference( plane
)))
1503 ret
= arrayMember( links
, this );
1510 bool IORegistryEntry::isParent( IORegistryEntry
* parent
,
1511 const IORegistryPlane
* plane
,
1512 bool onlyParent
) const
1520 if( (links
= getParentSetReference( plane
))) {
1521 if( (!onlyParent
) || (1 == links
->getCount()))
1522 ret
= arrayMember( links
, parent
);
1524 if( ret
&& (links
= parent
->getChildSetReference( plane
)))
1525 ret
= arrayMember( links
, this );
1532 bool IORegistryEntry::inPlane( const IORegistryPlane
* plane
) const
1539 ret
= (0 != getParentSetReference( plane
));
1542 // Check to see if this is in any plane. If it is in a plane
1543 // then the registryTable will contain a key with the ParentLinks
1544 // suffix. When we iterate over the keys looking for that suffix
1547 OSCollectionIterator
*iter
=
1548 OSCollectionIterator::withCollection( registryTable());
1550 const OSSymbol
*key
;
1552 while( (key
= (OSSymbol
*) iter
->getNextObject()) ) {
1553 const char *keysuffix
;
1555 // Get a pointer to this keys suffix
1556 keysuffix
= key
->getCStringNoCopy()
1557 + key
->getLength() - kIORegPlaneParentSuffixLen
;
1558 if( !strcmp(keysuffix
, kIORegPlaneParentSuffix
) ) {
1572 bool IORegistryEntry::attachToParent( IORegistryEntry
* parent
,
1573 const IORegistryPlane
* plane
)
1584 ret
= makeLink( parent
, kParentSetIndex
, plane
);
1586 if( (links
= parent
->getChildSetReference( plane
)))
1587 needParent
= (false == arrayMember( links
, this ));
1595 // Mark any collections in the property list as immutable
1596 OSDictionary
*ptable
= getPropertyTable();
1597 OSCollectionIterator
*iter
=
1598 OSCollectionIterator::withCollection( ptable
);
1600 const OSSymbol
*key
;
1602 while( (key
= (OSSymbol
*) iter
->getNextObject( ))) {
1603 // Is object for key a collection?
1604 OSCollection
*coll
=
1605 OSDynamicCast( OSCollection
, ptable
->getObject( key
));
1608 // Yup so mark it as immutable
1609 coll
->setOptions( OSCollection::kMASK
,
1610 OSCollection::kImmutable
);
1619 ret
&= parent
->attachToChild( this, plane
);
1624 bool IORegistryEntry::attachToChild( IORegistryEntry
* child
,
1625 const IORegistryPlane
* plane
)
1636 ret
= makeLink( child
, kChildSetIndex
, plane
);
1638 if( (links
= child
->getParentSetReference( plane
)))
1639 needChild
= (false == arrayMember( links
, this ));
1646 ret
&= child
->attachToParent( this, plane
);
1651 void IORegistryEntry::detachFromParent( IORegistryEntry
* parent
,
1652 const IORegistryPlane
* plane
)
1661 breakLink( parent
, kParentSetIndex
, plane
);
1663 if( (links
= parent
->getChildSetReference( plane
)))
1664 needParent
= arrayMember( links
, this );
1668 // parent->breakLink( this, kChildSetIndex, plane );
1673 parent
->detachFromChild( this, plane
);
1678 void IORegistryEntry::detachFromChild( IORegistryEntry
* child
,
1679 const IORegistryPlane
* plane
)
1688 breakLink( child
, kChildSetIndex
, plane
);
1690 if( (links
= child
->getParentSetReference( plane
)))
1691 needChild
= arrayMember( links
, this );
1698 child
->detachFromParent( this, plane
);
1703 void IORegistryEntry::detachAbove( const IORegistryPlane
* plane
)
1705 IORegistryEntry
* parent
;
1708 while( (parent
= getParentEntry( plane
)))
1709 detachFromParent( parent
, plane
);
1713 void IORegistryEntry::detachAll( const IORegistryPlane
* plane
)
1716 IORegistryEntry
* next
;
1717 IORegistryIterator
* regIter
;
1719 regIter
= IORegistryIterator::iterateOver( this, plane
, true );
1722 all
= regIter
->iterateAll();
1725 detachAbove( plane
);
1727 while( (next
= (IORegistryEntry
*) all
->getLastObject())) {
1730 all
->removeObject(next
);
1732 next
->detachAbove( plane
);
1739 unsigned int IORegistryEntry::getDepth( const IORegistryPlane
* plane
) const
1741 unsigned int depth
= 1;
1743 unsigned int oneDepth
, maxParentDepth
, count
;
1744 IORegistryEntry
* one
;
1745 const IORegistryEntry
* next
;
1751 while( (parents
= next
->getParentSetReference( plane
))) {
1753 count
= parents
->getCount();
1758 next
= (IORegistryEntry
*) parents
->getObject( 0 );
1763 (one
= (IORegistryEntry
*) parents
->getObject( index
));
1765 oneDepth
= one
->getDepth( plane
);
1766 if( oneDepth
> maxParentDepth
)
1767 maxParentDepth
= oneDepth
;
1769 depth
+= maxParentDepth
;
1779 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1782 #define super OSIterator
1784 OSDefineMetaClassAndStructors(IORegistryIterator
, OSIterator
)
1786 enum { kIORegistryIteratorInvalidFlag
= 0x80000000 };
1788 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1790 IORegistryIterator
*
1791 IORegistryIterator::iterateOver( IORegistryEntry
* root
,
1792 const IORegistryPlane
* plane
,
1793 IOOptionBits options
)
1795 IORegistryIterator
* create
;
1802 create
= new IORegistryIterator
;
1804 if( create
->init()) {
1807 create
->root
= root
;
1808 create
->where
= &create
->start
;
1809 create
->start
.current
= root
;
1810 create
->plane
= plane
;
1811 create
->options
= options
& ~kIORegistryIteratorInvalidFlag
;
1821 IORegistryIterator
*
1822 IORegistryIterator::iterateOver( const IORegistryPlane
* plane
,
1823 IOOptionBits options
)
1825 return( iterateOver( gRegistryRoot
, plane
, options
));
1828 bool IORegistryIterator::isValid( void )
1837 ok
= (0 == (kIORegistryIteratorInvalidFlag
& options
));
1839 while( ok
&& next
) {
1841 ok
= where
->iter
->isValid();
1849 void IORegistryIterator::enterEntry( const IORegistryPlane
* enterPlane
)
1854 where
= (IORegCursor
*) IOMalloc( sizeof( IORegCursor
));
1860 where
->current
= prev
->current
;
1865 void IORegistryIterator::enterEntry( void )
1867 enterEntry( plane
);
1870 bool IORegistryIterator::exitEntry( void )
1875 where
->iter
->release();
1877 if( where
->current
)// && (where != &start))
1878 where
->current
->release();
1881 if( where
!= &start
) {
1884 IOFree( gone
, sizeof( IORegCursor
));
1891 void IORegistryIterator::reset( void )
1901 where
->current
= root
;
1902 options
&= ~kIORegistryIteratorInvalidFlag
;
1905 void IORegistryIterator::free( void )
1916 IORegistryEntry
* IORegistryIterator::getNextObjectFlat( void )
1918 IORegistryEntry
* next
= 0;
1919 OSArray
* links
= 0;
1923 if( (0 == where
->iter
)) {
1924 // just entered - create new iter
1927 && (links
= ( (options
& kIORegistryIterateParents
) ?
1928 where
->current
->getParentSetReference( plane
) :
1929 where
->current
->getChildSetReference( plane
) )) )
1931 where
->iter
= OSCollectionIterator::withCollection( links
);
1934 // next sibling - release current
1936 where
->current
->release();
1940 next
= (IORegistryEntry
*) where
->iter
->getNextObject();
1944 else if( !where
->iter
->isValid())
1945 options
|= kIORegistryIteratorInvalidFlag
;
1948 where
->current
= next
;
1955 IORegistryEntry
* IORegistryIterator::getNextObjectRecursive( void )
1957 IORegistryEntry
* next
;
1960 next
= getNextObjectFlat();
1961 while( (0 == next
) && exitEntry());
1965 done
= OSOrderedSet::withCapacity( 10 );
1966 if( done
->setObject((OSObject
*) next
)) {
1967 // done set didn't contain this one, so recurse
1974 IORegistryEntry
* IORegistryIterator::getNextObject( void )
1976 if( options
& kIORegistryIterateRecursively
)
1977 return( getNextObjectRecursive());
1979 return( getNextObjectFlat());
1982 IORegistryEntry
* IORegistryIterator::getCurrentEntry( void )
1985 return( where
->current
);
1990 OSOrderedSet
* IORegistryIterator::iterateAll( void )
1993 while( getNextObjectRecursive())
2000 OSMetaClassDefineReservedUsed(IORegistryEntry
, 0);
2001 OSMetaClassDefineReservedUsed(IORegistryEntry
, 1);
2002 OSMetaClassDefineReservedUsed(IORegistryEntry
, 2);
2003 OSMetaClassDefineReservedUsed(IORegistryEntry
, 3);
2004 OSMetaClassDefineReservedUsed(IORegistryEntry
, 4);
2005 OSMetaClassDefineReservedUsed(IORegistryEntry
, 5);
2007 OSMetaClassDefineReservedUnused(IORegistryEntry
, 6);
2008 OSMetaClassDefineReservedUnused(IORegistryEntry
, 7);
2009 OSMetaClassDefineReservedUnused(IORegistryEntry
, 8);
2010 OSMetaClassDefineReservedUnused(IORegistryEntry
, 9);
2011 OSMetaClassDefineReservedUnused(IORegistryEntry
, 10);
2012 OSMetaClassDefineReservedUnused(IORegistryEntry
, 11);
2013 OSMetaClassDefineReservedUnused(IORegistryEntry
, 12);
2014 OSMetaClassDefineReservedUnused(IORegistryEntry
, 13);
2015 OSMetaClassDefineReservedUnused(IORegistryEntry
, 14);
2016 OSMetaClassDefineReservedUnused(IORegistryEntry
, 15);
2017 OSMetaClassDefineReservedUnused(IORegistryEntry
, 16);
2018 OSMetaClassDefineReservedUnused(IORegistryEntry
, 17);
2019 OSMetaClassDefineReservedUnused(IORegistryEntry
, 18);
2020 OSMetaClassDefineReservedUnused(IORegistryEntry
, 19);
2021 OSMetaClassDefineReservedUnused(IORegistryEntry
, 20);
2022 OSMetaClassDefineReservedUnused(IORegistryEntry
, 21);
2023 OSMetaClassDefineReservedUnused(IORegistryEntry
, 22);
2024 OSMetaClassDefineReservedUnused(IORegistryEntry
, 23);
2025 OSMetaClassDefineReservedUnused(IORegistryEntry
, 24);
2026 OSMetaClassDefineReservedUnused(IORegistryEntry
, 25);
2027 OSMetaClassDefineReservedUnused(IORegistryEntry
, 26);
2028 OSMetaClassDefineReservedUnused(IORegistryEntry
, 27);
2029 OSMetaClassDefineReservedUnused(IORegistryEntry
, 28);
2030 OSMetaClassDefineReservedUnused(IORegistryEntry
, 29);
2031 OSMetaClassDefineReservedUnused(IORegistryEntry
, 30);
2032 OSMetaClassDefineReservedUnused(IORegistryEntry
, 31);
2034 /* inline function implementation */
2035 OSDictionary
* IORegistryEntry::getPropertyTable( void ) const
2036 { return(fPropertyTable
); }