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