]> git.saurik.com Git - apple/xnu.git/blobdiff - iokit/Kernel/IORegistryEntry.cpp
xnu-3789.31.2.tar.gz
[apple/xnu.git] / iokit / Kernel / IORegistryEntry.cpp
index f039c28adef3a69569c91ca9391a7c124132efb0..f07b4231805428004c7417c315a87b4d645e3730 100644 (file)
  * 
  * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
  */
-/*
- * Copyright (c) 1998 Apple Computer, Inc.  All rights reserved. 
- *
- * HISTORY
- * 12 Nov 98 sdouglas created.
- *
- */
 
 #include <IOKit/IORegistryEntry.h>
 #include <libkern/c++/OSContainers.h>
 #include <IOKit/IOService.h>
 #include <IOKit/IOKitKeys.h>
+#include <IOKit/IOTimeStamp.h>
 
 #include <IOKit/IOLib.h>
 
 #include <IOKit/assert.h>
 
+#include "IOKitKernelInternal.h"
+
 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
 
 #define super OSObject
@@ -60,11 +56,23 @@ OSDefineMetaClassAndStructors(IORegistryEntry, OSObject)
 #define kIORegPlaneNameSuffixLen       (sizeof(kIORegPlaneNameSuffix) - 1)
 #define kIORegPlaneLocationSuffixLen   (sizeof(kIORegPlaneLocationSuffix) - 1)
 
+#define KASLR_IOREG_DEBUG 0
+
+struct IORegistryEntry::ExpansionData
+{
+    IORecursiveLock * fLock;
+    uint64_t         fRegistryEntryID;
+    SInt32            fRegistryEntryGenerationCount;
+};
+
+
 static IORegistryEntry * gRegistryRoot;
 static OSDictionary *   gIORegistryPlanes;
 
 const OSSymbol *       gIONameKey;
 const OSSymbol *       gIOLocationKey;
+const OSSymbol *       gIORegistryEntryIDKey;
+const OSSymbol *       gIORegistryEntryPropertyKeysKey;
 
 enum {
     kParentSetIndex    = 0,
@@ -75,6 +83,10 @@ enum {
     kIOMaxPlaneName    = 32
 };
 
+enum { kIORegistryIDReserved = (1ULL << 32) + 255 };
+
+static uint64_t gIORegistryLastID = kIORegistryIDReserved;
+
 class IORegistryPlane : public OSObject {
 
     friend class IORegistryEntry;
@@ -88,7 +100,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)
@@ -103,8 +115,8 @@ static SInt32                       gIORegistryGenerationCount;
                gIORegistryGenerationCount++
                // make atomic
 
-#define PUNLOCK        IORecursiveLockUnlock( gPropertiesLock )
-#define PLOCK  IORecursiveLockLock( gPropertiesLock )
+#define PUNLOCK        IORecursiveLockUnlock( reserved->fLock )
+#define PLOCK  IORecursiveLockLock( reserved->fLock )
 
 #define IOREGSPLITTABLES
 
@@ -149,8 +161,13 @@ 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 );
+        gIORegistryEntryPropertyKeysKey = OSSymbol::withCStringNoCopy( kIORegistryEntryPropertyKeysKey );
 
        assert( ok && gIONameKey && gIOLocationKey );
 
@@ -171,6 +188,10 @@ SInt32 IORegistryEntry::getGenerationCount( void )
     return( gIORegistryGenerationCount );
 }
 
