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