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