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