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