This is xnu-8019. See this file in:
/*
 * 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 <IOKit/IOService.h>
#endif
#endif

#ifndef _IOKIT_UIOSERVICE_H
#define _IOKIT_UIOSERVICE_H

#include <DriverKit/OSObject.iig>

class IOMemoryDescriptor;
class IOBufferMemoryDescriptor;
class IOUserClient;
class OSAction;
class IOServiceStateNotificationDispatchSource;

typedef char IOServiceName[128];
typedef char IOPropertyName[128];
typedef char IORegistryPlaneName[128];

enum {
	kIOServiceSearchPropertyParents = 0x00000001,
};

#define kIOServiceDefaultQueueName	"Default"

enum {
	kIOServicePowerCapabilityOff = 0x00000000,
	kIOServicePowerCapabilityOn  = 0x00000002,
	kIOServicePowerCapabilityLow = 0x00010000,
};

enum {
	_kIOPMWakeEventSource = 0x00000001,
};

// values for OSNumber kIOSystemStateHaltDescriptionKey:kIOSystemStateHaltDescriptionHaltStateKey
enum {
	kIOServiceHaltStatePowerOff = 0x00000001,
	kIOServiceHaltStateRestart  = 0x00000002,
};

/*!
 * @class IOService
 *
 * @abstract
 * IOService represents an device or OS service in IOKit and DriverKit.
 *
 * @discussion
 * IOKit provides driver lifecycle management through the IOService APIs. 
 * Drivers and devices are represented as subclasses of IOService.
 *

@iig implementation
#include <DriverKit/IODispatchQueue.h>
#include <DriverKit/IOUserClient.h>
#include <DriverKit/IOServiceStateNotificationDispatchSource.h>
@iig end
*/

class KERNEL IOService : public OSObject
{
public:
	virtual bool
	init() override;

	virtual void
	free() override;

    /*!
     * @brief       First call made to a matched IOService.
     * @discussion  During matching IOKit will create an IOService object for successful matches.
     *              Start is the first call made to the new object.
     * @param       provider The IOService provider for the match. This should be OSRequiredCast to the expected class.
     *              The provider is retained by DriverKit for the duration of Start() and on successful Start() until
     *              IOService::Stop() is called.
     * @return      kIOReturnSuccess on success. See IOReturn.h for error codes.
     */
	virtual kern_return_t
	Start(IOService * provider) LOCAL;

    /*!
     * @brief       Terminate access to provider.
     * @discussion  During termination IOKit will teardown any IOService objects attached to a terminated provider.
     *              Stop should quiesce all activity and when complete, pass the call to super. After calling super, the
     *              provider is no longer valid and this object will likely be freed.
     * @param       provider The IOService provider for being terminated, one previously passed to Start
     * @return      kIOReturnSuccess on success. See IOReturn.h for error codes.
     */
	virtual kern_return_t
	Stop(IOService * provider) LOCAL;

	/*! @function   ClientCrashed
	 * @discussion  Notification for kernel objects of a client crash.
     * @param       client Attached client.
     * @param       options No options are currently defined.
	 * @return      kIOReturnSuccess on success. See IOReturn.h for error codes.
	 */
	virtual kern_return_t
	ClientCrashed(IOService * client, uint64_t options);

    /*!
     * @brief       Obtain IOKit IORegistryEntryID.
     * @param       registryEntryID IORegistryEntryID for the IOKit object.
     * @return      kIOReturnSuccess on success. See IOReturn.h for error codes.
     */
	virtual kern_return_t
	GetRegistryEntryID(uint64_t * registryEntryID) LOCAL;

    /*!
     * @brief       Set the IORegistryEntry name.
     * @param       name Name for the IOKit object. The c-string will be copied.
     * @return      kIOReturnSuccess on success. See IOReturn.h for error codes.
     */
	virtual kern_return_t
	SetName(
	const IOServiceName name);

    /*!
     * @brief       Start the matching process on the IOService object.
     * @return      kIOReturnSuccess on success. See IOReturn.h for error codes.
     */
	virtual kern_return_t
	RegisterService();

