]> git.saurik.com Git - apple/xnu.git/blobdiff - iokit/Kernel/IORegistryEntry.cpp
xnu-3247.1.106.tar.gz
[apple/xnu.git] / iokit / Kernel / IORegistryEntry.cpp
index bb72bda03651e62e4df6ab86f87a384c9e00cbb6..1d9cf8f9d6314ca11eff3bd0649da55eb0a563d0 100644 (file)
@@ -1,23 +1,29 @@
 /*
- * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved.
+ * Copyright (c) 1998-2006 Apple Computer, Inc. All rights reserved.
  *
- * @APPLE_LICENSE_HEADER_START@
+ * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
  * 
- * The contents of this file constitute Original Code as defined in and
- * are subject to the Apple Public Source License Version 1.1 (the
- * "License").  You may not use this file except in compliance with the
- * License.  Please obtain a copy of the License at
- * http://www.apple.com/publicsource and read it before using this file.
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. The rights granted to you under the License
+ * may not be used to create, or enable the creation or redistribution of,
+ * unlawful or unlicensed copies of an Apple operating system, or to
+ * circumvent, violate, or enable the circumvention or violation of, any
+ * terms of an Apple operating system software license agreement.
  * 
- * This Original Code and all software distributed under the License are
- * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
- * License for the specific language governing rights and limitations
- * under the License.
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
  * 
- * @APPLE_LICENSE_HEADER_END@
+ * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
  */
 /*
  * Copyright (c) 1998 Apple Computer, Inc.  All rights reserved. 
@@ -44,11 +50,24 @@ OSDefineMetaClassAndStructors(IORegistryEntry, OSObject)
 
 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
 
+#define kIORegPlaneParentSuffix                "ParentLinks"
+#define kIORegPlaneChildSuffix         "ChildLinks"
+#define kIORegPlaneNameSuffix          "Name"
+#define kIORegPlaneLocationSuffix      "Location"
+
+#define kIORegPlaneParentSuffixLen     (sizeof(kIORegPlaneParentSuffix) - 1)
+#define kIORegPlaneChildSuffixLen      (sizeof(kIORegPlaneChildSuffix) - 1)
+#define kIORegPlaneNameSuffixLen       (sizeof(kIORegPlaneNameSuffix) - 1)
+#define kIORegPlaneLocationSuffixLen   (sizeof(kIORegPlaneLocationSuffix) - 1)
+
+#define KASLR_IOREG_DEBUG 0
+
 static IORegistryEntry * gRegistryRoot;
 static OSDictionary *   gIORegistryPlanes;
 
 const OSSymbol *       gIONameKey;
 const OSSymbol *       gIOLocationKey;
+const OSSymbol *       gIORegistryEntryIDKey;
 
 enum {
     kParentSetIndex    = 0,
@@ -59,9 +78,13 @@ enum {
     kIOMaxPlaneName    = 32
 };
 
+enum { kIORegistryIDReserved = (1ULL << 32) + 255 };
+
+static uint64_t gIORegistryLastID = kIORegistryIDReserved;
+
 class IORegistryPlane : public OSObject {
 
-    friend IORegistryEntry;
+    friend class IORegistryEntry;
 
     OSDeclareAbstractStructors(IORegistryPlane)
 
@@ -72,7 +95,7 @@ class IORegistryPlane : public OSObject {
     int                        reserved[2];
 
 public:
-    virtual bool serialize(OSSerialize *s) const;
+    virtual bool serialize(OSSerialize *s) const APPLE_KEXT_OVERRIDE;
 };
 
 OSDefineMetaClassAndStructors(IORegistryPlane, OSObject)
@@ -81,9 +104,9 @@ OSDefineMetaClassAndStructors(IORegistryPlane, OSObject)
 static IORecursiveLock *       gPropertiesLock;
 static SInt32                  gIORegistryGenerationCount;
 
-#define UNLOCK s_lock_done( &gIORegistryLock )
-#define RLOCK  s_lock_read( &gIORegistryLock )
-#define WLOCK  s_lock_write( &gIORegistryLock );       \
+#define UNLOCK lck_rw_done( &gIORegistryLock )
+#define RLOCK  lck_rw_lock_shared( &gIORegistryLock )
+#define WLOCK  lck_rw_lock_exclusive( &gIORegistryLock );      \
                gIORegistryGenerationCount++
                // make atomic
 
@@ -98,172 +121,15 @@ static SInt32                     gIORegistryGenerationCount;
 #define registryTable()        fPropertyTable
 #endif
 
-/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
-
-struct s_lock_t {
-       decl_simple_lock_data(,interlock) /* "hardware" interlock field */
-       volatile unsigned int
-               read_count:16,  /* No. of accepted readers */
-               want_upgrade:1, /* Read-to-write upgrade waiting */
-               want_write:1,   /* Writer is waiting, or
-                                  locked for write */
-               waiting:1,      /* Someone is sleeping on lock */
-               can_sleep:1;    /* Can attempts to lock go to sleep? */
-};
-
-static struct s_lock_t gIORegistryLock;
-
-/* Time we loop without holding the interlock. 
- * The former is for when we cannot sleep, the latter
- * for when our thread can go to sleep (loop less)
- * we shouldn't retake the interlock at all frequently
- * if we cannot go to sleep, since it interferes with
- * any other processors. In particular, 100 is too small
- * a number for powerpc MP systems because of cache
- * coherency issues and differing lock fetch times between
- * the processors
- */
-static unsigned int lock_wait_time[2] = { (unsigned int)-1, 100 } ;
-         
-static void
-s_lock_init(
-       s_lock_t        *l,
-       boolean_t       can_sleep)
-{
-       (void) memset((void *) l, 0, sizeof(s_lock_t));
-
-       simple_lock_init(&l->interlock, 0);
-       l->want_write = FALSE;
-       l->want_upgrade = FALSE;
-       l->read_count = 0;
-       l->can_sleep = can_sleep;
-}
-
-static void
-s_lock_write(
-       register s_lock_t       * l)
-{
-        register int      i;
-
-       simple_lock(&l->interlock);
+#define DEBUG_FREE     1
 
-       /*
-        *      Try to acquire the want_write bit.
-        */
-       while (l->want_write) {
-
-               i = lock_wait_time[l->can_sleep ? 1 : 0];
-               if (i != 0) {
-                       simple_unlock(&l->interlock);
-                       while (--i != 0 && l->want_write)
-                               continue;
-                       simple_lock(&l->interlock);
-               }
-
-               if (l->can_sleep && l->want_write) {
-                       l->waiting = TRUE;
-                       thread_sleep_simple_lock((event_t) l,
-                                       simple_lock_addr(l->interlock), FALSE);
-                       simple_lock(&l->interlock);
-               }
-       }
-       l->want_write = TRUE;
-
-       /* Wait for readers (and upgrades) to finish */
-
-       while ((l->read_count != 0) || l->want_upgrade) {
-
-               i = lock_wait_time[l->can_sleep ? 1 : 0];
-               if (i != 0) {
-                       simple_unlock(&l->interlock);
-                       while (--i != 0 && (l->read_count != 0 ||
-                                           l->want_upgrade))
-                               continue;
-                       simple_lock(&l->interlock);
-               }
-
-               if (l->can_sleep && (l->read_count != 0 || l->want_upgrade)) {
-                       l->waiting = TRUE;
-                       thread_sleep_simple_lock((event_t) l,
-                               simple_lock_addr(l->interlock), FALSE);
-                       simple_lock(&l->interlock);
-               }
-       }
-
-       simple_unlock(&l->interlock);
-}
-
-static void
-s_lock_done(
-       register s_lock_t       * l)
-{
-       boolean_t         do_wakeup = FALSE;
-
-       simple_lock(&l->interlock);
-
-       if (l->read_count != 0) {
-               l->read_count -= 1;
-       }
-       else    {
-               if (l->want_upgrade) {
-                       l->want_upgrade = FALSE;
-               }
-                else {
-                        l->want_write = FALSE;
-                }
-        }
-
-       /*
-        *      There is no reason to wakeup a waiting thread
-        *      if the read-count is non-zero.  Consider:
-        *              we must be dropping a read lock
-        *              threads are waiting only if one wants a write lock
-        *              if there are still readers, they can't proceed
-        */
-       if (l->waiting && (l->read_count == 0)) {
-               l->waiting = FALSE;
-               do_wakeup = TRUE;
-       }
-
-       simple_unlock(&l->interlock);
-
-       if (do_wakeup)
-               thread_wakeup((event_t) l);
-}
-
-static void
-s_lock_read(
-       register s_lock_t       * l)
-{
-       register int        i;
-
-       simple_lock(&l->interlock);
-
-       while ( l->want_upgrade || ((0 == l->read_count) && l->want_write )) {
-
-               i = lock_wait_time[l->can_sleep ? 1 : 0];
-
-               if (i != 0) {
-                       simple_unlock(&l->interlock);
-                       while (--i != 0 && 
-                            (l->want_upgrade || ((0 == l->read_count) && l->want_write )))
-                               continue;
-                       simple_lock(&l->interlock);
-               }
-
-               if (l->can_sleep &&
-                    (l->want_upgrade || ((0 == l->read_count) && l->want_write ))) {
-                       l->waiting = TRUE;
-                       thread_sleep_simple_lock((event_t) l,
-                                       simple_lock_addr(l->interlock), FALSE);
-                       simple_lock(&l->interlock);
-               }
-       }
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
 
-       l->read_count += 1;
-       simple_unlock(&l->interlock);
+lck_rw_t       gIORegistryLock;
+lck_grp_t       *gIORegistryLockGrp;
+lck_grp_attr_t  *gIORegistryLockGrpAttr;
+lck_attr_t      *gIORegistryLockAttr;
 
-}
 
 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
 
