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