1 | /* |
2 | * Copyright (c) 1998-2012 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 | #include <sys/proc.h> |
41 | |
42 | #define super IOUserClient |
43 | |
44 | /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ |
45 | |
46 | OSDefineMetaClassAndStructors(RootDomainUserClient, IOUserClient) |
47 | |
48 | /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ |
49 | |
50 | bool RootDomainUserClient::initWithTask(task_t owningTask, void *security_id, |
51 | UInt32 type, OSDictionary * properties) |
52 | { |
53 | if (properties) |
54 | properties->setObject(kIOUserClientCrossEndianCompatibleKey, kOSBooleanTrue); |
55 | |
56 | if (!super::initWithTask(owningTask, security_id, type, properties)) |
57 | return false; |
58 | |
59 | fOwningTask = owningTask; |
60 | task_reference (fOwningTask); |
61 | return true; |
62 | } |
63 | |
64 | |
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 | |
76 | IOReturn RootDomainUserClient::secureSleepSystem( uint32_t *return_code ) |
77 | { |
78 | return secureSleepSystemOptions(NULL, 0, return_code); |
79 | } |
80 | |
81 | IOReturn RootDomainUserClient::secureSleepSystemOptions( |
82 | const void *inOptions, |
83 | IOByteCount inOptionsSize, |
84 | uint32_t *returnCode) |
85 | { |
86 | |
87 | int local_priv = 0; |
88 | int admin_priv = 0; |
89 | IOReturn ret = kIOReturnNotPrivileged; |
90 | OSDictionary *unserializedOptions = NULL; |
91 | OSString *unserializeErrorString = NULL; |
92 | |
93 | ret = clientHasPrivilege(fOwningTask, kIOClientPrivilegeLocalUser); |
94 | local_priv = (kIOReturnSuccess == ret); |
95 | |
96 | ret = clientHasPrivilege(fOwningTask, kIOClientPrivilegeAdministrator); |
97 | admin_priv = (kIOReturnSuccess == ret); |
98 | |
99 | |
100 | if (inOptions) |
101 | { |
102 | unserializedOptions = OSDynamicCast( OSDictionary, |
103 | OSUnserializeXML((const char *)inOptions, inOptionsSize, &unserializeErrorString)); |
104 | |
105 | if (!unserializedOptions) { |
106 | IOLog("IOPMRootDomain SleepSystem unserialization failure: %s\n" , |
107 | unserializeErrorString ? unserializeErrorString->getCStringNoCopy() : "Unknown" ); |
108 | } |
109 | } |
110 | |
111 | if ( (local_priv || admin_priv) && fOwner ) |
112 | { |
113 | proc_t p; |
114 | p = (proc_t)get_bsdtask_info(fOwningTask); |
115 | if (p) { |
116 | fOwner->setProperty("SleepRequestedByPID" , proc_pid(p), 32); |
117 | } |
118 | |
119 | if (unserializedOptions) |
120 | { |
121 | // Publish Sleep Options in registry under root_domain |
122 | fOwner->setProperty( kRootDomainSleepOptionsKey, unserializedOptions); |
123 | |
124 | *returnCode = fOwner->sleepSystemOptions( unserializedOptions ); |
125 | |
126 | unserializedOptions->release(); |
127 | } else { |
128 | // No options |
129 | // Clear any pre-existing options |
130 | fOwner->removeProperty( kRootDomainSleepOptionsKey ); |
131 | |
132 | *returnCode = fOwner->sleepSystemOptions( NULL ); |
133 | } |
134 | |
135 | } else { |
136 | *returnCode = kIOReturnNotPrivileged; |
137 | } |
138 | |
139 | return kIOReturnSuccess; |
140 | } |
141 | |
142 | IOReturn RootDomainUserClient::secureSetAggressiveness( |
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); |
153 | |
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); |
159 | } else { |
160 | *return_code = kIOReturnNotPrivileged; |
161 | } |
162 | return kIOReturnSuccess; |
163 | } |
164 | |
165 | IOReturn RootDomainUserClient::secureSetMaintenanceWakeCalendar( |
166 | IOPMCalendarStruct *inCalendar, |
167 | uint32_t *returnCode) |
168 | { |
169 | int admin_priv = 0; |
170 | IOReturn ret = kIOReturnNotPrivileged; |
171 | |
172 | ret = clientHasPrivilege(fOwningTask, kIOClientPrivilegeAdministrator); |
173 | admin_priv = (kIOReturnSuccess == ret); |
174 | |
175 | if (admin_priv && fOwner) { |
176 | *returnCode = fOwner->setMaintenanceWakeCalendar(inCalendar); |
177 | } else { |
178 | *returnCode = kIOReturnNotPrivileged; |
179 | } |
180 | return kIOReturnSuccess; |
181 | } |
182 | |
183 | IOReturn RootDomainUserClient::secureSetUserAssertionLevels( |
184 | uint32_t assertionBitfield) |
185 | { |
186 | int admin_priv = 0; |
187 | IOReturn ret = kIOReturnNotPrivileged; |
188 | |
189 | ret = clientHasPrivilege(fOwningTask, kIOClientPrivilegeAdministrator); |
190 | admin_priv = (kIOReturnSuccess == ret); |
191 | |
192 | if (admin_priv && fOwner) { |
193 | ret = fOwner->setPMAssertionUserLevels(assertionBitfield); |
194 | } else { |
195 | ret = kIOReturnNotPrivileged; |
196 | } |
197 | return kIOReturnSuccess; |
198 | } |
199 | |
200 | IOReturn RootDomainUserClient::secureGetSystemSleepType( |
201 | uint32_t *outSleepType, uint32_t *sleepTimer) |
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, sleepTimer); |
211 | } else { |
212 | ret = kIOReturnNotPrivileged; |
213 | } |
214 | return ret; |
215 | } |
216 | |
217 | IOReturn RootDomainUserClient::clientClose( void ) |
218 | { |
219 | terminate(); |
220 | |
221 | return kIOReturnSuccess; |
222 | } |
223 | |
224 | void RootDomainUserClient::stop( IOService *provider) |
225 | { |
226 | if(fOwningTask) { |
227 | task_deallocate(fOwningTask); |
228 | fOwningTask = 0; |
229 | } |
230 | |
231 | super::stop(provider); |
232 | } |
233 | |
234 | IOReturn RootDomainUserClient::externalMethod( |
235 | uint32_t selector, |
236 | IOExternalMethodArguments * arguments, |
237 | IOExternalMethodDispatch * dispatch __unused, |
238 | OSObject * target __unused, |
239 | void * reference __unused ) |
240 | { |
241 | IOReturn ret = kIOReturnBadArgument; |
242 | |
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; |
255 | |
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; |
265 | |
266 | case kPMSleepSystem: |
267 | if (1 == arguments->scalarOutputCount) |
268 | { |
269 | ret = this->secureSleepSystem( |
270 | (uint32_t *)&arguments->scalarOutput[0]); |
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: |
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 | } |
314 | break; |
315 | |
316 | case kPMSetUserAssertionLevels: |
317 | ret = this->secureSetUserAssertionLevels( |
318 | (uint32_t)arguments->scalarInput[0]); |
319 | break; |
320 | |
321 | case kPMActivityTickle: |
322 | if ( fOwner->checkSystemCanSustainFullWake() ) |
323 | { |
324 | fOwner->reportUserInput( ); |
325 | fOwner->setProperty(kIOPMRootDomainWakeTypeKey, "UserActivity Assertion" ); |
326 | } |
327 | ret = kIOReturnSuccess; |
328 | break; |
329 | |
330 | case kPMSetClamshellSleepState: |
331 | fOwner->setDisableClamShellSleep(arguments->scalarInput[0] ? true : false); |
332 | ret = kIOReturnSuccess; |
333 | break; |
334 | |
335 | case kPMGetSystemSleepType: |
336 | if (2 == arguments->scalarOutputCount) |
337 | { |
338 | ret = this->secureGetSystemSleepType( |
339 | (uint32_t *) &arguments->scalarOutput[0], |
340 | (uint32_t *) &arguments->scalarOutput[1]); |
341 | } |
342 | break; |
343 | |
344 | #if defined(__i386__) || defined(__x86_64__) |
345 | case kPMSleepWakeWatchdogEnable: |
346 | ret = clientHasPrivilege(fOwningTask, kIOClientPrivilegeAdministrator); |
347 | if (ret == kIOReturnSuccess) |
348 | fOwner->sleepWakeDebugEnableWdog(); |
349 | break; |
350 | |
351 | |
352 | case kPMSleepWakeDebugTrig: |
353 | ret = clientHasPrivilege(fOwningTask, kIOClientPrivilegeAdministrator); |
354 | if (ret == kIOReturnSuccess) |
355 | fOwner->sleepWakeDebugTrig(false); |
356 | break; |
357 | #endif |
358 | |
359 | case kPMSetDisplayPowerOn: |
360 | if (1 == arguments->scalarInputCount) |
361 | { |
362 | ret = clientHasPrivilege(fOwningTask, kIOClientPrivilegeAdministrator); |
363 | if (ret == kIOReturnSuccess) |
364 | fOwner->setDisplayPowerOn((uint32_t)arguments->scalarInput[0]); |
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 | |