2 * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved.
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. The rights granted to you under the License
10 * may not be used to create, or enable the creation or redistribution of,
11 * unlawful or unlicensed copies of an Apple operating system, or to
12 * circumvent, violate, or enable the circumvention or violation of, any
13 * terms of an Apple operating system software license agreement.
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
18 * The Original Code and all software distributed under the License are
19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23 * Please see the License for the specific language governing rights and
24 * limitations under the License.
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
29 * Copyright (c) 1998 Apple Computer, Inc. All rights reserved.
32 * 12 Nov 98 sdouglas created.
36 #include <IOKit/IORegistryEntry.h>
37 #include <libkern/c++/OSContainers.h>
38 #include <IOKit/IOService.h>
39 #include <IOKit/IOKitKeys.h>
41 #include <IOKit/IOLib.h>
43 #include <IOKit/assert.h>
45 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
47 #define super OSObject
49 OSDefineMetaClassAndStructors(IORegistryEntry
, OSObject
)
51 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
53 #define kIORegPlaneParentSuffix "ParentLinks"
54 #define kIORegPlaneChildSuffix "ChildLinks"
55 #define kIORegPlaneNameSuffix "Name"
56 #define kIORegPlaneLocationSuffix "Location"
57 #define kIORegPlaneParentSuffixLen (sizeof(kIORegPlaneParentSuffix) - 1)
59 static IORegistryEntry
* gRegistryRoot
;
60 static OSDictionary
* gIORegistryPlanes
;
62 const OSSymbol
* gIONameKey
;
63 const OSSymbol
* gIOLocationKey
;
74 class IORegistryPlane
: public OSObject
{
76 friend class IORegistryEntry
;
78 OSDeclareAbstractStructors(IORegistryPlane
)
80 const OSSymbol
* nameKey
;
81 const OSSymbol
* keys
[ kNumSetIndex
];
82 const OSSymbol
* pathNameKey
;
83 const OSSymbol
* pathLocationKey
;
87 virtual bool serialize(OSSerialize
*s
) const;
90 OSDefineMetaClassAndStructors(IORegistryPlane
, OSObject
)
93 static IORecursiveLock
* gPropertiesLock
;
94 static SInt32 gIORegistryGenerationCount
;
96 #define UNLOCK s_lock_done( &gIORegistryLock )
97 #define RLOCK s_lock_read( &gIORegistryLock )
98 #define WLOCK s_lock_write( &gIORegistryLock ); \
99 gIORegistryGenerationCount++
102 #define PUNLOCK IORecursiveLockUnlock( gPropertiesLock )
103 #define PLOCK IORecursiveLockLock( gPropertiesLock )
105 #define IOREGSPLITTABLES
107 #ifdef IOREGSPLITTABLES
108 #define registryTable() fRegistryTable
110 #define registryTable() fPropertyTable
115 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
118 lck_spin_t interlock
; /* "hardware" interlock field */
119 volatile unsigned int
120 read_count
:16, /* No. of accepted readers */
121 want_upgrade
:1, /* Read-to-write upgrade waiting */
122 want_write
:1, /* Writer is waiting, or
124 waiting
:1, /* Someone is sleeping on lock */
125 can_sleep
:1; /* Can attempts to lock go to sleep? */
128 static struct s_lock_t gIORegistryLock
;
130 /* Time we loop without holding the interlock.
131 * The former is for when we cannot sleep, the latter
132 * for when our thread can go to sleep (loop less)
133 * we shouldn't retake the interlock at all frequently
134 * if we cannot go to sleep, since it interferes with
135 * any other processors. In particular, 100 is too small
136 * a number for powerpc MP systems because of cache
137 * coherency issues and differing lock fetch times between
140 static unsigned int lock_wait_time
[2] = { (unsigned int)-1, 100 } ;
147 (void) memset((void *) l
, 0, sizeof(s_lock_t
));
149 lck_spin_init(&l
->interlock
, IOLockGroup
, LCK_ATTR_NULL
);
150 l
->want_write
= FALSE
;
151 l
->want_upgrade
= FALSE
;
153 l
->can_sleep
= can_sleep
;
158 register s_lock_t
* l
)
162 lck_spin_lock(&l
->interlock
);
165 * Try to acquire the want_write bit.
167 while (l
->want_write
) {
169 i
= lock_wait_time
[l
->can_sleep
? 1 : 0];
171 lck_spin_unlock(&l
->interlock
);
172 while (--i
!= 0 && l
->want_write
)
174 lck_spin_lock(&l
->interlock
);
177 if (l
->can_sleep
&& l
->want_write
) {
179 lck_spin_sleep( &l
->interlock
, LCK_SLEEP_DEFAULT
,
180 (event_t
) l
, THREAD_UNINT
);
181 /* interlock relocked */
184 l
->want_write
= TRUE
;
186 /* Wait for readers (and upgrades) to finish */
188 while ((l
->read_count
!= 0) || l
->want_upgrade
) {
190 i
= lock_wait_time
[l
->can_sleep
? 1 : 0];
192 lck_spin_unlock(&l
->interlock
);
193 while (--i
!= 0 && (l
->read_count
!= 0 ||
196 lck_spin_lock(&l
->interlock
);
199 if (l
->can_sleep
&& (l
->read_count
!= 0 || l
->want_upgrade
)) {
201 lck_spin_sleep( &l
->interlock
, LCK_SLEEP_DEFAULT
,
202 (event_t
) l
, THREAD_UNINT
);
203 /* interlock relocked */
207 lck_spin_unlock(&l
->interlock
);
212 register s_lock_t
* l
)
214 boolean_t do_wakeup
= FALSE
;
216 lck_spin_lock(&l
->interlock
);
218 if (l
->read_count
!= 0) {
222 if (l
->want_upgrade
) {
223 l
->want_upgrade
= FALSE
;
226 l
->want_write
= FALSE
;
231 * There is no reason to wakeup a waiting thread
232 * if the read-count is non-zero. Consider:
233 * we must be dropping a read lock
234 * threads are waiting only if one wants a write lock
235 * if there are still readers, they can't proceed
237 if (l
->waiting
&& (l
->read_count
== 0)) {
242 lck_spin_unlock(&l
->interlock
);
245 thread_wakeup((event_t
) l
);
250 register s_lock_t
* l
)
254 lck_spin_lock(&l
->interlock
);
256 while ( l
->want_upgrade
|| ((0 == l
->read_count
) && l
->want_write
)) {
258 i
= lock_wait_time
[l
->can_sleep
? 1 : 0];
261 lck_spin_unlock(&l
->interlock
);
263 (l
->want_upgrade
|| ((0 == l
->read_count
) && l
->want_write
)))
265 lck_spin_lock(&l
->interlock
);
269 (l
->want_upgrade
|| ((0 == l
->read_count
) && l
->want_write
))) {
271 lck_spin_sleep( &l
->interlock
, LCK_SLEEP_DEFAULT
,
272 (event_t
) l
, THREAD_UNINT
);
273 /* interlock relocked */
278 lck_spin_unlock(&l
->interlock
);
282 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
284 IORegistryEntry
* IORegistryEntry::initialize( void )
288 if( !gRegistryRoot
) {
290 s_lock_init( &gIORegistryLock
, true );
291 gRegistryRoot
= new IORegistryEntry
;
292 gPropertiesLock
= IORecursiveLockAlloc();
293 gIORegistryPlanes
= OSDictionary::withCapacity( 1 );
295 assert( gRegistryRoot
&& gPropertiesLock
296 && gIORegistryPlanes
);
297 ok
= gRegistryRoot
->init();
299 gIONameKey
= OSSymbol::withCStringNoCopy( "IOName" );
300 gIOLocationKey
= OSSymbol::withCStringNoCopy( "IOLocation" );
302 assert( ok
&& gIONameKey
&& gIOLocationKey
);
304 gRegistryRoot
->setName( "Root" );
305 gRegistryRoot
->setProperty( kIORegistryPlanesKey
, gIORegistryPlanes
);
308 return( gRegistryRoot
);
311 IORegistryEntry
* IORegistryEntry::getRegistryRoot( void )
313 return( gRegistryRoot
);
316 SInt32
IORegistryEntry::getGenerationCount( void )
318 return( gIORegistryGenerationCount
);
322 const IORegistryPlane
* IORegistryEntry::makePlane( const char * name
)
324 IORegistryPlane
* plane
;
325 const OSSymbol
* nameKey
;
326 const OSSymbol
* parentKey
;
327 const OSSymbol
* childKey
;
328 const OSSymbol
* pathNameKey
;
329 const OSSymbol
* pathLocationKey
;
330 char key
[ kIOMaxPlaneName
+ 16 ];
333 strncpy( key
, name
, kIOMaxPlaneName
);
334 key
[ kIOMaxPlaneName
] = 0;
335 end
= key
+ strlen( name
);
337 nameKey
= OSSymbol::withCString( key
);
339 strcpy( end
, kIORegPlaneParentSuffix
);
340 parentKey
= OSSymbol::withCString( key
);
342 strcpy( end
, kIORegPlaneChildSuffix
);
343 childKey
= OSSymbol::withCString( key
);
345 strcpy( end
, kIORegPlaneNameSuffix
);
346 pathNameKey
= OSSymbol::withCString( key
);
348 strcpy( end
, kIORegPlaneLocationSuffix
);
349 pathLocationKey
= OSSymbol::withCString( key
);
351 plane
= new IORegistryPlane
;
353 if( plane
&& plane
->init()
354 && nameKey
&& parentKey
&& childKey
355 && pathNameKey
&& pathLocationKey
) {
357 plane
->nameKey
= nameKey
;
358 plane
->keys
[ kParentSetIndex
] = parentKey
;
359 plane
->keys
[ kChildSetIndex
] = childKey
;
360 plane
->pathNameKey
= pathNameKey
;
361 plane
->pathLocationKey
= pathLocationKey
;
364 gIORegistryPlanes
->setObject( nameKey
, plane
);
372 pathLocationKey
->release();
374 pathNameKey
->release();
376 parentKey
->release();
387 const IORegistryPlane
* IORegistryEntry::getPlane( const char * name
)
389 const IORegistryPlane
* plane
;
392 plane
= (const IORegistryPlane
*) gIORegistryPlanes
->getObject( name
);
398 bool IORegistryPlane::serialize(OSSerialize
*s
) const
400 return( nameKey
->serialize(s
) );
403 enum { kIORegCapacityIncrement
= 4 };
405 bool IORegistryEntry::init( OSDictionary
* dict
)
415 fPropertyTable
->release();
416 fPropertyTable
= dict
;
418 } else if( !fPropertyTable
) {
419 fPropertyTable
= OSDictionary::withCapacity( kIORegCapacityIncrement
);
421 fPropertyTable
->setCapacityIncrement( kIORegCapacityIncrement
);
427 #ifdef IOREGSPLITTABLES
428 if( !fRegistryTable
) {
429 fRegistryTable
= OSDictionary::withCapacity( kIORegCapacityIncrement
);
431 fRegistryTable
->setCapacityIncrement( kIORegCapacityIncrement
);
434 if( (prop
= OSDynamicCast( OSString
, getProperty( gIONameKey
)))) {
435 OSSymbol
* sym
= (OSSymbol
*)OSSymbol::withString( prop
);
436 // ok for OSSymbol too
441 #endif /* IOREGSPLITTABLES */
446 bool IORegistryEntry::init( IORegistryEntry
* old
,
447 const IORegistryPlane
* plane
)
450 IORegistryEntry
* next
;
458 fPropertyTable
= old
->getPropertyTable();
459 fPropertyTable
->retain();
460 #ifdef IOREGSPLITTABLES
461 fRegistryTable
= old
->fRegistryTable
;
462 old
->fRegistryTable
= OSDictionary::withDictionary( fRegistryTable
);
463 #endif /* IOREGSPLITTABLES */
465 old
->registryTable()->removeObject( plane
->keys
[ kParentSetIndex
] );
466 old
->registryTable()->removeObject( plane
->keys
[ kChildSetIndex
] );
468 all
= getParentSetReference( plane
);
469 if( all
) for( index
= 0;
470 (next
= (IORegistryEntry
*) all
->getObject(index
));
472 next
->makeLink( this, kChildSetIndex
, plane
);
473 next
->breakLink( old
, kChildSetIndex
, plane
);
476 all
= getChildSetReference( plane
);
477 if( all
) for( index
= 0;
478 (next
= (IORegistryEntry
*) all
->getObject(index
));
480 next
->makeLink( this, kParentSetIndex
, plane
);
481 next
->breakLink( old
, kParentSetIndex
, plane
);
489 void IORegistryEntry::free( void )
493 #define msg ": attached at free()"
494 char buf
[ strlen(msg
) + 40 ];
496 if( registryTable() && gIOServicePlane
) {
497 if( getParentSetReference( gIOServicePlane
)
498 || getChildSetReference( gIOServicePlane
)) {
500 strncpy( buf
, getName(), 32);
508 if( getPropertyTable())
509 getPropertyTable()->release();
511 #ifdef IOREGSPLITTABLES
513 registryTable()->release();
514 #endif /* IOREGSPLITTABLES */
519 void IORegistryEntry::setPropertyTable( OSDictionary
* dict
)
522 fPropertyTable
->release();
525 fPropertyTable
= dict
;
528 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
530 /* Wrappers to synchronize property table */
532 #define wrap2(type, constant) \
534 IORegistryEntry::copyProperty( type * aKey) constant \
539 obj = getProperty( aKey ); \
547 #define wrap4(type,constant) \
549 IORegistryEntry::getProperty( type * aKey, \
550 const IORegistryPlane * plane, \
551 IOOptionBits options ) constant \
553 OSObject * obj = getProperty( aKey ); \
555 if ( (0 == obj) && plane && (options & kIORegistryIterateRecursively) ) { \
556 IORegistryEntry * entry = (IORegistryEntry *) this; \
557 IORegistryIterator * iter; \
558 iter = IORegistryIterator::iterateOver( entry, plane, options ); \
561 while ( (0 == obj) && (entry = iter->getNextObject()) ) { \
562 obj = entry->getProperty( aKey ); \
571 #define wrap5(type,constant) \
573 IORegistryEntry::copyProperty( type * aKey, \
574 const IORegistryPlane * plane, \
575 IOOptionBits options ) constant \
577 OSObject * obj = copyProperty( aKey ); \
579 if ( (0 == obj) && plane && (options & kIORegistryIterateRecursively) ) { \
580 IORegistryEntry * entry = (IORegistryEntry *) this; \
581 IORegistryIterator * iter; \
582 iter = IORegistryIterator::iterateOver( entry, plane, options ); \
585 while ( (0 == obj) && (entry = iter->getNextObject()) ) { \
586 obj = entry->copyProperty( aKey ); \
595 bool IORegistryEntry::serializeProperties( OSSerialize
* s
) const
597 // setProperty( getRetainCount(), 32, "__retain" );
600 OSCollection
*snapshotProperties
= getPropertyTable()->copyCollection();
603 bool ok
= snapshotProperties
->serialize( s
);
604 snapshotProperties
->release();
608 OSDictionary
* IORegistryEntry::dictionaryWithProperties( void ) const
613 dict
= OSDictionary::withDictionary( getPropertyTable(),
614 getPropertyTable()->getCapacity() );
620 IOReturn
IORegistryEntry::setProperties( OSObject
* properties
)
622 return( kIOReturnUnsupported
);
625 wrap2(const OSSymbol
, const) // copyProperty() definition
626 wrap2(const OSString
, const) // copyProperty() definition
627 wrap2(const char, const) // copyProperty() definition
629 wrap4(const OSSymbol
, const) // getProperty() w/plane definition
630 wrap4(const OSString
, const) // getProperty() w/plane definition
631 wrap4(const char, const) // getProperty() w/plane definition
633 wrap5(const OSSymbol
, const) // copyProperty() w/plane definition
634 wrap5(const OSString
, const) // copyProperty() w/plane definition
635 wrap5(const char, const) // copyProperty() w/plane definition
639 IORegistryEntry::getProperty( const OSSymbol
* aKey
) const
644 obj
= getPropertyTable()->getObject( aKey
);
651 IORegistryEntry::removeProperty( const OSSymbol
* aKey
)
654 getPropertyTable()->removeObject( aKey
);
659 IORegistryEntry::setProperty( const OSSymbol
* aKey
, OSObject
* anObject
)
663 // If we are inserting a collection class and the current entry
664 // is attached into the registry (inPlane()) then mark the collection
666 OSCollection
*coll
= OSDynamicCast(OSCollection
, anObject
);
667 bool makeImmutable
= (coll
&& inPlane());
671 coll
->setOptions( OSCollection::kMASK
, OSCollection::kImmutable
);
673 ret
= getPropertyTable()->setObject( aKey
, anObject
);
679 IOReturn
IORegistryEntry::
680 runPropertyAction(Action inAction
, OSObject
*target
,
681 void *arg0
, void *arg1
, void *arg2
, void *arg3
)
685 // closeGate is recursive so don't worry if we already hold the lock.
687 res
= (*inAction
)(target
, arg0
, arg1
, arg2
, arg3
);
694 IORegistryEntry::getProperty( const OSString
* aKey
) const
696 const OSSymbol
* tmpKey
= OSSymbol::withString( aKey
);
697 OSObject
* obj
= getProperty( tmpKey
);
704 IORegistryEntry::getProperty( const char * aKey
) const
706 const OSSymbol
* tmpKey
= OSSymbol::withCString( aKey
);
707 OSObject
* obj
= getProperty( tmpKey
);
715 IORegistryEntry::removeProperty( const OSString
* aKey
)
717 const OSSymbol
* tmpKey
= OSSymbol::withString( aKey
);
718 removeProperty( tmpKey
);
723 IORegistryEntry::removeProperty( const char * aKey
)
725 const OSSymbol
* tmpKey
= OSSymbol::withCString( aKey
);
726 removeProperty( tmpKey
);
731 IORegistryEntry::setProperty( const OSString
* aKey
, OSObject
* anObject
)
733 const OSSymbol
* tmpKey
= OSSymbol::withString( aKey
);
734 bool ret
= setProperty( tmpKey
, anObject
);
741 IORegistryEntry::setProperty( const char * aKey
, OSObject
* anObject
)
743 const OSSymbol
* tmpKey
= OSSymbol::withCString( aKey
);
744 bool ret
= setProperty( tmpKey
, anObject
);
751 IORegistryEntry::setProperty(const char * aKey
, const char * aString
)
754 OSSymbol
* aSymbol
= (OSSymbol
*) OSSymbol::withCString( aString
);
757 const OSSymbol
* tmpKey
= OSSymbol::withCString( aKey
);
758 ret
= setProperty( tmpKey
, aSymbol
);
767 IORegistryEntry::setProperty(const char * aKey
, bool aBoolean
)
770 OSBoolean
* aBooleanObj
= OSBoolean::withBoolean( aBoolean
);
773 const OSSymbol
* tmpKey
= OSSymbol::withCString( aKey
);
774 ret
= setProperty( tmpKey
, aBooleanObj
);
777 aBooleanObj
->release();
783 IORegistryEntry::setProperty( const char * aKey
,
784 unsigned long long aValue
,
785 unsigned int aNumberOfBits
)
788 OSNumber
* anOffset
= OSNumber::withNumber( aValue
, aNumberOfBits
);
791 const OSSymbol
* tmpKey
= OSSymbol::withCString( aKey
);
792 ret
= setProperty( tmpKey
, anOffset
);
801 IORegistryEntry::setProperty( const char * aKey
,
806 OSData
* data
= OSData::withBytes( bytes
, length
);
809 const OSSymbol
* tmpKey
= OSSymbol::withCString( aKey
);
810 ret
= setProperty( tmpKey
, data
);
818 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
820 /* Name, location, paths */
822 const char * IORegistryEntry::getName( const IORegistryPlane
* plane
) const
828 sym
= (OSSymbol
*) registryTable()->getObject( plane
->pathNameKey
);
830 sym
= (OSSymbol
*) registryTable()->getObject( gIONameKey
);
834 return( sym
->getCStringNoCopy());
836 return( (getMetaClass())->getClassName());
839 const OSSymbol
* IORegistryEntry::copyName(
840 const IORegistryPlane
* plane
) const
846 sym
= (OSSymbol
*) registryTable()->getObject( plane
->pathNameKey
);
848 sym
= (OSSymbol
*) registryTable()->getObject( gIONameKey
);
856 return( OSSymbol::withCString((getMetaClass())->getClassName()) );
859 const OSSymbol
* IORegistryEntry::copyLocation(
860 const IORegistryPlane
* plane
) const
866 sym
= (OSSymbol
*) registryTable()->getObject( plane
->pathLocationKey
);
868 sym
= (OSSymbol
*) registryTable()->getObject( gIOLocationKey
);
876 const char * IORegistryEntry::getLocation( const IORegistryPlane
* plane
) const
878 const OSSymbol
* sym
= copyLocation( plane
);
879 const char * result
= 0;
882 result
= sym
->getCStringNoCopy();
889 void IORegistryEntry::setName( const OSSymbol
* name
,
890 const IORegistryPlane
* plane
)
892 const OSSymbol
* key
;
896 key
= plane
->pathNameKey
;
901 registryTable()->setObject( key
, (OSObject
*) name
);
906 void IORegistryEntry::setName( const char * name
,
907 const IORegistryPlane
* plane
)
909 OSSymbol
* sym
= (OSSymbol
*)OSSymbol::withCString( name
);
911 setName( sym
, plane
);
916 void IORegistryEntry::setLocation( const OSSymbol
* location
,
917 const IORegistryPlane
* plane
)
919 const OSSymbol
* key
;
923 key
= plane
->pathLocationKey
;
925 key
= gIOLocationKey
;
928 registryTable()->setObject( key
, (OSObject
*) location
);
933 void IORegistryEntry::setLocation( const char * location
,
934 const IORegistryPlane
* plane
)
936 OSSymbol
* sym
= (OSSymbol
*)OSSymbol::withCString( location
);
938 setLocation( sym
, plane
);
944 IORegistryEntry::compareName( OSString
* name
, OSString
** matched
) const
946 const OSSymbol
* sym
= copyName();
949 isEqual
= sym
->isEqualTo( name
);
951 if( isEqual
&& matched
) {
963 IORegistryEntry::compareNames( OSObject
* names
, OSString
** matched
) const
966 OSCollection
* collection
;
967 OSIterator
* iter
= 0;
970 if( (collection
= OSDynamicCast( OSCollection
, names
))) {
971 iter
= OSCollectionIterator::withCollection( collection
);
974 string
= OSDynamicCast( OSString
, names
);
978 result
= compareName( string
, matched
);
980 } while( (false == result
)
981 && iter
&& (string
= OSDynamicCast( OSString
, iter
->getNextObject())));
990 bool IORegistryEntry::getPath( char * path
, int * length
,
991 const IORegistryPlane
* plane
) const
994 IORegistryEntry
* root
;
995 const IORegistryEntry
* entry
;
996 IORegistryEntry
* parent
;
997 const OSSymbol
* alias
;
999 int len
, maxLength
, compLen
;
1003 if( !path
|| !length
|| !plane
)
1007 maxLength
= *length
- 2;
1010 len
= plane
->nameKey
->getLength();
1011 if( len
>= maxLength
)
1013 strcpy( nextComp
, plane
->nameKey
->getCStringNoCopy());
1014 nextComp
[ len
++ ] = ':';
1017 if( (alias
= hasAlias( plane
))) {
1018 len
+= alias
->getLength();
1019 ok
= (maxLength
> len
);
1022 strcpy( nextComp
, alias
->getCStringNoCopy());
1027 parent
= entry
->getParentEntry( plane
);
1029 // Error if not attached in plane
1032 stack
= OSArray::withCapacity( getDepth( plane
));
1038 root
= gRegistryRoot
->getChildEntry( plane
);
1039 while( parent
&& (entry
!= root
)) {
1041 stack
->setObject( (OSObject
*) entry
);
1043 parent
= entry
->getParentEntry( plane
);
1046 index
= stack
->getCount();
1055 } else while( ok
&& ((--index
) >= 0)) {
1057 entry
= (IORegistryEntry
*) stack
->getObject((unsigned int) index
);
1060 if( (alias
= entry
->hasAlias( plane
))) {
1061 len
= plane
->nameKey
->getLength() + 1;
1062 nextComp
= path
+ len
;
1064 compLen
= alias
->getLength();
1065 ok
= (maxLength
> len
+ compLen
);
1067 strcpy( nextComp
, alias
->getCStringNoCopy());
1069 compLen
= maxLength
- len
;
1070 ok
= entry
->getPathComponent( nextComp
+ 1, &compLen
, plane
);
1072 if( ok
&& compLen
) {
1080 nextComp
+= compLen
;
1092 bool IORegistryEntry::getPathComponent( char * path
, int * length
,
1093 const IORegistryPlane
* plane
) const
1095 int len
, locLen
, maxLength
;
1096 const char * compName
;
1100 maxLength
= *length
;
1102 compName
= getName( plane
);
1103 len
= strlen( compName
);
1104 if( (loc
= getLocation( plane
)))
1105 locLen
= 1 + strlen( loc
);
1109 ok
= ((len
+ locLen
) < maxLength
);
1111 strcpy( path
, compName
);
1116 strcpy( path
, loc
);
1124 const char * IORegistryEntry::matchPathLocation( const char * cmp
,
1125 const IORegistryPlane
* plane
)
1128 const char * result
= 0;
1129 u_quad_t num1
, num2
;
1130 char lastPathChar
, lastLocationChar
;
1132 str
= getLocation( plane
);
1134 lastPathChar
= cmp
[0];
1135 lastLocationChar
= str
[0];
1138 num1
= strtouq( cmp
, (char **) &cmp
, 16 );
1139 lastPathChar
= *cmp
++;
1143 if( lastLocationChar
) {
1144 num2
= strtouq( str
, (char **) &str
, 16 );
1145 lastLocationChar
= *str
++;
1152 if (!lastPathChar
&& !lastLocationChar
) {
1157 if( (',' != lastPathChar
) && (':' != lastPathChar
))
1160 if (lastPathChar
&& lastLocationChar
&& (lastPathChar
!= lastLocationChar
))
1169 IORegistryEntry
* IORegistryEntry::getChildFromComponent( const char ** opath
,
1170 const IORegistryPlane
* plane
)
1172 IORegistryEntry
* entry
= 0;
1176 const char * cmp
= 0;
1181 set
= getChildSetReference( plane
);
1187 (entry
= (IORegistryEntry
*) set
->getObject(index
));
1193 str
= entry
->getName( plane
);
1194 len
= strlen( str
);
1195 if( strncmp( str
, cmp
, len
))
1200 if( (c
== 0) || (c
== '/') || (c
== ':'))
1206 if( (cmp
= entry
->matchPathLocation( cmp
, plane
)))
1216 const OSSymbol
* IORegistryEntry::hasAlias( const IORegistryPlane
* plane
,
1217 char * opath
, int * length
) const
1219 IORegistryEntry
* entry
;
1220 IORegistryEntry
* entry2
;
1221 const OSSymbol
* key
;
1222 const OSSymbol
* bestKey
= 0;
1225 const char * path
= "/aliases";
1227 entry
= IORegistryEntry::fromPath( path
, plane
);
1230 if( (iter
= OSCollectionIterator::withCollection(
1231 entry
->getPropertyTable() ))) {
1233 while( (key
= (OSSymbol
*) iter
->getNextObject())) {
1235 data
= (OSData
*) entry
->getProperty( key
);
1236 path
= (const char *) data
->getBytesNoCopy();
1237 if( (entry2
= IORegistryEntry::fromPath( path
, plane
,
1239 if( this == entry2
) {
1241 || (bestKey
->getLength() > key
->getLength()))
1242 // pick the smallest alias
1256 const char * IORegistryEntry::dealiasPath(
1257 const char ** opath
,
1258 const IORegistryPlane
* plane
)
1260 IORegistryEntry
* entry
;
1262 const char * path
= *opath
;
1263 const char * rpath
= 0;
1266 char temp
[ kIOMaxPlaneName
+ 1 ];
1273 while( (c
= *end
++) && (c
!= '/') && (c
!= ':'))
1276 if( (end
- path
) < kIOMaxPlaneName
) {
1277 strncpy( temp
, path
, end
- path
);
1278 temp
[ end
- path
] = 0;
1281 entry
= IORegistryEntry::fromPath( "/aliases", plane
);
1283 data
= (OSData
*) entry
->getProperty( temp
);
1285 rpath
= (const char *) data
->getBytesNoCopy();
1297 IORegistryEntry
* IORegistryEntry::fromPath(
1299 const IORegistryPlane
* plane
,
1302 IORegistryEntry
* fromEntry
)
1304 IORegistryEntry
* where
= 0;
1305 IORegistryEntry
* aliasEntry
= 0;
1306 IORegistryEntry
* next
;
1312 char temp
[ kIOMaxPlaneName
+ 1 ];
1319 end
= strchr( path
, ':' );
1320 if( end
&& ((end
- path
) < kIOMaxPlaneName
)) {
1321 strncpy( temp
, path
, end
- path
);
1322 temp
[ end
- path
] = 0;
1323 plane
= getPlane( temp
);
1332 if( (alias
= dealiasPath( &end
, plane
))) {
1335 aliasEntry
= IORegistryEntry::fromPath( alias
, plane
,
1336 opath
, &len
, fromEntry
);
1348 if( (0 == fromEntry
) && (*path
++ == '/'))
1349 fromEntry
= gRegistryRoot
->getChildEntry( plane
);
1356 if( c
&& (c
!= ':')) // check valid terminator
1361 next
= where
->getChildFromComponent( &path
, plane
);
1367 // check residual path
1368 if( where
!= fromEntry
)
1371 if( opath
&& length
) {
1372 // copy out residual path
1373 len2
= len
+ strlen( path
);
1375 strcpy( opath
+ len
, path
);
1379 // no residual path => must be no tail for success
1386 aliasEntry
->release();
1393 IORegistryEntry
* IORegistryEntry::childFromPath(
1395 const IORegistryPlane
* plane
,
1399 return( IORegistryEntry::fromPath( path
, plane
, opath
, len
, this ));
1402 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1404 #define IOLinkIterator OSCollectionIterator
1407 #define super OSObject
1409 inline bool IORegistryEntry::arrayMember( OSArray
* set
,
1410 const IORegistryEntry
* member
,
1411 unsigned int * index
) const
1414 OSObject
* probeObject
;
1416 for( i
= 0; (probeObject
= set
->getObject(i
)); i
++) {
1417 if (probeObject
== (OSObject
*) member
) {
1426 bool IORegistryEntry::makeLink( IORegistryEntry
* to
,
1427 unsigned int relation
,
1428 const IORegistryPlane
* plane
) const
1431 bool result
= false;
1433 if( (links
= (OSArray
*)
1434 registryTable()->getObject( plane
->keys
[ relation
] ))) {
1436 result
= arrayMember( links
, to
);
1438 result
= links
->setObject( to
);
1442 links
= OSArray::withObjects( (const OSObject
**) &to
, 1, 1 );
1443 result
= (links
!= 0);
1445 result
= registryTable()->setObject( plane
->keys
[ relation
],
1454 void IORegistryEntry::breakLink( IORegistryEntry
* to
,
1455 unsigned int relation
,
1456 const IORegistryPlane
* plane
) const
1461 if( (links
= (OSArray
*)
1462 registryTable()->getObject( plane
->keys
[ relation
]))) {
1464 if( arrayMember( links
, to
, &index
)) {
1465 links
->removeObject( index
);
1466 if( 0 == links
->getCount())
1467 registryTable()->removeObject( plane
->keys
[ relation
]);
1473 OSArray
* IORegistryEntry::getParentSetReference(
1474 const IORegistryPlane
* plane
) const
1477 return( (OSArray
*) registryTable()->getObject(
1478 plane
->keys
[ kParentSetIndex
]));
1483 OSIterator
* IORegistryEntry::getParentIterator(
1484 const IORegistryPlane
* plane
) const
1493 links
= getParentSetReference( plane
);
1495 links
= OSArray::withCapacity( 1 );
1497 links
= OSArray::withArray( links
, links
->getCount() );
1500 iter
= IOLinkIterator::withCollection( links
);
1508 IORegistryEntry
* IORegistryEntry::copyParentEntry( const IORegistryPlane
* plane
) const
1510 IORegistryEntry
* entry
= 0;
1515 if( (links
= getParentSetReference( plane
))) {
1516 entry
= (IORegistryEntry
*) links
->getObject( 0 );
1525 IORegistryEntry
* IORegistryEntry::getParentEntry( const IORegistryPlane
* plane
) const
1527 IORegistryEntry
* entry
;
1529 entry
= copyParentEntry( plane
);
1536 OSArray
* IORegistryEntry::getChildSetReference( const IORegistryPlane
* plane
) const
1539 return( (OSArray
*) registryTable()->getObject(
1540 plane
->keys
[ kChildSetIndex
]));
1545 OSIterator
* IORegistryEntry::getChildIterator( const IORegistryPlane
* plane
) const
1554 links
= getChildSetReference( plane
);
1556 links
= OSArray::withCapacity( 1 );
1558 links
= OSArray::withArray( links
, links
->getCount() );
1561 iter
= IOLinkIterator::withCollection( links
);
1570 IORegistryEntry
* IORegistryEntry::copyChildEntry(
1571 const IORegistryPlane
* plane
) const
1573 IORegistryEntry
* entry
= 0;
1578 if( (links
= getChildSetReference( plane
))) {
1579 entry
= (IORegistryEntry
*) links
->getObject( 0 );
1588 IORegistryEntry
* IORegistryEntry::getChildEntry(
1589 const IORegistryPlane
* plane
) const
1591 IORegistryEntry
* entry
;
1593 entry
= copyChildEntry( plane
);
1600 void IORegistryEntry::applyToChildren( IORegistryEntryApplierFunction applier
,
1602 const IORegistryPlane
* plane
) const
1606 IORegistryEntry
* next
;
1612 array
= OSArray::withArray( getChildSetReference( plane
));
1616 (next
= (IORegistryEntry
*) array
->getObject( index
));
1618 (*applier
)(next
, context
);
1623 void IORegistryEntry::applyToParents( IORegistryEntryApplierFunction applier
,
1625 const IORegistryPlane
* plane
) const
1629 IORegistryEntry
* next
;
1635 array
= OSArray::withArray( getParentSetReference( plane
));
1639 (next
= (IORegistryEntry
*) array
->getObject( index
));
1641 (*applier
)(next
, context
);
1646 bool IORegistryEntry::isChild( IORegistryEntry
* child
,
1647 const IORegistryPlane
* plane
,
1648 bool onlyChild
) const
1655 if( (links
= getChildSetReference( plane
))) {
1656 if( (!onlyChild
) || (1 == links
->getCount()))
1657 ret
= arrayMember( links
, child
);
1659 if( ret
&& (links
= child
->getParentSetReference( plane
)))
1660 ret
= arrayMember( links
, this );
1667 bool IORegistryEntry::isParent( IORegistryEntry
* parent
,
1668 const IORegistryPlane
* plane
,
1669 bool onlyParent
) const
1677 if( (links
= getParentSetReference( plane
))) {
1678 if( (!onlyParent
) || (1 == links
->getCount()))
1679 ret
= arrayMember( links
, parent
);
1681 if( ret
&& (links
= parent
->getChildSetReference( plane
)))
1682 ret
= arrayMember( links
, this );
1689 bool IORegistryEntry::inPlane( const IORegistryPlane
* plane
) const
1696 ret
= (0 != getParentSetReference( plane
));
1699 // Check to see if this is in any plane. If it is in a plane
1700 // then the registryTable will contain a key with the ParentLinks
1701 // suffix. When we iterate over the keys looking for that suffix
1704 OSCollectionIterator
*iter
=
1705 OSCollectionIterator::withCollection( registryTable());
1707 const OSSymbol
*key
;
1709 while( (key
= (OSSymbol
*) iter
->getNextObject()) ) {
1710 const char *keysuffix
;
1712 // Get a pointer to this keys suffix
1713 keysuffix
= key
->getCStringNoCopy()
1714 + key
->getLength() - kIORegPlaneParentSuffixLen
;
1715 if( !strcmp(keysuffix
, kIORegPlaneParentSuffix
) ) {
1729 bool IORegistryEntry::attachToParent( IORegistryEntry
* parent
,
1730 const IORegistryPlane
* plane
)
1741 ret
= makeLink( parent
, kParentSetIndex
, plane
);
1743 if( (links
= parent
->getChildSetReference( plane
)))
1744 needParent
= (false == arrayMember( links
, this ));
1752 // Mark any collections in the property list as immutable
1753 OSDictionary
*ptable
= getPropertyTable();
1754 OSCollectionIterator
*iter
=
1755 OSCollectionIterator::withCollection( ptable
);
1757 const OSSymbol
*key
;
1759 while( (key
= (OSSymbol
*) iter
->getNextObject( ))) {
1760 // Is object for key a collection?
1761 OSCollection
*coll
=
1762 OSDynamicCast( OSCollection
, ptable
->getObject( key
));
1765 // Yup so mark it as immutable
1766 coll
->setOptions( OSCollection::kMASK
,
1767 OSCollection::kImmutable
);
1776 ret
&= parent
->attachToChild( this, plane
);
1781 bool IORegistryEntry::attachToChild( IORegistryEntry
* child
,
1782 const IORegistryPlane
* plane
)
1793 ret
= makeLink( child
, kChildSetIndex
, plane
);
1795 if( (links
= child
->getParentSetReference( plane
)))
1796 needChild
= (false == arrayMember( links
, this ));
1803 ret
&= child
->attachToParent( this, plane
);
1808 void IORegistryEntry::detachFromParent( IORegistryEntry
* parent
,
1809 const IORegistryPlane
* plane
)
1818 breakLink( parent
, kParentSetIndex
, plane
);
1820 if( (links
= parent
->getChildSetReference( plane
)))
1821 needParent
= arrayMember( links
, this );
1825 // parent->breakLink( this, kChildSetIndex, plane );
1830 parent
->detachFromChild( this, plane
);
1835 void IORegistryEntry::detachFromChild( IORegistryEntry
* child
,
1836 const IORegistryPlane
* plane
)
1845 breakLink( child
, kChildSetIndex
, plane
);
1847 if( (links
= child
->getParentSetReference( plane
)))
1848 needChild
= arrayMember( links
, this );
1855 child
->detachFromParent( this, plane
);
1860 void IORegistryEntry::detachAbove( const IORegistryPlane
* plane
)
1862 IORegistryEntry
* parent
;
1865 while( (parent
= getParentEntry( plane
)))
1866 detachFromParent( parent
, plane
);
1870 void IORegistryEntry::detachAll( const IORegistryPlane
* plane
)
1873 IORegistryEntry
* next
;
1874 IORegistryIterator
* regIter
;
1876 regIter
= IORegistryIterator::iterateOver( this, plane
, true );
1879 all
= regIter
->iterateAll();
1882 detachAbove( plane
);
1884 while( (next
= (IORegistryEntry
*) all
->getLastObject())) {
1887 all
->removeObject(next
);
1889 next
->detachAbove( plane
);
1896 unsigned int IORegistryEntry::getDepth( const IORegistryPlane
* plane
) const
1898 unsigned int depth
= 1;
1900 unsigned int oneDepth
, maxParentDepth
, count
;
1901 IORegistryEntry
* one
;
1902 const IORegistryEntry
* next
;
1908 while( (parents
= next
->getParentSetReference( plane
))) {
1910 count
= parents
->getCount();
1915 next
= (IORegistryEntry
*) parents
->getObject( 0 );
1920 (one
= (IORegistryEntry
*) parents
->getObject( index
));
1922 oneDepth
= one
->getDepth( plane
);
1923 if( oneDepth
> maxParentDepth
)
1924 maxParentDepth
= oneDepth
;
1926 depth
+= maxParentDepth
;
1936 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1939 #define super OSIterator
1941 OSDefineMetaClassAndStructors(IORegistryIterator
, OSIterator
)
1943 enum { kIORegistryIteratorInvalidFlag
= 0x80000000 };
1945 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1947 IORegistryIterator
*
1948 IORegistryIterator::iterateOver( IORegistryEntry
* root
,
1949 const IORegistryPlane
* plane
,
1950 IOOptionBits options
)
1952 IORegistryIterator
* create
;
1959 create
= new IORegistryIterator
;
1961 if( create
->init()) {
1964 create
->root
= root
;
1965 create
->where
= &create
->start
;
1966 create
->start
.current
= root
;
1967 create
->plane
= plane
;
1968 create
->options
= options
& ~kIORegistryIteratorInvalidFlag
;
1978 IORegistryIterator
*
1979 IORegistryIterator::iterateOver( const IORegistryPlane
* plane
,
1980 IOOptionBits options
)
1982 return( iterateOver( gRegistryRoot
, plane
, options
));
1985 bool IORegistryIterator::isValid( void )
1994 ok
= (0 == (kIORegistryIteratorInvalidFlag
& options
));
1996 while( ok
&& next
) {
1998 ok
= where
->iter
->isValid();
2006 void IORegistryIterator::enterEntry( const IORegistryPlane
* enterPlane
)
2011 where
= (IORegCursor
*) IOMalloc( sizeof( IORegCursor
));
2017 where
->current
= prev
->current
;
2022 void IORegistryIterator::enterEntry( void )
2024 enterEntry( plane
);
2027 bool IORegistryIterator::exitEntry( void )
2032 where
->iter
->release();
2034 if( where
->current
)// && (where != &start))
2035 where
->current
->release();
2038 if( where
!= &start
) {
2041 IOFree( gone
, sizeof( IORegCursor
));
2048 void IORegistryIterator::reset( void )
2058 where
->current
= root
;
2059 options
&= ~kIORegistryIteratorInvalidFlag
;
2062 void IORegistryIterator::free( void )
2073 IORegistryEntry
* IORegistryIterator::getNextObjectFlat( void )
2075 IORegistryEntry
* next
= 0;
2076 OSArray
* links
= 0;
2080 if( (0 == where
->iter
)) {
2081 // just entered - create new iter
2084 && (links
= ( (options
& kIORegistryIterateParents
) ?
2085 where
->current
->getParentSetReference( plane
) :
2086 where
->current
->getChildSetReference( plane
) )) )
2088 where
->iter
= OSCollectionIterator::withCollection( links
);
2091 // next sibling - release current
2093 where
->current
->release();
2097 next
= (IORegistryEntry
*) where
->iter
->getNextObject();
2101 else if( !where
->iter
->isValid())
2102 options
|= kIORegistryIteratorInvalidFlag
;
2105 where
->current
= next
;
2112 IORegistryEntry
* IORegistryIterator::getNextObjectRecursive( void )
2114 IORegistryEntry
* next
;
2117 next
= getNextObjectFlat();
2118 while( (0 == next
) && exitEntry());
2122 done
= OSOrderedSet::withCapacity( 10 );
2123 if( done
->setObject((OSObject
*) next
)) {
2124 // done set didn't contain this one, so recurse
2131 IORegistryEntry
* IORegistryIterator::getNextObject( void )
2133 if( options
& kIORegistryIterateRecursively
)
2134 return( getNextObjectRecursive());
2136 return( getNextObjectFlat());
2139 IORegistryEntry
* IORegistryIterator::getCurrentEntry( void )
2142 return( where
->current
);
2147 OSOrderedSet
* IORegistryIterator::iterateAll( void )
2150 while( getNextObjectRecursive())
2157 OSMetaClassDefineReservedUsed(IORegistryEntry
, 0);
2158 OSMetaClassDefineReservedUsed(IORegistryEntry
, 1);
2159 OSMetaClassDefineReservedUsed(IORegistryEntry
, 2);
2160 OSMetaClassDefineReservedUsed(IORegistryEntry
, 3);
2161 OSMetaClassDefineReservedUsed(IORegistryEntry
, 4);
2162 OSMetaClassDefineReservedUsed(IORegistryEntry
, 5);
2164 OSMetaClassDefineReservedUnused(IORegistryEntry
, 6);
2165 OSMetaClassDefineReservedUnused(IORegistryEntry
, 7);
2166 OSMetaClassDefineReservedUnused(IORegistryEntry
, 8);
2167 OSMetaClassDefineReservedUnused(IORegistryEntry
, 9);
2168 OSMetaClassDefineReservedUnused(IORegistryEntry
, 10);
2169 OSMetaClassDefineReservedUnused(IORegistryEntry
, 11);
2170 OSMetaClassDefineReservedUnused(IORegistryEntry
, 12);
2171 OSMetaClassDefineReservedUnused(IORegistryEntry
, 13);
2172 OSMetaClassDefineReservedUnused(IORegistryEntry
, 14);
2173 OSMetaClassDefineReservedUnused(IORegistryEntry
, 15);
2174 OSMetaClassDefineReservedUnused(IORegistryEntry
, 16);
2175 OSMetaClassDefineReservedUnused(IORegistryEntry
, 17);
2176 OSMetaClassDefineReservedUnused(IORegistryEntry
, 18);
2177 OSMetaClassDefineReservedUnused(IORegistryEntry
, 19);
2178 OSMetaClassDefineReservedUnused(IORegistryEntry
, 20);
2179 OSMetaClassDefineReservedUnused(IORegistryEntry
, 21);
2180 OSMetaClassDefineReservedUnused(IORegistryEntry
, 22);
2181 OSMetaClassDefineReservedUnused(IORegistryEntry
, 23);
2182 OSMetaClassDefineReservedUnused(IORegistryEntry
, 24);
2183 OSMetaClassDefineReservedUnused(IORegistryEntry
, 25);
2184 OSMetaClassDefineReservedUnused(IORegistryEntry
, 26);
2185 OSMetaClassDefineReservedUnused(IORegistryEntry
, 27);
2186 OSMetaClassDefineReservedUnused(IORegistryEntry
, 28);
2187 OSMetaClassDefineReservedUnused(IORegistryEntry
, 29);
2188 OSMetaClassDefineReservedUnused(IORegistryEntry
, 30);
2189 OSMetaClassDefineReservedUnused(IORegistryEntry
, 31);
2191 /* inline function implementation */
2192 OSDictionary
* IORegistryEntry::getPropertyTable( void ) const
2193 { return(fPropertyTable
); }