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