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