    /*!
     * @brief       Set the IODispatchQueue for a given name on the IOService.
     * @param       name Name for the queue. The name may be referenced by methods in the .iig class definition
     *              with the QUEUENAME() attribute to indicate the method must be invoked on that queue. If a method
     *              is invoked before the queue is set for the name, the default queue is used. A default queue is
     *              created by DriverKit for every new IOService object with the name kIOServiceDefaultQueueName.
     * @param       queue Queue to be associated with the name on this IOService.
     * @return      kIOReturnSuccess on success. See IOReturn.h for error codes.
     */
	virtual kern_return_t
	SetDispatchQueue(
		const IODispatchQueueName name,
		IODispatchQueue         * queue) override LOCAL;

    /*!
     * @brief       Obtain the IODispatchQueue for a given name on the IOService.
     * @param       name Name for the queue.
     * @param       queue Returned, retained queue or NULL. The caller should release this queue.
     * @return      kIOReturnSuccess on success. See IOReturn.h for error codes.
     */
	virtual kern_return_t
	CopyDispatchQueue(
		const IODispatchQueueName name,
		IODispatchQueue        ** queue) override;

    /*!
     * @brief       Create the default IODispatchQueue for an IOService. IOService::init()
     *              calls this to create its default queue.
     * @param       queue Returned, retained queue or NULL.
     * @return      kIOReturnSuccess on success. See IOReturn.h for error codes.
     */
	virtual kern_return_t
	CreateDefaultDispatchQueue(
		IODispatchQueue        ** queue) LOCAL;

    /*!
     * @brief       Obtain the IOKit registry properties for the IOService.
     * @param       properties Returned, retained dictionary of properties or NULL. The caller should release this dictionary.
     * @return      kIOReturnSuccess on success. See IOReturn.h for error codes.
     */
	virtual kern_return_t
	CopyProperties(
		OSDictionary ** properties);

    /*!
     * @brief       Obtain the an IOKit registry properties from the service or one of its parents.
     * @param       name Name of the property as a c-string.
     * @param       plane Name of the registry plane to be searched, if the option kIOServiceSearchPropertyParents
     *              is used.
     * @param       options Pass kIOServiceSearchPropertyParents to search for the property in the IOService and all
     *              its parents in the IOKit registry.
     * @param       property Returned, retained property object or NULL. The caller should release this property.
     * @return      kIOReturnSuccess on success. See IOReturn.h for error codes.
     */
	virtual kern_return_t
	SearchProperty(
		const IOPropertyName name,
		const IORegistryPlaneName plane,
		uint64_t options,
		OSContainer ** property);

    /*!
     * @brief       Send a dictionary of properties to an IOService.
     * @discussion  By default the method will fail. A DriverKit subclass or kernel class may implement this method.
     * @param       properties Dictionary of properties.
     * @return      kIOReturnSuccess on success. See IOReturn.h for error codes.
     */
	virtual kern_return_t
	SetProperties(
		OSDictionary * properties);

    /*!
     * @brief       Notification of change in power state of a provider.
     * @discussion  DriverKit notifies of changes in power of a provider. The driver should make itself safe for
     *              the new state before passing the call to super. 
     * @param       powerFlags The power capabilities of the new state. The values possible are:
	 *	kIOServicePowerCapabilityOff the system will be entering sleep state
	 *	kIOServicePowerCapabilityOn  the device and system are fully powered
	 *  kIOServicePowerCapabilityLow the device is in a reduced power state while the system is running
     * @return      kIOReturnSuccess on success. See IOReturn.h for error codes.
     */
	virtual kern_return_t
	SetPowerState(
		uint32_t powerFlags) LOCAL;

    /*!
     * @brief       Allow provider to enter a low power state.
     * @discussion  A driver may allow a device to enter a lower power state. 
     * @param       powerFlags The power capabilities of the new state. The values possible are:
	 *  kIOServicePowerCapabilityLow the device is in a reduced power state while the system is running
     * @return      kIOReturnSuccess on success. See IOReturn.h for error codes.
     */
	virtual kern_return_t
	ChangePowerState(
		uint32_t powerFlags);

