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