]>
Commit | Line | Data |
---|---|---|
55e303ae A |
1 | /* |
2 | * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. | |
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> | |
39 | ||
40 | #define super IOUserClient | |
41 | ||
42 | /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ | |
43 | ||
44 | OSDefineMetaClassAndStructors(RootDomainUserClient, IOUserClient) | |
45 | ||
46 | /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ | |
47 | ||
0c530ab8 A |
48 | bool RootDomainUserClient::initWithTask(task_t owningTask, void *security_id, |
49 | UInt32 type, OSDictionary * properties) | |
91447636 | 50 | { |
0c530ab8 A |
51 | if (properties) |
52 | properties->setObject(kIOUserClientCrossEndianCompatibleKey, kOSBooleanTrue); | |
53 | ||
54 | if (!super::initWithTask(owningTask, security_id, type, properties)) | |
91447636 A |
55 | return false; |
56 | ||
57 | fOwningTask = owningTask; | |
58 | task_reference (fOwningTask); | |
59 | return true; | |
60 | } | |
61 | ||
62 | ||
55e303ae A |
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 | ||
2d21ac55 | 74 | IOReturn RootDomainUserClient::secureSleepSystem( uint32_t *return_code ) |
91447636 | 75 | { |
6d2010ae | 76 | return secureSleepSystemOptions(NULL, 0, return_code); |
2d21ac55 A |
77 | } |
78 | ||
79 | IOReturn RootDomainUserClient::secureSleepSystemOptions( | |
6d2010ae A |
80 | const void *inOptions, |
81 | IOByteCount inOptionsSize __unused, | |
82 | uint32_t *returnCode) | |
2d21ac55 | 83 | { |
2d21ac55 | 84 | |
91447636 A |
85 | int local_priv = 0; |
86 | int admin_priv = 0; | |
87 | IOReturn ret = kIOReturnNotPrivileged; | |
2d21ac55 A |
88 | OSDictionary *unserializedOptions = NULL; |
89 | OSString *unserializeErrorString = NULL; | |
91447636 A |
90 | |
91 | ret = clientHasPrivilege(fOwningTask, kIOClientPrivilegeLocalUser); | |
92 | local_priv = (kIOReturnSuccess == ret); | |
93 | ||
94 | ret = clientHasPrivilege(fOwningTask, kIOClientPrivilegeAdministrator); | |
95 | admin_priv = (kIOReturnSuccess == ret); | |
2d21ac55 | 96 | |
2d21ac55 A |
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 | } | |
91447636 | 127 | |
91447636 | 128 | } else { |
2d21ac55 | 129 | *returnCode = kIOReturnNotPrivileged; |
91447636 A |
130 | } |
131 | ||
2d21ac55 | 132 | return kIOReturnSuccess; |
91447636 A |
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); | |
91447636 A |
152 | } else { |
153 | *return_code = kIOReturnNotPrivileged; | |
91447636 | 154 | } |
6d2010ae | 155 | return kIOReturnSuccess; |
91447636 A |
156 | } |
157 | ||
6d2010ae A |
158 | IOReturn RootDomainUserClient::secureSetMaintenanceWakeCalendar( |
159 | IOPMCalendarStruct *inCalendar, | |
160 | uint32_t *returnCode) | |
b0d623f7 | 161 | { |
b0d623f7 A |
162 | int admin_priv = 0; |
163 | IOReturn ret = kIOReturnNotPrivileged; | |
164 | ||
165 | ret = clientHasPrivilege(fOwningTask, kIOClientPrivilegeAdministrator); | |
166 | admin_priv = (kIOReturnSuccess == ret); | |
167 | ||
b0d623f7 A |
168 | if (admin_priv && fOwner) { |
169 | *returnCode = fOwner->setMaintenanceWakeCalendar(inCalendar); | |
b0d623f7 A |
170 | } else { |
171 | *returnCode = kIOReturnNotPrivileged; | |
b0d623f7 | 172 | } |
6d2010ae | 173 | return kIOReturnSuccess; |
b0d623f7 | 174 | } |
55e303ae | 175 | |
0b4c1975 | 176 | IOReturn RootDomainUserClient::secureSetUserAssertionLevels( |
6d2010ae | 177 | uint32_t assertionBitfield) |
0b4c1975 A |
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) { | |
6d2010ae | 186 | ret = fOwner->setPMAssertionUserLevels(assertionBitfield); |
0b4c1975 A |
187 | } else { |
188 | ret = kIOReturnNotPrivileged; | |
189 | } | |
190 | return kIOReturnSuccess; | |
191 | } | |
192 | ||
55e303ae A |
193 | IOReturn RootDomainUserClient::clientClose( void ) |
194 | { | |
195 | detach(fOwner); | |
91447636 A |
196 | |
197 | if(fOwningTask) { | |
198 | task_deallocate(fOwningTask); | |
199 | fOwningTask = 0; | |
200 | } | |
201 | ||
55e303ae A |
202 | return kIOReturnSuccess; |
203 | } | |
204 | ||
6d2010ae A |
205 | IOReturn RootDomainUserClient::clientMemoryForType( |
206 | UInt32 type, | |
207 | IOOptionBits *options, | |
208 | IOMemoryDescriptor ** memory) | |
55e303ae | 209 | { |
6d2010ae A |
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; | |
2d21ac55 | 222 | } |
6d2010ae | 223 | |
55e303ae | 224 | } |
6d2010ae | 225 | return kIOReturnUnsupported; |
55e303ae A |
226 | } |
227 | ||
6d2010ae A |
228 | IOReturn RootDomainUserClient::externalMethod( |
229 | uint32_t selector, | |
230 | IOExternalMethodArguments * arguments, | |
231 | IOExternalMethodDispatch * dispatch __unused, | |
232 | OSObject * target __unused, | |
233 | void * reference __unused ) | |
2d21ac55 | 234 | { |
6d2010ae A |
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 | ||
7ddcb079 A |
312 | case kPMActivityTickle: |
313 | fOwner->reportUserInput( ); | |
314 | ret = kIOReturnSuccess; | |
315 | break; | |
316 | ||
6d2010ae A |
317 | /* |
318 | case kPMMethodCopySystemTimeline: | |
319 | // intentional fallthrough | |
320 | case kPMMethodCopyDetailedTimeline: | |
321 | ||
322 | if (!arguments->structureOutputDescriptor) | |
323 | { | |
324 | // TODO: Force IOKit.framework to always send this data out | |
325 | // of line; so I don't have to create a MemoryDescriptor here. | |
326 | mem_size = arguments->structureOutputSize; | |
327 | mem = IOMemoryDescriptor::withAddressRange( | |
328 | (mach_vm_address_t)arguments->structureOutput, | |
329 | (mach_vm_size_t)mem_size, | |
330 | kIODirectionIn, current_task()); | |
331 | } else { | |
332 | mem_size = arguments->structureOutputDescriptorSize; | |
333 | if (( mem = arguments->structureOutputDescriptor )) | |
334 | mem->retain(); | |
335 | } | |
336 | ||
337 | if (mem) | |
338 | { | |
339 | mem->prepare(kIODirectionNone); | |
340 | ||
341 | if (kPMMethodCopySystemTimeline == selector) { | |
342 | arguments->scalarOutput[0] = fOwner->copySystemTimeline( | |
343 | mem, &mem_size); | |
344 | } | |
345 | else | |
346 | if (kPMMethodCopyDetailedTimeline == selector) { | |
347 | arguments->scalarOutput[0] = fOwner->copyDetailedTimeline( | |
348 | mem, &mem_size); | |
349 | } | |
350 | ||
351 | if (arguments->structureOutputDescriptor) { | |
352 | arguments->structureOutputDescriptorSize = mem_size; | |
353 | } else { | |
354 | arguments->structureOutputSize = mem_size; | |
355 | } | |
356 | ||
357 | mem->release(); | |
358 | ||
359 | ret = kIOReturnSuccess; | |
360 | } else { | |
361 | ret = kIOReturnCannotWire; | |
362 | } | |
363 | ||
364 | break; | |
365 | */ | |
366 | default: | |
367 | // bad selector | |
368 | return kIOReturnBadArgument; | |
369 | } | |
370 | ||
371 | return ret; | |
2d21ac55 | 372 | } |
2d21ac55 | 373 | |
6d2010ae A |
374 | /* getTargetAndMethodForIndex |
375 | * Not used. We prefer to use externalMethod() for user client invocations. | |
376 | * We maintain getTargetAndExternalMethod since it's an exported symbol, | |
377 | * and only for that reason. | |
378 | */ | |
379 | IOExternalMethod * RootDomainUserClient::getTargetAndMethodForIndex( | |
380 | IOService ** targetP, UInt32 index ) | |
55e303ae | 381 | { |
6d2010ae A |
382 | // DO NOT EDIT |
383 | return super::getTargetAndMethodForIndex(targetP, index); | |
55e303ae A |
384 | } |
385 | ||
6d2010ae A |
386 | /* setPreventative |
387 | * Does nothing. Exists only for exported symbol compatibility. | |
388 | */ | |
389 | void | |
390 | RootDomainUserClient::setPreventative(UInt32 on_off, UInt32 types_of_sleep) | |
391 | { return; } // DO NOT EDIT |