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