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