    /*!
     * @brief       Request create a new user client for a client process.
     * @discussion  An application may request an IOUserClient be opened with the IOKit framework
     *              IOServiceOpen() call. The type parameter of that call is passed here. The driver should respond to
     *              the call by calling IOService::Create() with a plist entry describing the new user client object.
     * @param       type The type passed to IOServiceOpen().
     * @param       userClient The object created by IOService::Create()
     * @return      kIOReturnSuccess on success. See IOReturn.h for error codes.
     */
	virtual kern_return_t
	NewUserClient(
		uint32_t type,
		IOUserClient ** userClient);

    /*!
     * @brief       Request to create an IOService object from a plist property.
     * @discussion  An IOService interface or IOUserClient subclass may be created from a plist property of the driver.
     *              The plist should contain the following IOKit matching keys:
     *              IOClass - kernel class of IOUserUserClient
     *              IOUserClass - DriverKit class to be instantiated
     *              IOServiceDEXTEntitlements - Array of entitlements to be checked against a user client owning task
     * @param       provider The provider of the new object.
     * @param       propertiesKey The name of the properties dictionary in this IOService
     * @param       result The created object retained, to be released by the caller.
     * @return      kIOReturnSuccess on success. See IOReturn.h for error codes.
     */
	virtual kern_return_t
	Create(
		IOService          * provider,
		const IOPropertyName propertiesKey,
		IOService         ** result) LOCAL;

    /*!
     * @brief       Start an IOService termination.
     * @discussion  An IOService object created with Create() may be removed by calling Terminate().
     *              The termination is asynchronous and will later call Stop() on the service.
     * @param       options No options are currently defined, pass zero.
     * @return      kIOReturnSuccess on success. See IOReturn.h for error codes.
     */
	virtual kern_return_t
	Terminate(
		uint64_t			 options);

   /*!
    * @brief       Obtain supportable properties describing the provider chain.
    * @discussion  Obtain supportable properties describing the provider chain. This will be a subset of registry
    *              properties the OS considers supportable.
    *              The array is ordered with a dictionary of properties for each entry in the provider chain from this
    *              service towards the root.
    * @param       propertyKeys If only certain property values are need, they may be passed in this array.
    * @param       properties Returned, retained array of dictionaries of properties or NULL. The caller should release
    *              this array.
    * @return      kIOReturnSuccess on success. See IOReturn.h for error codes.
    */
	virtual kern_return_t
	CopyProviderProperties(
		OSArray  * propertyKeys,
		OSArray ** properties);

   /*!
    * @brief       Reduce power saving modes in the system in order to provide decreased latency
	*			   to hardware DMA requests.
    * @discussion  When the system enters lower power states DMA access to memory may be affected.
	*			   The best way by far to handle this is to change how you schedule your time-critical DMA operations in
	*			   your driver such that an occasional delay will not affect the proper functioning of your device.
	*			   However, if this is not possible, your driver can inform power management when a time-critical transfer
	*			   begins and ends so that the system will not enter the lowest power states during that time. To do this,
	*			   pass a value to requireMaxBusStall that informs power management of the maximum memory access latency in
	*			   nanoseconds that can be tolerated by the driver. This value is hardware dependent and is related to the
	*			   amount of buffering available in the hardware.
	*			   Supported values are given by the kIOMaxBusStall* enum in IOTypes.h
	*			   Pass the largest value possible that works for your device. This will minimize power
	*			   consumption and maximize battery life by still allowing some level of CPU power management.
    * @param       maxBusStall A value from the kIOMaxBusStall* enum in IOTypes.h
    * @return      kIOReturnSuccess on success. See IOReturn.h for error codes.
    */
	virtual kern_return_t
	RequireMaxBusStall(
		uint64_t maxBusStall);

