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 = (uintptr_t)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 IOReturn RootDomainUserClient::secureSetMaintenanceWakeCalendar( 170 void * p1, void * p2, void * p3, 171 void * p4, void * p5, void * p6 ) 172 { 173 #if ROOT_DOMAIN_RUN_STATES 174 IOPMCalendarStruct * inCalendar = (IOPMCalendarStruct *) p1; 175 uint32_t * returnCode = (uint32_t *) p2; 176 IOByteCount * returnCodeSize = (IOByteCount *) p4; 177 int admin_priv = 0; 178 IOReturn ret = kIOReturnNotPrivileged; 179 180 ret = clientHasPrivilege(fOwningTask, kIOClientPrivilegeAdministrator); 181 admin_priv = (kIOReturnSuccess == ret); 182 183 *returnCodeSize = sizeof(uint32_t); 184 185 if (admin_priv && fOwner) { 186 *returnCode = fOwner->setMaintenanceWakeCalendar(inCalendar); 187 return kIOReturnSuccess; 188 } else { 189 *returnCode = kIOReturnNotPrivileged; 190 return kIOReturnSuccess; 191 } 192 #else 193 return kIOReturnUnsupported; 194 #endif 195 } 196 197 IOReturn RootDomainUserClient::clientClose( void ) 198 { 199 detach(fOwner); 200 201 if(fOwningTask) { 202 task_deallocate(fOwningTask); 203 fOwningTask = 0; 204 } 205 206 return kIOReturnSuccess; 207 } 208 209 IOExternalMethod * 210 RootDomainUserClient::getTargetAndMethodForIndex( IOService ** targetP, UInt32 index ) 211 { 212 static const IOExternalMethod sMethods[] = { 213 { // kPMSetAggressiveness, 0 214 (IOService *)1, (IOMethod)&RootDomainUserClient::secureSetAggressiveness, kIOUCScalarIScalarO, 2, 1 215 }, 216 { // kPMGetAggressiveness, 1 217 0, (IOMethod)&IOPMrootDomain::getAggressiveness, kIOUCScalarIScalarO, 1, 1 218 }, 219 { // kPMSleepSystem, 2 220 (IOService *)1, (IOMethod)&RootDomainUserClient::secureSleepSystem, kIOUCScalarIScalarO, 0, 1 221 }, 222 { // kPMAllowPowerChange, 3 223 0, (IOMethod)&IOPMrootDomain::allowPowerChange, kIOUCScalarIScalarO, 1, 0 224 }, 225 { // kPMCancelPowerChange, 4 226 0, (IOMethod)&IOPMrootDomain::cancelPowerChange, kIOUCScalarIScalarO, 1, 0 227 }, 228 { // kPMShutdownSystem, 5 229 0, (IOMethod)&IOPMrootDomain::shutdownSystem, kIOUCScalarIScalarO, 0, 0 230 }, 231 { // kPMRestartSystem, 6 232 0, (IOMethod)&IOPMrootDomain::restartSystem, kIOUCScalarIScalarO, 0, 0 233 }, 234 { // kPMSleepSystemOptions, 7 235 (IOService *)1, (IOMethod)&RootDomainUserClient::secureSleepSystemOptions, 236 kIOUCStructIStructO, kIOUCVariableStructureSize, sizeof(uint32_t) 237 }, 238 { // kPMSetMaintenanceWakeCalendar, 8 239 (IOService *)1, (IOMethod)&RootDomainUserClient::secureSetMaintenanceWakeCalendar, 240 kIOUCStructIStructO, sizeof(IOPMCalendarStruct), sizeof(uint32_t) 241 } 242 }; 243 244 if(index >= kNumPMMethods) 245 return NULL; 246 else { 247 if (sMethods[index].object) 248 *targetP = this; 249 else 250 *targetP = fOwner; 251 252 return (IOExternalMethod *)&sMethods[index]; 253 } 254 } 255 256 #if 0 257 IOReturn RootDomainUserClient::externalMethod( uint32_t selector, IOExternalMethodArguments * args, 258 IOExternalMethodDispatch * dispatch, OSObject * target, void * reference ) 259 { 260 static const IOExternalMethodDispatch sMethods[] = { 261 { // kPMSetAggressiveness, 0 262 (IOService *)1, (IOMethod)&RootDomainUserClient::secureSetAggressiveness, kIOUCScalarIScalarO, 2, 1 263 }, 264 { // kPMGetAggressiveness, 1 265 0, (IOMethod)&IOPMrootDomain::getAggressiveness, kIOUCScalarIScalarO, 1, 1 266 }, 267 { // kPMSleepSystem, 2 268 (IOService *)1, (IOMethod)&RootDomainUserClient::secureSleepSystem, kIOUCScalarIScalarO, 0, 1 269 }, 270 { // kPMAllowPowerChange, 3 271 0, (IOMethod)&IOPMrootDomain::allowPowerChange, kIOUCScalarIScalarO, 1, 0 272 }, 273 { // kPMCancelPowerChange, 4 274 0, (IOMethod)&IOPMrootDomain::cancelPowerChange, kIOUCScalarIScalarO, 1, 0 275 }, 276 { // kPMShutdownSystem, 5 277 0, (IOMethod)&IOPMrootDomain::shutdownSystem, kIOUCScalarIScalarO, 0, 0 278 }, 279 { // kPMRestartSystem, 6 280 0, (IOMethod)&IOPMrootDomain::restartSystem, kIOUCScalarIScalarO, 0, 0 281 }, 282 { // kPMSetPreventative, 7 283 (IOService *)1, (IOMethod)&RootDomainUserClient::setPreventative, kIOUCScalarIScalarO, 2, 0 284 }, 285 }; 286 287 if (selector > (sizeof(sMethods) / sizeof(sMethods[0]))) 288 return (kIOReturnBadArgument); 289 290 if ((1 << selector) & ((1 << 0) | (1 << 7)) 291 target = this; 292 else 293 target = fOwner; 294 295 return (super::externalMethod(selector, args, &sMethods[selector], target, 0)); 296 } 297 #endif 298 299 void 300 RootDomainUserClient::setPreventative(UInt32 on_off, UInt32 types_of_sleep) 301 { 302 return; 303 } 304 305