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