X-Git-Url: https://git.saurik.com/apple/xnu.git/blobdiff_plain/1c79356b52d46aa6b508fb032f5ae709b1f2897b..90556fb8d47e7b68fd301dde9dbb3ae7495cf323:/iokit/Kernel/IOUserClient.cpp diff --git a/iokit/Kernel/IOUserClient.cpp b/iokit/Kernel/IOUserClient.cpp index 83e846bca..06f700f5b 100644 --- a/iokit/Kernel/IOUserClient.cpp +++ b/iokit/Kernel/IOUserClient.cpp @@ -65,6 +65,9 @@ extern io_object_t iokit_lookup_connect_ref_current_task(io_object_t clientRef); extern ipc_port_t master_device_port; +extern void iokit_retain_port( ipc_port_t port ); +extern void iokit_release_port( ipc_port_t port ); + #include } /* extern "C" */ @@ -80,9 +83,12 @@ class IOMachPort : public OSObject public: OSObject * object; ipc_port_t port; + UInt32 mscount; static IOMachPort * portForObject( OSObject * obj, ipc_kobject_type_t type ); + static bool noMoreSendersForObject( OSObject * obj, + ipc_kobject_type_t type, mach_port_mscount_t * mscount ); static void releasePortForObject( OSObject * obj, ipc_kobject_type_t type ); static OSDictionary * dictForType( ipc_kobject_type_t type ); @@ -136,8 +142,11 @@ IOMachPort * IOMachPort::portForObject ( OSObject * obj, continue; if( (inst = (IOMachPort *) - dict->getObject( (const OSSymbol *) obj ))) + dict->getObject( (const OSSymbol *) obj ))) { + inst->mscount++; + inst->retain(); continue; + } inst = new IOMachPort; if( inst && !inst->init()) { @@ -149,7 +158,7 @@ IOMachPort * IOMachPort::portForObject ( OSObject * obj, if( inst->port) { // retains obj dict->setObject( (const OSSymbol *) obj, inst ); - inst->release(); // one more to free port => release obj + inst->mscount++; } else { inst->release(); @@ -163,6 +172,34 @@ IOMachPort * IOMachPort::portForObject ( OSObject * obj, return( inst ); } +bool IOMachPort::noMoreSendersForObject( OSObject * obj, + ipc_kobject_type_t type, mach_port_mscount_t * mscount ) +{ + OSDictionary * dict; + IOMachPort * machPort; + bool destroyed = true; + + IOTakeLock( gIOObjectPortLock); + + if( (dict = dictForType( type ))) { + obj->retain(); + + machPort = (IOMachPort *) dict->getObject( (const OSSymbol *) obj ); + if( machPort) { + destroyed = (machPort->mscount == *mscount); + if( destroyed) + dict->removeObject( (const OSSymbol *) obj ); + else + *mscount = machPort->mscount; + } + obj->release(); + } + + IOUnlock( gIOObjectPortLock); + + return( destroyed ); +} + void IOMachPort::releasePortForObject( OSObject * obj, ipc_kobject_type_t type ) { @@ -222,20 +259,32 @@ ipc_port_t iokit_port_for_object( io_object_t obj, ipc_kobject_type_t type ) { IOMachPort * machPort; + ipc_port_t port; - if( (machPort = IOMachPort::portForObject( obj, type ))) - return( machPort->port ); - else - return( 0 ); + if( (machPort = IOMachPort::portForObject( obj, type ))) { + + port = machPort->port; + if( port) + iokit_retain_port( port ); + + machPort->release(); + + } else + port = NULL; + + return( port ); } kern_return_t iokit_client_died( io_object_t obj, ipc_port_t /* port */, - ipc_kobject_type_t type ) + ipc_kobject_type_t type, mach_port_mscount_t * mscount ) { IOUserClient * client; IOMemoryMap * map; + if( !IOMachPort::noMoreSendersForObject( obj, type, mscount )) + return( kIOReturnNotReady ); + if( (IKOT_IOKIT_CONNECT == type) && (client = OSDynamicCast( IOUserClient, obj ))) client->clientDied(); @@ -243,9 +292,7 @@ iokit_client_died( io_object_t obj, ipc_port_t /* port */, && (map = OSDynamicCast( IOMemoryMap, obj ))) map->taskDied(); - IOMachPort::releasePortForObject( obj, type ); - - return( kIOReturnSuccess); + return( kIOReturnSuccess ); } }; /* extern "C" */ @@ -351,7 +398,7 @@ bool IOUserNotification::init( mach_port_t port, natural_t type, pingMsg->msgHdr.msgh_remote_port = port; pingMsg->msgHdr.msgh_bits = MACH_MSGH_BITS( MACH_MSG_TYPE_COPY_SEND, - MACH_MSG_TYPE_COPY_SEND ); + MACH_MSG_TYPE_MAKE_SEND ); pingMsg->msgHdr.msgh_size = msgSize; pingMsg->msgHdr.msgh_id = kOSNotificationMessageID; @@ -436,7 +483,7 @@ bool IOServiceUserNotification::handler( void * /* ref */, { unsigned int count; kern_return_t kr; - IOMachPort * machPort; + ipc_port_t port = NULL; bool sendPing = false; IOTakeLock( lock ); @@ -452,12 +499,16 @@ bool IOServiceUserNotification::handler( void * /* ref */, IOUnlock( lock ); if( sendPing) { - if( (0 == pingMsg->msgHdr.msgh_local_port) - && (machPort = IOMachPort::portForObject( this, IKOT_IOKIT_OBJECT ) )) - pingMsg->msgHdr.msgh_local_port = machPort->port; + if( (port = iokit_port_for_object( this, IKOT_IOKIT_OBJECT ) )) + pingMsg->msgHdr.msgh_local_port = port; + else + pingMsg->msgHdr.msgh_local_port = NULL; kr = mach_msg_send_from_kernel( &pingMsg->msgHdr, pingMsg->msgHdr.msgh_size); + if( port) + iokit_release_port( port ); + if( KERN_SUCCESS != kr) IOLog("%s: mach_msg_send_from_kernel {%x}\n", __FILE__, kr ); } @@ -522,7 +573,7 @@ IOReturn IOServiceMessageUserNotification::handler( void * ref, void * messageArgument, vm_size_t argSize ) { kern_return_t kr; - IOMachPort * machPort; + ipc_port_t port; IOServiceInterestContent * data = (IOServiceInterestContent *) pingMsg->notifyHeader.content; @@ -540,13 +591,17 @@ IOReturn IOServiceMessageUserNotification::handler( void * ref, - sizeof( data->messageArgument) + argSize; - if( (machPort = IOMachPort::portForObject( provider, IKOT_IOKIT_OBJECT ) )) - pingMsg->msgHdr.msgh_local_port = machPort->port; + if( (port = iokit_port_for_object( provider, IKOT_IOKIT_OBJECT ) )) + pingMsg->msgHdr.msgh_local_port = port; else - pingMsg->msgHdr.msgh_local_port = MACH_PORT_NULL; + pingMsg->msgHdr.msgh_local_port = NULL; kr = mach_msg_send_from_kernel( &pingMsg->msgHdr, pingMsg->msgHdr.msgh_size); + + if( port) + iokit_release_port( port ); + if( KERN_SUCCESS != kr) IOLog("%s: mach_msg_send_from_kernel {%x}\n", __FILE__, kr ); @@ -675,8 +730,8 @@ IOReturn IOUserClient::clientMemoryForType( UInt32 type, IOMemoryMap * IOUserClient::mapClientMemory( IOOptionBits type, task_t task, - IOOptionBits mapFlags = kIOMapAnywhere, - IOVirtualAddress atAddress = 0 ) + IOOptionBits mapFlags, + IOVirtualAddress atAddress ) { IOReturn err; IOOptionBits options = 0; @@ -802,47 +857,6 @@ IOReturn IOUserClient::sendAsyncResult(OSAsyncReference reference, /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ -#include - -static void makeMatchingCompatible( OSDictionary * dict ) -{ - const char * key; - const char * newKey; - OSObject * value; - OSString * str; - int i = 0; - - static const char * gratuitousNameChanges[] = { - "IOImports", kIOProviderClassKey, - "IOClass Names", kIOClassKey, - "IOProbe Score", kIOProbeScoreKey, - "IOKit Debug", kIOKitDebugKey, - "IONeededResources", kIOResourceMatchKey, - "IOName Match", kIONameMatchKey, - "IOPCI Match", kIOPCIMatchKey, - "IOPCI Primary Match", kIOPCIPrimaryMatchKey, - "IOPCI Secondary Match",kIOPCISecondaryMatchKey, - "IOPCI Class Match", kIOPCIClassMatchKey, - 0 - }; - - while( (key = gratuitousNameChanges[i++])) { - newKey = gratuitousNameChanges[i++]; - if( (value = dict->getObject( key)) - && (0 == dict->getObject( newKey))) { - - dict->setObject( newKey, value); - dict->removeObject( key); - - if( (str = OSDynamicCast(OSString, dict->getObject("CFBundleIdentifier")))) - IOLog("kext \"%s\" ", str->getCStringNoCopy()); - IOLog("must change \"%s\" to \"%s\"\n", key, newKey); - } - } -} - -/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ - extern "C" { #define CHECK(cls,obj,out) \ @@ -970,7 +984,6 @@ kern_return_t is_io_service_get_matching_services( obj = OSUnserializeXML( matching ); if( (dict = OSDynamicCast( OSDictionary, obj))) { - makeMatchingCompatible( dict ); // temp for binary compatibility *existing = IOService::getMatchingServices( dict ); kr = kIOReturnSuccess; } else @@ -1015,7 +1028,6 @@ kern_return_t is_io_service_add_notification( err = kIOReturnBadArgument; continue; } - makeMatchingCompatible( dict ); // temp for binary compatibility if( (sym == gIOPublishNotification) || (sym == gIOFirstPublishNotification)) @@ -1277,17 +1289,45 @@ kern_return_t is_io_registry_entry_get_name( /* Routine io_registry_entry_get_name_in_plane */ kern_return_t is_io_registry_entry_get_name_in_plane( io_object_t registry_entry, - io_name_t plane, + io_name_t planeName, io_name_t name ) { + const IORegistryPlane * plane; CHECK( IORegistryEntry, registry_entry, entry ); - strncpy( name, entry->getName( IORegistryEntry::getPlane( plane )), - sizeof( io_name_t)); + if( planeName[0]) + plane = IORegistryEntry::getPlane( planeName ); + else + plane = 0; + + strncpy( name, entry->getName( plane), sizeof( io_name_t)); return( kIOReturnSuccess ); } +/* Routine io_registry_entry_get_location_in_plane */ +kern_return_t is_io_registry_entry_get_location_in_plane( + io_object_t registry_entry, + io_name_t planeName, + io_name_t location ) +{ + const IORegistryPlane * plane; + CHECK( IORegistryEntry, registry_entry, entry ); + + if( planeName[0]) + plane = IORegistryEntry::getPlane( planeName ); + else + plane = 0; + + const char * cstr = entry->getLocation( plane ); + + if( cstr) { + strncpy( location, cstr, sizeof( io_name_t)); + return( kIOReturnSuccess ); + } else + return( kIOReturnNotFound ); +} + // Create a vm_map_copy_t or kalloc'ed data for memory // to be copied out. ipc will free after the copyout. @@ -1297,15 +1337,157 @@ static kern_return_t copyoutkdata( void * data, vm_size_t len, kern_return_t err; vm_map_copy_t copy; - err = vm_map_copyin( kernel_map, (vm_offset_t) data, len, - false /* src_destroy */, ©); + err = vm_map_copyin( kernel_map, (vm_offset_t) data, len, + false /* src_destroy */, ©); + + assert( err == KERN_SUCCESS ); + if( err == KERN_SUCCESS ) + *buf = (char *) copy; + + return( err ); +} + +/* Routine io_registry_entry_get_property */ +kern_return_t is_io_registry_entry_get_property_bytes( + io_object_t registry_entry, + io_name_t property_name, + io_scalar_inband_t buf, + mach_msg_type_number_t *dataCnt ) +{ + OSObject * obj; + OSData * data; + OSString * str; + OSBoolean * boo; + OSNumber * off; + UInt64 offsetBytes; + unsigned int len = 0; + const void * bytes = 0; + IOReturn ret = kIOReturnSuccess; + + CHECK( IORegistryEntry, registry_entry, entry ); + + obj = entry->copyProperty(property_name); + if( !obj) + return( kIOReturnNoResources ); + + // One day OSData will be a common container base class + // until then... + if( (data = OSDynamicCast( OSData, obj ))) { + len = data->getLength(); + bytes = data->getBytesNoCopy(); + + } else if( (str = OSDynamicCast( OSString, obj ))) { + len = str->getLength() + 1; + bytes = str->getCStringNoCopy(); + + } else if( (boo = OSDynamicCast( OSBoolean, obj ))) { + len = boo->isTrue() ? sizeof("Yes") : sizeof("No"); + bytes = boo->isTrue() ? "Yes" : "No"; + + } else if( (off = OSDynamicCast( OSNumber, obj ))) { + offsetBytes = off->unsigned64BitValue(); + len = off->numberOfBytes(); + bytes = &offsetBytes; +#if __BIG_ENDIAN__ + bytes = (const void *) + (((UInt32) bytes) + (sizeof( UInt64) - len)); +#endif + + } else + ret = kIOReturnBadArgument; + + if( bytes) { + if( *dataCnt < len) + ret = kIOReturnIPCError; + else { + *dataCnt = len; + bcopy( bytes, buf, len ); + } + } + obj->release(); + + return( ret ); +} + +/* Routine io_registry_entry_get_property */ +kern_return_t is_io_registry_entry_get_property( + io_object_t registry_entry, + io_name_t property_name, + io_buf_ptr_t *properties, + mach_msg_type_number_t *propertiesCnt ) +{ + kern_return_t err; + vm_size_t len; + OSObject * obj; + + CHECK( IORegistryEntry, registry_entry, entry ); + + obj = entry->copyProperty(property_name); + if( !obj) + return( kIOReturnNotFound ); + + OSSerialize * s = OSSerialize::withCapacity(4096); + if( !s) { + obj->release(); + return( kIOReturnNoMemory ); + } + s->clearText(); + + if( obj->serialize( s )) { + len = s->getLength(); + *propertiesCnt = len; + err = copyoutkdata( s->text(), len, properties ); + + } else + err = kIOReturnUnsupported; + + s->release(); + obj->release(); - assert( err == KERN_SUCCESS ); - if( err == KERN_SUCCESS ) - *buf = (char *) copy; return( err ); } +/* Routine io_registry_entry_get_property_recursively */ +kern_return_t is_io_registry_entry_get_property_recursively( + io_object_t registry_entry, + io_name_t plane, + io_name_t property_name, + int options, + io_buf_ptr_t *properties, + mach_msg_type_number_t *propertiesCnt ) +{ + kern_return_t err; + vm_size_t len; + OSObject * obj; + + CHECK( IORegistryEntry, registry_entry, entry ); + + obj = entry->copyProperty( property_name, + IORegistryEntry::getPlane( plane ), options); + if( !obj) + return( kIOReturnNotFound ); + + OSSerialize * s = OSSerialize::withCapacity(4096); + if( !s) { + obj->release(); + return( kIOReturnNoMemory ); + } + + s->clearText(); + + if( obj->serialize( s )) { + len = s->getLength(); + *propertiesCnt = len; + err = copyoutkdata( s->text(), len, properties ); + + } else + err = kIOReturnUnsupported; + + s->release(); + obj->release(); + + return( err ); +} /* Routine io_registry_entry_get_properties */ kern_return_t is_io_registry_entry_get_properties( @@ -1319,7 +1501,6 @@ kern_return_t is_io_registry_entry_get_properties( CHECK( IORegistryEntry, registry_entry, entry ); OSSerialize * s = OSSerialize::withCapacity(4096); - if( !s) return( kIOReturnNoMemory ); @@ -1333,7 +1514,7 @@ kern_return_t is_io_registry_entry_get_properties( } else err = kIOReturnUnsupported; - s->release(); + s->release(); return( err ); } @@ -1373,69 +1554,6 @@ kern_return_t is_io_registry_entry_set_properties return( err ); } - -/* Routine io_registry_entry_get_property */ -kern_return_t is_io_registry_entry_get_property( - io_object_t registry_entry, - io_name_t property_name, - io_scalar_inband_t buf, - mach_msg_type_number_t *dataCnt ) -{ - OSObject * obj; - OSData * data; - OSString * str; - OSBoolean * boo; - OSNumber * off; - UInt64 offsetBytes; - unsigned int len = 0; - const void * bytes = 0; - IOReturn ret = kIOReturnSuccess; - - CHECK( IORegistryEntry, registry_entry, entry ); - - obj = entry->getProperty( property_name ); - if( !obj) - return( kIOReturnNoResources ); - - // One day OSData will be a common container base class - // until then... - if( (data = OSDynamicCast( OSData, obj ))) { - len = data->getLength(); - bytes = data->getBytesNoCopy(); - - } else if( (str = OSDynamicCast( OSString, obj ))) { - len = str->getLength() + 1; - bytes = str->getCStringNoCopy(); - - } else if( (boo = OSDynamicCast( OSBoolean, obj ))) { - len = boo->isTrue() ? sizeof("Yes") : sizeof("No"); - bytes = boo->isTrue() ? "Yes" : "No"; - - } else if( (off = OSDynamicCast( OSNumber, obj ))) { - offsetBytes = off->unsigned64BitValue(); - len = off->numberOfBytes(); - bytes = &offsetBytes; -#if __BIG_ENDIAN__ - bytes = (const void *) - (((UInt32) bytes) + (sizeof( UInt64) - len)); -#endif - - } else - ret = kIOReturnBadArgument; - - if( bytes) { - if( *dataCnt < len) - ret = kIOReturnIPCError; - else { - *dataCnt = len; - bcopy( bytes, buf, len ); - } - } - - return( ret ); -} - - /* Routine io_registry_entry_get_child_iterator */ kern_return_t is_io_registry_entry_get_child_iterator( io_object_t registry_entry, @@ -1633,8 +1751,8 @@ kern_return_t is_io_connect_unmap_memory( IOLockLock( gIOObjectPortLock); if( client->mappings) client->mappings->removeObject( map); - IOMachPort::releasePortForObject( map, IKOT_IOKIT_OBJECT ); IOLockUnlock( gIOObjectPortLock); + IOMachPort::releasePortForObject( map, IKOT_IOKIT_OBJECT ); map->release(); } else err = kIOReturnBadArgument; @@ -2337,12 +2455,6 @@ kern_return_t is_io_catalog_send_data( array = OSDynamicCast(OSArray, obj); if ( array ) { -//-- - OSDictionary * dict; - int i = 0; - while( (dict = OSDynamicCast(OSDictionary, array->getObject(i++)))) - makeMatchingCompatible( dict ); -//-- if ( !gIOCatalogue->addDrivers( array , flag == kIOCatalogAddDrivers) ) { kr = kIOReturnError; @@ -2360,7 +2472,6 @@ kern_return_t is_io_catalog_send_data( dict = OSDynamicCast(OSDictionary, obj); if ( dict ) { - makeMatchingCompatible( dict ); if ( !gIOCatalogue->removeDrivers( dict, flag == kIOCatalogRemoveDrivers ) ) { kr = kIOReturnError; @@ -2377,7 +2488,6 @@ kern_return_t is_io_catalog_send_data( dict = OSDynamicCast(OSDictionary, obj); if ( dict ) { - makeMatchingCompatible( dict ); if ( !gIOCatalogue->startMatching( dict ) ) { kr = kIOReturnError; } @@ -2391,6 +2501,8 @@ kern_return_t is_io_catalog_send_data( case kIOCatalogRemoveKernelLinker: { if (gIOCatalogue->removeKernelLinker() != KERN_SUCCESS) { kr = kIOReturnError; + } else { + kr = kIOReturnSuccess; } } break; @@ -2568,31 +2680,34 @@ kern_return_t is_io_catalog_reset( return kIOReturnSuccess; } -kern_return_t iokit_user_client_trap(io_object_t userClientRef, UInt32 index, void *p1, void *p2, void *p3, void *p4, void *p5, void *p6) +kern_return_t iokit_user_client_trap(io_object_t userClientRef, UInt32 index, + void *p1, void *p2, void *p3, + void *p4, void *p5, void *p6) { - kern_return_t result = kIOReturnBadArgument; - IOUserClient *userClient; + kern_return_t result = kIOReturnBadArgument; + IOUserClient *userClient; - if ((userClient = OSDynamicCast(IOUserClient, iokit_lookup_connect_ref_current_task(userClientRef)))) { - IOExternalTrap *trap; - IOService *target = NULL; + if ((userClient = OSDynamicCast(IOUserClient, + iokit_lookup_connect_ref_current_task(userClientRef)))) { + IOExternalTrap *trap; + IOService *target = NULL; - trap = userClient->getTargetAndTrapForIndex(&target, index); + trap = userClient->getTargetAndTrapForIndex(&target, index); - if (trap && target) { - IOTrap func; + if (trap && target) { + IOTrap func; - func = trap->func; + func = trap->func; - if (func) { - result = (target->*func)(p1, p2, p3, p4, p5, p6); - } - } + if (func) { + result = (target->*func)(p1, p2, p3, p4, p5, p6); + } + } - userClient->release(); - } + userClient->release(); + } - return result; + return result; } }; /* extern "C" */