@@ -273,7 +139,15 @@ IORegistryEntry * IORegistryEntry::initialize( void )
 
     if( !gRegistryRoot) {
 
-        s_lock_init( &gIORegistryLock, true );
+
+       gIORegistryLockGrpAttr = lck_grp_attr_alloc_init();
+       //lck_grp_attr_setstat(gIORegistryLockGrpAttr);
+       gIORegistryLockGrp = lck_grp_alloc_init("IORegistryLock",  gIORegistryLockGrpAttr);
+       gIORegistryLockAttr = lck_attr_alloc_init();
+       lck_attr_rw_shared_priority(gIORegistryLockAttr);
+       //lck_attr_setdebug(gIORegistryLockAttr);
+       lck_rw_init( &gIORegistryLock, gIORegistryLockGrp, gIORegistryLockAttr);
+
        gRegistryRoot = new IORegistryEntry;
        gPropertiesLock = IORecursiveLockAlloc();
        gIORegistryPlanes = OSDictionary::withCapacity( 1 );
@@ -282,8 +156,12 @@ IORegistryEntry * IORegistryEntry::initialize( void )
                && gIORegistryPlanes );
         ok = gRegistryRoot->init();
 
+       if (ok)
+           gRegistryRoot->reserved->fRegistryEntryID = ++gIORegistryLastID;
+
        gIONameKey = OSSymbol::withCStringNoCopy( "IOName" );
        gIOLocationKey = OSSymbol::withCStringNoCopy( "IOLocation" );
+       gIORegistryEntryIDKey = OSSymbol::withCStringNoCopy( kIORegistryEntryIDKey );
 
        assert( ok && gIONameKey && gIOLocationKey );
 
@@ -316,22 +194,21 @@ const IORegistryPlane * IORegistryEntry::makePlane( const char * name )
     char               key[ kIOMaxPlaneName + 16 ];
     char *             end;
 
-    strncpy( key, name, kIOMaxPlaneName );
-    key[ kIOMaxPlaneName ] = 0;
-    end = key + strlen( name );
+    strlcpy( key, name, kIOMaxPlaneName + 1 );
+    end = key + strlen( key );
 
     nameKey = OSSymbol::withCString( key);
 
-    strcpy( end, "ParentLinks" );
+    strlcpy( end, kIORegPlaneParentSuffix, kIORegPlaneParentSuffixLen + 1 );
     parentKey = OSSymbol::withCString( key);
 
-    strcpy( end, "ChildLinks" );
+    strlcpy( end, kIORegPlaneChildSuffix, kIORegPlaneChildSuffixLen + 1 );
     childKey = OSSymbol::withCString( key);
 
-    strcpy( end, "Name" );
+    strlcpy( end, kIORegPlaneNameSuffix, kIORegPlaneNameSuffixLen + 1 );
     pathNameKey = OSSymbol::withCString( key);
 
-    strcpy( end, "Location" );
+    strlcpy( end, kIORegPlaneLocationSuffix, kIORegPlaneLocationSuffixLen + 1 );
     pathLocationKey = OSSymbol::withCString( key);
 
     plane = new IORegistryPlane;
@@ -388,18 +265,32 @@ bool IORegistryPlane::serialize(OSSerialize *s) const
 
 enum { kIORegCapacityIncrement = 4 };
 