	/*! @function AdjustBusy
	 * @discussion Adjust the busy state of this service by applying a delta to the current busy state.
	 *             Adjusting the busy state of a service to or from zero will change the provider's busy state by one, in the same direction.
	 * @param       delta  The delta value to apply to the busy state.
	 * @return      kIOReturnSuccess on success. See IOReturn.h for error codes.
	 */
	virtual kern_return_t
	AdjustBusy(int32_t delta);

	/*! @function GetBusyState
	 * @discussion Get the busy state of this service.
	 * @param      busyState The returned busy state.
	 * @return     kIOReturnSuccess on success. See IOReturn.h for error codes.
	 */
	virtual kern_return_t
	GetBusyState(uint32_t *busyState);

   /*!
    * @brief       Post an event to CoreAnalytics.
    * @discussion  Post an event to CoreAnalytics. See the CoreAnalytics documentation for
    *              details.
    * @param       options No options currently defined pass zero.
    * @param       eventName See the CoreAnalytics documentation for details.
    * @param       eventPayload See the CoreAnalytics documentation for details.
    * @return      kIOReturnSuccess on success. See IOReturn.h for error codes.
    */
	virtual kern_return_t
	CoreAnalyticsSendEvent(
		uint64_t       options,
		OSString     * eventName,
		OSDictionary * eventPayload);

	/*! @function IOCreatePropertyMatchingDictionary
	 *   @abstract Construct a matching dictionary for property matching.
	 */
	static OSDictionary *
	CreatePropertyMatchingDictionary(const char * key, OSObjectPtr value, OSDictionary * matching) LOCALONLY;

	/*! @function IOCreatePropertyMatchingDictionary
	 *   @abstract Construct a matching dictionary for property matching.
	 */
	static OSDictionary *
	CreatePropertyMatchingDictionary(const char * key, const char * stringValue, OSDictionary * matching) LOCALONLY;

	/*! @function IOCreateKernelClassMatchingDictionary
	 *   @abstract Construct a matching dictionary for kernel class matching.
	 */
	static OSDictionary *
	CreateKernelClassMatchingDictionary(OSString * className, OSDictionary * matching) LOCALONLY;

	/*! @function IOCreateKernelClassMatchingDictionary
	 *   @abstract Construct a matching dictionary for kernel class matching.
	 */
	static OSDictionary *
	CreateKernelClassMatchingDictionary(const char * className, OSDictionary * matching) LOCALONLY;

	/*! @function IOCreateUserClassMatchingDictionary
	 *   @abstract Construct a matching dictionary for user class matching.
	 */
	static OSDictionary *
	CreateUserClassMatchingDictionary(OSString * className, OSDictionary * matching) LOCALONLY;

	/*! @function IOCreateUserClassMatchingDictionary
	 *   @abstract Construct a matching dictionary for user class matching.
	 */
	static OSDictionary *
	CreateUserClassMatchingDictionary(const char * className, OSDictionary * matching) LOCALONLY;

	/*! @function IOCreateNameMatchingDictionary
	 *   @abstract Construct a matching dictionary for IOService name matching.
	 */
	static OSDictionary *
	CreateNameMatchingDictionary(OSString * serviceName, OSDictionary * matching) LOCALONLY;

	/*! @function IOCreateNameMatchingDictionary
	 *   @abstract Construct a matching dictionary for IOService name matching.
	 */
	static OSDictionary *
	CreateNameMatchingDictionary(const char * serviceName, OSDictionary * matching) LOCALONLY;

	/*! @function UpdateReport
	 *  @abstract update an IOReporting subscription by reading out channel data.
	 */
	virtual IOReturn UpdateReport(OSData *channels, uint32_t action,
                                   uint32_t *outElementCount,
                                   uint64_t offset, uint64_t capacity,
                                   IOMemoryDescriptor *buffer);

	/*! @function ConfigureReport
	*   @abstract Configure an IOReporting subscription
	*   @discussion outCount is counting channels for enable,disable.  It is counting
	*     elements for getDimensions
	*/
	virtual IOReturn ConfigureReport(OSData *channels, uint32_t action, uint32_t *outCount);

