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