/* * Copyright (c) 2019-2019 Apple Inc. All rights reserved. * * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. The rights granted to you under the License * may not be used to create, or enable the creation or redistribution of, * unlawful or unlicensed copies of an Apple operating system, or to * circumvent, violate, or enable the circumvention or violation of, any * terms of an Apple operating system software license agreement. * * Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this file. * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. * * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ */ #if !__IIG #if KERNEL #include #endif #endif #ifndef _IOKIT_UIOUSERCLIENT_H #define _IOKIT_UIOUSERCLIENT_H #include #include #include enum { kIOUserClientScalarArrayCountMax = 16, }; typedef uint64_t IOUserClientScalarArray[kIOUserClientScalarArrayCountMax]; enum { kIOUserClientAsyncReferenceCountMax = 16, }; typedef uint64_t IOUserClientAsyncReferenceArray[kIOUserClientAsyncReferenceCountMax]; enum { kIOUserClientAsyncArgumentsCountMax = 16, }; typedef uint64_t IOUserClientAsyncArgumentsArray[kIOUserClientAsyncArgumentsCountMax]; // CopyClientMemoryForType options enum { kIOUserClientMemoryReadOnly = 0x00000001, }; /*! @enum * @abstract Constant to denote a variable length structure argument to IOUserClient. * @constant kIOUserClientVariableStructureSize Use in the structures IOUserClientMethodDispatch to specify the size of the structure is variable. */ enum { kIOUserClientVariableStructureSize = 0xffffffff }; enum { #define IO_USER_CLIENT_METHOD_ARGUMENTS_CURRENT_VERSION 2 kIOUserClientMethodArgumentsCurrentVersion = IO_USER_CLIENT_METHOD_ARGUMENTS_CURRENT_VERSION }; /*! * @struct IOUserClientMethodArguments * @brief Holds arguments from IOKit.framework IOConnectMethod calls. * @discussion Any argument may be passed as NULL if not passed by the caller. * @field selector Selector argument to IOConnectMethod. * @field scalarInput Array of scalars from caller. * @field scalarInputCount Count of valid scalars in scalarInput. * @field structureInput OSData object containing structure input from IOConnectMethod. * @field structureInputDescriptor IOMemoryDescriptor containing structure input from IOConnectMethod. * This parameter is only set for large structures, and if set structureInput will be NULL. * @field scalarOutput Array of scalars to return to the caller. * @field scalarOutputCount Count of scalars to return to the caller in scalarOutput. * @field structureOutput An OSData to be returned to the caller as structure output. * This field should be set by the driver to an OSData object it created with * the data to be returned, and the OSData instance will be released by the OS. * It is an error for the driver to set this field if structureOutputDescriptor was passed in * @field structureOutputDescriptor A IOMemoryDescriptor specified by the caller for structure output. * @field structureOutputMaximumSize Maximum size of structure output specified by caller * or kIOUserClientVariableStructureSize. * @field completion For IOConnectAsyncMethod, an OSAction used to deliver async data to the caller. * It is only retained during the invocation of ExternalMethod and should be retained if * used beyond then. */ struct IOUserClientMethodArguments { uint64_t version; uint64_t selector; OSAction * completion; const uint64_t * scalarInput; uint32_t scalarInputCount; OSData * structureInput; IOMemoryDescriptor * structureInputDescriptor; uint64_t * scalarOutput; uint32_t scalarOutputCount; OSData * structureOutput; IOMemoryDescriptor * structureOutputDescriptor; uint64_t structureOutputMaximumSize; uint64_t __reserved[30]; }; typedef kern_return_t (*IOUserClientMethodFunction)( OSObject * target, void * reference, IOUserClientMethodArguments * arguments); /*! * @struct IOUserClientMethodDispatch * @brief Used to check fields in IOUserClientMethodArguments * @field function to invoke after making the checks specified below. If NULL and all checks pass, * kIOReturnNoCompletion will be returned for the caller to implement the method. * @field checkCompletionExists * if true completion field must be set, * if false must be zero, * if -1U don't care * @field checkScalarInputCount * if has value kIOUserClientVariableStructureSize don't care, * otherwise must equal args->scalarInputCount * @field checkStructureInputSize * if has value kIOUserClientVariableStructureSize don't care, * otherwise must equal length of structureInput or structureInputDescriptor * @field checkScalarOutputCount * if has value kIOUserClientVariableStructureSize don't care, * otherwise must equal args->scalarOutputCount * @field checkStructureOutputSize * if has value kIOUserClientVariableStructureSize don't care, * otherwise must equal length of structureOutputMaximumSize */ struct IOUserClientMethodDispatch { IOUserClientMethodFunction function; uint32_t checkCompletionExists; uint32_t checkScalarInputCount; uint32_t checkStructureInputSize; uint32_t checkScalarOutputCount; uint32_t checkStructureOutputSize; }; /*! * @class IOUserClient * * @abstract * IOUserClient represents a connection opened by IOServiceOpen in the IOKit.framework. * * @discussion * An application may open an IOUserClient by calling IOServiceOpen(). This results in a call * to the IOService::NewUserClient API to create an instance representing the connection. * and to receive untyped data via IOConnectMethod/IOConnectAsyncMethod. * As an IOService subclass, IOUserClient receives the normal Start()/Stop() lifecyle calls. * @iig implementation #include @iig end */ class KERNEL IOUserClient : public IOService { public: virtual bool init() override; virtual void free() override; /*! * @brief Receive arguments from IOKit.framework IOConnectMethod calls. * @discussion IOConnectMethod calls from the owner of the connection come here. * Any argument may be passed as NULL if not passed by the caller. * @param selector Selector argument to IOConnectMethod. * @param scalarInput Array of scalars from caller. * @param scalarInputCount Count of valid scalars in scalarInput. * @param structureInput OSData object containing structure input from IOConnectMethod. * @param structureInputDescriptor IOMemoryDescriptor containing structure input from IOConnectMethod. * This parameter is only set for large structures, and if set structureInput will be NULL. * @param scalarOutput Array of scalars to return to the caller. * @param scalarOutputCount Count of scalars to return to the caller in scalarOutput. * @param structureOutput An OSData to be returned to the caller as structureOutput. * A reference will be consumed by the caller. * @param structureOutputDescriptor An IOMemoryDescriptor to be returned to the caller as structureOutput. * A reference will be consumed by the caller. * Only one of structureOutput and structureOutputDescriptor may set. * @param completion For IOConnectAsyncMethod, an OSAction used to deliver async data to the caller. * It should be passed to the AsyncCompletion() method and released. * @return kIOReturnSuccess on success. See IOReturn.h for error codes. */ virtual kern_return_t ExternalMethod( uint64_t selector, IOUserClientMethodArguments * arguments, const IOUserClientMethodDispatch * dispatch, OSObject * target, void * reference) LOCALONLY; /*! * @brief Send asynchronous arguments to a completion supplied by ExternalMethod(). * @discussion IOConnectAsyncMethod calls from the owner of the connection come will pass an OSAction instance. * To deliver the asynchronous results the driver calls AsyncCompletion(). * @param action OSAction passed to IOExternalMethod(). * @param status An IOReturn status value to be sent. * @param asyncData An array of scalar data to be sent. * @param asyncDataCount Count of valid data in asyncData. */ virtual void AsyncCompletion( OSAction * action TARGET, IOReturn status, const IOUserClientAsyncArgumentsArray asyncData, uint32_t asyncDataCount) = 0; /*! * @brief Return an IOMemoryDescriptor to be mapped into the client task. * @discussion IOConnectMapMemory()/UnmapMemory() will result in a call to this method to obtain * an IOMemoryDescriptor instance for shared memory. For a given IOUserClient instance, calling * CopyClientMemoryForType() with a given type, should return the same IOMemoryDescriptor instance. * @param type Type parameter IOConnectMapMemory()/UnmapMemory(). * @param options Set kIOUserClientMemoryReadOnly for memory to be mapped read only in the client. * @param memory An instance of IOMemoryDescriptor on success. One reference will be consumed by the caller * of this method. * @return kIOReturnSuccess on success. See IOReturn.h for error codes. */ virtual kern_return_t CopyClientMemoryForType( uint64_t type, uint64_t * options, IOMemoryDescriptor ** memory) = 0; /*! * @brief Create a memory descriptor that describes a set of virtual ranges in * the client task of the user client. * @param memoryDescriptorCreateOptions * kIOMemoryDirectionIn memory described will be writable * kIOMemoryDirectionOut memory described will be readable * @param segmentsCount Number of valid address ranges being passed * in the segments array. * @param segments Array of address ranges. * @param memory Returned IOMemoryDescriptor object with +1 retain count. * @return kIOReturnSuccess on success. See IOReturn.h for error codes. */ virtual kern_return_t CreateMemoryDescriptorFromClient( uint64_t memoryDescriptorCreateOptions, uint32_t segmentsCount, const IOAddressSegment segments[32], IOMemoryDescriptor ** memory) __attribute__((availability(driverkit,introduced=20.0))); private: virtual kern_return_t _ExternalMethod( uint64_t selector, const IOUserClientScalarArray scalarInput, uint32_t scalarInputCount, OSData * structureInput, IOMemoryDescriptor * structureInputDescriptor, IOUserClientScalarArray scalarOutput, uint32_t * scalarOutputCount, uint64_t structureOutputMaximumSize, OSData ** structureOutput, IOMemoryDescriptor * structureOutputDescriptor, OSAction * completion TYPE(IOUserClient::AsyncCompletion)) LOCAL; virtual void KernelCompletion( OSAction * action TARGET, IOReturn status, const IOUserClientAsyncArgumentsArray asyncData, uint32_t asyncDataCount) KERNEL TYPE(IOUserClient::AsyncCompletion); }; #endif /* ! _IOKIT_UIOUSERCLIENT_H */