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 s_lock_done( &gIORegistryLock )
91 #define RLOCK s_lock_read( &gIORegistryLock )
92 #define WLOCK s_lock_write( &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 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
112 lck_spin_t interlock
; /* "hardware" interlock field */
113 volatile unsigned int
114 read_count
:16, /* No. of accepted readers */
115 want_upgrade
:1, /* Read-to-write upgrade waiting */
116 want_write
:1, /* Writer is waiting, or
118 waiting
:1, /* Someone is sleeping on lock */
119 can_sleep
:1; /* Can attempts to lock go to sleep? */
122 static struct s_lock_t gIORegistryLock
;
124 /* Time we loop without holding the interlock.
125 * The former is for when we cannot sleep, the latter
126 * for when our thread can go to sleep (loop less)
127 * we shouldn't retake the interlock at all frequently
128 * if we cannot go to sleep, since it interferes with
129 * any other processors. In particular, 100 is too small
130 * a number for powerpc MP systems because of cache
131 * coherency issues and differing lock fetch times between
134 static unsigned int lock_wait_time
[2] = { (unsigned int)-1, 100 } ;
141 (void) memset((void *) l
, 0, sizeof(s_lock_t
));
143 lck_spin_init(&l
->interlock
, IOLockGroup
, LCK_ATTR_NULL
);
144 l
->want_write
= FALSE
;
145 l
->want_upgrade
= FALSE
;
147 l
->can_sleep
= can_sleep
;
152 register s_lock_t
* l
)
156 lck_spin_lock(&l
->interlock
);
159 * Try to acquire the want_write bit.
161 while (l
->want_write
) {
163 i
= lock_wait_time
[l
->can_sleep
? 1 : 0];
165 lck_spin_unlock(&l
->interlock
);
166 while (--i
!= 0 && l
->want_write
)
168 lck_spin_lock(&l
->interlock
);
171 if (l
->can_sleep
&& l
->want_write
) {
173 lck_spin_sleep( &l
->interlock
, LCK_SLEEP_DEFAULT
,
174 (event_t
) l
, THREAD_UNINT
);
175 /* interlock relocked */
178 l
->want_write
= TRUE
;
180 /* Wait for readers (and upgrades) to finish */
182 while ((l
->read_count
!= 0) || l
->want_upgrade
) {
184 i
= lock_wait_time
[l
->can_sleep
? 1 : 0];
186 lck_spin_unlock(&l
->interlock
);
187 while (--i
!= 0 && (l
->read_count
!= 0 ||
190 lck_spin_lock(&l
->interlock
);
193 if (l
->can_sleep
&& (l
->read_count
!= 0 || l
->want_upgrade
)) {
195 lck_spin_sleep( &l
->interlock
, LCK_SLEEP_DEFAULT
,
196 (event_t
) l
, THREAD_UNINT
);
197 /* interlock relocked */
201 lck_spin_unlock(&l
->interlock
);
206 register s_lock_t
* l
)
208 boolean_t do_wakeup
= FALSE
;
210 lck_spin_lock(&l
->interlock
);
212 if (l
->read_count
!= 0) {
216 if (l
->want_upgrade
) {
217 l
->want_upgrade
= FALSE
;
220 l
->want_write
= FALSE
;
225 * There is no reason to wakeup a waiting thread
226 * if the read-count is non-zero. Consider:
227 * we must be dropping a read lock
228 * threads are waiting only if one wants a write lock
229 * if there are still readers, they can't proceed
231 if (l
->waiting
&& (l
->read_count
== 0)) {
236 lck_spin_unlock(&l
->interlock
);
239 thread_wakeup((event_t
) l
);
244 register s_lock_t
* l
)
248 lck_spin_lock(&l
->interlock
);
250 while ( l
->want_upgrade
|| ((0 == l
->read_count
) && l
->want_write
)) {
252 i
= lock_wait_time
[l
->can_sleep
? 1 : 0];
255 lck_spin_unlock(&l
->interlock
);
257 (l
->want_upgrade
|| ((0 == l
->read_count
) && l
->want_write
)))
259 lck_spin_lock(&l
->interlock
);
263 (l
->want_upgrade
|| ((0 == l
->read_count
) && l
->want_write
))) {
265 lck_spin_sleep( &l
->interlock
, LCK_SLEEP_DEFAULT
,
266 (event_t
) l
, THREAD_UNINT
);
267 /* interlock relocked */
272 lck_spin_unlock(&l
->interlock
);
276 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
278 IORegistryEntry
* IORegistryEntry::initialize( void )
282 if( !gRegistryRoot
) {
284 s_lock_init( &gIORegistryLock
, true );
285 gRegistryRoot
= new IORegistryEntry
;
286 gPropertiesLock
= IORecursiveLockAlloc();
287 gIORegistryPlanes
= OSDictionary::withCapacity( 1 );
289 assert( gRegistryRoot
&& gPropertiesLock
290 && gIORegistryPlanes
);
291 ok
= gRegistryRoot
->init();
293 gIONameKey
= OSSymbol::withCStringNoCopy( "IOName" );
294 gIOLocationKey
= OSSymbol::withCStringNoCopy( "IOLocation" );
296 assert( ok
&& gIONameKey
&& gIOLocationKey
);
298 gRegistryRoot
->setName( "Root" );
299 gRegistryRoot
->setProperty( kIORegistryPlanesKey
, gIORegistryPlanes
);
302 return( gRegistryRoot
);
305 IORegistryEntry
* IORegistryEntry::getRegistryRoot( void )
307 return( gRegistryRoot
);
310 SInt32
IORegistryEntry::getGenerationCount( void )
312 return( gIORegistryGenerationCount
);
316 const IORegistryPlane
* IORegistryEntry::makePlane( const char * name
)
318 IORegistryPlane
* plane
;
319 const OSSymbol
* nameKey
;
320 const OSSymbol
* parentKey
;
321 const OSSymbol
* childKey
;
322 const OSSymbol
* pathNameKey
;
323 const OSSymbol
* pathLocationKey
;
324 char key
[ kIOMaxPlaneName
+ 16 ];
327 strncpy( key
, name
, kIOMaxPlaneName
);
328 key
[ kIOMaxPlaneName
] = 0;
329 end
= key
+ strlen( name
);
331 nameKey
= OSSymbol::withCString( key
);
333 strcpy( end
, kIORegPlaneParentSuffix
);
334 parentKey
= OSSymbol::withCString( key
);
336 strcpy( end
, kIORegPlaneChildSuffix
);
337 childKey
= OSSymbol::withCString( key
);
339 strcpy( end
, kIORegPlaneNameSuffix
);
340 pathNameKey
= OSSymbol::withCString( key
);
342 strcpy( end
, kIORegPlaneLocationSuffix
);
343 pathLocationKey
= OSSymbol::withCString( key
);
345 plane
= new IORegistryPlane
;
347 if( plane
&& plane
->init()
348 && nameKey
&& parentKey
&& childKey
349 && pathNameKey
&& pathLocationKey
) {
351 plane
->nameKey
= nameKey
;
352 plane
->keys
[ kParentSetIndex
] = parentKey
;
353 plane
->keys
[ kChildSetIndex
] = childKey
;
354 plane
->pathNameKey
= pathNameKey
;
355 plane
->pathLocationKey
= pathLocationKey
;
358 gIORegistryPlanes
->setObject( nameKey
, plane
);
366 pathLocationKey
->release();
368 pathNameKey
->release();
370 parentKey
->release();
381 const IORegistryPlane
* IORegistryEntry::getPlane( const char * name
)
383 const IORegistryPlane
* plane
;
386 plane
= (const IORegistryPlane
*) gIORegistryPlanes
->getObject( name
);
392 bool IORegistryPlane::serialize(OSSerialize
*s
) const
394 return( nameKey
->serialize(s
) );
397 enum { kIORegCapacityIncrement
= 4 };
399 bool IORegistryEntry::init( OSDictionary
* dict
)
409 fPropertyTable
->release();
410 fPropertyTable
= dict
;
412 } else if( !fPropertyTable
) {
413 fPropertyTable
= OSDictionary::withCapacity( kIORegCapacityIncrement
);
415 fPropertyTable
->setCapacityIncrement( kIORegCapacityIncrement
);
421 #ifdef IOREGSPLITTABLES
422 if( !fRegistryTable
) {
423 fRegistryTable
= OSDictionary::withCapacity( kIORegCapacityIncrement
);
425 fRegistryTable
->setCapacityIncrement( kIORegCapacityIncrement
);
428 if( (prop
= OSDynamicCast( OSString
, getProperty( gIONameKey
)))) {
429 OSSymbol
* sym
= (OSSymbol
*)OSSymbol::withString( prop
);
430 // ok for OSSymbol too
435 #endif /* IOREGSPLITTABLES */
440 bool IORegistryEntry::init( IORegistryEntry
* old
,
441 const IORegistryPlane
* plane
)
444 IORegistryEntry
* next
;
452 fPropertyTable
= old
->getPropertyTable();
453 fPropertyTable
->retain();
454 #ifdef IOREGSPLITTABLES
455 fRegistryTable
= old
->fRegistryTable
;
456 old
->fRegistryTable
= OSDictionary::withDictionary( fRegistryTable
);
457 #endif /* IOREGSPLITTABLES */
459 old
->registryTable()->removeObject( plane
->keys
[ kParentSetIndex
] );
460 old
->registryTable()->removeObject( plane
->keys
[ kChildSetIndex
] );
462 all
= getParentSetReference( plane
);
463 if( all
) for( index
= 0;
464 (next
= (IORegistryEntry
*) all
->getObject(index
));
466 next
->makeLink( this, kChildSetIndex
, plane
);
467 next
->breakLink( old
, kChildSetIndex
, plane
);
470 all
= getChildSetReference( plane
);
471 if( all
) for( index
= 0;
472 (next
= (IORegistryEntry
*) all
->getObject(index
));
474 next
->makeLink( this, kParentSetIndex
, plane
);
475 next
->breakLink( old
, kParentSetIndex
, plane
);
483 void IORegistryEntry::free( void )
487 #define msg ": attached at free()"
488 char buf
[ strlen(msg
) + 40 ];
490 if( registryTable() && gIOServicePlane
) {
491 if( getParentSetReference( gIOServicePlane
)
492 || getChildSetReference( gIOServicePlane
)) {
494 strncpy( buf
, getName(), 32);
502 if( getPropertyTable())
503 getPropertyTable()->release();
505 #ifdef IOREGSPLITTABLES
507 registryTable()->release();
508 #endif /* IOREGSPLITTABLES */
513 void IORegistryEntry::setPropertyTable( OSDictionary
* dict
)
516 fPropertyTable
->release();
519 fPropertyTable
= dict
;
522 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
524 /* Wrappers to synchronize property table */
526 #define wrap2(type, constant) \
528 IORegistryEntry::copyProperty( type * aKey) constant \
533 obj = getProperty( aKey ); \
541 #define wrap4(type,constant) \
543 IORegistryEntry::getProperty( type * aKey, \
544 const IORegistryPlane * plane, \
545 IOOptionBits options ) constant \
547 OSObject * obj = getProperty( aKey ); \
549 if ( (0 == obj) && plane && (options & kIORegistryIterateRecursively) ) { \
550 IORegistryEntry * entry = (IORegistryEntry *) this; \
551 IORegistryIterator * iter; \
552 iter = IORegistryIterator::iterateOver( entry, plane, options ); \
555 while ( (0 == obj) && (entry = iter->getNextObject()) ) { \
556 obj = entry->getProperty( aKey ); \
565 #define wrap5(type,constant) \
567 IORegistryEntry::copyProperty( type * aKey, \
568 const IORegistryPlane * plane, \
569 IOOptionBits options ) constant \
571 OSObject * obj = copyProperty( aKey ); \
573 if ( (0 == obj) && plane && (options & kIORegistryIterateRecursively) ) { \
574 IORegistryEntry * entry = (IORegistryEntry *) this; \
575 IORegistryIterator * iter; \
576 iter = IORegistryIterator::iterateOver( entry, plane, options ); \
579 while ( (0 == obj) && (entry = iter->getNextObject()) ) { \
580 obj = entry->copyProperty( aKey ); \
589 bool IORegistryEntry::serializeProperties( OSSerialize
* s
) const
591 // setProperty( getRetainCount(), 32, "__retain" );
594 OSCollection
*snapshotProperties
= getPropertyTable()->copyCollection();
597 bool ok
= snapshotProperties
->serialize( s
);
598 snapshotProperties
->release();
602 OSDictionary
* IORegistryEntry::dictionaryWithProperties( void ) const
607 dict
= OSDictionary::withDictionary( getPropertyTable(),
608 getPropertyTable()->getCapacity() );
614 IOReturn
IORegistryEntry::setProperties( OSObject
* properties
)
616 return( kIOReturnUnsupported
);
619 wrap2(const OSSymbol
, const) // copyProperty() definition
620 wrap2(const OSString
, const) // copyProperty() definition
621 wrap2(const char, const) // copyProperty() definition
623 wrap4(const OSSymbol
, const) // getProperty() w/plane definition
624 wrap4(const OSString
, const) // getProperty() w/plane definition
625 wrap4(const char, const) // getProperty() w/plane definition
627 wrap5(const OSSymbol
, const) // copyProperty() w/plane definition
628 wrap5(const OSString
, const) // copyProperty() w/plane definition
629 wrap5(const char, const) // copyProperty() w/plane definition
633 IORegistryEntry::getProperty( const OSSymbol
* aKey
) const
638 obj
= getPropertyTable()->getObject( aKey
);
645 IORegistryEntry::removeProperty( const OSSymbol
* aKey
)
648 getPropertyTable()->removeObject( aKey
);
653 IORegistryEntry::setProperty( const OSSymbol
* aKey
, OSObject
* anObject
)
657 // If we are inserting a collection class and the current entry
658 // is attached into the registry (inPlane()) then mark the collection
660 OSCollection
*coll
= OSDynamicCast(OSCollection
, anObject
);
661 bool makeImmutable
= (coll
&& inPlane());
665 coll
->setOptions( OSCollection::kMASK
, OSCollection::kImmutable
);
667 ret
= getPropertyTable()->setObject( aKey
, anObject
);
673 IOReturn
IORegistryEntry::
674 runPropertyAction(Action inAction
, OSObject
*target
,
675 void *arg0
, void *arg1
, void *arg2
, void *arg3
)
679 // closeGate is recursive so don't worry if we already hold the lock.
681 res
= (*inAction
)(target
, arg0
, arg1
, arg2
, arg3
);
688 IORegistryEntry::getProperty( const OSString
* aKey
) const
690 const OSSymbol
* tmpKey
= OSSymbol::withString( aKey
);
691 OSObject
* obj
= getProperty( tmpKey
);
698 IORegistryEntry::getProperty( const char * aKey
) const
700 const OSSymbol
* tmpKey
= OSSymbol::withCString( aKey
);
701 OSObject
* obj
= getProperty( tmpKey
);
709 IORegistryEntry::removeProperty( const OSString
* aKey
)
711 const OSSymbol
* tmpKey
= OSSymbol::withString( aKey
);
712 removeProperty( tmpKey
);
717 IORegistryEntry::removeProperty( const char * aKey
)
719 const OSSymbol
* tmpKey
= OSSymbol::withCString( aKey
);
720 removeProperty( tmpKey
);
725 IORegistryEntry::setProperty( const OSString
* aKey
, OSObject
* anObject
)
727 const OSSymbol
* tmpKey
= OSSymbol::withString( aKey
);
728 bool ret
= setProperty( tmpKey
, anObject
);
735 IORegistryEntry::setProperty( const char * aKey
, OSObject
* anObject
)
737 const OSSymbol
* tmpKey
= OSSymbol::withCString( aKey
);
738 bool ret
= setProperty( tmpKey
, anObject
);
745 IORegistryEntry::setProperty(const char * aKey
, const char * aString
)
748 OSSymbol
* aSymbol
= (OSSymbol
*) OSSymbol::withCString( aString
);
751 const OSSymbol
* tmpKey
= OSSymbol::withCString( aKey
);
752 ret
= setProperty( tmpKey
, aSymbol
);
761 IORegistryEntry::setProperty(const char * aKey
, bool aBoolean
)
764 OSBoolean
* aBooleanObj
= OSBoolean::withBoolean( aBoolean
);
767 const OSSymbol
* tmpKey
= OSSymbol::withCString( aKey
);
768 ret
= setProperty( tmpKey
, aBooleanObj
);
771 aBooleanObj
->release();
777 IORegistryEntry::setProperty( const char * aKey
,
778 unsigned long long aValue
,
779 unsigned int aNumberOfBits
)
782 OSNumber
* anOffset
= OSNumber::withNumber( aValue
, aNumberOfBits
);
785 const OSSymbol
* tmpKey
= OSSymbol::withCString( aKey
);
786 ret
= setProperty( tmpKey
, anOffset
);
795 IORegistryEntry::setProperty( const char * aKey
,
800 OSData
* data
= OSData::withBytes( bytes
, length
);
803 const OSSymbol
* tmpKey
= OSSymbol::withCString( aKey
);
804 ret
= setProperty( tmpKey
, data
);
812 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
814 /* Name, location, paths */
816 const char * IORegistryEntry::getName( const IORegistryPlane
* plane
) const
822 sym
= (OSSymbol
*) registryTable()->getObject( plane
->pathNameKey
);
824 sym
= (OSSymbol
*) registryTable()->getObject( gIONameKey
);
828 return( sym
->getCStringNoCopy());
830 return( (getMetaClass())->getClassName());
833 const OSSymbol
* IORegistryEntry::copyName(
834 const IORegistryPlane
* plane
) const
840 sym
= (OSSymbol
*) registryTable()->getObject( plane
->pathNameKey
);
842 sym
= (OSSymbol
*) registryTable()->getObject( gIONameKey
);
850 return( OSSymbol::withCString((getMetaClass())->getClassName()) );
853 const OSSymbol
* IORegistryEntry::copyLocation(
854 const IORegistryPlane
* plane
) const
860 sym
= (OSSymbol
*) registryTable()->getObject( plane
->pathLocationKey
);
862 sym
= (OSSymbol
*) registryTable()->getObject( gIOLocationKey
);
870 const char * IORegistryEntry::getLocation( const IORegistryPlane
* plane
) const
872 const OSSymbol
* sym
= copyLocation( plane
);
873 const char * result
= 0;
876 result
= sym
->getCStringNoCopy();
883 void IORegistryEntry::setName( const OSSymbol
* name
,
884 const IORegistryPlane
* plane
)
886 const OSSymbol
* key
;
890 key
= plane
->pathNameKey
;
895 registryTable()->setObject( key
, (OSObject
*) name
);
900 void IORegistryEntry::setName( const char * name
,
901 const IORegistryPlane
* plane
)
903 OSSymbol
* sym
= (OSSymbol
*)OSSymbol::withCString( name
);
905 setName( sym
, plane
);
910 void IORegistryEntry::setLocation( const OSSymbol
* location
,
911 const IORegistryPlane
* plane
)
913 const OSSymbol
* key
;
917 key
= plane
->pathLocationKey
;
919 key
= gIOLocationKey
;
922 registryTable()->setObject( key
, (OSObject
*) location
);
927 void IORegistryEntry::setLocation( const char * location
,
928 const IORegistryPlane
* plane
)
930 OSSymbol
* sym
= (OSSymbol
*)OSSymbol::withCString( location
);
932 setLocation( sym
, plane
);
938 IORegistryEntry::compareName( OSString
* name
, OSString
** matched
) const
940 const OSSymbol
* sym
= copyName();
943 isEqual
= sym
->isEqualTo( name
);
945 if( isEqual
&& matched
) {
957 IORegistryEntry::compareNames( OSObject
* names
, OSString
** matched
) const
960 OSCollection
* collection
;
961 OSIterator
* iter
= 0;
964 if( (collection
= OSDynamicCast( OSCollection
, names
))) {
965 iter
= OSCollectionIterator::withCollection( collection
);
968 string
= OSDynamicCast( OSString
, names
);
972 result
= compareName( string
, matched
);
974 } while( (false == result
)
975 && iter
&& (string
= OSDynamicCast( OSString
, iter
->getNextObject())));
984 bool IORegistryEntry::getPath( char * path
, int * length
,
985 const IORegistryPlane
* plane
) const
988 IORegistryEntry
* root
;
989 const IORegistryEntry
* entry
;
990 IORegistryEntry
* parent
;
991 const OSSymbol
* alias
;
993 int len
, maxLength
, compLen
;
997 if( !path
|| !length
|| !plane
)
1001 maxLength
= *length
- 2;
1004 len
= plane
->nameKey
->getLength();
1005 if( len
>= maxLength
)
1007 strcpy( nextComp
, plane
->nameKey
->getCStringNoCopy());
1008 nextComp
[ len
++ ] = ':';
1011 if( (alias
= hasAlias( plane
))) {
1012 len
+= alias
->getLength();
1013 ok
= (maxLength
> len
);
1016 strcpy( nextComp
, alias
->getCStringNoCopy());
1021 parent
= entry
->getParentEntry( plane
);
1023 // Error if not attached in plane
1026 stack
= OSArray::withCapacity( getDepth( plane
));
1032 root
= gRegistryRoot
->getChildEntry( plane
);
1033 while( parent
&& (entry
!= root
)) {
1035 stack
->setObject( (OSObject
*) entry
);
1037 parent
= entry
->getParentEntry( plane
);
1040 index
= stack
->getCount();
1049 } else while( ok
&& ((--index
) >= 0)) {
1051 entry
= (IORegistryEntry
*) stack
->getObject((unsigned int) index
);
1054 if( (alias
= entry
->hasAlias( plane
))) {
1055 len
= plane
->nameKey
->getLength() + 1;
1056 nextComp
= path
+ len
;
1058 compLen
= alias
->getLength();
1059 ok
= (maxLength
> len
+ compLen
);
1061 strcpy( nextComp
, alias
->getCStringNoCopy());
1063 compLen
= maxLength
- len
;
1064 ok
= entry
->getPathComponent( nextComp
+ 1, &compLen
, plane
);
1066 if( ok
&& compLen
) {
1074 nextComp
+= compLen
;
1086 bool IORegistryEntry::getPathComponent( char * path
, int * length
,
1087 const IORegistryPlane
* plane
) const
1089 int len
, locLen
, maxLength
;
1090 const char * compName
;
1094 maxLength
= *length
;
1096 compName
= getName( plane
);
1097 len
= strlen( compName
);
1098 if( (loc
= getLocation( plane
)))
1099 locLen
= 1 + strlen( loc
);
1103 ok
= ((len
+ locLen
) < maxLength
);
1105 strcpy( path
, compName
);
1110 strcpy( path
, loc
);
1118 const char * IORegistryEntry::matchPathLocation( const char * cmp
,
1119 const IORegistryPlane
* plane
)
1122 const char * result
= 0;
1123 u_quad_t num1
, num2
;
1124 char lastPathChar
, lastLocationChar
;
1126 str
= getLocation( plane
);
1128 lastPathChar
= cmp
[0];
1129 lastLocationChar
= str
[0];
1132 num1
= strtouq( cmp
, (char **) &cmp
, 16 );
1133 lastPathChar
= *cmp
++;
1137 if( lastLocationChar
) {
1138 num2
= strtouq( str
, (char **) &str
, 16 );
1139 lastLocationChar
= *str
++;
1146 if (!lastPathChar
&& !lastLocationChar
) {
1151 if( (',' != lastPathChar
) && (':' != lastPathChar
))
1154 if (lastPathChar
&& lastLocationChar
&& (lastPathChar
!= lastLocationChar
))
1163 IORegistryEntry
* IORegistryEntry::getChildFromComponent( const char ** opath
,
1164 const IORegistryPlane
* plane
)
1166 IORegistryEntry
* entry
= 0;
1170 const char * cmp
= 0;
1175 set
= getChildSetReference( plane
);
1181 (entry
= (IORegistryEntry
*) set
->getObject(index
));
1187 str
= entry
->getName( plane
);
1188 len
= strlen( str
);
1189 if( strncmp( str
, cmp
, len
))
1194 if( (c
== 0) || (c
== '/') || (c
== ':'))
1200 if( (cmp
= entry
->matchPathLocation( cmp
, plane
)))
1210 const OSSymbol
* IORegistryEntry::hasAlias( const IORegistryPlane
* plane
,
1211 char * opath
, int * length
) const
1213 IORegistryEntry
* entry
;
1214 IORegistryEntry
* entry2
;
1215 const OSSymbol
* key
;
1216 const OSSymbol
* bestKey
= 0;
1219 const char * path
= "/aliases";
1221 entry
= IORegistryEntry::fromPath( path
, plane
);
1224 if( (iter
= OSCollectionIterator::withCollection(
1225 entry
->getPropertyTable() ))) {
1227 while( (key
= (OSSymbol
*) iter
->getNextObject())) {
1229 data
= (OSData
*) entry
->getProperty( key
);
1230 path
= (const char *) data
->getBytesNoCopy();
1231 if( (entry2
= IORegistryEntry::fromPath( path
, plane
,
1233 if( this == entry2
) {
1235 || (bestKey
->getLength() > key
->getLength()))
1236 // pick the smallest alias
1250 const char * IORegistryEntry::dealiasPath(
1251 const char ** opath
,
1252 const IORegistryPlane
* plane
)
1254 IORegistryEntry
* entry
;
1256 const char * path
= *opath
;
1257 const char * rpath
= 0;
1260 char temp
[ kIOMaxPlaneName
+ 1 ];
1267 while( (c
= *end
++) && (c
!= '/') && (c
!= ':'))
1270 if( (end
- path
) < kIOMaxPlaneName
) {
1271 strncpy( temp
, path
, end
- path
);
1272 temp
[ end
- path
] = 0;
1275 entry
= IORegistryEntry::fromPath( "/aliases", plane
);
1277 data
= (OSData
*) entry
->getProperty( temp
);
1279 rpath
= (const char *) data
->getBytesNoCopy();
1291 IORegistryEntry
* IORegistryEntry::fromPath(
1293 const IORegistryPlane
* plane
,
1296 IORegistryEntry
* fromEntry
)
1298 IORegistryEntry
* where
= 0;
1299 IORegistryEntry
* aliasEntry
= 0;
1300 IORegistryEntry
* next
;
1306 char temp
[ kIOMaxPlaneName
+ 1 ];
1313 end
= strchr( path
, ':' );
1314 if( end
&& ((end
- path
) < kIOMaxPlaneName
)) {
1315 strncpy( temp
, path
, end
- path
);
1316 temp
[ end
- path
] = 0;
1317 plane
= getPlane( temp
);
1326 if( (alias
= dealiasPath( &end
, plane
))) {
1329 aliasEntry
= IORegistryEntry::fromPath( alias
, plane
,
1330 opath
, &len
, fromEntry
);
1342 if( (0 == fromEntry
) && (*path
++ == '/'))
1343 fromEntry
= gRegistryRoot
->getChildEntry( plane
);
1350 if( c
&& (c
!= ':')) // check valid terminator
1355 next
= where
->getChildFromComponent( &path
, plane
);
1361 // check residual path
1362 if( where
!= fromEntry
)
1365 if( opath
&& length
) {
1366 // copy out residual path
1367 len2
= len
+ strlen( path
);
1369 strcpy( opath
+ len
, path
);
1373 // no residual path => must be no tail for success
1380 aliasEntry
->release();
1387 IORegistryEntry
* IORegistryEntry::childFromPath(
1389 const IORegistryPlane
* plane
,
1393 return( IORegistryEntry::fromPath( path
, plane
, opath
, len
, this ));
1396 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1398 #define IOLinkIterator OSCollectionIterator
1401 #define super OSObject
1403 inline bool IORegistryEntry::arrayMember( OSArray
* set
,
1404 const IORegistryEntry
* member
,
1405 unsigned int * index
) const
1408 OSObject
* probeObject
;
1410 for( i
= 0; (probeObject
= set
->getObject(i
)); i
++) {
1411 if (probeObject
== (OSObject
*) member
) {
1420 bool IORegistryEntry::makeLink( IORegistryEntry
* to
,
1421 unsigned int relation
,
1422 const IORegistryPlane
* plane
) const
1425 bool result
= false;
1427 if( (links
= (OSArray
*)
1428 registryTable()->getObject( plane
->keys
[ relation
] ))) {
1430 result
= arrayMember( links
, to
);
1432 result
= links
->setObject( to
);
1436 links
= OSArray::withObjects( (const OSObject
**) &to
, 1, 1 );
1437 result
= (links
!= 0);
1439 result
= registryTable()->setObject( plane
->keys
[ relation
],
1448 void IORegistryEntry::breakLink( IORegistryEntry
* to
,
1449 unsigned int relation
,
1450 const IORegistryPlane
* plane
) const
1455 if( (links
= (OSArray
*)
1456 registryTable()->getObject( plane
->keys
[ relation
]))) {
1458 if( arrayMember( links
, to
, &index
)) {
1459 links
->removeObject( index
);
1460 if( 0 == links
->getCount())
1461 registryTable()->removeObject( plane
->keys
[ relation
]);
1467 OSArray
* IORegistryEntry::getParentSetReference(
1468 const IORegistryPlane
* plane
) const
1471 return( (OSArray
*) registryTable()->getObject(
1472 plane
->keys
[ kParentSetIndex
]));
1477 OSIterator
* IORegistryEntry::getParentIterator(
1478 const IORegistryPlane
* plane
) const
1487 links
= getParentSetReference( plane
);
1489 links
= OSArray::withCapacity( 1 );
1491 links
= OSArray::withArray( links
, links
->getCount() );
1494 iter
= IOLinkIterator::withCollection( links
);
1502 IORegistryEntry
* IORegistryEntry::copyParentEntry( const IORegistryPlane
* plane
) const
1504 IORegistryEntry
* entry
= 0;
1509 if( (links
= getParentSetReference( plane
))) {
1510 entry
= (IORegistryEntry
*) links
->getObject( 0 );
1519 IORegistryEntry
* IORegistryEntry::getParentEntry( const IORegistryPlane
* plane
) const
1521 IORegistryEntry
* entry
;
1523 entry
= copyParentEntry( plane
);
1530 OSArray
* IORegistryEntry::getChildSetReference( const IORegistryPlane
* plane
) const
1533 return( (OSArray
*) registryTable()->getObject(
1534 plane
->keys
[ kChildSetIndex
]));
1539 OSIterator
* IORegistryEntry::getChildIterator( const IORegistryPlane
* plane
) const
1548 links
= getChildSetReference( plane
);
1550 links
= OSArray::withCapacity( 1 );
1552 links
= OSArray::withArray( links
, links
->getCount() );
1555 iter
= IOLinkIterator::withCollection( links
);
1564 IORegistryEntry
* IORegistryEntry::copyChildEntry(
1565 const IORegistryPlane
* plane
) const
1567 IORegistryEntry
* entry
= 0;
1572 if( (links
= getChildSetReference( plane
))) {
1573 entry
= (IORegistryEntry
*) links
->getObject( 0 );
1582 IORegistryEntry
* IORegistryEntry::getChildEntry(
1583 const IORegistryPlane
* plane
) const
1585 IORegistryEntry
* entry
;
1587 entry
= copyChildEntry( plane
);
1594 void IORegistryEntry::applyToChildren( IORegistryEntryApplierFunction applier
,
1596 const IORegistryPlane
* plane
) const
1600 IORegistryEntry
* next
;
1606 array
= OSArray::withArray( getChildSetReference( plane
));
1610 (next
= (IORegistryEntry
*) array
->getObject( index
));
1612 (*applier
)(next
, context
);
1617 void IORegistryEntry::applyToParents( IORegistryEntryApplierFunction applier
,
1619 const IORegistryPlane
* plane
) const
1623 IORegistryEntry
* next
;
1629 array
= OSArray::withArray( getParentSetReference( plane
));
1633 (next
= (IORegistryEntry
*) array
->getObject( index
));
1635 (*applier
)(next
, context
);
1640 bool IORegistryEntry::isChild( IORegistryEntry
* child
,
1641 const IORegistryPlane
* plane
,
1642 bool onlyChild
) const
1649 if( (links
= getChildSetReference( plane
))) {
1650 if( (!onlyChild
) || (1 == links
->getCount()))
1651 ret
= arrayMember( links
, child
);
1653 if( ret
&& (links
= child
->getParentSetReference( plane
)))
1654 ret
= arrayMember( links
, this );
1661 bool IORegistryEntry::isParent( IORegistryEntry
* parent
,
1662 const IORegistryPlane
* plane
,
1663 bool onlyParent
) const
1671 if( (links
= getParentSetReference( plane
))) {
1672 if( (!onlyParent
) || (1 == links
->getCount()))
1673 ret
= arrayMember( links
, parent
);
1675 if( ret
&& (links
= parent
->getChildSetReference( plane
)))
1676 ret
= arrayMember( links
, this );
1683 bool IORegistryEntry::inPlane( const IORegistryPlane
* plane
) const
1690 ret
= (0 != getParentSetReference( plane
));
1693 // Check to see if this is in any plane. If it is in a plane
1694 // then the registryTable will contain a key with the ParentLinks
1695 // suffix. When we iterate over the keys looking for that suffix
1698 OSCollectionIterator
*iter
=
1699 OSCollectionIterator::withCollection( registryTable());
1701 const OSSymbol
*key
;
1703 while( (key
= (OSSymbol
*) iter
->getNextObject()) ) {
1704 const char *keysuffix
;
1706 // Get a pointer to this keys suffix
1707 keysuffix
= key
->getCStringNoCopy()
1708 + key
->getLength() - kIORegPlaneParentSuffixLen
;
1709 if( !strcmp(keysuffix
, kIORegPlaneParentSuffix
) ) {
1723 bool IORegistryEntry::attachToParent( IORegistryEntry
* parent
,
1724 const IORegistryPlane
* plane
)
1735 ret
= makeLink( parent
, kParentSetIndex
, plane
);
1737 if( (links
= parent
->getChildSetReference( plane
)))
1738 needParent
= (false == arrayMember( links
, this ));
1746 // Mark any collections in the property list as immutable
1747 OSDictionary
*ptable
= getPropertyTable();
1748 OSCollectionIterator
*iter
=
1749 OSCollectionIterator::withCollection( ptable
);
1751 const OSSymbol
*key
;
1753 while( (key
= (OSSymbol
*) iter
->getNextObject( ))) {
1754 // Is object for key a collection?
1755 OSCollection
*coll
=
1756 OSDynamicCast( OSCollection
, ptable
->getObject( key
));
1759 // Yup so mark it as immutable
1760 coll
->setOptions( OSCollection::kMASK
,
1761 OSCollection::kImmutable
);
1770 ret
&= parent
->attachToChild( this, plane
);
1775 bool IORegistryEntry::attachToChild( IORegistryEntry
* child
,
1776 const IORegistryPlane
* plane
)
1787 ret
= makeLink( child
, kChildSetIndex
, plane
);
1789 if( (links
= child
->getParentSetReference( plane
)))
1790 needChild
= (false == arrayMember( links
, this ));
1797 ret
&= child
->attachToParent( this, plane
);
1802 void IORegistryEntry::detachFromParent( IORegistryEntry
* parent
,
1803 const IORegistryPlane
* plane
)
1812 breakLink( parent
, kParentSetIndex
, plane
);
1814 if( (links
= parent
->getChildSetReference( plane
)))
1815 needParent
= arrayMember( links
, this );
1819 // parent->breakLink( this, kChildSetIndex, plane );
1824 parent
->detachFromChild( this, plane
);
1829 void IORegistryEntry::detachFromChild( IORegistryEntry
* child
,
1830 const IORegistryPlane
* plane
)
1839 breakLink( child
, kChildSetIndex
, plane
);
1841 if( (links
= child
->getParentSetReference( plane
)))
1842 needChild
= arrayMember( links
, this );
1849 child
->detachFromParent( this, plane
);
1854 void IORegistryEntry::detachAbove( const IORegistryPlane
* plane
)
1856 IORegistryEntry
* parent
;
1859 while( (parent
= getParentEntry( plane
)))
1860 detachFromParent( parent
, plane
);
1864 void IORegistryEntry::detachAll( const IORegistryPlane
* plane
)
1867 IORegistryEntry
* next
;
1868 IORegistryIterator
* regIter
;
1870 regIter
= IORegistryIterator::iterateOver( this, plane
, true );
1873 all
= regIter
->iterateAll();
1876 detachAbove( plane
);
1878 while( (next
= (IORegistryEntry
*) all
->getLastObject())) {
1881 all
->removeObject(next
);
1883 next
->detachAbove( plane
);
1890 unsigned int IORegistryEntry::getDepth( const IORegistryPlane
* plane
) const
1892 unsigned int depth
= 1;
1894 unsigned int oneDepth
, maxParentDepth
, count
;
1895 IORegistryEntry
* one
;
1896 const IORegistryEntry
* next
;
1902 while( (parents
= next
->getParentSetReference( plane
))) {
1904 count
= parents
->getCount();
1909 next
= (IORegistryEntry
*) parents
->getObject( 0 );
1914 (one
= (IORegistryEntry
*) parents
->getObject( index
));
1916 oneDepth
= one
->getDepth( plane
);
1917 if( oneDepth
> maxParentDepth
)
1918 maxParentDepth
= oneDepth
;
1920 depth
+= maxParentDepth
;
1930 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1933 #define super OSIterator
1935 OSDefineMetaClassAndStructors(IORegistryIterator
, OSIterator
)
1937 enum { kIORegistryIteratorInvalidFlag
= 0x80000000 };
1939 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1941 IORegistryIterator
*
1942 IORegistryIterator::iterateOver( IORegistryEntry
* root
,
1943 const IORegistryPlane
* plane
,
1944 IOOptionBits options
)
1946 IORegistryIterator
* create
;
1953 create
= new IORegistryIterator
;
1955 if( create
->init()) {
1958 create
->root
= root
;
1959 create
->where
= &create
->start
;
1960 create
->start
.current
= root
;
1961 create
->plane
= plane
;
1962 create
->options
= options
& ~kIORegistryIteratorInvalidFlag
;
1972 IORegistryIterator
*
1973 IORegistryIterator::iterateOver( const IORegistryPlane
* plane
,
1974 IOOptionBits options
)
1976 return( iterateOver( gRegistryRoot
, plane
, options
));
1979 bool IORegistryIterator::isValid( void )
1988 ok
= (0 == (kIORegistryIteratorInvalidFlag
& options
));
1990 while( ok
&& next
) {
1992 ok
= where
->iter
->isValid();
2000 void IORegistryIterator::enterEntry( const IORegistryPlane
* enterPlane
)
2005 where
= (IORegCursor
*) IOMalloc( sizeof( IORegCursor
));
2011 where
->current
= prev
->current
;
2016 void IORegistryIterator::enterEntry( void )
2018 enterEntry( plane
);
2021 bool IORegistryIterator::exitEntry( void )
2026 where
->iter
->release();
2028 if( where
->current
)// && (where != &start))
2029 where
->current
->release();
2032 if( where
!= &start
) {
2035 IOFree( gone
, sizeof( IORegCursor
));
2042 void IORegistryIterator::reset( void )
2052 where
->current
= root
;
2053 options
&= ~kIORegistryIteratorInvalidFlag
;
2056 void IORegistryIterator::free( void )
2067 IORegistryEntry
* IORegistryIterator::getNextObjectFlat( void )
2069 IORegistryEntry
* next
= 0;
2070 OSArray
* links
= 0;
2074 if( (0 == where
->iter
)) {
2075 // just entered - create new iter
2078 && (links
= ( (options
& kIORegistryIterateParents
) ?
2079 where
->current
->getParentSetReference( plane
) :
2080 where
->current
->getChildSetReference( plane
) )) )
2082 where
->iter
= OSCollectionIterator::withCollection( links
);
2085 // next sibling - release current
2087 where
->current
->release();
2091 next
= (IORegistryEntry
*) where
->iter
->getNextObject();
2095 else if( !where
->iter
->isValid())
2096 options
|= kIORegistryIteratorInvalidFlag
;
2099 where
->current
= next
;
2106 IORegistryEntry
* IORegistryIterator::getNextObjectRecursive( void )
2108 IORegistryEntry
* next
;
2111 next
= getNextObjectFlat();
2112 while( (0 == next
) && exitEntry());
2116 done
= OSOrderedSet::withCapacity( 10 );
2117 if( done
->setObject((OSObject
*) next
)) {
2118 // done set didn't contain this one, so recurse
2125 IORegistryEntry
* IORegistryIterator::getNextObject( void )
2127 if( options
& kIORegistryIterateRecursively
)
2128 return( getNextObjectRecursive());
2130 return( getNextObjectFlat());
2133 IORegistryEntry
* IORegistryIterator::getCurrentEntry( void )
2136 return( where
->current
);
2141 OSOrderedSet
* IORegistryIterator::iterateAll( void )
2144 while( getNextObjectRecursive())
2151 OSMetaClassDefineReservedUsed(IORegistryEntry
, 0);
2152 OSMetaClassDefineReservedUsed(IORegistryEntry
, 1);
2153 OSMetaClassDefineReservedUsed(IORegistryEntry
, 2);
2154 OSMetaClassDefineReservedUsed(IORegistryEntry
, 3);
2155 OSMetaClassDefineReservedUsed(IORegistryEntry
, 4);
2156 OSMetaClassDefineReservedUsed(IORegistryEntry
, 5);
2158 OSMetaClassDefineReservedUnused(IORegistryEntry
, 6);
2159 OSMetaClassDefineReservedUnused(IORegistryEntry
, 7);
2160 OSMetaClassDefineReservedUnused(IORegistryEntry
, 8);
2161 OSMetaClassDefineReservedUnused(IORegistryEntry
, 9);
2162 OSMetaClassDefineReservedUnused(IORegistryEntry
, 10);
2163 OSMetaClassDefineReservedUnused(IORegistryEntry
, 11);
2164 OSMetaClassDefineReservedUnused(IORegistryEntry
, 12);
2165 OSMetaClassDefineReservedUnused(IORegistryEntry
, 13);
2166 OSMetaClassDefineReservedUnused(IORegistryEntry
, 14);
2167 OSMetaClassDefineReservedUnused(IORegistryEntry
, 15);
2168 OSMetaClassDefineReservedUnused(IORegistryEntry
, 16);
2169 OSMetaClassDefineReservedUnused(IORegistryEntry
, 17);
2170 OSMetaClassDefineReservedUnused(IORegistryEntry
, 18);
2171 OSMetaClassDefineReservedUnused(IORegistryEntry
, 19);
2172 OSMetaClassDefineReservedUnused(IORegistryEntry
, 20);
2173 OSMetaClassDefineReservedUnused(IORegistryEntry
, 21);
2174 OSMetaClassDefineReservedUnused(IORegistryEntry
, 22);
2175 OSMetaClassDefineReservedUnused(IORegistryEntry
, 23);
2176 OSMetaClassDefineReservedUnused(IORegistryEntry
, 24);
2177 OSMetaClassDefineReservedUnused(IORegistryEntry
, 25);
2178 OSMetaClassDefineReservedUnused(IORegistryEntry
, 26);
2179 OSMetaClassDefineReservedUnused(IORegistryEntry
, 27);
2180 OSMetaClassDefineReservedUnused(IORegistryEntry
, 28);
2181 OSMetaClassDefineReservedUnused(IORegistryEntry
, 29);
2182 OSMetaClassDefineReservedUnused(IORegistryEntry
, 30);
2183 OSMetaClassDefineReservedUnused(IORegistryEntry
, 31);
2185 /* inline function implementation */
2186 OSDictionary
* IORegistryEntry::getPropertyTable( void ) const
2187 { return(fPropertyTable
); }