2 * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_OSREFERENCE_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
10 * License may not be used to create, or enable the creation or
11 * redistribution of, unlawful or unlicensed copies of an Apple operating
12 * system, or to circumvent, violate, or enable the circumvention or
13 * violation of, any terms of an Apple operating system software license
16 * Please obtain a copy of the License at
17 * http://www.opensource.apple.com/apsl/ and read it before using this
20 * The Original Code and all software distributed under the License are
21 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
22 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
23 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
24 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
25 * Please see the License for the specific language governing rights and
26 * limitations under the License.
28 * @APPLE_LICENSE_OSREFERENCE_HEADER_END@
31 * Copyright (c) 1998 Apple Computer, Inc. All rights reserved.
34 * 12 Nov 98 sdouglas created.
38 #include <IOKit/IORegistryEntry.h>
39 #include <libkern/c++/OSContainers.h>
40 #include <IOKit/IOService.h>
41 #include <IOKit/IOKitKeys.h>
43 #include <IOKit/IOLib.h>
45 #include <IOKit/assert.h>
47 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
49 #define super OSObject
51 OSDefineMetaClassAndStructors(IORegistryEntry
, OSObject
)
53 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
55 #define kIORegPlaneParentSuffix "ParentLinks"
56 #define kIORegPlaneChildSuffix "ChildLinks"
57 #define kIORegPlaneNameSuffix "Name"
58 #define kIORegPlaneLocationSuffix "Location"
59 #define kIORegPlaneParentSuffixLen (sizeof(kIORegPlaneParentSuffix) - 1)
61 static IORegistryEntry
* gRegistryRoot
;
62 static OSDictionary
* gIORegistryPlanes
;
64 const OSSymbol
* gIONameKey
;
65 const OSSymbol
* gIOLocationKey
;
76 class IORegistryPlane
: public OSObject
{
78 friend class IORegistryEntry
;
80 OSDeclareAbstractStructors(IORegistryPlane
)
82 const OSSymbol
* nameKey
;
83 const OSSymbol
* keys
[ kNumSetIndex
];
84 const OSSymbol
* pathNameKey
;
85 const OSSymbol
* pathLocationKey
;
89 virtual bool serialize(OSSerialize
*s
) const;
92 OSDefineMetaClassAndStructors(IORegistryPlane
, OSObject
)
95 static IORecursiveLock
* gPropertiesLock
;
96 static SInt32 gIORegistryGenerationCount
;
98 #define UNLOCK s_lock_done( &gIORegistryLock )
99 #define RLOCK s_lock_read( &gIORegistryLock )
100 #define WLOCK s_lock_write( &gIORegistryLock ); \
101 gIORegistryGenerationCount++
104 #define PUNLOCK IORecursiveLockUnlock( gPropertiesLock )
105 #define PLOCK IORecursiveLockLock( gPropertiesLock )
107 #define IOREGSPLITTABLES
109 #ifdef IOREGSPLITTABLES
110 #define registryTable() fRegistryTable
112 #define registryTable() fPropertyTable
117 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
120 lck_spin_t interlock
; /* "hardware" interlock field */
121 volatile unsigned int
122 read_count
:16, /* No. of accepted readers */
123 want_upgrade
:1, /* Read-to-write upgrade waiting */
124 want_write
:1, /* Writer is waiting, or
126 waiting
:1, /* Someone is sleeping on lock */
127 can_sleep
:1; /* Can attempts to lock go to sleep? */
130 static struct s_lock_t gIORegistryLock
;
132 /* Time we loop without holding the interlock.
133 * The former is for when we cannot sleep, the latter
134 * for when our thread can go to sleep (loop less)
135 * we shouldn't retake the interlock at all frequently
136 * if we cannot go to sleep, since it interferes with
137 * any other processors. In particular, 100 is too small
138 * a number for powerpc MP systems because of cache
139 * coherency issues and differing lock fetch times between
142 static unsigned int lock_wait_time
[2] = { (unsigned int)-1, 100 } ;
149 (void) memset((void *) l
, 0, sizeof(s_lock_t
));
151 lck_spin_init(&l
->interlock
, IOLockGroup
, LCK_ATTR_NULL
);
152 l
->want_write
= FALSE
;
153 l
->want_upgrade
= FALSE
;
155 l
->can_sleep
= can_sleep
;
160 register s_lock_t
* l
)
164 lck_spin_lock(&l
->interlock
);
167 * Try to acquire the want_write bit.
169 while (l
->want_write
) {
171 i
= lock_wait_time
[l
->can_sleep
? 1 : 0];
173 lck_spin_unlock(&l
->interlock
);
174 while (--i
!= 0 && l
->want_write
)
176 lck_spin_lock(&l
->interlock
);
179 if (l
->can_sleep
&& l
->want_write
) {
181 lck_spin_sleep( &l
->interlock
, LCK_SLEEP_DEFAULT
,
182 (event_t
) l
, THREAD_UNINT
);
183 /* interlock relocked */
186 l
->want_write
= TRUE
;
188 /* Wait for readers (and upgrades) to finish */
190 while ((l
->read_count
!= 0) || l
->want_upgrade
) {
192 i
= lock_wait_time
[l
->can_sleep
? 1 : 0];
194 lck_spin_unlock(&l
->interlock
);
195 while (--i
!= 0 && (l
->read_count
!= 0 ||
198 lck_spin_lock(&l
->interlock
);
201 if (l
->can_sleep
&& (l
->read_count
!= 0 || l
->want_upgrade
)) {
203 lck_spin_sleep( &l
->interlock
, LCK_SLEEP_DEFAULT
,
204 (event_t
) l
, THREAD_UNINT
);
205 /* interlock relocked */
209 lck_spin_unlock(&l
->interlock
);
214 register s_lock_t
* l
)
216 boolean_t do_wakeup
= FALSE
;
218 lck_spin_lock(&l
->interlock
);
220 if (l
->read_count
!= 0) {
224 if (l
->want_upgrade
) {
225 l
->want_upgrade
= FALSE
;
228 l
->want_write
= FALSE
;
233 * There is no reason to wakeup a waiting thread
234 * if the read-count is non-zero. Consider:
235 * we must be dropping a read lock
236 * threads are waiting only if one wants a write lock
237 * if there are still readers, they can't proceed
239 if (l
->waiting
&& (l
->read_count
== 0)) {
244 lck_spin_unlock(&l
->interlock
);
247 thread_wakeup((event_t
) l
);
252 register s_lock_t
* l
)
256 lck_spin_lock(&l
->interlock
);
258 while ( l
->want_upgrade
|| ((0 == l
->read_count
) && l
->want_write
)) {
260 i
= lock_wait_time
[l
->can_sleep
? 1 : 0];
263 lck_spin_unlock(&l
->interlock
);
265 (l
->want_upgrade
|| ((0 == l
->read_count
) && l
->want_write
)))
267 lck_spin_lock(&l
->interlock
);
271 (l
->want_upgrade
|| ((0 == l
->read_count
) && l
->want_write
))) {
273 lck_spin_sleep( &l
->interlock
, LCK_SLEEP_DEFAULT
,
274 (event_t
) l
, THREAD_UNINT
);
275 /* interlock relocked */
280 lck_spin_unlock(&l
->interlock
);
284 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
286 IORegistryEntry
* IORegistryEntry::initialize( void )
290 if( !gRegistryRoot
) {
292 s_lock_init( &gIORegistryLock
, true );
293 gRegistryRoot
= new IORegistryEntry
;
294 gPropertiesLock
= IORecursiveLockAlloc();
295 gIORegistryPlanes
= OSDictionary::withCapacity( 1 );
297 assert( gRegistryRoot
&& gPropertiesLock
298 && gIORegistryPlanes
);
299 ok
= gRegistryRoot
->init();
301 gIONameKey
= OSSymbol::withCStringNoCopy( "IOName" );
302 gIOLocationKey
= OSSymbol::withCStringNoCopy( "IOLocation" );
304 assert( ok
&& gIONameKey
&& gIOLocationKey
);
306 gRegistryRoot
->setName( "Root" );
307 gRegistryRoot
->setProperty( kIORegistryPlanesKey
, gIORegistryPlanes
);
310 return( gRegistryRoot
);
313 IORegistryEntry
* IORegistryEntry::getRegistryRoot( void )
315 return( gRegistryRoot
);
318 SInt32
IORegistryEntry::getGenerationCount( void )
320 return( gIORegistryGenerationCount
);
324 const IORegistryPlane
* IORegistryEntry::makePlane( const char * name
)
326 IORegistryPlane
* plane
;
327 const OSSymbol
* nameKey
;
328 const OSSymbol
* parentKey
;
329 const OSSymbol
* childKey
;
330 const OSSymbol
* pathNameKey
;
331 const OSSymbol
* pathLocationKey
;
332 char key
[ kIOMaxPlaneName
+ 16 ];
335 strncpy( key
, name
, kIOMaxPlaneName
);
336 key
[ kIOMaxPlaneName
] = 0;
337 end
= key
+ strlen( name
);
339 nameKey
= OSSymbol::withCString( key
);
341 strcpy( end
, kIORegPlaneParentSuffix
);
342 parentKey
= OSSymbol::withCString( key
);
344 strcpy( end
, kIORegPlaneChildSuffix
);
345 childKey
= OSSymbol::withCString( key
);
347 strcpy( end
, kIORegPlaneNameSuffix
);
348 pathNameKey
= OSSymbol::withCString( key
);
350 strcpy( end
, kIORegPlaneLocationSuffix
);
351 pathLocationKey
= OSSymbol::withCString( key
);
353 plane
= new IORegistryPlane
;
355 if( plane
&& plane
->init()
356 && nameKey
&& parentKey
&& childKey
357 && pathNameKey
&& pathLocationKey
) {
359 plane
->nameKey
= nameKey
;
360 plane
->keys
[ kParentSetIndex
] = parentKey
;
361 plane
->keys
[ kChildSetIndex
] = childKey
;
362 plane
->pathNameKey
= pathNameKey
;
363 plane
->pathLocationKey
= pathLocationKey
;
366 gIORegistryPlanes
->setObject( nameKey
, plane
);
374 pathLocationKey
->release();
376 pathNameKey
->release();
378 parentKey
->release();
389 const IORegistryPlane
* IORegistryEntry::getPlane( const char * name
)
391 const IORegistryPlane
* plane
;
394 plane
= (const IORegistryPlane
*) gIORegistryPlanes
->getObject( name
);
400 bool IORegistryPlane::serialize(OSSerialize
*s
) const
402 return( nameKey
->serialize(s
) );
405 enum { kIORegCapacityIncrement
= 4 };
407 bool IORegistryEntry::init( OSDictionary
* dict
)
417 fPropertyTable
->release();
418 fPropertyTable
= dict
;
420 } else if( !fPropertyTable
) {
421 fPropertyTable
= OSDictionary::withCapacity( kIORegCapacityIncrement
);
423 fPropertyTable
->setCapacityIncrement( kIORegCapacityIncrement
);
429 #ifdef IOREGSPLITTABLES
430 if( !fRegistryTable
) {
431 fRegistryTable
= OSDictionary::withCapacity( kIORegCapacityIncrement
);
433 fRegistryTable
->setCapacityIncrement( kIORegCapacityIncrement
);
436 if( (prop
= OSDynamicCast( OSString
, getProperty( gIONameKey
)))) {
437 OSSymbol
* sym
= (OSSymbol
*)OSSymbol::withString( prop
);
438 // ok for OSSymbol too
443 #endif /* IOREGSPLITTABLES */
448 bool IORegistryEntry::init( IORegistryEntry
* old
,
449 const IORegistryPlane
* plane
)
452 IORegistryEntry
* next
;
460 fPropertyTable
= old
->getPropertyTable();
461 fPropertyTable
->retain();
462 #ifdef IOREGSPLITTABLES
463 fRegistryTable
= old
->fRegistryTable
;
464 old
->fRegistryTable
= OSDictionary::withDictionary( fRegistryTable
);
465 #endif /* IOREGSPLITTABLES */
467 old
->registryTable()->removeObject( plane
->keys
[ kParentSetIndex
] );
468 old
->registryTable()->removeObject( plane
->keys
[ kChildSetIndex
] );
470 all
= getParentSetReference( plane
);
471 if( all
) for( index
= 0;
472 (next
= (IORegistryEntry
*) all
->getObject(index
));
474 next
->makeLink( this, kChildSetIndex
, plane
);
475 next
->breakLink( old
, kChildSetIndex
, plane
);
478 all
= getChildSetReference( plane
);
479 if( all
) for( index
= 0;
480 (next
= (IORegistryEntry
*) all
->getObject(index
));
482 next
->makeLink( this, kParentSetIndex
, plane
);
483 next
->breakLink( old
, kParentSetIndex
, plane
);
491 void IORegistryEntry::free( void )
495 #define msg ": attached at free()"
496 char buf
[ strlen(msg
) + 40 ];
498 if( registryTable() && gIOServicePlane
) {
499 if( getParentSetReference( gIOServicePlane
)
500 || getChildSetReference( gIOServicePlane
)) {
502 strncpy( buf
, getName(), 32);
510 if( getPropertyTable())
511 getPropertyTable()->release();
513 #ifdef IOREGSPLITTABLES
515 registryTable()->release();
516 #endif /* IOREGSPLITTABLES */
521 void IORegistryEntry::setPropertyTable( OSDictionary
* dict
)
524 fPropertyTable
->release();
527 fPropertyTable
= dict
;
530 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
532 /* Wrappers to synchronize property table */
534 #define wrap2(type, constant) \
536 IORegistryEntry::copyProperty( type * aKey) constant \
541 obj = getProperty( aKey ); \
549 #define wrap4(type,constant) \
551 IORegistryEntry::getProperty( type * aKey, \
552 const IORegistryPlane * plane, \
553 IOOptionBits options ) constant \
555 OSObject * obj = getProperty( aKey ); \
557 if ( (0 == obj) && plane && (options & kIORegistryIterateRecursively) ) { \
558 IORegistryEntry * entry = (IORegistryEntry *) this; \
559 IORegistryIterator * iter; \
560 iter = IORegistryIterator::iterateOver( entry, plane, options ); \
563 while ( (0 == obj) && (entry = iter->getNextObject()) ) { \
564 obj = entry->getProperty( aKey ); \
573 #define wrap5(type,constant) \
575 IORegistryEntry::copyProperty( type * aKey, \
576 const IORegistryPlane * plane, \
577 IOOptionBits options ) constant \
579 OSObject * obj = copyProperty( aKey ); \
581 if ( (0 == obj) && plane && (options & kIORegistryIterateRecursively) ) { \
582 IORegistryEntry * entry = (IORegistryEntry *) this; \
583 IORegistryIterator * iter; \
584 iter = IORegistryIterator::iterateOver( entry, plane, options ); \
587 while ( (0 == obj) && (entry = iter->getNextObject()) ) { \
588 obj = entry->copyProperty( aKey ); \
597 bool IORegistryEntry::serializeProperties( OSSerialize
* s
) const
599 // setProperty( getRetainCount(), 32, "__retain" );
602 OSCollection
*snapshotProperties
= getPropertyTable()->copyCollection();
605 bool ok
= snapshotProperties
->serialize( s
);
606 snapshotProperties
->release();
610 OSDictionary
* IORegistryEntry::dictionaryWithProperties( void ) const
615 dict
= OSDictionary::withDictionary( getPropertyTable(),
616 getPropertyTable()->getCapacity() );
622 IOReturn
IORegistryEntry::setProperties( OSObject
* properties
)
624 return( kIOReturnUnsupported
);
627 wrap2(const OSSymbol
, const) // copyProperty() definition
628 wrap2(const OSString
, const) // copyProperty() definition
629 wrap2(const char, const) // copyProperty() definition
631 wrap4(const OSSymbol
, const) // getProperty() w/plane definition
632 wrap4(const OSString
, const) // getProperty() w/plane definition
633 wrap4(const char, const) // getProperty() w/plane definition
635 wrap5(const OSSymbol
, const) // copyProperty() w/plane definition
636 wrap5(const OSString
, const) // copyProperty() w/plane definition
637 wrap5(const char, const) // copyProperty() w/plane definition
641 IORegistryEntry::getProperty( const OSSymbol
* aKey
) const
646 obj
= getPropertyTable()->getObject( aKey
);
653 IORegistryEntry::removeProperty( const OSSymbol
* aKey
)
656 getPropertyTable()->removeObject( aKey
);
661 IORegistryEntry::setProperty( const OSSymbol
* aKey
, OSObject
* anObject
)
665 // If we are inserting a collection class and the current entry
666 // is attached into the registry (inPlane()) then mark the collection
668 OSCollection
*coll
= OSDynamicCast(OSCollection
, anObject
);
669 bool makeImmutable
= (coll
&& inPlane());
673 coll
->setOptions( OSCollection::kMASK
, OSCollection::kImmutable
);
675 ret
= getPropertyTable()->setObject( aKey
, anObject
);
681 IOReturn
IORegistryEntry::
682 runPropertyAction(Action inAction
, OSObject
*target
,
683 void *arg0
, void *arg1
, void *arg2
, void *arg3
)
687 // closeGate is recursive so don't worry if we already hold the lock.
689 res
= (*inAction
)(target
, arg0
, arg1
, arg2
, arg3
);
696 IORegistryEntry::getProperty( const OSString
* aKey
) const
698 const OSSymbol
* tmpKey
= OSSymbol::withString( aKey
);
699 OSObject
* obj
= getProperty( tmpKey
);
706 IORegistryEntry::getProperty( const char * aKey
) const
708 const OSSymbol
* tmpKey
= OSSymbol::withCString( aKey
);
709 OSObject
* obj
= getProperty( tmpKey
);
717 IORegistryEntry::removeProperty( const OSString
* aKey
)
719 const OSSymbol
* tmpKey
= OSSymbol::withString( aKey
);
720 removeProperty( tmpKey
);
725 IORegistryEntry::removeProperty( const char * aKey
)
727 const OSSymbol
* tmpKey
= OSSymbol::withCString( aKey
);
728 removeProperty( tmpKey
);
733 IORegistryEntry::setProperty( const OSString
* aKey
, OSObject
* anObject
)
735 const OSSymbol
* tmpKey
= OSSymbol::withString( aKey
);
736 bool ret
= setProperty( tmpKey
, anObject
);
743 IORegistryEntry::setProperty( const char * aKey
, OSObject
* anObject
)
745 const OSSymbol
* tmpKey
= OSSymbol::withCString( aKey
);
746 bool ret
= setProperty( tmpKey
, anObject
);
753 IORegistryEntry::setProperty(const char * aKey
, const char * aString
)
756 OSSymbol
* aSymbol
= (OSSymbol
*) OSSymbol::withCString( aString
);
759 const OSSymbol
* tmpKey
= OSSymbol::withCString( aKey
);
760 ret
= setProperty( tmpKey
, aSymbol
);
769 IORegistryEntry::setProperty(const char * aKey
, bool aBoolean
)
772 OSBoolean
* aBooleanObj
= OSBoolean::withBoolean( aBoolean
);
775 const OSSymbol
* tmpKey
= OSSymbol::withCString( aKey
);
776 ret
= setProperty( tmpKey
, aBooleanObj
);
779 aBooleanObj
->release();
785 IORegistryEntry::setProperty( const char * aKey
,
786 unsigned long long aValue
,
787 unsigned int aNumberOfBits
)
790 OSNumber
* anOffset
= OSNumber::withNumber( aValue
, aNumberOfBits
);
793 const OSSymbol
* tmpKey
= OSSymbol::withCString( aKey
);
794 ret
= setProperty( tmpKey
, anOffset
);
803 IORegistryEntry::setProperty( const char * aKey
,
808 OSData
* data
= OSData::withBytes( bytes
, length
);
811 const OSSymbol
* tmpKey
= OSSymbol::withCString( aKey
);
812 ret
= setProperty( tmpKey
, data
);
820 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
822 /* Name, location, paths */
824 const char * IORegistryEntry::getName( const IORegistryPlane
* plane
) const
830 sym
= (OSSymbol
*) registryTable()->getObject( plane
->pathNameKey
);
832 sym
= (OSSymbol
*) registryTable()->getObject( gIONameKey
);
836 return( sym
->getCStringNoCopy());
838 return( (getMetaClass())->getClassName());
841 const OSSymbol
* IORegistryEntry::copyName(
842 const IORegistryPlane
* plane
) const
848 sym
= (OSSymbol
*) registryTable()->getObject( plane
->pathNameKey
);
850 sym
= (OSSymbol
*) registryTable()->getObject( gIONameKey
);
858 return( OSSymbol::withCString((getMetaClass())->getClassName()) );
861 const OSSymbol
* IORegistryEntry::copyLocation(
862 const IORegistryPlane
* plane
) const
868 sym
= (OSSymbol
*) registryTable()->getObject( plane
->pathLocationKey
);
870 sym
= (OSSymbol
*) registryTable()->getObject( gIOLocationKey
);
878 const char * IORegistryEntry::getLocation( const IORegistryPlane
* plane
) const
880 const OSSymbol
* sym
= copyLocation( plane
);
881 const char * result
= 0;
884 result
= sym
->getCStringNoCopy();
891 void IORegistryEntry::setName( const OSSymbol
* name
,
892 const IORegistryPlane
* plane
)
894 const OSSymbol
* key
;
898 key
= plane
->pathNameKey
;
903 registryTable()->setObject( key
, (OSObject
*) name
);
908 void IORegistryEntry::setName( const char * name
,
909 const IORegistryPlane
* plane
)
911 OSSymbol
* sym
= (OSSymbol
*)OSSymbol::withCString( name
);
913 setName( sym
, plane
);
918 void IORegistryEntry::setLocation( const OSSymbol
* location
,
919 const IORegistryPlane
* plane
)
921 const OSSymbol
* key
;
925 key
= plane
->pathLocationKey
;
927 key
= gIOLocationKey
;
930 registryTable()->setObject( key
, (OSObject
*) location
);
935 void IORegistryEntry::setLocation( const char * location
,
936 const IORegistryPlane
* plane
)
938 OSSymbol
* sym
= (OSSymbol
*)OSSymbol::withCString( location
);
940 setLocation( sym
, plane
);
946 IORegistryEntry::compareName( OSString
* name
, OSString
** matched
) const
948 const OSSymbol
* sym
= copyName();
951 isEqual
= sym
->isEqualTo( name
);
953 if( isEqual
&& matched
) {
965 IORegistryEntry::compareNames( OSObject
* names
, OSString
** matched
) const
968 OSCollection
* collection
;
969 OSIterator
* iter
= 0;
972 if( (collection
= OSDynamicCast( OSCollection
, names
))) {
973 iter
= OSCollectionIterator::withCollection( collection
);
976 string
= OSDynamicCast( OSString
, names
);
980 result
= compareName( string
, matched
);
982 } while( (false == result
)
983 && iter
&& (string
= OSDynamicCast( OSString
, iter
->getNextObject())));
992 bool IORegistryEntry::getPath( char * path
, int * length
,
993 const IORegistryPlane
* plane
) const
996 IORegistryEntry
* root
;
997 const IORegistryEntry
* entry
;
998 IORegistryEntry
* parent
;
999 const OSSymbol
* alias
;
1001 int len
, maxLength
, compLen
;
1005 if( !path
|| !length
|| !plane
)
1009 maxLength
= *length
- 2;
1012 len
= plane
->nameKey
->getLength();
1013 if( len
>= maxLength
)
1015 strcpy( nextComp
, plane
->nameKey
->getCStringNoCopy());
1016 nextComp
[ len
++ ] = ':';
1019 if( (alias
= hasAlias( plane
))) {
1020 len
+= alias
->getLength();
1021 ok
= (maxLength
> len
);
1024 strcpy( nextComp
, alias
->getCStringNoCopy());
1029 parent
= entry
->getParentEntry( plane
);
1031 // Error if not attached in plane
1034 stack
= OSArray::withCapacity( getDepth( plane
));
1040 root
= gRegistryRoot
->getChildEntry( plane
);
1041 while( parent
&& (entry
!= root
)) {
1043 stack
->setObject( (OSObject
*) entry
);
1045 parent
= entry
->getParentEntry( plane
);
1048 index
= stack
->getCount();
1057 } else while( ok
&& ((--index
) >= 0)) {
1059 entry
= (IORegistryEntry
*) stack
->getObject((unsigned int) index
);
1062 if( (alias
= entry
->hasAlias( plane
))) {
1063 len
= plane
->nameKey
->getLength() + 1;
1064 nextComp
= path
+ len
;
1066 compLen
= alias
->getLength();
1067 ok
= (maxLength
> len
+ compLen
);
1069 strcpy( nextComp
, alias
->getCStringNoCopy());
1071 compLen
= maxLength
- len
;
1072 ok
= entry
->getPathComponent( nextComp
+ 1, &compLen
, plane
);
1074 if( ok
&& compLen
) {
1082 nextComp
+= compLen
;
1094 bool IORegistryEntry::getPathComponent( char * path
, int * length
,
1095 const IORegistryPlane
* plane
) const
1097 int len
, locLen
, maxLength
;
1098 const char * compName
;
1102 maxLength
= *length
;
1104 compName
= getName( plane
);
1105 len
= strlen( compName
);
1106 if( (loc
= getLocation( plane
)))
1107 locLen
= 1 + strlen( loc
);
1111 ok
= ((len
+ locLen
) < maxLength
);
1113 strcpy( path
, compName
);
1118 strcpy( path
, loc
);
1126 const char * IORegistryEntry::matchPathLocation( const char * cmp
,
1127 const IORegistryPlane
* plane
)
1130 const char * result
= 0;
1131 u_quad_t num1
, num2
;
1132 char lastPathChar
, lastLocationChar
;
1134 str
= getLocation( plane
);
1136 lastPathChar
= cmp
[0];
1137 lastLocationChar
= str
[0];
1140 num1
= strtouq( cmp
, (char **) &cmp
, 16 );
1141 lastPathChar
= *cmp
++;
1145 if( lastLocationChar
) {
1146 num2
= strtouq( str
, (char **) &str
, 16 );
1147 lastLocationChar
= *str
++;
1154 if (!lastPathChar
&& !lastLocationChar
) {
1159 if( (',' != lastPathChar
) && (':' != lastPathChar
))
1162 if (lastPathChar
&& lastLocationChar
&& (lastPathChar
!= lastLocationChar
))
1171 IORegistryEntry
* IORegistryEntry::getChildFromComponent( const char ** opath
,
1172 const IORegistryPlane
* plane
)
1174 IORegistryEntry
* entry
= 0;
1178 const char * cmp
= 0;
1183 set
= getChildSetReference( plane
);
1189 (entry
= (IORegistryEntry
*) set
->getObject(index
));
1195 str
= entry
->getName( plane
);
1196 len
= strlen( str
);
1197 if( strncmp( str
, cmp
, len
))
1202 if( (c
== 0) || (c
== '/') || (c
== ':'))
1208 if( (cmp
= entry
->matchPathLocation( cmp
, plane
)))
1218 const OSSymbol
* IORegistryEntry::hasAlias( const IORegistryPlane
* plane
,
1219 char * opath
, int * length
) const
1221 IORegistryEntry
* entry
;
1222 IORegistryEntry
* entry2
;
1223 const OSSymbol
* key
;
1224 const OSSymbol
* bestKey
= 0;
1227 const char * path
= "/aliases";
1229 entry
= IORegistryEntry::fromPath( path
, plane
);
1232 if( (iter
= OSCollectionIterator::withCollection(
1233 entry
->getPropertyTable() ))) {
1235 while( (key
= (OSSymbol
*) iter
->getNextObject())) {
1237 data
= (OSData
*) entry
->getProperty( key
);
1238 path
= (const char *) data
->getBytesNoCopy();
1239 if( (entry2
= IORegistryEntry::fromPath( path
, plane
,
1241 if( this == entry2
) {
1243 || (bestKey
->getLength() > key
->getLength()))
1244 // pick the smallest alias
1258 const char * IORegistryEntry::dealiasPath(
1259 const char ** opath
,
1260 const IORegistryPlane
* plane
)
1262 IORegistryEntry
* entry
;
1264 const char * path
= *opath
;
1265 const char * rpath
= 0;
1268 char temp
[ kIOMaxPlaneName
+ 1 ];
1275 while( (c
= *end
++) && (c
!= '/') && (c
!= ':'))
1278 if( (end
- path
) < kIOMaxPlaneName
) {
1279 strncpy( temp
, path
, end
- path
);
1280 temp
[ end
- path
] = 0;
1283 entry
= IORegistryEntry::fromPath( "/aliases", plane
);
1285 data
= (OSData
*) entry
->getProperty( temp
);
1287 rpath
= (const char *) data
->getBytesNoCopy();
1299 IORegistryEntry
* IORegistryEntry::fromPath(
1301 const IORegistryPlane
* plane
,
1304 IORegistryEntry
* fromEntry
)
1306 IORegistryEntry
* where
= 0;
1307 IORegistryEntry
* aliasEntry
= 0;
1308 IORegistryEntry
* next
;
1314 char temp
[ kIOMaxPlaneName
+ 1 ];
1321 end
= strchr( path
, ':' );
1322 if( end
&& ((end
- path
) < kIOMaxPlaneName
)) {
1323 strncpy( temp
, path
, end
- path
);
1324 temp
[ end
- path
] = 0;
1325 plane
= getPlane( temp
);
1334 if( (alias
= dealiasPath( &end
, plane
))) {
1337 aliasEntry
= IORegistryEntry::fromPath( alias
, plane
,
1338 opath
, &len
, fromEntry
);
1350 if( (0 == fromEntry
) && (*path
++ == '/'))
1351 fromEntry
= gRegistryRoot
->getChildEntry( plane
);
1358 if( c
&& (c
!= ':')) // check valid terminator
1363 next
= where
->getChildFromComponent( &path
, plane
);
1369 // check residual path
1370 if( where
!= fromEntry
)
1373 if( opath
&& length
) {
1374 // copy out residual path
1375 len2
= len
+ strlen( path
);
1377 strcpy( opath
+ len
, path
);
1381 // no residual path => must be no tail for success
1388 aliasEntry
->release();
1395 IORegistryEntry
* IORegistryEntry::childFromPath(
1397 const IORegistryPlane
* plane
,
1401 return( IORegistryEntry::fromPath( path
, plane
, opath
, len
, this ));
1404 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1406 #define IOLinkIterator OSCollectionIterator
1409 #define super OSObject
1411 inline bool IORegistryEntry::arrayMember( OSArray
* set
,
1412 const IORegistryEntry
* member
,
1413 unsigned int * index
) const
1416 OSObject
* probeObject
;
1418 for( i
= 0; (probeObject
= set
->getObject(i
)); i
++) {
1419 if (probeObject
== (OSObject
*) member
) {
1428 bool IORegistryEntry::makeLink( IORegistryEntry
* to
,
1429 unsigned int relation
,
1430 const IORegistryPlane
* plane
) const
1433 bool result
= false;
1435 if( (links
= (OSArray
*)
1436 registryTable()->getObject( plane
->keys
[ relation
] ))) {
1438 result
= arrayMember( links
, to
);
1440 result
= links
->setObject( to
);
1444 links
= OSArray::withObjects( (const OSObject
**) &to
, 1, 1 );
1445 result
= (links
!= 0);
1447 result
= registryTable()->setObject( plane
->keys
[ relation
],
1456 void IORegistryEntry::breakLink( IORegistryEntry
* to
,
1457 unsigned int relation
,
1458 const IORegistryPlane
* plane
) const
1463 if( (links
= (OSArray
*)
1464 registryTable()->getObject( plane
->keys
[ relation
]))) {
1466 if( arrayMember( links
, to
, &index
)) {
1467 links
->removeObject( index
);
1468 if( 0 == links
->getCount())
1469 registryTable()->removeObject( plane
->keys
[ relation
]);
1475 OSArray
* IORegistryEntry::getParentSetReference(
1476 const IORegistryPlane
* plane
) const
1479 return( (OSArray
*) registryTable()->getObject(
1480 plane
->keys
[ kParentSetIndex
]));
1485 OSIterator
* IORegistryEntry::getParentIterator(
1486 const IORegistryPlane
* plane
) const
1495 links
= getParentSetReference( plane
);
1497 links
= OSArray::withCapacity( 1 );
1499 links
= OSArray::withArray( links
, links
->getCount() );
1502 iter
= IOLinkIterator::withCollection( links
);
1510 IORegistryEntry
* IORegistryEntry::copyParentEntry( const IORegistryPlane
* plane
) const
1512 IORegistryEntry
* entry
= 0;
1517 if( (links
= getParentSetReference( plane
))) {
1518 entry
= (IORegistryEntry
*) links
->getObject( 0 );
1527 IORegistryEntry
* IORegistryEntry::getParentEntry( const IORegistryPlane
* plane
) const
1529 IORegistryEntry
* entry
;
1531 entry
= copyParentEntry( plane
);
1538 OSArray
* IORegistryEntry::getChildSetReference( const IORegistryPlane
* plane
) const
1541 return( (OSArray
*) registryTable()->getObject(
1542 plane
->keys
[ kChildSetIndex
]));
1547 OSIterator
* IORegistryEntry::getChildIterator( const IORegistryPlane
* plane
) const
1556 links
= getChildSetReference( plane
);
1558 links
= OSArray::withCapacity( 1 );
1560 links
= OSArray::withArray( links
, links
->getCount() );
1563 iter
= IOLinkIterator::withCollection( links
);
1572 IORegistryEntry
* IORegistryEntry::copyChildEntry(
1573 const IORegistryPlane
* plane
) const
1575 IORegistryEntry
* entry
= 0;
1580 if( (links
= getChildSetReference( plane
))) {
1581 entry
= (IORegistryEntry
*) links
->getObject( 0 );
1590 IORegistryEntry
* IORegistryEntry::getChildEntry(
1591 const IORegistryPlane
* plane
) const
1593 IORegistryEntry
* entry
;
1595 entry
= copyChildEntry( plane
);
1602 void IORegistryEntry::applyToChildren( IORegistryEntryApplierFunction applier
,
1604 const IORegistryPlane
* plane
) const
1608 IORegistryEntry
* next
;
1614 array
= OSArray::withArray( getChildSetReference( plane
));
1618 (next
= (IORegistryEntry
*) array
->getObject( index
));
1620 (*applier
)(next
, context
);
1625 void IORegistryEntry::applyToParents( IORegistryEntryApplierFunction applier
,
1627 const IORegistryPlane
* plane
) const
1631 IORegistryEntry
* next
;
1637 array
= OSArray::withArray( getParentSetReference( plane
));
1641 (next
= (IORegistryEntry
*) array
->getObject( index
));
1643 (*applier
)(next
, context
);
1648 bool IORegistryEntry::isChild( IORegistryEntry
* child
,
1649 const IORegistryPlane
* plane
,
1650 bool onlyChild
) const
1657 if( (links
= getChildSetReference( plane
))) {
1658 if( (!onlyChild
) || (1 == links
->getCount()))
1659 ret
= arrayMember( links
, child
);
1661 if( ret
&& (links
= child
->getParentSetReference( plane
)))
1662 ret
= arrayMember( links
, this );
1669 bool IORegistryEntry::isParent( IORegistryEntry
* parent
,
1670 const IORegistryPlane
* plane
,
1671 bool onlyParent
) const
1679 if( (links
= getParentSetReference( plane
))) {
1680 if( (!onlyParent
) || (1 == links
->getCount()))
1681 ret
= arrayMember( links
, parent
);
1683 if( ret
&& (links
= parent
->getChildSetReference( plane
)))
1684 ret
= arrayMember( links
, this );
1691 bool IORegistryEntry::inPlane( const IORegistryPlane
* plane
) const
1698 ret
= (0 != getParentSetReference( plane
));
1701 // Check to see if this is in any plane. If it is in a plane
1702 // then the registryTable will contain a key with the ParentLinks
1703 // suffix. When we iterate over the keys looking for that suffix
1706 OSCollectionIterator
*iter
=
1707 OSCollectionIterator::withCollection( registryTable());
1709 const OSSymbol
*key
;
1711 while( (key
= (OSSymbol
*) iter
->getNextObject()) ) {
1712 const char *keysuffix
;
1714 // Get a pointer to this keys suffix
1715 keysuffix
= key
->getCStringNoCopy()
1716 + key
->getLength() - kIORegPlaneParentSuffixLen
;
1717 if( !strcmp(keysuffix
, kIORegPlaneParentSuffix
) ) {
1731 bool IORegistryEntry::attachToParent( IORegistryEntry
* parent
,
1732 const IORegistryPlane
* plane
)
1743 ret
= makeLink( parent
, kParentSetIndex
, plane
);
1745 if( (links
= parent
->getChildSetReference( plane
)))
1746 needParent
= (false == arrayMember( links
, this ));
1754 // Mark any collections in the property list as immutable
1755 OSDictionary
*ptable
= getPropertyTable();
1756 OSCollectionIterator
*iter
=
1757 OSCollectionIterator::withCollection( ptable
);
1759 const OSSymbol
*key
;
1761 while( (key
= (OSSymbol
*) iter
->getNextObject( ))) {
1762 // Is object for key a collection?
1763 OSCollection
*coll
=
1764 OSDynamicCast( OSCollection
, ptable
->getObject( key
));
1767 // Yup so mark it as immutable
1768 coll
->setOptions( OSCollection::kMASK
,
1769 OSCollection::kImmutable
);
1778 ret
&= parent
->attachToChild( this, plane
);
1783 bool IORegistryEntry::attachToChild( IORegistryEntry
* child
,
1784 const IORegistryPlane
* plane
)
1795 ret
= makeLink( child
, kChildSetIndex
, plane
);
1797 if( (links
= child
->getParentSetReference( plane
)))
1798 needChild
= (false == arrayMember( links
, this ));
1805 ret
&= child
->attachToParent( this, plane
);
1810 void IORegistryEntry::detachFromParent( IORegistryEntry
* parent
,
1811 const IORegistryPlane
* plane
)
1820 breakLink( parent
, kParentSetIndex
, plane
);
1822 if( (links
= parent
->getChildSetReference( plane
)))
1823 needParent
= arrayMember( links
, this );
1827 // parent->breakLink( this, kChildSetIndex, plane );
1832 parent
->detachFromChild( this, plane
);
1837 void IORegistryEntry::detachFromChild( IORegistryEntry
* child
,
1838 const IORegistryPlane
* plane
)
1847 breakLink( child
, kChildSetIndex
, plane
);
1849 if( (links
= child
->getParentSetReference( plane
)))
1850 needChild
= arrayMember( links
, this );
1857 child
->detachFromParent( this, plane
);
1862 void IORegistryEntry::detachAbove( const IORegistryPlane
* plane
)
1864 IORegistryEntry
* parent
;
1867 while( (parent
= getParentEntry( plane
)))
1868 detachFromParent( parent
, plane
);
1872 void IORegistryEntry::detachAll( const IORegistryPlane
* plane
)
1875 IORegistryEntry
* next
;
1876 IORegistryIterator
* regIter
;
1878 regIter
= IORegistryIterator::iterateOver( this, plane
, true );
1881 all
= regIter
->iterateAll();
1884 detachAbove( plane
);
1886 while( (next
= (IORegistryEntry
*) all
->getLastObject())) {
1889 all
->removeObject(next
);
1891 next
->detachAbove( plane
);
1898 unsigned int IORegistryEntry::getDepth( const IORegistryPlane
* plane
) const
1900 unsigned int depth
= 1;
1902 unsigned int oneDepth
, maxParentDepth
, count
;
1903 IORegistryEntry
* one
;
1904 const IORegistryEntry
* next
;
1910 while( (parents
= next
->getParentSetReference( plane
))) {
1912 count
= parents
->getCount();
1917 next
= (IORegistryEntry
*) parents
->getObject( 0 );
1922 (one
= (IORegistryEntry
*) parents
->getObject( index
));
1924 oneDepth
= one
->getDepth( plane
);
1925 if( oneDepth
> maxParentDepth
)
1926 maxParentDepth
= oneDepth
;
1928 depth
+= maxParentDepth
;
1938 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1941 #define super OSIterator
1943 OSDefineMetaClassAndStructors(IORegistryIterator
, OSIterator
)
1945 enum { kIORegistryIteratorInvalidFlag
= 0x80000000 };
1947 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1949 IORegistryIterator
*
1950 IORegistryIterator::iterateOver( IORegistryEntry
* root
,
1951 const IORegistryPlane
* plane
,
1952 IOOptionBits options
)
1954 IORegistryIterator
* create
;
1961 create
= new IORegistryIterator
;
1963 if( create
->init()) {
1966 create
->root
= root
;
1967 create
->where
= &create
->start
;
1968 create
->start
.current
= root
;
1969 create
->plane
= plane
;
1970 create
->options
= options
& ~kIORegistryIteratorInvalidFlag
;
1980 IORegistryIterator
*
1981 IORegistryIterator::iterateOver( const IORegistryPlane
* plane
,
1982 IOOptionBits options
)
1984 return( iterateOver( gRegistryRoot
, plane
, options
));
1987 bool IORegistryIterator::isValid( void )
1996 ok
= (0 == (kIORegistryIteratorInvalidFlag
& options
));
1998 while( ok
&& next
) {
2000 ok
= where
->iter
->isValid();
2008 void IORegistryIterator::enterEntry( const IORegistryPlane
* enterPlane
)
2013 where
= (IORegCursor
*) IOMalloc( sizeof( IORegCursor
));
2019 where
->current
= prev
->current
;
2024 void IORegistryIterator::enterEntry( void )
2026 enterEntry( plane
);
2029 bool IORegistryIterator::exitEntry( void )
2034 where
->iter
->release();
2036 if( where
->current
)// && (where != &start))
2037 where
->current
->release();
2040 if( where
!= &start
) {
2043 IOFree( gone
, sizeof( IORegCursor
));
2050 void IORegistryIterator::reset( void )
2060 where
->current
= root
;
2061 options
&= ~kIORegistryIteratorInvalidFlag
;
2064 void IORegistryIterator::free( void )
2075 IORegistryEntry
* IORegistryIterator::getNextObjectFlat( void )
2077 IORegistryEntry
* next
= 0;
2078 OSArray
* links
= 0;
2082 if( (0 == where
->iter
)) {
2083 // just entered - create new iter
2086 && (links
= ( (options
& kIORegistryIterateParents
) ?
2087 where
->current
->getParentSetReference( plane
) :
2088 where
->current
->getChildSetReference( plane
) )) )
2090 where
->iter
= OSCollectionIterator::withCollection( links
);
2093 // next sibling - release current
2095 where
->current
->release();
2099 next
= (IORegistryEntry
*) where
->iter
->getNextObject();
2103 else if( !where
->iter
->isValid())
2104 options
|= kIORegistryIteratorInvalidFlag
;
2107 where
->current
= next
;
2114 IORegistryEntry
* IORegistryIterator::getNextObjectRecursive( void )
2116 IORegistryEntry
* next
;
2119 next
= getNextObjectFlat();
2120 while( (0 == next
) && exitEntry());
2124 done
= OSOrderedSet::withCapacity( 10 );
2125 if( done
->setObject((OSObject
*) next
)) {
2126 // done set didn't contain this one, so recurse
2133 IORegistryEntry
* IORegistryIterator::getNextObject( void )
2135 if( options
& kIORegistryIterateRecursively
)
2136 return( getNextObjectRecursive());
2138 return( getNextObjectFlat());
2141 IORegistryEntry
* IORegistryIterator::getCurrentEntry( void )
2144 return( where
->current
);
2149 OSOrderedSet
* IORegistryIterator::iterateAll( void )
2152 while( getNextObjectRecursive())
2159 OSMetaClassDefineReservedUsed(IORegistryEntry
, 0);
2160 OSMetaClassDefineReservedUsed(IORegistryEntry
, 1);
2161 OSMetaClassDefineReservedUsed(IORegistryEntry
, 2);
2162 OSMetaClassDefineReservedUsed(IORegistryEntry
, 3);
2163 OSMetaClassDefineReservedUsed(IORegistryEntry
, 4);
2164 OSMetaClassDefineReservedUsed(IORegistryEntry
, 5);
2166 OSMetaClassDefineReservedUnused(IORegistryEntry
, 6);
2167 OSMetaClassDefineReservedUnused(IORegistryEntry
, 7);
2168 OSMetaClassDefineReservedUnused(IORegistryEntry
, 8);
2169 OSMetaClassDefineReservedUnused(IORegistryEntry
, 9);
2170 OSMetaClassDefineReservedUnused(IORegistryEntry
, 10);
2171 OSMetaClassDefineReservedUnused(IORegistryEntry
, 11);
2172 OSMetaClassDefineReservedUnused(IORegistryEntry
, 12);
2173 OSMetaClassDefineReservedUnused(IORegistryEntry
, 13);
2174 OSMetaClassDefineReservedUnused(IORegistryEntry
, 14);
2175 OSMetaClassDefineReservedUnused(IORegistryEntry
, 15);
2176 OSMetaClassDefineReservedUnused(IORegistryEntry
, 16);
2177 OSMetaClassDefineReservedUnused(IORegistryEntry
, 17);
2178 OSMetaClassDefineReservedUnused(IORegistryEntry
, 18);
2179 OSMetaClassDefineReservedUnused(IORegistryEntry
, 19);
2180 OSMetaClassDefineReservedUnused(IORegistryEntry
, 20);
2181 OSMetaClassDefineReservedUnused(IORegistryEntry
, 21);
2182 OSMetaClassDefineReservedUnused(IORegistryEntry
, 22);
2183 OSMetaClassDefineReservedUnused(IORegistryEntry
, 23);
2184 OSMetaClassDefineReservedUnused(IORegistryEntry
, 24);
2185 OSMetaClassDefineReservedUnused(IORegistryEntry
, 25);
2186 OSMetaClassDefineReservedUnused(IORegistryEntry
, 26);
2187 OSMetaClassDefineReservedUnused(IORegistryEntry
, 27);
2188 OSMetaClassDefineReservedUnused(IORegistryEntry
, 28);
2189 OSMetaClassDefineReservedUnused(IORegistryEntry
, 29);
2190 OSMetaClassDefineReservedUnused(IORegistryEntry
, 30);
2191 OSMetaClassDefineReservedUnused(IORegistryEntry
, 31);
2193 /* inline function implementation */
2194 OSDictionary
* IORegistryEntry::getPropertyTable( void ) const
2195 { return(fPropertyTable
); }