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 46 OSDefineMetaClassAndStructors(RootDomainUserClient, IOUserClient) 47 48 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 49 50 bool 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 65 bool 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 76 IOReturn RootDomainUserClient::secureSleepSystem( uint32_t *return_code ) 77 { 78 return secureSleepSystemOptions(NULL, 0, return_code); 79 } 80 81 IOReturn 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 142 IOReturn 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 165 IOReturn 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 183 IOReturn 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 200 IOReturn RootDomainUserClient::secureGetSystemSleepType( 201 uint32_t *outSleepType, uint32_t *sleepTimer) 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, sleepTimer); 211 } else { 212 ret = kIOReturnNotPrivileged; 213 } 214 return ret; 215 } 216 217 IOReturn RootDomainUserClient::clientClose( void ) 218 { 219 terminate(); 220 221 return kIOReturnSuccess; 222 } 223 224 void RootDomainUserClient::stop( IOService *provider) 225 { 226 if(fOwningTask) { 227 task_deallocate(fOwningTask); 228 fOwningTask = 0; 229 } 230 231 super::stop(provider); 232 } 233 234 IOReturn RootDomainUserClient::externalMethod( 235 uint32_t selector, 236 IOExternalMethodArguments * arguments, 237 IOExternalMethodDispatch * dispatch __unused, 238 OSObject * target __unused, 239 void * reference __unused ) 240 { 241 IOReturn ret = kIOReturnBadArgument; 242 243 switch (selector) 244 { 245 case kPMSetAggressiveness: 246 if ((2 == arguments->scalarInputCount) 247 && (1 == arguments->scalarOutputCount)) 248 { 249 ret = this->secureSetAggressiveness( 250 (unsigned long)arguments->scalarInput[0], 251 (unsigned long)arguments->scalarInput[1], 252 (int *)&arguments->scalarOutput[0]); 253 } 254 break; 255 256 case kPMGetAggressiveness: 257 if ((1 == arguments->scalarInputCount) 258 && (1 == arguments->scalarOutputCount)) 259 { 260 ret = fOwner->getAggressiveness( 261 (unsigned long)arguments->scalarInput[0], 262 (unsigned long *)&arguments->scalarOutput[0]); 263 } 264 break; 265 266 case kPMSleepSystem: 267 if (1 == arguments->scalarOutputCount) 268 { 269 ret = this->secureSleepSystem( 270 (uint32_t *)&arguments->scalarOutput[0]); 271 } 272 break; 273 274 case kPMAllowPowerChange: 275 if (1 == arguments->scalarInputCount) 276 { 277 ret = fOwner->allowPowerChange( 278 arguments->scalarInput[0]); 279 } 280 break; 281 282 case kPMCancelPowerChange: 283 if (1 == arguments->scalarInputCount) 284 { 285 ret = fOwner->cancelPowerChange( 286 arguments->scalarInput[0]); 287 } 288 break; 289 290 case kPMShutdownSystem: 291 // deperecated interface 292 ret = kIOReturnUnsupported; 293 break; 294 295 case kPMRestartSystem: 296 // deperecated interface 297 ret = kIOReturnUnsupported; 298 break; 299 300 case kPMSleepSystemOptions: 301 ret = this->secureSleepSystemOptions( 302 arguments->structureInput, 303 arguments->structureInputSize, 304 (uint32_t *)&arguments->scalarOutput[0]); 305 break; 306 case kPMSetMaintenanceWakeCalendar: 307 if ((arguments->structureInputSize >= sizeof(IOPMCalendarStruct)) && 308 (arguments->structureOutputSize >= sizeof(uint32_t) )) { 309 ret = this->secureSetMaintenanceWakeCalendar( 310 (IOPMCalendarStruct *)arguments->structureInput, 311 (uint32_t *)&arguments->structureOutput); 312 arguments->structureOutputSize = sizeof(uint32_t); 313 } 314 break; 315 316 case kPMSetUserAssertionLevels: 317 ret = this->secureSetUserAssertionLevels( 318 (uint32_t)arguments->scalarInput[0]); 319 break; 320 321 case kPMActivityTickle: 322 if ( fOwner->checkSystemCanSustainFullWake() ) 323 { 324 fOwner->reportUserInput( ); 325 fOwner->setProperty(kIOPMRootDomainWakeTypeKey, "UserActivity Assertion"); 326 } 327 ret = kIOReturnSuccess; 328 break; 329 330 case kPMSetClamshellSleepState: 331 fOwner->setDisableClamShellSleep(arguments->scalarInput[0] ? true : false); 332 ret = kIOReturnSuccess; 333 break; 334 335 case kPMGetSystemSleepType: 336 if (2 == arguments->scalarOutputCount) 337 { 338 ret = this->secureGetSystemSleepType( 339 (uint32_t *) &arguments->scalarOutput[0], 340 (uint32_t *) &arguments->scalarOutput[1]); 341 } 342 break; 343 344 #if defined(__i386__) || defined(__x86_64__) 345 case kPMSleepWakeWatchdogEnable: 346 ret = clientHasPrivilege(fOwningTask, kIOClientPrivilegeAdministrator); 347 if (ret == kIOReturnSuccess) 348 fOwner->sleepWakeDebugEnableWdog(); 349 break; 350 351 352 case kPMSleepWakeDebugTrig: 353 ret = clientHasPrivilege(fOwningTask, kIOClientPrivilegeAdministrator); 354 if (ret == kIOReturnSuccess) 355 fOwner->sleepWakeDebugTrig(false); 356 break; 357 #endif 358 359 case kPMSetDisplayPowerOn: 360 if (1 == arguments->scalarInputCount) 361 { 362 ret = clientHasPrivilege(fOwningTask, kIOClientPrivilegeAdministrator); 363 if (ret == kIOReturnSuccess) 364 fOwner->setDisplayPowerOn((uint32_t)arguments->scalarInput[0]); 365 } 366 break; 367 368 default: 369 // bad selector 370 return kIOReturnBadArgument; 371 } 372 373 return ret; 374 } 375 376 /* getTargetAndMethodForIndex 377 * Not used. We prefer to use externalMethod() for user client invocations. 378 * We maintain getTargetAndExternalMethod since it's an exported symbol, 379 * and only for that reason. 380 */ 381 IOExternalMethod * RootDomainUserClient::getTargetAndMethodForIndex( 382 IOService ** targetP, UInt32 index ) 383 { 384 // DO NOT EDIT 385 return super::getTargetAndMethodForIndex(targetP, index); 386 } 387 388 /* setPreventative 389 * Does nothing. Exists only for exported symbol compatibility. 390 */ 391 void 392 RootDomainUserClient::setPreventative(UInt32 on_off, UInt32 types_of_sleep) 393 { return; } // DO NOT EDIT 394