1/*
2 * Copyright (c) 1998-2006 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5 *
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.
14 *
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
17 *
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.
25 *
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27 */
28
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
35#include <IOKit/IOLib.h>
36#include <stdatomic.h>
37#include <IOKit/assert.h>
38
39#include "IOKitKernelInternal.h"
40
41/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
42
43#define super OSObject
44
45OSDefineMetaClassAndStructors(IORegistryEntry, OSObject)
46
47/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
48
49#define kIORegPlaneParentSuffix "ParentLinks"
50#define kIORegPlaneChildSuffix "ChildLinks"
51#define kIORegPlaneNameSuffix "Name"
52#define kIORegPlaneLocationSuffix "Location"
53
54#define kIORegPlaneParentSuffixLen (sizeof(kIORegPlaneParentSuffix) - 1)
55#define kIORegPlaneChildSuffixLen (sizeof(kIORegPlaneChildSuffix) - 1)
56#define kIORegPlaneNameSuffixLen (sizeof(kIORegPlaneNameSuffix) - 1)
57#define kIORegPlaneLocationSuffixLen (sizeof(kIORegPlaneLocationSuffix) - 1)
58
59#define KASLR_IOREG_DEBUG 0
60
61struct IORegistryEntry::ExpansionData
62{
63 IORecursiveLock * fLock;
64 uint64_t fRegistryEntryID;
65 SInt32 fRegistryEntryGenerationCount;
66 OSObject **_Atomic fIndexedProperties;
67};
68
69
70static IORegistryEntry * gRegistryRoot;
71static OSDictionary * gIORegistryPlanes;
72
73const OSSymbol * gIONameKey;
74const OSSymbol * gIOLocationKey;
75const OSSymbol * gIORegistryEntryIDKey;
76const OSSymbol * gIORegistryEntryPropertyKeysKey;
77
78enum {
79 kParentSetIndex = 0,
80 kChildSetIndex = 1,
81 kNumSetIndex
82};
83enum {
84 kIOMaxPlaneName = 32
85};
86
87enum { kIORegistryIDReserved = (1ULL << 32) + 255 };
88
89static uint64_t gIORegistryLastID = kIORegistryIDReserved;
90
91class IORegistryPlane : public OSObject {
92
93 friend class IORegistryEntry;
94
95 OSDeclareAbstractStructors(IORegistryPlane)
96
97 const OSSymbol * nameKey;
98 const OSSymbol * keys[ kNumSetIndex ];
99 const OSSymbol * pathNameKey;
100 const OSSymbol * pathLocationKey;
101 int reserved[2];
102
103public:
104 virtual bool serialize(OSSerialize *s) const APPLE_KEXT_OVERRIDE;
105};
106
107OSDefineMetaClassAndStructors(IORegistryPlane, OSObject)
108
109
110static IORecursiveLock * gPropertiesLock;
111static SInt32 gIORegistryGenerationCount;
112
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++
117 // make atomic
118
119#define PUNLOCK IORecursiveLockUnlock( reserved->fLock )
120#define PLOCK IORecursiveLockLock( reserved->fLock )
121
122#define IOREGSPLITTABLES
123
124#ifdef IOREGSPLITTABLES
125#define registryTable() fRegistryTable
126#else
127#define registryTable() fPropertyTable
128#endif
129
130#define DEBUG_FREE 1
131
132/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
133
134lck_rw_t gIORegistryLock;
135lck_grp_t *gIORegistryLockGrp;
136lck_grp_attr_t *gIORegistryLockGrpAttr;
137lck_attr_t *gIORegistryLockAttr;
138
139
140/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
141
142IORegistryEntry * IORegistryEntry::initialize( void )
143{
144 bool ok;
145
146 if( !gRegistryRoot) {
147
148
149 gIORegistryLockGrpAttr = lck_grp_attr_alloc_init();
150 //lck_grp_attr_setstat(gIORegistryLockGrpAttr);
151 gIORegistryLockGrp = lck_grp_alloc_init("IORegistryLock", gIORegistryLockGrpAttr);
152 gIORegistryLockAttr = lck_attr_alloc_init();
153 lck_attr_rw_shared_priority(gIORegistryLockAttr);
154 //lck_attr_setdebug(gIORegistryLockAttr);
155 lck_rw_init( &gIORegistryLock, gIORegistryLockGrp, gIORegistryLockAttr);
156
157 gRegistryRoot = new IORegistryEntry;
158 gPropertiesLock = IORecursiveLockAlloc();
159 gIORegistryPlanes = OSDictionary::withCapacity( 1 );
160
161 assert( gRegistryRoot && gPropertiesLock
162 && gIORegistryPlanes );
163 ok = gRegistryRoot->init();
164
165 if (ok)
166 gRegistryRoot->reserved->fRegistryEntryID = ++gIORegistryLastID;
167
168 gIONameKey = OSSymbol::withCStringNoCopy( "IOName" );
169 gIOLocationKey = OSSymbol::withCStringNoCopy( "IOLocation" );
170 gIORegistryEntryIDKey = OSSymbol::withCStringNoCopy( kIORegistryEntryIDKey );
171 gIORegistryEntryPropertyKeysKey = OSSymbol::withCStringNoCopy( kIORegistryEntryPropertyKeysKey );
172
173 assert( ok && gIONameKey && gIOLocationKey );
174
175 gRegistryRoot->setName( "Root" );
176 gRegistryRoot->setProperty( kIORegistryPlanesKey, gIORegistryPlanes );
177 }
178
179 return( gRegistryRoot );
180}
181
182IORegistryEntry * IORegistryEntry::getRegistryRoot( void )
183{
184 return( gRegistryRoot );
185}
186
187SInt32 IORegistryEntry::getGenerationCount( void )
188{
189 return( gIORegistryGenerationCount );
190}
191
192SInt32 IORegistryEntry::getRegistryEntryGenerationCount(void) const
193{
194 return (reserved->fRegistryEntryGenerationCount);
195}
196
197const IORegistryPlane * IORegistryEntry::makePlane( const char * name )
198{
199 IORegistryPlane * plane;
200 const OSSymbol * nameKey;
201 const OSSymbol * parentKey;
202 const OSSymbol * childKey;
203 const OSSymbol * pathNameKey;
204 const OSSymbol * pathLocationKey;
205 char key[ kIOMaxPlaneName + 16 ];
206 char * end;
207
208 strlcpy( key, name, kIOMaxPlaneName + 1 );
209 end = key + strlen( key );
210
211 nameKey = OSSymbol::withCString( key);
212
213 strlcpy( end, kIORegPlaneParentSuffix, kIORegPlaneParentSuffixLen + 1 );
214 parentKey = OSSymbol::withCString( key);
215
216 strlcpy( end, kIORegPlaneChildSuffix, kIORegPlaneChildSuffixLen + 1 );
217 childKey = OSSymbol::withCString( key);
218
219 strlcpy( end, kIORegPlaneNameSuffix, kIORegPlaneNameSuffixLen + 1 );
220 pathNameKey = OSSymbol::withCString( key);
221
222 strlcpy( end, kIORegPlaneLocationSuffix, kIORegPlaneLocationSuffixLen + 1 );
223 pathLocationKey = OSSymbol::withCString( key);
224
225 plane = new IORegistryPlane;
226
227 if( plane && plane->init()
228 && nameKey && parentKey && childKey
229 && pathNameKey && pathLocationKey ) {
230
231 plane->nameKey = nameKey;
232 plane->keys[ kParentSetIndex ] = parentKey;
233 plane->keys[ kChildSetIndex ] = childKey;
234 plane->pathNameKey = pathNameKey;
235 plane->pathLocationKey = pathLocationKey;
236
237 WLOCK;
238 gIORegistryPlanes->setObject( nameKey, plane );
239 UNLOCK;
240
241 } else {
242
243 if( plane)
244 plane->release();
245 if( pathLocationKey)
246 pathLocationKey->release();
247 if( pathNameKey)
248 pathNameKey->release();
249 if( parentKey)
250 parentKey->release();
251 if( childKey)
252 childKey->release();
253 if( nameKey)
254 nameKey->release();
255 plane = 0;
256 }
257
258 return( plane);
259}
260
261const IORegistryPlane * IORegistryEntry::getPlane( const char * name )
262{
263 const IORegistryPlane * plane;
264
265 RLOCK;
266 plane = (const IORegistryPlane *) gIORegistryPlanes->getObject( name );
267 UNLOCK;
268
269 return( plane );
270}
271
272bool IORegistryPlane::serialize(OSSerialize *s) const
273{
274 return( nameKey->serialize(s) );
275}
276
277enum { kIORegCapacityIncrement = 4 };
278
279bool IORegistryEntry::init( OSDictionary * dict )
280{
281 OSString * prop;
282
283 if( !super::init())
284 return( false);
285
286 if (!reserved)
287 {
288 reserved = IONew(ExpansionData, 1);
289 if (!reserved)
290 return (false);
291 bzero(reserved, sizeof(ExpansionData));
292 reserved->fLock = IORecursiveLockAlloc();
293 if (!reserved->fLock) return (false);
294 }
295 if( dict) {
296 if (OSCollection::kImmutable & dict->setOptions(0, 0)) {
297 dict = (OSDictionary *) dict->copyCollection();
298 if (!dict)
299 return (false);
300 } else
301 dict->retain();
302 if( fPropertyTable)
303 fPropertyTable->release();
304 fPropertyTable = dict;
305
306 } else if( !fPropertyTable) {
307 fPropertyTable = OSDictionary::withCapacity( kIORegCapacityIncrement );
308 if( fPropertyTable)
309 fPropertyTable->setCapacityIncrement( kIORegCapacityIncrement );
310 }
311
312 if( !fPropertyTable)
313 return( false);
314
315#ifdef IOREGSPLITTABLES
316 if( !fRegistryTable) {
317 fRegistryTable = OSDictionary::withCapacity( kIORegCapacityIncrement );
318 if( fRegistryTable)
319 fRegistryTable->setCapacityIncrement( kIORegCapacityIncrement );
320 }
321
322 if( (prop = OSDynamicCast( OSString, getProperty( gIONameKey)))) {
323 OSSymbol * sym = (OSSymbol *)OSSymbol::withString( prop);
324 // ok for OSSymbol too
325 setName( sym);
326 sym->release();
327 }
328
329#endif /* IOREGSPLITTABLES */
330
331 return( true);
332}
333
334bool IORegistryEntry::init( IORegistryEntry * old,
335 const IORegistryPlane * plane )
336{
337 OSArray * all;
338 IORegistryEntry * next;
339 unsigned int index;
340
341 if( !super::init())
342 return( false);
343
344 if (!reserved)
345 {
346 reserved = IONew(ExpansionData, 1);
347 if (!reserved) return (false);
348 bzero(reserved, sizeof(ExpansionData));
349 reserved->fLock = IORecursiveLockAlloc();
350 if (!reserved->fLock) return (false);
351 }
352
353 WLOCK;
354
355 reserved->fRegistryEntryID = old->reserved->fRegistryEntryID;
356
357 fPropertyTable = old->dictionaryWithProperties();
358#ifdef IOREGSPLITTABLES
359 fRegistryTable = old->fRegistryTable;
360 old->fRegistryTable = (OSDictionary *) fRegistryTable->copyCollection();
361#endif /* IOREGSPLITTABLES */
362
363 old->registryTable()->removeObject( plane->keys[ kParentSetIndex ] );
364 old->registryTable()->removeObject( plane->keys[ kChildSetIndex ] );
365
366 all = getParentSetReference( plane );
367 if( all) for( index = 0;
368 (next = (IORegistryEntry *) all->getObject(index));
369 index++ ) {
370 next->makeLink( this, kChildSetIndex, plane );
371 next->breakLink( old, kChildSetIndex, plane );
372 }
373
374 all = getChildSetReference( plane );
375 if( all) for( index = 0;
376 (next = (IORegistryEntry *) all->getObject(index));
377 index++ ) {
378 next->makeLink( this, kParentSetIndex, plane );
379 next->breakLink( old, kParentSetIndex, plane );
380 }
381
382 UNLOCK;
383
384 return( true );
385}
386
387void IORegistryEntry::free( void )
388{
389#if DEBUG_FREE
390 if( registryTable() && gIOServicePlane) {
391 if( getParentSetReference( gIOServicePlane )
392 || getChildSetReference( gIOServicePlane )) {
393 panic("%s: attached at free()", getName());
394 }
395 }
396#endif
397
398 if( getPropertyTable())
399 getPropertyTable()->release();
400
401#ifdef IOREGSPLITTABLES
402 if( registryTable())
403 registryTable()->release();
404#endif /* IOREGSPLITTABLES */
405
406 if (reserved)
407 {
408 if (reserved->fIndexedProperties)
409 {
410 for (int idx = 0; idx < kIORegistryEntryIndexedPropertyCount; idx++)
411 {
412 if (reserved->fIndexedProperties[idx]) reserved->fIndexedProperties[idx]->release();
413 }
414 IODelete(reserved->fIndexedProperties, OSObject *, kIORegistryEntryIndexedPropertyCount);
415 }
416 if (reserved->fLock) IORecursiveLockFree(reserved->fLock);
417 IODelete(reserved, ExpansionData, 1);
418 }
419
420 super::free();
421}
422
423void IORegistryEntry::setPropertyTable( OSDictionary * dict )
424{
425 if( dict)
426 dict->retain();
427 if( fPropertyTable)
428 fPropertyTable->release();
429
430 fPropertyTable = dict;
431}
432
433/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
434
435/* Wrappers to synchronize property table */
436
437#define wrap2(type, constant) \
438OSObject * \
439IORegistryEntry::copyProperty( type * aKey) constant \
440{ \
441 OSObject * obj; \
442 \
443 PLOCK; \
444 obj = getProperty( aKey ); \
445 if( obj) \
446 obj->retain(); \
447 PUNLOCK; \
448 \
449 return( obj ); \
450}
451
452#define wrap4(type,constant) \
453OSObject * \
454IORegistryEntry::getProperty( type * aKey, \
455 const IORegistryPlane * plane, \
456 IOOptionBits options ) constant \
457{ \
458 OSObject * obj = getProperty( aKey ); \
459 \
460 if ( (0 == obj) && plane && (options & kIORegistryIterateRecursively) ) { \
461 IORegistryEntry * entry = (IORegistryEntry *) this; \
462 IORegistryIterator * iter; \
463 iter = IORegistryIterator::iterateOver( entry, plane, options ); \
464 \
465 if(iter) { \
466 while ( (0 == obj) && (entry = iter->getNextObject()) ) { \
467 obj = entry->getProperty( aKey ); \
468 } \
469 iter->release(); \
470 } \
471 } \
472 \
473 return( obj ); \
474}
475
476#define wrap5(type,constant) \
477OSObject * \
478IORegistryEntry::copyProperty( type * aKey, \
479 const IORegistryPlane * plane, \
480 IOOptionBits options ) constant \
481{ \
482 OSObject * obj = copyProperty( aKey ); \
483 \
484 if ( (0 == obj) && plane && (options & kIORegistryIterateRecursively) ) { \
485 IORegistryEntry * entry = (IORegistryEntry *) this; \
486 IORegistryIterator * iter; \
487 iter = IORegistryIterator::iterateOver( entry, plane, options ); \
488 \
489 if(iter) { \
490 while ( (0 == obj) && (entry = iter->getNextObject()) ) { \
491 obj = entry->copyProperty( aKey ); \
492 } \
493 iter->release(); \
494 } \
495 } \
496 \
497 return( obj ); \
498}
499
500bool IORegistryEntry::serializeProperties( OSSerialize * s ) const
501{
502// setProperty( getRetainCount(), 32, "__retain" );
503
504 PLOCK;
505 OSCollection *snapshotProperties = getPropertyTable()->copyCollection();
506 PUNLOCK;
507
508 if (!snapshotProperties) return (false);
509
510 bool ok = snapshotProperties->serialize( s );
511 snapshotProperties->release();
512 return( ok );
513}
514
515OSArray * IORegistryEntry::copyPropertyKeys(void) const
516{
517 PLOCK;
518 OSArray * keys = getPropertyTable()->copyKeys();
519 PUNLOCK;
520
521 return (keys);
522}
523
524OSDictionary * IORegistryEntry::dictionaryWithProperties( void ) const
525{
526 OSDictionary * dict;
527
528 PLOCK;
529 dict = OSDictionary::withDictionary( getPropertyTable(),
530 getPropertyTable()->getCapacity() );
531 PUNLOCK;
532
533 return( dict );
534}
535
536IOReturn IORegistryEntry::setProperties( OSObject * properties )
537{
538 return( kIOReturnUnsupported );
539}
540
541wrap2(const OSSymbol, const) // copyProperty() definition
542wrap2(const OSString, const) // copyProperty() definition
543wrap2(const char, const) // copyProperty() definition
544
545wrap4(const OSSymbol, const) // getProperty() w/plane definition
546wrap4(const OSString, const) // getProperty() w/plane definition
547wrap4(const char, const) // getProperty() w/plane definition
548
549wrap5(const OSSymbol, const) // copyProperty() w/plane definition
550wrap5(const OSString, const) // copyProperty() w/plane definition
551wrap5(const char, const) // copyProperty() w/plane definition
552
553
554OSObject *
555IORegistryEntry::getProperty( const OSSymbol * aKey) const
556{
557 OSObject * obj;
558
559 PLOCK;
560 obj = getPropertyTable()->getObject( aKey );
561 PUNLOCK;
562
563 return( obj );
564}
565
566void
567IORegistryEntry::removeProperty( const OSSymbol * aKey)
568{
569 PLOCK;
570 getPropertyTable()->removeObject( aKey );
571 PUNLOCK;
572}
573
574#if KASLR_IOREG_DEBUG
575extern "C" {
576
577bool ScanForAddrInObject(OSObject * theObject,
578 int indent);
579
580}; /* extern "C" */
581#endif
582
583bool
584IORegistryEntry::setProperty( const OSSymbol * aKey, OSObject * anObject)
585{
586 bool ret = false;
587
588 // If we are inserting a collection class and the current entry
589 // is attached into the registry (inPlane()) then mark the collection
590 // as immutable.
591 OSCollection *coll = OSDynamicCast(OSCollection, anObject);
592 bool makeImmutable = (coll && inPlane());
593
594 PLOCK;
595 if( makeImmutable )
596 coll->setOptions( OSCollection::kMASK, OSCollection::kImmutable );
597
598 ret = getPropertyTable()->setObject( aKey, anObject );
599 PUNLOCK;
600
601#if KASLR_IOREG_DEBUG
602 if ( anObject && strcmp(kIOKitDiagnosticsKey, aKey->getCStringNoCopy()) != 0 ) {
603 if (ScanForAddrInObject(anObject, 0)) {
604 IOLog("%s: IORegistryEntry name %s with key \"%s\" \n",
605 __FUNCTION__,
606 getName(0),
607 aKey->getCStringNoCopy() );
608 }
609 }
610#endif
611
612 return ret;
613}
614
615IOReturn IORegistryEntry::
616runPropertyAction(Action inAction, OSObject *target,
617 void *arg0, void *arg1, void *arg2, void *arg3)
618{
619 IOReturn res;
620
621 // closeGate is recursive so don't worry if we already hold the lock.
622 PLOCK;
623 res = (*inAction)(target, arg0, arg1, arg2, arg3);
624 PUNLOCK;
625
626 return res;
627}
628
629OSObject *
630IORegistryEntry::getProperty( const OSString * aKey) const
631{
632 const OSSymbol * tmpKey = OSSymbol::withString( aKey );
633 OSObject * obj = getProperty( tmpKey );
634
635 tmpKey->release();
636 return( obj );
637}
638
639OSObject *
640IORegistryEntry::getProperty( const char * aKey) const
641{
642 const OSSymbol * tmpKey = OSSymbol::withCString( aKey );
643 OSObject * obj = getProperty( tmpKey );
644
645 tmpKey->release();
646 return( obj );
647}
648
649
650void
651IORegistryEntry::removeProperty( const OSString * aKey)
652{
653 const OSSymbol * tmpKey = OSSymbol::withString( aKey );
654 removeProperty( tmpKey );
655 tmpKey->release();
656}
657
658void
659IORegistryEntry::removeProperty( const char * aKey)
660{
661 const OSSymbol * tmpKey = OSSymbol::withCString( aKey );
662 removeProperty( tmpKey );
663 tmpKey->release();
664}
665
666bool
667IORegistryEntry::setProperty( const OSString * aKey, OSObject * anObject)
668{
669 const OSSymbol * tmpKey = OSSymbol::withString( aKey );
670 bool ret = setProperty( tmpKey, anObject );
671
672 tmpKey->release();
673 return ret;
674}
675
676bool
677IORegistryEntry::setProperty( const char * aKey, OSObject * anObject)
678{
679 const OSSymbol * tmpKey = OSSymbol::withCString( aKey );
680 bool ret = setProperty( tmpKey, anObject );
681
682 tmpKey->release();
683 return ret;
684}
685
686bool
687IORegistryEntry::setProperty(const char * aKey, const char * aString)
688{
689 bool ret = false;
690 OSSymbol * aSymbol = (OSSymbol *) OSSymbol::withCString( aString );
691
692 if( aSymbol) {
693 const OSSymbol * tmpKey = OSSymbol::withCString( aKey );
694 ret = setProperty( tmpKey, aSymbol );
695
696 tmpKey->release();
697 aSymbol->release();
698 }
699 return( ret );
700}
701
702bool
703IORegistryEntry::setProperty(const char * aKey, bool aBoolean)
704{
705 bool ret = false;
706 OSBoolean * aBooleanObj = OSBoolean::withBoolean( aBoolean );
707
708 if( aBooleanObj) {
709 const OSSymbol * tmpKey = OSSymbol::withCString( aKey );
710 ret = setProperty( tmpKey, aBooleanObj );
711
712 tmpKey->release();
713 aBooleanObj->release();
714 }
715 return( ret );
716}
717
718bool
719IORegistryEntry::setProperty( const char * aKey,
720 unsigned long long aValue,
721 unsigned int aNumberOfBits)
722{
723 bool ret = false;
724 OSNumber * anOffset = OSNumber::withNumber( aValue, aNumberOfBits );
725
726 if( anOffset) {
727 const OSSymbol * tmpKey = OSSymbol::withCString( aKey );
728 ret = setProperty( tmpKey, anOffset );
729
730 tmpKey->release();
731 anOffset->release();
732 }
733 return( ret );
734}
735
736bool
737IORegistryEntry::setProperty( const char * aKey,
738 void * bytes,
739 unsigned int length)
740{
741 bool ret = false;
742 OSData * data = OSData::withBytes( bytes, length );
743
744 if( data) {
745 const OSSymbol * tmpKey = OSSymbol::withCString( aKey );
746 ret = setProperty( tmpKey, data );
747
748 tmpKey->release();
749 data->release();
750 }
751 return( ret );
752}
753
754/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
755
756OSObject * IORegistryEntry::setIndexedProperty(uint32_t index, OSObject * anObject)
757{
758 OSObject ** array;
759 OSObject * prior;
760
761 if (index >= kIORegistryEntryIndexedPropertyCount) return (0);
762
763 array = atomic_load_explicit(&reserved->fIndexedProperties, memory_order_acquire);
764 if (!array)
765 {
766 array = IONew(OSObject *, kIORegistryEntryIndexedPropertyCount);
767 if (!array) return (0);
768 bzero(array, kIORegistryEntryIndexedPropertyCount * sizeof(array[0]));
769 if (!OSCompareAndSwapPtr(NULL, array, &reserved->fIndexedProperties)) IODelete(array, OSObject *, kIORegistryEntryIndexedPropertyCount);
770 }
771 if (!reserved->fIndexedProperties) return (0);
772
773 prior = reserved->fIndexedProperties[index];
774 if (anObject) anObject->retain();
775 reserved->fIndexedProperties[index] = anObject;
776
777 return (prior);
778}
779
780OSObject * IORegistryEntry::getIndexedProperty(uint32_t index) const
781{
782 if (index >= kIORegistryEntryIndexedPropertyCount) return (0);
783 if (!reserved->fIndexedProperties) return (0);
784
785 return (reserved->fIndexedProperties[index]);
786}
787
788/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
789
790/* Name, location, paths */
791
792const char * IORegistryEntry::getName( const IORegistryPlane * plane ) const
793{
794 OSSymbol * sym = 0;
795
796 RLOCK;
797 if( plane)
798 sym = (OSSymbol *) registryTable()->getObject( plane->pathNameKey );
799 if( !sym)
800 sym = (OSSymbol *) registryTable()->getObject( gIONameKey );
801 UNLOCK;
802
803 if( sym)
804 return( sym->getCStringNoCopy());
805 else
806 return( (getMetaClass())->getClassName());
807}
808
809const OSSymbol * IORegistryEntry::copyName(
810 const IORegistryPlane * plane ) const
811{
812 OSSymbol * sym = 0;
813
814 RLOCK;
815 if( plane)
816 sym = (OSSymbol *) registryTable()->getObject( plane->pathNameKey );
817 if( !sym)
818 sym = (OSSymbol *) registryTable()->getObject( gIONameKey );
819 if( sym)
820 sym->retain();
821 UNLOCK;
822
823 if( sym)
824 return( sym );
825 else
826 return( OSSymbol::withCString((getMetaClass())->getClassName()) );
827}
828
829const OSSymbol * IORegistryEntry::copyLocation(
830 const IORegistryPlane * plane ) const
831{
832 OSSymbol * sym = 0;
833
834 RLOCK;
835 if( plane)
836 sym = (OSSymbol *) registryTable()->getObject( plane->pathLocationKey );
837 if( !sym)
838 sym = (OSSymbol *) registryTable()->getObject( gIOLocationKey );
839 if( sym)
840 sym->retain();
841 UNLOCK;
842
843 return( sym );
844}
845
846const char * IORegistryEntry::getLocation( const IORegistryPlane * plane ) const
847{
848 const OSSymbol * sym = copyLocation( plane );
849 const char * result = 0;
850
851 if( sym) {
852 result = sym->getCStringNoCopy();
853 sym->release();
854 }
855
856 return( result );
857}
858
859void IORegistryEntry::setName( const OSSymbol * name,
860 const IORegistryPlane * plane )
861{
862 const OSSymbol * key;
863
864 if( name) {
865 if( plane)
866 key = plane->pathNameKey;
867 else
868 key = gIONameKey;
869
870 if (gIOKitTrace && reserved && reserved->fRegistryEntryID)
871 {
872 uint64_t str_id = 0;
873 uint64_t __unused regID = getRegistryEntryID();
874 kernel_debug_string(IODBG_IOREGISTRY(IOREGISTRYENTRY_NAME_STRING), &str_id, name->getCStringNoCopy());
875 KERNEL_DEBUG_CONSTANT(IODBG_IOREGISTRY(IOREGISTRYENTRY_NAME),
876 (uintptr_t) regID,
877 (uintptr_t) (regID >> 32),
878 (uintptr_t) str_id,
879 (uintptr_t) (str_id >> 32),
880 0);
881 }
882
883 WLOCK;
884 registryTable()->setObject( key, (OSObject *) name);
885 UNLOCK;
886 }
887}
888
889void IORegistryEntry::setName( const char * name,
890 const IORegistryPlane * plane )
891{
892 OSSymbol * sym = (OSSymbol *)OSSymbol::withCString( name );
893 if ( sym ) {
894 setName( sym, plane );
895 sym->release();
896 }
897}
898
899void IORegistryEntry::setLocation( const OSSymbol * location,
900 const IORegistryPlane * plane )
901{
902 const OSSymbol * key;
903
904 if( location) {
905 if( plane)
906 key = plane->pathLocationKey;
907 else
908 key = gIOLocationKey;
909
910 WLOCK;
911 registryTable()->setObject( key, (OSObject *) location);
912 UNLOCK;
913 }
914}
915
916void IORegistryEntry::setLocation( const char * location,
917 const IORegistryPlane * plane )
918{
919 OSSymbol * sym = (OSSymbol *)OSSymbol::withCString( location );
920 if ( sym ) {
921 setLocation( sym, plane );
922 sym->release();
923 }
924}
925
926bool
927IORegistryEntry::compareName( OSString * name, OSString ** matched ) const
928{
929 const OSSymbol * sym = copyName();
930 bool isEqual;
931
932 isEqual = (sym && sym->isEqualTo(name));
933
934 if( isEqual && matched) {
935 name->retain();
936 *matched = name;
937 }
938
939 if( sym)
940 sym->release();
941
942 return( isEqual );
943}
944
945bool
946IORegistryEntry::compareNames( OSObject * names, OSString ** matched ) const
947{
948 OSString * string;
949 OSCollection * collection;
950 OSIterator * iter = 0;
951 bool result = false;
952
953 if( (collection = OSDynamicCast( OSCollection, names))) {
954 iter = OSCollectionIterator::withCollection( collection );
955 string = 0;
956 } else
957 string = OSDynamicCast( OSString, names);
958
959 do {
960 if( string)
961 result = compareName( string, matched );
962
963 } while( (false == result)
964 && iter && (string = OSDynamicCast( OSString, iter->getNextObject())));
965
966 if( iter)
967 iter->release();
968
969 return( result);
970}
971
972
973bool IORegistryEntry::getPath( char * path, int * length,
974 const IORegistryPlane * plane ) const
975{
976 OSArray * stack;
977 IORegistryEntry * root;
978 const IORegistryEntry * entry;
979 const IORegistryEntry * parent;
980 const OSSymbol * alias;
981 int index;
982 int len, maxLength, compLen, aliasLen;
983 char * nextComp;
984 bool ok;
985
986 if( !path || !length || !plane)
987 return( false);
988
989 len = 0;
990 maxLength = *length - 2;
991 nextComp = path;
992
993 len = plane->nameKey->getLength();
994 if( len >= maxLength)
995 return( false);
996 strlcpy( nextComp, plane->nameKey->getCStringNoCopy(), len + 1);
997 nextComp[ len++ ] = ':';
998 nextComp += len;
999
1000 if( (alias = hasAlias( plane ))) {
1001 aliasLen = alias->getLength();
1002 len += aliasLen;
1003 ok = (maxLength > len);
1004 *length = len;
1005 if( ok)
1006 strlcpy( nextComp, alias->getCStringNoCopy(), aliasLen + 1);
1007 return( ok );
1008 }
1009
1010 stack = OSArray::withCapacity( getDepth( plane ));
1011 if (!stack) return( false);
1012
1013 RLOCK;
1014
1015 parent = entry = this;
1016 root = gRegistryRoot->getChildEntry( plane );
1017 while (parent && (parent != root))
1018 {
1019 // stop below root
1020 entry = parent;
1021 parent = entry->getParentEntry( plane );
1022 stack->setObject( (OSObject *) entry );
1023 }
1024
1025 ok = (0 != parent);
1026 if (ok)
1027 {
1028 index = stack->getCount();
1029 if( 0 == index) {
1030
1031 *nextComp++ = '/';
1032 *nextComp = 0;
1033 len++;
1034
1035 } else while( ok && ((--index) >= 0)) {
1036
1037 entry = (IORegistryEntry *) stack->getObject((unsigned int) index );
1038 assert( entry );
1039
1040 if( (alias = entry->hasAlias( plane ))) {
1041 len = plane->nameKey->getLength() + 1;
1042 nextComp = path + len;
1043
1044 compLen = alias->getLength();
1045 ok = (maxLength > (len + compLen));
1046 if( ok)
1047 strlcpy( nextComp, alias->getCStringNoCopy(), compLen + 1);
1048 } else {
1049 compLen = maxLength - len;
1050 ok = entry->getPathComponent( nextComp + 1, &compLen, plane );
1051
1052 if( ok && compLen) {
1053 compLen++;
1054 *nextComp = '/';
1055 }
1056 }
1057
1058 if( ok) {
1059 len += compLen;
1060 nextComp += compLen;
1061 }
1062 }
1063 *length = len;
1064 }
1065 UNLOCK;
1066 stack->release();
1067
1068 return( ok );
1069}
1070
1071bool IORegistryEntry::getPathComponent( char * path, int * length,
1072 const IORegistryPlane * plane ) const
1073{
1074 int len, locLen, maxLength;
1075 const char * compName;
1076 const char * loc;
1077 bool ok;
1078
1079 maxLength = *length;
1080
1081 compName = getName( plane );
1082 len = strlen( compName );
1083 if( (loc = getLocation( plane )))
1084 locLen = 1 + strlen( loc );
1085 else
1086 locLen = 0;
1087
1088 ok = ((len + locLen + 1) < maxLength);
1089 if( ok) {
1090 strlcpy( path, compName, len + 1 );
1091 if( loc) {
1092 path += len;
1093 len += locLen;
1094 *path++ = '@';
1095 strlcpy( path, loc, locLen );
1096 }
1097 *length = len;
1098 }
1099
1100 return( ok );
1101}
1102
1103const char * IORegistryEntry::matchPathLocation( const char * cmp,
1104 const IORegistryPlane * plane )
1105{
1106 const char * str;
1107 const char * result = 0;
1108 u_quad_t num1, num2;
1109 char lastPathChar, lastLocationChar;
1110
1111 str = getLocation( plane );
1112 if( str) {
1113 lastPathChar = cmp[0];
1114 lastLocationChar = str[0];
1115 do {
1116 if( lastPathChar) {
1117 num1 = strtouq( cmp, (char **) &cmp, 16 );
1118 lastPathChar = *cmp++;
1119 } else
1120 num1 = 0;
1121
1122 if( lastLocationChar) {
1123 num2 = strtouq( str, (char **) &str, 16 );
1124 lastLocationChar = *str++;
1125 } else
1126 num2 = 0;
1127
1128 if( num1 != num2)
1129 break;
1130
1131 if (!lastPathChar && !lastLocationChar) {
1132 result = cmp - 1;
1133 break;
1134 }
1135
1136 if( (',' != lastPathChar) && (':' != lastPathChar))
1137 lastPathChar = 0;
1138
1139 if (lastPathChar && lastLocationChar && (lastPathChar != lastLocationChar))
1140 break;
1141
1142 } while( true);
1143 }
1144
1145 return( result );
1146}
1147
1148IORegistryEntry * IORegistryEntry::getChildFromComponent( const char ** opath,
1149 const IORegistryPlane * plane )
1150{
1151 IORegistryEntry * entry = 0;
1152 OSArray * set;
1153 unsigned int index;
1154 const char * path;
1155 const char * cmp = 0;
1156 char c;
1157 size_t len;
1158 const char * str;
1159
1160 set = getChildSetReference( plane );
1161 if( set) {
1162
1163 path = *opath;
1164
1165 for( index = 0;
1166 (entry = (IORegistryEntry *) set->getObject(index));
1167 index++ ) {
1168
1169 cmp = path;
1170
1171 if( *cmp != '@') {
1172 str = entry->getName( plane );
1173 len = strlen( str );
1174 if( strncmp( str, cmp, len ))
1175 continue;
1176 cmp += len;
1177
1178 c = *cmp;
1179 if( (c == 0) || (c == '/') || (c == ':'))
1180 break;
1181 if( c != '@')
1182 continue;
1183 }
1184 cmp++;
1185 if( (cmp = entry->matchPathLocation( cmp, plane )))
1186 break;
1187 }
1188 if( entry)
1189 *opath = cmp;
1190 }
1191
1192 return( entry );
1193}
1194
1195const OSSymbol * IORegistryEntry::hasAlias( const IORegistryPlane * plane,
1196 char * opath, int * length ) const
1197{
1198 IORegistryEntry * entry;
1199 IORegistryEntry * entry2;
1200 const OSSymbol * key;
1201 const OSSymbol * bestKey = 0;
1202 OSIterator * iter;
1203 OSData * data;
1204 const char * path = "/aliases";
1205
1206 entry = IORegistryEntry::fromPath( path, plane );
1207 if( entry) {
1208 RLOCK;
1209 if( (iter = OSCollectionIterator::withCollection(
1210 entry->getPropertyTable() ))) {
1211
1212 while( (key = (OSSymbol *) iter->getNextObject())) {
1213
1214 data = (OSData *) entry->getProperty( key );
1215 path = (const char *) data->getBytesNoCopy();
1216 if( (entry2 = IORegistryEntry::fromPath( path, plane,
1217 opath, length ))) {
1218 if( this == entry2) {
1219 if( !bestKey
1220 || (bestKey->getLength() > key->getLength()))
1221 // pick the smallest alias
1222 bestKey = key;
1223 }
1224 entry2->release();
1225 }
1226 }
1227 iter->release();
1228 }
1229 entry->release();
1230 UNLOCK;
1231 }
1232 return( bestKey );
1233}
1234
1235const char * IORegistryEntry::dealiasPath(
1236 const char ** opath,
1237 const IORegistryPlane * plane )
1238{
1239 IORegistryEntry * entry;
1240 OSData * data;
1241 const char * path = *opath;
1242 const char * rpath = 0;
1243 const char * end;
1244 char c;
1245 char temp[ kIOMaxPlaneName + 1 ];
1246
1247 if( path[0] == '/')
1248 return( rpath );
1249
1250 // check for alias
1251 end = path;
1252 while( (c = *end++) && (c != '/') && (c != ':'))
1253 {}
1254 end--;
1255 if( (end - path) < kIOMaxPlaneName) {
1256 strlcpy( temp, path, end - path + 1 );
1257
1258 RLOCK;
1259 entry = IORegistryEntry::fromPath( "/aliases", plane );
1260 if( entry) {
1261 data = (OSData *) entry->getProperty( temp );
1262 if( data ) {
1263 rpath = (const char *) data->getBytesNoCopy();
1264 if( rpath)
1265 *opath = end;
1266 }
1267 entry->release();
1268 }
1269 UNLOCK;
1270 }
1271
1272 return( rpath );
1273}
1274
1275IORegistryEntry * IORegistryEntry::fromPath(
1276 const char * path,
1277 const IORegistryPlane * plane,
1278 char * opath,
1279 int * length,
1280 IORegistryEntry * fromEntry )
1281{
1282 IORegistryEntry * where = 0;
1283 IORegistryEntry * aliasEntry = 0;
1284 IORegistryEntry * next;
1285 const char * alias;
1286 const char * end;
1287 int len = 0;
1288 int len2;
1289 char c;
1290 char temp[ kIOMaxPlaneName + 1 ];
1291
1292 if( 0 == path)
1293 return( 0 );
1294
1295 if( 0 == plane) {
1296 // get plane name
1297 end = strchr( path, ':' );
1298 if( end && ((end - path) < kIOMaxPlaneName)) {
1299 strlcpy( temp, path, end - path + 1 );
1300 plane = getPlane( temp );
1301 path = end + 1;
1302 }
1303 }
1304 if( 0 == plane)
1305 return( 0 );
1306
1307 // check for alias
1308 end = path;
1309 if( (alias = dealiasPath( &end, plane))) {
1310 if( length)
1311 len = *length;
1312 aliasEntry = IORegistryEntry::fromPath( alias, plane,
1313 opath, &len, fromEntry );
1314 where = aliasEntry;
1315 if( where)
1316 path = end;
1317 else
1318 len = 0;
1319 }
1320
1321 RLOCK;
1322
1323 do {
1324 if( 0 == where) {
1325 if( (0 == fromEntry) && (*path++ == '/'))
1326 fromEntry = gRegistryRoot->getChildEntry( plane );
1327 where = fromEntry;
1328 if( 0 == where)
1329 break;
1330 } else {
1331 c = *path++;
1332 if( c != '/') {
1333 if( c && (c != ':')) // check valid terminator
1334 where = 0;
1335 break;
1336 }
1337 }
1338 next = where->getChildFromComponent( &path, plane );
1339 if( next)
1340 where = next;
1341 } while( next );
1342
1343 if( where) {
1344 // check residual path
1345 if( where != fromEntry)
1346 path--;
1347
1348 if( opath && length) {
1349 // copy out residual path
1350 len2 = strlen( path );
1351 if( (len + len2) < *length)
1352 strlcpy( opath + len, path, len2 + 1 );
1353 *length = (len + len2);
1354
1355 } else if( path[0])
1356 // no residual path => must be no tail for success
1357 where = 0;
1358 }
1359
1360 if( where)
1361 where->retain();
1362 if( aliasEntry)
1363 aliasEntry->release();
1364
1365 UNLOCK;
1366
1367 return( where );
1368}
1369
1370IORegistryEntry * IORegistryEntry::childFromPath(
1371 const char * path,
1372 const IORegistryPlane * plane,
1373 char * opath,
1374 int * len )
1375{
1376 return( IORegistryEntry::fromPath( path, plane, opath, len, this ));
1377}
1378
1379/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1380
1381#define IOLinkIterator OSCollectionIterator
1382
1383#undef super
1384#define super OSObject
1385
1386inline bool IORegistryEntry::arrayMember( OSArray * set,
1387 const IORegistryEntry * member,
1388 unsigned int * index ) const
1389{
1390 int i;
1391 OSObject * probeObject;
1392
1393 for( i = 0; (probeObject = set->getObject(i)); i++) {
1394 if (probeObject == (OSObject *) member) {
1395 if( index)
1396 *index = i;
1397 return( true );
1398 }
1399 }
1400 return( false );
1401}
1402
1403bool IORegistryEntry::makeLink( IORegistryEntry * to,
1404 unsigned int relation,
1405 const IORegistryPlane * plane ) const
1406{
1407 OSArray * links;
1408 bool result = false;
1409
1410 if( (links = (OSArray *)
1411 registryTable()->getObject( plane->keys[ relation ] ))) {
1412
1413 result = arrayMember( links, to );
1414 if( !result)
1415 result = links->setObject( to );
1416
1417 } else {
1418
1419 links = OSArray::withObjects( (const OSObject **) &to, 1, 1 );
1420 result = (links != 0);
1421 if( result) {
1422 result = registryTable()->setObject( plane->keys[ relation ],
1423 links );
1424 links->release();
1425 }
1426 }
1427 reserved->fRegistryEntryGenerationCount++;
1428
1429 return( result);
1430}
1431
1432void IORegistryEntry::breakLink( IORegistryEntry * to,
1433 unsigned int relation,
1434 const IORegistryPlane * plane ) const
1435{
1436 OSArray * links;
1437 unsigned int index;
1438
1439 if( (links = (OSArray *)
1440 registryTable()->getObject( plane->keys[ relation ]))) {
1441
1442 if( arrayMember( links, to, &index )) {
1443 links->removeObject( index );
1444 if( 0 == links->getCount())
1445 registryTable()->removeObject( plane->keys[ relation ]);
1446 }
1447 }
1448 reserved->fRegistryEntryGenerationCount++;
1449}
1450
1451
1452OSArray * IORegistryEntry::getParentSetReference(
1453 const IORegistryPlane * plane ) const
1454{
1455 if( plane)
1456 return( (OSArray *) registryTable()->getObject(
1457 plane->keys[ kParentSetIndex ]));
1458 else
1459 return( 0 );
1460}
1461
1462OSIterator * IORegistryEntry::getParentIterator(
1463 const IORegistryPlane * plane ) const
1464{
1465 OSArray * links;
1466 OSIterator * iter;
1467
1468 if( !plane)
1469 return( 0 );
1470
1471 RLOCK;
1472 links = getParentSetReference( plane );
1473 if( 0 == links)
1474 links = OSArray::withCapacity( 1 );
1475 else
1476 links = OSArray::withArray( links, links->getCount() );
1477 UNLOCK;
1478
1479 iter = IOLinkIterator::withCollection( links );
1480
1481 if( links)
1482 links->release();
1483
1484 return( iter );
1485}
1486
1487IORegistryEntry * IORegistryEntry::copyParentEntry( const IORegistryPlane * plane ) const
1488{
1489 IORegistryEntry * entry = 0;
1490 OSArray * links;
1491
1492 RLOCK;
1493
1494 if( (links = getParentSetReference( plane ))) {
1495 entry = (IORegistryEntry *) links->getObject( 0 );
1496 entry->retain();
1497 }
1498
1499 UNLOCK;
1500
1501 return( entry);
1502}
1503
1504IORegistryEntry * IORegistryEntry::getParentEntry( const IORegistryPlane * plane ) const
1505{
1506 IORegistryEntry * entry;
1507
1508 entry = copyParentEntry( plane );
1509 if( entry)
1510 entry->release();
1511
1512 return( entry );
1513}
1514
1515OSArray * IORegistryEntry::getChildSetReference( const IORegistryPlane * plane ) const
1516{
1517 if( plane)
1518 return( (OSArray *) registryTable()->getObject(
1519 plane->keys[ kChildSetIndex ]));
1520 else
1521 return( 0 );
1522}
1523
1524OSIterator * IORegistryEntry::getChildIterator( const IORegistryPlane * plane ) const
1525{
1526 OSArray * links;
1527 OSIterator * iter;
1528
1529 if( !plane)
1530 return( 0 );
1531
1532 RLOCK;
1533 links = getChildSetReference( plane );
1534 if( 0 == links)
1535 links = OSArray::withCapacity( 1 );
1536 else
1537 links = OSArray::withArray( links, links->getCount() );
1538 UNLOCK;
1539
1540 iter = IOLinkIterator::withCollection( links );
1541
1542 if( links)
1543 links->release();
1544
1545 return( iter );
1546}
1547
1548uint32_t IORegistryEntry::getChildCount( const IORegistryPlane * plane ) const
1549{
1550 OSArray * links;
1551 uint32_t count = 0;
1552
1553 RLOCK;
1554 links = getChildSetReference( plane );
1555 if (links) count = links->getCount();
1556 UNLOCK;
1557
1558 return (count);
1559}
1560
1561IORegistryEntry * IORegistryEntry::copyChildEntry(
1562 const IORegistryPlane * plane ) const
1563{
1564 IORegistryEntry * entry = 0;
1565 OSArray * links;
1566
1567 RLOCK;
1568
1569 if( (links = getChildSetReference( plane ))) {
1570 entry = (IORegistryEntry *) links->getObject( 0 );
1571 entry->retain();
1572 }
1573
1574 UNLOCK;
1575
1576 return( entry);
1577}
1578
1579IORegistryEntry * IORegistryEntry::getChildEntry(
1580 const IORegistryPlane * plane ) const
1581{
1582 IORegistryEntry * entry;
1583
1584 entry = copyChildEntry( plane );
1585 if( entry)
1586 entry->release();
1587
1588 return( entry );
1589}
1590
1591void IORegistryEntry::applyToChildren( IORegistryEntryApplierFunction applier,
1592 void * context,
1593 const IORegistryPlane * plane ) const
1594{
1595 OSArray * array;
1596 unsigned int index;
1597 IORegistryEntry * next;
1598
1599 if( !plane)
1600 return;
1601
1602 RLOCK;
1603 array = OSArray::withArray( getChildSetReference( plane ));
1604 UNLOCK;
1605 if( array) {
1606 for( index = 0;
1607 (next = (IORegistryEntry *) array->getObject( index ));
1608 index++)
1609 (*applier)(next, context);
1610 array->release();
1611 }
1612}
1613
1614void IORegistryEntry::applyToParents( IORegistryEntryApplierFunction applier,
1615 void * context,
1616 const IORegistryPlane * plane ) const
1617{
1618 OSArray * array;
1619 unsigned int index;
1620 IORegistryEntry * next;
1621
1622 if( !plane)
1623 return;
1624
1625 RLOCK;
1626 array = OSArray::withArray( getParentSetReference( plane ));
1627 UNLOCK;
1628 if( array) {
1629 for( index = 0;
1630 (next = (IORegistryEntry *) array->getObject( index ));
1631 index++)
1632 (*applier)(next, context);
1633 array->release();
1634 }
1635}
1636
1637bool IORegistryEntry::isChild( IORegistryEntry * child,
1638 const IORegistryPlane * plane,
1639 bool onlyChild ) const
1640{
1641 OSArray * links;
1642 bool ret = false;
1643
1644 RLOCK;
1645
1646 if( (links = getChildSetReference( plane ))) {
1647 if( (!onlyChild) || (1 == links->getCount()))
1648 ret = arrayMember( links, child );
1649 }
1650 if( ret && (links = child->getParentSetReference( plane )))
1651 ret = arrayMember( links, this );
1652
1653 UNLOCK;
1654
1655 return( ret);
1656}
1657
1658bool IORegistryEntry::isParent( IORegistryEntry * parent,
1659 const IORegistryPlane * plane,
1660 bool onlyParent ) const
1661
1662{
1663 OSArray * links;
1664 bool ret = false;
1665
1666 RLOCK;
1667
1668 if( (links = getParentSetReference( plane ))) {
1669 if( (!onlyParent) || (1 == links->getCount()))
1670 ret = arrayMember( links, parent );
1671 }
1672 if( ret && (links = parent->getChildSetReference( plane )))
1673 ret = arrayMember( links, this );
1674
1675 UNLOCK;
1676
1677 return( ret);
1678}
1679
1680bool IORegistryEntry::inPlane( const IORegistryPlane * plane ) const
1681{
1682 bool ret;
1683
1684 RLOCK;
1685
1686 if( plane)
1687 ret = (0 != getParentSetReference( plane ));
1688 else {
1689
1690 // Check to see if this is in any plane. If it is in a plane
1691 // then the registryTable will contain a key with the ParentLinks
1692 // suffix. When we iterate over the keys looking for that suffix
1693 ret = false;
1694
1695 OSCollectionIterator *iter =
1696 OSCollectionIterator::withCollection( registryTable());
1697 if( iter) {
1698 const OSSymbol *key;
1699
1700 while( (key = (OSSymbol *) iter->getNextObject()) ) {
1701 size_t keysuffix;
1702
1703 // Get a pointer to this keys suffix
1704 keysuffix = key->getLength();
1705 if (keysuffix <= kIORegPlaneParentSuffixLen)
1706 continue;
1707 keysuffix -= kIORegPlaneParentSuffixLen;
1708 if( !strncmp(key->getCStringNoCopy() + keysuffix,
1709 kIORegPlaneParentSuffix,
1710 kIORegPlaneParentSuffixLen + 1) ) {
1711 ret = true;
1712 break;
1713 }
1714 }
1715 iter->release();
1716 }
1717 }
1718
1719 UNLOCK;
1720
1721 return( ret );
1722}
1723
1724bool IORegistryEntry::attachToParent( IORegistryEntry * parent,
1725 const IORegistryPlane * plane )
1726{
1727 OSArray * links;
1728 bool ret;
1729 bool needParent;
1730 bool traceName = false;
1731
1732 if( this == parent)
1733 return( false );
1734
1735 WLOCK;
1736
1737 if (!reserved->fRegistryEntryID)
1738 {
1739 reserved->fRegistryEntryID = ++gIORegistryLastID;
1740 traceName = (0 != gIOKitTrace);
1741 }
1742
1743 ret = makeLink( parent, kParentSetIndex, plane );
1744
1745 if( (links = parent->getChildSetReference( plane )))
1746 needParent = (false == arrayMember( links, this ));
1747 else
1748 needParent = true;
1749
1750 UNLOCK;
1751
1752 if (traceName)
1753 {
1754 uint64_t str_id = 0;
1755 uint64_t __unused regID = getRegistryEntryID();
1756 kernel_debug_string(IODBG_IOREGISTRY(IOREGISTRYENTRY_NAME_STRING), &str_id, getName());
1757 KERNEL_DEBUG_CONSTANT(IODBG_IOREGISTRY(IOREGISTRYENTRY_NAME),
1758 (uintptr_t) regID,
1759 (uintptr_t) (regID >> 32),
1760 (uintptr_t) str_id,
1761 (uintptr_t) (str_id >> 32),
1762 0);
1763 }
1764
1765 PLOCK;
1766
1767 // Mark any collections in the property list as immutable
1768 OSDictionary *ptable = getPropertyTable();
1769 OSCollectionIterator *iter =
1770 OSCollectionIterator::withCollection( ptable );
1771 if( iter) {
1772 const OSSymbol *key;
1773
1774 while( (key = (OSSymbol *) iter->getNextObject( ))) {
1775 // Is object for key a collection?
1776 OSCollection *coll =
1777 OSDynamicCast( OSCollection, ptable->getObject( key ));
1778
1779 if( coll) {
1780 // Yup so mark it as immutable
1781 coll->setOptions( OSCollection::kMASK,
1782 OSCollection::kImmutable );
1783 }
1784 }
1785 iter->release();
1786 }
1787
1788 PUNLOCK;
1789
1790 if( needParent)
1791 ret &= parent->attachToChild( this, plane );
1792
1793 return( ret );
1794}
1795
1796uint64_t IORegistryEntry::getRegistryEntryID( void )
1797{
1798 if (reserved)
1799 return (reserved->fRegistryEntryID);
1800 else
1801 return (0);
1802}
1803
1804bool IORegistryEntry::attachToChild( IORegistryEntry * child,
1805 const IORegistryPlane * plane )
1806{
1807 OSArray * links;
1808 bool ret;
1809 bool needChild;
1810
1811 if( this == child)
1812 return( false );
1813
1814 WLOCK;
1815
1816 ret = makeLink( child, kChildSetIndex, plane );
1817
1818 if( (links = child->getParentSetReference( plane )))
1819 needChild = (false == arrayMember( links, this ));
1820 else
1821 needChild = true;
1822
1823 UNLOCK;
1824
1825 if( needChild)
1826 ret &= child->attachToParent( this, plane );
1827
1828 return( ret );
1829}
1830
1831void IORegistryEntry::detachFromParent( IORegistryEntry * parent,
1832 const IORegistryPlane * plane )
1833{
1834 OSArray * links;
1835 bool needParent;
1836
1837 WLOCK;
1838
1839 parent->retain();
1840
1841 breakLink( parent, kParentSetIndex, plane );
1842
1843 if( (links = parent->getChildSetReference( plane )))
1844 needParent = arrayMember( links, this );
1845 else
1846 needParent = false;
1847
1848// parent->breakLink( this, kChildSetIndex, plane );
1849
1850 UNLOCK;
1851
1852 if( needParent)
1853 parent->detachFromChild( this, plane );
1854
1855 parent->release();
1856}
1857
1858void IORegistryEntry::detachFromChild( IORegistryEntry * child,
1859 const IORegistryPlane * plane )
1860{
1861 OSArray * links;
1862 bool needChild;
1863
1864 WLOCK;
1865
1866 child->retain();
1867
1868 breakLink( child, kChildSetIndex, plane );
1869
1870 if( (links = child->getParentSetReference( plane )))
1871 needChild = arrayMember( links, this );
1872 else
1873 needChild = false;
1874
1875 UNLOCK;
1876
1877 if( needChild)
1878 child->detachFromParent( this, plane );
1879
1880 child->release();
1881}
1882
1883void IORegistryEntry::detachAbove( const IORegistryPlane * plane )
1884{
1885 IORegistryEntry * parent;
1886
1887 retain();
1888 while( (parent = copyParentEntry( plane )))
1889 {
1890 detachFromParent( parent, plane );
1891 parent->release();
1892 }
1893 release();
1894}
1895
1896void IORegistryEntry::detachAll( const IORegistryPlane * plane )
1897{
1898 OSOrderedSet * all;
1899 IORegistryEntry * next;
1900 IORegistryIterator * regIter;
1901
1902 regIter = IORegistryIterator::iterateOver( this, plane, true );
1903 if( 0 == regIter)
1904 return;
1905 all = regIter->iterateAll();
1906 regIter->release();
1907
1908 detachAbove( plane );
1909 if( all) {
1910 while( (next = (IORegistryEntry *) all->getLastObject())) {
1911
1912 next->retain();
1913 all->removeObject(next);
1914
1915 next->detachAbove( plane );
1916 next->release();
1917 }
1918 all->release();
1919 }
1920}
1921
1922unsigned int IORegistryEntry::getDepth( const IORegistryPlane * plane ) const
1923{
1924 unsigned int depth = 1;
1925 OSArray * parents;
1926 unsigned int oneDepth, maxParentDepth, count;
1927 IORegistryEntry * one;
1928 const IORegistryEntry * next;
1929 unsigned int index;
1930
1931 RLOCK;
1932
1933 next = this;
1934 while( (parents = next->getParentSetReference( plane ))) {
1935
1936 count = parents->getCount();
1937 if( 0 == count)
1938 break;
1939 if( 1 == count) {
1940 depth++;
1941 next = (IORegistryEntry *) parents->getObject( 0 );
1942 } else {
1943 // painful
1944 maxParentDepth = 0;
1945 for( index = 0;
1946 (one = (IORegistryEntry *) parents->getObject( index ));
1947 index++ ) {
1948 oneDepth = one->getDepth( plane );
1949 if( oneDepth > maxParentDepth)
1950 maxParentDepth = oneDepth;
1951 }
1952 depth += maxParentDepth;
1953 break;
1954 }
1955 }
1956
1957 UNLOCK;
1958
1959 return( depth);
1960}
1961
1962/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1963
1964#undef super
1965#define super OSIterator
1966
1967OSDefineMetaClassAndStructors(IORegistryIterator, OSIterator)
1968
1969enum { kIORegistryIteratorInvalidFlag = 0x80000000 };
1970
1971/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1972
1973IORegistryIterator *
1974IORegistryIterator::iterateOver( IORegistryEntry * root,
1975 const IORegistryPlane * plane,
1976 IOOptionBits options )
1977{
1978 IORegistryIterator * create;
1979
1980 if( 0 == root)
1981 return( 0);
1982 if( 0 == plane)
1983 return( 0);
1984
1985 create = new IORegistryIterator;
1986 if( create) {
1987 if( create->init()) {
1988
1989 root->retain();
1990 create->root = root;
1991 create->where = &create->start;
1992 create->start.current = root;
1993 create->plane = plane;
1994 create->options = options & ~kIORegistryIteratorInvalidFlag;
1995
1996 } else {
1997 create->release();
1998 create = 0;
1999 }
2000 }
2001 return( create);
2002}
2003
2004IORegistryIterator *
2005IORegistryIterator::iterateOver( const IORegistryPlane * plane,
2006 IOOptionBits options )
2007{
2008 return( iterateOver( gRegistryRoot, plane, options ));
2009}
2010
2011bool IORegistryIterator::isValid( void )
2012{
2013 bool ok;
2014 IORegCursor * next;
2015
2016 next = where;
2017
2018 RLOCK;
2019
2020 ok = (0 == (kIORegistryIteratorInvalidFlag & options));
2021
2022 while( ok && next) {
2023 if( where->iter)
2024 ok = where->iter->isValid();
2025 next = next->next;
2026 }
2027 UNLOCK;
2028
2029 return( ok);
2030}
2031
2032void IORegistryIterator::enterEntry( const IORegistryPlane * enterPlane )
2033{
2034 IORegCursor * prev;
2035
2036 prev = where;
2037 where = (IORegCursor *) IOMalloc( sizeof(IORegCursor));
2038 assert( where);
2039
2040 if( where) {
2041 where->iter = 0;
2042 where->next = prev;
2043 where->current = prev->current;
2044 plane = enterPlane;
2045 }
2046}
2047
2048void IORegistryIterator::enterEntry( void )
2049{
2050 enterEntry( plane );
2051}
2052
2053bool IORegistryIterator::exitEntry( void )
2054{
2055 IORegCursor * gone;
2056
2057 if( where->iter) {
2058 where->iter->release();
2059 where->iter = 0;
2060 if( where->current)// && (where != &start))
2061 where->current->release();
2062 }
2063
2064 if( where != &start) {
2065 gone = where;
2066 where = gone->next;
2067 IOFree( gone, sizeof(IORegCursor));
2068 return( true);
2069
2070 } else
2071 return( false);
2072}
2073
2074void IORegistryIterator::reset( void )
2075{
2076 while( exitEntry())
2077 {}
2078
2079 if( done) {
2080 done->release();
2081 done = 0;
2082 }
2083
2084 where->current = root;
2085 options &= ~kIORegistryIteratorInvalidFlag;
2086}
2087
2088void IORegistryIterator::free( void )
2089{
2090 reset();
2091
2092 if( root)
2093 root->release();
2094
2095 super::free();
2096}
2097
2098
2099IORegistryEntry * IORegistryIterator::getNextObjectFlat( void )
2100{
2101 IORegistryEntry * next = 0;
2102 OSArray * links = 0;
2103
2104 RLOCK;
2105
2106 if( (0 == where->iter)) {
2107 // just entered - create new iter
2108 if( isValid()
2109 && where->current
2110 && (links = ( (options & kIORegistryIterateParents) ?
2111 where->current->getParentSetReference( plane ) :
2112 where->current->getChildSetReference( plane ) )) )
2113
2114 where->iter = OSCollectionIterator::withCollection( links );
2115
2116 } else
2117 // next sibling - release current
2118 if( where->current)
2119 where->current->release();
2120
2121 if( where->iter) {
2122
2123 next = (IORegistryEntry *) where->iter->getNextObject();
2124
2125 if( next)
2126 next->retain();
2127 else if( !where->iter->isValid())
2128 options |= kIORegistryIteratorInvalidFlag;
2129 }
2130
2131 where->current = next;
2132
2133 UNLOCK;
2134
2135 return( next);
2136}
2137
2138IORegistryEntry * IORegistryIterator::getNextObjectRecursive( void )
2139{
2140 IORegistryEntry * next;
2141
2142 do
2143 next = getNextObjectFlat();
2144 while( (0 == next) && exitEntry());
2145
2146 if( next) {
2147 if( 0 == done)
2148 done = OSOrderedSet::withCapacity( 10 );
2149 if( done->setObject((OSObject *) next)) {
2150 // done set didn't contain this one, so recurse
2151 enterEntry();
2152 }
2153 }
2154 return( next);
2155}
2156
2157IORegistryEntry * IORegistryIterator::getNextObject( void )
2158{
2159 if( options & kIORegistryIterateRecursively)
2160 return( getNextObjectRecursive());
2161 else
2162 return( getNextObjectFlat());
2163}
2164
2165IORegistryEntry * IORegistryIterator::getCurrentEntry( void )
2166{
2167 if( isValid())
2168 return( where->current);
2169 else
2170 return( 0);
2171}
2172
2173OSOrderedSet * IORegistryIterator::iterateAll( void )
2174{
2175 reset();
2176 while( getNextObjectRecursive())
2177 {}
2178 if( done)
2179 done->retain();
2180 return( done);
2181}
2182
2183#if __LP64__
2184OSMetaClassDefineReservedUnused(IORegistryEntry, 0);
2185OSMetaClassDefineReservedUnused(IORegistryEntry, 1);
2186OSMetaClassDefineReservedUnused(IORegistryEntry, 2);
2187OSMetaClassDefineReservedUnused(IORegistryEntry, 3);
2188OSMetaClassDefineReservedUnused(IORegistryEntry, 4);
2189OSMetaClassDefineReservedUnused(IORegistryEntry, 5);
2190#else
2191OSMetaClassDefineReservedUsed(IORegistryEntry, 0);
2192OSMetaClassDefineReservedUsed(IORegistryEntry, 1);
2193OSMetaClassDefineReservedUsed(IORegistryEntry, 2);
2194OSMetaClassDefineReservedUsed(IORegistryEntry, 3);
2195OSMetaClassDefineReservedUsed(IORegistryEntry, 4);
2196OSMetaClassDefineReservedUsed(IORegistryEntry, 5);
2197#endif
2198OSMetaClassDefineReservedUnused(IORegistryEntry, 6);
2199OSMetaClassDefineReservedUnused(IORegistryEntry, 7);
2200OSMetaClassDefineReservedUnused(IORegistryEntry, 8);
2201OSMetaClassDefineReservedUnused(IORegistryEntry, 9);
2202OSMetaClassDefineReservedUnused(IORegistryEntry, 10);
2203OSMetaClassDefineReservedUnused(IORegistryEntry, 11);
2204OSMetaClassDefineReservedUnused(IORegistryEntry, 12);
2205OSMetaClassDefineReservedUnused(IORegistryEntry, 13);
2206OSMetaClassDefineReservedUnused(IORegistryEntry, 14);
2207OSMetaClassDefineReservedUnused(IORegistryEntry, 15);
2208OSMetaClassDefineReservedUnused(IORegistryEntry, 16);
2209OSMetaClassDefineReservedUnused(IORegistryEntry, 17);
2210OSMetaClassDefineReservedUnused(IORegistryEntry, 18);
2211OSMetaClassDefineReservedUnused(IORegistryEntry, 19);
2212OSMetaClassDefineReservedUnused(IORegistryEntry, 20);
2213OSMetaClassDefineReservedUnused(IORegistryEntry, 21);
2214OSMetaClassDefineReservedUnused(IORegistryEntry, 22);
2215OSMetaClassDefineReservedUnused(IORegistryEntry, 23);
2216OSMetaClassDefineReservedUnused(IORegistryEntry, 24);
2217OSMetaClassDefineReservedUnused(IORegistryEntry, 25);
2218OSMetaClassDefineReservedUnused(IORegistryEntry, 26);
2219OSMetaClassDefineReservedUnused(IORegistryEntry, 27);
2220OSMetaClassDefineReservedUnused(IORegistryEntry, 28);
2221OSMetaClassDefineReservedUnused(IORegistryEntry, 29);
2222OSMetaClassDefineReservedUnused(IORegistryEntry, 30);
2223OSMetaClassDefineReservedUnused(IORegistryEntry, 31);
2224
2225/* inline function implementation */
2226OSDictionary * IORegistryEntry::getPropertyTable( void ) const
2227{ return(fPropertyTable); }
2228