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