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