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