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