-bool IORegistryEntry::init( OSDictionary * dict = 0 )
+bool IORegistryEntry::init( OSDictionary * dict )
 {
     OSString * prop;
 
     if( !super::init())
        return( false);
 
+    if (!reserved)
+    {
+       reserved = IONew(ExpansionData, 1);
+       if (!reserved)
+           return (false);
+       bzero(reserved, sizeof(ExpansionData));
+    }
     if( dict) {
-       dict->retain();
+       if (OSCollection::kImmutable & dict->setOptions(0, 0)) {
+           dict = (OSDictionary *) dict->copyCollection();
+           if (!dict)
+               return (false);
+       } else
+           dict->retain();
+       if( fPropertyTable)
+           fPropertyTable->release();
        fPropertyTable = dict;
 
-    } else {
+    } else if( !fPropertyTable) {
         fPropertyTable = OSDictionary::withCapacity( kIORegCapacityIncrement );
        if( fPropertyTable)
             fPropertyTable->setCapacityIncrement( kIORegCapacityIncrement );
@@ -409,9 +300,11 @@ bool IORegistryEntry::init( OSDictionary * dict = 0 )
         return( false);
 
 #ifdef IOREGSPLITTABLES
-    fRegistryTable = OSDictionary::withCapacity( kIORegCapacityIncrement );
-    if( fRegistryTable)
-        fRegistryTable->setCapacityIncrement( kIORegCapacityIncrement );
+    if( !fRegistryTable) {
+       fRegistryTable = OSDictionary::withCapacity( kIORegCapacityIncrement );
+       if( fRegistryTable)
+           fRegistryTable->setCapacityIncrement( kIORegCapacityIncrement );
+    }
 
     if( (prop = OSDynamicCast( OSString, getProperty( gIONameKey)))) {
         OSSymbol * sym = (OSSymbol *)OSSymbol::withString( prop);
@@ -437,13 +330,19 @@ bool IORegistryEntry::init( IORegistryEntry * old,
 
     WLOCK;
 
+    reserved = old->reserved;
+    old->reserved = NULL;
+
     fPropertyTable = old->getPropertyTable();
-    old->fPropertyTable = 0;
+    fPropertyTable->retain();
 #ifdef IOREGSPLITTABLES
     fRegistryTable = old->fRegistryTable;
-    old->fRegistryTable = 0;
+    old->fRegistryTable = (OSDictionary *) fRegistryTable->copyCollection();
 #endif /* IOREGSPLITTABLES */
 
+    old->registryTable()->removeObject( plane->keys[ kParentSetIndex ] );
+    old->registryTable()->removeObject( plane->keys[ kChildSetIndex ] );
+
     all = getParentSetReference( plane );
     if( all) for( index = 0;
               (next = (IORegistryEntry *) all->getObject(index));
@@ -467,29 +366,11 @@ bool IORegistryEntry::init( IORegistryEntry * old,
 
 void IORegistryEntry::free( void )
 {
-
-#ifdef DEBUG
-    OSArray *                  links;
-    const OSSymbol *           key;
-    const IORegistryPlane *    plane;
-    OSCollectionIterator *     iter;
-
-    if( registryTable()) {
-        iter = OSCollectionIterator::withCollection( gIORegistryPlanes );
-        if( iter) {
-            while( (key = (const OSSymbol *) iter->getNextObject())) {
-                if( 0 == (plane = (const IORegistryPlane *)
-                       OSDynamicCast( IORegistryPlane,
-                                 gIORegistryPlanes->getObject( key ))))
-                   continue;
-                if( (links = getParentSetReference( plane ))
-                 || (links = getChildSetReference( plane )) ) {
-
-                    IOLog("%s: Still attached in %s at free()\n",
-                               getName(), plane->nameKey->getCStringNoCopy());
-               }
-            }
-            iter->release();
+#if DEBUG_FREE
+    if( registryTable() && gIOServicePlane) {
+        if( getParentSetReference( gIOServicePlane )
+            || getChildSetReference( gIOServicePlane )) {
+            panic("%s: attached at free()", getName());
         }
     }
 #endif
@@ -502,6 +383,9 @@ void IORegistryEntry::free( void )
         registryTable()->release();
 #endif /* IOREGSPLITTABLES */
 
+    if (reserved)
+       IODelete(reserved, ExpansionData, 1);
+
     super::free();
 }
 
@@ -518,27 +402,14 @@ void IORegistryEntry::setPropertyTable( OSDictionary * dict )
 
 /* Wrappers to synchronize property table */
 
-#define wrap1(func,type,constant)                                      \
-OSObject *                                                             \
-IORegistryEntry::func ## Property( type * aKey) constant               \
-{                                                                      \
-    OSObject * obj;                                                    \
-                                                                       \
-    PLOCK;                                                             \
-    obj = getPropertyTable()->func ## Object( aKey );                  \
-    PUNLOCK;                                                           \
-                                                                       \
-    return( obj );                                                     \
-}
-
-#define wrap2(type,constant)                                           \
+#define wrap2(type, constant)                                          \
 OSObject *                                                             \
 IORegistryEntry::copyProperty( type * aKey) constant                   \
 {                                                                      \
     OSObject * obj;                                                    \
                                                                        \
     PLOCK;                                                             \
-    obj = getPropertyTable()->getObject( aKey );                       \
+    obj = getProperty( aKey );                                         \
     if( obj)                                                           \
         obj->retain();                                                 \
     PUNLOCK;                                                           \
@@ -546,15 +417,6 @@ IORegistryEntry::copyProperty( type * aKey) constant                       \
     return( obj );                                                     \
 }
 
-#define wrap3(func,type,constant)                                      \
-void                                                                   \
-IORegistryEntry::func ## Property( type * aKey) constant               \
-{                                                                      \
-    PLOCK;                                                             \
-    getPropertyTable()->func ## Object( aKey );                                \
-    PUNLOCK;                                                           \
-}
-
 #define wrap4(type,constant) \
 OSObject * \
 IORegistryEntry::getProperty( type *                  aKey, \
@@ -563,15 +425,41 @@ IORegistryEntry::getProperty( type *                  aKey, \
 { \
     OSObject * obj = getProperty( aKey ); \
     \
-    if ( (0 == obj) && (options & kIORegistryIterateRecursively) ) { \
+    if ( (0 == obj) && plane && (options & kIORegistryIterateRecursively) ) { \
+        IORegistryEntry * entry = (IORegistryEntry *) this; \
+        IORegistryIterator * iter; \
+        iter = IORegistryIterator::iterateOver( entry, plane, options ); \
+        \
+        if(iter) { \
+            while ( (0 == obj) && (entry = iter->getNextObject()) ) { \
+                obj = entry->getProperty( aKey ); \
+            } \
+            iter->release(); \
+        } \
+    } \
+    \
+    return( obj ); \
+}
+
+#define wrap5(type,constant) \
+OSObject * \
+IORegistryEntry::copyProperty( type *                  aKey, \
+                              const IORegistryPlane * plane, \
+                              IOOptionBits            options ) constant \
+{ \
+    OSObject * obj = copyProperty( aKey ); \
+    \
+    if ( (0 == obj) && plane && (options & kIORegistryIterateRecursively) ) { \
         IORegistryEntry * entry = (IORegistryEntry *) this; \
         IORegistryIterator * iter; \
         iter = IORegistryIterator::iterateOver( entry, plane, options ); \
         \
-        while ( (0 == obj) && (entry = iter->getNextObject()) ) { \
-            obj = entry->getProperty( aKey ); \
+        if(iter) { \
+            while ( (0 == obj) && (entry = iter->getNextObject()) ) { \
+                obj = entry->copyProperty( aKey ); \
+            } \
+            iter->release(); \
         } \
-        iter->release(); \
     } \
     \
     return( obj ); \
@@ -579,14 +467,14 @@ IORegistryEntry::getProperty( type *                  aKey, \
 
 bool IORegistryEntry::serializeProperties( OSSerialize * s ) const
 {
-    bool ok;
-
 //    setProperty( getRetainCount(), 32, "__retain" );
 
     PLOCK;
-    ok = getPropertyTable()->serialize( s );
+    OSCollection *snapshotProperties = getPropertyTable()->copyCollection();
     PUNLOCK;
 
+    bool ok =  snapshotProperties->serialize( s );
+    snapshotProperties->release();
     return( ok );
 }
 
@@ -607,52 +495,148 @@ IOReturn IORegistryEntry::setProperties( OSObject * properties )
     return( kIOReturnUnsupported );
 }
 
-wrap1(get, const OSSymbol, const)  // getProperty() definition
-wrap1(get, const OSString, const)  // getProperty() definition
-wrap1(get, const char, const)      // getProperty() definition
-
 wrap2(const OSSymbol, const)       // copyProperty() definition
 wrap2(const OSString, const)       // copyProperty() definition
 wrap2(const char, const)          // copyProperty() definition
 
-wrap3(remove, const OSSymbol,)     // removeProperty() definition
-wrap3(remove, const OSString,)     // removeProperty() definition
-wrap3(remove, const char,)         // removeProperty() definition
-
 wrap4(const OSSymbol, const)       // getProperty() w/plane definition
 wrap4(const OSString, const)       // getProperty() w/plane definition
 wrap4(const char, const)           // getProperty() w/plane definition
 
+wrap5(const OSSymbol, const)       // copyProperty() w/plane definition
+wrap5(const OSString, const)       // copyProperty() w/plane definition
+wrap5(const char, const)           // copyProperty() w/plane definition
+
+
+OSObject *
+IORegistryEntry::getProperty( const OSSymbol * aKey) const
+{
+    OSObject * obj;
+
+    PLOCK;
+    obj = getPropertyTable()->getObject( aKey );
+    PUNLOCK;
+
+    return( obj );
+}
+
+void
+IORegistryEntry::removeProperty( const OSSymbol * aKey)
+{
+    PLOCK;
+    getPropertyTable()->removeObject( aKey );
+    PUNLOCK;
+}
+
+#if KASLR_IOREG_DEBUG
+extern "C" {
+    
+bool ScanForAddrInObject(OSObject * theObject, 
+                         int indent);
+    
+}; /* extern "C" */
+#endif
+
 bool
 IORegistryEntry::setProperty( const OSSymbol * aKey, OSObject * anObject)
 {
     bool ret = false;
+
+    // If we are inserting a collection class and the current entry
+    // is attached into the registry (inPlane()) then mark the collection
+    // as immutable.
+    OSCollection *coll = OSDynamicCast(OSCollection, anObject);
+    bool makeImmutable = (coll && inPlane());
+
     PLOCK;
+    if( makeImmutable )
+       coll->setOptions( OSCollection::kMASK, OSCollection::kImmutable );
+
     ret = getPropertyTable()->setObject( aKey, anObject );
     PUNLOCK;
-    
+
+#if KASLR_IOREG_DEBUG
+    if ( anObject && strcmp(kIOKitDiagnosticsKey, aKey->getCStringNoCopy()) != 0 ) {
+        if (ScanForAddrInObject(anObject, 0)) {
+            IOLog("%s: IORegistryEntry name %s with key \"%s\" \n",
+                  __FUNCTION__,
+                  getName(0),
+                  aKey->getCStringNoCopy() );        
+        }
+    }
+#endif
+
     return ret;
 }
 
-bool
-IORegistryEntry::setProperty( const OSString * aKey, OSObject * anObject)
+IOReturn IORegistryEntry::
+runPropertyAction(Action inAction, OSObject *target,
+       void *arg0, void *arg1, void *arg2, void *arg3)
 {
-    bool ret = false;
+    IOReturn res;
+
+    // closeGate is recursive so don't worry if we already hold the lock.
     PLOCK;
-    ret = getPropertyTable()->setObject( aKey, anObject );
+    res = (*inAction)(target, arg0, arg1, arg2, arg3);
     PUNLOCK;
 
+    return res;
+}
+
+OSObject *
+IORegistryEntry::getProperty( const OSString * aKey) const
+{
+    const OSSymbol * tmpKey = OSSymbol::withString( aKey );
+    OSObject * obj = getProperty( tmpKey );
+
+    tmpKey->release();
+    return( obj );
+}
+
+OSObject *
+IORegistryEntry::getProperty( const char * aKey) const
+{
+    const OSSymbol * tmpKey = OSSymbol::withCString( aKey );
+    OSObject * obj = getProperty( tmpKey );
+
+    tmpKey->release();
+    return( obj );
+}
+
+
+void
+IORegistryEntry::removeProperty( const OSString * aKey)
+{
+    const OSSymbol * tmpKey = OSSymbol::withString( aKey );
+    removeProperty( tmpKey );
+    tmpKey->release();
+}
+
+void
+IORegistryEntry::removeProperty( const char * aKey)
+{
+    const OSSymbol * tmpKey = OSSymbol::withCString( aKey );
+    removeProperty( tmpKey );
+    tmpKey->release();
+}
+
+bool
+IORegistryEntry::setProperty( const OSString * aKey, OSObject * anObject)
+{
+    const OSSymbol * tmpKey = OSSymbol::withString( aKey );
+    bool ret = setProperty( tmpKey, anObject );
+
+    tmpKey->release();
     return ret;
 }
 
 bool
 IORegistryEntry::setProperty( const char * aKey,  OSObject * anObject)
 {
-    bool ret = false;
-    PLOCK;
-    ret = getPropertyTable()->setObject( aKey, anObject );
-    PUNLOCK;
-    
+    const OSSymbol * tmpKey = OSSymbol::withCString( aKey );
+    bool ret = setProperty( tmpKey, anObject );
+
+    tmpKey->release();
     return ret;
 }
 
@@ -663,9 +647,10 @@ IORegistryEntry::setProperty(const char * aKey, const char * aString)
     OSSymbol * aSymbol = (OSSymbol *) OSSymbol::withCString( aString );
 
     if( aSymbol) {
-        PLOCK;
-        ret = getPropertyTable()->setObject( aKey, aSymbol );
-        PUNLOCK;
+        const OSSymbol * tmpKey = OSSymbol::withCString( aKey );
+        ret = setProperty( tmpKey, aSymbol );
+
+        tmpKey->release();
         aSymbol->release();
     }
     return( ret );
@@ -678,9 +663,10 @@ IORegistryEntry::setProperty(const char * aKey, bool aBoolean)
     OSBoolean * aBooleanObj = OSBoolean::withBoolean( aBoolean );
 
     if( aBooleanObj) {
-        PLOCK;
-        ret = getPropertyTable()->setObject( aKey, aBooleanObj );
-        PUNLOCK;
+        const OSSymbol * tmpKey = OSSymbol::withCString( aKey );
+        ret = setProperty( tmpKey, aBooleanObj );
+
+        tmpKey->release();
         aBooleanObj->release();
     }
     return( ret );
@@ -695,9 +681,10 @@ IORegistryEntry::setProperty( const char *       aKey,
     OSNumber * anOffset = OSNumber::withNumber( aValue, aNumberOfBits );
 
     if( anOffset) {
-        PLOCK;
-        ret = getPropertyTable()->setObject( aKey, anOffset );
-        PUNLOCK;
+        const OSSymbol * tmpKey = OSSymbol::withCString( aKey );
+        ret = setProperty( tmpKey, anOffset );
+
+        tmpKey->release();
         anOffset->release();
     }
     return( ret );
@@ -712,9 +699,10 @@ IORegistryEntry::setProperty( const char *      aKey,
     OSData * data = OSData::withBytes( bytes, length );
 
     if( data) {
-        PLOCK;
-        ret = getPropertyTable()->setObject( aKey, data );
-        PUNLOCK;
+        const OSSymbol * tmpKey = OSSymbol::withCString( aKey );
+        ret = setProperty( tmpKey, data );
+
+        tmpKey->release();
         data->release();
     }
     return( ret );
@@ -724,7 +712,7 @@ IORegistryEntry::setProperty( const char *      aKey,
 
 /* Name, location, paths */
 
-const char * IORegistryEntry::getName( const IORegistryPlane * plane = 0 ) const
+const char * IORegistryEntry::getName( const IORegistryPlane * plane ) const
 {
     OSSymbol *         sym = 0;
 
@@ -742,7 +730,7 @@ const char * IORegistryEntry::getName( const IORegistryPlane * plane = 0 ) const
 }
 
 const OSSymbol * IORegistryEntry::copyName(
-                       const IORegistryPlane * plane = 0 ) const
+                       const IORegistryPlane * plane ) const
 {
     OSSymbol *         sym = 0;
 
@@ -762,7 +750,7 @@ const OSSymbol * IORegistryEntry::copyName(
 }
 
 const OSSymbol * IORegistryEntry::copyLocation(
-                       const IORegistryPlane * plane = 0 ) const
+                       const IORegistryPlane * plane ) const
 {
     OSSymbol *         sym = 0;
 
@@ -778,7 +766,7 @@ const OSSymbol * IORegistryEntry::copyLocation(
     return( sym );
 }
 
-const char * IORegistryEntry::getLocation( const IORegistryPlane * plane = 0 ) const
+const char * IORegistryEntry::getLocation( const IORegistryPlane * plane ) const
 {
     const OSSymbol *   sym = copyLocation( plane );
     const char *       result = 0;
@@ -792,7 +780,7 @@ const char * IORegistryEntry::getLocation( const IORegistryPlane * plane = 0 ) c
 }
 
 void IORegistryEntry::setName( const OSSymbol * name,
-                            const IORegistryPlane * plane = 0 )
+                            const IORegistryPlane * plane )
 {
     const OSSymbol *   key;
 
@@ -809,7 +797,7 @@ void IORegistryEntry::setName( const OSSymbol * name,
 }
 
 void IORegistryEntry::setName( const char * name,
-                            const IORegistryPlane * plane = 0 )
+                            const IORegistryPlane * plane )
 {
     OSSymbol * sym = (OSSymbol *)OSSymbol::withCString( name );
     if ( sym ) {
@@ -819,7 +807,7 @@ void IORegistryEntry::setName( const char * name,
 }
 
 void IORegistryEntry::setLocation( const OSSymbol * location,
-                            const IORegistryPlane * plane = 0 )
+                            const IORegistryPlane * plane )
 {
     const OSSymbol *   key;
 
@@ -836,7 +824,7 @@ void IORegistryEntry::setLocation( const OSSymbol * location,
 }
 
 void IORegistryEntry::setLocation( const char * location,
-                            const IORegistryPlane * plane = 0 )
+                            const IORegistryPlane * plane )
 {
     OSSymbol * sym = (OSSymbol *)OSSymbol::withCString( location );
     if ( sym ) {
@@ -846,7 +834,7 @@ void IORegistryEntry::setLocation( const char * location,
 }
 
 bool
-IORegistryEntry::compareName( OSString * name, OSString ** matched = 0 ) const
+IORegistryEntry::compareName( OSString * name, OSString ** matched ) const
 {
     const OSSymbol *   sym = copyName();
     bool               isEqual;
@@ -865,7 +853,7 @@ IORegistryEntry::compareName( OSString * name, OSString ** matched = 0 ) const
 }
 
 bool
-IORegistryEntry::compareNames( OSObject * names, OSString ** matched = 0 ) const
+IORegistryEntry::compareNames( OSObject * names, OSString ** matched ) const
 {
     OSString *         string;
     OSCollection *     collection;
@@ -898,10 +886,10 @@ bool IORegistryEntry::getPath(    char * path, int * length,
     OSArray *          stack;
     IORegistryEntry *  root;
     const IORegistryEntry * entry;
-    IORegistryEntry *  parent;
+    const IORegistryEntry * parent;
     const OSSymbol *   alias;
     int                        index;
-    int                        len, maxLength, compLen;
+    int                        len, maxLength, compLen, aliasLen;
     char *             nextComp;
     bool               ok;
 
@@ -915,80 +903,76 @@ bool IORegistryEntry::getPath(    char * path, int * length,
     len = plane->nameKey->getLength();
     if( len >= maxLength)
        return( false);
-    strcpy( nextComp, plane->nameKey->getCStringNoCopy());
+    strlcpy( nextComp, plane->nameKey->getCStringNoCopy(), len + 1);
     nextComp[ len++ ] = ':';
     nextComp += len;
 
     if( (alias = hasAlias( plane ))) {
-       len += alias->getLength();
+       aliasLen = alias->getLength();
+       len += aliasLen;
        ok = (maxLength > len);
        *length = len;
        if( ok)
-           strcpy( nextComp, alias->getCStringNoCopy());
+           strlcpy( nextComp, alias->getCStringNoCopy(), aliasLen + 1);
        return( ok );
     }
 
-    entry = this;
-    parent = entry->getParentEntry( plane );
-    if( !parent)
-       // Error if not attached in plane
-       return( false);
-
     stack = OSArray::withCapacity( getDepth( plane ));
-    if( !stack)
-       return( false);
+    if (!stack) return( false);
 
     RLOCK;
 
+    parent = entry = this;
     root = gRegistryRoot->getChildEntry( plane );
-    while( parent && (entry != root)) {
+    while (parent && (parent != root))
+    {
        // stop below root
-       stack->setObject( (OSObject *) entry );
        entry = parent;
        parent = entry->getParentEntry( plane );
+       stack->setObject( (OSObject *) entry );
     }
 
-    index = stack->getCount();
-    ok = true;
-
-    if( 0 == index) {
+    ok = (0 != parent);
+    if (ok)
+    {
+        index = stack->getCount();
+        if( 0 == index) {
 
-        *nextComp++ = '/';
-        *nextComp = 0;
-        len++;
+            *nextComp++ = '/';
+            *nextComp = 0;
+            len++;
 
-    } else while( ok && ((--index) >= 0)) {
+        } else while( ok && ((--index) >= 0)) {
 
-        entry = (IORegistryEntry *) stack->getObject((unsigned int) index );
-        assert( entry );
+            entry = (IORegistryEntry *) stack->getObject((unsigned int) index );
+            assert( entry );
 
-        if( (alias = entry->hasAlias( plane ))) {
-            len = plane->nameKey->getLength() + 1;
-            nextComp = path + len;
+            if( (alias = entry->hasAlias( plane ))) {
+                len = plane->nameKey->getLength() + 1;
+                nextComp = path + len;
 
-            compLen = alias->getLength();
-            ok = (maxLength > len + compLen);
-            if( ok)
-                strcpy( nextComp, alias->getCStringNoCopy());
-        } else {
-            compLen = maxLength - len;
-            ok = entry->getPathComponent( nextComp + 1, &compLen, plane );
+                compLen = alias->getLength();
+                ok = (maxLength > (len + compLen));
+                if( ok)
+                    strlcpy( nextComp, alias->getCStringNoCopy(), compLen + 1);
+            } else {
+                compLen = maxLength - len;
+                ok = entry->getPathComponent( nextComp + 1, &compLen, plane );
 
-            if( ok && compLen) {
-                compLen++;
-                *nextComp = '/';
+                if( ok && compLen) {
+                    compLen++;
+                    *nextComp = '/';
+                }
             }
-        }
 
-        if( ok) {
-            len += compLen;
-            nextComp += compLen;
+            if( ok) {
+                len += compLen;
+                nextComp += compLen;
+            }
         }
+        *length = len;
     }
-    *length = len;
-
     UNLOCK;
-
     stack->release();
 
     return( ok );
@@ -1011,14 +995,14 @@ bool IORegistryEntry::getPathComponent( char * path, int * length,
     else
        locLen = 0;
 
-    ok = ((len + locLen) < maxLength);
+    ok = ((len + locLen + 1) < maxLength);
     if( ok) {
-        strcpy( path, compName );
+        strlcpy( path, compName, len + 1 );
        if( loc) {
             path += len;
             len += locLen;
             *path++ = '@';
-            strcpy( path, loc );
+            strlcpy( path, loc, locLen );
        }
         *length = len;
     }
@@ -1031,40 +1015,39 @@ const char * IORegistryEntry::matchPathLocation( const char * cmp,
 {
     const char *       str;
     const char *       result = 0;
-    int                        num1, num2;
-    char               c1, c2;
+    u_quad_t           num1, num2;
+    char               lastPathChar, lastLocationChar;
 
     str = getLocation( plane );
     if( str) {
-       c2 = str[0];
+       lastPathChar = cmp[0];
+       lastLocationChar = str[0];
        do {
-            num1 = strtoul( cmp, (char **) &cmp, 16 );
-            if( c2) {
-                num2 = strtoul( str, (char **) &str, 16 );
-                c2 = str[0];
+            if( lastPathChar) {
+                num1 = strtouq( cmp, (char **) &cmp, 16 );
+                lastPathChar = *cmp++;
+           } else
+                num1 = 0;
+
+            if( lastLocationChar) {
+                num2 = strtouq( str, (char **) &str, 16 );
+                lastLocationChar = *str++;
            } else
                 num2 = 0;
 
             if( num1 != num2)
                 break;
 
-            c1 = *cmp++;
-
-            if( (c2 == ':') && (c2 == c1)) {
-                str++;
-                continue;
-            }
-
-            if( ',' != c1) {
+           if (!lastPathChar && !lastLocationChar) {
                 result = cmp - 1;
                 break;
             }
 
-            if( c2) {
-                if( c2 != ',')
-                    break;
-                str++;
-            }
+            if( (',' != lastPathChar) && (':' != lastPathChar))
+               lastPathChar = 0;
+
+           if (lastPathChar && lastLocationChar && (lastPathChar != lastLocationChar))
+                break;
 
         } while( true);
     }
@@ -1080,6 +1063,7 @@ IORegistryEntry * IORegistryEntry::getChildFromComponent( const char ** opath,
     unsigned int       index;
     const char *       path;
     const char *       cmp = 0;
+    char               c;
     size_t             len;
     const char *       str;
 
@@ -1100,8 +1084,12 @@ IORegistryEntry * IORegistryEntry::getChildFromComponent( const char ** opath,
                 if( strncmp( str, cmp, len ))
                     continue;
                 cmp += len;
-                if( *cmp != '@' )
-                break;
+
+                c = *cmp;
+                if( (c == 0) || (c == '/') || (c == ':'))
+                    break;
+                if( c != '@')
+                    continue;
             }
             cmp++;
             if( (cmp = entry->matchPathLocation( cmp, plane )))
@@ -1115,7 +1103,7 @@ IORegistryEntry * IORegistryEntry::getChildFromComponent( const char ** opath,
 }
 
 const OSSymbol * IORegistryEntry::hasAlias( const IORegistryPlane * plane,
-                               char * opath = 0, int * length = 0 ) const
+                               char * opath, int * length ) const
 {
     IORegistryEntry *  entry;
     IORegistryEntry *  entry2;
@@ -1175,8 +1163,7 @@ const char * IORegistryEntry::dealiasPath(
         {}
     end--;
     if( (end - path) < kIOMaxPlaneName) {
-        strncpy( temp, path, end - path );
-        temp[ end - path ] = 0;
+        strlcpy( temp, path, end - path + 1 );
 
         RLOCK;
         entry = IORegistryEntry::fromPath( "/aliases", plane );
@@ -1197,12 +1184,13 @@ const char * IORegistryEntry::dealiasPath(
 
 IORegistryEntry * IORegistryEntry::fromPath(
                         const char *           path,
-                        const IORegistryPlane * plane = 0,
-                        char *                 opath = 0,
-                       int *                   length = 0,
-                        IORegistryEntry *      fromEntry = 0 )
+                        const IORegistryPlane * plane,
+                        char *                 opath,
+                       int *                   length,
+                        IORegistryEntry *      fromEntry )
 {
     IORegistryEntry *  where = 0;
+    IORegistryEntry *  aliasEntry = 0;
     IORegistryEntry *  next;
     const char *       alias;
     const char *       end;
@@ -1218,8 +1206,7 @@ IORegistryEntry * IORegistryEntry::fromPath(
        // get plane name
         end = strchr( path, ':' );
        if( end && ((end - path) < kIOMaxPlaneName)) {
-           strncpy( temp, path, end - path );
-           temp[ end - path ] = 0;
+           strlcpy( temp, path, end - path + 1 );
             plane = getPlane( temp );
            path = end + 1;
        }
@@ -1232,8 +1219,9 @@ IORegistryEntry * IORegistryEntry::fromPath(
     if( (alias = dealiasPath( &end, plane))) {
         if( length)
             len = *length;
-        where = IORegistryEntry::fromPath( alias, plane,
+        aliasEntry = IORegistryEntry::fromPath( alias, plane,
                                     opath, &len, fromEntry );
+        where = aliasEntry;
         if( where)
             path = end;
         else
@@ -1269,10 +1257,10 @@ IORegistryEntry * IORegistryEntry::fromPath(
 
        if( opath && length) {
             // copy out residual path
-           len2 = len + strlen( path );
-           if( len2 < *length)
-                strcpy( opath + len, path );
-           *length = len2;
+           len2 = strlen( path );
+           if( (len + len2) < *length)
+                strlcpy( opath + len, path, len2 + 1 );
+           *length = (len + len2);
 
        } else if( path[0])
            // no residual path => must be no tail for success
@@ -1281,6 +1269,8 @@ IORegistryEntry * IORegistryEntry::fromPath(
 
     if( where)
        where->retain();
+    if( aliasEntry)
+        aliasEntry->release();
 
     UNLOCK;
 
@@ -1289,9 +1279,9 @@ IORegistryEntry * IORegistryEntry::fromPath(
 
 IORegistryEntry * IORegistryEntry::childFromPath(
                        const char *            path,
-                        const IORegistryPlane * plane = 0,
-                        char *                 opath = 0,
-                        int *                  len = 0 )
+                        const IORegistryPlane * plane,
+                        char *                 opath,
+                        int *                  len )
 {
     return( IORegistryEntry::fromPath( path, plane, opath, len, this ));
 }
@@ -1305,7 +1295,7 @@ IORegistryEntry * IORegistryEntry::childFromPath(
 
 inline bool IORegistryEntry::arrayMember( OSArray * set,
                                          const IORegistryEntry * member,
-                                       unsigned int * index = 0 ) const
+                                       unsigned int * index ) const
 {
     int                i;
     OSObject * probeObject;
@@ -1336,7 +1326,7 @@ bool IORegistryEntry::makeLink( IORegistryEntry * to,
 
     } else {
 
-       links = OSArray::withObjects( & (const OSObject *) to, 1, 1 );
+       links = OSArray::withObjects( (const OSObject **) &to, 1, 1 );
        result = (links != 0);
        if( result) {
            result = registryTable()->setObject( plane->keys[ relation ],
@@ -1402,21 +1392,34 @@ OSIterator * IORegistryEntry::getParentIterator(
     return( iter );
 }
 
-IORegistryEntry * IORegistryEntry::getParentEntry( const IORegistryPlane * plane ) const
+IORegistryEntry * IORegistryEntry::copyParentEntry( const IORegistryPlane * plane ) const
 {
     IORegistryEntry *  entry = 0;
     OSArray *          links;
 
     RLOCK;
 
-    if( (links = getParentSetReference( plane )))
+    if( (links = getParentSetReference( plane ))) {
         entry = (IORegistryEntry *) links->getObject( 0 );
+        entry->retain();
+    }
 
     UNLOCK;
 
     return( entry);
 }
 
+IORegistryEntry * IORegistryEntry::getParentEntry( const IORegistryPlane * plane ) const
+{
+    IORegistryEntry * entry;
+
+    entry = copyParentEntry( plane );
+    if( entry)
+        entry->release();
+
+    return( entry );
+}
+
 OSArray * IORegistryEntry::getChildSetReference( const IORegistryPlane * plane ) const
 {
     if( plane)
@@ -1451,7 +1454,7 @@ OSIterator * IORegistryEntry::getChildIterator( const IORegistryPlane * plane )
 }
 
 
-IORegistryEntry * IORegistryEntry::getChildEntry(
+IORegistryEntry * IORegistryEntry::copyChildEntry(
                                const IORegistryPlane * plane ) const
 {
     IORegistryEntry *  entry = 0;
@@ -1459,14 +1462,28 @@ IORegistryEntry * IORegistryEntry::getChildEntry(
 
     RLOCK;
 
-    if( (links = getChildSetReference( plane )))
+    if( (links = getChildSetReference( plane ))) {
        entry = (IORegistryEntry *) links->getObject( 0 );
+        entry->retain();
+    }
 
     UNLOCK;
 
     return( entry);
 }
 
+IORegistryEntry * IORegistryEntry::getChildEntry(
+                               const IORegistryPlane * plane ) const
+{
+    IORegistryEntry * entry;
+
+    entry = copyChildEntry( plane );
+    if( entry)
+        entry->release();
+        
+    return( entry );
+}
+
 void IORegistryEntry::applyToChildren( IORegistryEntryApplierFunction applier,
                                        void * context,
                                        const IORegistryPlane * plane ) const
@@ -1515,7 +1532,7 @@ void IORegistryEntry::applyToParents( IORegistryEntryApplierFunction applier,
 
 bool IORegistryEntry::isChild( IORegistryEntry * child,
                                 const IORegistryPlane * plane,
-                               bool onlyChild = false ) const
+                               bool onlyChild ) const
 {
     OSArray *  links;
     bool       ret = false;
@@ -1536,7 +1553,7 @@ bool IORegistryEntry::isChild( IORegistryEntry * child,
 
 bool IORegistryEntry::isParent( IORegistryEntry * parent,
                                 const IORegistryPlane * plane,
-                               bool onlyParent = false ) const
+                               bool onlyParent ) const
 
 {
     OSArray *  links;
@@ -1562,7 +1579,38 @@ bool IORegistryEntry::inPlane( const IORegistryPlane * plane ) const
 
     RLOCK;
 
-    ret = (0 != getParentSetReference( plane ));
+    if( plane)
+       ret = (0 != getParentSetReference( plane ));
+    else {
+
+       // Check to see if this is in any plane.  If it is in a plane
+       // then the registryTable will contain a key with the ParentLinks
+       // suffix.  When we iterate over the keys looking for that suffix
+       ret = false;
+
+       OSCollectionIterator *iter =
+           OSCollectionIterator::withCollection( registryTable());
+       if( iter) {
+           const OSSymbol *key;
+
+            while( (key = (OSSymbol *) iter->getNextObject()) ) {
+               size_t keysuffix;
+
+               // Get a pointer to this keys suffix
+               keysuffix = key->getLength();
+               if (keysuffix <= kIORegPlaneParentSuffixLen)
+                   continue;
+               keysuffix -= kIORegPlaneParentSuffixLen;
+               if( !strncmp(key->getCStringNoCopy() + keysuffix, 
+                               kIORegPlaneParentSuffix, 
+                               kIORegPlaneParentSuffixLen + 1) ) {
+                   ret = true;
+                   break;
+               }
+            }
+            iter->release();
+        }
+    }
 
     UNLOCK;
 
@@ -1581,6 +1629,9 @@ bool IORegistryEntry::attachToParent( IORegistryEntry * parent,
 
     WLOCK;
 
+    if (!reserved->fRegistryEntryID)
+       reserved->fRegistryEntryID = ++gIORegistryLastID;
+
     ret = makeLink( parent, kParentSetIndex, plane );
 
     if( (links = parent->getChildSetReference( plane )))
@@ -1588,16 +1639,47 @@ bool IORegistryEntry::attachToParent( IORegistryEntry * parent,
     else
        needParent = true;
 
-//    ret &= parent->makeLink( this, kChildSetIndex, plane );
-
     UNLOCK;
 
+    PLOCK;
+
+    // Mark any collections in the property list as immutable
+    OSDictionary *ptable = getPropertyTable();
+    OSCollectionIterator *iter =
+       OSCollectionIterator::withCollection( ptable );
+    if( iter) {
+       const OSSymbol *key;
+
+       while( (key = (OSSymbol *) iter->getNextObject( ))) {
+           // Is object for key a collection?
+           OSCollection *coll =
+               OSDynamicCast( OSCollection, ptable->getObject( key ));
+
+           if( coll) {
+               // Yup so mark it as immutable
+               coll->setOptions( OSCollection::kMASK,
+                                 OSCollection::kImmutable );
+           }
+       }
+       iter->release();
+    }
+
+    PUNLOCK;
+
     if( needParent)
         ret &= parent->attachToChild( this, plane );
 
     return( ret );
 }
 
+uint64_t IORegistryEntry::getRegistryEntryID( void )
+{
+    if (reserved)
+       return (reserved->fRegistryEntryID);
+    else
+       return (0);
+}
+
 bool IORegistryEntry::attachToChild( IORegistryEntry * child,
                                         const IORegistryPlane * plane )
 {
@@ -1682,8 +1764,11 @@ void IORegistryEntry::detachAbove( const IORegistryPlane * plane )
     IORegistryEntry *  parent;
 
     retain();
-    while( (parent = getParentEntry( plane )))
+    while( (parent = copyParentEntry( plane )))
+    {
        detachFromParent( parent, plane );
+       parent->release();
+    }
     release();
 }
 
@@ -1760,12 +1845,14 @@ unsigned int IORegistryEntry::getDepth( const IORegistryPlane * plane ) const
 
 OSDefineMetaClassAndStructors(IORegistryIterator, OSIterator)
 
+enum { kIORegistryIteratorInvalidFlag = 0x80000000 };
+
 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
 
 IORegistryIterator *
 IORegistryIterator::iterateOver( IORegistryEntry * root,
                                  const IORegistryPlane * plane,
-                                 IOOptionBits options = 0 )
+                                 IOOptionBits options )
 {
     IORegistryIterator *       create;
 
@@ -1783,7 +1870,7 @@ IORegistryIterator::iterateOver( IORegistryEntry * root,
             create->where = &create->start;
             create->start.current = root;
             create->plane = plane;
-            create->options = options;
+            create->options = options & ~kIORegistryIteratorInvalidFlag;
 
        } else {
            create->release();
@@ -1795,7 +1882,7 @@ IORegistryIterator::iterateOver( IORegistryEntry * root,
 
 IORegistryIterator *
 IORegistryIterator::iterateOver( const IORegistryPlane * plane,
-                                IOOptionBits options = 0 )
+                                IOOptionBits options )
 {
     return( iterateOver( gRegistryRoot, plane, options ));
 }
@@ -1805,10 +1892,12 @@ bool IORegistryIterator::isValid( void )
     bool               ok;
     IORegCursor *      next;
 
-    ok = true;
     next = where;
 
     RLOCK;
+
+    ok = (0 == (kIORegistryIteratorInvalidFlag & options));
+
     while( ok && next) {
        if( where->iter)
             ok = where->iter->isValid();
@@ -1824,7 +1913,7 @@ void IORegistryIterator::enterEntry( const IORegistryPlane * enterPlane )
     IORegCursor *      prev;
 
     prev = where;
-    where = (IORegCursor *) IOMalloc( sizeof( IORegCursor));
+    where = (IORegCursor *) IOMalloc( sizeof(IORegCursor));
     assert( where);
 
     if( where) {
@@ -1854,7 +1943,7 @@ bool IORegistryIterator::exitEntry( void )
     if( where != &start) {
        gone = where;
         where = gone->next;
-        IOFree( gone, sizeof( IORegCursor));
+        IOFree( gone, sizeof(IORegCursor));
        return( true);
 
     } else
@@ -1872,6 +1961,7 @@ void IORegistryIterator::reset( void )
     }
 
     where->current = root;
+    options &= ~kIORegistryIteratorInvalidFlag;
 }
 
 void IORegistryIterator::free( void )
@@ -1907,11 +1997,15 @@ IORegistryEntry * IORegistryIterator::getNextObjectFlat( void )
         if( where->current)
             where->current->release();
 
-    if( where->iter)
+    if( where->iter) {
+
         next = (IORegistryEntry *) where->iter->getNextObject();
 
-    if( next)
-       next->retain();
+        if( next)
+            next->retain();
+        else if( !where->iter->isValid())
+            options |= kIORegistryIteratorInvalidFlag;
+    }
 
     where->current = next;
 
@@ -1965,12 +2059,21 @@ OSOrderedSet * IORegistryIterator::iterateAll( void )
     return( done);
 }
 
+#if __LP64__
 OSMetaClassDefineReservedUnused(IORegistryEntry, 0);
 OSMetaClassDefineReservedUnused(IORegistryEntry, 1);
 OSMetaClassDefineReservedUnused(IORegistryEntry, 2);
 OSMetaClassDefineReservedUnused(IORegistryEntry, 3);
 OSMetaClassDefineReservedUnused(IORegistryEntry, 4);
 OSMetaClassDefineReservedUnused(IORegistryEntry, 5);
+#else
+OSMetaClassDefineReservedUsed(IORegistryEntry, 0);
+OSMetaClassDefineReservedUsed(IORegistryEntry, 1);
+OSMetaClassDefineReservedUsed(IORegistryEntry, 2);
+OSMetaClassDefineReservedUsed(IORegistryEntry, 3);
+OSMetaClassDefineReservedUsed(IORegistryEntry, 4);
+OSMetaClassDefineReservedUsed(IORegistryEntry, 5);
+#endif
 OSMetaClassDefineReservedUnused(IORegistryEntry, 6);
 OSMetaClassDefineReservedUnused(IORegistryEntry, 7);
 OSMetaClassDefineReservedUnused(IORegistryEntry, 8);
@@ -1997,3 +2100,7 @@ OSMetaClassDefineReservedUnused(IORegistryEntry, 28);
 OSMetaClassDefineReservedUnused(IORegistryEntry, 29);
 OSMetaClassDefineReservedUnused(IORegistryEntry, 30);
 OSMetaClassDefineReservedUnused(IORegistryEntry, 31);
+
+/* inline function implementation */
+OSDictionary * IORegistryEntry::getPropertyTable( void ) const
+{ return(fPropertyTable); }