]> git.saurik.com Git - apple/xnu.git/blob - iokit/Kernel/RootDomainUserClient.cpp
75a26e7cc544f7af607e8142bc74bc5118e1f0e7
[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::clientClose( void )
195 {
196 detach(fOwner);
197
198 if(fOwningTask) {
199 task_deallocate(fOwningTask);
200 fOwningTask = 0;
201 }
202
203 return kIOReturnSuccess;
204 }
205
206 IOReturn RootDomainUserClient::clientMemoryForType(
207 UInt32 type,
208 IOOptionBits *options,
209 IOMemoryDescriptor ** memory)
210 {
211 if (!fOwner)
212 return kIOReturnNotReady;
213
214 if (kPMRootDomainMapTraceBuffer == type)
215 {
216 *memory = fOwner->getPMTraceMemoryDescriptor();
217 if (*memory) {
218 (*memory)->retain();
219 *options = 0;
220 return kIOReturnSuccess;
221 } else {
222 return kIOReturnNotFound;
223 }
224
225 }
226 return kIOReturnUnsupported;
227 }
228
229 IOReturn RootDomainUserClient::externalMethod(
230 uint32_t selector,
231 IOExternalMethodArguments * arguments,
232 IOExternalMethodDispatch * dispatch __unused,
233 OSObject * target __unused,
234 void * reference __unused )
235 {
236 IOReturn ret = kIOReturnBadArgument;
237
238 switch (selector)
239 {
240 case kPMSetAggressiveness:
241 if ((2 == arguments->scalarInputCount)
242 && (1 == arguments->scalarOutputCount))
243 {
244 ret = this->secureSetAggressiveness(
245 (unsigned long)arguments->scalarInput[0],
246 (unsigned long)arguments->scalarInput[1],
247 (int *)&arguments->scalarOutput[0]);
248 }
249 break;
250
251 case kPMGetAggressiveness:
252 if ((1 == arguments->scalarInputCount)
253 && (1 == arguments->scalarOutputCount))
254 {
255 ret = fOwner->getAggressiveness(
256 (unsigned long)arguments->scalarInput[0],
257 (unsigned long *)&arguments->scalarOutput[0]);
258 }
259 break;
260
261 case kPMSleepSystem:
262 if (1 == arguments->scalarOutputCount)
263 {
264 ret = this->secureSleepSystem(
265 (uint32_t *)&arguments->scalarOutput[0]);
266 }
267 break;
268
269 case kPMAllowPowerChange:
270 if (1 == arguments->scalarInputCount)
271 {
272 ret = fOwner->allowPowerChange(
273 arguments->scalarInput[0]);
274 }
275 break;
276
277 case kPMCancelPowerChange:
278 if (1 == arguments->scalarInputCount)
279 {
280 ret = fOwner->cancelPowerChange(
281 arguments->scalarInput[0]);
282 }
283 break;
284
285 case kPMShutdownSystem:
286 // deperecated interface
287 ret = kIOReturnUnsupported;
288 break;
289
290 case kPMRestartSystem:
291 // deperecated interface
292 ret = kIOReturnUnsupported;
293 break;
294
295 case kPMSleepSystemOptions:
296 ret = this->secureSleepSystemOptions(
297 arguments->structureInput,
298 arguments->structureInputSize,
299 (uint32_t *)&arguments->scalarOutput[0]);
300 break;
301 case kPMSetMaintenanceWakeCalendar:
302 ret = this->secureSetMaintenanceWakeCalendar(
303 (IOPMCalendarStruct *)arguments->structureInput,
304 (uint32_t *)&arguments->structureOutput);
305 arguments->structureOutputSize = sizeof(uint32_t);
306 break;
307
308 case kPMSetUserAssertionLevels:
309 ret = this->secureSetUserAssertionLevels(
310 (uint32_t)arguments->scalarInput[0]);
311 break;
312
313 case kPMActivityTickle:
314 fOwner->reportUserInput( );
315 fOwner->setProperty(kIOPMRootDomainWakeTypeKey, "UserActivity Assertion");
316 ret = kIOReturnSuccess;
317 break;
318
319 /*
320 case kPMMethodCopySystemTimeline:
321 // intentional fallthrough
322 case kPMMethodCopyDetailedTimeline:
323
324 if (!arguments->structureOutputDescriptor)
325 {
326 // TODO: Force IOKit.framework to always send this data out
327 // of line; so I don't have to create a MemoryDescriptor here.
328 mem_size = arguments->structureOutputSize;
329 mem = IOMemoryDescriptor::withAddressRange(
330 (mach_vm_address_t)arguments->structureOutput,
331 (mach_vm_size_t)mem_size,
332 kIODirectionIn, current_task());
333 } else {
334 mem_size = arguments->structureOutputDescriptorSize;
335 if (( mem = arguments->structureOutputDescriptor ))
336 mem->retain();
337 }
338
339 if (mem)
340 {
341 mem->prepare(kIODirectionNone);
342
343 if (kPMMethodCopySystemTimeline == selector) {
344 arguments->scalarOutput[0] = fOwner->copySystemTimeline(
345 mem, &mem_size);
346 }
347 else
348 if (kPMMethodCopyDetailedTimeline == selector) {
349 arguments->scalarOutput[0] = fOwner->copyDetailedTimeline(
350 mem, &mem_size);
351 }
352
353 if (arguments->structureOutputDescriptor) {
354 arguments->structureOutputDescriptorSize = mem_size;
355 } else {
356 arguments->structureOutputSize = mem_size;
357 }
358
359 mem->release();
360
361 ret = kIOReturnSuccess;
362 } else {
363 ret = kIOReturnCannotWire;
364 }
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