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