1/*
2 * Copyright (c) 2001-2007 Apple Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * The contents of this file constitute Original Code as defined in and
7 * are subject to the Apple Public Source License Version 1.1 (the
8 * "License").  You may not use this file except in compliance with the
9 * License.  Please obtain a copy of the License at
10 * http://www.apple.com/publicsource and read it before using this file.
11 *
12 * This Original Code and all software distributed under the License are
13 * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
14 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
15 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
17 * License for the specific language governing rights and limitations
18 * under the License.
19 *
20 * @APPLE_LICENSE_HEADER_END@
21 */
22
23#include "AppleRAID.h"
24
25#define super IOUserClient
26OSDefineMetaClassAndStructors(AppleRAIDUserClient, IOUserClient);
27
28
29bool
30AppleRAIDUserClient::initWithTask(task_t owningTask, void *security_id, UInt32 type)
31{
32    IOLogUC("AppleRAIDUserClient::initWithTask()\n");
33
34    if (!super::initWithTask(owningTask, security_id, type)) return false;
35
36    if (!owningTask) return false;
37    ucClient = owningTask;
38    ucController = NULL;
39
40    return true;
41}
42
43
44bool
45AppleRAIDUserClient::start(IOService * provider)
46{
47    IOLogUC("AppleRAIDUserClient::start()\n");
48
49    if (!super::start(provider)) return false;
50
51    ucController = OSDynamicCast(AppleRAID, provider);
52    if (!ucController) return false;
53
54    return true;
55}
56
57
58IOReturn
59AppleRAIDUserClient::clientClose(void)
60{
61    IOLogUC("AppleRAIDUserClient::clientClose()\n");
62
63    closeController();
64
65    ucClient = NULL;
66    ucController = NULL;
67
68    terminate();
69
70    // Do not call super::clientClose, which just returns notSupported
71    return kIOReturnSuccess;
72}
73
74
75IOReturn
76AppleRAIDUserClient::externalMethod(uint32_t                    selector,
77				    IOExternalMethodArguments * arguments,
78				    IOExternalMethodDispatch *  dispatch,
79				    OSObject *                  target,
80				    void *                      reference)
81{
82    IOLogUC("AppleRAIDUserClient::externalMethod(selector = %d)\n", (int)selector);
83
84    static const IOExternalMethodDispatch sMethods[kAppleRAIDUserClientMethodsCount] =
85    {
86        {   // 0 - kAppleRAIDClientOpen
87            (IOExternalMethodAction) &AppleRAIDUserClient::openShim,
88            0, 0,							// scalar in count, struct in size
89	    0, 0							// scalar out count, struct out size
90        },
91        {   // 1 - kAppleRAIDClientClose
92            (IOExternalMethodAction) &AppleRAIDUserClient::closeShim,
93            0, 0,							// scalar in count, struct in size
94	    0, 0							// scalar out count, struct out size
95        },
96        {   // 2 - kAppleRAIDGetListOfSets
97            (IOExternalMethodAction) &AppleRAIDUserClient::getListOfSetsShim,
98            0, sizeof(UInt32),						// scalar in count, struct in size
99	    0, 0xffffffff						// scalar out count, struct out size
100        },
101	{   // 3 - kAppleRAIDGetSetProperties
102            (IOExternalMethodAction) &AppleRAIDUserClient::getSetPropertiesShim,
103            0, kAppleRAIDMaxUUIDStringSize,				// scalar in count, struct in size
104	    0, 0xffffffff						// scalar out count, struct out size
105        },
106        {   // 4 - kAppleRAIDGetMemberProperties
107            (IOExternalMethodAction) &AppleRAIDUserClient::getMemberPropertiesShim,
108            0, kAppleRAIDMaxUUIDStringSize,				// scalar in count, struct in size
109	    0, 0xffffffff						// scalar out count, struct out size
110        },
111        {   // 5 - kAppleRAIDUpdateSet
112            (IOExternalMethodAction) &AppleRAIDUserClient::updateSetShim,
113            0, 0xffffffff,						// scalar in count, struct in size
114	    0, 0xffffffff						// scalar out count, struct out size
115        },
116        {   // 6 - kAppleLVMGetVolumesForGroup
117            (IOExternalMethodAction) &AppleRAIDUserClient::getVolumesForGroupShim,
118            0, kAppleRAIDMaxUUIDStringSize * 2,				// scalar in count, struct in size
119	    0, 0xffffffff						// scalar out count, struct out size
120        },
121        {   // 7 - kAppleLVMGetVolumeProperties
122            (IOExternalMethodAction) &AppleRAIDUserClient::getVolumePropertiesShim,
123            0, kAppleRAIDMaxUUIDStringSize,				// scalar in count, struct in size
124	    0, 0xffffffff						// scalar out count, struct out size
125        },
126        {   // 8 - kAppleLVMGetVolumeExtents
127            (IOExternalMethodAction) &AppleRAIDUserClient::getVolumeExtentsShim,
128            0, kAppleRAIDMaxUUIDStringSize,				// scalar in count, struct in size
129	    0, 0xffffffff						// scalar out count, struct out size
130        },
131        {   // 9 - kAppleLVMUpdateLogicalVolume
132            (IOExternalMethodAction) &AppleRAIDUserClient::updateLogicalVolumeShim,
133            0, 0xffffffff,						// scalar in count, struct in size
134	    0, 0xffffffff						// scalar out count, struct out size
135        },
136        {   // 10 - kAppleLVMDestroyLogicalVolume
137            (IOExternalMethodAction) &AppleRAIDUserClient::destroyLogicalVolumeShim,
138            0, 0xffffffff,						// scalar in count, struct in size
139	    0, 0xffffffff						// scalar out count, struct out size
140        }
141    };
142
143    // Make sure that the index of the function we're calling actually exists in the function table.
144    if (selector < (uint32_t)kAppleRAIDUserClientMethodsCount)
145    {
146	dispatch = (IOExternalMethodDispatch *) &sMethods[selector];
147	target = this;
148	return super::externalMethod(selector, arguments, dispatch, target, reference);
149    }
150
151    return kIOReturnBadArgument;
152}
153
154
155// ***********************************************************************************************************
156// ***********************************************************************************************************
157// ***********************************************************************************************************
158
159IOReturn
160AppleRAIDUserClient::openController(void)
161{
162    IOLogUC("AppleRAIDUserClient::openController()\n");
163
164    if (!ucController) return kIOReturnNotAttached;
165
166    if (!ucController->open(this)) return kIOReturnExclusiveAccess;
167
168    return kIOReturnSuccess;
169}
170
171
172IOReturn
173AppleRAIDUserClient::closeController(void)
174{
175    IOLogUC("AppleRAIDUserClient::closeController()\n");
176
177    if (!ucController) return kIOReturnNotAttached;
178
179    if (ucController->isOpen(this)) {
180	ucController->close(this);
181    }
182
183    return kIOReturnSuccess;
184}
185
186#if 0
187// XXX will need to support larger ool arguments someday
188
189IOReturn
190AppleRAIDUserClient::mapArguments(IOExternalMethodArguments * arguments, void ** in, uint32_t * inCount, void ** out, uint32_t * outCount)
191{
192    if (arguments->structureInputDescriptor) {
193
194        IOMemoryDescriptor * mem = arguments->structureInputDescriptor;
195        IOReturn ret = mem->map();  ///////////
196        if (ret != kIOReturnSuccess) return ret;
197
198	*in = mem->virtual;  ////////////
199	*inCount = mem->getLength();
200    } else {
201        *in = arguments->structureInput;
202	*inCount = arguments->structureInputSize;
203    }
204    if (arguments->structureOutputDescriptor) {
205
206        IOMemoryDescriptor * mem = arguments->structureOutputDescriptor;
207        IOReturn ret = mem->map();  ///////////
208        if (ret != kIOReturnSuccess) return ret;
209
210	*out = 0;  ////////
211	*outCount = arguments->structureOutputSize;
212    } else {
213        *out = arguments->structureOutput;
214	*outCount = arguments->structureOutputSize;
215    }
216
217    return IOReturnSuccess;
218}
219
220IOReturn
221AppleRAIDUserClient::unmapArguments(IOExternalMethodArguments * arguments, void * out, uint32_t outCount)
222{
223}
224#endif
225
226IOReturn
227AppleRAIDUserClient::getListOfSets(IOExternalMethodArguments * arguments)
228{
229    IOLogUC("AppleRAIDUserClient::getListOfSets()\n");
230
231    if (arguments->structureInputDescriptor) return kIOReturnBadArgument;
232    if (arguments->structureOutputDescriptor) return kIOReturnBadArgument;
233
234    if (!ucController || isInactive()) return kIOReturnNotAttached;
235
236    UInt32 flags = *((UInt32 *)arguments->structureInput);
237
238    return ucController->getListOfSets(flags, (char *)arguments->structureOutput, &arguments->structureOutputSize);
239}
240
241
242IOReturn
243AppleRAIDUserClient::getSetProperties(IOExternalMethodArguments * arguments)
244{
245    IOLogUC("AppleRAIDUserClient::getSetProperties()\n");
246
247    if (arguments->structureInputDescriptor) return kIOReturnBadArgument;
248    if (arguments->structureOutputDescriptor) return kIOReturnBadArgument;
249
250    if (!ucController || isInactive()) return kIOReturnNotAttached;
251
252    return ucController->getSetProperties((char *)arguments->structureInput, arguments->structureInputSize,
253					  (char *)arguments->structureOutput, &arguments->structureOutputSize);
254}
255
256
257IOReturn
258AppleRAIDUserClient::getMemberProperties(IOExternalMethodArguments * arguments)
259{
260    IOLogUC("AppleRAIDUserClient::getMemberProperties()\n");
261
262    if (arguments->structureInputDescriptor) return kIOReturnBadArgument;
263    if (arguments->structureOutputDescriptor) return kIOReturnBadArgument;
264
265    if (!ucController || isInactive()) return kIOReturnNotAttached;
266
267    return ucController->getMemberProperties((char *)arguments->structureInput, arguments->structureInputSize,
268					     (char *)arguments->structureOutput, &arguments->structureOutputSize);
269}
270
271
272IOReturn
273AppleRAIDUserClient::updateSet(IOExternalMethodArguments * arguments)
274{
275    IOLogUC("AppleRAIDUserClient::updateSet()\n");
276
277    if (arguments->structureInputDescriptor) return kIOReturnBadArgument;
278    if (arguments->structureOutputDescriptor) return kIOReturnBadArgument;
279
280    if (!ucController || isInactive()) return kIOReturnNotAttached;
281
282    if (clientHasPrivilege(ucClient, kIOClientPrivilegeAdministrator)) return kIOReturnNotPrivileged;
283
284    return ucController->updateSet((char *)arguments->structureInput, arguments->structureInputSize,
285				   (char *)arguments->structureOutput, &arguments->structureOutputSize);
286}
287
288IOReturn
289AppleRAIDUserClient::getVolumesForGroup(IOExternalMethodArguments * arguments)
290{
291    IOLogUC("AppleRAIDUserClient::getVolumesForGroup()\n");
292
293    if (arguments->structureInputDescriptor) return kIOReturnBadArgument;
294    if (arguments->structureOutputDescriptor) return kIOReturnBadArgument;
295
296    if (!ucController || isInactive()) return kIOReturnNotAttached;
297
298    return ucController->getVolumesForGroup((char *)arguments->structureInput, arguments->structureInputSize,
299					    (char *)arguments->structureOutput, &arguments->structureOutputSize);
300}
301
302IOReturn
303AppleRAIDUserClient::getVolumeProperties(IOExternalMethodArguments * arguments)
304{
305    IOLogUC("AppleRAIDUserClient::getVolumeProperties()\n");
306
307    if (arguments->structureInputDescriptor) return kIOReturnBadArgument;
308    if (arguments->structureOutputDescriptor) return kIOReturnBadArgument;
309
310    if (!ucController || isInactive()) return kIOReturnNotAttached;
311
312    return ucController->getVolumeProperties((char *)arguments->structureInput, arguments->structureInputSize,
313					     (char *)arguments->structureOutput, &arguments->structureOutputSize);
314}
315
316IOReturn
317AppleRAIDUserClient::getVolumeExtents(IOExternalMethodArguments * arguments)
318{
319    IOLogUC("AppleRAIDUserClient::getVolumeExtentss()\n");
320
321    if (arguments->structureInputDescriptor) return kIOReturnBadArgument;
322    if (arguments->structureOutputDescriptor) return kIOReturnBadArgument;
323
324    if (!ucController || isInactive()) return kIOReturnNotAttached;
325
326    return ucController->getVolumeExtents((char *)arguments->structureInput, arguments->structureInputSize,
327					  (char *)arguments->structureOutput, &arguments->structureOutputSize);
328}
329
330IOReturn
331AppleRAIDUserClient::updateLogicalVolume(IOExternalMethodArguments * arguments)
332{
333    IOLogUC("AppleRAIDUserClient::updateLogicalVolume()\n");
334
335    if (arguments->structureInputDescriptor) return kIOReturnBadArgument;
336    if (arguments->structureOutputDescriptor) return kIOReturnBadArgument;
337
338    if (!ucController || isInactive()) return kIOReturnNotAttached;
339
340    if (clientHasPrivilege(ucClient, kIOClientPrivilegeAdministrator)) return kIOReturnNotPrivileged;
341
342    return ucController->updateLogicalVolume((char *)arguments->structureInput, arguments->structureInputSize,
343					     (char *)arguments->structureOutput, &arguments->structureOutputSize);
344    return 0;
345}
346
347
348IOReturn
349AppleRAIDUserClient::destroyLogicalVolume(IOExternalMethodArguments * arguments)
350{
351    IOLogUC("AppleRAIDUserClient::destroyLogicalVolume()\n");
352
353    if (arguments->structureInputDescriptor) return kIOReturnBadArgument;
354    if (arguments->structureOutputDescriptor) return kIOReturnBadArgument;
355
356    if (!ucController || isInactive()) return kIOReturnNotAttached;
357
358    if (clientHasPrivilege(ucClient, kIOClientPrivilegeAdministrator)) return kIOReturnNotPrivileged;
359
360    return ucController->destroyLogicalVolume((char *)arguments->structureInput, arguments->structureInputSize,
361					      (char *)arguments->structureOutput, &arguments->structureOutputSize);
362    return 0;
363}
364