Loading...
--- xnu/xnu-12377.121.6/iokit/Kernel/IOUserServer.cpp
+++ xnu/xnu-11215.41.3/iokit/Kernel/IOUserServer.cpp
@@ -47,7 +47,6 @@
#include <IOKit/IOUserServer.h>
#include <IOKit/IOInterruptEventSource.h>
#include <IOKit/IOTimerEventSource.h>
-#include <IOKit/IODeviceTreeSupport.h>
#include <IOKit/pwr_mgt/RootDomain.h>
#include <IOKit/pwr_mgt/IOPowerConnection.h>
#include <libkern/c++/OSAllocation.h>
@@ -61,10 +60,7 @@
#include <sys/proc.h>
#include <sys/reboot.h>
#include <sys/codesign.h>
-#include <vm/vm_iokit.h>
-#include <mach_debug/mach_debug_types.h>
#include "IOKitKernelInternal.h"
-#include "IOServicePMPrivate.h"
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
@@ -90,17 +86,10 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
-enum{
- kIOUserServerCheckInTimeoutMSecs = 120000ULL,
- kIOUserServerCheckInMaxRetry = 3,
-};
-
TUNABLE(SInt64, gIODKDebug, "dk", kIODKEnable);
#if DEBUG || DEVELOPMENT
-uint64_t driverkit_checkin_timed_out = 0;
TUNABLE(bool, disable_dext_crash_reboot, "disable_dext_crash_reboot", 0);
-extern "C" kern_return_t kern_register_userspace_coredump(task_t task, const char * name, boolean_t emergency);
#endif /* DEBUG || DEVELOPMENT */
extern bool restore_boot;
@@ -165,6 +154,32 @@
OSDefineMetaClassAndStructors(IOUserService, IOService)
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+class IOUserUserClient : public IOUserClient
+{
+ OSDeclareDefaultStructors(IOUserUserClient);
+public:
+ task_t fTask;
+ OSDictionary * fWorkGroups;
+ OSDictionary * fEventLinks;
+ IOLock * fLock;
+
+ IOReturn setTask(task_t task);
+ IOReturn eventlinkConfigurationTrap(void * p1, void * p2, void * p3, void * p4, void * p5, void * p6);
+ IOReturn workgroupConfigurationTrap(void * p1, void * p2, void * p3, void * p4, void * p5, void * p6);
+
+ virtual bool init( OSDictionary * dictionary ) APPLE_KEXT_OVERRIDE;
+ virtual void free() APPLE_KEXT_OVERRIDE;
+ virtual void stop(IOService * provider) APPLE_KEXT_OVERRIDE;
+ virtual IOReturn clientClose(void) APPLE_KEXT_OVERRIDE;
+ virtual IOReturn setProperties(OSObject * properties) APPLE_KEXT_OVERRIDE;
+ virtual IOReturn externalMethod(uint32_t selector, IOExternalMethodArguments * args,
+ IOExternalMethodDispatch * dispatch, OSObject * target, void * reference) APPLE_KEXT_OVERRIDE;
+ virtual IOReturn clientMemoryForType(UInt32 type,
+ IOOptionBits * options,
+ IOMemoryDescriptor ** memory) APPLE_KEXT_OVERRIDE;
+ virtual IOExternalTrap * getTargetAndTrapForIndex( IOService **targetP, UInt32 index ) APPLE_KEXT_OVERRIDE;
+};
OSDefineMetaClassAndStructors(IOUserServerCheckInToken, OSObject);
OSDefineMetaClassAndStructors(_IOUserServerCheckInCancellationHandler, OSObject);
@@ -1468,11 +1483,7 @@
bool canceled;
};
-void
-IOInterruptDispatchSourceInterrupt(OSObject * target, void * refCon,
- IOService * nub, int source );
-
-void
+static void
IOInterruptDispatchSourceInterrupt(OSObject * target, void * refCon,
IOService * nub, int source )
{
@@ -1608,11 +1619,6 @@
if (enable == ivars->enable) {
return kIOReturnSuccess;
}
-
- if (ivars->canceled) {
- return kIOReturnUnsupported;
- }
- assert(ivars->provider != NULL);
if (enable) {
is = IOSimpleLockLockDisableInterrupt(ivars->lock);
@@ -1811,7 +1817,7 @@
inst->ivars->notifier = IOService::addMatchingNotification(gIOMatchedNotification, matching, 0 /*priority*/,
^bool (IOService * newService, IONotifier * notifier) {
bool notifyReady = false;
- IONotifier * interest = NULL;
+ IONotifier * interest;
OSObject * serverName;
bool okToUse;
@@ -1852,45 +1858,35 @@
IOLockLock(inst->ivars->lock);
notifyReady = (0 == inst->ivars->pending[kIOServiceNotificationTypeMatched]->getCount());
inst->ivars->pending[kIOServiceNotificationTypeMatched]->setObject(newService);
- bool needInterest = (NULL == inst->ivars->interestNotifiers->getObject((const OSSymbol *) newService));
IOLockUnlock(inst->ivars->lock);
- if (needInterest) {
- interest = newService->registerInterest(gIOGeneralInterest,
- ^IOReturn (uint32_t messageType, IOService * provider,
- void * messageArgument, size_t argSize) {
- IONotifier * interest;
- bool notifyReady = false;
-
- // after the notifier remove, IOServiceNotificationDispatchSource::free
- // will not wait for this code to complete
- if (!inst->taggedTryRetain(NULL)) {
- return kIOReturnSuccess;
+ interest = newService->registerInterest(gIOGeneralInterest,
+ ^IOReturn (uint32_t messageType, IOService * provider,
+ void * messageArgument, size_t argSize) {
+ IONotifier * interest;
+ bool notifyReady = false;
+
+ switch (messageType) {
+ case kIOMessageServiceIsTerminated:
+ IOLockLock(inst->ivars->lock);
+ notifyReady = (0 == inst->ivars->pending[kIOServiceNotificationTypeTerminated]->getCount());
+ inst->ivars->pending[kIOServiceNotificationTypeTerminated]->setObject(provider);
+ if (inst->ivars->interestNotifiers != NULL) {
+ interest = (typeof(interest))inst->ivars->interestNotifiers->getObject((const OSSymbol *) newService);
+ assert(interest);
+ interest->remove();
+ inst->ivars->interestNotifiers->removeObject((const OSSymbol *) newService);
}
-
- switch (messageType) {
- case kIOMessageServiceIsTerminated:
- IOLockLock(inst->ivars->lock);
- notifyReady = (0 == inst->ivars->pending[kIOServiceNotificationTypeTerminated]->getCount());
- inst->ivars->pending[kIOServiceNotificationTypeTerminated]->setObject(provider);
- if (inst->ivars->interestNotifiers != NULL) {
- interest = (typeof(interest))inst->ivars->interestNotifiers->getObject((const OSSymbol *) newService);
- assert(interest);
- interest->remove();
- inst->ivars->interestNotifiers->removeObject((const OSSymbol *) newService);
- }
- IOLockUnlock(inst->ivars->lock);
- break;
- default:
- break;
- }
- if (notifyReady && inst->ivars->action) {
- inst->ServiceNotificationReady(inst->ivars->action);
- }
- inst->release();
- return kIOReturnSuccess;
- });
- }
+ IOLockUnlock(inst->ivars->lock);
+ break;
+ default:
+ break;
+ }
+ if (notifyReady && inst->ivars->action) {
+ inst->ServiceNotificationReady(inst->ivars->action);
+ }
+ return kIOReturnSuccess;
+ });
if (interest) {
IOLockLock(inst->ivars->lock);
inst->ivars->interestNotifiers->setObject((const OSSymbol *) newService, interest);
@@ -1987,7 +1983,6 @@
for (uint32_t idx = 0; idx < kIOServiceNotificationTypeCount; idx++) {
OSSafeReleaseNULL(ivars->pending[idx]);
}
- OSSafeReleaseNULL(ivars->action);
if (ivars->lock) {
IOLockFree(ivars->lock);
ivars->lock = NULL;
@@ -2311,21 +2306,6 @@
}
kern_return_t
-IOUserServer::Panic_Impl(const char * reason)
-{
- if (isPlatformDriver()) {
- if (strnlen(reason, kIOUserServrMaxPanicReasonLength) == kIOUserServrMaxPanicReasonLength) {
- // Invalid panic message, panic anyways
- panic("%s: dext requested panic", getName());
- } else {
- panic("%s: dext requested panic: \"%s\"", getName(), reason);
- }
- return kIOReturnSuccess;
- }
- return kIOReturnNotPermitted;
-}
-
-kern_return_t
IOUserServer::RegisterService_Impl()
{
kern_return_t ret = IOService::RegisterService_Impl();
@@ -2735,7 +2715,7 @@
IOReturn
IOUserServer::exit(const char * reason)
{
- DKLOG(DKS "::exit(%s)\n", DKN(this), reason);
+ DKLOG("%s::exit(%s)\n", getName(), reason);
Exit(reason);
return kIOReturnSuccess;
}
@@ -2745,30 +2725,11 @@
{
IOReturn ret = kIOReturnError;
if (fOwningTask != NULL) {
- DKLOG(DKS"::kill(%s)\n", DKN(this), reason);
- proc_t unsafe_proc = (proc_t)get_bsdtask_info(fOwningTask);
- proc_t p = proc_ref_nowait(unsafe_proc);
- if (p) {
- taskbsd_kill_and_release(p);
- }
+ DKLOG("%s::kill(%s)\n", getName(), reason);
+ task_bsdtask_kill(fOwningTask);
ret = kIOReturnSuccess;
}
return ret;
-}
-
-void
-IOUserServer::emergencyPanicCoreDumpEnable()
-{
-#if DEVELOPMENT || DEBUG
- if (isPlatformDriver()) {
- // Enable coredump for the first party dext that is causing an imminent panic
- // This is enabled on non-release without requiring an entitlement,
- // so this coredump has only a generic name
- char core_name[MACH_CORE_FILEHEADER_NAMELEN];
- snprintf(core_name, sizeof(core_name), "dext-%d", pid_from_task(fOwningTask));
- kern_register_userspace_coredump(fOwningTask, core_name, TRUE);
- }
-#endif /* DEVELOPMENT || DEBUG */
}
OSObjectUserVars *
@@ -2973,7 +2934,6 @@
return kIOReturnError;
}
IOLockLock(service->reserved->uvars->userServer->fLock);
- service->reserved->uvars->instantiated = true;
userMeta = (typeof(userMeta))service->reserved->uvars->userServer->fClasses->getObject(str);
IOLockUnlock(service->reserved->uvars->userServer->fLock);
}
@@ -3159,15 +3119,15 @@
if (OSObject_Instantiate_ID == message->msgid) {
ret = objectInstantiate(obj, rpc, message);
if (kIOReturnSuccess != ret) {
- DKLOG(DKS ": %s: instantiate failed 0x%x\n", DKN(this), obj->getMetaClass()->getClassName(), ret);
+ DKLOG("%s: instantiate failed 0x%x\n", obj->getMetaClass()->getClassName(), ret);
}
} else {
if (kIODKLogIPC & gIODKDebug) {
- DKLOG(DKS ": %s::Dispatch kernel 0x%qx\n", DKN(this), obj->getMetaClass()->getClassName(), message->msgid);
+ DKLOG("%s::Dispatch kernel 0x%qx\n", obj->getMetaClass()->getClassName(), message->msgid);
}
ret = obj->Dispatch(rpc);
if (kIODKLogIPC & gIODKDebug) {
- DKLOG(DKS ": %s::Dispatch kernel 0x%qx result 0x%x\n", DKN(this), obj->getMetaClass()->getClassName(), message->msgid, ret);
+ DKLOG("%s::Dispatch kernel 0x%qx result 0x%x\n", obj->getMetaClass()->getClassName(), message->msgid, ret);
}
}
@@ -3723,13 +3683,25 @@
ipc_port_t
IOUserServer::copySendRightForObject(OSObject * object, ipc_kobject_type_t type)
{
- return iokit_port_make_send_for_object(object, type);
+ ipc_port_t port;
+ ipc_port_t sendPort = NULL;
+ ipc_kobject_t kobj;
+
+ port = iokit_port_for_object(object, type, &kobj);
+ if (port) {
+ sendPort = ipc_kobject_make_send(port, kobj, type);
+ iokit_release_port(port);
+ }
+
+ return sendPort;
}
OSObject *
IOUserServer::copyObjectForSendRight(ipc_port_t port, ipc_kobject_type_t type)
{
- return iokit_lookup_io_object(port, type);
+ OSObject * object;
+ object = iokit_lookup_io_object(port, type);
+ return object;
}
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
@@ -4034,16 +4006,13 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
-static kern_return_t
-acknowledgeSetPowerState(IOService * service);
-
bool
IOUserServer::finalize(IOOptionBits options)
{
OSArray * services;
if (kIODKLogSetup & gIODKDebug) {
- DKLOG(DKS "::finalize(%p)\n", DKN(this), this);
+ DKLOG("%s::finalize(%p)\n", getName(), this);
}
IOLockLock(gIOUserServerLock);
@@ -4063,11 +4032,11 @@
if (can_rematch) {
terminateFlags |= kIOServiceTerminateWithRematchCurrentDext;
} else {
- DKLOG(DKS "::finalize(%p) dext was replaced, do not rematch current dext\n", DKN(this), this);
+ DKLOG("%s::finalize(%p) dext was replaced, do not rematch current dext\n", getName(), this);
}
} else {
terminateFlags |= kIOServiceTerminateWithRematchCurrentDext;
- DKLOG(DKS "::finalize(%p) could not find fCheckInToken\n", DKN(this), this);
+ DKLOG("%s::finalize(%p) could not find fCheckInToken\n", getName(), this);
}
if (services) {
@@ -4076,11 +4045,10 @@
IOService * nextService;
IOService * provider;
bool started = false;
- bool instantiated = false;
nextService = (IOService *) obj;
if (kIODKLogSetup & gIODKDebug) {
- DKLOG(DKS "::terminate(" DKS ")\n", DKN(this), DKN(nextService));
+ DKLOG("%s::terminate(" DKS ")\n", getName(), DKN(nextService));
}
if (nextService->reserved->uvars) {
IOUserClient * nextUserClient = OSDynamicCast(IOUserClient, nextService);
@@ -4088,9 +4056,7 @@
if (nextUserClient) {
nextUserClient->setTerminateDefer(provider, false);
}
- (void)::acknowledgeSetPowerState(nextService);
started = nextService->reserved->uvars->started;
- instantiated = nextService->reserved->uvars->instantiated;
nextService->reserved->uvars->serverDied = true;
serviceDidStop(nextService, provider);
@@ -4098,22 +4064,11 @@
provider->resetRematchProperties();
}
if (started) {
- IOService * provider = nextService;
- while ((provider = provider->getProvider())) {
- if (-1U != services->getNextIndexOfObject(provider, 0)) {
- break;
- }
- }
- if (!provider) {
- // this service is the root of the set, so only terminate it
- nextService->terminate(terminateFlags);
- }
+ nextService->terminate(terminateFlags);
}
}
- if (!started || !instantiated) {
- DKLOG(DKS "::terminate(" DKS ") server exit before start() instantiated %d\n", DKN(this), DKN(nextService), instantiated);
- // Override started since we are forcing serviceStop to happen
- nextService->reserved->uvars->started = true;
+ if (!started) {
+ DKLOG("%s::terminate(" DKS ") server exit before start()\n", getName(), DKN(nextService));
serviceStop(nextService, NULL);
}
return false;
@@ -4203,7 +4158,6 @@
if (csproc_get_validation_category(current_proc(), &inst->fCSValidationCategory) != KERN_SUCCESS) {
inst->fCSValidationCategory = CS_VALIDATION_CATEGORY_INVALID;
}
- inst->fWorkLoop = IOWorkLoop::workLoop();
inst->setProperty(kIOUserClientDefaultLockingKey, kOSBooleanTrue);
inst->setProperty(kIOUserClientDefaultLockingSetPropertiesKey, kOSBooleanTrue);
@@ -4280,7 +4234,7 @@
bool __block unexpectedExit = false;
if (kIODKLogSetup & gIODKDebug) {
- DKLOG(DKS "::clientClose(%p)\n", DKN(this), this);
+ DKLOG("%s::clientClose(%p)\n", getName(), this);
}
services = NULL;
IOLockLock(fLock);
@@ -4334,14 +4288,7 @@
#endif /* DEVELOPMENT || DEBUG */
if (policy == kOSDextCrashPolicyReboot && allowPanic) {
- emergencyPanicCoreDumpEnable();
- panic("Driver %s has crashed too many times (reason %u:%llu)\n",
- getName(), fTaskCrashReason->osr_namespace, fTaskCrashReason->osr_code);
- }
-
- IOPMrootDomain *rootDomain = IOService::getPMRootDomain();
- if (rootDomain) {
- rootDomain->requestRunMode(kIOPMRunModeFullWake);
+ panic("Driver %s has crashed too many times\n", getName());
}
}
@@ -4373,12 +4320,6 @@
if (fInterruptLock) {
IOSimpleLockFree(fInterruptLock);
}
-}
-
-IOWorkLoop *
-IOUserServer::getWorkLoop() const
-{
- return fWorkLoop;
}
void
@@ -4404,7 +4345,6 @@
if (fTaskCrashReason != OS_REASON_NULL) {
os_reason_free(fTaskCrashReason);
}
- OSSafeReleaseNULL(fWorkLoop);
IOUserClient::free();
}
@@ -4424,7 +4364,7 @@
}
if (kIODKLogSetup & gIODKDebug) {
- DKLOG(DKS "::registerClass %s, %d, %d\n", DKN(this), desc->name, desc->queueNamesSize, desc->methodNamesSize);
+ DKLOG("%s::registerClass %s, %d, %d\n", getName(), desc->name, desc->queueNamesSize, desc->methodNamesSize);
}
if (desc->descriptionSize != size) {
@@ -4644,12 +4584,6 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
-void
-IOUserServer::pageout()
-{
- fPageout = 1;
-}
-
IOReturn
IOUserServer::serviceAttach(IOService * service, IOService * provider)
{
@@ -4666,7 +4600,6 @@
vars->userServer = this;
vars->userServer->retain();
vars->uvarsLock = IOLockAlloc();
- vars->originalProperties = service->dictionaryWithProperties();
IOLockLock(fLock);
if (-1U == fServices->getNextIndexOfObject(service, 0)) {
fServices->setObject(service);
@@ -4726,16 +4659,13 @@
if (ok) {
ret = LoadModule(execPath);
if (kIODKLogSetup & gIODKDebug) {
- DKLOG(DKS "::LoadModule 0x%x %s\n", DKN(this), ret, execPath);
+ DKLOG("%s::LoadModule 0x%x %s\n", getName(), ret, execPath);
}
}
}
OSSafeReleaseNULL(prop);
ret = kIOReturnSuccess;
- if (kIODKLogSetup & gIODKDebug) {
- DKLOG(DKS "::serviceAttach(" DKS ", " DKS ")\n", DKN(this), DKN(service), DKN(provider));
- }
return ret;
}
@@ -4771,18 +4701,15 @@
*handler = NULL;
ret = service->_NewUserClient(type, entitlements, &uc);
- if (kIOReturnSuccess != ret || uc == NULL) {
- OSSafeReleaseNULL(uc);
+ if (kIOReturnSuccess != ret) {
OSSafeReleaseNULL(entitlements);
return ret;
}
userUC = OSDynamicCast(IOUserUserClient, uc);
if (!userUC) {
- if (uc) {
- uc->terminate(kIOServiceTerminateNeedWillTerminate);
- uc->setTerminateDefer(service, false);
- OSSafeReleaseNULL(uc);
- }
+ uc->terminate(kIOServiceTerminateNeedWillTerminate);
+ uc->setTerminateDefer(service, false);
+ OSSafeReleaseNULL(uc);
OSSafeReleaseNULL(entitlements);
return kIOReturnUnsupported;
}
@@ -4907,17 +4834,13 @@
.outputPowerCharacter = kIOPMLowPower,
.inputPowerRequirement = kIOPMLowPower},
{ .version = kIOPMPowerStateVersion1,
- .capabilityFlags = kIOPMAOTPower,
- .outputPowerCharacter = kIOPMAOTPower,
- .inputPowerRequirement = kIOPMAOTPower},
- { .version = kIOPMPowerStateVersion1,
.capabilityFlags = kIOPMPowerOn,
.outputPowerCharacter = kIOPMPowerOn,
.inputPowerRequirement = kIOPMPowerOn},
};
enum {
- kUserServerMaxPowerState = 3
+ kUserServerMaxPowerState = 2
};
IOReturn
@@ -4947,10 +4870,6 @@
if (props->getObject(kIOPMResetPowerStateOnWakeKey) == kOSBooleanTrue) {
service->setProperty(kIOPMResetPowerStateOnWakeKey, kOSBooleanTrue);
}
- fAOTAllow |= (NULL != props->getObject(kIOPMAOTAllowKey));
- if (!(kIODKDisableIOPMSystemOffPhase2Allow & gIODKDebug)) {
- fSystemOffPhase2Allow |= (NULL != props->getObject(kIOPMSystemOffPhase2AllowKey));
- }
OSSafeReleaseNULL(props);
}
service->PMinit();
@@ -5026,6 +4945,29 @@
IOLockLock(fLock);
if (service->reserved->uvars) {
if (!fSystemOff && !(kIODKDisablePM & gIODKDebug)) {
+ OSDictionary * wakeDescription;
+ OSObject * prop;
+ char wakeReasonString[128];
+
+ wakeDescription = OSDictionary::withCapacity(4);
+ if (wakeDescription) {
+ wakeReasonString[0] = 0;
+ getPMRootDomain()->copyWakeReasonString(wakeReasonString, sizeof(wakeReasonString));
+
+ if (wakeReasonString[0]) {
+ prop = OSString::withCString(&wakeReasonString[0]);
+ wakeDescription->setObject(gIOSystemStateWakeDescriptionWakeReasonKey, prop);
+ OSSafeReleaseNULL(prop);
+ }
+#if defined(__arm__) || defined(__arm64__)
+ prop = OSNumber::withNumber(ml_get_conttime_offset(), sizeof(uint64_t) * CHAR_BIT);
+ wakeDescription->setObject(gIOSystemStateWakeDescriptionContinuousTimeOffsetKey, prop);
+ OSSafeReleaseNULL(prop);
+#endif /* defined(__arm__) || defined(__arm64__) */
+ getSystemStateNotificationService()->StateNotificationItemSet(gIOSystemStateWakeDescriptionKey, wakeDescription);
+ OSSafeReleaseNULL(wakeDescription);
+ }
+
service->reserved->uvars->willPower = true;
service->reserved->uvars->willPowerState = state;
service->reserved->uvars->controllingDriver = controllingDriver;
@@ -5037,31 +4979,10 @@
IOLockUnlock(fLock);
if (sendIt) {
- uint32_t driverFlags = (uint32_t) flags;
if (kIODKLogPM & gIODKDebug) {
- DKLOG(DKS "::serviceSetPowerState(%ld, 0x%x) %d\n", DKN(service), state, driverFlags, fSystemPowerAck);
- }
-#if DEBUG || DEVELOPMENT
- bool pageout = false;
- uint64_t pageincount = 0;
- if (gLPWFlags) {
- pageout = fPageout;
- if (pageout) {
- fPageout = false;
- DKLOG(DKS " pageout\n", DKN(service));
- pageincount = vm_task_evict_shared_cache(fOwningTask);
- }
- }
-#endif /* DEBUG || DEVELOPMENT */
-
- ret = service->SetPowerState(driverFlags);
-
-#if DEBUG || DEVELOPMENT
- if (pageout) {
- DKLOG(DKS " state %ld pageins %qd\n", DKN(service), state, vm_task_pageins(fOwningTask) - pageincount);
- }
-#endif /* DEBUG || DEVELOPMENT */
-
+ DKLOG(DKS "::serviceSetPowerState(%ld) %d\n", DKN(service), state, fSystemPowerAck);
+ }
+ ret = service->SetPowerState((uint32_t) flags);
if (kIOReturnSuccess == ret) {
return 20 * 1000 * 1000;
} else {
@@ -5117,7 +5038,7 @@
IOLockUnlock(fLock);
if (pmAck) {
- serverAck();
+ IOServicePH::serverAck(this);
}
return kIOPMAckImplied;
@@ -5148,106 +5069,6 @@
return ready;
}
-IOReturn
-IOUserServer::serviceCreatePMAssertion(IOService * service, uint32_t assertionBits, uint64_t * assertionID, bool synced)
-{
- IOReturn ret = kIOReturnSuccess;
-
- *assertionID = kIOPMUndefinedDriverAssertionID;
-
- if (!service->reserved->uvars || service->reserved->uvars->userServer != this) {
- return kIOReturnError;
- }
-
- if (!service->reserved->uvars->userServerPM) {
- // Cannot create PM assertion unless joined PM tree
- return kIOReturnNotReady;
- }
-
- // Check to make sure the bits are allowed
- uint32_t userAllowedBits = kIOPMDriverAssertionCPUBit |
- kIOPMDriverAssertionForceFullWakeupBit;
- if (synced) {
- userAllowedBits = kIOPMDriverAssertionCPUBit;
- }
- if (0 == (assertionBits & ~userAllowedBits)) {
- if (synced) {
- ret = getPMRootDomain()->acquireDriverKitSyncedAssertion(service, assertionID);
- assert(ret != kIOReturnSuccess || *assertionID != kIOPMUndefinedDriverAssertionID);
- } else {
- *assertionID = getPMRootDomain()->createPMAssertion(assertionBits,
- kIOPMDriverAssertionLevelOn,
- getPMRootDomain(),
- service->getName());
- if (!*assertionID) {
- ret = kIOReturnInternalError;
- }
- }
- } else {
- ret = kIOReturnBadArgument;
- }
- if (*assertionID != kIOPMUndefinedDriverAssertionID) {
- IOLockLock(fLock);
- OSNumber * assertionIDNumber = OSNumber::withNumber(*assertionID, 64);
- OSArray ** pmAssertions = (synced ? &service->reserved->uvars->pmAssertionsSynced : &service->reserved->uvars->pmAssertions);
- if (!*pmAssertions) {
- *pmAssertions = OSArray::withCapacity(1);
- }
- (*pmAssertions)->setObject(assertionIDNumber);
- assertionIDNumber->release();
- IOLockUnlock(fLock);
- }
-
- return ret;
-}
-
-IOReturn
-IOUserServer::serviceReleasePMAssertion(IOService * service, IOPMDriverAssertionID assertionID)
-{
- kern_return_t ret = kIOReturnSuccess;
- bool synced = false;
-
- bool (^findAndRemoveAssertionID)(OSArray *) = ^(OSArray * assertions) {
- unsigned index;
- if (!assertions) {
- return false;
- }
- for (index = 0; index < assertions->getCount(); index++) {
- OSNumber * theID = (OSNumber *)assertions->getObject(index);
- if (theID->unsigned64BitValue() == assertionID) {
- break;
- }
- }
- if (index == assertions->getCount()) {
- return false;
- }
- assertions->removeObject(index);
- return true;
- };
-
- if (!service->reserved->uvars || !service->reserved->uvars->userServer) {
- return kIOReturnError;
- }
-
- IOLockLock(fLock);
- if (findAndRemoveAssertionID(service->reserved->uvars->pmAssertionsSynced)) {
- synced = true;
- } else if (!findAndRemoveAssertionID(service->reserved->uvars->pmAssertions)) {
- ret = kIOReturnNotFound;
- }
- IOLockUnlock(fLock);
-
- if (ret == kIOReturnSuccess) {
- if (synced) {
- getPMRootDomain()->releaseDriverKitSyncedAssertion(assertionID);
- } else {
- getPMRootDomain()->releasePMAssertion(assertionID);
- }
- }
-
- return ret;
-}
-
kern_return_t
IOService::JoinPMTree_Impl(void)
{
@@ -5257,23 +5078,6 @@
return reserved->uvars->userServer->serviceJoinPMTree(this);
}
-static kern_return_t
-acknowledgeSetPowerState(IOService * service)
-{
- if (service->reserved->uvars
- && service->reserved->uvars->userServer
- && service->reserved->uvars->willPower) {
- IOReturn ret;
- service->reserved->uvars->willPower = false;
- ret = service->reserved->uvars->controllingDriver->setPowerState(service->reserved->uvars->willPowerState, service);
- if (kIOPMAckImplied == ret) {
- service->acknowledgeSetPowerState();
- }
- return kIOReturnSuccess;
- }
- return kIOReturnNotReady;
-}
-
kern_return_t
IOService::SetPowerState_Impl(
uint32_t powerFlags)
@@ -5281,7 +5085,18 @@
if (kIODKLogPM & gIODKDebug) {
DKLOG(DKS "::SetPowerState(%d), %d\n", DKN(this), powerFlags, reserved->uvars->willPower);
}
- return ::acknowledgeSetPowerState(this);
+ if (reserved->uvars
+ && reserved->uvars->userServer
+ && reserved->uvars->willPower) {
+ IOReturn ret;
+ reserved->uvars->willPower = false;
+ ret = reserved->uvars->controllingDriver->setPowerState(reserved->uvars->willPowerState, this);
+ if (kIOPMAckImplied == ret) {
+ acknowledgeSetPowerState();
+ }
+ return kIOReturnSuccess;
+ }
+ return kIOReturnNotReady;
}
kern_return_t
@@ -5296,28 +5111,13 @@
changePowerStateToPriv(1);
break;
case kIOServicePowerCapabilityOn:
- changePowerStateToPriv(kUserServerMaxPowerState);
+ changePowerStateToPriv(2);
break;
default:
return kIOReturnBadArgument;
}
return kIOReturnSuccess;
-}
-
-kern_return_t
-IOService::SetPowerOverride_Impl(
- bool enable)
-{
- kern_return_t ret;
-
- if (enable) {
- ret = powerOverrideOnPriv();
- } else {
- ret = powerOverrideOffPriv();
- }
-
- return ret == IOPMNoErr ? kIOReturnSuccess : kIOReturnError;
}
kern_return_t
@@ -5362,19 +5162,12 @@
if (provider != this) {
return kIOReturnUnsupported;
}
- if (reserved == NULL || reserved->uvars == NULL) {
- return kIOReturnUnsupported;
- }
ret = kIOReturnUnsupported;
inst = NULL;
service = NULL;
- prop = reserved->uvars->originalProperties->getObject(propertiesKey);
- if (!prop) {
- return kIOReturnBadArgument;
- }
- prop->retain();
+ prop = copyProperty(propertiesKey);
properties = OSDynamicCast(OSDictionary, prop);
if (!properties) {
ret = kIOReturnBadArgument;
@@ -5494,7 +5287,7 @@
}
return kIOReturnSuccess;
});
- if (object || !(kIORegistryIterateParents & regOptions)) {
+ if (object || !(kIORegistryIterateParents & options)) {
break;
}
}
@@ -5617,77 +5410,15 @@
return kIOReturnSuccess;
}
-kern_return_t
-IOService::CreatePMAssertion_Impl(uint32_t assertionBits, uint64_t * assertionID, bool synced)
-{
- *assertionID = kIOPMUndefinedDriverAssertionID;
-
- if (!reserved->uvars || !reserved->uvars->userServer) {
- return kIOReturnError;
- }
-
- return reserved->uvars->userServer->serviceCreatePMAssertion(this, assertionBits, assertionID, synced);
-}
-
-kern_return_t
-IOService::ReleasePMAssertion_Impl(uint64_t assertionID)
-{
- if (!reserved->uvars || !reserved->uvars->userServer) {
- return kIOReturnError;
- }
-
- return reserved->uvars->userServer->serviceReleasePMAssertion(this, assertionID);
-}
-
void
-IOUserServer::serverAck(void)
-{
- IOServicePH::serverAck(this);
-}
-
-OSArray *
-IOUserServer::servicesWithPowerState(bool state)
-{
- OSArray * result = OSArray::withCapacity(1);
- if (!result) {
- return NULL;
- }
- IOLockLock(fLock);
- fServices->iterateObjects(^(OSObject * object) {
- IOService * service = OSDynamicCast(IOService, object);
- if (service && service->reserved->uvars->powerState == state) {
- result->setObject(service);
- }
- return false;
- });
- IOLockUnlock(fLock);
- if (!result->getCount()) {
- OSSafeReleaseNULL(result);
- }
- return result;
-}
-
-void
-IOUserServer::systemSuspend()
-{
- if (fSystemOff && !fSuspended) {
- KDBG(MACHDBG_CODE(DBG_MACH_SCHED, MACH_SUSPEND_DRIVERKIT_USERSPACE) | DBG_FUNC_START,
- task_pid(fOwningTask));
- task_suspend_internal(fOwningTask);
- DKLOG(DKS " did task_suspend_internal\n", DKN(this));
- fSuspended = true;
- }
-}
-
-void
-IOUserServer::systemPower(uint8_t systemState, bool hibernate)
+IOUserServer::systemPower(bool powerOff, bool hibernate)
{
OSArray * services;
{
OSDictionary * sleepDescription;
OSObject * prop;
- sleepDescription = OSDictionary::withCapacity(3);
+ sleepDescription = OSDictionary::withCapacity(4);
if (sleepDescription) {
prop = getPMRootDomain()->copyProperty(kRootDomainSleepReasonKey);
if (prop) {
@@ -5708,30 +5439,6 @@
}
getSystemStateNotificationService()->StateNotificationItemSet(gIOSystemStateSleepDescriptionKey, sleepDescription);
OSSafeReleaseNULL(sleepDescription);
- }
- }
- if (!IsIOServiceSystemStateOff(systemState)) {
- OSDictionary * wakeDescription;
- OSObject * prop;
- char wakeReasonString[128];
-
- wakeDescription = OSDictionary::withCapacity(2);
- if (wakeDescription) {
- wakeReasonString[0] = 0;
- getPMRootDomain()->copyWakeReasonString(wakeReasonString, sizeof(wakeReasonString));
-
- if (wakeReasonString[0]) {
- prop = OSString::withCString(&wakeReasonString[0]);
- wakeDescription->setObject(gIOSystemStateWakeDescriptionWakeReasonKey, prop);
- OSSafeReleaseNULL(prop);
- }
-#if defined(__arm__) || defined(__arm64__)
- prop = OSNumber::withNumber(ml_get_conttime_offset(), sizeof(uint64_t) * CHAR_BIT);
- wakeDescription->setObject(gIOSystemStateWakeDescriptionContinuousTimeOffsetKey, prop);
- OSSafeReleaseNULL(prop);
-#endif /* defined(__arm__) || defined(__arm64__) */
- getSystemStateNotificationService()->StateNotificationItemSet(gIOSystemStateWakeDescriptionKey, wakeDescription);
- OSSafeReleaseNULL(wakeDescription);
}
}
@@ -5750,17 +5457,11 @@
return allPowerStates;
});
- // figure what phase this DK server process will be suspended in,
- // and make sure its power changes complete before suspension
-
- bool effectiveOff = IsIOServiceSystemStateOff(systemState) && !allPowerStates;
- effectiveOff |= ((kIOServiceSystemStateOffPhase1 == systemState) && !fSystemOffPhase2Allow);
- effectiveOff |= (kIOServiceSystemStateOffPhase2 == systemState);
- effectiveOff |= ((kIOServiceSystemStateAOT == systemState) && !fAOTAllow);
-
- DKLOG(DKS "::systemPower(0x%x) effective %d current %d\n", DKN(this), systemState, !effectiveOff, allPowerStates != 0);
-
- if (effectiveOff) {
+ if (kIODKLogPM & gIODKDebug) {
+ DKLOG("%s::powerOff(%d) %d\n", getName(), powerOff, allPowerStates);
+ }
+
+ if (powerOff) {
fSystemPowerAck = allPowerStates;
if (!fSystemPowerAck) {
fSystemOff = true;
@@ -5768,7 +5469,7 @@
IOLockUnlock(fLock);
if (!fSystemPowerAck) {
- serverAck();
+ IOServicePH::serverAck(this);
} else {
if (services) {
services->iterateObjects(^bool (OSObject * obj) {
@@ -5784,17 +5485,8 @@
});
}
}
- } else if (fSystemOff) {
+ } else {
fSystemOff = false;
-
- if (fSuspended) {
- KDBG(MACHDBG_CODE(DBG_MACH_SCHED, MACH_SUSPEND_DRIVERKIT_USERSPACE) | DBG_FUNC_END,
- task_pid(fOwningTask));
- task_resume_internal(fOwningTask);
- DKLOG(DKS " did task_resume_internal\n", DKN(this));
- fSuspended = false;
- }
-
IOLockUnlock(fLock);
if (services) {
services->iterateObjects(^bool (OSObject * obj) {
@@ -5813,12 +5505,10 @@
return false;
});
}
- } else {
- IOLockUnlock(fLock);
- serverAck();
}
OSSafeReleaseNULL(services);
}
+
void
IOUserServer::systemHalt(int howto)
@@ -5826,7 +5516,7 @@
OSArray * services;
if (true || (kIODKLogPM & gIODKDebug)) {
- DKLOG(DKS "::systemHalt()\n", DKN(this));
+ DKLOG("%s::systemHalt()\n", getName());
}
{
@@ -5876,15 +5566,9 @@
if (!root) {
return false;
}
- if (nextService->reserved && nextService->reserved->uvars) {
- if (nextService->reserved->uvars->started) {
- terminateOptions = kIOServiceRequired | kIOServiceTerminateNeedWillTerminate;
- if (!nextService->terminate(terminateOptions)) {
- IOLog("failed to terminate service %s-0x%llx\n", nextService->getName(), nextService->getRegistryEntryID());
- }
- } else {
- IOLog("service %s-0x%llx not started, skipped termination\n", nextService->getName(), nextService->getRegistryEntryID());
- }
+ terminateOptions = kIOServiceRequired | kIOServiceTerminateNeedWillTerminate;
+ if (!nextService->terminate(terminateOptions)) {
+ IOLog("failed to terminate service %s-0x%llx\n", nextService->getName(), nextService->getRegistryEntryID());
}
return false;
});
@@ -5911,39 +5595,17 @@
IOUserServer::serviceStarted(IOService * service, IOService * provider, bool result)
{
IOReturn ret;
- bool needStop = false;
DKLOG(DKS "::start(" DKS ") %s\n", DKN(service), DKN(provider), result ? "ok" : "fail");
if (!result) {
- if (!service->reserved->uvars->instantiated && provider) {
- // Object instantiation did not happen. This can happen if,
- // 1. Dext crashed, in which case the user server has been terminated when the task is marked as corpse
- // 2. Kernel IOService failed start, and it did not attempt Start
- // A rematch should be attempted for 1, not 2
- bool shouldReRegister = true;
- if (lockForArbitration()) {
- shouldReRegister = (__state[0] & kIOServiceInactiveState);
- unlockForArbitration();
- }
- if (shouldReRegister) {
- provider->registerService(kIOServiceAsynchronous);
- }
- }
ret = kIOReturnSuccess;
return ret;
}
ret = serviceJoinPMTree(service);
- IOLockLock(service->reserved->uvars->uvarsLock);
service->reserved->uvars->started = true;
- needStop = service->reserved->uvars->needStop;
- IOLockUnlock(service->reserved->uvars->uvarsLock);
- if (needStop) {
- serviceStop(service, provider);
- return kIOReturnSuccess;
- }
if (service->reserved->uvars->deferredRegisterService) {
service->registerService(kIOServiceAsynchronous | kIOServiceDextRequirePowerForMatching);
@@ -6006,34 +5668,18 @@
finish:
IOLockUnlock(client->reserved->uvars->uvarsLock);
- if (kIODKLogSetup & gIODKDebug) {
- DKLOG(DKS "::serviceClose(" DKS ", " DKS ") -> %x\n", DKN(this), DKN(provider), DKN(client), ret);
- }
return ret;
}
IOReturn
-IOUserServer::serviceStop(IOService * service, IOService *provider)
+IOUserServer::serviceStop(IOService * service, IOService *)
{
IOReturn ret;
uint32_t idx;
bool pmAck;
- bool deferred = false;
- OSObjectUserVars * uvars = service->reserved->uvars;
-
- IOLockLock(uvars->uvarsLock);
- if (!uvars->started) {
- // started will be set, at a later point
- uvars->needStop = true;
- deferred = true;
- }
- IOLockUnlock(uvars->uvarsLock);
- if (deferred) {
- return kIOReturnSuccess;
- }
-
+ OSObjectUserVars * uvars;
pmAck = false;
IOLockLock(fLock);
idx = fServices->getNextIndexOfObject(service, 0);
@@ -6060,6 +5706,7 @@
OSSafeReleaseNULL(serviceArray);
OSSafeReleaseNULL(serviceArrayObj);
+ uvars = service->reserved->uvars;
uvars->stopped = true;
uvars->powerState = 0;
@@ -6081,38 +5728,16 @@
}
IOLockUnlock(fLock);
if (pmAck) {
- serverAck();
+ IOServicePH::serverAck(this);
}
if (-1U == idx) {
- if (kIODKLogSetup & gIODKDebug) {
- DKLOG(DKS "::serviceStop(" DKS ", " DKS "): could not find service\n", DKN(this), DKN(service), DKN(provider));
- }
return kIOReturnSuccess;
}
(void) service->deRegisterInterestedDriver(this);
if (uvars->userServerPM) {
- IOPMrootDomain * rootDomain = getPMRootDomain();
service->PMstop();
- service->acknowledgeSetPowerState();
- if (uvars->pmAssertions) {
- uvars->pmAssertions->iterateObjects(^(OSObject * obj) {
- rootDomain->releasePMAssertion(((OSNumber *)obj)->unsigned64BitValue());
- return false;
- });
- OSSafeReleaseNULL(uvars->pmAssertions);
- }
- if (uvars->pmAssertionsSynced) {
- uvars->pmAssertionsSynced->iterateObjects(^(OSObject * obj) {
- rootDomain->releaseDriverKitSyncedAssertion(((OSNumber *)obj)->unsigned64BitValue());
- return false;
- });
- OSSafeReleaseNULL(uvars->pmAssertionsSynced);
- }
- }
- if (kIODKLogSetup & gIODKDebug) {
- DKLOG(DKS "::serviceStop(" DKS ", " DKS ")\n", DKN(this), DKN(service), DKN(provider));
}
ret = kIOReturnSuccess;
@@ -6144,7 +5769,6 @@
}
OSSafeReleaseNULL(uvars->userServer);
IOLockFree(uvars->uvarsLock);
- OSSafeReleaseNULL(service->reserved->uvars->originalProperties);
IOFreeType(service->reserved->uvars, OSObjectUserVars);
}
@@ -6162,25 +5786,13 @@
willTerminate = true;
}
IOLockUnlock(client->reserved->uvars->uvarsLock);
- if (kIODKLogSetup & gIODKDebug) {
- DKLOG("serviceWillTerminate(" DKS ", " DKS ")\n", DKN(client), DKN(provider));
- }
if (willTerminate) {
if (provider->isInactive() || IOServicePH::serverSlept()) {
- if (kIODKLogIPC & gIODKDebug) {
- DKLOG(DKS "->Stop_async(" DKS ")\n", DKN(client), DKN(provider));
- }
client->Stop_async(provider);
ret = kIOReturnOffline;
} else {
- if (kIODKLogIPC & gIODKDebug) {
- DKLOG(DKS "->Stop(" DKS ")\n", DKN(client), DKN(provider));
- }
ret = client->Stop(provider);
- if (kIODKLogIPC & gIODKDebug) {
- DKLOG(DKS "->Stop(" DKS ") returned %x\n", DKN(client), DKN(provider), ret);
- }
}
if (kIOReturnSuccess != ret) {
IOUserServer::serviceDidStop(client, provider);
@@ -6199,9 +5811,6 @@
*defer = true;
}
IOLockUnlock(client->reserved->uvars->uvarsLock);
- if (kIODKLogSetup & gIODKDebug) {
- DKLOG("serviceDidTerminate(" DKS ", " DKS ") -> defer %d\n", DKN(client), DKN(provider), *defer);
- }
}
void
@@ -6226,10 +5835,6 @@
client->reserved->uvars->openProviders = NULL;
}
IOLockUnlock(client->reserved->uvars->uvarsLock);
-
- if (kIODKLogSetup & gIODKDebug) {
- DKLOG("serviceDidStop(" DKS ", " DKS ") -> complete %d\n", DKN(client), DKN(provider), complete);
- }
if (closeArray) {
closeArray->iterateObjects(^bool (OSObject * obj) {
@@ -6359,6 +5964,7 @@
user_addr_t userObjectName = (user_addr_t)p1;
mach_port_name_t portName = (mach_port_name_t)(uintptr_t)p3;
mach_port_t port = MACH_PORT_NULL;
+ ipc_kobject_type_t portType;
char eventlinkName[kIOEventLinkMaxNameLength + 1] = {0};
size_t eventLinkNameLen;
OSString * eventlinkNameStr = NULL; // must release
@@ -6394,8 +6000,15 @@
goto finish;
}
- ret = iokit_lookup_raw_current_task(portName, IKOT_EVENTLINK, &port);
- if (ret != kIOReturnSuccess) {
+ port = iokit_lookup_raw_current_task(portName, &portType);
+
+ if (port == NULL) {
+ ret = kIOReturnNotFound;
+ goto finish;
+ }
+
+ if (portType != IKOT_EVENTLINK) {
+ ret = kIOReturnBadArgument;
goto finish;
}
@@ -6424,6 +6037,7 @@
user_addr_t userObjectName = (user_addr_t)p1;
mach_port_name_t portName = (mach_port_name_t)(uintptr_t)p3;
mach_port_t port = MACH_PORT_NULL;
+ ipc_kobject_type_t portType;
char workgroupName[kIOWorkGroupMaxNameLength + 1] = {0};
size_t workgroupNameLen;
OSString * workgroupNameStr = NULL; // must release
@@ -6459,8 +6073,15 @@
goto finish;
}
- ret = iokit_lookup_raw_current_task(portName, IKOT_WORK_INTERVAL, &port);
- if (ret != kIOReturnSuccess) {
+ port = iokit_lookup_raw_current_task(portName, &portType);
+
+ if (port == NULL) {
+ ret = kIOReturnNotFound;
+ goto finish;
+ }
+
+ if (portType != IKOT_WORK_INTERVAL) {
+ ret = kIOReturnBadArgument;
goto finish;
}
@@ -6654,26 +6275,6 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
-/*
- * IOUserServerCheckInToken state machine
- *
- * token
- * creation
- * |
- * |
- * v dext
- * +-----------+ check-in +-----------+
- * | Pending +--------------->| Complete |
- * +-----+-----+ +-----+-----+
- * | |
- * dext crash | | dext crash
- * before | | before server
- * check-in | | registration
- * | +-----------+ |
- * +----->| Canceled |<--------+
- * +-----------+
- */
-
extern IORecursiveLock * gDriverKitLaunchLock;
extern OSSet * gDriverKitLaunches;
@@ -6716,12 +6317,8 @@
{
IORecursiveLockLock(gDriverKitLaunchLock);
- if (fState != kIOUserServerCheckInCanceled) {
- // Move the state to canceled even if the token has completed
- // This is to cover the gap between dext check-in and the registration of user server
- // Cancellation listeners must be informed of a crash in between
+ if (fState == kIOUserServerCheckInPending) {
fState = kIOUserServerCheckInCanceled;
-
if (gDriverKitLaunches != NULL) {
// Remove pending launch from list, if we have not shut down yet.
gDriverKitLaunches->removeObject(this);
@@ -6752,14 +6349,15 @@
ret = kIOReturnSuccess;
}
- if (fState == kIOUserServerCheckInPending) {
+ if (fState == kIOUserServerCheckInPending && --fPendingCount == 0) {
fState = kIOUserServerCheckInComplete;
if (gDriverKitLaunches != NULL) {
// Remove pending launch from list, if we have not shut down yet.
gDriverKitLaunches->removeObject(this);
}
- // Do not flush the cancellation handlers, as we might still trigger them
+ // No need to hold on to the cancellation handlers
+ fHandlers->flushCollection();
}
IORecursiveLockUnlock(gDriverKitLaunchLock);
@@ -6791,6 +6389,7 @@
}
fState = kIOUserServerCheckInPending;
+ fPendingCount = 1;
fKextBundleID = NULL;
fNeedDextDec = false;
@@ -6883,66 +6482,15 @@
return fServerTag;
}
-/*
- * Wait for a IOUserServer to check in
- */
-
-static
-__attribute__((noinline, not_tail_called))
IOUserServer *
-__WAITING_FOR_USER_SERVER__(IOUserServerCheckInToken * token, uint64_t * timeoutMS)
-{
- IOUserServer * result = NULL;
- IOService * server = NULL;
- const OSSymbol * serverName = token->copyServerName();
- OSNumber * serverTag = token->copyServerTag();
- OSDictionary * matching = IOService::serviceMatching(gIOUserServerClassKey);
- uint64_t startTime = 0, endTime = 0;
-
- if (!matching || !serverName || !serverTag) {
- goto finish;
- }
- IOService::propertyMatching(gIOUserServerNameKey, serverName, matching);
- if (!(kIODKDisableDextTag & gIODKDebug)) {
- IOService::propertyMatching(gIOUserServerTagKey, serverTag, matching);
- }
-
- absolutetime_to_nanoseconds(mach_absolute_time(), &startTime);
- startTime /= NSEC_PER_MSEC;
- server = IOService::waitForMatchingServiceWithToken(matching, (*timeoutMS) * NSEC_PER_MSEC, token);
- result = OSDynamicCast(IOUserServer, server);
- if (!result) {
- // Calculate the remaining timeout if the server isn't registered
- OSSafeReleaseNULL(server);
- token->cancel();
- absolutetime_to_nanoseconds(mach_absolute_time(), &endTime);
- endTime /= NSEC_PER_MSEC;
- if (endTime > startTime) {
- if (os_sub_overflow(*timeoutMS, endTime - startTime, timeoutMS)) {
- *timeoutMS = 0;
- }
- }
- }
-
-finish:
- OSSafeReleaseNULL(matching);
- OSSafeReleaseNULL(serverName);
- OSSafeReleaseNULL(serverTag);
-
- return result;
-}
-
-IOUserServer *
-IOUserServer::launchUserServer(IOService * provider, IOService * service, OSString * bundleID, const OSSymbol * serverName, OSNumber * serverTag, bool reuseIfExists, OSData *serverDUI)
-{
- IOUserServer *me = NULL, *providerServer = NULL;
+IOUserServer::launchUserServer(OSString * bundleID, const OSSymbol * serverName, OSNumber * serverTag, bool reuseIfExists, IOUserServerCheckInToken ** resultToken, OSData *serverDUI)
+{
+ IOUserServer *me = NULL;
IOUserServerCheckInToken * token = NULL;
OSDictionary * matching = NULL; // must release
OSKext * driverKext = NULL; // must release
OSDextStatistics * driverStatistics = NULL; // must release
bool reslide = false;
- uint32_t retries = kIOUserServerCheckInMaxRetry;
- uint64_t timeRemainingMS = kIOUserServerCheckInTimeoutMSecs;
/* TODO: Check we are looking for same dextID
* and if it is not the same
@@ -6958,7 +6506,15 @@
reslide = driverStatistics->getCrashCount() > 0;
} else {
DKLOG("Could not find OSKext for %s\n", bundleID->getCStringNoCopy());
+ *resultToken = NULL;
return NULL;
+ }
+
+ IORecursiveLockLock(gDriverKitLaunchLock);
+
+ if (gDriverKitLaunches == NULL) {
+ // About to shut down, don't launch anything
+ goto finish;
}
if (reuseIfExists) {
@@ -6975,136 +6531,65 @@
}
}
+ // Find existing server
if (reuseIfExists) {
- // Check provider's user server, if exists
- if (provider->reserved && provider->reserved->uvars && (providerServer = provider->reserved->uvars->userServer) != NULL) {
- OSString * providerServerName = OSDynamicCast(OSString, providerServer->getProperty(gIOUserServerNameKey));
- if (providerServerName && providerServerName->isEqualTo(serverName)) {
- // Reuse is required
-
- DKLOG("using existing server " DKS " from provider " DKS "\n", DKN(providerServer), DKN(provider));
-
- // If provider has the user server that we are supposed to reuse, and it has become inactive
- // start of this service should simply fail
- // If the user server become inactive after this check, start should fail at a later stage
- if (!providerServer->isInactive()) {
- providerServer->retain();
- me = providerServer;
- } else {
- DKLOG(DKS " cannot reuse inactive server\n", DKN(service));
- // Must not create a token as reuse is required
- }
+ token = IOUserServerCheckInToken::findExistingToken(serverName);
+ if (token) {
+ // Launch in progress, return token
+ goto finish;
+ } else {
+ // Check if launch completed
+ matching = IOService::serviceMatching(gIOUserServerClassKey);
+ if (!matching) {
goto finish;
}
- }
- }
-
- do {
- const OSSymbol * tokenServerName;
- OSNumber * tokenServerTag;
-
- IORecursiveLockLock(gDriverKitLaunchLock);
-
- if (gDriverKitLaunches == NULL) {
- // About to shut down, don't launch anything
- IORecursiveLockUnlock(gDriverKitLaunchLock);
- goto finish;
- }
-
- // Find existing server
- if (reuseIfExists) {
- token = IOUserServerCheckInToken::findExistingToken(serverName);
- if (!token) {
- // Check if launch completed
-
- matching = IOService::serviceMatching(gIOUserServerClassKey);
- if (!matching) {
- IORecursiveLockUnlock(gDriverKitLaunchLock);
- goto finish;
- }
- IOService::propertyMatching(gIOUserServerNameKey, serverName, matching);
- IOService * service = IOService::copyMatchingService(matching);
- IOUserServer * userServer = OSDynamicCast(IOUserServer, service);
- if (userServer) {
- // found existing user server
- me = userServer;
- IORecursiveLockUnlock(gDriverKitLaunchLock);
- goto finish;
- } else {
- OSSafeReleaseNULL(service);
- }
- }
- }
-
- if (!token) {
- // No existing server, request launch
- token = new IOUserServerCheckInToken;
- if (!token) {
- IORecursiveLockUnlock(gDriverKitLaunchLock);
+ IOService::propertyMatching(gIOUserServerNameKey, serverName, matching);
+ IOService * service = IOService::copyMatchingService(matching);
+ IOUserServer * userServer = OSDynamicCast(IOUserServer, service);
+ if (userServer) {
+ // found existing user server
+ me = userServer;
goto finish;
- }
-
- /*
- * TODO: If the init fails because the personalities are not up to date
- * restart the whole matching process.
- */
- if (token && !token->init(serverName, serverTag, driverKext, serverDUI)) {
- DKLOG(DKS " could not initialize token\n", DKN(service));
- IORecursiveLockUnlock(gDriverKitLaunchLock);
- OSSafeReleaseNULL(token);
- goto finish;
- }
-
- /*
- * If the launch fails at any point terminate() will
- * be called on this IOUserServer.
- */
- gDriverKitLaunches->setObject(token);
- OSKext::requestDaemonLaunch(bundleID, (OSString *)serverName, serverTag, reslide ? kOSBooleanTrue : kOSBooleanFalse, token, serverDUI);
- }
-
- IORecursiveLockUnlock(gDriverKitLaunchLock);
-
- tokenServerName = token->copyServerName();
- tokenServerTag = token->copyServerTag();
- assert(tokenServerName && tokenServerTag);
- DKLOG(DKS " waiting for server %s-%llx\n", DKN(service), tokenServerName->getCStringNoCopy(), tokenServerTag->unsigned64BitValue());
-
- me = __WAITING_FOR_USER_SERVER__(token, &timeRemainingMS);
- if (me) {
- OSSafeReleaseNULL(tokenServerName);
- OSSafeReleaseNULL(tokenServerTag);
- break;
- }
- DKLOG(DKS " failed to find server %s-%llx, remaining %llums, retries %u\n", DKN(service),
- tokenServerName->getCStringNoCopy(), tokenServerTag->unsigned64BitValue(), timeRemainingMS, retries - 1);
- OSSafeReleaseNULL(tokenServerName);
- OSSafeReleaseNULL(tokenServerTag);
+ } else {
+ OSSafeReleaseNULL(service);
+ }
+ }
+ }
+
+ // No existing server, request launch
+ token = new IOUserServerCheckInToken;
+ if (!token) {
+ goto finish;
+ }
+
+ /*
+ * TODO: If the init fails because the personalities are not up to date
+ * restart the whole matching process.
+ */
+ if (token && !token->init(serverName, serverTag, driverKext, serverDUI)) {
+ IOLog("Could not initialize token\n");
OSSafeReleaseNULL(token);
- // If the loop continues it means the dext has been killed
- // We don't record a crash since start never happened. No client code has run
- } while (--retries && timeRemainingMS && !gInUserspaceReboot);
-
- if (me) {
- DKLOG(DKS " server launched, validating\n", DKN(service));
- if (token && !(kIODKDisableCheckInTokenVerification & gIODKDebug)) {
- if (!me->serviceMatchesCheckInToken(token)) {
- DKLOG(DKS " server does not match token\n", DKN(service));
- me->exit("Check In Token verification failed");
- OSSafeReleaseNULL(me);
- }
- }
- } else {
-#if DEVELOPMENT || DEBUG
- driverkit_checkin_timed_out = mach_absolute_time();
-#endif
- }
+ goto finish;
+ }
+
+ /*
+ * If the launch fails at any point terminate() will
+ * be called on this IOUserServer.
+ */
+ gDriverKitLaunches->setObject(token);
+ OSKext::requestDaemonLaunch(bundleID, (OSString *)serverName, serverTag, reslide ? kOSBooleanTrue : kOSBooleanFalse, token, serverDUI);
finish:
+ IORecursiveLockUnlock(gDriverKitLaunchLock);
OSSafeReleaseNULL(matching);
OSSafeReleaseNULL(driverStatistics);
OSSafeReleaseNULL(driverKext);
- OSSafeReleaseNULL(token);
+
+ if (resultToken) {
+ *resultToken = token;
+ } else {
+ OSSafeReleaseNULL(token);
+ }
return me;
}
@@ -7149,6 +6634,7 @@
const OSSymbol * tokenServerName = token->fServerName;
if (tokenServerName->isEqualTo(serverName)) {
assert(token->fState == kIOUserServerCheckInPending);
+ token->fPendingCount++;
result = token;
result->retain();
}
@@ -7457,6 +6943,7 @@
public:
virtual bool init() override;
+ OSDictionary * fSchema;
OSDictionary * fValue;
OSSet * fListeners;
};
@@ -7529,19 +7016,8 @@
gIOSystemStateWakeDescriptionWakeReasonKey = OSSymbol::withCStringNoCopy(kIOSystemStateWakeDescriptionWakeReasonKey);
gIOSystemStateWakeDescriptionContinuousTimeOffsetKey = OSSymbol::withCStringNoCopy(kIOSystemStateWakeDescriptionContinuousTimeOffsetKey);
-#if defined(__arm__) || defined(__arm64__)
- // Make ml_get_conttime_offset available before systemPower
- OSDictionary * wakeDescription = OSDictionary::withCapacity(1);
- OSObject * prop = OSNumber::withNumber(ml_get_conttime_offset(), sizeof(uint64_t) * CHAR_BIT);
- wakeDescription->setObject(gIOSystemStateWakeDescriptionContinuousTimeOffsetKey, prop);
- ret = me->StateNotificationItemCreate(gIOSystemStateWakeDescriptionKey, wakeDescription);
- OSSafeReleaseNULL(prop);
- OSSafeReleaseNULL(wakeDescription);
- assert(kIOReturnSuccess == ret);
-#else /* !defined(__arm__) && !defined(__arm64__) */
ret = me->StateNotificationItemCreate(gIOSystemStateWakeDescriptionKey, NULL);
assert(kIOReturnSuccess == ret);
-#endif /* defined(__arm__) || defined(__arm64__) */
gIOSystemStateHaltDescriptionKey = (OSString *)OSSymbol::withCStringNoCopy(kIOSystemStateHaltDescriptionKey);
gIOSystemStateHaltDescriptionHaltStateKey = OSSymbol::withCStringNoCopy(kIOSystemStateHaltDescriptionHaltStateKey);
@@ -7593,6 +7069,7 @@
{
kern_return_t kr;
OSDictionary * dict;
+ OSDictionary * schema;
OSDictionary * value;
OSString * itemName;
@@ -7605,12 +7082,9 @@
return kIOReturnNotPermitted;
}
- if ((value = OSDynamicCast(OSDictionary, dict->getObject(kIOStateNotificationItemCreateKey)))) {
- itemName = OSDynamicCast(OSString, value->getObject(kIOStateNotificationNameKey));
- itemName->retain();
- value->removeObject(kIOStateNotificationNameKey);
- kr = StateNotificationItemCreate(itemName, value);
- itemName->release();
+ if ((schema = OSDynamicCast(OSDictionary, dict->getObject(kIOStateNotificationItemCreateKey)))) {
+ itemName = OSDynamicCast(OSString, schema->getObject(kIOStateNotificationNameKey));
+ kr = StateNotificationItemCreate(itemName, schema);
} else if ((value = OSDynamicCast(OSDictionary, dict->getObject(kIOStateNotificationItemSetKey)))) {
itemName = OSDynamicCast(OSString, value->getObject(kIOStateNotificationNameKey));
itemName->retain();
@@ -7637,7 +7111,7 @@
}
IOStateNotificationItem *
-IOService::stateNotificationItemCopy(OSString * itemName, OSDictionary * initialValue)
+IOService::stateNotificationItemCopy(OSString * itemName, OSDictionary * schema)
{
IOServiceStateChangeVars * ivars = reserved->svars;
@@ -7654,10 +7128,13 @@
item->init();
item->fListeners = OSSet::withCapacity(16);
- if (initialValue) {
- initialValue->retain();
- item->fValue = initialValue;
- }
+ if (schema) {
+ schema->retain();
+ } else {
+ schema = OSDictionary::withCapacity(8);
+ }
+ schema->setObject(kIOStateNotificationNameKey, name);
+ item->fSchema = schema;
ivars->fItems->setObject(name, item);
}
IOLockUnlock(ivars->fLock);
@@ -7668,11 +7145,11 @@
}
kern_return_t
-IOService::StateNotificationItemCreate_Impl(OSString * itemName, OSDictionary * value)
+IOService::StateNotificationItemCreate_Impl(OSString * itemName, OSDictionary * schema)
{
IOStateNotificationItem * item;
- item = stateNotificationItemCopy(itemName, value);
+ item = stateNotificationItemCopy(itemName, schema);
if (!item) {
return kIOReturnNoMemory;
}
@@ -7684,27 +7161,20 @@
kern_return_t
IOService::StateNotificationItemSet_Impl(OSString * itemName, OSDictionary * value)
{
- kern_return_t ret = kIOReturnSuccess;
IOServiceStateChangeVars * ivars = reserved->svars;
- OSSet * listeners = NULL;
- IOStateNotificationItem * item;
+ OSSet * listeners;
+ IOStateNotificationItem * item;
value->retain();
IOLockLock(ivars->fLock);
- do {
- item = (typeof(item))ivars->fItems->getObject(itemName);
- if (!item) {
- ret = kIOReturnNotFound;
- value->release();
- break;
- }
- OSSafeReleaseNULL(item->fValue);
- item->fValue = value;
- if (item->fListeners->getCount()) {
- listeners = OSSet::withSet(item->fListeners);
- }
- } while (false);
+ item = (typeof(item))ivars->fItems->getObject(itemName);
+ OSSafeReleaseNULL(item->fValue);
+ item->fValue = value;
+ listeners = NULL;
+ if (item->fListeners->getCount()) {
+ listeners = OSSet::withSet(item->fListeners);
+ }
IOLockUnlock(ivars->fLock);
if (listeners) {
@@ -7718,7 +7188,7 @@
OSSafeReleaseNULL(listeners);
}
- return ret;
+ return kIOReturnSuccess;
}
kern_return_t