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