*
* @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
#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,
kIOMaxPlaneName = 32
};
+enum { kIORegistryIDReserved = (1ULL << 32) + 255 };
+
+static uint64_t gIORegistryLastID = kIORegistryIDReserved;
+
class IORegistryPlane : public OSObject {
friend class IORegistryEntry;
int reserved[2];
public:
- virtual bool serialize(OSSerialize *s) const;
+ virtual bool serialize(OSSerialize *s) const APPLE_KEXT_OVERRIDE;
};
OSDefineMetaClassAndStructors(IORegistryPlane, OSObject)
gIORegistryGenerationCount++
// make atomic
-#define PUNLOCK IORecursiveLockUnlock( gPropertiesLock )
-#define PLOCK IORecursiveLockLock( gPropertiesLock )
+#define PUNLOCK IORecursiveLockUnlock( reserved->fLock )
+#define PLOCK IORecursiveLockLock( reserved->fLock )
#define IOREGSPLITTABLES
&& 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 );
return( gIORegistryGenerationCount );
}
+SInt32 IORegistryEntry::getRegistryEntryGenerationCount(void) const
+{
+ return (reserved->fRegistryEntryGenerationCount);
+}
const IORegistryPlane * IORegistryEntry::makePlane( const char * name )
{
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;
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 ] );
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
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;
}
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;
PUNLOCK;
}
+#if KASLR_IOREG_DEBUG
+extern "C" {
+
+bool ScanForAddrInObject(OSObject * theObject,
+ int indent);
+
+}; /* extern "C" */
+#endif
+
bool
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;
}
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;
OSArray * stack;
IORegistryEntry * root;
const IORegistryEntry * entry;
- IORegistryEntry * parent;
+ const IORegistryEntry * parent;
const OSSymbol * alias;
int index;
int len, maxLength, compLen, aliasLen;
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 );
links->release();
}
}
+ reserved->fRegistryEntryGenerationCount++;
return( result);
}
registryTable()->removeObject( plane->keys[ relation ]);
}
}
+ reserved->fRegistryEntryGenerationCount++;
}
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
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 )))
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
return( ret );
}
+uint64_t IORegistryEntry::getRegistryEntryID( void )
+{
+ if (reserved)
+ return (reserved->fRegistryEntryID);
+ else
+ return (0);
+}
+
bool IORegistryEntry::attachToChild( IORegistryEntry * child,
const IORegistryPlane * plane )
{
IORegistryEntry * parent;
retain();
- while( (parent = getParentEntry( plane )))
+ while( (parent = copyParentEntry( plane )))
+ {
detachFromParent( parent, plane );
+ parent->release();
+ }
release();
}
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);