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