2 * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved.
4 * @APPLE_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. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
21 * @APPLE_LICENSE_HEADER_END@
24 * Copyright (c) 1998 Apple Computer, Inc. All rights reserved.
27 * 12 Nov 98 sdouglas created.
31 #include <IOKit/IORegistryEntry.h>
32 #include <libkern/c++/OSContainers.h>
33 #include <IOKit/IOService.h>
34 #include <IOKit/IOKitKeys.h>
36 #include <IOKit/IOLib.h>
38 #include <IOKit/assert.h>
40 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
42 #define super OSObject
44 OSDefineMetaClassAndStructors(IORegistryEntry
, OSObject
)
46 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
48 #define kIORegPlaneParentSuffix "ParentLinks"
49 #define kIORegPlaneChildSuffix "ChildLinks"
50 #define kIORegPlaneNameSuffix "Name"
51 #define kIORegPlaneLocationSuffix "Location"
52 #define kIORegPlaneParentSuffixLen (sizeof(kIORegPlaneParentSuffix) - 1)
54 static IORegistryEntry
* gRegistryRoot
;
55 static OSDictionary
* gIORegistryPlanes
;
57 const OSSymbol
* gIONameKey
;
58 const OSSymbol
* gIOLocationKey
;
69 class IORegistryPlane
: public OSObject
{
71 friend class IORegistryEntry
;
73 OSDeclareAbstractStructors(IORegistryPlane
)
75 const OSSymbol
* nameKey
;
76 const OSSymbol
* keys
[ kNumSetIndex
];
77 const OSSymbol
* pathNameKey
;
78 const OSSymbol
* pathLocationKey
;
82 virtual bool serialize(OSSerialize
*s
) const;
85 OSDefineMetaClassAndStructors(IORegistryPlane
, OSObject
)
88 static IORecursiveLock
* gPropertiesLock
;
89 static SInt32 gIORegistryGenerationCount
;
91 #define UNLOCK s_lock_done( &gIORegistryLock )
92 #define RLOCK s_lock_read( &gIORegistryLock )
93 #define WLOCK s_lock_write( &gIORegistryLock ); \
94 gIORegistryGenerationCount++
97 #define PUNLOCK IORecursiveLockUnlock( gPropertiesLock )
98 #define PLOCK IORecursiveLockLock( gPropertiesLock )
100 #define IOREGSPLITTABLES
102 #ifdef IOREGSPLITTABLES
103 #define registryTable() fRegistryTable
105 #define registryTable() fPropertyTable
110 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
113 lck_spin_t interlock
; /* "hardware" interlock field */
114 volatile unsigned int
115 read_count
:16, /* No. of accepted readers */
116 want_upgrade
:1, /* Read-to-write upgrade waiting */
117 want_write
:1, /* Writer is waiting, or
119 waiting
:1, /* Someone is sleeping on lock */
120 can_sleep
:1; /* Can attempts to lock go to sleep? */
123 static struct s_lock_t gIORegistryLock
;
125 /* Time we loop without holding the interlock.
126 * The former is for when we cannot sleep, the latter
127 * for when our thread can go to sleep (loop less)
128 * we shouldn't retake the interlock at all frequently
129 * if we cannot go to sleep, since it interferes with
130 * any other processors. In particular, 100 is too small
131 * a number for powerpc MP systems because of cache
132 * coherency issues and differing lock fetch times between
135 static unsigned int lock_wait_time
[2] = { (unsigned int)-1, 100 } ;
142 (void) memset((void *) l
, 0, sizeof(s_lock_t
));
144 lck_spin_init(&l
->interlock
, IOLockGroup
, LCK_ATTR_NULL
);
145 l
->want_write
= FALSE
;
146 l
->want_upgrade
= FALSE
;
148 l
->can_sleep
= can_sleep
;
153 register s_lock_t
* l
)
157 lck_spin_lock(&l
->interlock
);
160 * Try to acquire the want_write bit.
162 while (l
->want_write
) {
164 i
= lock_wait_time
[l
->can_sleep
? 1 : 0];
166 lck_spin_unlock(&l
->interlock
);
167 while (--i
!= 0 && l
->want_write
)
169 lck_spin_lock(&l
->interlock
);
172 if (l
->can_sleep
&& l
->want_write
) {
174 lck_spin_sleep( &l
->interlock
, LCK_SLEEP_DEFAULT
,
175 (event_t
) l
, THREAD_UNINT
);
176 /* interlock relocked */
179 l
->want_write
= TRUE
;
181 /* Wait for readers (and upgrades) to finish */
183 while ((l
->read_count
!= 0) || l
->want_upgrade
) {
185 i
= lock_wait_time
[l
->can_sleep
? 1 : 0];
187 lck_spin_unlock(&l
->interlock
);
188 while (--i
!= 0 && (l
->read_count
!= 0 ||
191 lck_spin_lock(&l
->interlock
);
194 if (l
->can_sleep
&& (l
->read_count
!= 0 || l
->want_upgrade
)) {
196 lck_spin_sleep( &l
->interlock
, LCK_SLEEP_DEFAULT
,
197 (event_t
) l
, THREAD_UNINT
);
198 /* interlock relocked */
202 lck_spin_unlock(&l
->interlock
);
207 register s_lock_t
* l
)
209 boolean_t do_wakeup
= FALSE
;
211 lck_spin_lock(&l
->interlock
);
213 if (l
->read_count
!= 0) {
217 if (l
->want_upgrade
) {
218 l
->want_upgrade
= FALSE
;
221 l
->want_write
= FALSE
;
226 * There is no reason to wakeup a waiting thread
227 * if the read-count is non-zero. Consider:
228 * we must be dropping a read lock
229 * threads are waiting only if one wants a write lock
230 * if there are still readers, they can't proceed
232 if (l
->waiting
&& (l
->read_count
== 0)) {
237 lck_spin_unlock(&l
->interlock
);
240 thread_wakeup((event_t
) l
);
245 register s_lock_t
* l
)
249 lck_spin_lock(&l
->interlock
);
251 while ( l
->want_upgrade
|| ((0 == l
->read_count
) && l
->want_write
)) {
253 i
= lock_wait_time
[l
->can_sleep
? 1 : 0];
256 lck_spin_unlock(&l
->interlock
);
258 (l
->want_upgrade
|| ((0 == l
->read_count
) && l
->want_write
)))
260 lck_spin_lock(&l
->interlock
);
264 (l
->want_upgrade
|| ((0 == l
->read_count
) && l
->want_write
))) {
266 lck_spin_sleep( &l
->interlock
, LCK_SLEEP_DEFAULT
,
267 (event_t
) l
, THREAD_UNINT
);
268 /* interlock relocked */
273 lck_spin_unlock(&l
->interlock
);
277 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
279 IORegistryEntry
* IORegistryEntry::initialize( void )
283 if( !gRegistryRoot
) {
285 s_lock_init( &gIORegistryLock
, true );
286 gRegistryRoot
= new IORegistryEntry
;
287 gPropertiesLock
= IORecursiveLockAlloc();
288 gIORegistryPlanes
= OSDictionary::withCapacity( 1 );
290 assert( gRegistryRoot
&& gPropertiesLock
291 && gIORegistryPlanes
);
292 ok
= gRegistryRoot
->init();
294 gIONameKey
= OSSymbol::withCStringNoCopy( "IOName" );
295 gIOLocationKey
= OSSymbol::withCStringNoCopy( "IOLocation" );
297 assert( ok
&& gIONameKey
&& gIOLocationKey
);
299 gRegistryRoot
->setName( "Root" );
300 gRegistryRoot
->setProperty( kIORegistryPlanesKey
, gIORegistryPlanes
);
303 return( gRegistryRoot
);
306 IORegistryEntry
* IORegistryEntry::getRegistryRoot( void )
308 return( gRegistryRoot
);
311 SInt32
IORegistryEntry::getGenerationCount( void )
313 return( gIORegistryGenerationCount
);
317 const IORegistryPlane
* IORegistryEntry::makePlane( const char * name
)
319 IORegistryPlane
* plane
;
320 const OSSymbol
* nameKey
;
321 const OSSymbol
* parentKey
;
322 const OSSymbol
* childKey
;
323 const OSSymbol
* pathNameKey
;
324 const OSSymbol
* pathLocationKey
;
325 char key
[ kIOMaxPlaneName
+ 16 ];
328 strncpy( key
, name
, kIOMaxPlaneName
);
329 key
[ kIOMaxPlaneName
] = 0;
330 end
= key
+ strlen( name
);
332 nameKey
= OSSymbol::withCString( key
);
334 strcpy( end
, kIORegPlaneParentSuffix
);
335 parentKey
= OSSymbol::withCString( key
);
337 strcpy( end
, kIORegPlaneChildSuffix
);
338 childKey
= OSSymbol::withCString( key
);
340 strcpy( end
, kIORegPlaneNameSuffix
);
341 pathNameKey
= OSSymbol::withCString( key
);
343 strcpy( end
, kIORegPlaneLocationSuffix
);
344 pathLocationKey
= OSSymbol::withCString( key
);
346 plane
= new IORegistryPlane
;
348 if( plane
&& plane
->init()
349 && nameKey
&& parentKey
&& childKey
350 && pathNameKey
&& pathLocationKey
) {
352 plane
->nameKey
= nameKey
;
353 plane
->keys
[ kParentSetIndex
] = parentKey
;
354 plane
->keys
[ kChildSetIndex
] = childKey
;
355 plane
->pathNameKey
= pathNameKey
;
356 plane
->pathLocationKey
= pathLocationKey
;
359 gIORegistryPlanes
->setObject( nameKey
, plane
);
367 pathLocationKey
->release();
369 pathNameKey
->release();
371 parentKey
->release();
382 const IORegistryPlane
* IORegistryEntry::getPlane( const char * name
)
384 const IORegistryPlane
* plane
;
387 plane
= (const IORegistryPlane
*) gIORegistryPlanes
->getObject( name
);
393 bool IORegistryPlane::serialize(OSSerialize
*s
) const
395 return( nameKey
->serialize(s
) );
398 enum { kIORegCapacityIncrement
= 4 };
400 bool IORegistryEntry::init( OSDictionary
* dict
)
410 fPropertyTable
->release();
411 fPropertyTable
= dict
;
413 } else if( !fPropertyTable
) {
414 fPropertyTable
= OSDictionary::withCapacity( kIORegCapacityIncrement
);
416 fPropertyTable
->setCapacityIncrement( kIORegCapacityIncrement
);
422 #ifdef IOREGSPLITTABLES
423 if( !fRegistryTable
) {
424 fRegistryTable
= OSDictionary::withCapacity( kIORegCapacityIncrement
);
426 fRegistryTable
->setCapacityIncrement( kIORegCapacityIncrement
);
429 if( (prop
= OSDynamicCast( OSString
, getProperty( gIONameKey
)))) {
430 OSSymbol
* sym
= (OSSymbol
*)OSSymbol::withString( prop
);
431 // ok for OSSymbol too
436 #endif /* IOREGSPLITTABLES */
441 bool IORegistryEntry::init( IORegistryEntry
* old
,
442 const IORegistryPlane
* plane
)
445 IORegistryEntry
* next
;
453 fPropertyTable
= old
->getPropertyTable();
454 fPropertyTable
->retain();
455 #ifdef IOREGSPLITTABLES
456 fRegistryTable
= old
->fRegistryTable
;
457 old
->fRegistryTable
= OSDictionary::withDictionary( fRegistryTable
);
458 #endif /* IOREGSPLITTABLES */
460 old
->registryTable()->removeObject( plane
->keys
[ kParentSetIndex
] );
461 old
->registryTable()->removeObject( plane
->keys
[ kChildSetIndex
] );
463 all
= getParentSetReference( plane
);
464 if( all
) for( index
= 0;
465 (next
= (IORegistryEntry
*) all
->getObject(index
));
467 next
->makeLink( this, kChildSetIndex
, plane
);
468 next
->breakLink( old
, kChildSetIndex
, plane
);
471 all
= getChildSetReference( plane
);
472 if( all
) for( index
= 0;
473 (next
= (IORegistryEntry
*) all
->getObject(index
));
475 next
->makeLink( this, kParentSetIndex
, plane
);
476 next
->breakLink( old
, kParentSetIndex
, plane
);
484 void IORegistryEntry::free( void )
488 #define msg ": attached at free()"
489 char buf
[ strlen(msg
) + 40 ];
491 if( registryTable() && gIOServicePlane
) {
492 if( getParentSetReference( gIOServicePlane
)
493 || getChildSetReference( gIOServicePlane
)) {
495 strncpy( buf
, getName(), 32);
503 if( getPropertyTable())
504 getPropertyTable()->release();
506 #ifdef IOREGSPLITTABLES
508 registryTable()->release();
509 #endif /* IOREGSPLITTABLES */
514 void IORegistryEntry::setPropertyTable( OSDictionary
* dict
)
517 fPropertyTable
->release();
520 fPropertyTable
= dict
;
523 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
525 /* Wrappers to synchronize property table */
527 #define wrap2(type, constant) \
529 IORegistryEntry::copyProperty( type * aKey) constant \
534 obj = getProperty( aKey ); \
542 #define wrap4(type,constant) \
544 IORegistryEntry::getProperty( type * aKey, \
545 const IORegistryPlane * plane, \
546 IOOptionBits options ) constant \
548 OSObject * obj = getProperty( aKey ); \
550 if ( (0 == obj) && plane && (options & kIORegistryIterateRecursively) ) { \
551 IORegistryEntry * entry = (IORegistryEntry *) this; \
552 IORegistryIterator * iter; \
553 iter = IORegistryIterator::iterateOver( entry, plane, options ); \
556 while ( (0 == obj) && (entry = iter->getNextObject()) ) { \
557 obj = entry->getProperty( aKey ); \
566 #define wrap5(type,constant) \
568 IORegistryEntry::copyProperty( type * aKey, \
569 const IORegistryPlane * plane, \
570 IOOptionBits options ) constant \
572 OSObject * obj = copyProperty( aKey ); \
574 if ( (0 == obj) && plane && (options & kIORegistryIterateRecursively) ) { \
575 IORegistryEntry * entry = (IORegistryEntry *) this; \
576 IORegistryIterator * iter; \
577 iter = IORegistryIterator::iterateOver( entry, plane, options ); \
580 while ( (0 == obj) && (entry = iter->getNextObject()) ) { \
581 obj = entry->copyProperty( aKey ); \
590 bool IORegistryEntry::serializeProperties( OSSerialize
* s
) const
592 // setProperty( getRetainCount(), 32, "__retain" );
595 OSCollection
*snapshotProperties
= getPropertyTable()->copyCollection();
598 bool ok
= snapshotProperties
->serialize( s
);
599 snapshotProperties
->release();
603 OSDictionary
* IORegistryEntry::dictionaryWithProperties( void ) const
608 dict
= OSDictionary::withDictionary( getPropertyTable(),
609 getPropertyTable()->getCapacity() );
615 IOReturn
IORegistryEntry::setProperties( OSObject
* properties
)
617 return( kIOReturnUnsupported
);
620 wrap2(const OSSymbol
, const) // copyProperty() definition
621 wrap2(const OSString
, const) // copyProperty() definition
622 wrap2(const char, const) // copyProperty() definition
624 wrap4(const OSSymbol
, const) // getProperty() w/plane definition
625 wrap4(const OSString
, const) // getProperty() w/plane definition
626 wrap4(const char, const) // getProperty() w/plane definition
628 wrap5(const OSSymbol
, const) // copyProperty() w/plane definition
629 wrap5(const OSString
, const) // copyProperty() w/plane definition
630 wrap5(const char, const) // copyProperty() w/plane definition
634 IORegistryEntry::getProperty( const OSSymbol
* aKey
) const
639 obj
= getPropertyTable()->getObject( aKey
);
646 IORegistryEntry::removeProperty( const OSSymbol
* aKey
)
649 getPropertyTable()->removeObject( aKey
);
654 IORegistryEntry::setProperty( const OSSymbol
* aKey
, OSObject
* anObject
)
658 // If we are inserting a collection class and the current entry
659 // is attached into the registry (inPlane()) then mark the collection
661 OSCollection
*coll
= OSDynamicCast(OSCollection
, anObject
);
662 bool makeImmutable
= (coll
&& inPlane());
666 coll
->setOptions( OSCollection::kMASK
, OSCollection::kImmutable
);
668 ret
= getPropertyTable()->setObject( aKey
, anObject
);
674 IOReturn
IORegistryEntry::
675 runPropertyAction(Action inAction
, OSObject
*target
,
676 void *arg0
, void *arg1
, void *arg2
, void *arg3
)
680 // closeGate is recursive so don't worry if we already hold the lock.
682 res
= (*inAction
)(target
, arg0
, arg1
, arg2
, arg3
);
689 IORegistryEntry::getProperty( const OSString
* aKey
) const
691 const OSSymbol
* tmpKey
= OSSymbol::withString( aKey
);
692 OSObject
* obj
= getProperty( tmpKey
);
699 IORegistryEntry::getProperty( const char * aKey
) const
701 const OSSymbol
* tmpKey
= OSSymbol::withCString( aKey
);
702 OSObject
* obj
= getProperty( tmpKey
);
710 IORegistryEntry::removeProperty( const OSString
* aKey
)
712 const OSSymbol
* tmpKey
= OSSymbol::withString( aKey
);
713 removeProperty( tmpKey
);
718 IORegistryEntry::removeProperty( const char * aKey
)
720 const OSSymbol
* tmpKey
= OSSymbol::withCString( aKey
);
721 removeProperty( tmpKey
);
726 IORegistryEntry::setProperty( const OSString
* aKey
, OSObject
* anObject
)
728 const OSSymbol
* tmpKey
= OSSymbol::withString( aKey
);
729 bool ret
= setProperty( tmpKey
, anObject
);
736 IORegistryEntry::setProperty( const char * aKey
, OSObject
* anObject
)
738 const OSSymbol
* tmpKey
= OSSymbol::withCString( aKey
);
739 bool ret
= setProperty( tmpKey
, anObject
);
746 IORegistryEntry::setProperty(const char * aKey
, const char * aString
)
749 OSSymbol
* aSymbol
= (OSSymbol
*) OSSymbol::withCString( aString
);
752 const OSSymbol
* tmpKey
= OSSymbol::withCString( aKey
);
753 ret
= setProperty( tmpKey
, aSymbol
);
762 IORegistryEntry::setProperty(const char * aKey
, bool aBoolean
)
765 OSBoolean
* aBooleanObj
= OSBoolean::withBoolean( aBoolean
);
768 const OSSymbol
* tmpKey
= OSSymbol::withCString( aKey
);
769 ret
= setProperty( tmpKey
, aBooleanObj
);
772 aBooleanObj
->release();
778 IORegistryEntry::setProperty( const char * aKey
,
779 unsigned long long aValue
,
780 unsigned int aNumberOfBits
)
783 OSNumber
* anOffset
= OSNumber::withNumber( aValue
, aNumberOfBits
);
786 const OSSymbol
* tmpKey
= OSSymbol::withCString( aKey
);
787 ret
= setProperty( tmpKey
, anOffset
);
796 IORegistryEntry::setProperty( const char * aKey
,
801 OSData
* data
= OSData::withBytes( bytes
, length
);
804 const OSSymbol
* tmpKey
= OSSymbol::withCString( aKey
);
805 ret
= setProperty( tmpKey
, data
);
813 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
815 /* Name, location, paths */
817 const char * IORegistryEntry::getName( const IORegistryPlane
* plane
) const
823 sym
= (OSSymbol
*) registryTable()->getObject( plane
->pathNameKey
);
825 sym
= (OSSymbol
*) registryTable()->getObject( gIONameKey
);
829 return( sym
->getCStringNoCopy());
831 return( (getMetaClass())->getClassName());
834 const OSSymbol
* IORegistryEntry::copyName(
835 const IORegistryPlane
* plane
) const
841 sym
= (OSSymbol
*) registryTable()->getObject( plane
->pathNameKey
);
843 sym
= (OSSymbol
*) registryTable()->getObject( gIONameKey
);
851 return( OSSymbol::withCString((getMetaClass())->getClassName()) );
854 const OSSymbol
* IORegistryEntry::copyLocation(
855 const IORegistryPlane
* plane
) const
861 sym
= (OSSymbol
*) registryTable()->getObject( plane
->pathLocationKey
);
863 sym
= (OSSymbol
*) registryTable()->getObject( gIOLocationKey
);
871 const char * IORegistryEntry::getLocation( const IORegistryPlane
* plane
) const
873 const OSSymbol
* sym
= copyLocation( plane
);
874 const char * result
= 0;
877 result
= sym
->getCStringNoCopy();
884 void IORegistryEntry::setName( const OSSymbol
* name
,
885 const IORegistryPlane
* plane
)
887 const OSSymbol
* key
;
891 key
= plane
->pathNameKey
;
896 registryTable()->setObject( key
, (OSObject
*) name
);
901 void IORegistryEntry::setName( const char * name
,
902 const IORegistryPlane
* plane
)
904 OSSymbol
* sym
= (OSSymbol
*)OSSymbol::withCString( name
);
906 setName( sym
, plane
);
911 void IORegistryEntry::setLocation( const OSSymbol
* location
,
912 const IORegistryPlane
* plane
)
914 const OSSymbol
* key
;
918 key
= plane
->pathLocationKey
;
920 key
= gIOLocationKey
;
923 registryTable()->setObject( key
, (OSObject
*) location
);
928 void IORegistryEntry::setLocation( const char * location
,
929 const IORegistryPlane
* plane
)
931 OSSymbol
* sym
= (OSSymbol
*)OSSymbol::withCString( location
);
933 setLocation( sym
, plane
);
939 IORegistryEntry::compareName( OSString
* name
, OSString
** matched
) const
941 const OSSymbol
* sym
= copyName();
944 isEqual
= sym
->isEqualTo( name
);
946 if( isEqual
&& matched
) {
958 IORegistryEntry::compareNames( OSObject
* names
, OSString
** matched
) const
961 OSCollection
* collection
;
962 OSIterator
* iter
= 0;
965 if( (collection
= OSDynamicCast( OSCollection
, names
))) {
966 iter
= OSCollectionIterator::withCollection( collection
);
969 string
= OSDynamicCast( OSString
, names
);
973 result
= compareName( string
, matched
);
975 } while( (false == result
)
976 && iter
&& (string
= OSDynamicCast( OSString
, iter
->getNextObject())));
985 bool IORegistryEntry::getPath( char * path
, int * length
,
986 const IORegistryPlane
* plane
) const
989 IORegistryEntry
* root
;
990 const IORegistryEntry
* entry
;
991 IORegistryEntry
* parent
;
992 const OSSymbol
* alias
;
994 int len
, maxLength
, compLen
;
998 if( !path
|| !length
|| !plane
)
1002 maxLength
= *length
- 2;
1005 len
= plane
->nameKey
->getLength();
1006 if( len
>= maxLength
)
1008 strcpy( nextComp
, plane
->nameKey
->getCStringNoCopy());
1009 nextComp
[ len
++ ] = ':';
1012 if( (alias
= hasAlias( plane
))) {
1013 len
+= alias
->getLength();
1014 ok
= (maxLength
> len
);
1017 strcpy( nextComp
, alias
->getCStringNoCopy());
1022 parent
= entry
->getParentEntry( plane
);
1024 // Error if not attached in plane
1027 stack
= OSArray::withCapacity( getDepth( plane
));
1033 root
= gRegistryRoot
->getChildEntry( plane
);
1034 while( parent
&& (entry
!= root
)) {
1036 stack
->setObject( (OSObject
*) entry
);
1038 parent
= entry
->getParentEntry( plane
);
1041 index
= stack
->getCount();
1050 } else while( ok
&& ((--index
) >= 0)) {
1052 entry
= (IORegistryEntry
*) stack
->getObject((unsigned int) index
);
1055 if( (alias
= entry
->hasAlias( plane
))) {
1056 len
= plane
->nameKey
->getLength() + 1;
1057 nextComp
= path
+ len
;
1059 compLen
= alias
->getLength();
1060 ok
= (maxLength
> len
+ compLen
);
1062 strcpy( nextComp
, alias
->getCStringNoCopy());
1064 compLen
= maxLength
- len
;
1065 ok
= entry
->getPathComponent( nextComp
+ 1, &compLen
, plane
);
1067 if( ok
&& compLen
) {
1075 nextComp
+= compLen
;
1087 bool IORegistryEntry::getPathComponent( char * path
, int * length
,
1088 const IORegistryPlane
* plane
) const
1090 int len
, locLen
, maxLength
;
1091 const char * compName
;
1095 maxLength
= *length
;
1097 compName
= getName( plane
);
1098 len
= strlen( compName
);
1099 if( (loc
= getLocation( plane
)))
1100 locLen
= 1 + strlen( loc
);
1104 ok
= ((len
+ locLen
) < maxLength
);
1106 strcpy( path
, compName
);
1111 strcpy( path
, loc
);
1119 const char * IORegistryEntry::matchPathLocation( const char * cmp
,
1120 const IORegistryPlane
* plane
)
1123 const char * result
= 0;
1124 u_quad_t num1
, num2
;
1125 char lastPathChar
, lastLocationChar
;
1127 str
= getLocation( plane
);
1129 lastPathChar
= cmp
[0];
1130 lastLocationChar
= str
[0];
1133 num1
= strtouq( cmp
, (char **) &cmp
, 16 );
1134 lastPathChar
= *cmp
++;
1138 if( lastLocationChar
) {
1139 num2
= strtouq( str
, (char **) &str
, 16 );
1140 lastLocationChar
= *str
++;
1147 if (!lastPathChar
&& !lastLocationChar
) {
1152 if( (',' != lastPathChar
) && (':' != lastPathChar
))
1155 if (lastPathChar
&& lastLocationChar
&& (lastPathChar
!= lastLocationChar
))
1164 IORegistryEntry
* IORegistryEntry::getChildFromComponent( const char ** opath
,
1165 const IORegistryPlane
* plane
)
1167 IORegistryEntry
* entry
= 0;
1171 const char * cmp
= 0;
1176 set
= getChildSetReference( plane
);
1182 (entry
= (IORegistryEntry
*) set
->getObject(index
));
1188 str
= entry
->getName( plane
);
1189 len
= strlen( str
);
1190 if( strncmp( str
, cmp
, len
))
1195 if( (c
== 0) || (c
== '/') || (c
== ':'))
1201 if( (cmp
= entry
->matchPathLocation( cmp
, plane
)))
1211 const OSSymbol
* IORegistryEntry::hasAlias( const IORegistryPlane
* plane
,
1212 char * opath
, int * length
) const
1214 IORegistryEntry
* entry
;
1215 IORegistryEntry
* entry2
;
1216 const OSSymbol
* key
;
1217 const OSSymbol
* bestKey
= 0;
1220 const char * path
= "/aliases";
1222 entry
= IORegistryEntry::fromPath( path
, plane
);
1225 if( (iter
= OSCollectionIterator::withCollection(
1226 entry
->getPropertyTable() ))) {
1228 while( (key
= (OSSymbol
*) iter
->getNextObject())) {
1230 data
= (OSData
*) entry
->getProperty( key
);
1231 path
= (const char *) data
->getBytesNoCopy();
1232 if( (entry2
= IORegistryEntry::fromPath( path
, plane
,
1234 if( this == entry2
) {
1236 || (bestKey
->getLength() > key
->getLength()))
1237 // pick the smallest alias
1251 const char * IORegistryEntry::dealiasPath(
1252 const char ** opath
,
1253 const IORegistryPlane
* plane
)
1255 IORegistryEntry
* entry
;
1257 const char * path
= *opath
;
1258 const char * rpath
= 0;
1261 char temp
[ kIOMaxPlaneName
+ 1 ];
1268 while( (c
= *end
++) && (c
!= '/') && (c
!= ':'))
1271 if( (end
- path
) < kIOMaxPlaneName
) {
1272 strncpy( temp
, path
, end
- path
);
1273 temp
[ end
- path
] = 0;
1276 entry
= IORegistryEntry::fromPath( "/aliases", plane
);
1278 data
= (OSData
*) entry
->getProperty( temp
);
1280 rpath
= (const char *) data
->getBytesNoCopy();
1292 IORegistryEntry
* IORegistryEntry::fromPath(
1294 const IORegistryPlane
* plane
,
1297 IORegistryEntry
* fromEntry
)
1299 IORegistryEntry
* where
= 0;
1300 IORegistryEntry
* aliasEntry
= 0;
1301 IORegistryEntry
* next
;
1307 char temp
[ kIOMaxPlaneName
+ 1 ];
1314 end
= strchr( path
, ':' );
1315 if( end
&& ((end
- path
) < kIOMaxPlaneName
)) {
1316 strncpy( temp
, path
, end
- path
);
1317 temp
[ end
- path
] = 0;
1318 plane
= getPlane( temp
);
1327 if( (alias
= dealiasPath( &end
, plane
))) {
1330 aliasEntry
= IORegistryEntry::fromPath( alias
, plane
,
1331 opath
, &len
, fromEntry
);
1343 if( (0 == fromEntry
) && (*path
++ == '/'))
1344 fromEntry
= gRegistryRoot
->getChildEntry( plane
);
1351 if( c
&& (c
!= ':')) // check valid terminator
1356 next
= where
->getChildFromComponent( &path
, plane
);
1362 // check residual path
1363 if( where
!= fromEntry
)
1366 if( opath
&& length
) {
1367 // copy out residual path
1368 len2
= len
+ strlen( path
);
1370 strcpy( opath
+ len
, path
);
1374 // no residual path => must be no tail for success
1381 aliasEntry
->release();
1388 IORegistryEntry
* IORegistryEntry::childFromPath(
1390 const IORegistryPlane
* plane
,
1394 return( IORegistryEntry::fromPath( path
, plane
, opath
, len
, this ));
1397 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1399 #define IOLinkIterator OSCollectionIterator
1402 #define super OSObject
1404 inline bool IORegistryEntry::arrayMember( OSArray
* set
,
1405 const IORegistryEntry
* member
,
1406 unsigned int * index
) const
1409 OSObject
* probeObject
;
1411 for( i
= 0; (probeObject
= set
->getObject(i
)); i
++) {
1412 if (probeObject
== (OSObject
*) member
) {
1421 bool IORegistryEntry::makeLink( IORegistryEntry
* to
,
1422 unsigned int relation
,
1423 const IORegistryPlane
* plane
) const
1426 bool result
= false;
1428 if( (links
= (OSArray
*)
1429 registryTable()->getObject( plane
->keys
[ relation
] ))) {
1431 result
= arrayMember( links
, to
);
1433 result
= links
->setObject( to
);
1437 links
= OSArray::withObjects( (const OSObject
**) &to
, 1, 1 );
1438 result
= (links
!= 0);
1440 result
= registryTable()->setObject( plane
->keys
[ relation
],
1449 void IORegistryEntry::breakLink( IORegistryEntry
* to
,
1450 unsigned int relation
,
1451 const IORegistryPlane
* plane
) const
1456 if( (links
= (OSArray
*)
1457 registryTable()->getObject( plane
->keys
[ relation
]))) {
1459 if( arrayMember( links
, to
, &index
)) {
1460 links
->removeObject( index
);
1461 if( 0 == links
->getCount())
1462 registryTable()->removeObject( plane
->keys
[ relation
]);
1468 OSArray
* IORegistryEntry::getParentSetReference(
1469 const IORegistryPlane
* plane
) const
1472 return( (OSArray
*) registryTable()->getObject(
1473 plane
->keys
[ kParentSetIndex
]));
1478 OSIterator
* IORegistryEntry::getParentIterator(
1479 const IORegistryPlane
* plane
) const
1488 links
= getParentSetReference( plane
);
1490 links
= OSArray::withCapacity( 1 );
1492 links
= OSArray::withArray( links
, links
->getCount() );
1495 iter
= IOLinkIterator::withCollection( links
);
1503 IORegistryEntry
* IORegistryEntry::copyParentEntry( const IORegistryPlane
* plane
) const
1505 IORegistryEntry
* entry
= 0;
1510 if( (links
= getParentSetReference( plane
))) {
1511 entry
= (IORegistryEntry
*) links
->getObject( 0 );
1520 IORegistryEntry
* IORegistryEntry::getParentEntry( const IORegistryPlane
* plane
) const
1522 IORegistryEntry
* entry
;
1524 entry
= copyParentEntry( plane
);
1531 OSArray
* IORegistryEntry::getChildSetReference( const IORegistryPlane
* plane
) const
1534 return( (OSArray
*) registryTable()->getObject(
1535 plane
->keys
[ kChildSetIndex
]));
1540 OSIterator
* IORegistryEntry::getChildIterator( const IORegistryPlane
* plane
) const
1549 links
= getChildSetReference( plane
);
1551 links
= OSArray::withCapacity( 1 );
1553 links
= OSArray::withArray( links
, links
->getCount() );
1556 iter
= IOLinkIterator::withCollection( links
);
1565 IORegistryEntry
* IORegistryEntry::copyChildEntry(
1566 const IORegistryPlane
* plane
) const
1568 IORegistryEntry
* entry
= 0;
1573 if( (links
= getChildSetReference( plane
))) {
1574 entry
= (IORegistryEntry
*) links
->getObject( 0 );
1583 IORegistryEntry
* IORegistryEntry::getChildEntry(
1584 const IORegistryPlane
* plane
) const
1586 IORegistryEntry
* entry
;
1588 entry
= copyChildEntry( plane
);
1595 void IORegistryEntry::applyToChildren( IORegistryEntryApplierFunction applier
,
1597 const IORegistryPlane
* plane
) const
1601 IORegistryEntry
* next
;
1607 array
= OSArray::withArray( getChildSetReference( plane
));
1611 (next
= (IORegistryEntry
*) array
->getObject( index
));
1613 (*applier
)(next
, context
);
1618 void IORegistryEntry::applyToParents( IORegistryEntryApplierFunction applier
,
1620 const IORegistryPlane
* plane
) const
1624 IORegistryEntry
* next
;
1630 array
= OSArray::withArray( getParentSetReference( plane
));
1634 (next
= (IORegistryEntry
*) array
->getObject( index
));
1636 (*applier
)(next
, context
);
1641 bool IORegistryEntry::isChild( IORegistryEntry
* child
,
1642 const IORegistryPlane
* plane
,
1643 bool onlyChild
) const
1650 if( (links
= getChildSetReference( plane
))) {
1651 if( (!onlyChild
) || (1 == links
->getCount()))
1652 ret
= arrayMember( links
, child
);
1654 if( ret
&& (links
= child
->getParentSetReference( plane
)))
1655 ret
= arrayMember( links
, this );
1662 bool IORegistryEntry::isParent( IORegistryEntry
* parent
,
1663 const IORegistryPlane
* plane
,
1664 bool onlyParent
) const
1672 if( (links
= getParentSetReference( plane
))) {
1673 if( (!onlyParent
) || (1 == links
->getCount()))
1674 ret
= arrayMember( links
, parent
);
1676 if( ret
&& (links
= parent
->getChildSetReference( plane
)))
1677 ret
= arrayMember( links
, this );
1684 bool IORegistryEntry::inPlane( const IORegistryPlane
* plane
) const
1691 ret
= (0 != getParentSetReference( plane
));
1694 // Check to see if this is in any plane. If it is in a plane
1695 // then the registryTable will contain a key with the ParentLinks
1696 // suffix. When we iterate over the keys looking for that suffix
1699 OSCollectionIterator
*iter
=
1700 OSCollectionIterator::withCollection( registryTable());
1702 const OSSymbol
*key
;
1704 while( (key
= (OSSymbol
*) iter
->getNextObject()) ) {
1705 const char *keysuffix
;
1707 // Get a pointer to this keys suffix
1708 keysuffix
= key
->getCStringNoCopy()
1709 + key
->getLength() - kIORegPlaneParentSuffixLen
;
1710 if( !strcmp(keysuffix
, kIORegPlaneParentSuffix
) ) {
1724 bool IORegistryEntry::attachToParent( IORegistryEntry
* parent
,
1725 const IORegistryPlane
* plane
)
1736 ret
= makeLink( parent
, kParentSetIndex
, plane
);
1738 if( (links
= parent
->getChildSetReference( plane
)))
1739 needParent
= (false == arrayMember( links
, this ));
1747 // Mark any collections in the property list as immutable
1748 OSDictionary
*ptable
= getPropertyTable();
1749 OSCollectionIterator
*iter
=
1750 OSCollectionIterator::withCollection( ptable
);
1752 const OSSymbol
*key
;
1754 while( (key
= (OSSymbol
*) iter
->getNextObject( ))) {
1755 // Is object for key a collection?
1756 OSCollection
*coll
=
1757 OSDynamicCast( OSCollection
, ptable
->getObject( key
));
1760 // Yup so mark it as immutable
1761 coll
->setOptions( OSCollection::kMASK
,
1762 OSCollection::kImmutable
);
1771 ret
&= parent
->attachToChild( this, plane
);
1776 bool IORegistryEntry::attachToChild( IORegistryEntry
* child
,
1777 const IORegistryPlane
* plane
)
1788 ret
= makeLink( child
, kChildSetIndex
, plane
);
1790 if( (links
= child
->getParentSetReference( plane
)))
1791 needChild
= (false == arrayMember( links
, this ));
1798 ret
&= child
->attachToParent( this, plane
);
1803 void IORegistryEntry::detachFromParent( IORegistryEntry
* parent
,
1804 const IORegistryPlane
* plane
)
1813 breakLink( parent
, kParentSetIndex
, plane
);
1815 if( (links
= parent
->getChildSetReference( plane
)))
1816 needParent
= arrayMember( links
, this );
1820 // parent->breakLink( this, kChildSetIndex, plane );
1825 parent
->detachFromChild( this, plane
);
1830 void IORegistryEntry::detachFromChild( IORegistryEntry
* child
,
1831 const IORegistryPlane
* plane
)
1840 breakLink( child
, kChildSetIndex
, plane
);
1842 if( (links
= child
->getParentSetReference( plane
)))
1843 needChild
= arrayMember( links
, this );
1850 child
->detachFromParent( this, plane
);
1855 void IORegistryEntry::detachAbove( const IORegistryPlane
* plane
)
1857 IORegistryEntry
* parent
;
1860 while( (parent
= getParentEntry( plane
)))
1861 detachFromParent( parent
, plane
);
1865 void IORegistryEntry::detachAll( const IORegistryPlane
* plane
)
1868 IORegistryEntry
* next
;
1869 IORegistryIterator
* regIter
;
1871 regIter
= IORegistryIterator::iterateOver( this, plane
, true );
1874 all
= regIter
->iterateAll();
1877 detachAbove( plane
);
1879 while( (next
= (IORegistryEntry
*) all
->getLastObject())) {
1882 all
->removeObject(next
);
1884 next
->detachAbove( plane
);
1891 unsigned int IORegistryEntry::getDepth( const IORegistryPlane
* plane
) const
1893 unsigned int depth
= 1;
1895 unsigned int oneDepth
, maxParentDepth
, count
;
1896 IORegistryEntry
* one
;
1897 const IORegistryEntry
* next
;
1903 while( (parents
= next
->getParentSetReference( plane
))) {
1905 count
= parents
->getCount();
1910 next
= (IORegistryEntry
*) parents
->getObject( 0 );
1915 (one
= (IORegistryEntry
*) parents
->getObject( index
));
1917 oneDepth
= one
->getDepth( plane
);
1918 if( oneDepth
> maxParentDepth
)
1919 maxParentDepth
= oneDepth
;
1921 depth
+= maxParentDepth
;
1931 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1934 #define super OSIterator
1936 OSDefineMetaClassAndStructors(IORegistryIterator
, OSIterator
)
1938 enum { kIORegistryIteratorInvalidFlag
= 0x80000000 };
1940 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1942 IORegistryIterator
*
1943 IORegistryIterator::iterateOver( IORegistryEntry
* root
,
1944 const IORegistryPlane
* plane
,
1945 IOOptionBits options
)
1947 IORegistryIterator
* create
;
1954 create
= new IORegistryIterator
;
1956 if( create
->init()) {
1959 create
->root
= root
;
1960 create
->where
= &create
->start
;
1961 create
->start
.current
= root
;
1962 create
->plane
= plane
;
1963 create
->options
= options
& ~kIORegistryIteratorInvalidFlag
;
1973 IORegistryIterator
*
1974 IORegistryIterator::iterateOver( const IORegistryPlane
* plane
,
1975 IOOptionBits options
)
1977 return( iterateOver( gRegistryRoot
, plane
, options
));
1980 bool IORegistryIterator::isValid( void )
1989 ok
= (0 == (kIORegistryIteratorInvalidFlag
& options
));
1991 while( ok
&& next
) {
1993 ok
= where
->iter
->isValid();
2001 void IORegistryIterator::enterEntry( const IORegistryPlane
* enterPlane
)
2006 where
= (IORegCursor
*) IOMalloc( sizeof( IORegCursor
));
2012 where
->current
= prev
->current
;
2017 void IORegistryIterator::enterEntry( void )
2019 enterEntry( plane
);
2022 bool IORegistryIterator::exitEntry( void )
2027 where
->iter
->release();
2029 if( where
->current
)// && (where != &start))
2030 where
->current
->release();
2033 if( where
!= &start
) {
2036 IOFree( gone
, sizeof( IORegCursor
));
2043 void IORegistryIterator::reset( void )
2053 where
->current
= root
;
2054 options
&= ~kIORegistryIteratorInvalidFlag
;
2057 void IORegistryIterator::free( void )
2068 IORegistryEntry
* IORegistryIterator::getNextObjectFlat( void )
2070 IORegistryEntry
* next
= 0;
2071 OSArray
* links
= 0;
2075 if( (0 == where
->iter
)) {
2076 // just entered - create new iter
2079 && (links
= ( (options
& kIORegistryIterateParents
) ?
2080 where
->current
->getParentSetReference( plane
) :
2081 where
->current
->getChildSetReference( plane
) )) )
2083 where
->iter
= OSCollectionIterator::withCollection( links
);
2086 // next sibling - release current
2088 where
->current
->release();
2092 next
= (IORegistryEntry
*) where
->iter
->getNextObject();
2096 else if( !where
->iter
->isValid())
2097 options
|= kIORegistryIteratorInvalidFlag
;
2100 where
->current
= next
;
2107 IORegistryEntry
* IORegistryIterator::getNextObjectRecursive( void )
2109 IORegistryEntry
* next
;
2112 next
= getNextObjectFlat();
2113 while( (0 == next
) && exitEntry());
2117 done
= OSOrderedSet::withCapacity( 10 );
2118 if( done
->setObject((OSObject
*) next
)) {
2119 // done set didn't contain this one, so recurse
2126 IORegistryEntry
* IORegistryIterator::getNextObject( void )
2128 if( options
& kIORegistryIterateRecursively
)
2129 return( getNextObjectRecursive());
2131 return( getNextObjectFlat());
2134 IORegistryEntry
* IORegistryIterator::getCurrentEntry( void )
2137 return( where
->current
);
2142 OSOrderedSet
* IORegistryIterator::iterateAll( void )
2145 while( getNextObjectRecursive())
2152 OSMetaClassDefineReservedUsed(IORegistryEntry
, 0);
2153 OSMetaClassDefineReservedUsed(IORegistryEntry
, 1);
2154 OSMetaClassDefineReservedUsed(IORegistryEntry
, 2);
2155 OSMetaClassDefineReservedUsed(IORegistryEntry
, 3);
2156 OSMetaClassDefineReservedUsed(IORegistryEntry
, 4);
2157 OSMetaClassDefineReservedUsed(IORegistryEntry
, 5);
2159 OSMetaClassDefineReservedUnused(IORegistryEntry
, 6);
2160 OSMetaClassDefineReservedUnused(IORegistryEntry
, 7);
2161 OSMetaClassDefineReservedUnused(IORegistryEntry
, 8);
2162 OSMetaClassDefineReservedUnused(IORegistryEntry
, 9);
2163 OSMetaClassDefineReservedUnused(IORegistryEntry
, 10);
2164 OSMetaClassDefineReservedUnused(IORegistryEntry
, 11);
2165 OSMetaClassDefineReservedUnused(IORegistryEntry
, 12);
2166 OSMetaClassDefineReservedUnused(IORegistryEntry
, 13);
2167 OSMetaClassDefineReservedUnused(IORegistryEntry
, 14);
2168 OSMetaClassDefineReservedUnused(IORegistryEntry
, 15);
2169 OSMetaClassDefineReservedUnused(IORegistryEntry
, 16);
2170 OSMetaClassDefineReservedUnused(IORegistryEntry
, 17);
2171 OSMetaClassDefineReservedUnused(IORegistryEntry
, 18);
2172 OSMetaClassDefineReservedUnused(IORegistryEntry
, 19);
2173 OSMetaClassDefineReservedUnused(IORegistryEntry
, 20);
2174 OSMetaClassDefineReservedUnused(IORegistryEntry
, 21);
2175 OSMetaClassDefineReservedUnused(IORegistryEntry
, 22);
2176 OSMetaClassDefineReservedUnused(IORegistryEntry
, 23);
2177 OSMetaClassDefineReservedUnused(IORegistryEntry
, 24);
2178 OSMetaClassDefineReservedUnused(IORegistryEntry
, 25);
2179 OSMetaClassDefineReservedUnused(IORegistryEntry
, 26);
2180 OSMetaClassDefineReservedUnused(IORegistryEntry
, 27);
2181 OSMetaClassDefineReservedUnused(IORegistryEntry
, 28);
2182 OSMetaClassDefineReservedUnused(IORegistryEntry
, 29);
2183 OSMetaClassDefineReservedUnused(IORegistryEntry
, 30);
2184 OSMetaClassDefineReservedUnused(IORegistryEntry
, 31);
2186 /* inline function implementation */
2187 OSDictionary
* IORegistryEntry::getPropertyTable( void ) const
2188 { return(fPropertyTable
); }