RootDomainUserClient.cpp [plain text]
#include <IOKit/assert.h>
#include <IOKit/IOLib.h>
#include <IOKit/IOKitKeys.h>
#include <IOKit/IOBufferMemoryDescriptor.h>
#include "RootDomainUserClient.h"
#include <IOKit/pwr_mgt/IOPMLibDefs.h>
#define super IOUserClient
OSDefineMetaClassAndStructors(RootDomainUserClient, IOUserClient)
bool RootDomainUserClient::initWithTask(task_t owningTask, void *security_id,
UInt32 type, OSDictionary * properties)
{
if (properties)
properties->setObject(kIOUserClientCrossEndianCompatibleKey, kOSBooleanTrue);
if (!super::initWithTask(owningTask, security_id, type, properties))
return false;
fOwningTask = owningTask;
task_reference (fOwningTask);
return true;
}
bool RootDomainUserClient::start( IOService * provider )
{
assert(OSDynamicCast(IOPMrootDomain, provider));
if(!super::start(provider))
return false;
fOwner = (IOPMrootDomain *)provider;
return true;
}
IOReturn RootDomainUserClient::secureSleepSystem( uint32_t *return_code )
{
return secureSleepSystemOptions(NULL, 0, return_code);
}
IOReturn RootDomainUserClient::secureSleepSystemOptions(
const void *inOptions,
IOByteCount inOptionsSize __unused,
uint32_t *returnCode)
{
int local_priv = 0;
int admin_priv = 0;
IOReturn ret = kIOReturnNotPrivileged;
OSDictionary *unserializedOptions = NULL;
OSString *unserializeErrorString = NULL;
ret = clientHasPrivilege(fOwningTask, kIOClientPrivilegeLocalUser);
local_priv = (kIOReturnSuccess == ret);
ret = clientHasPrivilege(fOwningTask, kIOClientPrivilegeAdministrator);
admin_priv = (kIOReturnSuccess == ret);
if (inOptions)
{
unserializedOptions = OSDynamicCast( OSDictionary,
OSUnserializeXML((const char *)inOptions, &unserializeErrorString));
if (!unserializedOptions) {
IOLog("IOPMRootDomain SleepSystem unserialization failure: %s\n",
unserializeErrorString ? unserializeErrorString->getCStringNoCopy() : "Unknown");
}
}
if ( (local_priv || admin_priv)
&& fOwner )
{
if (unserializedOptions)
{
fOwner->setProperty( kRootDomainSleepOptionsKey, unserializedOptions);
*returnCode = fOwner->sleepSystemOptions( unserializedOptions );
unserializedOptions->release();
} else {
fOwner->removeProperty( kRootDomainSleepOptionsKey );
*returnCode = fOwner->sleepSystemOptions( NULL );
}
} else {
*returnCode = kIOReturnNotPrivileged;
}
return kIOReturnSuccess;
}
IOReturn RootDomainUserClient::secureSetAggressiveness(
unsigned long type,
unsigned long newLevel,
int *return_code )
{
int local_priv = 0;
int admin_priv = 0;
IOReturn ret = kIOReturnNotPrivileged;
ret = clientHasPrivilege(fOwningTask, kIOClientPrivilegeLocalUser);
local_priv = (kIOReturnSuccess == ret);
ret = clientHasPrivilege(fOwningTask, kIOClientPrivilegeAdministrator);
admin_priv = (kIOReturnSuccess == ret);
if((local_priv || admin_priv) && fOwner) {
*return_code = fOwner->setAggressiveness(type, newLevel);
} else {
*return_code = kIOReturnNotPrivileged;
}
return kIOReturnSuccess;
}
IOReturn RootDomainUserClient::secureSetMaintenanceWakeCalendar(
IOPMCalendarStruct *inCalendar,
uint32_t *returnCode)
{
int admin_priv = 0;
IOReturn ret = kIOReturnNotPrivileged;
ret = clientHasPrivilege(fOwningTask, kIOClientPrivilegeAdministrator);
admin_priv = (kIOReturnSuccess == ret);
if (admin_priv && fOwner) {
*returnCode = fOwner->setMaintenanceWakeCalendar(inCalendar);
} else {
*returnCode = kIOReturnNotPrivileged;
}
return kIOReturnSuccess;
}
IOReturn RootDomainUserClient::secureSetUserAssertionLevels(
uint32_t assertionBitfield)
{
int admin_priv = 0;
IOReturn ret = kIOReturnNotPrivileged;
ret = clientHasPrivilege(fOwningTask, kIOClientPrivilegeAdministrator);
admin_priv = (kIOReturnSuccess == ret);
if (admin_priv && fOwner) {
ret = fOwner->setPMAssertionUserLevels(assertionBitfield);
} else {
ret = kIOReturnNotPrivileged;
}
return kIOReturnSuccess;
}
IOReturn RootDomainUserClient::clientClose( void )
{
detach(fOwner);
if(fOwningTask) {
task_deallocate(fOwningTask);
fOwningTask = 0;
}
return kIOReturnSuccess;
}
IOReturn RootDomainUserClient::clientMemoryForType(
UInt32 type,
IOOptionBits *options,
IOMemoryDescriptor ** memory)
{
if (!fOwner)
return kIOReturnNotReady;
if (kPMRootDomainMapTraceBuffer == type)
{
*memory = fOwner->getPMTraceMemoryDescriptor();
if (*memory) {
(*memory)->retain();
*options = 0;
return kIOReturnSuccess;
} else {
return kIOReturnNotFound;
}
}
return kIOReturnUnsupported;
}
IOReturn RootDomainUserClient::externalMethod(
uint32_t selector,
IOExternalMethodArguments * arguments,
IOExternalMethodDispatch * dispatch __unused,
OSObject * target __unused,
void * reference __unused )
{
IOReturn ret = kIOReturnBadArgument;
switch (selector)
{
case kPMSetAggressiveness:
if ((2 == arguments->scalarInputCount)
&& (1 == arguments->scalarOutputCount))
{
ret = this->secureSetAggressiveness(
(unsigned long)arguments->scalarInput[0],
(unsigned long)arguments->scalarInput[1],
(int *)&arguments->scalarOutput[0]);
}
break;
case kPMGetAggressiveness:
if ((1 == arguments->scalarInputCount)
&& (1 == arguments->scalarOutputCount))
{
ret = fOwner->getAggressiveness(
(unsigned long)arguments->scalarInput[0],
(unsigned long *)&arguments->scalarOutput[0]);
}
break;
case kPMSleepSystem:
if (1 == arguments->scalarOutputCount)
{
ret = this->secureSleepSystem(
(uint32_t *)&arguments->scalarOutput[0]);
}
break;
case kPMAllowPowerChange:
if (1 == arguments->scalarInputCount)
{
ret = fOwner->allowPowerChange(
arguments->scalarInput[0]);
}
break;
case kPMCancelPowerChange:
if (1 == arguments->scalarInputCount)
{
ret = fOwner->cancelPowerChange(
arguments->scalarInput[0]);
}
break;
case kPMShutdownSystem:
ret = kIOReturnUnsupported;
break;
case kPMRestartSystem:
ret = kIOReturnUnsupported;
break;
case kPMSleepSystemOptions:
ret = this->secureSleepSystemOptions(
arguments->structureInput,
arguments->structureInputSize,
(uint32_t *)&arguments->scalarOutput[0]);
break;
case kPMSetMaintenanceWakeCalendar:
ret = this->secureSetMaintenanceWakeCalendar(
(IOPMCalendarStruct *)arguments->structureInput,
(uint32_t *)&arguments->structureOutput);
arguments->structureOutputSize = sizeof(uint32_t);
break;
case kPMSetUserAssertionLevels:
ret = this->secureSetUserAssertionLevels(
(uint32_t)arguments->scalarInput[0]);
break;
default:
return kIOReturnBadArgument;
}
return ret;
}
IOExternalMethod * RootDomainUserClient::getTargetAndMethodForIndex(
IOService ** targetP, UInt32 index )
{
return super::getTargetAndMethodForIndex(targetP, index);
}
void
RootDomainUserClient::setPreventative(UInt32 on_off, UInt32 types_of_sleep)
{ return; }