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