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