]>
Commit | Line | Data |
---|---|---|
55e303ae | 1 | /* |
39236c6e | 2 | * Copyright (c) 1998-2012 Apple Computer, Inc. All rights reserved. |
55e303ae | 3 | * |
2d21ac55 | 4 | * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ |
55e303ae | 5 | * |
2d21ac55 A |
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. | |
8f6c56a5 | 14 | * |
2d21ac55 A |
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 | |
8f6c56a5 A |
20 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, |
21 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, | |
2d21ac55 A |
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. | |
8f6c56a5 | 25 | * |
2d21ac55 | 26 | * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ |
55e303ae A |
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> | |
0c530ab8 | 35 | #include <IOKit/IOKitKeys.h> |
55e303ae A |
36 | #include <IOKit/IOBufferMemoryDescriptor.h> |
37 | #include "RootDomainUserClient.h" | |
38 | #include <IOKit/pwr_mgt/IOPMLibDefs.h> | |
316670eb | 39 | #include <IOKit/pwr_mgt/IOPMPrivate.h> |
39236c6e | 40 | #include <sys/proc.h> |
55e303ae A |
41 | |
42 | #define super IOUserClient | |
43 | ||
44 | /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ | |
45 | ||
46 | OSDefineMetaClassAndStructors(RootDomainUserClient, IOUserClient) | |
47 | ||
48 | /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ | |
49 | ||
fe8ab488 A |
50 | bool RootDomainUserClient::initWithTask(task_t owningTask, void *security_id, |
51 | UInt32 type, OSDictionary * properties) | |
91447636 | 52 | { |
0c530ab8 | 53 | if (properties) |
fe8ab488 | 54 | properties->setObject(kIOUserClientCrossEndianCompatibleKey, kOSBooleanTrue); |
0c530ab8 A |
55 | |
56 | if (!super::initWithTask(owningTask, security_id, type, properties)) | |
fe8ab488 | 57 | return false; |
91447636 A |
58 | |
59 | fOwningTask = owningTask; | |
fe8ab488 | 60 | task_reference (fOwningTask); |
91447636 A |
61 | return true; |
62 | } | |
63 | ||
64 | ||
55e303ae A |
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 | ||
2d21ac55 | 76 | IOReturn RootDomainUserClient::secureSleepSystem( uint32_t *return_code ) |
91447636 | 77 | { |
6d2010ae | 78 | return secureSleepSystemOptions(NULL, 0, return_code); |
2d21ac55 A |
79 | } |
80 | ||
fe8ab488 A |
81 | IOReturn RootDomainUserClient::secureSleepSystemOptions( |
82 | const void *inOptions, | |
39236c6e | 83 | IOByteCount inOptionsSize, |
6d2010ae | 84 | uint32_t *returnCode) |
2d21ac55 | 85 | { |
2d21ac55 | 86 | |
91447636 A |
87 | int local_priv = 0; |
88 | int admin_priv = 0; | |
89 | IOReturn ret = kIOReturnNotPrivileged; | |
2d21ac55 A |
90 | OSDictionary *unserializedOptions = NULL; |
91 | OSString *unserializeErrorString = NULL; | |
91447636 A |
92 | |
93 | ret = clientHasPrivilege(fOwningTask, kIOClientPrivilegeLocalUser); | |
94 | local_priv = (kIOReturnSuccess == ret); | |
fe8ab488 | 95 | |
91447636 A |
96 | ret = clientHasPrivilege(fOwningTask, kIOClientPrivilegeAdministrator); |
97 | admin_priv = (kIOReturnSuccess == ret); | |
fe8ab488 A |
98 | |
99 | ||
2d21ac55 A |
100 | if (inOptions) |
101 | { | |
102 | unserializedOptions = OSDynamicCast( OSDictionary, | |
39236c6e | 103 | OSUnserializeXML((const char *)inOptions, inOptionsSize, &unserializeErrorString)); |
fe8ab488 | 104 | |
2d21ac55 | 105 | if (!unserializedOptions) { |
fe8ab488 | 106 | IOLog("IOPMRootDomain SleepSystem unserialization failure: %s\n", |
2d21ac55 A |
107 | unserializeErrorString ? unserializeErrorString->getCStringNoCopy() : "Unknown"); |
108 | } | |
109 | } | |
110 | ||
39236c6e | 111 | if ( (local_priv || admin_priv) && fOwner ) |
2d21ac55 | 112 | { |
39236c6e A |
113 | proc_t p; |
114 | p = (proc_t)get_bsdtask_info(fOwningTask); | |
115 | if (p) { | |
116 | fOwner->setProperty("SleepRequestedByPID", proc_pid(p), 32); | |
117 | } | |
fe8ab488 A |
118 | |
119 | if (unserializedOptions) | |
2d21ac55 A |
120 | { |
121 | // Publish Sleep Options in registry under root_domain | |
fe8ab488 | 122 | fOwner->setProperty( kRootDomainSleepOptionsKey, unserializedOptions); |
2d21ac55 A |
123 | |
124 | *returnCode = fOwner->sleepSystemOptions( unserializedOptions ); | |
125 | ||
fe8ab488 | 126 | unserializedOptions->release(); |
2d21ac55 A |
127 | } else { |
128 | // No options | |
129 | // Clear any pre-existing options | |
130 | fOwner->removeProperty( kRootDomainSleepOptionsKey ); | |
131 | ||
fe8ab488 | 132 | *returnCode = fOwner->sleepSystemOptions( NULL ); |
2d21ac55 | 133 | } |
91447636 | 134 | |
91447636 | 135 | } else { |
2d21ac55 | 136 | *returnCode = kIOReturnNotPrivileged; |
91447636 A |
137 | } |
138 | ||
2d21ac55 | 139 | return kIOReturnSuccess; |
91447636 A |
140 | } |
141 | ||
fe8ab488 | 142 | IOReturn RootDomainUserClient::secureSetAggressiveness( |
91447636 A |
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); | |
fe8ab488 | 153 | |
91447636 A |
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); | |
91447636 A |
159 | } else { |
160 | *return_code = kIOReturnNotPrivileged; | |
91447636 | 161 | } |
6d2010ae | 162 | return kIOReturnSuccess; |
91447636 A |
163 | } |
164 | ||
6d2010ae A |
165 | IOReturn RootDomainUserClient::secureSetMaintenanceWakeCalendar( |
166 | IOPMCalendarStruct *inCalendar, | |
167 | uint32_t *returnCode) | |
b0d623f7 | 168 | { |
b0d623f7 A |
169 | int admin_priv = 0; |
170 | IOReturn ret = kIOReturnNotPrivileged; | |
fe8ab488 | 171 | |
b0d623f7 A |
172 | ret = clientHasPrivilege(fOwningTask, kIOClientPrivilegeAdministrator); |
173 | admin_priv = (kIOReturnSuccess == ret); | |
174 | ||
b0d623f7 A |
175 | if (admin_priv && fOwner) { |
176 | *returnCode = fOwner->setMaintenanceWakeCalendar(inCalendar); | |
b0d623f7 A |
177 | } else { |
178 | *returnCode = kIOReturnNotPrivileged; | |
b0d623f7 | 179 | } |
6d2010ae | 180 | return kIOReturnSuccess; |
b0d623f7 | 181 | } |
55e303ae | 182 | |
0b4c1975 | 183 | IOReturn RootDomainUserClient::secureSetUserAssertionLevels( |
6d2010ae | 184 | uint32_t assertionBitfield) |
0b4c1975 A |
185 | { |
186 | int admin_priv = 0; | |
187 | IOReturn ret = kIOReturnNotPrivileged; | |
fe8ab488 | 188 | |
0b4c1975 A |
189 | ret = clientHasPrivilege(fOwningTask, kIOClientPrivilegeAdministrator); |
190 | admin_priv = (kIOReturnSuccess == ret); | |
191 | ||
192 | if (admin_priv && fOwner) { | |
6d2010ae | 193 | ret = fOwner->setPMAssertionUserLevels(assertionBitfield); |
0b4c1975 A |
194 | } else { |
195 | ret = kIOReturnNotPrivileged; | |
196 | } | |
197 | return kIOReturnSuccess; | |
198 | } | |
199 | ||
db609669 A |
200 | IOReturn RootDomainUserClient::secureGetSystemSleepType( |
201 | uint32_t *outSleepType) | |
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); | |
211 | } else { | |
212 | ret = kIOReturnNotPrivileged; | |
213 | } | |
214 | return ret; | |
215 | } | |
216 | ||
55e303ae A |
217 | IOReturn RootDomainUserClient::clientClose( void ) |
218 | { | |
d190cdc3 | 219 | terminate(); |
fe8ab488 | 220 | |
d190cdc3 A |
221 | return kIOReturnSuccess; |
222 | } | |
223 | ||
224 | void RootDomainUserClient::stop( IOService *provider) | |
225 | { | |
91447636 A |
226 | if(fOwningTask) { |
227 | task_deallocate(fOwningTask); | |
228 | fOwningTask = 0; | |
55e303ae | 229 | } |
fe8ab488 | 230 | |
d190cdc3 | 231 | super::stop(provider); |
55e303ae A |
232 | } |
233 | ||
6d2010ae | 234 | IOReturn RootDomainUserClient::externalMethod( |
fe8ab488 | 235 | uint32_t selector, |
6d2010ae | 236 | IOExternalMethodArguments * arguments, |
fe8ab488 | 237 | IOExternalMethodDispatch * dispatch __unused, |
6d2010ae A |
238 | OSObject * target __unused, |
239 | void * reference __unused ) | |
2d21ac55 | 240 | { |
fe8ab488 A |
241 | IOReturn ret = kIOReturnBadArgument; |
242 | ||
6d2010ae A |
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; | |
fe8ab488 | 255 | |
6d2010ae A |
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; | |
fe8ab488 | 265 | |
6d2010ae A |
266 | case kPMSleepSystem: |
267 | if (1 == arguments->scalarOutputCount) | |
268 | { | |
269 | ret = this->secureSleepSystem( | |
fe8ab488 | 270 | (uint32_t *)&arguments->scalarOutput[0]); |
6d2010ae A |
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: | |
39037602 A |
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 | } | |
6d2010ae | 314 | break; |
fe8ab488 | 315 | |
6d2010ae A |
316 | case kPMSetUserAssertionLevels: |
317 | ret = this->secureSetUserAssertionLevels( | |
318 | (uint32_t)arguments->scalarInput[0]); | |
319 | break; | |
fe8ab488 | 320 | |
7ddcb079 | 321 | case kPMActivityTickle: |
db609669 A |
322 | if ( fOwner->checkSystemCanSustainFullWake() ) |
323 | { | |
324 | fOwner->reportUserInput( ); | |
325 | fOwner->setProperty(kIOPMRootDomainWakeTypeKey, "UserActivity Assertion"); | |
326 | } | |
7ddcb079 A |
327 | ret = kIOReturnSuccess; |
328 | break; | |
db609669 A |
329 | |
330 | case kPMSetClamshellSleepState: | |
331 | fOwner->setDisableClamShellSleep(arguments->scalarInput[0] ? true : false); | |
332 | ret = kIOReturnSuccess; | |
333 | break; | |
334 | ||
335 | case kPMGetSystemSleepType: | |
336 | if (1 == arguments->scalarOutputCount) | |
337 | { | |
338 | ret = this->secureGetSystemSleepType( | |
339 | (uint32_t *) &arguments->scalarOutput[0]); | |
340 | } | |
341 | break; | |
39236c6e | 342 | |
fe8ab488 | 343 | #if defined(__i386__) || defined(__x86_64__) |
39236c6e A |
344 | case kPMSleepWakeWatchdogEnable: |
345 | ret = clientHasPrivilege(fOwningTask, kIOClientPrivilegeAdministrator); | |
346 | if (ret == kIOReturnSuccess) | |
347 | fOwner->sleepWakeDebugEnableWdog(); | |
348 | break; | |
349 | ||
350 | ||
351 | case kPMSleepWakeDebugTrig: | |
352 | ret = clientHasPrivilege(fOwningTask, kIOClientPrivilegeAdministrator); | |
353 | if (ret == kIOReturnSuccess) | |
354 | fOwner->sleepWakeDebugTrig(false); | |
355 | break; | |
fe8ab488 | 356 | #endif |
39236c6e A |
357 | |
358 | case kPMSetDisplayPowerOn: | |
359 | if (1 == arguments->scalarInputCount) | |
360 | { | |
361 | ret = clientHasPrivilege(fOwningTask, kIOClientPrivilegeAdministrator); | |
362 | if (ret == kIOReturnSuccess) | |
363 | fOwner->setDisplayPowerOn((uint32_t)arguments->scalarInput[0]); | |
364 | } | |
365 | break; | |
6d2010ae | 366 | |
6d2010ae A |
367 | default: |
368 | // bad selector | |
369 | return kIOReturnBadArgument; | |
370 | } | |
371 | ||
372 | return ret; | |
2d21ac55 | 373 | } |
2d21ac55 | 374 | |
6d2010ae A |
375 | /* getTargetAndMethodForIndex |
376 | * Not used. We prefer to use externalMethod() for user client invocations. | |
377 | * We maintain getTargetAndExternalMethod since it's an exported symbol, | |
378 | * and only for that reason. | |
379 | */ | |
fe8ab488 | 380 | IOExternalMethod * RootDomainUserClient::getTargetAndMethodForIndex( |
6d2010ae | 381 | IOService ** targetP, UInt32 index ) |
55e303ae | 382 | { |
6d2010ae A |
383 | // DO NOT EDIT |
384 | return super::getTargetAndMethodForIndex(targetP, index); | |
55e303ae A |
385 | } |
386 | ||
6d2010ae A |
387 | /* setPreventative |
388 | * Does nothing. Exists only for exported symbol compatibility. | |
389 | */ | |
fe8ab488 | 390 | void |
6d2010ae A |
391 | RootDomainUserClient::setPreventative(UInt32 on_off, UInt32 types_of_sleep) |
392 | { return; } // DO NOT EDIT |