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 IOByteCount return_code_size = 1; 77 78 return secureSleepSystemOptions( NULL, // inOptions 79 (void *)return_code, // returnCode 80 (void *)0, // inSize 81 (void *)&return_code_size, // returnSize 82 NULL, NULL); 83 } 84 85 IOReturn RootDomainUserClient::secureSleepSystemOptions( 86 void * p1, void * p2, void * p3, 87 void * p4, void * p5, void * p6 ) 88 { 89 void *inOptions = (void *)p1; 90 uint32_t *returnCode = (uint32_t *)p2; 91 IOByteCount inOptionsSize = (IOByteCount)p3; 92 IOByteCount *returnCodeSize = (IOByteCount *)p4; 93 94 int local_priv = 0; 95 int admin_priv = 0; 96 IOReturn ret = kIOReturnNotPrivileged; 97 OSDictionary *unserializedOptions = NULL; 98 OSString *unserializeErrorString = NULL; 99 100 ret = clientHasPrivilege(fOwningTask, kIOClientPrivilegeLocalUser); 101 local_priv = (kIOReturnSuccess == ret); 102 103 ret = clientHasPrivilege(fOwningTask, kIOClientPrivilegeAdministrator); 104 admin_priv = (kIOReturnSuccess == ret); 105 106 *returnCodeSize = sizeof(uint32_t); 107 108 if (inOptions) 109 { 110 unserializedOptions = OSDynamicCast( OSDictionary, 111 OSUnserializeXML((const char *)inOptions, &unserializeErrorString)); 112 113 if (!unserializedOptions) { 114 IOLog("IOPMRootDomain SleepSystem unserialization failure: %s\n", 115 unserializeErrorString ? unserializeErrorString->getCStringNoCopy() : "Unknown"); 116 } 117 } 118 119 if ( (local_priv || admin_priv) 120 && fOwner ) 121 { 122 if (unserializedOptions) 123 { 124 // Publish Sleep Options in registry under root_domain 125 fOwner->setProperty( kRootDomainSleepOptionsKey, unserializedOptions); 126 127 *returnCode = fOwner->sleepSystemOptions( unserializedOptions ); 128 129 unserializedOptions->release(); 130 } else { 131 // No options 132 // Clear any pre-existing options 133 fOwner->removeProperty( kRootDomainSleepOptionsKey ); 134 135 *returnCode = fOwner->sleepSystemOptions( NULL ); 136 } 137 138 } else { 139 *returnCode = kIOReturnNotPrivileged; 140 } 141 142 return kIOReturnSuccess; 143 } 144 145 IOReturn RootDomainUserClient::secureSetAggressiveness( 146 unsigned long type, 147 unsigned long newLevel, 148 int *return_code ) 149 { 150 int local_priv = 0; 151 int admin_priv = 0; 152 IOReturn ret = kIOReturnNotPrivileged; 153 154 ret = clientHasPrivilege(fOwningTask, kIOClientPrivilegeLocalUser); 155 local_priv = (kIOReturnSuccess == ret); 156 157 ret = clientHasPrivilege(fOwningTask, kIOClientPrivilegeAdministrator); 158 admin_priv = (kIOReturnSuccess == ret); 159 160 if((local_priv || admin_priv) && fOwner) { 161 *return_code = fOwner->setAggressiveness(type, newLevel); 162 return kIOReturnSuccess; 163 } else { 164 *return_code = kIOReturnNotPrivileged; 165 return kIOReturnSuccess; 166 } 167 168 } 169 170 171 IOReturn RootDomainUserClient::clientClose( void ) 172 { 173 detach(fOwner); 174 175 if(fOwningTask) { 176 task_deallocate(fOwningTask); 177 fOwningTask = 0; 178 } 179 180 return kIOReturnSuccess; 181 } 182 183 IOExternalMethod * 184 RootDomainUserClient::getTargetAndMethodForIndex( IOService ** targetP, UInt32 index ) 185 { 186 static const IOExternalMethod sMethods[] = { 187 { // kPMSetAggressiveness, 0 188 (IOService *)1, (IOMethod)&RootDomainUserClient::secureSetAggressiveness, kIOUCScalarIScalarO, 2, 1 189 }, 190 { // kPMGetAggressiveness, 1 191 0, (IOMethod)&IOPMrootDomain::getAggressiveness, kIOUCScalarIScalarO, 1, 1 192 }, 193 { // kPMSleepSystem, 2 194 (IOService *)1, (IOMethod)&RootDomainUserClient::secureSleepSystem, kIOUCScalarIScalarO, 0, 1 195 }, 196 { // kPMAllowPowerChange, 3 197 0, (IOMethod)&IOPMrootDomain::allowPowerChange, kIOUCScalarIScalarO, 1, 0 198 }, 199 { // kPMCancelPowerChange, 4 200 0, (IOMethod)&IOPMrootDomain::cancelPowerChange, kIOUCScalarIScalarO, 1, 0 201 }, 202 { // kPMShutdownSystem, 5 203 0, (IOMethod)&IOPMrootDomain::shutdownSystem, kIOUCScalarIScalarO, 0, 0 204 }, 205 { // kPMRestartSystem, 6 206 0, (IOMethod)&IOPMrootDomain::restartSystem, kIOUCScalarIScalarO, 0, 0 207 }, 208 { // kPMSleepSystemOptions, 7 209 (IOService *)1, (IOMethod)&RootDomainUserClient::secureSleepSystemOptions, 210 kIOUCStructIStructO, kIOUCVariableStructureSize, sizeof(uint32_t) 211 } 212 }; 213 214 if(index >= kNumPMMethods) 215 return NULL; 216 else { 217 if (sMethods[index].object) 218 *targetP = this; 219 else 220 *targetP = fOwner; 221 222 return (IOExternalMethod *)&sMethods[index]; 223 } 224 } 225 226 #if 0 227 IOReturn RootDomainUserClient::externalMethod( uint32_t selector, IOExternalMethodArguments * args, 228 IOExternalMethodDispatch * dispatch, OSObject * target, void * reference ) 229 { 230 static const IOExternalMethodDispatch sMethods[] = { 231 { // kPMSetAggressiveness, 0 232 (IOService *)1, (IOMethod)&RootDomainUserClient::secureSetAggressiveness, kIOUCScalarIScalarO, 2, 1 233 }, 234 { // kPMGetAggressiveness, 1 235 0, (IOMethod)&IOPMrootDomain::getAggressiveness, kIOUCScalarIScalarO, 1, 1 236 }, 237 { // kPMSleepSystem, 2 238 (IOService *)1, (IOMethod)&RootDomainUserClient::secureSleepSystem, kIOUCScalarIScalarO, 0, 1 239 }, 240 { // kPMAllowPowerChange, 3 241 0, (IOMethod)&IOPMrootDomain::allowPowerChange, kIOUCScalarIScalarO, 1, 0 242 }, 243 { // kPMCancelPowerChange, 4 244 0, (IOMethod)&IOPMrootDomain::cancelPowerChange, kIOUCScalarIScalarO, 1, 0 245 }, 246 { // kPMShutdownSystem, 5 247 0, (IOMethod)&IOPMrootDomain::shutdownSystem, kIOUCScalarIScalarO, 0, 0 248 }, 249 { // kPMRestartSystem, 6 250 0, (IOMethod)&IOPMrootDomain::restartSystem, kIOUCScalarIScalarO, 0, 0 251 }, 252 { // kPMSetPreventative, 7 253 (IOService *)1, (IOMethod)&RootDomainUserClient::setPreventative, kIOUCScalarIScalarO, 2, 0 254 }, 255 }; 256 257 if (selector > (sizeof(sMethods) / sizeof(sMethods[0]))) 258 return (kIOReturnBadArgument); 259 260 if ((1 << selector) & ((1 << 0) | (1 << 7)) 261 target = this; 262 else 263 target = fOwner; 264 265 return (super::externalMethod(selector, args, &sMethods[selector], target, 0)); 266 } 267 #endif 268 269 void 270 RootDomainUserClient::setPreventative(UInt32 on_off, UInt32 types_of_sleep) 271 { 272 return; 273 } 274 275