/*
* 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 Add an IOService created by Create() to the power manangement tree.
* @discussion IOService objects created by matching on a provider are always added to the power management tree.
* Any IOService created with the Create() API is not, but may be added by calling this method.
* @return kIOReturnSuccess on success. See IOReturn.h for error codes.
*/
virtual kern_return_t
JoinPMTree(void);
/*!
* @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;
/*!
* @brief Send the kIOMessageServicePropertyChange message
* @return kIOReturnSuccess on success. See IOReturn.h for error codes.
*/
virtual kern_return_t
SendIOMessageServicePropertyChange();
const char *
StringFromReturn(
IOReturn retval) LOCALONLY;
#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 */