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