2 * Copyright (c) 1998-2019 Apple 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 #include <IOKit/IORegistryEntry.h>
30 #include <libkern/c++/OSContainers.h>
31 #include <IOKit/IOService.h>
32 #include <IOKit/IOKitKeys.h>
33 #include <IOKit/IOTimeStamp.h>
34 #include <libkern/c++/OSSharedPtr.h>
36 #include <IOKit/IOLib.h>
37 #include <stdatomic.h>
38 #include <IOKit/assert.h>
39 #include <machine/atomic.h>
41 #include "IOKitKernelInternal.h"
43 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
45 #define super OSObject
47 OSDefineMetaClassAndStructors(IORegistryEntry
, OSObject
)
49 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
51 #define kIORegPlaneParentSuffix "ParentLinks"
52 #define kIORegPlaneChildSuffix "ChildLinks"
53 #define kIORegPlaneNameSuffix "Name"
54 #define kIORegPlaneLocationSuffix "Location"
56 #define kIORegPlaneParentSuffixLen (sizeof(kIORegPlaneParentSuffix) - 1)
57 #define kIORegPlaneChildSuffixLen (sizeof(kIORegPlaneChildSuffix) - 1)
58 #define kIORegPlaneNameSuffixLen (sizeof(kIORegPlaneNameSuffix) - 1)
59 #define kIORegPlaneLocationSuffixLen (sizeof(kIORegPlaneLocationSuffix) - 1)
61 #define KASLR_IOREG_DEBUG 0
63 struct IORegistryEntry::ExpansionData
{
64 IORecursiveLock
* fLock
;
65 uint64_t fRegistryEntryID
;
66 SInt32 fRegistryEntryGenerationCount
;
67 OSObject
**_Atomic fIndexedProperties
;
71 static IORegistryEntry
* gRegistryRoot
;
72 static OSDictionary
* gIORegistryPlanes
;
74 const OSSymbol
* gIONameKey
;
75 const OSSymbol
* gIOLocationKey
;
76 const OSSymbol
* gIORegistryEntryIDKey
;
77 const OSSymbol
* gIORegistryEntryPropertyKeysKey
;
88 enum { kIORegistryIDReserved
= (1ULL << 32) + 255 };
90 static uint64_t gIORegistryLastID
= kIORegistryIDReserved
;
92 class IORegistryPlane
: public OSObject
{
93 friend class IORegistryEntry
;
95 OSDeclareAbstractStructors(IORegistryPlane
);
97 const OSSymbol
* nameKey
;
98 const OSSymbol
* keys
[kNumSetIndex
];
99 const OSSymbol
* pathNameKey
;
100 const OSSymbol
* pathLocationKey
;
104 virtual bool serialize(OSSerialize
*s
) const APPLE_KEXT_OVERRIDE
;
107 OSDefineMetaClassAndStructors(IORegistryPlane
, OSObject
)
110 static IORecursiveLock
* gPropertiesLock
;
111 static SInt32 gIORegistryGenerationCount
;
113 #define UNLOCK lck_rw_done( &gIORegistryLock )
114 #define RLOCK lck_rw_lock_shared( &gIORegistryLock )
115 #define WLOCK lck_rw_lock_exclusive( &gIORegistryLock ); \
116 gIORegistryGenerationCount++
119 #define PUNLOCK IORecursiveLockUnlock( reserved->fLock )
120 #define PLOCK IORecursiveLockLock( reserved->fLock )
122 #define IOREGSPLITTABLES
124 #ifdef IOREGSPLITTABLES
125 #define registryTable() fRegistryTable
127 #define registryTable() fPropertyTable
132 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
134 lck_rw_t gIORegistryLock
;
135 lck_grp_t
*gIORegistryLockGrp
;
136 lck_grp_attr_t
*gIORegistryLockGrpAttr
;
137 lck_attr_t
*gIORegistryLockAttr
;
140 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
143 IORegistryEntry::initialize( void )
147 if (!gRegistryRoot
) {
148 gIORegistryLockGrpAttr
= lck_grp_attr_alloc_init();
149 gIORegistryLockGrp
= lck_grp_alloc_init("IORegistryLock", gIORegistryLockGrpAttr
);
150 gIORegistryLockAttr
= lck_attr_alloc_init();
151 lck_attr_rw_shared_priority(gIORegistryLockAttr
);
152 lck_rw_init( &gIORegistryLock
, gIORegistryLockGrp
, gIORegistryLockAttr
);
154 gRegistryRoot
= new IORegistryEntry
;
155 gPropertiesLock
= IORecursiveLockAlloc();
156 gIORegistryPlanes
= OSDictionary::withCapacity( 1 );
158 assert( gRegistryRoot
&& gPropertiesLock
159 && gIORegistryPlanes
);
160 ok
= gRegistryRoot
->init();
163 gRegistryRoot
->reserved
->fRegistryEntryID
= ++gIORegistryLastID
;
166 gIONameKey
= OSSymbol::withCStringNoCopy( "IOName" );
167 gIOLocationKey
= OSSymbol::withCStringNoCopy( "IOLocation" );
168 gIORegistryEntryIDKey
= OSSymbol::withCStringNoCopy( kIORegistryEntryIDKey
);
169 gIORegistryEntryPropertyKeysKey
= OSSymbol::withCStringNoCopy( kIORegistryEntryPropertyKeysKey
);
171 assert( ok
&& gIONameKey
&& gIOLocationKey
);
173 gRegistryRoot
->setName( "Root" );
174 gRegistryRoot
->setProperty( kIORegistryPlanesKey
, gIORegistryPlanes
);
177 return gRegistryRoot
;
181 IORegistryEntry::getRegistryRoot( void )
183 return gRegistryRoot
;
187 IORegistryEntry::getGenerationCount( void )
189 return gIORegistryGenerationCount
;
193 IORegistryEntry::getRegistryEntryGenerationCount(void) const
195 return reserved
->fRegistryEntryGenerationCount
;
198 const IORegistryPlane
*
199 IORegistryEntry::makePlane( const char * name
)
201 IORegistryPlane
* plane
;
202 const OSSymbol
* nameKey
;
203 const OSSymbol
* parentKey
;
204 const OSSymbol
* childKey
;
205 const OSSymbol
* pathNameKey
;
206 const OSSymbol
* pathLocationKey
;
207 char key
[kIOMaxPlaneName
+ 16];
210 strlcpy( key
, name
, kIOMaxPlaneName
+ 1 );
211 end
= key
+ strlen( key
);
213 nameKey
= OSSymbol::withCString( key
);
215 strlcpy( end
, kIORegPlaneParentSuffix
, kIORegPlaneParentSuffixLen
+ 1 );
216 parentKey
= OSSymbol::withCString( key
);
218 strlcpy( end
, kIORegPlaneChildSuffix
, kIORegPlaneChildSuffixLen
+ 1 );
219 childKey
= OSSymbol::withCString( key
);
221 strlcpy( end
, kIORegPlaneNameSuffix
, kIORegPlaneNameSuffixLen
+ 1 );
222 pathNameKey
= OSSymbol::withCString( key
);
224 strlcpy( end
, kIORegPlaneLocationSuffix
, kIORegPlaneLocationSuffixLen
+ 1 );
225 pathLocationKey
= OSSymbol::withCString( key
);
227 plane
= new IORegistryPlane
;
229 if (plane
&& plane
->init()
230 && nameKey
&& parentKey
&& childKey
231 && pathNameKey
&& pathLocationKey
) {
232 plane
->nameKey
= nameKey
;
233 plane
->keys
[kParentSetIndex
] = parentKey
;
234 plane
->keys
[kChildSetIndex
] = childKey
;
235 plane
->pathNameKey
= pathNameKey
;
236 plane
->pathLocationKey
= pathLocationKey
;
239 gIORegistryPlanes
->setObject( nameKey
, plane
);
245 if (pathLocationKey
) {
246 pathLocationKey
->release();
249 pathNameKey
->release();
252 parentKey
->release();
266 const IORegistryPlane
*
267 IORegistryEntry::getPlane( const char * name
)
269 const IORegistryPlane
* plane
;
272 plane
= (const IORegistryPlane
*) gIORegistryPlanes
->getObject( name
);
279 IORegistryPlane::serialize(OSSerialize
*s
) const
281 return nameKey
->serialize(s
);
284 enum { kIORegCapacityIncrement
= 4 };
287 IORegistryEntry::init( OSDictionary
* dict
)
291 if (!super::init()) {
296 reserved
= IONew(ExpansionData
, 1);
300 bzero(reserved
, sizeof(ExpansionData
));
301 reserved
->fLock
= IORecursiveLockAlloc();
302 if (!reserved
->fLock
) {
307 if (OSCollection::kImmutable
& dict
->setOptions(0, 0)) {
308 dict
= (OSDictionary
*) dict
->copyCollection();
315 if (fPropertyTable
) {
316 fPropertyTable
->release();
318 fPropertyTable
= dict
;
319 } else if (!fPropertyTable
) {
320 fPropertyTable
= OSDictionary::withCapacity( kIORegCapacityIncrement
);
321 if (fPropertyTable
) {
322 fPropertyTable
->setCapacityIncrement( kIORegCapacityIncrement
);
326 if (!fPropertyTable
) {
330 #ifdef IOREGSPLITTABLES
331 if (!fRegistryTable
) {
332 fRegistryTable
= OSDictionary::withCapacity( kIORegCapacityIncrement
);
333 if (fRegistryTable
) {
334 fRegistryTable
->setCapacityIncrement( kIORegCapacityIncrement
);
338 if ((prop
= OSDynamicCast( OSString
, getProperty( gIONameKey
)))) {
339 OSSymbol
* sym
= (OSSymbol
*)OSSymbol::withString( prop
);
340 // ok for OSSymbol too
345 #endif /* IOREGSPLITTABLES */
351 IORegistryEntry::init( IORegistryEntry
* old
,
352 const IORegistryPlane
* plane
)
355 IORegistryEntry
* next
;
358 if (!super::init()) {
363 reserved
= IONew(ExpansionData
, 1);
367 bzero(reserved
, sizeof(ExpansionData
));
368 reserved
->fLock
= IORecursiveLockAlloc();
369 if (!reserved
->fLock
) {
376 reserved
->fRegistryEntryID
= old
->reserved
->fRegistryEntryID
;
378 fPropertyTable
= old
->dictionaryWithProperties();
379 #ifdef IOREGSPLITTABLES
380 fRegistryTable
= old
->fRegistryTable
;
381 old
->fRegistryTable
= (OSDictionary
*) fRegistryTable
->copyCollection();
382 #endif /* IOREGSPLITTABLES */
384 old
->registryTable()->removeObject( plane
->keys
[kParentSetIndex
] );
385 old
->registryTable()->removeObject( plane
->keys
[kChildSetIndex
] );
387 all
= getParentSetReference( plane
);
390 (next
= (IORegistryEntry
*) all
->getObject(index
));
392 next
->makeLink( this, kChildSetIndex
, plane
);
393 next
->breakLink( old
, kChildSetIndex
, plane
);
397 all
= getChildSetReference( plane
);
400 (next
= (IORegistryEntry
*) all
->getObject(index
));
402 next
->makeLink( this, kParentSetIndex
, plane
);
403 next
->breakLink( old
, kParentSetIndex
, plane
);
413 IORegistryEntry::free( void )
416 if (registryTable() && gIOServicePlane
) {
417 if (getParentSetReference( gIOServicePlane
)
418 || getChildSetReference( gIOServicePlane
)) {
419 panic("%s: attached at free()", getName());
424 if (getPropertyTable()) {
425 getPropertyTable()->release();
428 #ifdef IOREGSPLITTABLES
429 if (registryTable()) {
430 registryTable()->release();
432 #endif /* IOREGSPLITTABLES */
435 OSObject
** array
= os_atomic_load(&reserved
->fIndexedProperties
, acquire
);
437 for (int idx
= 0; idx
< kIORegistryEntryIndexedPropertyCount
; idx
++) {
439 array
[idx
]->release();
442 IODelete(array
, OSObject
*, kIORegistryEntryIndexedPropertyCount
);
444 if (reserved
->fLock
) {
445 IORecursiveLockFree(reserved
->fLock
);
447 IODelete(reserved
, ExpansionData
, 1);
454 IORegistryEntry::setPropertyTable( OSDictionary
* dict
)
460 if (fPropertyTable
) {
461 fPropertyTable
->release();
464 fPropertyTable
= dict
;
468 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
470 /* Wrappers to synchronize property table */
472 #define wrap2(type, constant) \
474 IORegistryEntry::copyProperty( type * aKey) constant \
479 obj = getProperty( aKey ); \
487 #define wrap4(type, constant) \
489 IORegistryEntry::getProperty( type * aKey, \
490 const IORegistryPlane * plane, \
491 IOOptionBits options ) constant \
493 OSObject * obj = getProperty( aKey ); \
495 if ( (NULL == obj) && plane && (options & kIORegistryIterateRecursively) ) { \
496 IORegistryEntry * entry = (IORegistryEntry *) this; \
497 IORegistryIterator * iter; \
498 iter = IORegistryIterator::iterateOver( entry, plane, options ); \
501 while ( (NULL == obj) && (entry = iter->getNextObject()) ) { \
502 obj = entry->getProperty( aKey ); \
511 #define wrap5(type, constant) \
513 IORegistryEntry::copyProperty( type * aKey, \
514 const IORegistryPlane * plane, \
515 IOOptionBits options ) constant \
517 OSObject * obj = copyProperty( aKey ); \
519 if ( (NULL == obj) && plane && (options & kIORegistryIterateRecursively) ) { \
520 IORegistryEntry * entry = (IORegistryEntry *) this; \
521 IORegistryIterator * iter; \
522 iter = IORegistryIterator::iterateOver( entry, plane, options ); \
525 while ( (NULL == obj) && (entry = iter->getNextObject()) ) { \
526 obj = entry->copyProperty( aKey ); \
536 IORegistryEntry::serializeProperties( OSSerialize
* s
) const
538 // setProperty( getRetainCount(), 32, "__retain" );
541 OSCollection
*snapshotProperties
= getPropertyTable()->copyCollection();
544 if (!snapshotProperties
) {
548 bool ok
= snapshotProperties
->serialize( s
);
549 snapshotProperties
->release();
554 IORegistryEntry::copyPropertyKeys(void) const
557 OSArray
* keys
= getPropertyTable()->copyKeys();
564 IORegistryEntry::dictionaryWithProperties( void ) const
569 dict
= OSDictionary::withDictionary( getPropertyTable(),
570 getPropertyTable()->getCapacity());
577 IORegistryEntry::setProperties( OSObject
* properties
)
579 return kIOReturnUnsupported
;
582 wrap2(const OSSymbol
, const) // copyProperty() definition
583 wrap2(const OSString
, const) // copyProperty() definition
584 wrap2(const char, const) // copyProperty() definition
586 wrap4(const OSSymbol
, const) // getProperty() w/plane definition
587 wrap4(const OSString
, const) // getProperty() w/plane definition
588 wrap4(const char, const) // getProperty() w/plane definition
590 wrap5(const OSSymbol
, const) // copyProperty() w/plane definition
591 wrap5(const OSString
, const) // copyProperty() w/plane definition
592 wrap5(const char, const) // copyProperty() w/plane definition
596 IORegistryEntry::propertyExists(const OSSymbol
* aKey
)
598 return NULL
!= getProperty(aKey
);
602 IORegistryEntry::propertyExists(const OSString
* aKey
)
604 return NULL
!= getProperty(aKey
);
608 IORegistryEntry::propertyExists(const char * aKey
)
610 return NULL
!= getProperty(aKey
);
615 IORegistryEntry::propertyHasValue(const OSSymbol
* aKey
,
616 const OSObject
* value
)
618 const OSObject
* found
;
621 found
= copyProperty(aKey
);
622 result
= (!found
&& !value
) || (found
&& value
&& value
->isEqualTo(found
));
623 OSSafeReleaseNULL(found
);
628 IORegistryEntry::propertyHasValue(const OSString
* aKey
,
629 const OSObject
* value
)
631 const OSObject
* found
;
634 found
= copyProperty(aKey
);
635 result
= (!found
&& !value
) || (found
&& value
&& value
->isEqualTo(found
));
636 OSSafeReleaseNULL(found
);
641 IORegistryEntry::propertyHasValue(const char * aKey
,
642 const OSObject
* value
)
644 const OSObject
* found
;
647 found
= copyProperty(aKey
);
648 result
= (!found
&& !value
) || (found
&& value
&& value
->isEqualTo(found
));
649 OSSafeReleaseNULL(found
);
655 IORegistryEntry::propertyExists(const OSSymbol
* aKey
,
656 const IORegistryPlane
* plane
,
657 uint32_t options
) const
659 return NULL
!= getProperty(aKey
, plane
, options
);
663 IORegistryEntry::propertyExists(const OSString
* aKey
,
664 const IORegistryPlane
* plane
,
665 uint32_t options
) const
667 return NULL
!= getProperty(aKey
, plane
, options
);
670 IORegistryEntry::propertyExists(const char * aKey
,
671 const IORegistryPlane
* plane
,
672 uint32_t options
) const
674 return NULL
!= getProperty(aKey
, plane
, options
);
679 IORegistryEntry::propertyHasValue(const OSSymbol
* aKey
,
680 const OSObject
* value
,
681 const IORegistryPlane
* plane
,
682 uint32_t options
) const
684 const OSObject
* found
;
687 found
= copyProperty(aKey
, plane
, options
);
688 result
= (!found
&& !value
) || (found
&& value
&& value
->isEqualTo(found
));
689 OSSafeReleaseNULL(found
);
694 IORegistryEntry::propertyHasValue(const OSString
* aKey
,
695 const OSObject
* value
,
696 const IORegistryPlane
* plane
,
697 uint32_t options
) const
699 const OSObject
* found
;
702 found
= copyProperty(aKey
, plane
, options
);
703 result
= (!found
&& !value
) || (found
&& value
&& value
->isEqualTo(found
));
704 OSSafeReleaseNULL(found
);
709 IORegistryEntry::propertyHasValue(const char * aKey
,
710 const OSObject
* value
,
711 const IORegistryPlane
* plane
,
712 uint32_t options
) const
714 const OSObject
* found
;
717 found
= copyProperty(aKey
, plane
, options
);
718 result
= (!found
&& !value
) || (found
&& value
&& value
->isEqualTo(found
));
719 OSSafeReleaseNULL(found
);
725 IORegistryEntry::getProperty( const OSSymbol
* aKey
) const
730 obj
= getPropertyTable()->getObject( aKey
);
737 IORegistryEntry::removeProperty( const OSSymbol
* aKey
)
740 getPropertyTable()->removeObject( aKey
);
744 #if KASLR_IOREG_DEBUG
746 bool ScanForAddrInObject(OSObject
* theObject
,
752 IORegistryEntry::setProperty( const OSSymbol
* aKey
, OSObject
* anObject
)
756 // If we are inserting a collection class and the current entry
757 // is attached into the registry (inPlane()) then mark the collection
759 OSCollection
*coll
= OSDynamicCast(OSCollection
, anObject
);
760 bool makeImmutable
= (coll
&& inPlane());
764 coll
->setOptions( OSCollection::kMASK
, OSCollection::kImmutable
);
767 ret
= getPropertyTable()->setObject( aKey
, anObject
);
770 #if KASLR_IOREG_DEBUG
771 if (anObject
&& strcmp(kIOKitDiagnosticsKey
, aKey
->getCStringNoCopy()) != 0) {
772 if (ScanForAddrInObject(anObject
, 0)) {
773 IOLog("%s: IORegistryEntry name %s with key \"%s\" \n",
776 aKey
->getCStringNoCopy());
786 runPropertyAction(Action inAction
, OSObject
*target
,
787 void *arg0
, void *arg1
, void *arg2
, void *arg3
)
791 // closeGate is recursive so don't worry if we already hold the lock.
793 res
= (*inAction
)(target
, arg0
, arg1
, arg2
, arg3
);
800 IORegistryEntryActionToBlock(OSObject
*target
,
801 void *arg0
, void *arg1
,
802 void *arg2
, void *arg3
)
804 IORegistryEntry::ActionBlock block
= (typeof(block
))arg0
;
809 IORegistryEntry::runPropertyActionBlock(ActionBlock block
)
813 res
= runPropertyAction(&IORegistryEntryActionToBlock
, this, block
);
819 IORegistryEntry::getProperty( const OSString
* aKey
) const
821 const OSSymbol
* tmpKey
= OSSymbol::withString( aKey
);
822 OSObject
* obj
= getProperty( tmpKey
);
829 IORegistryEntry::getProperty( const char * aKey
) const
831 const OSSymbol
* tmpKey
= OSSymbol::withCString( aKey
);
832 OSObject
* obj
= getProperty( tmpKey
);
840 IORegistryEntry::removeProperty( const OSString
* aKey
)
842 const OSSymbol
* tmpKey
= OSSymbol::withString( aKey
);
843 removeProperty( tmpKey
);
848 IORegistryEntry::removeProperty( const char * aKey
)
850 const OSSymbol
* tmpKey
= OSSymbol::withCString( aKey
);
851 removeProperty( tmpKey
);
856 IORegistryEntry::setProperty( const OSString
* aKey
, OSObject
* anObject
)
858 const OSSymbol
* tmpKey
= OSSymbol::withString( aKey
);
859 bool ret
= setProperty( tmpKey
, anObject
);
866 IORegistryEntry::setProperty( const char * aKey
, OSObject
* anObject
)
868 const OSSymbol
* tmpKey
= OSSymbol::withCString( aKey
);
869 bool ret
= setProperty( tmpKey
, anObject
);
876 IORegistryEntry::setProperty(const char * aKey
, const char * aString
)
879 OSSymbol
* aSymbol
= (OSSymbol
*) OSSymbol::withCString( aString
);
882 const OSSymbol
* tmpKey
= OSSymbol::withCString( aKey
);
883 ret
= setProperty( tmpKey
, aSymbol
);
892 IORegistryEntry::setProperty(const char * aKey
, bool aBoolean
)
895 OSBoolean
* aBooleanObj
= OSBoolean::withBoolean( aBoolean
);
898 const OSSymbol
* tmpKey
= OSSymbol::withCString( aKey
);
899 ret
= setProperty( tmpKey
, aBooleanObj
);
902 aBooleanObj
->release();
908 IORegistryEntry::setProperty( const char * aKey
,
909 unsigned long long aValue
,
910 unsigned int aNumberOfBits
)
913 OSNumber
* anOffset
= OSNumber::withNumber( aValue
, aNumberOfBits
);
916 const OSSymbol
* tmpKey
= OSSymbol::withCString( aKey
);
917 ret
= setProperty( tmpKey
, anOffset
);
926 IORegistryEntry::setProperty( const char * aKey
,
931 OSData
* data
= OSData::withBytes( bytes
, length
);
934 const OSSymbol
* tmpKey
= OSSymbol::withCString( aKey
);
935 ret
= setProperty( tmpKey
, data
);
943 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
946 IORegistryEntry::setIndexedProperty(uint32_t index
, OSObject
* anObject
)
951 if (index
>= kIORegistryEntryIndexedPropertyCount
) {
955 array
= os_atomic_load(&reserved
->fIndexedProperties
, acquire
);
957 array
= IONew(OSObject
*, kIORegistryEntryIndexedPropertyCount
);
961 bzero(array
, kIORegistryEntryIndexedPropertyCount
* sizeof(array
[0]));
962 if (!os_atomic_cmpxchg(&reserved
->fIndexedProperties
, NULL
, array
, release
)) {
963 IODelete(array
, OSObject
*, kIORegistryEntryIndexedPropertyCount
);
964 array
= os_atomic_load(&reserved
->fIndexedProperties
, acquire
);
972 prior
= array
[index
];
976 array
[index
] = anObject
;
982 IORegistryEntry::getIndexedProperty(uint32_t index
) const
984 if (index
>= kIORegistryEntryIndexedPropertyCount
) {
988 OSObject
** array
= os_atomic_load(&reserved
->fIndexedProperties
, acquire
);
996 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
998 /* Name, location, paths */
1001 IORegistryEntry::getName( const IORegistryPlane
* plane
) const
1003 OSSymbol
* sym
= NULL
;
1007 sym
= (OSSymbol
*) registryTable()->getObject( plane
->pathNameKey
);
1010 sym
= (OSSymbol
*) registryTable()->getObject( gIONameKey
);
1015 return sym
->getCStringNoCopy();
1017 return (getMetaClass())->getClassName();
1022 IORegistryEntry::copyName(
1023 const IORegistryPlane
* plane
) const
1025 OSSymbol
* sym
= NULL
;
1029 sym
= (OSSymbol
*) registryTable()->getObject( plane
->pathNameKey
);
1032 sym
= (OSSymbol
*) registryTable()->getObject( gIONameKey
);
1042 return OSSymbol::withCString((getMetaClass())->getClassName());
1047 IORegistryEntry::copyLocation(
1048 const IORegistryPlane
* plane
) const
1050 OSSymbol
* sym
= NULL
;
1054 sym
= (OSSymbol
*) registryTable()->getObject( plane
->pathLocationKey
);
1057 sym
= (OSSymbol
*) registryTable()->getObject( gIOLocationKey
);
1068 IORegistryEntry::getLocation( const IORegistryPlane
* plane
) const
1070 const OSSymbol
* sym
= copyLocation( plane
);
1071 const char * result
= NULL
;
1074 result
= sym
->getCStringNoCopy();
1082 IORegistryEntry::setName( const OSSymbol
* name
,
1083 const IORegistryPlane
* plane
)
1085 const OSSymbol
* key
;
1089 key
= plane
->pathNameKey
;
1094 if (gIOKitTrace
&& reserved
&& reserved
->fRegistryEntryID
) {
1095 uint64_t str_id
= 0;
1096 uint64_t __unused regID
= getRegistryEntryID();
1097 kernel_debug_string(IODBG_IOREGISTRY(IOREGISTRYENTRY_NAME_STRING
), &str_id
, name
->getCStringNoCopy());
1098 KERNEL_DEBUG_CONSTANT(IODBG_IOREGISTRY(IOREGISTRYENTRY_NAME
),
1100 (uintptr_t) (regID
>> 32),
1102 (uintptr_t) (str_id
>> 32),
1107 registryTable()->setObject( key
, (OSObject
*) name
);
1113 IORegistryEntry::setName( const char * name
,
1114 const IORegistryPlane
* plane
)
1116 OSSymbol
* sym
= (OSSymbol
*)OSSymbol::withCString( name
);
1118 setName( sym
, plane
);
1124 IORegistryEntry::setName( const OSString
* name
,
1125 const IORegistryPlane
* plane
)
1127 const OSSymbol
* sym
= OSSymbol::withString( name
);
1129 setName( sym
, plane
);
1135 IORegistryEntry::setLocation( const OSSymbol
* location
,
1136 const IORegistryPlane
* plane
)
1138 const OSSymbol
* key
;
1142 key
= plane
->pathLocationKey
;
1144 key
= gIOLocationKey
;
1148 registryTable()->setObject( key
, (OSObject
*) location
);
1154 IORegistryEntry::setLocation( const char * location
,
1155 const IORegistryPlane
* plane
)
1157 OSSymbol
* sym
= (OSSymbol
*)OSSymbol::withCString( location
);
1159 setLocation( sym
, plane
);
1166 IORegistryEntry::compareName( OSString
* name
, OSString
** matched
) const
1168 const OSSymbol
* sym
= copyName();
1171 isEqual
= (sym
&& sym
->isEqualTo(name
));
1173 if (isEqual
&& matched
) {
1186 IORegistryEntry::compareNames( OSObject
* names
, OSString
** matched
) const
1189 OSCollection
* collection
;
1190 OSIterator
* iter
= NULL
;
1191 bool result
= false;
1193 if ((collection
= OSDynamicCast( OSCollection
, names
))) {
1194 iter
= OSCollectionIterator::withCollection( collection
);
1197 string
= OSDynamicCast( OSString
, names
);
1202 result
= compareName( string
, matched
);
1204 } while ((false == result
)
1205 && iter
&& (string
= OSDynamicCast( OSString
, iter
->getNextObject())));
1215 IORegistryEntry::compareName( OSString
* name
, OSSharedPtr
<OSString
>& matched
) const
1217 OSString
* matchedRaw
= NULL
;
1218 bool result
= compareName(name
, &matchedRaw
);
1219 matched
.reset(matchedRaw
, OSNoRetain
);
1224 IORegistryEntry::compareNames( OSObject
* names
, OSSharedPtr
<OSString
>& matched
) const
1226 OSString
* matchedRaw
= NULL
;
1227 bool result
= compareNames(names
, &matchedRaw
);
1228 matched
.reset(matchedRaw
, OSNoRetain
);
1233 IORegistryEntry::getPath( char * path
, int * length
,
1234 const IORegistryPlane
* plane
) const
1237 IORegistryEntry
* root
;
1238 const IORegistryEntry
* entry
;
1239 const IORegistryEntry
* parent
;
1240 const OSSymbol
* alias
;
1242 int len
, maxLength
, compLen
, aliasLen
;
1246 if (!path
|| !length
|| !plane
) {
1251 maxLength
= *length
- 2;
1254 len
= plane
->nameKey
->getLength();
1255 if (len
>= maxLength
) {
1258 strlcpy( nextComp
, plane
->nameKey
->getCStringNoCopy(), len
+ 1);
1259 nextComp
[len
++] = ':';
1262 if ((alias
= hasAlias( plane
))) {
1263 aliasLen
= alias
->getLength();
1265 ok
= (maxLength
> len
);
1268 strlcpy( nextComp
, alias
->getCStringNoCopy(), aliasLen
+ 1);
1273 stack
= OSArray::withCapacity( getDepth( plane
));
1280 parent
= entry
= this;
1281 root
= gRegistryRoot
->getChildEntry( plane
);
1282 while (parent
&& (parent
!= root
)) {
1285 parent
= entry
->getParentEntry( plane
);
1286 stack
->setObject((OSObject
*) entry
);
1289 ok
= (NULL
!= parent
);
1291 index
= stack
->getCount();
1297 while (ok
&& ((--index
) >= 0)) {
1298 entry
= (IORegistryEntry
*) stack
->getObject((unsigned int) index
);
1301 if ((alias
= entry
->hasAlias( plane
))) {
1302 len
= plane
->nameKey
->getLength() + 1;
1303 nextComp
= path
+ len
;
1305 compLen
= alias
->getLength();
1306 ok
= (maxLength
> (len
+ compLen
));
1308 strlcpy( nextComp
, alias
->getCStringNoCopy(), compLen
+ 1);
1311 compLen
= maxLength
- len
;
1312 ok
= entry
->getPathComponent( nextComp
+ 1, &compLen
, plane
);
1314 if (ok
&& compLen
) {
1322 nextComp
+= compLen
;
1335 IORegistryEntry::getPathComponent( char * path
, int * length
,
1336 const IORegistryPlane
* plane
) const
1338 int len
, locLen
, maxLength
;
1339 const char * compName
;
1343 maxLength
= *length
;
1345 compName
= getName( plane
);
1346 len
= (int) strnlen( compName
, sizeof(io_name_t
));
1347 if ((loc
= getLocation( plane
))) {
1348 locLen
= 1 + ((int) strnlen( loc
, sizeof(io_name_t
)));
1353 ok
= ((len
+ locLen
+ 1) < maxLength
);
1355 strlcpy( path
, compName
, len
+ 1 );
1360 strlcpy( path
, loc
, locLen
);
1369 IORegistryEntry::matchPathLocation( const char * cmp
,
1370 const IORegistryPlane
* plane
)
1373 const char * result
= NULL
;
1374 u_quad_t num1
, num2
;
1375 char lastPathChar
, lastLocationChar
;
1377 str
= getLocation( plane
);
1379 lastPathChar
= cmp
[0];
1380 lastLocationChar
= str
[0];
1383 num1
= strtouq( cmp
, (char **) &cmp
, 16 );
1384 lastPathChar
= *cmp
++;
1389 if (lastLocationChar
) {
1390 num2
= strtouq( str
, (char **) &str
, 16 );
1391 lastLocationChar
= *str
++;
1400 if (!lastPathChar
&& !lastLocationChar
) {
1405 if ((',' != lastPathChar
) && (':' != lastPathChar
)) {
1409 if (lastPathChar
&& lastLocationChar
&& (lastPathChar
!= lastLocationChar
)) {
1419 IORegistryEntry::getChildFromComponent( const char ** opath
,
1420 const IORegistryPlane
* plane
)
1422 IORegistryEntry
* entry
= NULL
;
1426 const char * cmp
= NULL
;
1431 set
= getChildSetReference( plane
);
1436 (entry
= (IORegistryEntry
*) set
->getObject(index
));
1441 str
= entry
->getName( plane
);
1442 len
= strlen( str
);
1443 if (strncmp( str
, cmp
, len
)) {
1449 if ((c
== 0) || (c
== '/') || (c
== ':')) {
1457 if ((cmp
= entry
->matchPathLocation( cmp
, plane
))) {
1470 IORegistryEntry::hasAlias( const IORegistryPlane
* plane
,
1471 char * opath
, int * length
) const
1473 IORegistryEntry
* entry
;
1474 IORegistryEntry
* entry2
;
1475 const OSSymbol
* key
;
1476 const OSSymbol
* bestKey
= NULL
;
1479 const char * path
= "/aliases";
1481 entry
= IORegistryEntry::fromPath( path
, plane
);
1484 if ((iter
= OSCollectionIterator::withCollection(
1485 entry
->getPropertyTable()))) {
1486 while ((key
= (OSSymbol
*) iter
->getNextObject())) {
1487 data
= (OSData
*) entry
->getProperty( key
);
1488 path
= (const char *) data
->getBytesNoCopy();
1489 if ((entry2
= IORegistryEntry::fromPath( path
, plane
,
1491 if (this == entry2
) {
1493 || (bestKey
->getLength() > key
->getLength())) {
1494 // pick the smallest alias
1510 IORegistryEntry::dealiasPath(
1511 const char ** opath
,
1512 const IORegistryPlane
* plane
)
1514 IORegistryEntry
* entry
;
1516 const char * path
= *opath
;
1517 const char * rpath
= NULL
;
1520 char temp
[kIOMaxPlaneName
+ 1];
1522 if (path
[0] == '/') {
1528 while ((c
= *end
++) && (c
!= '/') && (c
!= ':')) {
1531 if ((end
- path
) < kIOMaxPlaneName
) {
1532 strlcpy( temp
, path
, end
- path
+ 1 );
1535 entry
= IORegistryEntry::fromPath( "/aliases", plane
);
1537 data
= (OSData
*) entry
->getProperty( temp
);
1539 rpath
= (const char *) data
->getBytesNoCopy();
1553 IORegistryEntry::fromPath(
1555 const IORegistryPlane
* plane
,
1558 IORegistryEntry
* fromEntry
)
1560 IORegistryEntry
* where
= NULL
;
1561 IORegistryEntry
* aliasEntry
= NULL
;
1562 IORegistryEntry
* next
;
1568 char temp
[kIOMaxPlaneName
+ 1];
1574 if (NULL
== plane
) {
1576 end
= strchr( path
, ':' );
1577 if (end
&& ((end
- path
) < kIOMaxPlaneName
)) {
1578 strlcpy( temp
, path
, end
- path
+ 1 );
1579 plane
= getPlane( temp
);
1583 if (NULL
== plane
) {
1589 if ((alias
= dealiasPath( &end
, plane
))) {
1593 aliasEntry
= IORegistryEntry::fromPath( alias
, plane
,
1594 opath
, &len
, fromEntry
);
1606 if (NULL
== where
) {
1607 if ((NULL
== fromEntry
) && (*path
++ == '/')) {
1608 fromEntry
= gRegistryRoot
->getChildEntry( plane
);
1611 if (NULL
== where
) {
1617 if (c
&& (c
!= ':')) { // check valid terminator
1623 next
= where
->getChildFromComponent( &path
, plane
);
1630 // check residual path
1631 if (where
!= fromEntry
) {
1635 if (opath
&& length
) {
1636 // copy out residual path
1637 len2
= (int) strnlen(path
, 65536);
1638 if ((len
+ len2
) < *length
) {
1639 strlcpy( opath
+ len
, path
, len2
+ 1 );
1641 *length
= (len
+ len2
);
1642 } else if (path
[0]) {
1643 // no residual path => must be no tail for success
1652 aliasEntry
->release();
1661 IORegistryEntry::childFromPath(
1663 const IORegistryPlane
* plane
,
1667 return IORegistryEntry::fromPath( path
, plane
, opath
, len
, this );
1670 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1672 #define IOLinkIterator OSCollectionIterator
1675 #define super OSObject
1678 IORegistryEntry::arrayMember( OSArray
* set
,
1679 const IORegistryEntry
* member
,
1680 unsigned int * index
) const
1683 OSObject
* probeObject
;
1685 for (i
= 0; (probeObject
= set
->getObject(i
)); i
++) {
1686 if (probeObject
== (OSObject
*) member
) {
1697 IORegistryEntry::makeLink( IORegistryEntry
* to
,
1698 unsigned int relation
,
1699 const IORegistryPlane
* plane
) const
1702 bool result
= false;
1704 if ((links
= (OSArray
*)
1705 registryTable()->getObject( plane
->keys
[relation
] ))) {
1706 result
= arrayMember( links
, to
);
1708 result
= links
->setObject( to
);
1711 links
= OSArray::withObjects((const OSObject
**) &to
, 1, 1 );
1712 result
= (links
!= NULL
);
1714 result
= registryTable()->setObject( plane
->keys
[relation
],
1719 reserved
->fRegistryEntryGenerationCount
++;
1725 IORegistryEntry::breakLink( IORegistryEntry
* to
,
1726 unsigned int relation
,
1727 const IORegistryPlane
* plane
) const
1732 if ((links
= (OSArray
*)
1733 registryTable()->getObject( plane
->keys
[relation
]))) {
1734 if (arrayMember( links
, to
, &index
)) {
1735 links
->removeObject( index
);
1736 if (0 == links
->getCount()) {
1737 registryTable()->removeObject( plane
->keys
[relation
]);
1741 reserved
->fRegistryEntryGenerationCount
++;
1746 IORegistryEntry::getParentSetReference(
1747 const IORegistryPlane
* plane
) const
1750 return (OSArray
*) registryTable()->getObject(
1751 plane
->keys
[kParentSetIndex
]);
1758 IORegistryEntry::getParentIterator(
1759 const IORegistryPlane
* plane
) const
1769 links
= getParentSetReference( plane
);
1770 if (NULL
== links
) {
1771 links
= OSArray::withCapacity( 1 );
1773 links
= OSArray::withArray( links
, links
->getCount());
1777 iter
= IOLinkIterator::withCollection( links
);
1787 IORegistryEntry::copyParentEntry( const IORegistryPlane
* plane
) const
1789 IORegistryEntry
* entry
= NULL
;
1794 if ((links
= getParentSetReference( plane
))) {
1795 entry
= (IORegistryEntry
*) links
->getObject( 0 );
1805 IORegistryEntry::getParentEntry( const IORegistryPlane
* plane
) const
1807 IORegistryEntry
* entry
;
1809 entry
= copyParentEntry( plane
);
1818 IORegistryEntry::getChildSetReference( const IORegistryPlane
* plane
) const
1821 return (OSArray
*) registryTable()->getObject(
1822 plane
->keys
[kChildSetIndex
]);
1829 IORegistryEntry::getChildIterator( const IORegistryPlane
* plane
) const
1839 links
= getChildSetReference( plane
);
1840 if (NULL
== links
) {
1841 links
= OSArray::withCapacity( 1 );
1843 links
= OSArray::withArray( links
, links
->getCount());
1847 iter
= IOLinkIterator::withCollection( links
);
1857 IORegistryEntry::getChildCount( const IORegistryPlane
* plane
) const
1863 links
= getChildSetReference( plane
);
1865 count
= links
->getCount();
1873 IORegistryEntry::copyChildEntry(
1874 const IORegistryPlane
* plane
) const
1876 IORegistryEntry
* entry
= NULL
;
1881 if ((links
= getChildSetReference( plane
))) {
1882 entry
= (IORegistryEntry
*) links
->getObject( 0 );
1891 // FIXME: Implementation of this function is hidden from the static analyzer.
1892 // The analyzer is worried that this release might as well be the last release.
1893 // Feel free to remove the #ifndef and address the warning!
1894 // See also rdar://problem/63023165.
1895 #ifndef __clang_analyzer__
1897 IORegistryEntry::getChildEntry(
1898 const IORegistryPlane
* plane
) const
1900 IORegistryEntry
* entry
;
1902 entry
= copyChildEntry( plane
);
1909 #endif // __clang_analyzer__
1912 IORegistryEntry::applyToChildren( IORegistryEntryApplierFunction applier
,
1914 const IORegistryPlane
* plane
) const
1918 IORegistryEntry
* next
;
1925 array
= OSArray::withArray( getChildSetReference( plane
));
1929 (next
= (IORegistryEntry
*) array
->getObject( index
));
1931 (*applier
)(next
, context
);
1938 IORegistryEntry::applyToParents( IORegistryEntryApplierFunction applier
,
1940 const IORegistryPlane
* plane
) const
1944 IORegistryEntry
* next
;
1951 array
= OSArray::withArray( getParentSetReference( plane
));
1955 (next
= (IORegistryEntry
*) array
->getObject( index
));
1957 (*applier
)(next
, context
);
1964 IORegistryEntry::isChild( IORegistryEntry
* child
,
1965 const IORegistryPlane
* plane
,
1966 bool onlyChild
) const
1973 if ((links
= getChildSetReference( plane
))) {
1974 if ((!onlyChild
) || (1 == links
->getCount())) {
1975 ret
= arrayMember( links
, child
);
1978 if (ret
&& (links
= child
->getParentSetReference( plane
))) {
1979 ret
= arrayMember( links
, this );
1988 IORegistryEntry::isParent( IORegistryEntry
* parent
,
1989 const IORegistryPlane
* plane
,
1990 bool onlyParent
) const
1997 if ((links
= getParentSetReference( plane
))) {
1998 if ((!onlyParent
) || (1 == links
->getCount())) {
1999 ret
= arrayMember( links
, parent
);
2002 if (ret
&& (links
= parent
->getChildSetReference( plane
))) {
2003 ret
= arrayMember( links
, this );
2012 IORegistryEntry::inPlane( const IORegistryPlane
* plane
) const
2019 ret
= (NULL
!= getParentSetReference( plane
));
2021 // Check to see if this is in any plane. If it is in a plane
2022 // then the registryTable will contain a key with the ParentLinks
2023 // suffix. When we iterate over the keys looking for that suffix
2026 OSCollectionIterator
*iter
=
2027 OSCollectionIterator::withCollection( registryTable());
2029 const OSSymbol
*key
;
2031 while ((key
= (OSSymbol
*) iter
->getNextObject())) {
2034 // Get a pointer to this keys suffix
2035 keysuffix
= key
->getLength();
2036 if (keysuffix
<= kIORegPlaneParentSuffixLen
) {
2039 keysuffix
-= kIORegPlaneParentSuffixLen
;
2040 if (!strncmp(key
->getCStringNoCopy() + keysuffix
,
2041 kIORegPlaneParentSuffix
,
2042 kIORegPlaneParentSuffixLen
+ 1)) {
2057 IORegistryEntry::attachToParent( IORegistryEntry
* parent
,
2058 const IORegistryPlane
* plane
)
2063 bool traceName
= false;
2065 if (this == parent
) {
2071 if (!reserved
->fRegistryEntryID
) {
2072 reserved
->fRegistryEntryID
= ++gIORegistryLastID
;
2073 traceName
= (0 != gIOKitTrace
);
2076 ret
= makeLink( parent
, kParentSetIndex
, plane
);
2078 if ((links
= parent
->getChildSetReference( plane
))) {
2079 needParent
= (false == arrayMember( links
, this ));
2087 uint64_t str_id
= 0;
2088 uint64_t __unused regID
= getRegistryEntryID();
2089 kernel_debug_string(IODBG_IOREGISTRY(IOREGISTRYENTRY_NAME_STRING
), &str_id
, getName());
2090 KERNEL_DEBUG_CONSTANT(IODBG_IOREGISTRY(IOREGISTRYENTRY_NAME
),
2092 (uintptr_t) (regID
>> 32),
2094 (uintptr_t) (str_id
>> 32),
2100 // Mark any collections in the property list as immutable
2101 OSDictionary
*ptable
= getPropertyTable();
2102 OSCollectionIterator
*iter
=
2103 OSCollectionIterator::withCollection( ptable
);
2105 const OSSymbol
*key
;
2107 while ((key
= (OSSymbol
*) iter
->getNextObject())) {
2108 // Is object for key a collection?
2109 OSCollection
*coll
=
2110 OSDynamicCast( OSCollection
, ptable
->getObject( key
));
2113 // Yup so mark it as immutable
2114 coll
->setOptions( OSCollection::kMASK
,
2115 OSCollection::kImmutable
);
2124 ret
&= parent
->attachToChild( this, plane
);
2131 IORegistryEntry::getRegistryEntryID( void )
2134 return reserved
->fRegistryEntryID
;
2141 IORegistryEntry::attachToChild( IORegistryEntry
* child
,
2142 const IORegistryPlane
* plane
)
2148 if (this == child
) {
2154 ret
= makeLink( child
, kChildSetIndex
, plane
);
2156 if ((links
= child
->getParentSetReference( plane
))) {
2157 needChild
= (false == arrayMember( links
, this ));
2165 ret
&= child
->attachToParent( this, plane
);
2172 IORegistryEntry::detachFromParent( IORegistryEntry
* parent
,
2173 const IORegistryPlane
* plane
)
2182 breakLink( parent
, kParentSetIndex
, plane
);
2184 if ((links
= parent
->getChildSetReference( plane
))) {
2185 needParent
= arrayMember( links
, this );
2190 // parent->breakLink( this, kChildSetIndex, plane );
2195 parent
->detachFromChild( this, plane
);
2202 IORegistryEntry::detachFromChild( IORegistryEntry
* child
,
2203 const IORegistryPlane
* plane
)
2212 breakLink( child
, kChildSetIndex
, plane
);
2214 if ((links
= child
->getParentSetReference( plane
))) {
2215 needChild
= arrayMember( links
, this );
2223 child
->detachFromParent( this, plane
);
2230 IORegistryEntry::detachAbove( const IORegistryPlane
* plane
)
2232 IORegistryEntry
* parent
;
2235 while ((parent
= copyParentEntry( plane
))) {
2236 detachFromParent( parent
, plane
);
2243 IORegistryEntry::detachAll( const IORegistryPlane
* plane
)
2246 IORegistryEntry
* next
;
2247 IORegistryIterator
* regIter
;
2249 regIter
= IORegistryIterator::iterateOver( this, plane
, true );
2250 if (NULL
== regIter
) {
2253 all
= regIter
->iterateAll();
2256 detachAbove( plane
);
2258 while ((next
= (IORegistryEntry
*) all
->getLastObject())) {
2260 all
->removeObject(next
);
2262 next
->detachAbove( plane
);
2270 IORegistryEntry::getDepth( const IORegistryPlane
* plane
) const
2272 unsigned int depth
= 1;
2274 unsigned int oneDepth
, maxParentDepth
, count
;
2275 IORegistryEntry
* one
;
2276 const IORegistryEntry
* next
;
2282 while ((parents
= next
->getParentSetReference( plane
))) {
2283 count
= parents
->getCount();
2289 next
= (IORegistryEntry
*) parents
->getObject( 0 );
2294 (one
= (IORegistryEntry
*) parents
->getObject( index
));
2296 oneDepth
= one
->getDepth( plane
);
2297 if (oneDepth
> maxParentDepth
) {
2298 maxParentDepth
= oneDepth
;
2301 depth
+= maxParentDepth
;
2311 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2314 #define super OSIterator
2316 OSDefineMetaClassAndStructors(IORegistryIterator
, OSIterator
)
2318 enum { kIORegistryIteratorInvalidFlag
= 0x80000000 };
2320 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2322 IORegistryIterator
*
2323 IORegistryIterator::iterateOver( IORegistryEntry
* root
,
2324 const IORegistryPlane
* plane
,
2325 IOOptionBits options
)
2327 IORegistryIterator
* create
;
2332 if (NULL
== plane
) {
2336 create
= new IORegistryIterator
;
2338 if (create
->init()) {
2340 create
->root
= root
;
2341 create
->where
= &create
->start
;
2342 create
->start
.current
= root
;
2343 create
->plane
= plane
;
2344 create
->options
= options
& ~kIORegistryIteratorInvalidFlag
;
2353 IORegistryIterator
*
2354 IORegistryIterator::iterateOver( const IORegistryPlane
* plane
,
2355 IOOptionBits options
)
2357 return iterateOver( gRegistryRoot
, plane
, options
);
2361 IORegistryIterator::isValid( void )
2370 ok
= (0 == (kIORegistryIteratorInvalidFlag
& options
));
2372 while (ok
&& next
) {
2374 ok
= where
->iter
->isValid();
2384 IORegistryIterator::enterEntry( const IORegistryPlane
* enterPlane
)
2389 where
= (IORegCursor
*) IOMalloc( sizeof(IORegCursor
));
2395 where
->current
= prev
->current
;
2401 IORegistryIterator::enterEntry( void )
2403 enterEntry( plane
);
2407 IORegistryIterator::exitEntry( void )
2412 where
->iter
->release();
2414 if (where
->current
) {// && (where != &start))
2415 where
->current
->release();
2419 if (where
!= &start
) {
2422 IOFree( gone
, sizeof(IORegCursor
));
2430 IORegistryIterator::reset( void )
2432 while (exitEntry()) {
2440 where
->current
= root
;
2441 options
&= ~kIORegistryIteratorInvalidFlag
;
2445 IORegistryIterator::free( void )
2458 IORegistryIterator::getNextObjectFlat( void )
2460 IORegistryEntry
* next
= NULL
;
2461 OSArray
* links
= NULL
;
2465 if ((NULL
== where
->iter
)) {
2466 // just entered - create new iter
2469 && (links
= ((options
& kIORegistryIterateParents
) ?
2470 where
->current
->getParentSetReference( plane
) :
2471 where
->current
->getChildSetReference( plane
)))) {
2472 where
->iter
= OSCollectionIterator::withCollection( links
);
2475 // next sibling - release current
2476 if (where
->current
) {
2477 where
->current
->release();
2481 next
= (IORegistryEntry
*) where
->iter
->getNextObject();
2485 } else if (!where
->iter
->isValid()) {
2486 options
|= kIORegistryIteratorInvalidFlag
;
2490 where
->current
= next
;
2498 IORegistryIterator::getNextObjectRecursive( void )
2500 IORegistryEntry
* next
;
2503 next
= getNextObjectFlat();
2504 } while ((NULL
== next
) && exitEntry());
2508 done
= OSOrderedSet::withCapacity( 10 );
2510 if (done
->setObject((OSObject
*) next
)) {
2511 // done set didn't contain this one, so recurse
2519 IORegistryIterator::getNextObject( void )
2521 if (options
& kIORegistryIterateRecursively
) {
2522 return getNextObjectRecursive();
2524 return getNextObjectFlat();
2529 IORegistryIterator::getCurrentEntry( void )
2532 return where
->current
;
2539 IORegistryIterator::iterateAll( void )
2542 while (getNextObjectRecursive()) {
2551 OSMetaClassDefineReservedUnused(IORegistryEntry
, 0);
2552 OSMetaClassDefineReservedUnused(IORegistryEntry
, 1);
2553 OSMetaClassDefineReservedUnused(IORegistryEntry
, 2);
2554 OSMetaClassDefineReservedUnused(IORegistryEntry
, 3);
2555 OSMetaClassDefineReservedUnused(IORegistryEntry
, 4);
2556 OSMetaClassDefineReservedUnused(IORegistryEntry
, 5);
2558 OSMetaClassDefineReservedUsedX86(IORegistryEntry
, 0);
2559 OSMetaClassDefineReservedUsedX86(IORegistryEntry
, 1);
2560 OSMetaClassDefineReservedUsedX86(IORegistryEntry
, 2);
2561 OSMetaClassDefineReservedUsedX86(IORegistryEntry
, 3);
2562 OSMetaClassDefineReservedUsedX86(IORegistryEntry
, 4);
2563 OSMetaClassDefineReservedUsedX86(IORegistryEntry
, 5);
2565 OSMetaClassDefineReservedUnused(IORegistryEntry
, 6);
2566 OSMetaClassDefineReservedUnused(IORegistryEntry
, 7);
2567 OSMetaClassDefineReservedUnused(IORegistryEntry
, 8);
2568 OSMetaClassDefineReservedUnused(IORegistryEntry
, 9);
2569 OSMetaClassDefineReservedUnused(IORegistryEntry
, 10);
2570 OSMetaClassDefineReservedUnused(IORegistryEntry
, 11);
2571 OSMetaClassDefineReservedUnused(IORegistryEntry
, 12);
2572 OSMetaClassDefineReservedUnused(IORegistryEntry
, 13);
2573 OSMetaClassDefineReservedUnused(IORegistryEntry
, 14);
2574 OSMetaClassDefineReservedUnused(IORegistryEntry
, 15);
2575 OSMetaClassDefineReservedUnused(IORegistryEntry
, 16);
2576 OSMetaClassDefineReservedUnused(IORegistryEntry
, 17);
2577 OSMetaClassDefineReservedUnused(IORegistryEntry
, 18);
2578 OSMetaClassDefineReservedUnused(IORegistryEntry
, 19);
2579 OSMetaClassDefineReservedUnused(IORegistryEntry
, 20);
2580 OSMetaClassDefineReservedUnused(IORegistryEntry
, 21);
2581 OSMetaClassDefineReservedUnused(IORegistryEntry
, 22);
2582 OSMetaClassDefineReservedUnused(IORegistryEntry
, 23);
2583 OSMetaClassDefineReservedUnused(IORegistryEntry
, 24);
2584 OSMetaClassDefineReservedUnused(IORegistryEntry
, 25);
2585 OSMetaClassDefineReservedUnused(IORegistryEntry
, 26);
2586 OSMetaClassDefineReservedUnused(IORegistryEntry
, 27);
2587 OSMetaClassDefineReservedUnused(IORegistryEntry
, 28);
2588 OSMetaClassDefineReservedUnused(IORegistryEntry
, 29);
2589 OSMetaClassDefineReservedUnused(IORegistryEntry
, 30);
2590 OSMetaClassDefineReservedUnused(IORegistryEntry
, 31);
2592 /* inline function implementation */
2594 IORegistryEntry::getPropertyTable( void ) const
2596 return fPropertyTable
;