xref: /xnu-10002.41.9/iokit/DriverKit/IOUserClient.iig (revision 699cd48037512bf4380799317ca44ca453c82f57)
1/*
2 * Copyright (c) 2019-2019 Apple 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#if !__IIG
30#if KERNEL
31#include <IOKit/IOUserClient.h>
32#endif
33#endif
34
35#ifndef _IOKIT_UIOUSERCLIENT_H
36#define _IOKIT_UIOUSERCLIENT_H
37
38#include <DriverKit/OSAction.iig>
39#include <DriverKit/IOService.iig>
40#include <DriverKit/IOBufferMemoryDescriptor.iig>
41
42
43enum {
44	kIOUserClientScalarArrayCountMax  = 16,
45};
46typedef uint64_t IOUserClientScalarArray[kIOUserClientScalarArrayCountMax];
47
48enum {
49	kIOUserClientAsyncReferenceCountMax  = 16,
50};
51typedef uint64_t IOUserClientAsyncReferenceArray[kIOUserClientAsyncReferenceCountMax];
52
53enum {
54	kIOUserClientAsyncArgumentsCountMax  = 16,
55};
56typedef uint64_t IOUserClientAsyncArgumentsArray[kIOUserClientAsyncArgumentsCountMax];
57
58// CopyClientMemoryForType options
59enum {
60	kIOUserClientMemoryReadOnly  = 0x00000001,
61};
62
63#define kIOUserClientQueueNameExternalMethod  "IOUserClientQueueExternalMethod"
64
65
66/*! @enum
67 *   @abstract Constant to denote a variable length structure argument to IOUserClient.
68 *   @constant kIOUserClientVariableStructureSize Use in the structures IOUserClientMethodDispatch to specify the size of the structure is variable.
69 */
70enum {
71	kIOUserClientVariableStructureSize = 0xffffffff
72};
73
74
75enum {
76#define IO_USER_CLIENT_METHOD_ARGUMENTS_CURRENT_VERSION    2
77	kIOUserClientMethodArgumentsCurrentVersion = IO_USER_CLIENT_METHOD_ARGUMENTS_CURRENT_VERSION
78};
79
80/*!
81 * @struct      IOUserClientMethodArguments
82 * @brief       Holds arguments from IOKit.framework IOConnectMethod calls.
83 * @discussion  Any argument may be passed as NULL if not passed by the caller.
84 * @field       selector Selector argument to IOConnectMethod.
85 * @field       scalarInput Array of scalars from caller.
86 * @field       scalarInputCount Count of valid scalars in scalarInput.
87 * @field       structureInput OSData object containing structure input from IOConnectMethod.
88 * @field       structureInputDescriptor IOMemoryDescriptor containing structure input from IOConnectMethod.
89 *				This parameter is only set for large structures, and if set structureInput will be NULL.
90 * @field       scalarOutput Array of scalars to return to the caller.
91 * @field       scalarOutputCount Count of scalars to return to the caller in scalarOutput.
92 * @field       structureOutput An OSData to be returned to the caller as structure output.
93 *              This field should be set by the driver to an OSData object it created with
94 *              the data to be returned, and the OSData instance will be released by the OS.
95 *              It is an error for the driver to set this field if structureOutputDescriptor was passed in
96 * @field       structureOutputDescriptor A IOMemoryDescriptor specified by the caller for structure output.
97 * @field       structureOutputMaximumSize Maximum size of structure output specified by caller
98 *              or kIOUserClientVariableStructureSize.
99 * @field       completion For IOConnectAsyncMethod, an OSAction used to deliver async data to the caller.
100 *              It is only retained during the invocation of ExternalMethod and should be retained if
101 *              used beyond then.
102 */
103
104struct IOUserClientMethodArguments {
105	uint64_t            			version;
106	uint64_t                        selector;
107	OSAction                      * completion;
108    const uint64_t			      * scalarInput;
109	uint32_t						scalarInputCount;
110	OSData 						  * structureInput;
111	IOMemoryDescriptor            * structureInputDescriptor;
112	uint64_t                      * scalarOutput;
113	uint32_t                        scalarOutputCount;
114	OSData                        * structureOutput;
115	IOMemoryDescriptor            * structureOutputDescriptor;
116	uint64_t                        structureOutputMaximumSize;
117	uint64_t                        __reserved[30];
118};
119
120typedef kern_return_t (*IOUserClientMethodFunction)(
121	OSObject * target,
122	void * reference,
123    IOUserClientMethodArguments * arguments);
124
125/*!
126 * @struct      IOUserClientMethodDispatch
127 * @brief       Used to check fields in IOUserClientMethodArguments
128 * @field       function to invoke after making the checks specified below. If NULL and all checks pass,
129 *              kIOReturnNoCompletion will be returned for the caller to implement the method.
130 * @field       checkCompletionExists
131 *              if true completion field must be set,
132 *              if false must be zero,
133 *              if -1U don't care
134 * @field       checkScalarInputCount
135 *              if has value kIOUserClientVariableStructureSize don't care,
136 *              otherwise must equal args->scalarInputCount
137 * @field       checkStructureInputSize
138 *              if has value kIOUserClientVariableStructureSize don't care,
139 *              otherwise must equal length of structureInput or structureInputDescriptor
140 * @field       checkScalarOutputCount
141 *              if has value kIOUserClientVariableStructureSize don't care,
142 *              otherwise must equal args->scalarOutputCount
143 * @field       checkStructureOutputSize
144 *              if has value kIOUserClientVariableStructureSize don't care,
145 *              otherwise must equal length of structureOutputMaximumSize
146 */
147
148struct IOUserClientMethodDispatch {
149	IOUserClientMethodFunction function;
150	uint32_t			       checkCompletionExists;
151	uint32_t			       checkScalarInputCount;
152	uint32_t			       checkStructureInputSize;
153	uint32_t			       checkScalarOutputCount;
154	uint32_t			       checkStructureOutputSize;
155};
156
157/*!
158 * @class IOUserClient
159 *
160 * @abstract
161 * IOUserClient represents a connection opened by IOServiceOpen in the IOKit.framework.
162 *
163 * @discussion
164 * An application may open an IOUserClient by calling IOServiceOpen(). This results in a call
165 * to the IOService::NewUserClient API to create an instance representing the connection.
166 * and to receive untyped data via IOConnectMethod/IOConnectAsyncMethod.
167 * As an IOService subclass, IOUserClient receives the normal Start()/Stop() lifecyle calls.
168 *
169
170@iig implementation
171#include <DriverKit/IOBufferMemoryDescriptor.h>
172@iig end
173*/
174
175class KERNEL IOUserClient : public IOService
176{
177public:
178	virtual bool
179	init() override;
180
181	virtual void
182	free() override;
183
184	/*!
185	 * @brief       Receive arguments from IOKit.framework IOConnectMethod calls.
186	 * @discussion  IOConnectMethod calls from the owner of the connection come here.
187	 *              Any argument may be passed as NULL if not passed by the caller.
188	 *              The method runs on a queue set by IOService::SetDispatchQueuue()
189	 *              with the name kIOUserClientQueueNameExternalMethod, or the default
190	 *              queue for the IOUserClient object if one was not set.
191	 * @param       selector Selector argument to IOConnectMethod.
192	 * @param       arguments Structure describing all arguments being passed to IOConnectMethod.
193	 * 				          See the IOUserClientMethodArguments definition.
194	 * @param       dispatch NULL when called in the driver. The IOUserClient::ExternalMethod()
195	 *				         implementation may be called with a non-NULL argument to check
196	 *				         certain fields of the arguments structure before calling a target procedure
197	 *				         specified by the dispatch structure 'function' field, and the
198	 *				         'target' and 'reference' parameters to this method.
199	 *				         See the IOUserClientMethodDispatch definition.
200	 * @param       target Target for the dispatch function
201	 * @param       reference Reference constant for the dispatch function
202	 * @return      kIOReturnSuccess on success. See IOReturn.h for error codes.
203	 */
204
205	virtual kern_return_t
206	ExternalMethod(
207		uint64_t                            selector,
208	    IOUserClientMethodArguments       * arguments,
209	    const IOUserClientMethodDispatch  * dispatch,
210	    OSObject                          * target,
211	    void                              * reference) LOCALONLY
212	QUEUENAME(IOUserClientQueueExternalMethod);
213
214
215    /*!
216     * @brief       Send asynchronous arguments to a completion supplied by ExternalMethod().
217     * @discussion  IOConnectAsyncMethod calls from the owner of the connection come will pass an OSAction instance.
218     *              To deliver the asynchronous results the driver calls AsyncCompletion().
219     * @param       action OSAction passed to IOExternalMethod().
220     * @param       status An IOReturn status value to be sent.
221     * @param       asyncData An array of scalar data to be sent.
222     * @param       asyncDataCount Count of valid data in asyncData.
223     */
224    virtual void
225    AsyncCompletion(
226        OSAction                            * action TARGET,
227        IOReturn                              status,
228        const IOUserClientAsyncArgumentsArray asyncData,
229		uint32_t                              asyncDataCount) = 0;
230
231    /*!
232     * @brief       Return an IOMemoryDescriptor to be mapped into the client task.
233     * @discussion  IOConnectMapMemory()/UnmapMemory() will result in a call to this method to obtain
234     *              an IOMemoryDescriptor instance for shared memory. For a given IOUserClient instance, calling
235     *              CopyClientMemoryForType() with a given type, should return the same IOMemoryDescriptor instance.
236     * @param       type Type parameter IOConnectMapMemory()/UnmapMemory().
237     * @param       options Set kIOUserClientMemoryReadOnly for memory to be mapped read only in the client.
238     * @param       memory An instance of IOMemoryDescriptor on success. One reference will be consumed by the caller
239     *              of this method.
240     * @return      kIOReturnSuccess on success. See IOReturn.h for error codes.
241     */
242	virtual kern_return_t
243	CopyClientMemoryForType(
244		uint64_t                              type,
245	    uint64_t                            * options,
246	    IOMemoryDescriptor                 ** memory) = 0;
247
248    /*!
249     * @brief       Create a memory descriptor that describes a set of virtual ranges in
250     *              the client task of the user client.
251     * @param       memoryDescriptorCreateOptions
252	 *              kIOMemoryDirectionIn memory described will be writable
253	 *              kIOMemoryDirectionOut memory described will be readable
254	 * @param       segmentsCount Number of valid address ranges being passed
255	 *              in the segments array.
256	 * @param       segments Array of address ranges.
257	 * @param       memory Returned IOMemoryDescriptor object with +1 retain count.
258     * @return      kIOReturnSuccess on success. See IOReturn.h for error codes.
259     */
260	virtual kern_return_t
261	CreateMemoryDescriptorFromClient(
262		uint64_t memoryDescriptorCreateOptions,
263		uint32_t segmentsCount,
264		const IOAddressSegment segments[32],
265		IOMemoryDescriptor ** memory) __attribute__((availability(driverkit,introduced=20.0)));
266
267   /*!
268    * @function CopyClientEntitlements
269    * @abstract Return owning task's entitlements dictionary.
270    * @param    entitlements Dictionary of entitlements given to the owning task. To be released by caller.
271    * @return   kIOReturnSuccess on success. See IOReturn.h for error codes.
272	*/
273	virtual kern_return_t
274	CopyClientEntitlements(OSDictionary ** entitlements) LOCAL;
275
276
277private:
278	virtual kern_return_t
279	_ExternalMethod(
280		uint64_t                              selector,
281		const IOUserClientScalarArray		  scalarInput,
282		uint32_t							  scalarInputCount,
283		OSData 							    * structureInput,
284		IOMemoryDescriptor                  * structureInputDescriptor,
285		IOUserClientScalarArray               scalarOutput,
286		uint32_t                            * scalarOutputCount,
287		uint64_t                              structureOutputMaximumSize,
288		OSData                             ** structureOutput,
289		IOMemoryDescriptor                  * structureOutputDescriptor,
290        OSAction                            * completion TYPE(IOUserClient::AsyncCompletion)) LOCAL
291	QUEUENAME(IOUserClientQueueExternalMethod);
292
293    virtual void
294    KernelCompletion(
295        OSAction                            * action TARGET,
296        IOReturn                              status,
297        const IOUserClientAsyncArgumentsArray asyncData,
298		uint32_t                              asyncDataCount)
299        KERNEL
300        TYPE(IOUserClient::AsyncCompletion);
301};
302
303#endif /* ! _IOKIT_UIOUSERCLIENT_H */
304