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 40 #define super IOUserClient 41 42 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 43 44 OSDefineMetaClassAndStructors(RootDomainUserClient, IOUserClient) 45 46 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 47 48 bool RootDomainUserClient::initWithTask(task_t owningTask, void *security_id, 49 UInt32 type, OSDictionary * properties) 50 { 51 if (properties) 52 properties->setObject(kIOUserClientCrossEndianCompatibleKey, kOSBooleanTrue); 53 54 if (!super::initWithTask(owningTask, security_id, type, properties)) 55 return false; 56 57 fOwningTask = owningTask; 58 task_reference (fOwningTask); 59 return true; 60 } 61 62 63 bool RootDomainUserClient::start( IOService * provider ) 64 { 65 assert(OSDynamicCast(IOPMrootDomain, provider)); 66 if(!super::start(provider)) 67 return false; 68 fOwner = (IOPMrootDomain *)provider; 69 70 71 return true; 72 } 73 74 IOReturn RootDomainUserClient::secureSleepSystem( uint32_t *return_code ) 75 { 76 return secureSleepSystemOptions(NULL, 0, return_code); 77 } 78 79 IOReturn RootDomainUserClient::secureSleepSystemOptions( 80 const void *inOptions, 81 IOByteCount inOptionsSize __unused, 82 uint32_t *returnCode) 83 { 84 85 int local_priv = 0; 86 int admin_priv = 0; 87 IOReturn ret = kIOReturnNotPrivileged; 88 OSDictionary *unserializedOptions = NULL; 89 OSString *unserializeErrorString = NULL; 90 91 ret = clientHasPrivilege(fOwningTask, kIOClientPrivilegeLocalUser); 92 local_priv = (kIOReturnSuccess == ret); 93 94 ret = clientHasPrivilege(fOwningTask, kIOClientPrivilegeAdministrator); 95 admin_priv = (kIOReturnSuccess == ret); 96 97 98 if (inOptions) 99 { 100 unserializedOptions = OSDynamicCast( OSDictionary, 101 OSUnserializeXML((const char *)inOptions, &unserializeErrorString)); 102 103 if (!unserializedOptions) { 104 IOLog("IOPMRootDomain SleepSystem unserialization failure: %s\n", 105 unserializeErrorString ? unserializeErrorString->getCStringNoCopy() : "Unknown"); 106 } 107 } 108 109 if ( (local_priv || admin_priv) 110 && fOwner ) 111 { 112 if (unserializedOptions) 113 { 114 // Publish Sleep Options in registry under root_domain 115 fOwner->setProperty( kRootDomainSleepOptionsKey, unserializedOptions); 116 117 *returnCode = fOwner->sleepSystemOptions( unserializedOptions ); 118 119 unserializedOptions->release(); 120 } else { 121 // No options 122 // Clear any pre-existing options 123 fOwner->removeProperty( kRootDomainSleepOptionsKey ); 124 125 *returnCode = fOwner->sleepSystemOptions( NULL ); 126 } 127 128 } else { 129 *returnCode = kIOReturnNotPrivileged; 130 } 131 132 return kIOReturnSuccess; 133 } 134 135 IOReturn RootDomainUserClient::secureSetAggressiveness( 136 unsigned long type, 137 unsigned long newLevel, 138 int *return_code ) 139 { 140 int local_priv = 0; 141 int admin_priv = 0; 142 IOReturn ret = kIOReturnNotPrivileged; 143 144 ret = clientHasPrivilege(fOwningTask, kIOClientPrivilegeLocalUser); 145 local_priv = (kIOReturnSuccess == ret); 146 147 ret = clientHasPrivilege(fOwningTask, kIOClientPrivilegeAdministrator); 148 admin_priv = (kIOReturnSuccess == ret); 149 150 if((local_priv || admin_priv) && fOwner) { 151 *return_code = fOwner->setAggressiveness(type, newLevel); 152 } else { 153 *return_code = kIOReturnNotPrivileged; 154 } 155 return kIOReturnSuccess; 156 } 157 158 IOReturn RootDomainUserClient::secureSetMaintenanceWakeCalendar( 159 IOPMCalendarStruct *inCalendar, 160 uint32_t *returnCode) 161 { 162 int admin_priv = 0; 163 IOReturn ret = kIOReturnNotPrivileged; 164 165 ret = clientHasPrivilege(fOwningTask, kIOClientPrivilegeAdministrator); 166 admin_priv = (kIOReturnSuccess == ret); 167 168 if (admin_priv && fOwner) { 169 *returnCode = fOwner->setMaintenanceWakeCalendar(inCalendar); 170 } else { 171 *returnCode = kIOReturnNotPrivileged; 172 } 173 return kIOReturnSuccess; 174 } 175 176 IOReturn RootDomainUserClient::secureSetUserAssertionLevels( 177 uint32_t assertionBitfield) 178 { 179 int admin_priv = 0; 180 IOReturn ret = kIOReturnNotPrivileged; 181 182 ret = clientHasPrivilege(fOwningTask, kIOClientPrivilegeAdministrator); 183 admin_priv = (kIOReturnSuccess == ret); 184 185 if (admin_priv && fOwner) { 186 ret = fOwner->setPMAssertionUserLevels(assertionBitfield); 187 } else { 188 ret = kIOReturnNotPrivileged; 189 } 190 return kIOReturnSuccess; 191 } 192 193 IOReturn RootDomainUserClient::clientClose( void ) 194 { 195 detach(fOwner); 196 197 if(fOwningTask) { 198 task_deallocate(fOwningTask); 199 fOwningTask = 0; 200 } 201 202 return kIOReturnSuccess; 203 } 204 205 IOReturn RootDomainUserClient::clientMemoryForType( 206 UInt32 type, 207 IOOptionBits *options, 208 IOMemoryDescriptor ** memory) 209 { 210 if (!fOwner) 211 return kIOReturnNotReady; 212 213 if (kPMRootDomainMapTraceBuffer == type) 214 { 215 *memory = fOwner->getPMTraceMemoryDescriptor(); 216 if (*memory) { 217 (*memory)->retain(); 218 *options = 0; 219 return kIOReturnSuccess; 220 } else { 221 return kIOReturnNotFound; 222 } 223 224 } 225 return kIOReturnUnsupported; 226 } 227 228 IOReturn RootDomainUserClient::externalMethod( 229 uint32_t selector, 230 IOExternalMethodArguments * arguments, 231 IOExternalMethodDispatch * dispatch __unused, 232 OSObject * target __unused, 233 void * reference __unused ) 234 { 235 IOReturn ret = kIOReturnBadArgument; 236 237 switch (selector) 238 { 239 case kPMSetAggressiveness: 240 if ((2 == arguments->scalarInputCount) 241 && (1 == arguments->scalarOutputCount)) 242 { 243 ret = this->secureSetAggressiveness( 244 (unsigned long)arguments->scalarInput[0], 245 (unsigned long)arguments->scalarInput[1], 246 (int *)&arguments->scalarOutput[0]); 247 } 248 break; 249 250 case kPMGetAggressiveness: 251 if ((1 == arguments->scalarInputCount) 252 && (1 == arguments->scalarOutputCount)) 253 { 254 ret = fOwner->getAggressiveness( 255 (unsigned long)arguments->scalarInput[0], 256 (unsigned long *)&arguments->scalarOutput[0]); 257 } 258 break; 259 260 case kPMSleepSystem: 261 if (1 == arguments->scalarOutputCount) 262 { 263 ret = this->secureSleepSystem( 264 (uint32_t *)&arguments->scalarOutput[0]); 265 } 266 break; 267 268 case kPMAllowPowerChange: 269 if (1 == arguments->scalarInputCount) 270 { 271 ret = fOwner->allowPowerChange( 272 arguments->scalarInput[0]); 273 } 274 break; 275 276 case kPMCancelPowerChange: 277 if (1 == arguments->scalarInputCount) 278 { 279 ret = fOwner->cancelPowerChange( 280 arguments->scalarInput[0]); 281 } 282 break; 283 284 case kPMShutdownSystem: 285 // deperecated interface 286 ret = kIOReturnUnsupported; 287 break; 288 289 case kPMRestartSystem: 290 // deperecated interface 291 ret = kIOReturnUnsupported; 292 break; 293 294 case kPMSleepSystemOptions: 295 ret = this->secureSleepSystemOptions( 296 arguments->structureInput, 297 arguments->structureInputSize, 298 (uint32_t *)&arguments->scalarOutput[0]); 299 break; 300 case kPMSetMaintenanceWakeCalendar: 301 ret = this->secureSetMaintenanceWakeCalendar( 302 (IOPMCalendarStruct *)arguments->structureInput, 303 (uint32_t *)&arguments->structureOutput); 304 arguments->structureOutputSize = sizeof(uint32_t); 305 break; 306 307 case kPMSetUserAssertionLevels: 308 ret = this->secureSetUserAssertionLevels( 309 (uint32_t)arguments->scalarInput[0]); 310 break; 311 312 /* 313 case kPMMethodCopySystemTimeline: 314 // intentional fallthrough 315 case kPMMethodCopyDetailedTimeline: 316 317 if (!arguments->structureOutputDescriptor) 318 { 319 // TODO: Force IOKit.framework to always send this data out 320 // of line; so I don't have to create a MemoryDescriptor here. 321 mem_size = arguments->structureOutputSize; 322 mem = IOMemoryDescriptor::withAddressRange( 323 (mach_vm_address_t)arguments->structureOutput, 324 (mach_vm_size_t)mem_size, 325 kIODirectionIn, current_task()); 326 } else { 327 mem_size = arguments->structureOutputDescriptorSize; 328 if (( mem = arguments->structureOutputDescriptor )) 329 mem->retain(); 330 } 331 332 if (mem) 333 { 334 mem->prepare(kIODirectionNone); 335 336 if (kPMMethodCopySystemTimeline == selector) { 337 arguments->scalarOutput[0] = fOwner->copySystemTimeline( 338 mem, &mem_size); 339 } 340 else 341 if (kPMMethodCopyDetailedTimeline == selector) { 342 arguments->scalarOutput[0] = fOwner->copyDetailedTimeline( 343 mem, &mem_size); 344 } 345 346 if (arguments->structureOutputDescriptor) { 347 arguments->structureOutputDescriptorSize = mem_size; 348 } else { 349 arguments->structureOutputSize = mem_size; 350 } 351 352 mem->release(); 353 354 ret = kIOReturnSuccess; 355 } else { 356 ret = kIOReturnCannotWire; 357 } 358 359 break; 360 */ 361 default: 362 // bad selector 363 return kIOReturnBadArgument; 364 } 365 366 return ret; 367 } 368 369 /* getTargetAndMethodForIndex 370 * Not used. We prefer to use externalMethod() for user client invocations. 371 * We maintain getTargetAndExternalMethod since it's an exported symbol, 372 * and only for that reason. 373 */ 374 IOExternalMethod * RootDomainUserClient::getTargetAndMethodForIndex( 375 IOService ** targetP, UInt32 index ) 376 { 377 // DO NOT EDIT 378 return super::getTargetAndMethodForIndex(targetP, index); 379 } 380 381 /* setPreventative 382 * Does nothing. Exists only for exported symbol compatibility. 383 */ 384 void 385 RootDomainUserClient::setPreventative(UInt32 on_off, UInt32 types_of_sleep) 386 { return; } // DO NOT EDIT 387