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