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