	/*! @function SetLegend
	 * @abstract set IORLegend and IORLegendPublic ioreg properties on this service.
	 * @discussion For use by DriverKit userspace services, since they can't set
	 *  registry properties directly.
	 */
	virtual IOReturn SetLegend(OSArray *legend, bool is_public);

	/*!
	 * @brief       Get the IORegistryEntry name.
	 * @return      kIOReturnSuccess on success. See IOReturn.h for error codes.
	 */
	virtual kern_return_t
	CopyName(OSString ** name);

	/*! @function StringFromReturn
	 *   @abstract Get a string description for an IOReturn value.
	 *   @return   kIOReturnSuccess on success. See IOReturn.h for error codes.
	 */
	virtual kern_return_t
	StringFromReturn(
		 IOReturn    retval,
		 OSString ** str);

	virtual kern_return_t
	_ClaimSystemWakeEvent(
		IOService          * device,
		uint64_t             flags,
		const IOPropertyName reason,
		OSContainer       *  details);

#if PRIVATE_WIFI_ONLY
	/*!
	 * @brief      Optionally supported external method to set properties in this service.
	 * @param      properties The properties to set.
	 * @return     kIOReturnSuccess on success. See IOReturn.h for error codes.
	 */
	virtual kern_return_t
	UserSetProperties(OSContainer * properties) LOCAL;
#endif /* PRIVATE_WIFI_ONLY */

	/*! @function RemoveProperty
	 *   @abstract Remove a property from the IOService.
	 *   @return   kIOReturnSuccess on success. See IOReturn.h for error codes.
	 */
	virtual kern_return_t
	RemoveProperty(OSString * propertyName);

	/*! @function GetProvider
	 *   @abstract Get the provider of this IOService.
	 *   @discussion The DriverKit runtime caches the provider passed to IOService::Start(IOService * provider).
	 *               This method returns the cached object.
	 */
	IOService *
	GetProvider() const LOCALONLY;

   /*!
    * @function CopySystemStateNotificationService
    * @abstract Obtain the system state notification service.
    * @param    service Return IOService object with +1 retain count, to be released
    *           by the caller.
    * @return   kIOReturnSuccess on success. See IOReturn.h for error codes.
	*/
	virtual kern_return_t
	CopySystemStateNotificationService(IOService ** service);

   /*!
    * @function StateNotificationItemCreate
    * @abstract Create a state notification item.
    * @param    itemName name of the item.
    * @param    schema dictionary describing behaviors for the item. Keys are defined in
    *           IOKitKeys.h kIOStateNotification*
    * @return   kIOReturnSuccess on success. See IOReturn.h for error codes.
	*/
	virtual kern_return_t
	StateNotificationItemCreate(OSString * itemName, OSDictionary * schema);

   /*!
    * @function StateNotificationItemSet
    * @abstract Set the value of a state notification item.
    * @param    itemName name of the item.
    * @param    value dictionary value for the item, item creator to define.
    * @return   kIOReturnSuccess on success. See IOReturn.h for error codes.
	*/
	virtual kern_return_t
	StateNotificationItemSet(OSString * itemName, OSDictionary * value);

   /*!
    * @function StateNotificationItemCopy
    * @abstract Set the value of a state notification item.
    * @param    itemName name of the item.
    * @param    value dictionary value for the item, item creator to define.
    * @return   kIOReturnSuccess on success. See IOReturn.h for error codes.
	*/
	virtual kern_return_t
	StateNotificationItemCopy(OSString * itemName, OSDictionary ** value);

private:
	virtual void
	Stop_async(
		IOService          * provider) LOCAL;

	virtual kern_return_t
	_NewUserClient(
		uint32_t type,
		OSDictionary *  entitlements,
		IOUserClient ** userClient) LOCAL;
};

#endif /* ! _IOKIT_UIOSERVICE_H */