+SInt32 IORegistryEntry::getRegistryEntryGenerationCount(void) const
+{
+    return (reserved->fRegistryEntryGenerationCount);
+}
 
 const IORegistryPlane * IORegistryEntry::makePlane( const char * name )
 {
@@ -261,8 +282,22 @@ bool IORegistryEntry::init( OSDictionary * dict )
     if( !super::init())
        return( false);
 
+    if (!reserved)
+    {
+       reserved = IONew(ExpansionData, 1);
+       if (!reserved)
+           return (false);
+       bzero(reserved, sizeof(ExpansionData));
+       reserved->fLock = IORecursiveLockAlloc();
+       if (!reserved->fLock) return (false);
+    }
     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;
@@ -305,13 +340,23 @@ bool IORegistryEntry::init( IORegistryEntry * old,
     if( !super::init())
        return( false);
 
+    if (!reserved)
+    {
+       reserved = IONew(ExpansionData, 1);
+       if (!reserved) return (false);
+       bzero(reserved, sizeof(ExpansionData));
+       reserved->fLock = IORecursiveLockAlloc();
+       if (!reserved->fLock) return (false);
+    }
+
     WLOCK;
 
-    fPropertyTable = old->getPropertyTable();
-    fPropertyTable->retain();
+    reserved->fRegistryEntryID = old->reserved->fRegistryEntryID;
+
+    fPropertyTable = old->dictionaryWithProperties();
 #ifdef IOREGSPLITTABLES
     fRegistryTable = old->fRegistryTable;
-    old->fRegistryTable = OSDictionary::withDictionary( fRegistryTable );
+    old->fRegistryTable = (OSDictionary *) fRegistryTable->copyCollection();
 #endif /* IOREGSPLITTABLES */
 
     old->registryTable()->removeObject( plane->keys[ kParentSetIndex ] );
@@ -340,19 +385,11 @@ bool IORegistryEntry::init( IORegistryEntry * old,
 
 void IORegistryEntry::free( void )
 {
-
 #if DEBUG_FREE
-#define msg ": attached at free()"
-    int len = strlen(msg) + 40;
-    char buf[len];
-
     if( registryTable() && gIOServicePlane) {
         if( getParentSetReference( gIOServicePlane )
             || getChildSetReference( gIOServicePlane )) {
-
-            strlcpy( buf, getName(), 32);
-            strlcat( buf, msg, len );
-            IOPanic( buf );
+            panic("%s: attached at free()", getName());
         }
     }
 #endif
@@ -365,15 +402,22 @@ void IORegistryEntry::free( void )
         registryTable()->release();
 #endif /* IOREGSPLITTABLES */
 
+    if (reserved)
+    {
+       if (reserved->fLock) IORecursiveLockFree(reserved->fLock);
+       IODelete(reserved, ExpansionData, 1);
+    }
+
     super::free();
 }
 
 void IORegistryEntry::setPropertyTable( OSDictionary * dict )
 {
-    if( fPropertyTable)
-       fPropertyTable->release();
     if( dict)
        dict->retain();
+    if( fPropertyTable)
+       fPropertyTable->release();
+
     fPropertyTable = dict;
 }
 
@@ -452,11 +496,22 @@ bool IORegistryEntry::serializeProperties( OSSerialize * s ) const
     OSCollection *snapshotProperties = getPropertyTable()->copyCollection();
     PUNLOCK;
 
+    if (!snapshotProperties) return (false);
+
     bool ok =  snapshotProperties->serialize( s );
     snapshotProperties->release();
     return( ok );
 }
 
+OSArray * IORegistryEntry::copyPropertyKeys(void) const
+{
+    PLOCK;
+    OSArray * keys = getPropertyTable()->copyKeys();
+    PUNLOCK;
+
+    return (keys);
+}
+
 OSDictionary * IORegistryEntry::dictionaryWithProperties( void ) const
 {
     OSDictionary *     dict;
@@ -507,6 +562,15 @@ IORegistryEntry::removeProperty( const OSSymbol * 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)
 {
@@ -524,7 +588,18 @@ IORegistryEntry::setProperty( const OSSymbol * aKey, OSObject * anObject)
 
     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;
 }
 
@@ -749,6 +824,19 @@ void IORegistryEntry::setName( const OSSymbol * name,
         else
             key = gIONameKey;
 
+        if (gIOKitTrace && reserved && reserved->fRegistryEntryID)
+        {
+            uint64_t str_id = 0;
+            uint64_t __unused regID = getRegistryEntryID();
+            kernel_debug_string(IODBG_IOREGISTRY(IOREGISTRYENTRY_NAME_STRING), &str_id, name->getCStringNoCopy());
+            KERNEL_DEBUG_CONSTANT(IODBG_IOREGISTRY(IOREGISTRYENTRY_NAME),
+                (uintptr_t) regID,
+                (uintptr_t) (regID >> 32),
+                (uintptr_t) str_id,
+                (uintptr_t) (str_id >> 32),
+                0);
+        }
+
        WLOCK;
         registryTable()->setObject( key, (OSObject *) name);
        UNLOCK;
@@ -845,7 +933,7 @@ 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, aliasLen;
@@ -876,67 +964,62 @@ bool IORegistryEntry::getPath(    char * path, int * length,
        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) {
-
-        *nextComp++ = '/';
-        *nextComp = 0;
-        len++;
-
-    } else while( ok && ((--index) >= 0)) {
-
-        entry = (IORegistryEntry *) stack->getObject((unsigned int) index );
-        assert( entry );
-
-        if( (alias = entry->hasAlias( plane ))) {
-            len = plane->nameKey->getLength() + 1;
-            nextComp = path + len;
-
-            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 = '/';
+    ok = (0 != parent);
+    if (ok)
+    {
+        index = stack->getCount();
+        if( 0 == index) {
+
+            *nextComp++ = '/';
+            *nextComp = 0;
+            len++;
+
+        } else while( ok && ((--index) >= 0)) {
+
+            entry = (IORegistryEntry *) stack->getObject((unsigned int) index );
+            assert( entry );
+
+            if( (alias = entry->hasAlias( plane ))) {
+                len = plane->nameKey->getLength() + 1;
+                nextComp = path + len;
+
+                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) {
-            len += compLen;
-            nextComp += compLen;
+            if( ok) {
+                len += compLen;
+                nextComp += compLen;
+            }
         }
+        *length = len;
     }
-    *length = len;
-
     UNLOCK;
-
     stack->release();
 
     return( ok );
@@ -1298,6 +1381,7 @@ bool IORegistryEntry::makeLink( IORegistryEntry * to,
             links->release();
        }
     }
+    reserved->fRegistryEntryGenerationCount++;
 
     return( result);
 }
@@ -1318,6 +1402,7 @@ void IORegistryEntry::breakLink( IORegistryEntry * to,
                 registryTable()->removeObject( plane->keys[ relation ]);
            }
     }
+    reserved->fRegistryEntryGenerationCount++;
 }
 
 
@@ -1417,6 +1502,18 @@ OSIterator * IORegistryEntry::getChildIterator( const IORegistryPlane * plane )
     return( iter );
 }
 
+uint32_t IORegistryEntry::getChildCount( const IORegistryPlane * plane ) const
+{
+    OSArray * links;
+    uint32_t  count = 0;
+
+    RLOCK;
+    links = getChildSetReference( plane );
+    if (links) count = links->getCount();
+    UNLOCK;
+
+    return (count);
+}
 
 IORegistryEntry * IORegistryEntry::copyChildEntry(
                                const IORegistryPlane * plane ) const
@@ -1587,12 +1684,19 @@ bool IORegistryEntry::attachToParent( IORegistryEntry * parent,
     OSArray *  links;
     bool       ret;
     bool       needParent;
+    bool        traceName = false;
 
     if( this == parent)
        return( false );
 
     WLOCK;
 
+    if (!reserved->fRegistryEntryID)
+    {
+       reserved->fRegistryEntryID = ++gIORegistryLastID;
+       traceName = (0 != gIOKitTrace);
+    }
+
     ret = makeLink( parent, kParentSetIndex, plane );
 
     if( (links = parent->getChildSetReference( plane )))
@@ -1602,6 +1706,19 @@ bool IORegistryEntry::attachToParent( IORegistryEntry * parent,
 
     UNLOCK;
 
+    if (traceName)
+    {
+        uint64_t str_id = 0;
+        uint64_t __unused regID = getRegistryEntryID();
+        kernel_debug_string(IODBG_IOREGISTRY(IOREGISTRYENTRY_NAME_STRING), &str_id, getName());
+        KERNEL_DEBUG_CONSTANT(IODBG_IOREGISTRY(IOREGISTRYENTRY_NAME),
+            (uintptr_t) regID,
+            (uintptr_t) (regID >> 32),
+            (uintptr_t) str_id,
+            (uintptr_t) (str_id >> 32),
+            0);
+    }
+
     PLOCK;
 
     // Mark any collections in the property list as immutable
@@ -1633,6 +1750,14 @@ bool IORegistryEntry::attachToParent( IORegistryEntry * parent,
     return( ret );
 }
 
+uint64_t IORegistryEntry::getRegistryEntryID( void )
+{
+    if (reserved)
+       return (reserved->fRegistryEntryID);
+    else
+       return (0);
+}
+
 bool IORegistryEntry::attachToChild( IORegistryEntry * child,
                                         const IORegistryPlane * plane )
 {
@@ -1717,8 +1842,11 @@ void IORegistryEntry::detachAbove( const IORegistryPlane * plane )
     IORegistryEntry *  parent;
 
     retain();
-    while( (parent = getParentEntry( plane )))
+    while( (parent = copyParentEntry( plane )))
+    {
        detachFromParent( parent, plane );
+       parent->release();
+    }
     release();
 }
 
@@ -2009,13 +2137,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);