1/*
2 * Copyright (C) 2006-2017 Oracle Corporation
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 * OTHER DEALINGS IN THE SOFTWARE.
21 */
22
23
24#ifndef ___VBox_Graphics_HGSMI_h
25#define ___VBox_Graphics_HGSMI_h
26
27#include "VBoxVideoIPRT.h"
28
29#include "HGSMIDefs.h"
30#include "HGSMIChannels.h"
31#include "HGSMIMemAlloc.h"
32
33/*
34 * Basic mechanism for the HGSMI is to prepare and pass data buffer to the host and the guest.
35 * Data inside these buffers are opaque for the HGSMI and are interpreted by higher levels.
36 *
37 * Every shared memory buffer passed between the guest/host has the following structure:
38 *
39 * HGSMIBUFFERHEADER header;
40 * uint8_t data[header.u32BufferSize];
41 * HGSMIBUFFERTAIL tail;
42 *
43 * Note: Offset of the 'header' in the memory is used for virtual hardware IO.
44 *
45 * Buffers are verifyed using the offset and the content of the header and the tail,
46 * which are constant during a call.
47 *
48 * Invalid buffers are ignored.
49 *
50 * Actual 'data' is not verifyed, as it is expected that the data can be changed by the
51 * called function.
52 *
53 * Since only the offset of the buffer is passed in a IO operation, the header and tail
54 * must contain:
55 *     * size of data in this buffer;
56 *     * checksum for buffer verification.
57 *
58 * For segmented transfers:
59 *     * the sequence identifier;
60 *     * offset of the current segment in the sequence;
61 *     * total bytes in the transfer.
62 *
63 * Additionally contains:
64 *     * the channel ID;
65 *     * the channel information.
66 */
67
68typedef struct HGSMIHEAP
69{
70    HGSMIAREA area; /* Description. */
71    HGSMIMADATA ma; /* Memory allocator */
72} HGSMIHEAP;
73
74/* The size of the array of channels. Array indexes are uint8_t. Note: the value must not be changed. */
75#define HGSMI_NUMBER_OF_CHANNELS 0x100
76
77/* Channel handler called when the guest submits a buffer. */
78typedef DECLCALLBACK(int) FNHGSMICHANNELHANDLER(void *pvHandler, uint16_t u16ChannelInfo, void *pvBuffer, HGSMISIZE cbBuffer);
79typedef FNHGSMICHANNELHANDLER *PFNHGSMICHANNELHANDLER;
80
81/* Information about a handler: pfn + context. */
82typedef struct _HGSMICHANNELHANDLER
83{
84    PFNHGSMICHANNELHANDLER pfnHandler;
85    void *pvHandler;
86} HGSMICHANNELHANDLER;
87
88/* Channel description. */
89typedef struct _HGSMICHANNEL
90{
91    HGSMICHANNELHANDLER handler;       /* The channel handler. */
92    const char *pszName;               /* NULL for hardcoded channels or RTStrDup'ed name. */
93    uint8_t u8Channel;                 /* The channel id, equal to the channel index in the array. */
94    uint8_t u8Flags;                   /* HGSMI_CH_F_* */
95} HGSMICHANNEL;
96
97typedef struct _HGSMICHANNELINFO
98{
99    HGSMICHANNEL Channels[HGSMI_NUMBER_OF_CHANNELS]; /* Channel handlers indexed by the channel id.
100                                                      * The array is accessed under the instance lock.
101                                                      */
102}  HGSMICHANNELINFO;
103
104
105RT_C_DECLS_BEGIN
106
107DECLINLINE(HGSMIBUFFERHEADER *) HGSMIBufferHeaderFromPtr(void *pvBuffer)
108{
109    return (HGSMIBUFFERHEADER *)pvBuffer;
110}
111
112DECLINLINE(uint8_t *) HGSMIBufferDataFromPtr(void *pvBuffer)
113{
114    return (uint8_t *)pvBuffer + sizeof(HGSMIBUFFERHEADER);
115}
116
117DECLINLINE(HGSMIBUFFERTAIL *) HGSMIBufferTailFromPtr(void *pvBuffer,
118                                                     uint32_t u32DataSize)
119{
120    return (HGSMIBUFFERTAIL *)(HGSMIBufferDataFromPtr(pvBuffer) + u32DataSize);
121}
122
123DECLINLINE(HGSMISIZE) HGSMIBufferMinimumSize(void)
124{
125    return sizeof(HGSMIBUFFERHEADER) + sizeof(HGSMIBUFFERTAIL);
126}
127
128DECLINLINE(HGSMIBUFFERHEADER *) HGSMIBufferHeaderFromData(const void *pvData)
129{
130    return (HGSMIBUFFERHEADER *)((uint8_t *)pvData - sizeof(HGSMIBUFFERHEADER));
131}
132
133DECLINLINE(HGSMISIZE) HGSMIBufferRequiredSize(uint32_t u32DataSize)
134{
135    return HGSMIBufferMinimumSize() + u32DataSize;
136}
137
138DECLINLINE(HGSMIOFFSET) HGSMIPointerToOffset(const HGSMIAREA *pArea,
139                                             const void *pv)
140{
141    return pArea->offBase + (HGSMIOFFSET)((uint8_t *)pv - pArea->pu8Base);
142}
143
144DECLINLINE(void *) HGSMIOffsetToPointer(const HGSMIAREA *pArea,
145                                        HGSMIOFFSET offBuffer)
146{
147    return pArea->pu8Base + (offBuffer - pArea->offBase);
148}
149
150DECLINLINE(uint8_t *) HGSMIBufferDataFromOffset(const HGSMIAREA *pArea,
151                                                HGSMIOFFSET offBuffer)
152{
153    void *pvBuffer = HGSMIOffsetToPointer(pArea, offBuffer);
154    return HGSMIBufferDataFromPtr(pvBuffer);
155}
156
157DECLINLINE(HGSMIOFFSET) HGSMIBufferOffsetFromData(const HGSMIAREA *pArea,
158                                                  void *pvData)
159{
160    HGSMIBUFFERHEADER *pHeader = HGSMIBufferHeaderFromData(pvData);
161    return HGSMIPointerToOffset(pArea, pHeader);
162}
163
164DECLINLINE(uint8_t *) HGSMIBufferDataAndChInfoFromOffset(const HGSMIAREA *pArea,
165                                                         HGSMIOFFSET offBuffer,
166                                                         uint16_t *pu16ChannelInfo)
167{
168    HGSMIBUFFERHEADER *pHeader = (HGSMIBUFFERHEADER *)HGSMIOffsetToPointer(pArea, offBuffer);
169    *pu16ChannelInfo = pHeader->u16ChannelInfo;
170    return HGSMIBufferDataFromPtr(pHeader);
171}
172
173uint32_t HGSMIChecksum(HGSMIOFFSET offBuffer,
174                       const HGSMIBUFFERHEADER *pHeader,
175                       const HGSMIBUFFERTAIL *pTail);
176
177int HGSMIAreaInitialize(HGSMIAREA *pArea,
178                        void *pvBase,
179                        HGSMISIZE cbArea,
180                        HGSMIOFFSET offBase);
181
182void HGSMIAreaClear(HGSMIAREA *pArea);
183
184DECLINLINE(bool) HGSMIAreaContainsOffset(const HGSMIAREA *pArea, HGSMIOFFSET off)
185{
186    return off >= pArea->offBase && off - pArea->offBase < pArea->cbArea;
187}
188
189DECLINLINE(bool) HGSMIAreaContainsPointer(const HGSMIAREA *pArea, const void *pv)
190{
191    return (uintptr_t)pv >= (uintptr_t)pArea->pu8Base && (uintptr_t)pv - (uintptr_t)pArea->pu8Base < pArea->cbArea;
192}
193
194HGSMIOFFSET HGSMIBufferInitializeSingle(const HGSMIAREA *pArea,
195                                        HGSMIBUFFERHEADER *pHeader,
196                                        HGSMISIZE cbBuffer,
197                                        uint8_t u8Channel,
198                                        uint16_t u16ChannelInfo);
199
200int HGSMIHeapSetup(HGSMIHEAP *pHeap,
201                   void *pvBase,
202                   HGSMISIZE cbArea,
203                   HGSMIOFFSET offBase,
204                   const HGSMIENV *pEnv);
205
206void HGSMIHeapDestroy(HGSMIHEAP *pHeap);
207
208void *HGSMIHeapBufferAlloc(HGSMIHEAP *pHeap,
209                           HGSMISIZE cbBuffer);
210
211void HGSMIHeapBufferFree(HGSMIHEAP *pHeap,
212                         void *pvBuf);
213
214void *HGSMIHeapAlloc(HGSMIHEAP *pHeap,
215                     HGSMISIZE cbData,
216                     uint8_t u8Channel,
217                     uint16_t u16ChannelInfo);
218
219void HGSMIHeapFree(HGSMIHEAP *pHeap,
220                   void *pvData);
221
222DECLINLINE(const HGSMIAREA *) HGSMIHeapArea(HGSMIHEAP *pHeap)
223{
224    return &pHeap->area;
225}
226
227DECLINLINE(HGSMIOFFSET) HGSMIHeapOffset(HGSMIHEAP *pHeap)
228{
229    return HGSMIHeapArea(pHeap)->offBase;
230}
231
232DECLINLINE(HGSMISIZE) HGSMIHeapSize(HGSMIHEAP *pHeap)
233{
234    return HGSMIHeapArea(pHeap)->cbArea;
235}
236
237DECLINLINE(HGSMIOFFSET) HGSMIHeapBufferOffset(HGSMIHEAP *pHeap,
238                                              void *pvData)
239{
240    return HGSMIBufferOffsetFromData(HGSMIHeapArea(pHeap), pvData);
241}
242
243HGSMICHANNEL *HGSMIChannelFindById(HGSMICHANNELINFO *pChannelInfo,
244                                   uint8_t u8Channel);
245
246int HGSMIChannelRegister(HGSMICHANNELINFO *pChannelInfo,
247                         uint8_t u8Channel,
248                         const char *pszName,
249                         PFNHGSMICHANNELHANDLER pfnChannelHandler,
250                         void *pvChannelHandler);
251
252int HGSMIBufferProcess(const HGSMIAREA *pArea,
253                       HGSMICHANNELINFO *pChannelInfo,
254                       HGSMIOFFSET offBuffer);
255RT_C_DECLS_END
256
257#endif /* !___VBox_Graphics_HGSMI_h */
258
259