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