1 /* 2 * Copyright (c) 1998-2000 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 41 #define super IOUserClient 42 43 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 44 45 OSDefineMetaClassAndStructors(RootDomainUserClient, IOUserClient) 46 47 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 48 49 bool RootDomainUserClient::initWithTask(task_t owningTask, void *security_id, 50 UInt32 type, OSDictionary * properties) 51 { 52 if (properties) 53 properties->setObject(kIOUserClientCrossEndianCompatibleKey, kOSBooleanTrue); 54 55 if (!super::initWithTask(owningTask, security_id, type, properties)) 56 return false; 57 58 fOwningTask = owningTask; 59 task_reference (fOwningTask); 60 return true; 61 } 62 63 64 bool RootDomainUserClient::start( IOService * provider ) 65 { 66 assert(OSDynamicCast(IOPMrootDomain, provider)); 67 if(!super::start(provider)) 68 return false; 69 fOwner = (IOPMrootDomain *)provider; 70 71 72 return true; 73 } 74 75 IOReturn RootDomainUserClient::secureSleepSystem( uint32_t *return_code ) 76 { 77 return secureSleepSystemOptions(NULL, 0, return_code); 78 } 79 80 IOReturn RootDomainUserClient::secureSleepSystemOptions( 81 const void *inOptions, 82 IOByteCount inOptionsSize __unused, 83 uint32_t *returnCode) 84 { 85 86 int local_priv = 0; 87 int admin_priv = 0; 88 IOReturn ret = kIOReturnNotPrivileged; 89 OSDictionary *unserializedOptions = NULL; 90 OSString *unserializeErrorString = NULL; 91 92 ret = clientHasPrivilege(fOwningTask, kIOClientPrivilegeLocalUser); 93 local_priv = (kIOReturnSuccess == ret); 94 95 ret = clientHasPrivilege(fOwningTask, kIOClientPrivilegeAdministrator); 96 admin_priv = (kIOReturnSuccess == ret); 97 98 99 if (inOptions) 100 { 101 unserializedOptions = OSDynamicCast( OSDictionary, 102 OSUnserializeXML((const char *)inOptions, &unserializeErrorString)); 103 104 if (!unserializedOptions) { 105 IOLog("IOPMRootDomain SleepSystem unserialization failure: %s\n", 106 unserializeErrorString ? unserializeErrorString->getCStringNoCopy() : "Unknown"); 107 } 108 } 109 110 if ( (local_priv || admin_priv) 111 && fOwner ) 112 { 113 if (unserializedOptions) 114 { 115 // Publish Sleep Options in registry under root_domain 116 fOwner->setProperty( kRootDomainSleepOptionsKey, unserializedOptions); 117 118 *returnCode = fOwner->sleepSystemOptions( unserializedOptions ); 119 120 unserializedOptions->release(); 121 } else { 122 // No options 123 // Clear any pre-existing options 124 fOwner->removeProperty( kRootDomainSleepOptionsKey ); 125 126 *returnCode = fOwner->sleepSystemOptions( NULL ); 127 } 128 129 } else { 130 *returnCode = kIOReturnNotPrivileged; 131 } 132 133 return kIOReturnSuccess; 134 } 135 136 IOReturn RootDomainUserClient::secureSetAggressiveness( 137 unsigned long type, 138 unsigned long newLevel, 139 int *return_code ) 140 { 141 int local_priv = 0; 142 int admin_priv = 0; 143 IOReturn ret = kIOReturnNotPrivileged; 144 145 ret = clientHasPrivilege(fOwningTask, kIOClientPrivilegeLocalUser); 146 local_priv = (kIOReturnSuccess == ret); 147 148 ret = clientHasPrivilege(fOwningTask, kIOClientPrivilegeAdministrator); 149 admin_priv = (kIOReturnSuccess == ret); 150 151 if((local_priv || admin_priv) && fOwner) { 152 *return_code = fOwner->setAggressiveness(type, newLevel); 153 } else { 154 *return_code = kIOReturnNotPrivileged; 155 } 156 return kIOReturnSuccess; 157 } 158 159 IOReturn RootDomainUserClient::secureSetMaintenanceWakeCalendar( 160 IOPMCalendarStruct *inCalendar, 161 uint32_t *returnCode) 162 { 163 int admin_priv = 0; 164 IOReturn ret = kIOReturnNotPrivileged; 165 166 ret = clientHasPrivilege(fOwningTask, kIOClientPrivilegeAdministrator); 167 admin_priv = (kIOReturnSuccess == ret); 168 169 if (admin_priv && fOwner) { 170 *returnCode = fOwner->setMaintenanceWakeCalendar(inCalendar); 171 } else { 172 *returnCode = kIOReturnNotPrivileged; 173 } 174 return kIOReturnSuccess; 175 } 176 177 IOReturn RootDomainUserClient::secureSetUserAssertionLevels( 178 uint32_t assertionBitfield) 179 { 180 int admin_priv = 0; 181 IOReturn ret = kIOReturnNotPrivileged; 182 183 ret = clientHasPrivilege(fOwningTask, kIOClientPrivilegeAdministrator); 184 admin_priv = (kIOReturnSuccess == ret); 185 186 if (admin_priv && fOwner) { 187 ret = fOwner->setPMAssertionUserLevels(assertionBitfield); 188 } else { 189 ret = kIOReturnNotPrivileged; 190 } 191 return kIOReturnSuccess; 192 } 193 194 IOReturn RootDomainUserClient::clientClose( void ) 195 { 196 detach(fOwner); 197 198 if(fOwningTask) { 199 task_deallocate(fOwningTask); 200 fOwningTask = 0; 201 } 202 203 return kIOReturnSuccess; 204 } 205 206 IOReturn RootDomainUserClient::clientMemoryForType( 207 UInt32 type, 208 IOOptionBits *options, 209 IOMemoryDescriptor ** memory) 210 { 211 if (!fOwner) 212 return kIOReturnNotReady; 213 214 if (kPMRootDomainMapTraceBuffer == type) 215 { 216 *memory = fOwner->getPMTraceMemoryDescriptor(); 217 if (*memory) { 218 (*memory)->retain(); 219 *options = 0; 220 return kIOReturnSuccess; 221 } else { 222 return kIOReturnNotFound; 223 } 224 225 } 226 return kIOReturnUnsupported; 227 } 228 229 IOReturn 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 fOwner->reportUserInput( ); 315 fOwner->setProperty(kIOPMRootDomainWakeTypeKey, "UserActivity Assertion"); 316 ret = kIOReturnSuccess; 317 break; 318 319 /* 320 case kPMMethodCopySystemTimeline: 321 // intentional fallthrough 322 case kPMMethodCopyDetailedTimeline: 323 324 if (!arguments->structureOutputDescriptor) 325 { 326 // TODO: Force IOKit.framework to always send this data out 327 // of line; so I don't have to create a MemoryDescriptor here. 328 mem_size = arguments->structureOutputSize; 329 mem = IOMemoryDescriptor::withAddressRange( 330 (mach_vm_address_t)arguments->structureOutput, 331 (mach_vm_size_t)mem_size, 332 kIODirectionIn, current_task()); 333 } else { 334 mem_size = arguments->structureOutputDescriptorSize; 335 if (( mem = arguments->structureOutputDescriptor )) 336 mem->retain(); 337 } 338 339 if (mem) 340 { 341 mem->prepare(kIODirectionNone); 342 343 if (kPMMethodCopySystemTimeline == selector) { 344 arguments->scalarOutput[0] = fOwner->copySystemTimeline( 345 mem, &mem_size); 346 } 347 else 348 if (kPMMethodCopyDetailedTimeline == selector) { 349 arguments->scalarOutput[0] = fOwner->copyDetailedTimeline( 350 mem, &mem_size); 351 } 352 353 if (arguments->structureOutputDescriptor) { 354 arguments->structureOutputDescriptorSize = mem_size; 355 } else { 356 arguments->structureOutputSize = mem_size; 357 } 358 359 mem->release(); 360 361 ret = kIOReturnSuccess; 362 } else { 363 ret = kIOReturnCannotWire; 364 } 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