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