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