1*bbb1b6f9SApple OSS Distributions /* 2*bbb1b6f9SApple OSS Distributions * Copyright (c) 1998-2019 Apple Inc. All rights reserved. 3*bbb1b6f9SApple OSS Distributions * 4*bbb1b6f9SApple OSS Distributions * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ 5*bbb1b6f9SApple OSS Distributions * 6*bbb1b6f9SApple OSS Distributions * This file contains Original Code and/or Modifications of Original Code 7*bbb1b6f9SApple OSS Distributions * as defined in and that are subject to the Apple Public Source License 8*bbb1b6f9SApple OSS Distributions * Version 2.0 (the 'License'). You may not use this file except in 9*bbb1b6f9SApple OSS Distributions * compliance with the License. The rights granted to you under the License 10*bbb1b6f9SApple OSS Distributions * may not be used to create, or enable the creation or redistribution of, 11*bbb1b6f9SApple OSS Distributions * unlawful or unlicensed copies of an Apple operating system, or to 12*bbb1b6f9SApple OSS Distributions * circumvent, violate, or enable the circumvention or violation of, any 13*bbb1b6f9SApple OSS Distributions * terms of an Apple operating system software license agreement. 14*bbb1b6f9SApple OSS Distributions * 15*bbb1b6f9SApple OSS Distributions * Please obtain a copy of the License at 16*bbb1b6f9SApple OSS Distributions * http://www.opensource.apple.com/apsl/ and read it before using this file. 17*bbb1b6f9SApple OSS Distributions * 18*bbb1b6f9SApple OSS Distributions * The Original Code and all software distributed under the License are 19*bbb1b6f9SApple OSS Distributions * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 20*bbb1b6f9SApple OSS Distributions * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 21*bbb1b6f9SApple OSS Distributions * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 22*bbb1b6f9SApple OSS Distributions * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 23*bbb1b6f9SApple OSS Distributions * Please see the License for the specific language governing rights and 24*bbb1b6f9SApple OSS Distributions * limitations under the License. 25*bbb1b6f9SApple OSS Distributions * 26*bbb1b6f9SApple OSS Distributions * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ 27*bbb1b6f9SApple OSS Distributions */ 28*bbb1b6f9SApple OSS Distributions 29*bbb1b6f9SApple OSS Distributions #ifndef _IOKIT_IODATAQUEUE_H 30*bbb1b6f9SApple OSS Distributions #define _IOKIT_IODATAQUEUE_H 31*bbb1b6f9SApple OSS Distributions 32*bbb1b6f9SApple OSS Distributions #ifndef DISABLE_DATAQUEUE_WARNING 33*bbb1b6f9SApple OSS Distributions #warning "IODataQueue is deprecated due to security issues in its interfaces, please use IOSharedDataQueue instead" 34*bbb1b6f9SApple OSS Distributions #endif 35*bbb1b6f9SApple OSS Distributions 36*bbb1b6f9SApple OSS Distributions #include <libkern/c++/OSPtr.h> 37*bbb1b6f9SApple OSS Distributions #include <libkern/c++/OSObject.h> 38*bbb1b6f9SApple OSS Distributions #include <libkern/OSTypes.h> 39*bbb1b6f9SApple OSS Distributions #include <mach/port.h> 40*bbb1b6f9SApple OSS Distributions #include <mach/message.h> 41*bbb1b6f9SApple OSS Distributions 42*bbb1b6f9SApple OSS Distributions typedef struct _IODataQueueMemory IODataQueueMemory; 43*bbb1b6f9SApple OSS Distributions class IOMemoryDescriptor; 44*bbb1b6f9SApple OSS Distributions 45*bbb1b6f9SApple OSS Distributions struct _notifyMsg { 46*bbb1b6f9SApple OSS Distributions mach_msg_header_t h; 47*bbb1b6f9SApple OSS Distributions }; 48*bbb1b6f9SApple OSS Distributions 49*bbb1b6f9SApple OSS Distributions 50*bbb1b6f9SApple OSS Distributions #ifdef dequeue 51*bbb1b6f9SApple OSS Distributions #undef dequeue 52*bbb1b6f9SApple OSS Distributions #endif 53*bbb1b6f9SApple OSS Distributions #ifdef enqueue 54*bbb1b6f9SApple OSS Distributions #undef enqueue 55*bbb1b6f9SApple OSS Distributions #endif 56*bbb1b6f9SApple OSS Distributions 57*bbb1b6f9SApple OSS Distributions /*! 58*bbb1b6f9SApple OSS Distributions * @class IODataQueue : public OSObject 59*bbb1b6f9SApple OSS Distributions * @abstract A generic queue designed to pass data from the kernel to a user process. 60*bbb1b6f9SApple OSS Distributions * @discussion The IODataQueue class is designed to allow kernel code to queue data to a user process. IODataQueue objects are designed to be used in a single producer / single consumer situation. As such, there are no locks on the data itself. Because the kernel enqueue and user-space dequeue methods follow a strict set of guidelines, no locks are necessary to maintain the integrity of the data struct. 61*bbb1b6f9SApple OSS Distributions * 62*bbb1b6f9SApple OSS Distributions * <br>Each data entry can be variable sized, but the entire size of the queue data region (including overhead for each entry) must be specified up front. 63*bbb1b6f9SApple OSS Distributions * 64*bbb1b6f9SApple OSS Distributions * <br>In order for the IODataQueue instance to notify the user process that data is available, a notification mach port must be set. When the queue is empty and a new entry is added, a message is sent to the specified port. 65*bbb1b6f9SApple OSS Distributions * 66*bbb1b6f9SApple OSS Distributions * <br>User client code exists in the IOKit framework that facilitates the creation of the receive notification port as well as the listen process for new data available notifications. 67*bbb1b6f9SApple OSS Distributions * 68*bbb1b6f9SApple OSS Distributions * <br>In order to make the data queue memory available to a user process, the method getMemoryDescriptor() must be used to get an IOMemoryDescriptor instance that can be mapped into a user process. Typically, the clientMemoryForType() method on an IOUserClient instance will be used to request the IOMemoryDescriptor and then return it to be mapped into the user process. 69*bbb1b6f9SApple OSS Distributions */ 70*bbb1b6f9SApple OSS Distributions #ifndef DISABLE_DATAQUEUE_WARNING 71*bbb1b6f9SApple OSS Distributions class __attribute__((deprecated)) IODataQueue: public OSObject 72*bbb1b6f9SApple OSS Distributions #else 73*bbb1b6f9SApple OSS Distributions class IODataQueue : public OSObject 74*bbb1b6f9SApple OSS Distributions #endif 75*bbb1b6f9SApple OSS Distributions { 76*bbb1b6f9SApple OSS Distributions OSDeclareDefaultStructors(IODataQueue); 77*bbb1b6f9SApple OSS Distributions 78*bbb1b6f9SApple OSS Distributions protected: 79*bbb1b6f9SApple OSS Distributions IODataQueueMemory * dataQueue; 80*bbb1b6f9SApple OSS Distributions 81*bbb1b6f9SApple OSS Distributions void * notifyMsg; 82*bbb1b6f9SApple OSS Distributions 83*bbb1b6f9SApple OSS Distributions virtual void free() APPLE_KEXT_OVERRIDE; 84*bbb1b6f9SApple OSS Distributions 85*bbb1b6f9SApple OSS Distributions /*! 86*bbb1b6f9SApple OSS Distributions * @function sendDataAvailableNotification 87*bbb1b6f9SApple OSS Distributions * @abstract Sends a dataAvailableNotification message to the specified mach port. 88*bbb1b6f9SApple OSS Distributions * @discussion This method sends a message to the mach port passed to setNotificationPort(). It is used to indicate that data is available in the queue. 89*bbb1b6f9SApple OSS Distributions */ 90*bbb1b6f9SApple OSS Distributions virtual void sendDataAvailableNotification(); 91*bbb1b6f9SApple OSS Distributions 92*bbb1b6f9SApple OSS Distributions public: 93*bbb1b6f9SApple OSS Distributions /*! 94*bbb1b6f9SApple OSS Distributions * @function withCapacity 95*bbb1b6f9SApple OSS Distributions * @abstract Static method that creates a new IODataQueue instance with the capacity specified in the size parameter. 96*bbb1b6f9SApple OSS Distributions * @discussion The actual size of the entire data queue memory region (to be shared into a user process) is equal to the capacity plus the IODataQueueMemory overhead. This overhead value can be determined from the DATA_QUEUE_MEMORY_HEADER_SIZE macro in <IOKit/IODataQueueShared.h>. The size of the data queue memory region must include space for the overhead of each IODataQueueEntry. This entry overhead can be determined from the DATA_QUEUE_ENTRY_HEADER_SIZE macro in <IOKit/IODataQueueShared.h>.<br> This method allocates a new IODataQueue instance and then calls initWithCapacity() with the given size parameter. If the initWithCapacity() fails, the new instance is released and zero is returned. 97*bbb1b6f9SApple OSS Distributions * @param size The size of the data queue memory region. 98*bbb1b6f9SApple OSS Distributions * @result Returns the newly allocated IODataQueue instance. Zero is returned on failure. 99*bbb1b6f9SApple OSS Distributions */ 100*bbb1b6f9SApple OSS Distributions static OSPtr<IODataQueue> withCapacity(UInt32 size __xnu_data_size); 101*bbb1b6f9SApple OSS Distributions 102*bbb1b6f9SApple OSS Distributions /*! 103*bbb1b6f9SApple OSS Distributions * @function withEntries 104*bbb1b6f9SApple OSS Distributions * @abstract Static method that creates a new IODataQueue instance with the specified number of entries of the given size. 105*bbb1b6f9SApple OSS Distributions * @discussion This method will create a new IODataQueue instance with enough capacity for numEntries of entrySize. It does account for the IODataQueueEntry overhead for each entry. Note that the numEntries and entrySize are simply used to determine the data region size. They do not actually restrict the size of number of entries that can be added to the queue.<br> This method allocates a new IODataQueue instance and then calls initWithEntries() with the given numEntries and entrySize parameters. If the initWithEntries() fails, the new instance is released and zero is returned. 106*bbb1b6f9SApple OSS Distributions * @param numEntries Number of entries to allocate space for. 107*bbb1b6f9SApple OSS Distributions * @param entrySize Size of each entry. 108*bbb1b6f9SApple OSS Distributions * @result Returns the newly allocated IODataQueue instance. Zero is returned on failure. 109*bbb1b6f9SApple OSS Distributions */ 110*bbb1b6f9SApple OSS Distributions static OSPtr<IODataQueue> withEntries(UInt32 numEntries, UInt32 entrySize __xnu_data_size); 111*bbb1b6f9SApple OSS Distributions 112*bbb1b6f9SApple OSS Distributions /*! 113*bbb1b6f9SApple OSS Distributions * @function initWithCapacity 114*bbb1b6f9SApple OSS Distributions * @abstract Initializes an IODataQueue instance with the capacity specified in the size parameter. 115*bbb1b6f9SApple OSS Distributions * @discussion The actual size of the entire data queue memory region (to be shared into a user process) is equal to the capacity plus the IODataQueueMemory overhead. This overhead value can be determined from the DATA_QUEUE_MEMORY_HEADER_SIZE macro in <IOKit/IODataQueueShared.h>. The size of the data queue memory region must include space for the overhead of each IODataQueueEntry. This entry overhead can be determined from the DATA_QUEUE_ENTRY_HEADER_SIZE macro in <IOKit/IODataQueueShared.h>. 116*bbb1b6f9SApple OSS Distributions * @param size The size of the data queue memory region. 117*bbb1b6f9SApple OSS Distributions * @result Returns true on success and false on failure. 118*bbb1b6f9SApple OSS Distributions */ 119*bbb1b6f9SApple OSS Distributions virtual Boolean initWithCapacity(UInt32 size); 120*bbb1b6f9SApple OSS Distributions 121*bbb1b6f9SApple OSS Distributions /*! 122*bbb1b6f9SApple OSS Distributions * @function initWithEntries 123*bbb1b6f9SApple OSS Distributions * @abstract Initializes an IODataQueue instance with the specified number of entries of the given size. 124*bbb1b6f9SApple OSS Distributions * @discussion This method will initialize an IODataQueue instance with enough capacity for numEntries of entrySize. It does account for the IODataQueueEntry overhead for each entry. Note that the numEntries and entrySize are simply used to determine the data region size. They do not actually restrict the size of number of entries that can be added to the queue.<br> This method allocates a new IODataQueue instance and then calls initWithEntries() with the given numEntries and entrySize parameters. 125*bbb1b6f9SApple OSS Distributions * @param numEntries Number of entries to allocate space for. 126*bbb1b6f9SApple OSS Distributions * @param entrySize Size of each entry. 127*bbb1b6f9SApple OSS Distributions * @result Returns true on success and false on failure. 128*bbb1b6f9SApple OSS Distributions */ 129*bbb1b6f9SApple OSS Distributions virtual Boolean initWithEntries(UInt32 numEntries, UInt32 entrySize); 130*bbb1b6f9SApple OSS Distributions 131*bbb1b6f9SApple OSS Distributions /*! 132*bbb1b6f9SApple OSS Distributions * @function enqueue 133*bbb1b6f9SApple OSS Distributions * @abstract Enqueues a new entry on the queue. 134*bbb1b6f9SApple OSS Distributions * @discussion This method adds a new data entry of dataSize to the queue. It sets the size parameter of the entry pointed to by the tail value and copies the memory pointed to by the data parameter in place in the queue. Once that is done, it moves the tail to the next available location. When attempting to add a new entry towards the end of the queue and there isn't enough space at the end, it wraps back to the beginning.<br> If the queue is empty when a new entry is added, sendDataAvailableNotification() is called to send a message to the user process that data is now available. 135*bbb1b6f9SApple OSS Distributions * @param data Pointer to the data to be added to the queue. 136*bbb1b6f9SApple OSS Distributions * @param dataSize Size of the data pointed to by data. 137*bbb1b6f9SApple OSS Distributions * @result Returns true on success and false on failure. Typically failure means that the queue is full. 138*bbb1b6f9SApple OSS Distributions */ 139*bbb1b6f9SApple OSS Distributions virtual Boolean enqueue(void *data, UInt32 dataSize); 140*bbb1b6f9SApple OSS Distributions 141*bbb1b6f9SApple OSS Distributions /*! 142*bbb1b6f9SApple OSS Distributions * @function setNotificationPort 143*bbb1b6f9SApple OSS Distributions * @abstract Creates a simple mach message targeting the mach port specified in port. 144*bbb1b6f9SApple OSS Distributions * @discussion This message is sent when data is added to an empty queue. It is to notify a user process that new data has become available. 145*bbb1b6f9SApple OSS Distributions * @param port The mach port to target with the notification message. 146*bbb1b6f9SApple OSS Distributions */ 147*bbb1b6f9SApple OSS Distributions virtual void setNotificationPort(mach_port_t port); 148*bbb1b6f9SApple OSS Distributions 149*bbb1b6f9SApple OSS Distributions /*! 150*bbb1b6f9SApple OSS Distributions * @function getMemoryDescriptor 151*bbb1b6f9SApple OSS Distributions * @abstract Returns a memory descriptor covering the IODataQueueMemory region. 152*bbb1b6f9SApple OSS Distributions * @discussion The IOMemoryDescriptor instance returned by this method is intended to be mapped into a user process. This is the memory region that the IODataQueueClient code operates on. 153*bbb1b6f9SApple OSS Distributions * @result Returns a newly allocated IOMemoryDescriptor for the IODataQueueMemory region. Returns zero on failure. 154*bbb1b6f9SApple OSS Distributions */ 155*bbb1b6f9SApple OSS Distributions virtual OSPtr<IOMemoryDescriptor> getMemoryDescriptor(); 156*bbb1b6f9SApple OSS Distributions }; 157*bbb1b6f9SApple OSS Distributions 158*bbb1b6f9SApple OSS Distributions #endif /* _IOKIT_IODATAQUEUE_H */ 159