#include <IOKit/IOCatalogue.h>
#include <IOKit/IOMemoryDescriptor.h>
#include <IOKit/IOBufferMemoryDescriptor.h>
+#include <IOKit/IOSubMemoryDescriptor.h>
+#include <IOKit/IOMultiMemoryDescriptor.h>
#include <IOKit/IOMapper.h>
#include <IOKit/IOLib.h>
#include <IOKit/IOBSD.h>
#include <IOKit/IOTimerEventSource.h>
#include <IOKit/pwr_mgt/RootDomain.h>
#include <libkern/c++/OSKext.h>
+#include <libkern/c++/OSSharedPtr.h>
#include <libkern/OSDebug.h>
#include <libkern/Block.h>
#include <sys/proc.h>
#include "IOKitKernelInternal.h"
-/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#include <DriverKit/IODispatchQueue.h>
#include <DriverKit/OSObject.h>
#include <DriverKit/IOServiceNotificationDispatchSource.h>
#include <DriverKit/IOUserServer.h>
-/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#include <System/IODataQueueDispatchSourceShared.h>
-/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
-SInt64 gIODKDebug = kIODKEnable;
+SECURITY_READ_ONLY_LATE(SInt64) gIODKDebug = kIODKEnable;
-/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
struct IOPStrings;
IOMemoryDescriptor ** memory) APPLE_KEXT_OVERRIDE;
};
+OSDefineMetaClassAndStructors(IOUserServerCheckInToken, OSObject);
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
return ok;
}
-/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#undef super
-/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
struct IODispatchQueue_IVars {
IOUserServer * userServer;
uint64_t msgid;
OSActionAbortedHandler abortedHandler;
size_t referenceSize;
+ OSString * typeName;
void * reference[0];
};
-/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
kern_return_t
-IMPL(IOService, GetRegistryEntryID)
+IOService::GetRegistryEntryID_Impl(
+ uint64_t * registryEntryID)
{
IOReturn ret = kIOReturnSuccess;
}
kern_return_t
-IMPL(IOService, SetName)
+IOService::SetName_Impl(
+ const char * name)
{
IOReturn ret = kIOReturnSuccess;
}
kern_return_t
-IMPL(IOService, Start)
+IOService::Start_Impl(
+ IOService * provider)
{
IOReturn ret = kIOReturnSuccess;
return ret;
}
kern_return_t
-IMPL(IOService, RegisterService)
+IOService::RegisterService_Impl()
{
IOReturn ret = kIOReturnSuccess;
}
kern_return_t
-IMPL(IOService, CopyDispatchQueue)
+IOService::CopyDispatchQueue_Impl(
+ const char * name,
+ IODispatchQueue ** queue)
{
IODispatchQueue * result;
IOService * service;
IOReturn ret;
uint32_t index;
+ if (!reserved->uvars) {
+ return kIOReturnError;
+ }
+
ret = kIOReturnNotFound;
index = -1U;
if (!strcmp("Default", name)) {
}
kern_return_t
-IMPL(IOService, SetDispatchQueue)
+IOService::SetDispatchQueue_Impl(
+ const char * name,
+ IODispatchQueue * queue)
{
IOReturn ret = kIOReturnSuccess;
uint32_t index;
+ if (!reserved->uvars) {
+ return kIOReturnError;
+ }
+
if (kIODKLogSetup & gIODKDebug) {
DKLOG(DKS "::SetDispatchQueue(%s)\n", DKN(this), name);
}
}
kern_return_t
-IMPL(IOService, SetProperties)
+IOService::SetProperties_Impl(
+ OSDictionary * properties)
{
IOUserServer * us;
OSDictionary * dict;
}
kern_return_t
-IMPL(IOService, CopyProperties)
+IOService::CopyProperties_Impl(
+ OSDictionary ** properties)
{
IOReturn ret = kIOReturnSuccess;
*properties = dictionaryWithProperties();
return ret;
}
-/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+kern_return_t
+IOService::RequireMaxBusStall_Impl(
+ uint64_t u64ns)
+{
+ IOReturn ret;
+ UInt32 ns;
+
+ if (os_convert_overflow(u64ns, &ns)) {
+ return kIOReturnBadArgument;
+ }
+ ret = requireMaxBusStall(ns);
+
+ return kIOReturnSuccess;
+}
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
kern_return_t
-IMPL(IOMemoryDescriptor, _CopyState)
+IOMemoryDescriptor::_CopyState_Impl(
+ _IOMDPrivateState * state)
{
IOReturn ret;
}
kern_return_t
-IMPL(IOMemoryDescriptor, CreateMapping)
+IOMemoryDescriptor::CreateMapping_Impl(
+ uint64_t options,
+ uint64_t address,
+ uint64_t offset,
+ uint64_t length,
+ uint64_t alignment,
+ IOMemoryMap ** map)
{
IOReturn ret;
IOMemoryMap * resultMap;
}
kern_return_t
-IMPL(IOMemoryDescriptor, PrepareForDMA)
+IOMemoryDescriptor::CreateSubMemoryDescriptor_Impl(
+ uint64_t memoryDescriptorCreateOptions,
+ uint64_t offset,
+ uint64_t length,
+ IOMemoryDescriptor * ofDescriptor,
+ IOMemoryDescriptor ** memory)
+{
+ IOReturn ret;
+ IOMemoryDescriptor * iomd;
+ IOByteCount mdOffset;
+ IOByteCount mdLength;
+ IOByteCount mdEnd;
+
+ if (!ofDescriptor) {
+ return kIOReturnBadArgument;
+ }
+ if (memoryDescriptorCreateOptions & ~kIOMemoryDirectionOutIn) {
+ return kIOReturnBadArgument;
+ }
+ if (os_convert_overflow(offset, &mdOffset)) {
+ return kIOReturnBadArgument;
+ }
+ if (os_convert_overflow(length, &mdLength)) {
+ return kIOReturnBadArgument;
+ }
+ if (os_add_overflow(mdOffset, mdLength, &mdEnd)) {
+ return kIOReturnBadArgument;
+ }
+ if (mdEnd > ofDescriptor->getLength()) {
+ return kIOReturnBadArgument;
+ }
+
+ iomd = IOSubMemoryDescriptor::withSubRange(
+ ofDescriptor, mdOffset, mdLength, (IOOptionBits) memoryDescriptorCreateOptions);
+
+ if (iomd) {
+ ret = kIOReturnSuccess;
+ *memory = iomd;
+ } else {
+ ret = kIOReturnNoMemory;
+ *memory = NULL;
+ }
+
+ return ret;
+}
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+kern_return_t
+IOMemoryDescriptor::CreateWithMemoryDescriptors_Impl(
+ uint64_t memoryDescriptorCreateOptions,
+ uint32_t withDescriptorsCount,
+ IOMemoryDescriptor ** const withDescriptors,
+ IOMemoryDescriptor ** memory)
{
- IOReturn ret;
- uint32_t idx, count;
- uint64_t sumLength;
- uint64_t lflags;
+ IOReturn ret;
+ IOMemoryDescriptor * iomd;
- if (!device) {
+ if (!withDescriptors) {
+ return kIOReturnBadArgument;
+ }
+ if (!withDescriptorsCount) {
+ return kIOReturnBadArgument;
+ }
+ if (memoryDescriptorCreateOptions & ~kIOMemoryDirectionOutIn) {
return kIOReturnBadArgument;
}
- count = *segmentsCount;
- sumLength = 0;
- for (idx = 0; idx < count; idx++) {
-#ifdef __LP64__
- segments[idx].address = getPhysicalSegment(offset, &segments[idx].length);
-#else
- segments[idx].address = 0;
-#endif
- if (!segments[idx].address) {
- break;
+ for (unsigned int idx = 0; idx < withDescriptorsCount; idx++) {
+ if (NULL == withDescriptors[idx]) {
+ return kIOReturnBadArgument;
}
- sumLength += segments[idx].length;
- offset += segments[idx].length;
}
- *returnLength = sumLength;
- *segmentsCount = idx;
- // !!translate flags
- lflags = 0;
- if (kIODirectionOut & _flags) {
- lflags |= kIOMemoryDirectionOut;
+ iomd = IOMultiMemoryDescriptor::withDescriptors(withDescriptors, withDescriptorsCount,
+ (IODirection) memoryDescriptorCreateOptions, false);
+
+ if (iomd) {
+ ret = kIOReturnSuccess;
+ *memory = iomd;
+ } else {
+ ret = kIOReturnNoMemory;
+ *memory = NULL;
}
- if (kIODirectionIn & _flags) {
- lflags |= kIOMemoryDirectionIn;
+
+ return ret;
+}
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+kern_return_t
+IOUserClient::CreateMemoryDescriptorFromClient_Impl(
+ uint64_t memoryDescriptorCreateOptions,
+ uint32_t segmentsCount,
+ const IOAddressSegment segments[32],
+ IOMemoryDescriptor ** memory)
+{
+ IOReturn ret;
+ IOMemoryDescriptor * iomd;
+ IOOptionBits mdOptions;
+ IOUserUserClient * me;
+ IOAddressRange * ranges;
+
+ me = OSDynamicCast(IOUserUserClient, this);
+ if (!me) {
+ return kIOReturnBadArgument;
}
- *flags = lflags;
- ret = kIOReturnSuccess;
+ mdOptions = 0;
+ if (kIOMemoryDirectionOut & memoryDescriptorCreateOptions) {
+ mdOptions |= kIODirectionOut;
+ }
+ if (kIOMemoryDirectionIn & memoryDescriptorCreateOptions) {
+ mdOptions |= kIODirectionIn;
+ }
+ if (!(kIOMemoryDisableCopyOnWrite & memoryDescriptorCreateOptions)) {
+ mdOptions |= kIOMemoryMapCopyOnWrite;
+ }
+
+ static_assert(sizeof(IOAddressRange) == sizeof(IOAddressSegment));
+ ranges = __DECONST(IOAddressRange *, &segments[0]);
+
+ iomd = IOMemoryDescriptor::withAddressRanges(
+ ranges, segmentsCount,
+ mdOptions, me->fTask);
+
+ if (iomd) {
+ ret = kIOReturnSuccess;
+ *memory = iomd;
+ } else {
+ ret = kIOReturnNoMemory;
+ *memory = NULL;
+ }
return ret;
}
-/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
kern_return_t
-IMPL(IOMemoryMap, _CopyState)
+IOMemoryMap::_CopyState_Impl(
+ _IOMemoryMapPrivateState * state)
{
IOReturn ret;
return ret;
}
-/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
kern_return_t
-IMPL(IOBufferMemoryDescriptor, Create)
+IOBufferMemoryDescriptor::Create_Impl(
+ uint64_t options,
+ uint64_t capacity,
+ uint64_t alignment,
+ IOBufferMemoryDescriptor ** memory)
{
IOReturn ret;
+ IOOptionBits bmdOptions;
IOBufferMemoryDescriptor * bmd;
IOMemoryDescriptorReserved * reserved;
// no other options currently defined
return kIOReturnBadArgument;
}
- options &= kIOMemoryDirectionOutIn;
- options |= kIOMemoryKernelUserShared;
+ bmdOptions = (options & kIOMemoryDirectionOutIn) | kIOMemoryKernelUserShared;
bmd = IOBufferMemoryDescriptor::inTaskWithOptions(
- kernel_task, options, capacity, alignment);
+ kernel_task, bmdOptions, capacity, alignment);
*memory = bmd;
}
kern_return_t
-IMPL(IOBufferMemoryDescriptor, SetLength)
+IOBufferMemoryDescriptor::SetLength_Impl(
+ uint64_t length)
{
setLength(length);
return kIOReturnSuccess;
}
-/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
kern_return_t
-IMPL(IODMACommand, Create)
+IODMACommand::Create_Impl(
+ IOService * device,
+ uint64_t options,
+ const IODMACommandSpecification * specification,
+ IODMACommand ** command)
{
IOReturn ret;
IODMACommand * dma;
}
kern_return_t
-IMPL(IODMACommand, PrepareForDMA)
+IODMACommand::PrepareForDMA_Impl(
+ uint64_t options,
+ IOMemoryDescriptor * memory,
+ uint64_t offset,
+ uint64_t length,
+ uint64_t * flags,
+ uint32_t * segmentsCount,
+ IOAddressSegment * segments)
{
IOReturn ret;
uint64_t lflags, mdFlags;
return kIOReturnBadArgument;
}
+ // uses IOMD direction
+ ret = memory->prepare();
+ if (kIOReturnSuccess != ret) {
+ return ret;
+ }
+
ret = setMemoryDescriptor(memory, false);
if (kIOReturnSuccess != ret) {
+ memory->complete();
return ret;
}
ret = prepare(offset, length);
if (kIOReturnSuccess != ret) {
clearMemoryDescriptor(false);
+ memory->complete();
return ret;
}
ret = genIOVMSegments(&genOffset, segments, &numSegments);
if (kIOReturnSuccess == ret) {
- IOMemoryDescriptor * mem;
- mem = __IODEQUALIFY(IOMemoryDescriptor *, fMemory);
- mdFlags = mem->getFlags();
+ mdFlags = fMemory->getFlags();
lflags = 0;
if (kIODirectionOut & mdFlags) {
lflags |= kIOMemoryDirectionOut;
}
kern_return_t
-IMPL(IODMACommand, CompleteDMA)
+IODMACommand::CompleteDMA_Impl(
+ uint64_t options)
{
- IOReturn ret;
+ IOReturn ret, completeRet;
+ IOMemoryDescriptor * md;
if (options & ~((uint64_t) kIODMACommandCompleteDMANoOptions)) {
// no other options currently defined
return kIOReturnBadArgument;
}
+ if (!fActive) {
+ return kIOReturnNotReady;
+ }
+
+ md = __DECONST(IOMemoryDescriptor *, fMemory);
+ if (md) {
+ md->retain();
+ }
ret = clearMemoryDescriptor(true);
+ if (md) {
+ completeRet = md->complete();
+ OSSafeReleaseNULL(md);
+ if (kIOReturnSuccess == ret) {
+ ret = completeRet;
+ }
+ }
+
return ret;
}
kern_return_t
-IMPL(IODMACommand, GetPreparation)
+IODMACommand::GetPreparation_Impl(
+ uint64_t * offset,
+ uint64_t * length,
+ IOMemoryDescriptor ** memory)
{
IOReturn ret;
IOMemoryDescriptor * md;
}
kern_return_t
-IMPL(IODMACommand, PerformOperation)
+IODMACommand::PerformOperation_Impl(
+ uint64_t options,
+ uint64_t dmaOffset,
+ uint64_t length,
+ uint64_t dataOffset,
+ IOMemoryDescriptor * data)
{
IOReturn ret;
void * buffer;
}
-/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
-
-kern_return_t
-OSAction::Create(OSAction_Create_Args)
-{
- kern_return_t ret;
- ret = OSAction::Create_Call(target, targetmsgid, msgid, referenceSize, action);
- return ret;
-}
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
-kern_return_t
-IMPL(OSAction, Create)
+static kern_return_t
+OSActionCreateWithTypeNameInternal(OSObject * target, uint64_t targetmsgid, uint64_t msgid, size_t referenceSize, OSString * typeName, bool fromKernel, OSAction ** action)
{
- OSAction * inst;
+ OSAction * inst = NULL;
vm_size_t allocsize;
+ const OSSymbol *sym = NULL; // must release
+ OSObject *obj = NULL; // must release
+ const OSMetaClass *actionMetaClass = NULL; // do not release
+ kern_return_t ret;
if (os_add_overflow(referenceSize, sizeof(OSAction_IVars), &allocsize)) {
- return kIOReturnBadArgument;
+ ret = kIOReturnBadArgument;
+ goto finish;
}
- inst = OSTypeAlloc(OSAction);
- if (!inst) {
- return kIOReturnNoMemory;
+
+ if (fromKernel && typeName) {
+ /* The action is being constructed in the kernel with a type name */
+ sym = OSSymbol::withString(typeName);
+ actionMetaClass = OSMetaClass::getMetaClassWithName(sym);
+ if (actionMetaClass && actionMetaClass->getSuperClass() == OSTypeID(OSAction)) {
+ obj = actionMetaClass->alloc();
+ if (!obj) {
+ ret = kIOReturnNoMemory;
+ goto finish;
+ }
+ inst = OSDynamicCast(OSAction, obj);
+ obj = NULL; // prevent release
+ assert(inst); // obj is a subclass of OSAction so the dynamic cast should always work
+ } else {
+ DKLOG("Attempted to create action object with type \"%s\" which does not inherit from OSAction\n", typeName->getCStringNoCopy());
+ ret = kIOReturnBadArgument;
+ goto finish;
+ }
+ } else {
+ inst = OSTypeAlloc(OSAction);
+ if (!inst) {
+ ret = kIOReturnNoMemory;
+ goto finish;
+ }
}
+
inst->ivars = (typeof(inst->ivars))(uintptr_t) IONewZero(uint8_t, allocsize);
if (!inst->ivars) {
- inst->release();
- return kIOReturnNoMemory;
+ ret = kIOReturnNoMemory;
+ goto finish;
}
target->retain();
inst->ivars->target = target;
inst->ivars->targetmsgid = targetmsgid;
inst->ivars->msgid = msgid;
inst->ivars->referenceSize = referenceSize;
+ if (typeName) {
+ typeName->retain();
+ }
+ inst->ivars->typeName = typeName;
*action = inst;
+ inst = NULL; // prevent release
+ ret = kIOReturnSuccess;
- return kIOReturnSuccess;
+finish:
+ OSSafeReleaseNULL(obj);
+ OSSafeReleaseNULL(sym);
+ OSSafeReleaseNULL(inst);
+
+ return ret;
+}
+
+kern_return_t
+OSAction::Create(OSAction_Create_Args)
+{
+ return OSAction::CreateWithTypeName(target, targetmsgid, msgid, referenceSize, NULL, action);
+}
+
+kern_return_t
+OSAction::CreateWithTypeName(OSAction_CreateWithTypeName_Args)
+{
+ return OSActionCreateWithTypeNameInternal(target, targetmsgid, msgid, referenceSize, typeName, true, action);
+}
+
+kern_return_t
+OSAction::Create_Impl(
+ OSObject * target,
+ uint64_t targetmsgid,
+ uint64_t msgid,
+ size_t referenceSize,
+ OSAction ** action)
+{
+ return OSAction::CreateWithTypeName_Impl(target, targetmsgid, msgid, referenceSize, NULL, action);
+}
+
+kern_return_t
+OSAction::CreateWithTypeName_Impl(
+ OSObject * target,
+ uint64_t targetmsgid,
+ uint64_t msgid,
+ size_t referenceSize,
+ OSString * typeName,
+ OSAction ** action)
+{
+ return OSActionCreateWithTypeNameInternal(target, targetmsgid, msgid, referenceSize, typeName, false, action);
}
void
ivars->abortedHandler = NULL;
}
OSSafeReleaseNULL(ivars->target);
+ OSSafeReleaseNULL(ivars->typeName);
IOSafeDeleteNULL(ivars, uint8_t, ivars->referenceSize + sizeof(OSAction_IVars));
}
return super::free();
}
}
-/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
struct IODispatchSource_IVars {
queue_chain_t link;
}
kern_return_t
-IMPL(IODispatchSource, SetEnable)
+IODispatchSource::SetEnable_Impl(
+ bool enable)
{
return SetEnableWithCompletion(enable, NULL);
}
-/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
struct IOInterruptDispatchSource_IVars {
IOService * provider;
uint32_t intIndex;
+ int interruptType;
IOSimpleLock * lock;
thread_t waiter;
uint64_t count;
thread_wakeup_thread((event_t) ivars, ivars->waiter);
ivars->waiter = NULL;
}
+ if (kIOInterruptTypeLevel & ivars->interruptType) {
+ ivars->provider->disableInterrupt(ivars->intIndex);
+ }
IOSimpleLockUnlockEnableInterrupt(ivars->lock, is);
}
kern_return_t
-IMPL(IOInterruptDispatchSource, Create)
+IOInterruptDispatchSource::Create_Impl(
+ IOService * provider,
+ uint32_t index,
+ IODispatchQueue * queue,
+ IOInterruptDispatchSource ** source)
{
IOReturn ret;
IOInterruptDispatchSource * inst;
inst->ivars->lock = IOSimpleLockAlloc();
+ ret = provider->getInterruptType(index, &inst->ivars->interruptType);
+ if (kIOReturnSuccess != ret) {
+ OSSafeReleaseNULL(inst);
+ return ret;
+ }
ret = provider->registerInterrupt(index, inst, IOInterruptDispatchSourceInterrupt, inst->ivars);
if (kIOReturnSuccess == ret) {
inst->ivars->intIndex = index;
inst->ivars->provider = provider;
+ inst->ivars->provider->retain();
*source = inst;
}
return ret;
}
kern_return_t
-IMPL(IOInterruptDispatchSource, GetInterruptType)
+IOInterruptDispatchSource::GetInterruptType_Impl(
+ IOService * provider,
+ uint32_t index,
+ uint64_t * interruptType)
{
IOReturn ret;
int type;
if (ivars && ivars->provider) {
ret = ivars->provider->unregisterInterrupt(ivars->intIndex);
assert(kIOReturnSuccess == ret);
+ ivars->provider->release();
}
if (ivars && ivars->lock) {
}
kern_return_t
-IMPL(IOInterruptDispatchSource, SetHandler)
+IOInterruptDispatchSource::SetHandler_Impl(
+ OSAction * action)
{
IOReturn ret;
OSAction * oldAction;
}
kern_return_t
-IMPL(IOInterruptDispatchSource, SetEnableWithCompletion)
+IOInterruptDispatchSource::SetEnableWithCompletion_Impl(
+ bool enable,
+ IODispatchSourceCancelHandler handler)
{
IOReturn ret;
IOInterruptState is;
}
kern_return_t
-IMPL(IOInterruptDispatchSource, Cancel)
+IOInterruptDispatchSource::Cancel_Impl(
+ IODispatchSourceCancelHandler handler)
{
return kIOReturnUnsupported;
}
kern_return_t
-IMPL(IOInterruptDispatchSource, CheckForWork)
+IOInterruptDispatchSource::CheckForWork_Impl(
+ const IORPC rpc,
+ bool synchronous)
{
IOReturn ret = kIOReturnNotReady;
IOInterruptState is;
+ bool willWait;
wait_result_t waitResult;
uint64_t icount;
uint64_t itime;
ivars->waiter = self;
waitResult = assert_wait((event_t) ivars, THREAD_INTERRUPTIBLE);
}
+ willWait = (synchronous && (waitResult == THREAD_WAITING));
+ if (willWait && (kIOInterruptTypeLevel & ivars->interruptType) && ivars->enable) {
+ ivars->provider->enableInterrupt(ivars->intIndex);
+ }
IOSimpleLockUnlockEnableInterrupt(ivars->lock, is);
- if (synchronous && (waitResult == THREAD_WAITING)) {
+ if (willWait) {
waitResult = thread_block(THREAD_CONTINUE_NULL);
if (THREAD_INTERRUPTED == waitResult) {
+ is = IOSimpleLockLockDisableInterrupt(ivars->lock);
+ ivars->waiter = NULL;
+ IOSimpleLockUnlockEnableInterrupt(ivars->lock, is);
break;
}
}
}
void
-IMPL(IOInterruptDispatchSource, InterruptOccurred)
+IOInterruptDispatchSource::InterruptOccurred_Impl(
+ OSAction * action,
+ uint64_t count,
+ uint64_t time)
{
}
-/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
enum {
kIOServiceNotificationTypeCount = kIOServiceNotificationTypeLast + 1,
};
kern_return_t
-IMPL(IOServiceNotificationDispatchSource, Create)
+IOServiceNotificationDispatchSource::Create_Impl(
+ OSDictionary * matching,
+ uint64_t options,
+ IODispatchQueue * queue,
+ IOServiceNotificationDispatchSource ** notification)
{
IOUserServer * us;
IOReturn ret;
}
kern_return_t
-IMPL(IOServiceNotificationDispatchSource, CopyNextNotification)
+IOServiceNotificationDispatchSource::CopyNextNotification_Impl(
+ uint64_t * type,
+ IOService ** service,
+ uint64_t * options)
{
IOService * next;
uint32_t idx;
}
kern_return_t
-IMPL(IOServiceNotificationDispatchSource, SetHandler)
+IOServiceNotificationDispatchSource::SetHandler_Impl(
+ OSAction * action)
{
IOReturn ret;
bool notifyReady;
}
kern_return_t
-IMPL(IOServiceNotificationDispatchSource, SetEnableWithCompletion)
+IOServiceNotificationDispatchSource::SetEnableWithCompletion_Impl(
+ bool enable,
+ IODispatchSourceCancelHandler handler)
{
if (enable == ivars->enable) {
return kIOReturnSuccess;
}
kern_return_t
-IMPL(IOServiceNotificationDispatchSource, Cancel)
+IOServiceNotificationDispatchSource::Cancel_Impl(
+ IODispatchSourceCancelHandler handler)
{
return kIOReturnUnsupported;
}
kern_return_t
-IMPL(IOServiceNotificationDispatchSource, CheckForWork)
+IOServiceNotificationDispatchSource::CheckForWork_Impl(
+ const IORPC rpc,
+ bool synchronous)
{
return kIOReturnNotReady;
}
return kIOReturnUnsupported;
}
-/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
kern_return_t
IOUserServer::waitInterruptTrap(void * p1, void * p2, void * p3, void * p4, void * p5, void * p6)
IOInterruptDispatchSource_IVars * ivars;
IOInterruptDispatchSourcePayload payload;
+ bool willWait;
wait_result_t waitResult;
thread_t self;
ivars->waiter = self;
waitResult = assert_wait((event_t) ivars, THREAD_INTERRUPTIBLE);
}
+ willWait = (waitResult == THREAD_WAITING);
+ if (willWait && (kIOInterruptTypeLevel & ivars->interruptType) && ivars->enable) {
+ ivars->provider->enableInterrupt(ivars->intIndex);
+ }
IOSimpleLockUnlockEnableInterrupt(ivars->lock, is);
- if (waitResult == THREAD_WAITING) {
+ if (willWait) {
waitResult = thread_block(THREAD_CONTINUE_NULL);
if (THREAD_INTERRUPTED == waitResult) {
+ is = IOSimpleLockLockDisableInterrupt(ivars->lock);
+ ivars->waiter = NULL;
+ IOSimpleLockUnlockEnableInterrupt(ivars->lock, is);
break;
}
}
return ret;
}
-/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
kern_return_t
-IMPL(IOUserServer, Create)
+IOUserServer::Create_Impl(
+ const char * name,
+ uint64_t tag,
+ uint64_t options,
+ IOUserServer ** server)
{
IOReturn ret;
IOUserServer * us;
}
kern_return_t
-IMPL(IOUserServer, Exit)
+IOUserServer::Exit_Impl(
+ const char * reason)
{
return kIOReturnUnsupported;
}
kern_return_t
-IMPL(IOUserServer, LoadModule)
+IOUserServer::LoadModule_Impl(
+ const char * path)
{
return kIOReturnUnsupported;
}
-/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
kern_return_t
-IMPL(IODispatchQueue, Create)
+IODispatchQueue::Create_Impl(
+ const char * name,
+ uint64_t options,
+ uint64_t priority,
+ IODispatchQueue ** queue)
{
IODispatchQueue * result;
IOUserServer * us;
}
kern_return_t
-IMPL(IODispatchQueue, SetPort)
+IODispatchQueue::SetPort_Impl(
+ mach_port_t port)
{
if (MACH_PORT_NULL != ivars->serverPort) {
return kIOReturnNotReady;
kext->setDriverKitUUID(new_uuid);
}
-bool
-IOUserServer::serviceMatchesCDHash(IOService *service)
+void
+IOUserServer::setCheckInToken(IOUserServerCheckInToken *token)
{
- OSObject *obj = NULL;
- bool result = false;
- OSString *requiredCDHashStr = NULL;
- const char *requiredCDHash = NULL;
- char taskCDHash[CS_CDHASH_LEN];
-
- task_t owningTask = this->fOwningTask;
- if (!owningTask) {
- printf("%s: fOwningTask not found\n", __FUNCTION__);
- goto out;
- }
-
- obj = service->copyProperty(gIOUserServerCDHashKey);
- requiredCDHashStr = OSDynamicCast(OSString, obj);
- if (!requiredCDHashStr) {
- printf("%s: required cdhash not found as property of personality\n", __FUNCTION__);
- goto out;
- }
-
- requiredCDHash = requiredCDHashStr->getCStringNoCopy();
- if (!requiredCDHash) {
- printf("%s: required cdhash unable to be read as string\n", __FUNCTION__);
- goto out;
- }
-
- if (strlen(requiredCDHash) != CS_CDHASH_LEN * 2) {
- printf("%s: required cdhash string has incorrect length\n", __FUNCTION__);
- goto out;
+ if (token != NULL && fCheckInToken == NULL) {
+ token->retain();
+ fCheckInToken = token;
+ } else {
+ printf("%s: failed to set check in token. token=%p, fCheckInToken=%p\n", __FUNCTION__, token, fCheckInToken);
}
+}
- get_task_cdhash(owningTask, taskCDHash);
- for (int i = 0; i < (int)CS_CDHASH_LEN * 2; i++) {
- uint8_t which = (i + 1) & 0x1; /* 1 for upper nibble, 0 for lower */
- uint8_t nibble = requiredCDHash[i];
- uint8_t byte = taskCDHash[i / 2];
- if ('0' <= nibble && nibble <= '9') {
- nibble -= '0';
- } else if ('a' <= nibble && nibble <= 'f') {
- nibble -= 'a' - 10;
- } else if ('A' <= nibble && nibble <= 'F') {
- nibble -= 'A' - 10;
- } else {
- printf("%s: required cdhash contains invalid token '%c'\n", __FUNCTION__, nibble);
- goto out;
- }
-
- /*
- * Decide which half of the byte to compare
- */
- if (nibble != (which ? (byte >> 4) : (byte & 0x0f))) {
- printf("%s: required cdhash %s in personality does not match service\n", __FUNCTION__, requiredCDHash);
- goto out;
- }
+bool
+IOUserServer::serviceMatchesCheckInToken(IOUserServerCheckInToken *token)
+{
+ if (token != NULL) {
+ return token == fCheckInToken;
+ } else {
+ printf("%s: null check in token\n", __FUNCTION__);
+ return false;
}
-
- result = true;
-out:
- OSSafeReleaseNULL(obj);
- return result;
}
bool
const char * resultClassName;
uint64_t resultFlags;
- size_t replySize;
+ mach_msg_size_t replySize;
uint32_t methodCount;
const uint64_t * methods;
IODispatchQueue * queue;
ret = kIOReturnUnsupportedMode;
service = OSDynamicCast(IOService, obj);
+ action = OSDynamicCast(OSAction, obj);
if (!service) {
// xxx other classes hosted
resultFlags |= kOSObjectRPCKernel;
const OSMetaClass * meta;
meta = obj->getMetaClass();
IOLockLock(fLock);
+ if (action) {
+ str = action->ivars->typeName;
+ if (str) {
+ userMeta = (typeof(userMeta))fClasses->getObject(str);
+ }
+ }
while (meta && !userMeta) {
str = (OSString *) meta->getClassNameSymbol();
userMeta = (typeof(userMeta))fClasses->getObject(str);
}
if (userMeta) {
if (kOSObjectRPCRemote & resultFlags) {
- while (userMeta && !(kOSClassCanRemote & userMeta->description->flags)) {
- userMeta = userMeta->superMeta;
+ if (!action) {
+ /* Special case: For OSAction subclasses, do not use the superclass */
+ while (userMeta && !(kOSClassCanRemote & userMeta->description->flags)) {
+ userMeta = userMeta->superMeta;
+ }
}
if (userMeta) {
resultClassName = userMeta->description->name;
resultClassName = str->getCStringNoCopy();
ret = kIOReturnSuccess;
}
+ } else if (kIODKLogSetup & gIODKDebug) {
+ DKLOG("userMeta %s was not found in fClasses\n", str->getCStringNoCopy());
+ IOLockLock(fLock);
+ fClasses->iterateObjects(^bool (const OSSymbol * key, OSObject * val) {
+ DKLOG(" fClasses[\"%s\"] => %p\n", key->getCStringNoCopy(), val);
+ return false;
+ });
+ IOLockUnlock(fLock);
}
}
OSSafeReleaseNULL(prop);
if ((kIOReturnSuccess == ret) && (kOSObjectRPCRemote & resultFlags)) {
target = obj;
- if ((action = OSDynamicCast(OSAction, obj))) {
+ if (action) {
if (action->ivars->referenceSize) {
resultFlags |= kOSObjectRPCKernel;
} else {
}
if (kIODKLogIPC & gIODKDebug) {
- DKLOG("instantiate %s\n", obj->getMetaClass()->getClassName());
+ DKLOG("instantiate object %s with user class %s\n", obj->getMetaClass()->getClassName(), str ? str->getCStringNoCopy() : "(null)");
}
if (kIOReturnSuccess != ret) {
return ret;
}
-/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
IOReturn
IOUserServer::kernelDispatch(OSObject * obj, IORPC rpc)
}
-/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
OSObject *
IOUserServer::target(OSAction * action, IORPCMessage * message)
message->objects[0] = (OSObjectRef) object;
if (kIORPCMessageRemote & message->flags) {
object->retain();
+#ifndef __clang_analyzer__
+ // Hide the release of 'action' from the clang static analyzer to suppress
+ // an overrelease diagnostic. The analyzer doesn't have a way to express the
+ // non-standard contract of this method, which is that it releases 'action' when
+ // the message flags have kIORPCMessageRemote set.
action->release();
+#endif
}
if (kIODKLogIPC & gIODKDebug) {
DKLOG("TARGET %s msg 0x%qx from 0x%qx\n", object->getMetaClass()->getClassName(), message->msgid, action->ivars->msgid);
return object;
}
-/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
kern_return_t
uext_server(ipc_kmsg_t requestkmsg, ipc_kmsg_t * pReply)
return oneway ? MIG_NO_REPLY : KERN_SUCCESS;
}
-/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#define MAX_OBJECT_COUNT(mach, size, message) \
- ((((size) + ((uintptr_t) (mach))) - ((uintptr_t) (&message->objects[0]))) / sizeof(OSObjectRef))
+ ((uint32_t)(((((size) + ((uintptr_t) (mach))) - ((uintptr_t) (&message->objects[0]))) / sizeof(OSObjectRef))))
kern_return_t
IOUserServerUEXTTrap(OSObject * object, void * p1, void * p2, void * p3, void * p4, void * p5, void * p6)
size_t inSize = (uintptr_t) p2;
user_addr_t out = (uintptr_t) p3;
size_t outSize = (uintptr_t) p4;
- mach_port_name_t objectName1 = (uintptr_t) p5;
+ mach_port_name_t objectName1 = (mach_port_name_t)(uintptr_t) p5;
size_t totalSize;
OSObject * objectArg1;
mach = (typeof(mach))(p - refs * sizeof(*descs) - sizeof(*mach));
mach->msgh.msgh_id = kIORPCVersionCurrent;
- mach->msgh.msgh_size = sizeof(IORPCMessageMach) + refs * sizeof(*descs) + inSize;
- mach->msgh_body.msgh_descriptor_count = refs;
+ mach->msgh.msgh_size = (mach_msg_size_t) (sizeof(IORPCMessageMach) + refs * sizeof(*descs) + inSize); // totalSize was checked
+ mach->msgh_body.msgh_descriptor_count = ((mach_msg_size_t) refs);
rpc.message = mach;
rpc.sendSize = mach->msgh.msgh_size;
rpc.reply = (IORPCMessageMach *) (p + inSize);
- rpc.replySize = sizeof(buffer.buffer) - inSize;
+ rpc.replySize = ((uint32_t) (sizeof(buffer.buffer) - inSize)); // inSize was checked
message->objects[0] = 0;
if ((action = OSDynamicCast(OSAction, object))) {
return ret;
}
-/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
IOReturn
IOUserServer::rpc(IORPC rpc)
message = IORPCMessageFromMach(mach, false);
if (!message) {
- ret = kIOReturnIPCError;
+ return kIOReturnIPCError;
}
msgid = message->msgid;
machid = (msgid >> 32);
IOLockFree(fLock);
}
OSSafeReleaseNULL(fServices);
+ OSSafeReleaseNULL(fCheckInToken);
IOUserClient::free();
}
return ret;
}
+IOReturn
+IOUserServer::registerClass(OSClassDescription * desc, uint32_t size, OSSharedPtr<OSUserMetaClass>& pCls)
+{
+ OSUserMetaClass* pClsRaw = NULL;
+ IOReturn result = registerClass(desc, size, &pClsRaw);
+ if (result == kIOReturnSuccess) {
+ pCls.reset(pClsRaw, OSRetain);
+ }
+ return result;
+}
+
IOReturn
IOUserServer::setRootQueue(IODispatchQueue * queue)
{
if (args->scalarOutputCount != 1) {
return kIOReturnBadArgument;
}
+ if (!(kIODKDisableCheckInTokenVerification & gIODKDebug)) {
+ if (args->scalarInputCount != 1) {
+ return kIOReturnBadArgument;
+ }
+ mach_port_name_t checkInPortName = ((typeof(checkInPortName))args->scalarInput[0]);
+ OSObject * obj = iokit_lookup_object_with_port_name(checkInPortName, IKOT_IOKIT_IDENT, fOwningTask);
+ IOUserServerCheckInToken * retrievedToken = OSDynamicCast(IOUserServerCheckInToken, obj);
+ if (retrievedToken != NULL) {
+ setCheckInToken(retrievedToken);
+ } else {
+ OSSafeReleaseNULL(obj);
+ return kIOReturnBadArgument;
+ }
+ OSSafeReleaseNULL(obj);
+ }
portname = iokit_make_send_right(fOwningTask, this, IKOT_UEXT_OBJECT);
assert(portname);
args->scalarOutput[0] = portname;
OSObjectUserVars * vars;
OSObject * prop;
OSString * str;
- OSSymbolConstPtr bundleID;
+ OSSymbol const* bundleID;
char execPath[1024];
vars = IONewZero(OSObjectUserVars, 1);
return ret;
}
+IOReturn
+IOUserServer::serviceNewUserClient(IOService * service, task_t owningTask, void * securityID,
+ uint32_t type, OSDictionary * properties, OSSharedPtr<IOUserClient>& handler)
+{
+ IOUserClient* handlerRaw = NULL;
+ IOReturn result = serviceNewUserClient(service, owningTask, securityID, type, properties, &handlerRaw);
+ handler.reset(handlerRaw, OSNoRetain);
+ return result;
+}
+
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static IOPMPowerState
}
IOReturn
-IOUserServer::powerStateWillChangeTo(IOPMPowerFlags flags, unsigned long state, IOService * service)
+IOUserServer::serviceSetPowerState(IOService * controllingDriver, IOService * service, IOPMPowerFlags flags, unsigned long state)
{
IOReturn ret;
if (service->reserved->uvars) {
if (!fSystemOff && !(kIODKDisablePM & gIODKDebug)) {
service->reserved->uvars->willPower = true;
+ service->reserved->uvars->willPowerState = state;
+ service->reserved->uvars->controllingDriver = controllingDriver;
if (kIODKLogPM & gIODKDebug) {
- DKLOG(DKS "::powerStateWillChangeTo(%ld) 0x%qx, %d\n", DKN(service), state, fPowerStates, fSystemPowerAck);
+ DKLOG(DKS "::serviceSetPowerState(%ld) 0x%qx, %d\n", DKN(service), state, fPowerStates, fSystemPowerAck);
}
- ret = service->SetPowerState(flags);
+ ret = service->SetPowerState((uint32_t) flags);
if (kIOReturnSuccess == ret) {
return 20 * 1000 * 1000;
}
return kIOPMAckImplied;
}
+IOReturn
+IOUserServer::powerStateWillChangeTo(IOPMPowerFlags flags, unsigned long state, IOService * service)
+{
+ return kIOPMAckImplied;
+}
+
IOReturn
IOUserServer::powerStateDidChangeTo(IOPMPowerFlags flags, unsigned long state, IOService * service)
{
}
kern_return_t
-IMPL(IOService, SetPowerState)
+IOService::SetPowerState_Impl(
+ uint32_t powerFlags)
{
if (kIODKLogPM & gIODKDebug) {
DKLOG(DKS "::SetPowerState(%d), %d\n", DKN(this), powerFlags, reserved->uvars->willPower);
if (reserved->uvars
&& reserved->uvars->userServer
&& reserved->uvars->willPower) {
+ IOReturn ret;
reserved->uvars->willPower = false;
- acknowledgePowerChange(reserved->uvars->userServer);
+ ret = reserved->uvars->controllingDriver->setPowerState(reserved->uvars->willPowerState, this);
+ if (kIOPMAckImplied == ret) {
+ acknowledgeSetPowerState();
+ }
return kIOReturnSuccess;
}
return kIOReturnNotReady;
}
kern_return_t
-IMPL(IOService, ChangePowerState)
+IOService::ChangePowerState_Impl(
+ uint32_t powerFlags)
{
switch (powerFlags) {
case kIOServicePowerCapabilityOff:
}
kern_return_t
-IMPL(IOService, Create)
+IOService::Create_Impl(
+ IOService * provider,
+ const char * propertiesKey,
+ IOService ** result)
{
OSObject * inst;
IOService * service;
}
kern_return_t
-IMPL(IOService, Terminate)
+IOService::Terminate_Impl(
+ uint64_t options)
{
IOUserServer * us;
}
kern_return_t
-IMPL(IOService, NewUserClient)
+IOService::NewUserClient_Impl(
+ uint32_t type,
+ IOUserClient ** userClient)
{
return kIOReturnError;
}
kern_return_t
-IMPL(IOService, SearchProperty)
+IOService::SearchProperty_Impl(
+ const char * name,
+ const char * plane,
+ uint64_t options,
+ OSContainer ** property)
{
- OSObject * object;
+ OSObject * object;
+ IOOptionBits regOptions;
if (kIOServiceSearchPropertyParents & options) {
- options = kIORegistryIterateParents | kIORegistryIterateRecursively;
+ regOptions = kIORegistryIterateParents | kIORegistryIterateRecursively;
} else {
- options = 0;
+ regOptions = 0;
}
- object = copyProperty(name, IORegistryEntry::getPlane(plane), options);
+ object = copyProperty(name, IORegistryEntry::getPlane(plane), regOptions);
*property = object;
return object ? kIOReturnSuccess : kIOReturnNotFound;
}
kern_return_t
-IMPL(IOService, CopyProviderProperties)
+IOService::CopyProviderProperties_Impl(
+ OSArray * propertyKeys,
+ OSArray ** properties)
{
IOReturn ret;
OSArray * result;
{
IOReturn ret;
IOService * pmProvider;
+ bool joinTree;
DKLOG(DKS "::start(" DKS ") %s\n", DKN(service), DKN(provider), result ? "ok" : "fail");
fRootNotifier = true;
}
+ joinTree = false;
if (!(kIODKDisablePM & gIODKDebug) && !service->pm_vars) {
service->PMinit();
ret = service->registerPowerDriver(this, sPowerStates, sizeof(sPowerStates) / sizeof(sPowerStates[0]));
assert(kIOReturnSuccess == ret);
+ joinTree = true;
+ }
- pmProvider = service;
- while (pmProvider && !pmProvider->inPlane(gIOPowerPlane)) {
- pmProvider = pmProvider->getProvider();
- }
- if (pmProvider) {
- OSObject * prop;
- OSString * str;
- prop = pmProvider->copyProperty("non-removable");
- if (prop) {
- str = OSDynamicCast(OSString, prop);
- if (str && str->isEqualTo("yes")) {
- pmProvider = NULL;
- }
- prop->release();
+ pmProvider = service;
+ while (pmProvider && !pmProvider->inPlane(gIOPowerPlane)) {
+ pmProvider = pmProvider->getProvider();
+ }
+ if (pmProvider) {
+ OSObject * prop;
+ OSString * str;
+ prop = pmProvider->copyProperty("non-removable");
+ if (prop) {
+ str = OSDynamicCast(OSString, prop);
+ if (str && str->isEqualTo("yes")) {
+ pmProvider = NULL;
}
+ prop->release();
}
- if (pmProvider) {
- IOLockLock(fLock);
- unsigned int idx = fServices->getNextIndexOfObject(service, 0);
- assert(idx <= 63);
- fPowerStates |= (1ULL << idx);
- IOLockUnlock(fLock);
+ }
+ if (!(kIODKDisablePM & gIODKDebug) && pmProvider) {
+ IOLockLock(fLock);
+ unsigned int idx = fServices->getNextIndexOfObject(service, 0);
+ assert(idx <= 63);
+ fPowerStates |= (1ULL << idx);
+ IOLockUnlock(fLock);
+
+ if (joinTree) {
pmProvider->joinPMtree(service);
service->reserved->uvars->userServerPM = true;
}
}
if (willTerminate) {
- ret = client->Stop(provider);
+ if (IOServicePH::serverSlept()) {
+ client->Stop_async(provider);
+ ret = kIOReturnOffline;
+ } else {
+ ret = client->Stop(provider);
+ }
if (kIOReturnSuccess != ret) {
- ret = client->IOService::Stop(provider);
+ IOUserServer::serviceDidStop(client, provider);
+ ret = kIOReturnSuccess;
}
}
}
}
kern_return_t
-IMPL(IOService, Stop)
+IOService::Stop_Impl(
+ IOService * provider)
{
IOUserServer::serviceDidStop(this, provider);
return kIOReturnSuccess;
}
+void
+IOService::Stop_async_Impl(
+ IOService * provider)
+{
+}
+
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#undef super
};
void
-IMPL(IOUserClient, KernelCompletion)
+IOUserClient::KernelCompletion_Impl(
+ OSAction * action,
+ IOReturn status,
+ const unsigned long long * asyncData,
+ uint32_t asyncDataCount)
{
IOUserUserClientActionRef * ref;
}
kern_return_t
-IMPL(IOUserClient, _ExternalMethod)
+IOUserClient::_ExternalMethod_Impl(
+ uint64_t selector,
+ const unsigned long long * scalarInput,
+ uint32_t scalarInputCount,
+ OSData * structureInput,
+ IOMemoryDescriptor * structureInputDescriptor,
+ unsigned long long * scalarOutput,
+ uint32_t * scalarOutputCount,
+ uint64_t structureOutputMaximumSize,
+ OSData ** structureOutput,
+ IOMemoryDescriptor * structureOutputDescriptor,
+ OSAction * completion)
{
return kIOReturnUnsupported;
}
kr = kIOReturnUnsupported;
structureInput = NULL;
action = NULL;
+ ref = NULL;
if (args->structureInputSize) {
structureInput = OSData::withBytesNoCopy((void *) args->structureInput, args->structureInputSize);
assert(KERN_SUCCESS == kr);
ref = (typeof(ref))action->GetReference();
bcopy(args->asyncReference, &ref->asyncRef[0], args->asyncReferenceCount * sizeof(ref->asyncRef[0]));
+
+ kr = action->SetAbortedHandler(^(void) {
+ IOUserUserClientActionRef * ref;
+ IOReturn ret;
+
+ ref = (typeof(ref))action->GetReference();
+ ret = releaseAsyncReference64(ref->asyncRef);
+ assert(kIOReturnSuccess == ret);
+ bzero(&ref->asyncRef[0], sizeof(ref->asyncRef));
+ });
+ assert(KERN_SUCCESS == kr);
}
if (args->structureVariableOutputData) {
OSSafeReleaseNULL(action);
if (kIOReturnSuccess != kr) {
+ if (ref) {
+ // mig will destroy any async port, remove our pointer to it
+ bzero(&ref->asyncRef[0], sizeof(ref->asyncRef));
+ }
return kr;
}
if (structureOutput) {
}
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+void
+IOUserServerCheckInToken::setNoSendersNotification(IOUserServerCheckInNotificationHandler handler,
+ void* handlerArgs)
+{
+ this->handler = handler;
+ this->handlerArgs = handlerArgs;
+}
+
+void
+IOUserServerCheckInToken::notifyNoSenders(IOUserServerCheckInToken *token)
+{
+ if (token->handler) {
+ token->handler(token, token->handlerArgs);
+ }
+}
+
+void
+IOUserServerCheckInToken::clearNotification()
+{
+ this->handler = NULL;
+ this->handlerArgs = NULL;
+}
+
+IOUserServerCheckInToken *
+IOUserServerCheckInToken::create()
+{
+ IOUserServerCheckInToken *me = new IOUserServerCheckInToken;
+ if (me && !me->init()) {
+ me->release();
+ return NULL;
+ }
+ me->clearNotification();
+ return me;
+}
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */