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