1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
|
/* $Id: HGSMIBase.cpp $ */
/** @file
* VirtualBox Video driver, common code - HGSMI guest-to-host communication.
*/
/*
* Copyright (C) 2006-2023 Oracle and/or its affiliates.
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#include <HGSMIBase.h>
#include <VBoxVideoIPRT.h>
#include <VBoxVideoGuest.h>
#include <VBoxVideoVBE.h>
#include <HGSMIChannels.h>
#include <HGSMIChSetup.h>
/** Detect whether HGSMI is supported by the host. */
DECLHIDDEN(bool) VBoxHGSMIIsSupported(void)
{
uint16_t DispiId;
VBVO_PORT_WRITE_U16(VBE_DISPI_IOPORT_INDEX, VBE_DISPI_INDEX_ID);
VBVO_PORT_WRITE_U16(VBE_DISPI_IOPORT_DATA, VBE_DISPI_ID_HGSMI);
DispiId = VBVO_PORT_READ_U16(VBE_DISPI_IOPORT_DATA);
return (DispiId == VBE_DISPI_ID_HGSMI);
}
/**
* Inform the host of the location of the host flags in VRAM via an HGSMI command.
* @returns IPRT status value.
* @returns VERR_NOT_IMPLEMENTED if the host does not support the command.
* @returns VERR_NO_MEMORY if a heap allocation fails.
* @param pCtx the context of the guest heap to use.
* @param offLocation the offset chosen for the flags withing guest VRAM.
*/
DECLHIDDEN(int) VBoxHGSMIReportFlagsLocation(PHGSMIGUESTCOMMANDCONTEXT pCtx, HGSMIOFFSET offLocation)
{
/* Allocate the IO buffer. */
HGSMIBUFFERLOCATION RT_UNTRUSTED_VOLATILE_HOST *p =
(HGSMIBUFFERLOCATION RT_UNTRUSTED_VOLATILE_HOST *)VBoxHGSMIBufferAlloc(pCtx, sizeof(*p), HGSMI_CH_HGSMI,
HGSMI_CC_HOST_FLAGS_LOCATION);
if (!p)
return VERR_NO_MEMORY;
/* Prepare data to be sent to the host. */
p->offLocation = offLocation;
p->cbLocation = sizeof(HGSMIHOSTFLAGS);
/* No need to check that the buffer is valid as we have just allocated it. */
VBoxHGSMIBufferSubmit(pCtx, p);
/* Free the IO buffer. */
VBoxHGSMIBufferFree(pCtx, p);
return VINF_SUCCESS;
}
/**
* Notify the host of HGSMI-related guest capabilities via an HGSMI command.
* @returns IPRT status value.
* @returns VERR_NOT_IMPLEMENTED if the host does not support the command.
* @returns VERR_NO_MEMORY if a heap allocation fails.
* @param pCtx the context of the guest heap to use.
* @param fCaps the capabilities to report, see VBVACAPS.
*/
DECLHIDDEN(int) VBoxHGSMISendCapsInfo(PHGSMIGUESTCOMMANDCONTEXT pCtx, uint32_t fCaps)
{
/* Allocate the IO buffer. */
VBVACAPS RT_UNTRUSTED_VOLATILE_HOST *p =
(VBVACAPS RT_UNTRUSTED_VOLATILE_HOST *)VBoxHGSMIBufferAlloc(pCtx, sizeof(*p), HGSMI_CH_VBVA, VBVA_INFO_CAPS);
if (!p)
return VERR_NO_MEMORY;
/* Prepare data to be sent to the host. */
p->rc = VERR_NOT_IMPLEMENTED;
p->fCaps = fCaps;
/* No need to check that the buffer is valid as we have just allocated it. */
VBoxHGSMIBufferSubmit(pCtx, p);
AssertRC(p->rc);
/* Free the IO buffer. */
VBoxHGSMIBufferFree(pCtx, p);
return p->rc;
}
/**
* Get the information needed to map the basic communication structures in
* device memory into our address space. All pointer parameters are optional.
*
* @param cbVRAM how much video RAM is allocated to the device
* @param poffVRAMBaseMapping where to save the offset from the start of the
* device VRAM of the whole area to map
* @param pcbMapping where to save the mapping size
* @param poffGuestHeapMemory where to save the offset into the mapped area
* of the guest heap backing memory
* @param pcbGuestHeapMemory where to save the size of the guest heap
* backing memory
* @param poffHostFlags where to save the offset into the mapped area
* of the host flags
*/
DECLHIDDEN(void) VBoxHGSMIGetBaseMappingInfo(uint32_t cbVRAM,
uint32_t *poffVRAMBaseMapping,
uint32_t *pcbMapping,
uint32_t *poffGuestHeapMemory,
uint32_t *pcbGuestHeapMemory,
uint32_t *poffHostFlags)
{
AssertPtrNullReturnVoid(poffVRAMBaseMapping);
AssertPtrNullReturnVoid(pcbMapping);
AssertPtrNullReturnVoid(poffGuestHeapMemory);
AssertPtrNullReturnVoid(pcbGuestHeapMemory);
AssertPtrNullReturnVoid(poffHostFlags);
if (poffVRAMBaseMapping)
*poffVRAMBaseMapping = cbVRAM - VBVA_ADAPTER_INFORMATION_SIZE;
if (pcbMapping)
*pcbMapping = VBVA_ADAPTER_INFORMATION_SIZE;
if (poffGuestHeapMemory)
*poffGuestHeapMemory = 0;
if (pcbGuestHeapMemory)
*pcbGuestHeapMemory = VBVA_ADAPTER_INFORMATION_SIZE
- sizeof(HGSMIHOSTFLAGS);
if (poffHostFlags)
*poffHostFlags = VBVA_ADAPTER_INFORMATION_SIZE
- sizeof(HGSMIHOSTFLAGS);
}
/**
* Query the host for an HGSMI configuration parameter via an HGSMI command.
* @returns iprt status value
* @param pCtx the context containing the heap used
* @param u32Index the index of the parameter to query,
* @see VBVACONF32::u32Index
* @param pulValue where to store the value of the parameter on success
*/
DECLHIDDEN(int) VBoxQueryConfHGSMI(PHGSMIGUESTCOMMANDCONTEXT pCtx, uint32_t u32Index, uint32_t *pulValue)
{
VBVACONF32 *p;
/* Allocate the IO buffer. */
p = (VBVACONF32 *)VBoxHGSMIBufferAlloc(pCtx, sizeof(*p), HGSMI_CH_VBVA, VBVA_QUERY_CONF32);
if (!p)
return VERR_NO_MEMORY;
/* Prepare data to be sent to the host. */
p->u32Index = u32Index;
p->u32Value = UINT32_MAX;
/* No need to check that the buffer is valid as we have just allocated it. */
VBoxHGSMIBufferSubmit(pCtx, p);
*pulValue = p->u32Value;
/* Free the IO buffer. */
VBoxHGSMIBufferFree(pCtx, p);
return VINF_SUCCESS;
}
/**
* Pass the host a new mouse pointer shape via an HGSMI command.
*
* @returns success or failure
* @param pCtx the context containing the heap to be used
* @param fFlags cursor flags, @see VMMDevReqMousePointer::fFlags
* @param cHotX horizontal position of the hot spot
* @param cHotY vertical position of the hot spot
* @param cWidth width in pixels of the cursor
* @param cHeight height in pixels of the cursor
* @param pPixels pixel data, @see VMMDevReqMousePointer for the format
* @param cbLength size in bytes of the pixel data
*/
DECLHIDDEN(int) VBoxHGSMIUpdatePointerShape(PHGSMIGUESTCOMMANDCONTEXT pCtx, uint32_t fFlags,
uint32_t cHotX, uint32_t cHotY, uint32_t cWidth, uint32_t cHeight,
uint8_t *pPixels, uint32_t cbLength)
{
VBVAMOUSEPOINTERSHAPE *p;
uint32_t cbPixels = 0;
int rc;
if (fFlags & VBOX_MOUSE_POINTER_SHAPE)
{
/*
* Size of the pointer data:
* sizeof (AND mask) + sizeof (XOR_MASK)
*/
cbPixels = ((((cWidth + 7) / 8) * cHeight + 3) & ~3)
+ cWidth * 4 * cHeight;
if (cbPixels > cbLength)
return VERR_INVALID_PARAMETER;
/*
* If shape is supplied, then always create the pointer visible.
* See comments in 'vboxUpdatePointerShape'
*/
fFlags |= VBOX_MOUSE_POINTER_VISIBLE;
}
/* Allocate the IO buffer. */
p = (VBVAMOUSEPOINTERSHAPE *)VBoxHGSMIBufferAlloc(pCtx, sizeof(*p) + cbPixels, HGSMI_CH_VBVA,
VBVA_MOUSE_POINTER_SHAPE);
if (!p)
return VERR_NO_MEMORY;
/* Prepare data to be sent to the host. */
/* Will be updated by the host. */
p->i32Result = VINF_SUCCESS;
/* We have our custom flags in the field */
p->fu32Flags = fFlags;
p->u32HotX = cHotX;
p->u32HotY = cHotY;
p->u32Width = cWidth;
p->u32Height = cHeight;
if (cbPixels)
/* Copy the actual pointer data. */
memcpy (p->au8Data, pPixels, cbPixels);
/* No need to check that the buffer is valid as we have just allocated it. */
VBoxHGSMIBufferSubmit(pCtx, p);
rc = p->i32Result;
/* Free the IO buffer. */
VBoxHGSMIBufferFree(pCtx, p);
return rc;
}
/**
* Report the guest cursor position. The host may wish to use this information
* to re-position its own cursor (though this is currently unlikely). The
* current host cursor position is returned.
* @param pCtx The context containing the heap used.
* @param fReportPosition Are we reporting a position?
* @param x Guest cursor X position.
* @param y Guest cursor Y position.
* @param pxHost Host cursor X position is stored here. Optional.
* @param pyHost Host cursor Y position is stored here. Optional.
* @returns iprt status code.
* @returns VERR_NO_MEMORY HGSMI heap allocation failed.
*/
DECLHIDDEN(int) VBoxHGSMICursorPosition(PHGSMIGUESTCOMMANDCONTEXT pCtx, bool fReportPosition,
uint32_t x, uint32_t y, uint32_t *pxHost, uint32_t *pyHost)
{
VBVACURSORPOSITION *p;
/* Allocate the IO buffer. */
p = (VBVACURSORPOSITION *)VBoxHGSMIBufferAlloc(pCtx, sizeof(*p), HGSMI_CH_VBVA,
VBVA_CURSOR_POSITION);
if (!p)
return VERR_NO_MEMORY;
/* Prepare data to be sent to the host. */
p->fReportPosition = fReportPosition;
p->x = x;
p->y = y;
/* No need to check that the buffer is valid as we have just allocated it. */
VBoxHGSMIBufferSubmit(pCtx, p);
if (pxHost)
*pxHost = p->x;
if (pyHost)
*pyHost = p->y;
/* Free the IO buffer. */
VBoxHGSMIBufferFree(pCtx, p);
return VINF_SUCCESS;
}
/**
* @todo Mouse pointer position to be read from VMMDev memory, address of the
* memory region can be queried from VMMDev via an IOCTL. This VMMDev memory
* region will contain host information which is needed by the guest.
*
* Reading will not cause a switch to the host.
*
* Have to take into account:
* * synchronization: host must write to the memory only from EMT,
* large structures must be read under flag, which tells the host
* that the guest is currently reading the memory (OWNER flag?).
* * guest writes: may be allocate a page for the host info and make
* the page readonly for the guest.
* * the information should be available only for additions drivers.
* * VMMDev additions driver will inform the host which version of the info
* it expects, host must support all versions.
*/
|