1/* 2 * Copyright (c) 1998-2012 Apple Computer, Inc. All rights reserved. 3 * 4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ 5 * 6 * This file contains Original Code and/or Modifications of Original Code 7 * as defined in and that are subject to the Apple Public Source License 8 * Version 2.0 (the 'License'). You may not use this file except in 9 * compliance with the License. The rights granted to you under the License 10 * may not be used to create, or enable the creation or redistribution of, 11 * unlawful or unlicensed copies of an Apple operating system, or to 12 * circumvent, violate, or enable the circumvention or violation of, any 13 * terms of an Apple operating system software license agreement. 14 * 15 * Please obtain a copy of the License at 16 * http://www.opensource.apple.com/apsl/ and read it before using this file. 17 * 18 * The Original Code and all software distributed under the License are 19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 23 * Please see the License for the specific language governing rights and 24 * limitations under the License. 25 * 26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ 27 */ 28/* 29 * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. 30 * 31 */ 32 33#include <IOKit/assert.h> 34#include <IOKit/IOLib.h> 35#include <IOKit/IOKitKeys.h> 36#include <IOKit/IOBufferMemoryDescriptor.h> 37#include "RootDomainUserClient.h" 38#include <IOKit/pwr_mgt/IOPMLibDefs.h> 39#include <IOKit/pwr_mgt/IOPMPrivate.h> 40#include <sys/proc.h> 41 42#define super IOUserClient 43 44/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 45 46OSDefineMetaClassAndStructors(RootDomainUserClient, IOUserClient) 47 48/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 49 50bool RootDomainUserClient::initWithTask(task_t owningTask, void *security_id, 51 UInt32 type, OSDictionary * properties) 52{ 53 if (properties) 54 properties->setObject(kIOUserClientCrossEndianCompatibleKey, kOSBooleanTrue); 55 56 if (!super::initWithTask(owningTask, security_id, type, properties)) 57 return false; 58 59 fOwningTask = owningTask; 60 task_reference (fOwningTask); 61 return true; 62} 63 64 65bool RootDomainUserClient::start( IOService * provider ) 66{ 67 assert(OSDynamicCast(IOPMrootDomain, provider)); 68 if(!super::start(provider)) 69 return false; 70 fOwner = (IOPMrootDomain *)provider; 71 72 73 return true; 74} 75 76IOReturn RootDomainUserClient::secureSleepSystem( uint32_t *return_code ) 77{ 78 return secureSleepSystemOptions(NULL, 0, return_code); 79} 80 81IOReturn RootDomainUserClient::secureSleepSystemOptions( 82 const void *inOptions, 83 IOByteCount inOptionsSize, 84 uint32_t *returnCode) 85{ 86 87 int local_priv = 0; 88 int admin_priv = 0; 89 IOReturn ret = kIOReturnNotPrivileged; 90 OSDictionary *unserializedOptions = NULL; 91 OSString *unserializeErrorString = NULL; 92 93 ret = clientHasPrivilege(fOwningTask, kIOClientPrivilegeLocalUser); 94 local_priv = (kIOReturnSuccess == ret); 95 96 ret = clientHasPrivilege(fOwningTask, kIOClientPrivilegeAdministrator); 97 admin_priv = (kIOReturnSuccess == ret); 98 99 100 if (inOptions) 101 { 102 unserializedOptions = OSDynamicCast( OSDictionary, 103 OSUnserializeXML((const char *)inOptions, inOptionsSize, &unserializeErrorString)); 104 105 if (!unserializedOptions) { 106 IOLog("IOPMRootDomain SleepSystem unserialization failure: %s\n", 107 unserializeErrorString ? unserializeErrorString->getCStringNoCopy() : "Unknown"); 108 } 109 } 110 111 if ( (local_priv || admin_priv) && fOwner ) 112 { 113 proc_t p; 114 p = (proc_t)get_bsdtask_info(fOwningTask); 115 if (p) { 116 fOwner->setProperty("SleepRequestedByPID", proc_pid(p), 32); 117 } 118 119 if (unserializedOptions) 120 { 121 // Publish Sleep Options in registry under root_domain 122 fOwner->setProperty( kRootDomainSleepOptionsKey, unserializedOptions); 123 124 *returnCode = fOwner->sleepSystemOptions( unserializedOptions ); 125 126 unserializedOptions->release(); 127 } else { 128 // No options 129 // Clear any pre-existing options 130 fOwner->removeProperty( kRootDomainSleepOptionsKey ); 131 132 *returnCode = fOwner->sleepSystemOptions( NULL ); 133 } 134 135 } else { 136 *returnCode = kIOReturnNotPrivileged; 137 } 138 139 return kIOReturnSuccess; 140} 141 142IOReturn RootDomainUserClient::secureSetAggressiveness( 143 unsigned long type, 144 unsigned long newLevel, 145 int *return_code ) 146{ 147 int local_priv = 0; 148 int admin_priv = 0; 149 IOReturn ret = kIOReturnNotPrivileged; 150 151 ret = clientHasPrivilege(fOwningTask, kIOClientPrivilegeLocalUser); 152 local_priv = (kIOReturnSuccess == ret); 153 154 ret = clientHasPrivilege(fOwningTask, kIOClientPrivilegeAdministrator); 155 admin_priv = (kIOReturnSuccess == ret); 156 157 if((local_priv || admin_priv) && fOwner) { 158 *return_code = fOwner->setAggressiveness(type, newLevel); 159 } else { 160 *return_code = kIOReturnNotPrivileged; 161 } 162 return kIOReturnSuccess; 163} 164 165IOReturn RootDomainUserClient::secureSetMaintenanceWakeCalendar( 166 IOPMCalendarStruct *inCalendar, 167 uint32_t *returnCode) 168{ 169 int admin_priv = 0; 170 IOReturn ret = kIOReturnNotPrivileged; 171 172 ret = clientHasPrivilege(fOwningTask, kIOClientPrivilegeAdministrator); 173 admin_priv = (kIOReturnSuccess == ret); 174 175 if (admin_priv && fOwner) { 176 *returnCode = fOwner->setMaintenanceWakeCalendar(inCalendar); 177 } else { 178 *returnCode = kIOReturnNotPrivileged; 179 } 180 return kIOReturnSuccess; 181} 182 183IOReturn RootDomainUserClient::secureSetUserAssertionLevels( 184 uint32_t assertionBitfield) 185{ 186 int admin_priv = 0; 187 IOReturn ret = kIOReturnNotPrivileged; 188 189 ret = clientHasPrivilege(fOwningTask, kIOClientPrivilegeAdministrator); 190 admin_priv = (kIOReturnSuccess == ret); 191 192 if (admin_priv && fOwner) { 193 ret = fOwner->setPMAssertionUserLevels(assertionBitfield); 194 } else { 195 ret = kIOReturnNotPrivileged; 196 } 197 return kIOReturnSuccess; 198} 199 200IOReturn RootDomainUserClient::secureGetSystemSleepType( 201 uint32_t *outSleepType) 202{ 203 int admin_priv = 0; 204 IOReturn ret; 205 206 ret = clientHasPrivilege(fOwningTask, kIOClientPrivilegeAdministrator); 207 admin_priv = (kIOReturnSuccess == ret); 208 209 if (admin_priv && fOwner) { 210 ret = fOwner->getSystemSleepType(outSleepType); 211 } else { 212 ret = kIOReturnNotPrivileged; 213 } 214 return ret; 215} 216 217IOReturn RootDomainUserClient::clientClose( void ) 218{ 219 detach(fOwner); 220 221 if(fOwningTask) { 222 task_deallocate(fOwningTask); 223 fOwningTask = 0; 224 } 225 226 return kIOReturnSuccess; 227} 228 229IOReturn RootDomainUserClient::externalMethod( 230 uint32_t selector, 231 IOExternalMethodArguments * arguments, 232 IOExternalMethodDispatch * dispatch __unused, 233 OSObject * target __unused, 234 void * reference __unused ) 235{ 236 IOReturn ret = kIOReturnBadArgument; 237 238 switch (selector) 239 { 240 case kPMSetAggressiveness: 241 if ((2 == arguments->scalarInputCount) 242 && (1 == arguments->scalarOutputCount)) 243 { 244 ret = this->secureSetAggressiveness( 245 (unsigned long)arguments->scalarInput[0], 246 (unsigned long)arguments->scalarInput[1], 247 (int *)&arguments->scalarOutput[0]); 248 } 249 break; 250 251 case kPMGetAggressiveness: 252 if ((1 == arguments->scalarInputCount) 253 && (1 == arguments->scalarOutputCount)) 254 { 255 ret = fOwner->getAggressiveness( 256 (unsigned long)arguments->scalarInput[0], 257 (unsigned long *)&arguments->scalarOutput[0]); 258 } 259 break; 260 261 case kPMSleepSystem: 262 if (1 == arguments->scalarOutputCount) 263 { 264 ret = this->secureSleepSystem( 265 (uint32_t *)&arguments->scalarOutput[0]); 266 } 267 break; 268 269 case kPMAllowPowerChange: 270 if (1 == arguments->scalarInputCount) 271 { 272 ret = fOwner->allowPowerChange( 273 arguments->scalarInput[0]); 274 } 275 break; 276 277 case kPMCancelPowerChange: 278 if (1 == arguments->scalarInputCount) 279 { 280 ret = fOwner->cancelPowerChange( 281 arguments->scalarInput[0]); 282 } 283 break; 284 285 case kPMShutdownSystem: 286 // deperecated interface 287 ret = kIOReturnUnsupported; 288 break; 289 290 case kPMRestartSystem: 291 // deperecated interface 292 ret = kIOReturnUnsupported; 293 break; 294 295 case kPMSleepSystemOptions: 296 ret = this->secureSleepSystemOptions( 297 arguments->structureInput, 298 arguments->structureInputSize, 299 (uint32_t *)&arguments->scalarOutput[0]); 300 break; 301 case kPMSetMaintenanceWakeCalendar: 302 ret = this->secureSetMaintenanceWakeCalendar( 303 (IOPMCalendarStruct *)arguments->structureInput, 304 (uint32_t *)&arguments->structureOutput); 305 arguments->structureOutputSize = sizeof(uint32_t); 306 break; 307 308 case kPMSetUserAssertionLevels: 309 ret = this->secureSetUserAssertionLevels( 310 (uint32_t)arguments->scalarInput[0]); 311 break; 312 313 case kPMActivityTickle: 314 if ( fOwner->checkSystemCanSustainFullWake() ) 315 { 316 fOwner->reportUserInput( ); 317 fOwner->setProperty(kIOPMRootDomainWakeTypeKey, "UserActivity Assertion"); 318 } 319 ret = kIOReturnSuccess; 320 break; 321 322 case kPMSetClamshellSleepState: 323 fOwner->setDisableClamShellSleep(arguments->scalarInput[0] ? true : false); 324 ret = kIOReturnSuccess; 325 break; 326 327 case kPMGetSystemSleepType: 328 if (1 == arguments->scalarOutputCount) 329 { 330 ret = this->secureGetSystemSleepType( 331 (uint32_t *) &arguments->scalarOutput[0]); 332 } 333 break; 334 335#if defined(__i386__) || defined(__x86_64__) 336 case kPMSleepWakeWatchdogEnable: 337 ret = clientHasPrivilege(fOwningTask, kIOClientPrivilegeAdministrator); 338 if (ret == kIOReturnSuccess) 339 fOwner->sleepWakeDebugEnableWdog(); 340 break; 341 342 343 case kPMSleepWakeDebugTrig: 344 ret = clientHasPrivilege(fOwningTask, kIOClientPrivilegeAdministrator); 345 if (ret == kIOReturnSuccess) 346 fOwner->sleepWakeDebugTrig(false); 347 break; 348#endif 349 350 case kPMSetDisplayPowerOn: 351 if (1 == arguments->scalarInputCount) 352 { 353 ret = clientHasPrivilege(fOwningTask, kIOClientPrivilegeAdministrator); 354 if (ret == kIOReturnSuccess) 355 fOwner->setDisplayPowerOn((uint32_t)arguments->scalarInput[0]); 356 } 357 break; 358 359 default: 360 // bad selector 361 return kIOReturnBadArgument; 362 } 363 364 return ret; 365} 366 367/* getTargetAndMethodForIndex 368 * Not used. We prefer to use externalMethod() for user client invocations. 369 * We maintain getTargetAndExternalMethod since it's an exported symbol, 370 * and only for that reason. 371 */ 372IOExternalMethod * RootDomainUserClient::getTargetAndMethodForIndex( 373 IOService ** targetP, UInt32 index ) 374{ 375 // DO NOT EDIT 376 return super::getTargetAndMethodForIndex(targetP, index); 377} 378 379/* setPreventative 380 * Does nothing. Exists only for exported symbol compatibility. 381 */ 382void 383RootDomainUserClient::setPreventative(UInt32 on_off, UInt32 types_of_sleep) 384{ return; } // DO NOT EDIT 385