VirtualBox

source: vbox/trunk/src/VBox/Devices/VMMDev/VBoxDev.cpp@ 4540

Last change on this file since 4540 was 4540, checked in by vboxsync, 17 years ago

Implemented notification for guest about an active VRDP connection.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 84.6 KB
Line 
1/** @file
2 *
3 * VBox Guest/VMM/host communication:
4 * Virtual communication device
5 */
6
7/*
8 * Copyright (C) 2006-2007 innotek GmbH
9 *
10 * This file is part of VirtualBox Open Source Edition (OSE), as
11 * available from http://www.virtualbox.org. This file is free software;
12 * you can redistribute it and/or modify it under the terms of the GNU
13 * General Public License as published by the Free Software Foundation,
14 * in version 2 as it comes in the "COPYING" file of the VirtualBox OSE
15 * distribution. VirtualBox OSE is distributed in the hope that it will
16 * be useful, but WITHOUT ANY WARRANTY of any kind.
17 */
18
19/* #define LOG_ENABLED */
20
21#include <stdio.h>
22#include <string.h>
23
24#define LOG_GROUP LOG_GROUP_DEV_VMM
25#include <VBox/log.h>
26
27#include <VBox/VBoxDev.h>
28#include <VBox/VBoxGuest.h>
29#include <VBox/param.h>
30#include <VBox/mm.h>
31#include <VBox/pgm.h>
32#include <VBox/err.h>
33#include <VBox/vm.h> /* for VM_IS_EMT */
34
35#include <iprt/assert.h>
36#include <iprt/time.h>
37
38#include "VMMDevState.h"
39
40#ifdef VBOX_HGCM
41#include "VMMDevHGCM.h"
42#endif
43
44#define PCIDEV_2_VMMDEVSTATE(pPciDev) ( (VMMDevState *)(pPciDev) )
45#define VMMDEVSTATE_2_DEVINS(pVMMDevState) ( (pVMMDevState)->pDevIns )
46
47#define VBOX_GUEST_ADDITIONS_VERSION_1_03(s) \
48 ((RT_HIWORD ((s)->guestInfo.additionsVersion) == 1) && \
49 (RT_LOWORD ((s)->guestInfo.additionsVersion) == 3))
50
51#define VBOX_GUEST_ADDITIONS_VERSION_OK(additionsVersion) \
52 (RT_HIWORD(additionsVersion) == RT_HIWORD(VMMDEV_VERSION) \
53 && RT_LOWORD(additionsVersion) <= RT_LOWORD(VMMDEV_VERSION))
54
55#define VBOX_GUEST_ADDITIONS_VERSION_OLD(additionsVersion) \
56 ((RT_HIWORD(additionsVersion) < RT_HIWORD(VMMDEV_VERSION) \
57 || ((RT_HIWORD(additionsVersion) == RT_HIWORD(VMMDEV_VERSION) \
58 && RT_LOWORD(additionsVersion) <= RT_LOWORD(VMMDEV_VERSION))
59
60#define VBOX_GUEST_ADDITIONS_VERSION_TOO_OLD(additionsVersion) \
61 (RT_HIWORD(additionsVersion) < RT_HIWORD(VMMDEV_VERSION))
62
63#define VBOX_GUEST_ADDITIONS_VERSION_NEW(additionsVersion) \
64 ((RT_HIWORD(additionsVersion) > RT_HIWORD(VMMDEV_VERSION) \
65 || ((RT_HIWORD(additionsVersion) == RT_HIWORD(VMMDEV_VERSION) \
66 && RT_LOWORD(additionsVersion) > RT_LOWORD(VMMDEV_VERSION))
67
68#ifndef VBOX_DEVICE_STRUCT_TESTCASE
69
70/* Whenever host wants to inform guest about something
71 * an IRQ notification will be raised.
72 *
73 * VMMDev PDM interface will contain the guest notification method.
74 *
75 * There is a 32 bit event mask which will be read
76 * by guest on an interrupt. A non zero bit in the mask
77 * means that the specific event occured and requires
78 * processing on guest side.
79 *
80 * After reading the event mask guest must issue a
81 * generic request AcknowlegdeEvents.
82 *
83 * IRQ line is set to 1 (request) if there are unprocessed
84 * events, that is the event mask is not zero.
85 *
86 * After receiving an interrupt and checking event mask,
87 * the guest must process events using the event specific
88 * mechanism.
89 *
90 * That is if mouse capabilities were changed,
91 * guest will use VMMDev_GetMouseStatus generic request.
92 *
93 * Event mask is only a set of flags indicating that guest
94 * must proceed with a procedure.
95 *
96 * Unsupported events are therefore ignored.
97 * The guest additions must inform host which events they
98 * want to receive, to avoid unnecessary IRQ processing.
99 * By default no events are signalled to guest.
100 *
101 * This seems to be fast method. It requires
102 * only one context switch for an event processing.
103 *
104 */
105
106static void vmmdevSetIRQ_Legacy_EMT (VMMDevState *pVMMDevState)
107{
108 if (!pVMMDevState->fu32AdditionsOk)
109 {
110 Log(("vmmdevSetIRQ: IRQ is not generated, guest has not yet reported to us.\n"));
111 return;
112 }
113
114 uint32_t u32IRQLevel = 0;
115
116 /* Filter unsupported events */
117 uint32_t u32EventFlags =
118 pVMMDevState->u32HostEventFlags
119 & pVMMDevState->pVMMDevRAMHC->V.V1_03.u32GuestEventMask;
120
121 Log(("vmmdevSetIRQ: u32EventFlags = 0x%08X, "
122 "pVMMDevState->u32HostEventFlags = 0x%08X, "
123 "pVMMDevState->pVMMDevRAMHC->u32GuestEventMask = 0x%08X\n",
124 u32EventFlags,
125 pVMMDevState->u32HostEventFlags,
126 pVMMDevState->pVMMDevRAMHC->V.V1_03.u32GuestEventMask));
127
128 /* Move event flags to VMMDev RAM */
129 pVMMDevState->pVMMDevRAMHC->V.V1_03.u32HostEvents = u32EventFlags;
130
131 if (u32EventFlags)
132 {
133 /* Clear host flags which will be delivered to guest. */
134 pVMMDevState->u32HostEventFlags &= ~u32EventFlags;
135 Log(("vmmdevSetIRQ: pVMMDevState->u32HostEventFlags = 0x%08X\n",
136 pVMMDevState->u32HostEventFlags));
137 u32IRQLevel = 1;
138 }
139
140 /* Set IRQ level for pin 0 */
141 /** @todo make IRQ pin configurable, at least a symbolic constant */
142 PPDMDEVINS pDevIns = VMMDEVSTATE_2_DEVINS(pVMMDevState);
143 PDMDevHlpPCISetIrqNoWait(pDevIns, 0, u32IRQLevel);
144 Log(("vmmdevSetIRQ: IRQ set %d\n", u32IRQLevel));
145}
146
147static void vmmdevMaybeSetIRQ_EMT (VMMDevState *pVMMDevState)
148{
149 PPDMDEVINS pDevIns = VMMDEVSTATE_2_DEVINS (pVMMDevState);
150
151#ifdef DEBUG_sunlover
152 Log(("vmmdevMaybeSetIRQ_EMT: u32HostEventFlags = 0x%08X, u32GuestFilterMask = 0x%08X.\n",
153 pVMMDevState->u32HostEventFlags, pVMMDevState->u32GuestFilterMask));
154#endif /* DEBUG_sunlover */
155
156 if (pVMMDevState->u32HostEventFlags & pVMMDevState->u32GuestFilterMask)
157 {
158 pVMMDevState->pVMMDevRAMHC->V.V1_04.fHaveEvents = true;
159 PDMDevHlpPCISetIrqNoWait (pDevIns, 0, 1);
160#ifdef DEBUG_sunlover
161 Log(("vmmdevMaybeSetIRQ_EMT: IRQ set.\n"));
162#endif /* DEBUG_sunlover */
163 }
164}
165
166static void vmmdevNotifyGuest_EMT (VMMDevState *pVMMDevState, uint32_t u32EventMask)
167{
168#ifdef DEBUG_sunlover
169 Log(("VMMDevNotifyGuest_EMT: u32EventMask = 0x%08X.\n", u32EventMask));
170#endif /* DEBUG_sunlover */
171
172 if (VBOX_GUEST_ADDITIONS_VERSION_1_03 (pVMMDevState))
173 {
174#ifdef DEBUG_sunlover
175 Log(("VMMDevNotifyGuest_EMT: Old additions detected.\n"));
176#endif /* DEBUG_sunlover */
177
178 pVMMDevState->u32HostEventFlags |= u32EventMask;
179 vmmdevSetIRQ_Legacy_EMT (pVMMDevState);
180 }
181 else
182 {
183#ifdef DEBUG_sunlover
184 Log(("VMMDevNotifyGuest_EMT: New additions detected.\n"));
185#endif /* DEBUG_sunlover */
186
187 if (!pVMMDevState->fu32AdditionsOk)
188 {
189 pVMMDevState->u32HostEventFlags |= u32EventMask;
190 Log(("vmmdevNotifyGuest_EMT: IRQ is not generated, guest has not yet reported to us.\n"));
191 return;
192 }
193
194 const bool fHadEvents =
195 (pVMMDevState->u32HostEventFlags & pVMMDevState->u32GuestFilterMask) != 0;
196
197#ifdef DEBUG_sunlover
198 Log(("VMMDevNotifyGuest_EMT: fHadEvents = %d, u32HostEventFlags = 0x%08X, u32GuestFilterMask = 0x%08X.\n",
199 fHadEvents, pVMMDevState->u32HostEventFlags, pVMMDevState->u32GuestFilterMask));
200#endif /* DEBUG_sunlover */
201
202 pVMMDevState->u32HostEventFlags |= u32EventMask;
203
204 if (!fHadEvents)
205 vmmdevMaybeSetIRQ_EMT (pVMMDevState);
206 }
207}
208
209static void vmmdevCtlGuestFilterMask_EMT (VMMDevState *pVMMDevState,
210 uint32_t u32OrMask,
211 uint32_t u32NotMask)
212{
213 const bool fHadEvents =
214 (pVMMDevState->u32HostEventFlags & pVMMDevState->u32GuestFilterMask) != 0;
215
216 Log(("vmmdevCtlGuestFilterMask_EMT: u32OrMask = 0x%08X, u32NotMask = 0x%08X, fHadEvents = %d.\n", u32OrMask, u32NotMask, fHadEvents));
217 if (fHadEvents)
218 {
219 if (!pVMMDevState->fNewGuestFilterMask)
220 pVMMDevState->u32NewGuestFilterMask = pVMMDevState->u32GuestFilterMask;
221
222 pVMMDevState->u32NewGuestFilterMask |= u32OrMask;
223 pVMMDevState->u32NewGuestFilterMask &= ~u32NotMask;
224 pVMMDevState->fNewGuestFilterMask = true;
225 }
226 else
227 {
228 pVMMDevState->u32GuestFilterMask |= u32OrMask;
229 pVMMDevState->u32GuestFilterMask &= ~u32NotMask;
230 vmmdevMaybeSetIRQ_EMT (pVMMDevState);
231 }
232}
233
234void VMMDevCtlSetGuestFilterMask (VMMDevState *pVMMDevState,
235 uint32_t u32OrMask,
236 uint32_t u32NotMask)
237{
238 PPDMDEVINS pDevIns = VMMDEVSTATE_2_DEVINS(pVMMDevState);
239 PVM pVM = PDMDevHlpGetVM(pDevIns);
240
241 Log(("VMMDevCtlSetGuestFilterMask: u32OrMask = 0x%08X, u32NotMask = 0x%08X.\n", u32OrMask, u32NotMask));
242
243 if (VM_IS_EMT(pVM))
244 {
245 vmmdevCtlGuestFilterMask_EMT (pVMMDevState, u32OrMask, u32NotMask);
246 }
247 else
248 {
249 int rc;
250 PVMREQ pReq;
251
252 rc = VMR3ReqCallVoid (pVM, &pReq, RT_INDEFINITE_WAIT,
253 (PFNRT) vmmdevCtlGuestFilterMask_EMT,
254 3, pVMMDevState, u32OrMask, u32NotMask);
255 AssertReleaseRC (rc);
256 VMR3ReqFree (pReq);
257 }
258}
259
260void VMMDevNotifyGuest (VMMDevState *pVMMDevState, uint32_t u32EventMask)
261{
262 PPDMDEVINS pDevIns = VMMDEVSTATE_2_DEVINS(pVMMDevState);
263 PVM pVM = PDMDevHlpGetVM(pDevIns);
264 int rc;
265 PVMREQ pReq;
266
267#ifdef DEBUG_sunlover
268 Log(("VMMDevNotifyGuest: u32EventMask = 0x%08X.\n", u32EventMask));
269#endif /* DEBUG_sunlover */
270
271 rc = VMR3ReqCallVoid (pVM, &pReq, RT_INDEFINITE_WAIT,
272 (PFNRT) vmmdevNotifyGuest_EMT,
273 2, pVMMDevState, u32EventMask);
274 AssertReleaseRC (rc);
275 VMR3ReqFree (pReq);
276}
277
278/**
279 * Port I/O Handler for OUT operations.
280 *
281 * @returns VBox status code.
282 *
283 * @param pDevIns The device instance.
284 * @param pvUser User argument - ignored.
285 * @param uPort Port number used for the IN operation.
286 * @param u32 The value to output.
287 * @param cb The value size in bytes.
288 */
289#undef LOG_GROUP
290#define LOG_GROUP LOG_GROUP_DEV_VMM_BACKDOOR
291
292static DECLCALLBACK(int) vmmdevBackdoorLog(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t u32, unsigned cb)
293{
294 VMMDevState *pData = PDMINS2DATA(pDevIns, VMMDevState *);
295
296 if (!pData->fBackdoorLogDisabled && cb == 1 && Port == RTLOG_DEBUG_PORT)
297 {
298
299 /* The raw version. */
300 switch (u32)
301 {
302 case '\r': Log2(("vmmdev: <return>\n")); break;
303 case '\n': Log2(("vmmdev: <newline>\n")); break;
304 case '\t': Log2(("vmmdev: <tab>\n")); break;
305 default: Log2(("vmmdev: %c (%02x)\n", u32, u32)); break;
306 }
307
308 /* The readable, buffered version. */
309 if (u32 == '\n' || u32 == '\r')
310 {
311 pData->szMsg[pData->iMsg] = '\0';
312 if (pData->iMsg)
313 LogRel(("Guest Log: %s\n", pData->szMsg));
314 pData->iMsg = 0;
315 }
316 else
317 {
318 if (pData->iMsg >= sizeof(pData->szMsg)-1)
319 {
320 pData->szMsg[pData->iMsg] = '\0';
321 LogRel(("Guest Log: %s\n", pData->szMsg));
322 pData->iMsg = 0;
323 }
324 pData->szMsg[pData->iMsg] = (char )u32;
325 pData->szMsg[++pData->iMsg] = '\0';
326 }
327 }
328 return VINF_SUCCESS;
329}
330#undef LOG_GROUP
331#define LOG_GROUP LOG_GROUP_DEV_VMM
332
333#ifdef TIMESYNC_BACKDOOR
334/**
335 * Port I/O Handler for OUT operations.
336 *
337 * @returns VBox status code.
338 *
339 * @param pDevIns The device instance.
340 * @param pvUser User argument - ignored.
341 * @param uPort Port number used for the IN operation.
342 * @param u32 The value to output.
343 * @param cb The value size in bytes.
344 */
345static DECLCALLBACK(int) vmmdevTimesyncBackdoorWrite(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t u32, unsigned cb)
346{
347 NOREF(pvUser);
348 if (cb == 4)
349 {
350 VMMDevState *pData = PDMINS2DATA(pDevIns, VMMDevState *);
351 switch (u32)
352 {
353 case 0:
354 pData->fTimesyncBackdoorLo = false;
355 break;
356 case 1:
357 pData->fTimesyncBackdoorLo = true;
358 }
359 return VINF_SUCCESS;
360
361 }
362 return VINF_SUCCESS;
363}
364
365/**
366 * Port I/O Handler for backdoor timesync IN operations.
367 *
368 * @returns VBox status code.
369 *
370 * @param pDevIns The device instance.
371 * @param pvUser User argument - ignored.
372 * @param uPort Port number used for the IN operation.
373 * @param pu32 Where to store the result.
374 * @param cb Number of bytes read.
375 */
376static DECLCALLBACK(int) vmmdevTimesyncBackdoorRead(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t *pu32, unsigned cb)
377{
378 int rc;
379 NOREF(pvUser);
380 if (cb == 4)
381 {
382 VMMDevState *pData = PDMINS2DATA(pDevIns, VMMDevState *);
383 RTTIMESPEC now;
384
385 if (pData->fTimesyncBackdoorLo)
386 {
387 *pu32 = (uint32_t)(pData->hostTime & (uint64_t)0xFFFFFFFF);
388 }
389 else
390 {
391 pData->hostTime = RTTimeSpecGetMilli(PDMDevHlpUTCNow(pDevIns, &now));
392 *pu32 = (uint32_t)(pData->hostTime >> 32);
393 }
394 rc = VINF_SUCCESS;
395 }
396 else
397 rc = VERR_IOM_IOPORT_UNUSED;
398 return rc;
399}
400#endif /* TIMESYNC_BACKDOOR */
401
402/**
403 * Port I/O Handler for the generic request interface
404 * @see FNIOMIOPORTOUT for details.
405 */
406static DECLCALLBACK(int) vmmdevRequestHandler(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t u32, unsigned cb)
407{
408 VMMDevState *pData = (VMMDevState*)pvUser;
409 int rcRet = VINF_SUCCESS;
410 int rc;
411
412 /*
413 * The caller has passed the guest context physical address
414 * of the request structure. Get the corresponding host virtual
415 * address.
416 */
417 VMMDevRequestHeader *requestHeader = NULL;
418 rc = PDMDevHlpPhys2HCVirt(pDevIns, (RTGCPHYS)u32, 0, (PRTHCPTR)&requestHeader);
419 if (VBOX_FAILURE(rc) || !requestHeader)
420 {
421 AssertMsgFailed(("VMMDev could not convert guest physical address to host virtual! rc = %Vrc\n", rc));
422 return VINF_SUCCESS;
423 }
424
425 /* the structure size must be greater or equal to the header size */
426 if (requestHeader->size < sizeof(VMMDevRequestHeader))
427 {
428 Log(("VMMDev request header size too small! size = %d\n", requestHeader->size));
429 return VINF_SUCCESS;
430 }
431
432 /* check the version of the header structure */
433 if (requestHeader->version != VMMDEV_REQUEST_HEADER_VERSION)
434 {
435 Log(("VMMDev: guest header version (0x%08X) differs from ours (0x%08X)\n", requestHeader->version, VMMDEV_REQUEST_HEADER_VERSION));
436 return VINF_SUCCESS;
437 }
438
439 Log2(("VMMDev request issued: %d\n", requestHeader->requestType));
440
441 if (requestHeader->requestType != VMMDevReq_ReportGuestInfo
442 && !pData->fu32AdditionsOk)
443 {
444 Log(("VMMDev: guest has not yet reported to us. Refusing operation.\n"));
445 requestHeader->rc = VERR_NOT_SUPPORTED;
446 return VINF_SUCCESS;
447 }
448
449 /* which request was sent? */
450 switch (requestHeader->requestType)
451 {
452 /*
453 * Guest wants to give up a timeslice
454 */
455 case VMMDevReq_Idle:
456 {
457 /* just return to EMT telling it that we want to halt */
458 return VINF_EM_HALT;
459 break;
460 }
461
462 /*
463 * Guest is reporting its information
464 */
465 case VMMDevReq_ReportGuestInfo:
466 {
467 if (requestHeader->size < sizeof(VMMDevReportGuestInfo))
468 {
469 AssertMsgFailed(("VMMDev guest information structure has invalid size!\n"));
470 requestHeader->rc = VERR_INVALID_PARAMETER;
471 }
472 else
473 {
474 VMMDevReportGuestInfo *guestInfo = (VMMDevReportGuestInfo*)requestHeader;
475
476 if (memcmp (&pData->guestInfo, &guestInfo->guestInfo, sizeof (guestInfo->guestInfo)) != 0)
477 {
478 /* make a copy of supplied information */
479 pData->guestInfo = guestInfo->guestInfo;
480
481 /* Check additions version */
482 pData->fu32AdditionsOk = VBOX_GUEST_ADDITIONS_VERSION_OK(pData->guestInfo.additionsVersion);
483
484 LogRel(("Guest Additions information report: additionsVersion = 0x%08X osType = 0x%08X\n",
485 pData->guestInfo.additionsVersion,
486 pData->guestInfo.osType));
487 pData->pDrv->pfnUpdateGuestVersion(pData->pDrv, &pData->guestInfo);
488 }
489
490 if (pData->fu32AdditionsOk)
491 {
492 requestHeader->rc = VINF_SUCCESS;
493 }
494 else
495 {
496 requestHeader->rc = VERR_VERSION_MISMATCH;
497 }
498 }
499 break;
500 }
501
502 /* Report guest capabilities */
503 case VMMDevReq_ReportGuestCapabilities:
504 {
505 if (requestHeader->size != sizeof(VMMDevReqGuestCapabilities))
506 {
507 AssertMsgFailed(("VMMDev guest caps structure has invalid size!\n"));
508 requestHeader->rc = VERR_INVALID_PARAMETER;
509 }
510 else
511 {
512 VMMDevReqGuestCapabilities *guestCaps = (VMMDevReqGuestCapabilities*)requestHeader;
513
514 if (pData->guestCaps != guestCaps->caps)
515 {
516 /* make a copy of supplied information */
517 pData->guestCaps = guestCaps->caps;
518
519 LogRel(("Guest Additions capability report: (0x%x) "
520 "VMMDEV_GUEST_SUPPORTS_SEAMLESS: %s "
521 "VMMDEV_GUEST_SUPPORTS_GUEST_HOST_WINDOW_MAPPING: %s\n",
522 guestCaps->caps,
523 guestCaps->caps & VMMDEV_GUEST_SUPPORTS_SEAMLESS ? "yes" : "no",
524 guestCaps->caps & VMMDEV_GUEST_SUPPORTS_GUEST_HOST_WINDOW_MAPPING ? "yes" : "no"));
525
526 pData->pDrv->pfnUpdateGuestCapabilities(pData->pDrv, guestCaps->caps);
527 }
528 requestHeader->rc = VINF_SUCCESS;
529 }
530 break;
531 }
532
533 /*
534 * Retrieve mouse information
535 */
536 case VMMDevReq_GetMouseStatus:
537 {
538 if (requestHeader->size != sizeof(VMMDevReqMouseStatus))
539 {
540 AssertMsgFailed(("VMMDev mouse status structure has invalid size!\n"));
541 requestHeader->rc = VERR_INVALID_PARAMETER;
542 }
543 else
544 {
545 VMMDevReqMouseStatus *mouseStatus = (VMMDevReqMouseStatus*)requestHeader;
546 mouseStatus->mouseFeatures = 0;
547 if (pData->mouseCapabilities & VMMDEV_MOUSEHOSTWANTSABS)
548 {
549 mouseStatus->mouseFeatures |= VBOXGUEST_MOUSE_HOST_CAN_ABSOLUTE;
550 }
551 if (pData->mouseCapabilities & VMMDEV_MOUSEGUESTWANTSABS)
552 {
553 mouseStatus->mouseFeatures |= VBOXGUEST_MOUSE_GUEST_CAN_ABSOLUTE;
554 }
555 if (pData->mouseCapabilities & VMMDEV_MOUSEHOSTCANNOTHWPOINTER)
556 {
557 mouseStatus->mouseFeatures |= VBOXGUEST_MOUSE_HOST_CANNOT_HWPOINTER;
558 }
559 mouseStatus->pointerXPos = pData->mouseXAbs;
560 mouseStatus->pointerYPos = pData->mouseYAbs;
561 Log2(("returning mouse status: features = %d, absX = %d, absY = %d\n", mouseStatus->mouseFeatures,
562 mouseStatus->pointerXPos, mouseStatus->pointerYPos));
563 requestHeader->rc = VINF_SUCCESS;
564 }
565 break;
566 }
567
568 /*
569 * Set mouse information
570 */
571 case VMMDevReq_SetMouseStatus:
572 {
573 if (requestHeader->size != sizeof(VMMDevReqMouseStatus))
574 {
575 AssertMsgFailed(("VMMDev mouse status structure has invalid size %d (%#x) version=%d!\n",
576 requestHeader->size, requestHeader->size, requestHeader->size, requestHeader->version));
577 requestHeader->rc = VERR_INVALID_PARAMETER;
578 }
579 else
580 {
581 bool bCapsChanged = false;
582
583 VMMDevReqMouseStatus *mouseStatus = (VMMDevReqMouseStatus*)requestHeader;
584
585 /* check if the guest wants absolute coordinates */
586 if (mouseStatus->mouseFeatures & VBOXGUEST_MOUSE_GUEST_CAN_ABSOLUTE)
587 {
588 /* set the capability flag and the changed flag if it's actually a change */
589 if (!(pData->mouseCapabilities & VMMDEV_MOUSEGUESTWANTSABS))
590 {
591 pData->mouseCapabilities |= VMMDEV_MOUSEGUESTWANTSABS;
592 bCapsChanged = true;
593 LogRel(("Guest requests mouse pointer integration\n"));
594 }
595 } else
596 {
597 if (pData->mouseCapabilities & VMMDEV_MOUSEGUESTWANTSABS)
598 {
599 pData->mouseCapabilities &= ~VMMDEV_MOUSEGUESTWANTSABS;
600 bCapsChanged = true;
601 LogRel(("Guest disables mouse pointer integration\n"));
602 }
603 }
604 if (mouseStatus->mouseFeatures & VBOXGUEST_MOUSE_GUEST_NEEDS_HOST_CURSOR)
605 pData->mouseCapabilities |= VMMDEV_MOUSEGUESTNEEDSHOSTCUR;
606 else
607 pData->mouseCapabilities &= ~VMMDEV_MOUSEGUESTNEEDSHOSTCUR;
608
609 /*
610 * Notify connector if something has changed
611 */
612 if (bCapsChanged)
613 {
614 Log(("VMMDevReq_SetMouseStatus: capabilities changed (%x), informing connector\n", pData->mouseCapabilities));
615 pData->pDrv->pfnUpdateMouseCapabilities(pData->pDrv, pData->mouseCapabilities);
616 }
617 requestHeader->rc = VINF_SUCCESS;
618 }
619
620 break;
621 }
622
623 /*
624 * Set a new mouse pointer shape
625 */
626 case VMMDevReq_SetPointerShape:
627 {
628 if (requestHeader->size < sizeof(VMMDevReqMousePointer))
629 {
630 AssertMsg(requestHeader->size == 0x10028 && requestHeader->version == 10000, /* don't bitch about legacy!!! */
631 ("VMMDev mouse shape structure has invalid size %d (%#x) version=%d!\n",
632 requestHeader->size, requestHeader->size, requestHeader->size, requestHeader->version));
633 requestHeader->rc = VERR_INVALID_PARAMETER;
634 }
635 else
636 {
637 VMMDevReqMousePointer *pointerShape = (VMMDevReqMousePointer*)requestHeader;
638
639 bool fVisible = (pointerShape->fFlags & VBOX_MOUSE_POINTER_VISIBLE) != 0;
640 bool fAlpha = (pointerShape->fFlags & VBOX_MOUSE_POINTER_ALPHA) != 0;
641 bool fShape = (pointerShape->fFlags & VBOX_MOUSE_POINTER_SHAPE) != 0;
642
643 Log(("VMMDevReq_SetPointerShape: visible: %d, alpha: %d, shape = %d, width: %d, height: %d\n",
644 fVisible, fAlpha, fShape, pointerShape->width, pointerShape->height));
645
646 /* forward call to driver */
647 if (fShape)
648 {
649 pData->pDrv->pfnUpdatePointerShape(pData->pDrv,
650 fVisible,
651 fAlpha,
652 pointerShape->xHot, pointerShape->yHot,
653 pointerShape->width, pointerShape->height,
654 pointerShape->pointerData);
655 }
656 else
657 {
658 pData->pDrv->pfnUpdatePointerShape(pData->pDrv,
659 fVisible,
660 0,
661 0, 0,
662 0, 0,
663 NULL);
664 }
665 requestHeader->rc = VINF_SUCCESS;
666 }
667 break;
668 }
669
670 /*
671 * Query the system time from the host
672 */
673 case VMMDevReq_GetHostTime:
674 {
675 if (requestHeader->size != sizeof(VMMDevReqHostTime))
676 {
677 AssertMsgFailed(("VMMDev host time structure has invalid size!\n"));
678 requestHeader->rc = VERR_INVALID_PARAMETER;
679 }
680 else if (RT_UNLIKELY(pData->fGetHostTimeDisabled))
681 requestHeader->rc = VERR_NOT_SUPPORTED;
682 else
683 {
684 VMMDevReqHostTime *hostTimeReq = (VMMDevReqHostTime*)requestHeader;
685 RTTIMESPEC now;
686 hostTimeReq->time = RTTimeSpecGetMilli(PDMDevHlpUTCNow(pDevIns, &now));
687 requestHeader->rc = VINF_SUCCESS;
688 }
689 break;
690 }
691
692 /*
693 * Query information about the hypervisor
694 */
695 case VMMDevReq_GetHypervisorInfo:
696 {
697 if (requestHeader->size != sizeof(VMMDevReqHypervisorInfo))
698 {
699 AssertMsgFailed(("VMMDev hypervisor info structure has invalid size!\n"));
700 requestHeader->rc = VERR_INVALID_PARAMETER;
701 }
702 else
703 {
704 VMMDevReqHypervisorInfo *hypervisorInfo = (VMMDevReqHypervisorInfo*)requestHeader;
705 PVM pVM = PDMDevHlpGetVM(pDevIns);
706 size_t hypervisorSize = 0;
707 requestHeader->rc = PGMR3MappingsSize(pVM, &hypervisorSize);
708 hypervisorInfo->hypervisorSize = (uint32_t)hypervisorSize;
709 Assert(hypervisorInfo->hypervisorSize == hypervisorSize);
710 }
711 break;
712 }
713
714 /*
715 * Set hypervisor information
716 */
717 case VMMDevReq_SetHypervisorInfo:
718 {
719 if (requestHeader->size != sizeof(VMMDevReqHypervisorInfo))
720 {
721 AssertMsgFailed(("VMMDev hypervisor info structure has invalid size!\n"));
722 requestHeader->rc = VERR_INVALID_PARAMETER;
723 }
724 else
725 {
726 VMMDevReqHypervisorInfo *hypervisorInfo = (VMMDevReqHypervisorInfo*)requestHeader;
727 PVM pVM = PDMDevHlpGetVM(pDevIns);
728 if (hypervisorInfo->hypervisorStart == 0)
729 {
730 requestHeader->rc = PGMR3MappingsUnfix(pVM);
731 } else
732 {
733 /* only if the client has queried the size before! */
734 size_t mappingsSize;
735 requestHeader->rc = PGMR3MappingsSize(pVM, &mappingsSize);
736 if (VBOX_SUCCESS(requestHeader->rc) && (hypervisorInfo->hypervisorSize == mappingsSize))
737 {
738 /* new reservation */
739 requestHeader->rc = PGMR3MappingsFix(pVM, hypervisorInfo->hypervisorStart,
740 hypervisorInfo->hypervisorSize);
741 LogRel(("Guest reported fixed hypervisor window at 0x%p (size = 0x%x, rc = %Vrc)\n",
742 hypervisorInfo->hypervisorStart,
743 hypervisorInfo->hypervisorSize,
744 requestHeader->rc));
745 }
746 }
747 }
748 break;
749 }
750
751 /*
752 * Set the system power status
753 */
754 case VMMDevReq_SetPowerStatus:
755 {
756 if (requestHeader->size != sizeof(VMMDevPowerStateRequest))
757 {
758 AssertMsgFailed(("VMMDev power state request structure has invalid size!\n"));
759 requestHeader->rc = VERR_INVALID_PARAMETER;
760 }
761 else
762 {
763 VMMDevPowerStateRequest *powerStateRequest = (VMMDevPowerStateRequest*)requestHeader;
764 switch(powerStateRequest->powerState)
765 {
766 case VMMDevPowerState_Pause:
767 {
768 LogRel(("Guest requests the VM to be suspended (paused)\n"));
769 requestHeader->rc = rcRet = PDMDevHlpVMSuspend(pDevIns);
770 break;
771 }
772
773 case VMMDevPowerState_PowerOff:
774 {
775 LogRel(("Guest requests the VM to be turned off\n"));
776 requestHeader->rc = rcRet = PDMDevHlpVMPowerOff(pDevIns);
777 break;
778 }
779
780 case VMMDevPowerState_SaveState:
781 {
782 /** @todo no API for that yet */
783 requestHeader->rc = VERR_NOT_IMPLEMENTED;
784 break;
785 }
786
787 default:
788 AssertMsgFailed(("VMMDev invalid power state request: %d\n", powerStateRequest->powerState));
789 requestHeader->rc = VERR_INVALID_PARAMETER;
790 break;
791 }
792 }
793 break;
794 }
795
796 /*
797 * Get display change request
798 */
799 case VMMDevReq_GetDisplayChangeRequest:
800 {
801 if (requestHeader->size != sizeof(VMMDevDisplayChangeRequest))
802 {
803 /* Assert only if the size also not equal to a previous version size to prevent
804 * assertion with old additions.
805 */
806 AssertMsg(requestHeader->size == sizeof(VMMDevDisplayChangeRequest) - sizeof (uint32_t),
807 ("VMMDev display change request structure has invalid size!\n"));
808 requestHeader->rc = VERR_INVALID_PARAMETER;
809 }
810 else
811 {
812 VMMDevDisplayChangeRequest *displayChangeRequest = (VMMDevDisplayChangeRequest*)requestHeader;
813 /* just pass on the information */
814 Log(("VMMDev: returning display change request xres = %d, yres = %d, bpp = %d\n",
815 pData->displayChangeRequest.xres, pData->displayChangeRequest.yres, pData->displayChangeRequest.bpp));
816 displayChangeRequest->xres = pData->displayChangeRequest.xres;
817 displayChangeRequest->yres = pData->displayChangeRequest.yres;
818 displayChangeRequest->bpp = pData->displayChangeRequest.bpp;
819
820 if (displayChangeRequest->eventAck == VMMDEV_EVENT_DISPLAY_CHANGE_REQUEST)
821 {
822 /* Remember which resolution the client has queried. */
823 pData->lastReadDisplayChangeRequest = pData->displayChangeRequest;
824 }
825
826 requestHeader->rc = VINF_SUCCESS;
827 }
828 break;
829 }
830
831 case VMMDevReq_GetDisplayChangeRequest2:
832 {
833 if (requestHeader->size != sizeof(VMMDevDisplayChangeRequest2))
834 {
835 requestHeader->rc = VERR_INVALID_PARAMETER;
836 }
837 else
838 {
839 VMMDevDisplayChangeRequest2 *displayChangeRequest = (VMMDevDisplayChangeRequest2*)requestHeader;
840 /* just pass on the information */
841 Log(("VMMDev: returning display change request xres = %d, yres = %d, bpp = %d at %d\n",
842 pData->displayChangeRequest.xres, pData->displayChangeRequest.yres, pData->displayChangeRequest.bpp, pData->displayChangeRequest.display));
843 displayChangeRequest->xres = pData->displayChangeRequest.xres;
844 displayChangeRequest->yres = pData->displayChangeRequest.yres;
845 displayChangeRequest->bpp = pData->displayChangeRequest.bpp;
846 displayChangeRequest->display = pData->displayChangeRequest.display;
847
848 if (displayChangeRequest->eventAck == VMMDEV_EVENT_DISPLAY_CHANGE_REQUEST)
849 {
850 /* Remember which resolution the client has queried. */
851 pData->lastReadDisplayChangeRequest = pData->displayChangeRequest;
852 }
853
854 requestHeader->rc = VINF_SUCCESS;
855 }
856 break;
857 }
858
859 /*
860 * Query whether the given video mode is supported
861 */
862 case VMMDevReq_VideoModeSupported:
863 {
864 if (requestHeader->size != sizeof(VMMDevVideoModeSupportedRequest))
865 {
866 AssertMsgFailed(("VMMDev video mode supported request structure has invalid size!\n"));
867 requestHeader->rc = VERR_INVALID_PARAMETER;
868 }
869 else
870 {
871 VMMDevVideoModeSupportedRequest *videoModeSupportedRequest = (VMMDevVideoModeSupportedRequest*)requestHeader;
872 /* forward the call */
873 requestHeader->rc = pData->pDrv->pfnVideoModeSupported(pData->pDrv,
874 videoModeSupportedRequest->width,
875 videoModeSupportedRequest->height,
876 videoModeSupportedRequest->bpp,
877 &videoModeSupportedRequest->fSupported);
878 }
879 break;
880 }
881
882 /*
883 * Query the height reduction in pixels
884 */
885 case VMMDevReq_GetHeightReduction:
886 {
887 if (requestHeader->size != sizeof(VMMDevGetHeightReductionRequest))
888 {
889 AssertMsgFailed(("VMMDev height reduction request structure has invalid size!\n"));
890 requestHeader->rc = VERR_INVALID_PARAMETER;
891 }
892 else
893 {
894 VMMDevGetHeightReductionRequest *heightReductionRequest = (VMMDevGetHeightReductionRequest*)requestHeader;
895 /* forward the call */
896 requestHeader->rc = pData->pDrv->pfnGetHeightReduction(pData->pDrv,
897 &heightReductionRequest->heightReduction);
898 }
899 break;
900 }
901
902 /*
903 * Acknowledge VMMDev events
904 */
905 case VMMDevReq_AcknowledgeEvents:
906 {
907 if (requestHeader->size != sizeof(VMMDevEvents))
908 {
909 AssertMsgFailed(("VMMDevReq_AcknowledgeEvents structure has invalid size!\n"));
910 requestHeader->rc = VERR_INVALID_PARAMETER;
911 }
912 else
913 {
914 if (VBOX_GUEST_ADDITIONS_VERSION_1_03 (pData))
915 {
916 vmmdevSetIRQ_Legacy_EMT (pData);
917 }
918 else
919 {
920 VMMDevEvents *pAckRequest;
921
922 if (pData->fNewGuestFilterMask)
923 {
924 pData->fNewGuestFilterMask = false;
925 pData->u32GuestFilterMask = pData->u32NewGuestFilterMask;
926 }
927
928 pAckRequest = (VMMDevEvents *) requestHeader;
929 pAckRequest->events =
930 pData->u32HostEventFlags & pData->u32GuestFilterMask;
931
932 pData->u32HostEventFlags &= ~pData->u32GuestFilterMask;
933 pData->pVMMDevRAMHC->V.V1_04.fHaveEvents = false;
934 PDMDevHlpPCISetIrqNoWait (pData->pDevIns, 0, 0);
935 }
936 requestHeader->rc = VINF_SUCCESS;
937 }
938 break;
939 }
940
941 /*
942 * Change guest filter mask
943 */
944 case VMMDevReq_CtlGuestFilterMask:
945 {
946 if (requestHeader->size != sizeof(VMMDevCtlGuestFilterMask))
947 {
948 AssertMsgFailed(("VMMDevReq_AcknowledgeEvents structure has invalid size!\n"));
949 requestHeader->rc = VERR_INVALID_PARAMETER;
950 }
951 else
952 {
953 VMMDevCtlGuestFilterMask *pCtlMaskRequest;
954
955 pCtlMaskRequest = (VMMDevCtlGuestFilterMask *) requestHeader;
956 /* The HGCM events are enabled by the VMMDev device automatically when any
957 * HGCM command is issued. The guest then can not disable these events.
958 */
959 vmmdevCtlGuestFilterMask_EMT (pData,
960 pCtlMaskRequest->u32OrMask,
961 pCtlMaskRequest->u32NotMask & ~VMMDEV_EVENT_HGCM);
962 requestHeader->rc = VINF_SUCCESS;
963
964 }
965 break;
966 }
967
968#ifdef VBOX_HGCM
969 /*
970 * Process HGCM request
971 */
972 case VMMDevReq_HGCMConnect:
973 {
974 if (requestHeader->size < sizeof(VMMDevHGCMConnect))
975 {
976 AssertMsgFailed(("VMMDevReq_HGCMConnect structure has invalid size!\n"));
977 requestHeader->rc = VERR_INVALID_PARAMETER;
978 }
979 else if (!pData->pHGCMDrv)
980 {
981 Log(("VMMDevReq_HGCMConnect HGCM Connector is NULL!\n"));
982 requestHeader->rc = VERR_NOT_SUPPORTED;
983 }
984 else
985 {
986 VMMDevHGCMConnect *pHGCMConnect = (VMMDevHGCMConnect *)requestHeader;
987
988 Log(("VMMDevReq_HGCMConnect\n"));
989
990 requestHeader->rc = vmmdevHGCMConnect (pData, pHGCMConnect, (RTGCPHYS)u32);
991 }
992 break;
993 }
994
995 case VMMDevReq_HGCMDisconnect:
996 {
997 if (requestHeader->size < sizeof(VMMDevHGCMDisconnect))
998 {
999 AssertMsgFailed(("VMMDevReq_HGCMDisconnect structure has invalid size!\n"));
1000 requestHeader->rc = VERR_INVALID_PARAMETER;
1001 }
1002 else if (!pData->pHGCMDrv)
1003 {
1004 Log(("VMMDevReq_HGCMDisconnect HGCM Connector is NULL!\n"));
1005 requestHeader->rc = VERR_NOT_SUPPORTED;
1006 }
1007 else
1008 {
1009 VMMDevHGCMDisconnect *pHGCMDisconnect = (VMMDevHGCMDisconnect *)requestHeader;
1010
1011 Log(("VMMDevReq_VMMDevHGCMDisconnect\n"));
1012 requestHeader->rc = vmmdevHGCMDisconnect (pData, pHGCMDisconnect, (RTGCPHYS)u32);
1013 }
1014 break;
1015 }
1016
1017 case VMMDevReq_HGCMCall:
1018 {
1019 if (requestHeader->size < sizeof(VMMDevHGCMCall))
1020 {
1021 AssertMsgFailed(("VMMDevReq_HGCMCall structure has invalid size!\n"));
1022 requestHeader->rc = VERR_INVALID_PARAMETER;
1023 }
1024 else if (!pData->pHGCMDrv)
1025 {
1026 Log(("VMMDevReq_HGCMCall HGCM Connector is NULL!\n"));
1027 requestHeader->rc = VERR_NOT_SUPPORTED;
1028 }
1029 else
1030 {
1031 VMMDevHGCMCall *pHGCMCall = (VMMDevHGCMCall *)requestHeader;
1032
1033 Log2(("VMMDevReq_HGCMCall: sizeof (VMMDevHGCMRequest) = %04X\n", sizeof (VMMDevHGCMCall)));
1034 Log2(("%.*Vhxd\n", requestHeader->size, requestHeader));
1035
1036 requestHeader->rc = vmmdevHGCMCall (pData, pHGCMCall, (RTGCPHYS)u32);
1037 }
1038 break;
1039 }
1040#endif /* VBOX_HGCM */
1041
1042 case VMMDevReq_VideoAccelEnable:
1043 {
1044 if (requestHeader->size < sizeof(VMMDevVideoAccelEnable))
1045 {
1046 Log(("VMMDevReq_VideoAccelEnable request size too small!!!\n"));
1047 requestHeader->rc = VERR_INVALID_PARAMETER;
1048 }
1049 else if (!pData->pDrv)
1050 {
1051 Log(("VMMDevReq_VideoAccelEnable Connector is NULL!!!\n"));
1052 requestHeader->rc = VERR_NOT_SUPPORTED;
1053 }
1054 else
1055 {
1056 VMMDevVideoAccelEnable *ptr = (VMMDevVideoAccelEnable *)requestHeader;
1057
1058 if (ptr->cbRingBuffer != VBVA_RING_BUFFER_SIZE)
1059 {
1060 /* The guest driver seems compiled with another headers. */
1061 Log(("VMMDevReq_VideoAccelEnable guest ring buffer size %d, should be %d!!!\n", ptr->cbRingBuffer, VBVA_RING_BUFFER_SIZE));
1062 requestHeader->rc = VERR_INVALID_PARAMETER;
1063 }
1064 else
1065 {
1066 /* The request is correct. */
1067 ptr->fu32Status |= VBVA_F_STATUS_ACCEPTED;
1068
1069 LogFlow(("VMMDevReq_VideoAccelEnable ptr->u32Enable = %d\n", ptr->u32Enable));
1070
1071 requestHeader->rc = ptr->u32Enable?
1072 pData->pDrv->pfnVideoAccelEnable (pData->pDrv, true, &pData->pVMMDevRAMHC->vbvaMemory):
1073 pData->pDrv->pfnVideoAccelEnable (pData->pDrv, false, NULL);
1074
1075 if ( ptr->u32Enable
1076 && VBOX_SUCCESS (requestHeader->rc))
1077 {
1078 ptr->fu32Status |= VBVA_F_STATUS_ENABLED;
1079
1080 /* Remember that guest successfully enabled acceleration.
1081 * We need to reestablish it on restoring the VM from saved state.
1082 */
1083 pData->u32VideoAccelEnabled = 1;
1084 }
1085 else
1086 {
1087 /* The acceleration was not enabled. Remember that. */
1088 pData->u32VideoAccelEnabled = 0;
1089 }
1090 }
1091 }
1092 break;
1093 }
1094
1095 case VMMDevReq_VideoAccelFlush:
1096 {
1097 if (requestHeader->size < sizeof(VMMDevVideoAccelFlush))
1098 {
1099 AssertMsgFailed(("VMMDevReq_VideoAccelFlush request size too small.\n"));
1100 requestHeader->rc = VERR_INVALID_PARAMETER;
1101 }
1102 else if (!pData->pDrv)
1103 {
1104 Log(("VMMDevReq_VideoAccelFlush Connector is NULL!\n"));
1105 requestHeader->rc = VERR_NOT_SUPPORTED;
1106 }
1107 else
1108 {
1109 pData->pDrv->pfnVideoAccelFlush (pData->pDrv);
1110
1111 requestHeader->rc = VINF_SUCCESS;
1112 }
1113 break;
1114 }
1115
1116 case VMMDevReq_VideoSetVisibleRegion:
1117 {
1118 if (requestHeader->size < sizeof(VMMDevVideoSetVisibleRegion))
1119 {
1120 Log(("VMMDevReq_VideoSetVisibleRegion request size too small!!!\n"));
1121 requestHeader->rc = VERR_INVALID_PARAMETER;
1122 }
1123 else if (!pData->pDrv)
1124 {
1125 Log(("VMMDevReq_VideoSetVisibleRegion Connector is NULL!!!\n"));
1126 requestHeader->rc = VERR_NOT_SUPPORTED;
1127 }
1128 else
1129 {
1130 VMMDevVideoSetVisibleRegion *ptr = (VMMDevVideoSetVisibleRegion *)requestHeader;
1131
1132 if (!ptr->cRect)
1133 {
1134 Log(("VMMDevReq_VideoSetVisibleRegion no rectangles!!!\n"));
1135 requestHeader->rc = VERR_INVALID_PARAMETER;
1136 }
1137 else
1138 if (requestHeader->size != sizeof(VMMDevVideoSetVisibleRegion) + (ptr->cRect-1)*sizeof(RTRECT))
1139 {
1140 Log(("VMMDevReq_VideoSetVisibleRegion request size too small!!!\n"));
1141 requestHeader->rc = VERR_INVALID_PARAMETER;
1142 }
1143 else
1144 {
1145 Log(("VMMDevReq_VideoSetVisibleRegion %d rectangles\n", ptr->cRect));
1146 /* forward the call */
1147 requestHeader->rc = pData->pDrv->pfnSetVisibleRegion(pData->pDrv, ptr->cRect, &ptr->Rect);
1148 }
1149 }
1150 break;
1151 }
1152
1153 case VMMDevReq_GetSeamlessChangeRequest:
1154 {
1155 if (requestHeader->size != sizeof(VMMDevSeamlessChangeRequest))
1156 {
1157 requestHeader->rc = VERR_INVALID_PARAMETER;
1158 }
1159 else
1160 {
1161 VMMDevSeamlessChangeRequest *seamlessChangeRequest = (VMMDevSeamlessChangeRequest*)requestHeader;
1162 /* just pass on the information */
1163 Log(("VMMDev: returning seamless change request mode=%d\n", pData->fSeamlessEnabled));
1164 if (pData->fSeamlessEnabled)
1165 seamlessChangeRequest->mode = VMMDev_Seamless_Visible_Region;
1166 else
1167 seamlessChangeRequest->mode = VMMDev_Seamless_Disabled;
1168
1169 if (seamlessChangeRequest->eventAck == VMMDEV_EVENT_SEAMLESS_MODE_CHANGE_REQUEST)
1170 {
1171 /* Remember which mode the client has queried. */
1172 pData->fLastSeamlessEnabled = pData->fSeamlessEnabled;
1173 }
1174
1175 requestHeader->rc = VINF_SUCCESS;
1176 }
1177 break;
1178 }
1179
1180 case VMMDevReq_GetVRDPChangeRequest:
1181 {
1182 if (requestHeader->size != sizeof(VMMDevVRDPChangeRequest))
1183 {
1184 requestHeader->rc = VERR_INVALID_PARAMETER;
1185 }
1186 else
1187 {
1188 VMMDevVRDPChangeRequest *vrdpChangeRequest = (VMMDevVRDPChangeRequest*)requestHeader;
1189 /* just pass on the information */
1190 Log(("VMMDev: returning VRDP status %d level %d\n", pData->fVRDPEnabled, pData->u32VRDPExperienceLevel));
1191
1192 vrdpChangeRequest->u8VRDPActive = pData->fVRDPEnabled;
1193 vrdpChangeRequest->u32VRDPExperienceLevel = pData->u32VRDPExperienceLevel;
1194
1195 requestHeader->rc = VINF_SUCCESS;
1196 }
1197 break;
1198 }
1199
1200 case VMMDevReq_GetMemBalloonChangeRequest:
1201 {
1202 Log(("VMMDevReq_GetMemBalloonChangeRequest\n"));
1203 if (requestHeader->size != sizeof(VMMDevGetMemBalloonChangeRequest))
1204 {
1205 AssertFailed();
1206 requestHeader->rc = VERR_INVALID_PARAMETER;
1207 }
1208 else
1209 {
1210 VMMDevGetMemBalloonChangeRequest *memBalloonChangeRequest = (VMMDevGetMemBalloonChangeRequest*)requestHeader;
1211 /* just pass on the information */
1212 Log(("VMMDev: returning memory balloon size =%d\n", pData->u32MemoryBalloonSize));
1213 memBalloonChangeRequest->u32BalloonSize = pData->u32MemoryBalloonSize;
1214
1215 if (memBalloonChangeRequest->eventAck == VMMDEV_EVENT_BALLOON_CHANGE_REQUEST)
1216 {
1217 /* Remember which mode the client has queried. */
1218 pData->u32LastMemoryBalloonSize = pData->u32MemoryBalloonSize;
1219 }
1220
1221 requestHeader->rc = VINF_SUCCESS;
1222 }
1223 break;
1224 }
1225
1226 case VMMDevReq_ChangeMemBalloon:
1227 {
1228 VMMDevChangeMemBalloon *memBalloonChange = (VMMDevChangeMemBalloon*)requestHeader;
1229
1230 Log(("VMMDevReq_ChangeMemBalloon\n"));
1231 if ( requestHeader->size < sizeof(VMMDevChangeMemBalloon)
1232 || memBalloonChange->cPages != VMMDEV_MEMORY_BALLOON_CHUNK_PAGES
1233 || requestHeader->size != RT_OFFSETOF(VMMDevChangeMemBalloon, aPhysPage[memBalloonChange->cPages]))
1234 {
1235 AssertFailed();
1236 requestHeader->rc = VERR_INVALID_PARAMETER;
1237 }
1238 else
1239 {
1240 requestHeader->rc = pData->pDrv->pfnChangeMemoryBalloon(pData->pDrv, !!memBalloonChange->fInflate, memBalloonChange->cPages, memBalloonChange->aPhysPage);
1241 }
1242 break;
1243 }
1244
1245 case VMMDevReq_GetStatisticsChangeRequest:
1246 {
1247 Log(("VMMDevReq_GetStatisticsChangeRequest\n"));
1248 if (requestHeader->size != sizeof(VMMDevGetStatisticsChangeRequest))
1249 {
1250 AssertFailed();
1251 requestHeader->rc = VERR_INVALID_PARAMETER;
1252 }
1253 else
1254 {
1255 VMMDevGetStatisticsChangeRequest *statIntervalChangeRequest = (VMMDevGetStatisticsChangeRequest*)requestHeader;
1256 /* just pass on the information */
1257 Log(("VMMDev: returning statistics interval %d seconds\n", pData->u32StatIntervalSize));
1258 statIntervalChangeRequest->u32StatInterval = pData->u32StatIntervalSize;
1259
1260 if (statIntervalChangeRequest->eventAck == VMMDEV_EVENT_STATISTICS_INTERVAL_CHANGE_REQUEST)
1261 {
1262 /* Remember which mode the client has queried. */
1263 pData->u32LastStatIntervalSize= pData->u32StatIntervalSize;
1264 }
1265
1266 requestHeader->rc = VINF_SUCCESS;
1267 }
1268 break;
1269 }
1270
1271 case VMMDevReq_ReportGuestStats:
1272 {
1273 Log(("VMMDevReq_ReportGuestStats\n"));
1274 if (requestHeader->size != sizeof(VMMDevReportGuestStats))
1275 {
1276 requestHeader->rc = VERR_INVALID_PARAMETER;
1277 }
1278 else
1279 {
1280 VMMDevReportGuestStats *stats = (VMMDevReportGuestStats*)requestHeader;
1281
1282 /* Update the last known memory balloon size */
1283 if (stats->guestStats.u32StatCaps & VBOX_GUEST_STAT_PHYS_MEM_BALLOON)
1284 pData->u32LastMemoryBalloonSize = stats->guestStats.u32PhysMemBalloon;
1285
1286 /* forward the call */
1287 requestHeader->rc = pData->pDrv->pfnReportStatistics(pData->pDrv, &stats->guestStats);
1288 }
1289 break;
1290 }
1291
1292 case VMMDevReq_QueryCredentials:
1293 {
1294 if (requestHeader->size != sizeof(VMMDevCredentials))
1295 {
1296 AssertMsgFailed(("VMMDevReq_QueryCredentials request size too small.\n"));
1297 requestHeader->rc = VERR_INVALID_PARAMETER;
1298 }
1299 else
1300 {
1301 VMMDevCredentials *credentials = (VMMDevCredentials*)requestHeader;
1302
1303 /* let's start by nulling out the data */
1304 memset(credentials->szUserName, '\0', VMMDEV_CREDENTIALS_STRLEN);
1305 memset(credentials->szPassword, '\0', VMMDEV_CREDENTIALS_STRLEN);
1306 memset(credentials->szDomain, '\0', VMMDEV_CREDENTIALS_STRLEN);
1307
1308 /* should we return whether we got credentials for a logon? */
1309 if (credentials->u32Flags & VMMDEV_CREDENTIALS_QUERYPRESENCE)
1310 {
1311 if ( pData->credentialsLogon.szUserName[0]
1312 || pData->credentialsLogon.szPassword[0]
1313 || pData->credentialsLogon.szDomain[0])
1314 {
1315 credentials->u32Flags |= VMMDEV_CREDENTIALS_PRESENT;
1316 }
1317 else
1318 {
1319 credentials->u32Flags &= ~VMMDEV_CREDENTIALS_PRESENT;
1320 }
1321 }
1322
1323 /* does the guest want to read logon credentials? */
1324 if (credentials->u32Flags & VMMDEV_CREDENTIALS_READ)
1325 {
1326 if (pData->credentialsLogon.szUserName[0])
1327 strcpy(credentials->szUserName, pData->credentialsLogon.szUserName);
1328 if (pData->credentialsLogon.szPassword[0])
1329 strcpy(credentials->szPassword, pData->credentialsLogon.szPassword);
1330 if (pData->credentialsLogon.szDomain[0])
1331 strcpy(credentials->szDomain, pData->credentialsLogon.szDomain);
1332 if (!pData->credentialsLogon.fAllowInteractiveLogon)
1333 credentials->u32Flags |= VMMDEV_CREDENTIALS_NOLOCALLOGON;
1334 else
1335 credentials->u32Flags &= ~VMMDEV_CREDENTIALS_NOLOCALLOGON;
1336 }
1337
1338 /* does the caller want us to destroy the logon credentials? */
1339 if (credentials->u32Flags & VMMDEV_CREDENTIALS_CLEAR)
1340 {
1341 memset(pData->credentialsLogon.szUserName, '\0', VMMDEV_CREDENTIALS_STRLEN);
1342 memset(pData->credentialsLogon.szPassword, '\0', VMMDEV_CREDENTIALS_STRLEN);
1343 memset(pData->credentialsLogon.szDomain, '\0', VMMDEV_CREDENTIALS_STRLEN);
1344 }
1345
1346 /* does the guest want to read credentials for verification? */
1347 if (credentials->u32Flags & VMMDEV_CREDENTIALS_READJUDGE)
1348 {
1349 if (pData->credentialsJudge.szUserName[0])
1350 strcpy(credentials->szUserName, pData->credentialsJudge.szUserName);
1351 if (pData->credentialsJudge.szPassword[0])
1352 strcpy(credentials->szPassword, pData->credentialsJudge.szPassword);
1353 if (pData->credentialsJudge.szDomain[0])
1354 strcpy(credentials->szDomain, pData->credentialsJudge.szDomain);
1355 }
1356
1357 /* does the caller want us to destroy the judgement credentials? */
1358 if (credentials->u32Flags & VMMDEV_CREDENTIALS_CLEARJUDGE)
1359 {
1360 memset(pData->credentialsJudge.szUserName, '\0', VMMDEV_CREDENTIALS_STRLEN);
1361 memset(pData->credentialsJudge.szPassword, '\0', VMMDEV_CREDENTIALS_STRLEN);
1362 memset(pData->credentialsJudge.szDomain, '\0', VMMDEV_CREDENTIALS_STRLEN);
1363 }
1364
1365 requestHeader->rc = VINF_SUCCESS;
1366 }
1367 break;
1368 }
1369
1370 case VMMDevReq_ReportCredentialsJudgement:
1371 {
1372 if (requestHeader->size != sizeof(VMMDevCredentials))
1373 {
1374 AssertMsgFailed(("VMMDevReq_ReportCredentialsJudgement request size too small.\n"));
1375 requestHeader->rc = VERR_INVALID_PARAMETER;
1376 }
1377 else
1378 {
1379 VMMDevCredentials *credentials = (VMMDevCredentials*)requestHeader;
1380
1381 /* what does the guest think about the credentials? (note: the order is important here!) */
1382 if (credentials->u32Flags & VMMDEV_CREDENTIALS_JUDGE_DENY)
1383 {
1384 pData->pDrv->pfnSetCredentialsJudgementResult(pData->pDrv, VMMDEV_CREDENTIALS_JUDGE_DENY);
1385 }
1386 else if (credentials->u32Flags & VMMDEV_CREDENTIALS_JUDGE_NOJUDGEMENT)
1387 {
1388 pData->pDrv->pfnSetCredentialsJudgementResult(pData->pDrv, VMMDEV_CREDENTIALS_JUDGE_NOJUDGEMENT);
1389 }
1390 else if (credentials->u32Flags & VMMDEV_CREDENTIALS_JUDGE_OK)
1391 {
1392 pData->pDrv->pfnSetCredentialsJudgementResult(pData->pDrv, VMMDEV_CREDENTIALS_JUDGE_OK);
1393 }
1394 else
1395 Log(("VMMDevReq_ReportCredentialsJudgement: invalid flags: %d!!!\n", credentials->u32Flags));
1396
1397 requestHeader->rc = VINF_SUCCESS;
1398 }
1399 break;
1400 }
1401
1402#ifdef DEBUG
1403 case VMMDevReq_LogString:
1404 {
1405 if (requestHeader->size < sizeof(VMMDevReqLogString))
1406 {
1407 AssertMsgFailed(("VMMDevReq_LogString request size too small.\n"));
1408 requestHeader->rc = VERR_INVALID_PARAMETER;
1409 }
1410 else
1411 {
1412 VMMDevReqLogString *pReqLogString = (VMMDevReqLogString*)requestHeader;
1413#undef LOG_GROUP
1414#define LOG_GROUP LOG_GROUP_DEV_VMM_BACKDOOR
1415// Log(("Guest Log: %s", pReqLogString->szString));
1416 Log(("DEBUG LOG: %s", pReqLogString->szString));
1417
1418#undef LOG_GROUP
1419#define LOG_GROUP LOG_GROUP_DEV_VMM
1420 requestHeader->rc = VINF_SUCCESS;
1421 }
1422 break;
1423 }
1424#endif
1425 default:
1426 {
1427 requestHeader->rc = VERR_NOT_IMPLEMENTED;
1428
1429 Log(("VMMDev unknown request type %d\n", requestHeader->requestType));
1430
1431 break;
1432 }
1433 }
1434
1435 return rcRet;
1436}
1437
1438/**
1439 * Callback function for mapping an PCI I/O region.
1440 *
1441 * @return VBox status code.
1442 * @param pPciDev Pointer to PCI device. Use pPciDev->pDevIns to get the device instance.
1443 * @param iRegion The region number.
1444 * @param GCPhysAddress Physical address of the region. If iType is PCI_ADDRESS_SPACE_IO, this is an
1445 * I/O port, else it's a physical address.
1446 * This address is *NOT* relative to pci_mem_base like earlier!
1447 * @param enmType One of the PCI_ADDRESS_SPACE_* values.
1448 */
1449static DECLCALLBACK(int) vmmdevIORAMRegionMap(PPCIDEVICE pPciDev, /*unsigned*/ int iRegion, RTGCPHYS GCPhysAddress, uint32_t cb, PCIADDRESSSPACE enmType)
1450{
1451 int rc;
1452 VMMDevState *pData = PCIDEV_2_VMMDEVSTATE(pPciDev);
1453 LogFlow(("vmmdevR3IORAMRegionMap: iRegion=%d GCPhysAddress=%VGp cb=%#x enmType=%d\n", iRegion, GCPhysAddress, cb, enmType));
1454
1455
1456 Assert(pData->pVMMDevRAMHC != NULL);
1457
1458 memset (pData->pVMMDevRAMHC, 0, sizeof (VMMDevMemory));
1459 pData->pVMMDevRAMHC->u32Size = sizeof (VMMDevMemory);
1460 pData->pVMMDevRAMHC->u32Version = VMMDEV_MEMORY_VERSION;
1461
1462 /*
1463 * VMMDev RAM mapping.
1464 */
1465 if (iRegion == 1 && enmType == PCI_ADDRESS_SPACE_MEM)
1466 {
1467 /*
1468 * Register and lock the RAM.
1469 *
1470 * Windows usually re-initializes the PCI devices, so we have to check whether the memory was
1471 * already registered before trying to do that all over again.
1472 */
1473 PVM pVM = PDMDevHlpGetVM(pPciDev->pDevIns);
1474
1475 if (pData->GCPhysVMMDevRAM)
1476 {
1477 /*
1478 * Relocate the already registered VMMDevRAM.
1479 */
1480 rc = MMR3PhysRelocate(pVM, pData->GCPhysVMMDevRAM, GCPhysAddress, VMMDEV_RAM_SIZE);
1481 if (VBOX_SUCCESS(rc))
1482 {
1483 pData->GCPhysVMMDevRAM = GCPhysAddress;
1484 return VINF_SUCCESS;
1485 }
1486 AssertReleaseMsgFailed(("Failed to relocate VMMDev RAM from %VGp to %VGp! rc=%Vra\n", pData->GCPhysVMMDevRAM, GCPhysAddress, rc));
1487 }
1488 else
1489 {
1490 /*
1491 * Register and lock the VMMDevRAM.
1492 */
1493 /** @todo MM_RAM_FLAGS_MMIO2 seems to be appropriate for a RW memory.
1494 * Need to check. May be a RO memory is enough for the device.
1495 */
1496 rc = MMR3PhysRegister(pVM, pData->pVMMDevRAMHC, GCPhysAddress, VMMDEV_RAM_SIZE, MM_RAM_FLAGS_MMIO2, "VBoxDev");
1497 if (VBOX_SUCCESS(rc))
1498 {
1499 pData->GCPhysVMMDevRAM = GCPhysAddress;
1500 return VINF_SUCCESS;
1501 }
1502 AssertReleaseMsgFailed(("Failed to register VMMDev RAM! rc=%Vra\n", rc));
1503 }
1504 return rc;
1505 }
1506
1507 AssertReleaseMsgFailed(("VMMDev wrong region type: iRegion=%d enmType=%d\n", iRegion, enmType));
1508 return VERR_INTERNAL_ERROR;
1509}
1510
1511
1512/**
1513 * Callback function for mapping a PCI I/O region.
1514 *
1515 * @return VBox status code.
1516 * @param pPciDev Pointer to PCI device. Use pPciDev->pDevIns to get the device instance.
1517 * @param iRegion The region number.
1518 * @param GCPhysAddress Physical address of the region. If iType is PCI_ADDRESS_SPACE_IO, this is an
1519 * I/O port, else it's a physical address.
1520 * This address is *NOT* relative to pci_mem_base like earlier!
1521 * @param enmType One of the PCI_ADDRESS_SPACE_* values.
1522 */
1523static DECLCALLBACK(int) vmmdevIOPortRegionMap(PPCIDEVICE pPciDev, /*unsigned*/ int iRegion, RTGCPHYS GCPhysAddress, uint32_t cb, PCIADDRESSSPACE enmType)
1524{
1525 VMMDevState *pData = PCIDEV_2_VMMDEVSTATE(pPciDev);
1526 int rc = VINF_SUCCESS;
1527
1528 Assert(enmType == PCI_ADDRESS_SPACE_IO);
1529 Assert(iRegion == 0);
1530 AssertMsg(RT_ALIGN(GCPhysAddress, 8) == GCPhysAddress, ("Expected 8 byte alignment. GCPhysAddress=%#x\n", GCPhysAddress));
1531
1532 /*
1533 * Save the base port address to simplify Port offset calculations.
1534 */
1535 pData->PortBase = (RTIOPORT)GCPhysAddress;
1536
1537 /*
1538 * Register our port IO handlers.
1539 */
1540 rc = PDMDevHlpIOPortRegister(pPciDev->pDevIns,
1541 (RTIOPORT)GCPhysAddress + PORT_VMMDEV_REQUEST_OFFSET, 1,
1542 (void*)pData, vmmdevRequestHandler,
1543 NULL, NULL, NULL, "VMMDev Request Handler");
1544 AssertRC(rc);
1545 return rc;
1546}
1547
1548/**
1549 * Queries an interface to the driver.
1550 *
1551 * @returns Pointer to interface.
1552 * @returns NULL if the interface was not supported by the driver.
1553 * @param pInterface Pointer to this interface structure.
1554 * @param enmInterface The requested interface identification.
1555 * @thread Any thread.
1556 */
1557static DECLCALLBACK(void *) vmmdevPortQueryInterface(PPDMIBASE pInterface, PDMINTERFACE enmInterface)
1558{
1559 VMMDevState *pData = (VMMDevState*)((uintptr_t)pInterface - RT_OFFSETOF(VMMDevState, Base));
1560 switch (enmInterface)
1561 {
1562 case PDMINTERFACE_BASE:
1563 return &pData->Base;
1564 case PDMINTERFACE_VMMDEV_PORT:
1565 return &pData->Port;
1566#ifdef VBOX_HGCM
1567 case PDMINTERFACE_HGCM_PORT:
1568 return &pData->HGCMPort;
1569#endif
1570 case PDMINTERFACE_LED_PORTS:
1571 /* Currently only for shared folders */
1572 return &pData->SharedFolders.ILeds;
1573 default:
1574 return NULL;
1575 }
1576}
1577
1578/**
1579 * Gets the pointer to the status LED of a unit.
1580 *
1581 * @returns VBox status code.
1582 * @param pInterface Pointer to the interface structure containing the called function pointer.
1583 * @param iLUN The unit which status LED we desire.
1584 * @param ppLed Where to store the LED pointer.
1585 */
1586static DECLCALLBACK(int) vmmdevQueryStatusLed(PPDMILEDPORTS pInterface, unsigned iLUN, PPDMLED *ppLed)
1587{
1588 VMMDevState *pData = (VMMDevState *)( (uintptr_t)pInterface - RT_OFFSETOF(VMMDevState, SharedFolders.ILeds) );
1589 if (iLUN == 0) /* LUN 0 is shared folders */
1590 {
1591 *ppLed = &pData->SharedFolders.Led;
1592 return VINF_SUCCESS;
1593 }
1594 return VERR_PDM_LUN_NOT_FOUND;
1595}
1596
1597/* -=-=-=-=-=- IVMMDevPort -=-=-=-=-=- */
1598
1599/** Converts a VMMDev port interface pointer to a VMMDev state pointer. */
1600#define IVMMDEVPORT_2_VMMDEVSTATE(pInterface) ( (VMMDevState*)((uintptr_t)pInterface - RT_OFFSETOF(VMMDevState, Port)) )
1601
1602
1603/**
1604 * Return the current absolute mouse position in pixels
1605 *
1606 * @returns VBox status code
1607 * @param pAbsX Pointer of result value, can be NULL
1608 * @param pAbsY Pointer of result value, can be NULL
1609 */
1610static DECLCALLBACK(int) vmmdevQueryAbsoluteMouse(PPDMIVMMDEVPORT pInterface, uint32_t *pAbsX, uint32_t *pAbsY)
1611{
1612 VMMDevState *pData = IVMMDEVPORT_2_VMMDEVSTATE(pInterface);
1613 if (pAbsX)
1614 *pAbsX = pData->mouseXAbs;
1615 if (pAbsY)
1616 *pAbsY = pData->mouseYAbs;
1617 return VINF_SUCCESS;
1618}
1619
1620/**
1621 * Set the new absolute mouse position in pixels
1622 *
1623 * @returns VBox status code
1624 * @param absX New absolute X position
1625 * @param absY New absolute Y position
1626 */
1627static DECLCALLBACK(int) vmmdevSetAbsoluteMouse(PPDMIVMMDEVPORT pInterface, uint32_t absX, uint32_t absY)
1628{
1629 VMMDevState *pData = IVMMDEVPORT_2_VMMDEVSTATE(pInterface);
1630 Log2(("vmmdevSetAbsoluteMouse: settings absolute position to x = %d, y = %d\n", absX, absY));
1631 pData->mouseXAbs = absX;
1632 pData->mouseYAbs = absY;
1633 return VINF_SUCCESS;
1634}
1635
1636/**
1637 * Return the current mouse capability flags
1638 *
1639 * @returns VBox status code
1640 * @param pCapabilities Pointer of result value
1641 */
1642static DECLCALLBACK(int) vmmdevQueryMouseCapabilities(PPDMIVMMDEVPORT pInterface, uint32_t *pCapabilities)
1643{
1644 VMMDevState *pData = IVMMDEVPORT_2_VMMDEVSTATE(pInterface);
1645 if (!pCapabilities)
1646 return VERR_INVALID_PARAMETER;
1647 *pCapabilities = pData->mouseCapabilities;
1648 return VINF_SUCCESS;
1649}
1650
1651/**
1652 * Set the current mouse capability flag (host side)
1653 *
1654 * @returns VBox status code
1655 * @param capabilities Capability mask
1656 */
1657static DECLCALLBACK(int) vmmdevSetMouseCapabilities(PPDMIVMMDEVPORT pInterface, uint32_t capabilities)
1658{
1659 VMMDevState *pData = IVMMDEVPORT_2_VMMDEVSTATE(pInterface);
1660
1661 bool bCapsChanged = ((capabilities & VMMDEV_MOUSEHOSTWANTSABS)
1662 != (pData->mouseCapabilities & VMMDEV_MOUSEHOSTWANTSABS));
1663
1664 Log(("vmmdevSetMouseCapabilities: bCapsChanged %d\n", bCapsChanged));
1665
1666 if (capabilities & VMMDEV_MOUSEHOSTCANNOTHWPOINTER)
1667 pData->mouseCapabilities |= VMMDEV_MOUSEHOSTCANNOTHWPOINTER;
1668 else
1669 pData->mouseCapabilities &= ~VMMDEV_MOUSEHOSTCANNOTHWPOINTER;
1670
1671 if (capabilities & VMMDEV_MOUSEHOSTWANTSABS)
1672 pData->mouseCapabilities |= VMMDEV_MOUSEHOSTWANTSABS;
1673 else
1674 pData->mouseCapabilities &= ~VMMDEV_MOUSEHOSTWANTSABS;
1675
1676 if (bCapsChanged)
1677 VMMDevNotifyGuest (pData, VMMDEV_EVENT_MOUSE_CAPABILITIES_CHANGED);
1678
1679 return VINF_SUCCESS;
1680}
1681
1682
1683static DECLCALLBACK(int) vmmdevRequestDisplayChange(PPDMIVMMDEVPORT pInterface, uint32_t xres, uint32_t yres, uint32_t bpp, uint32_t display)
1684{
1685 VMMDevState *pData = IVMMDEVPORT_2_VMMDEVSTATE(pInterface);
1686
1687 /* Verify that the new resolution is different and that guest does not yet know about it. */
1688 bool fSameResolution = (!xres || (pData->lastReadDisplayChangeRequest.xres == xres)) &&
1689 (!yres || (pData->lastReadDisplayChangeRequest.yres == yres)) &&
1690 (!bpp || (pData->lastReadDisplayChangeRequest.bpp == bpp)) &&
1691 pData->lastReadDisplayChangeRequest.display == display;
1692
1693 if (!xres && !yres && !bpp)
1694 {
1695 /* Special case of reset video mode. */
1696 fSameResolution = false;
1697 }
1698
1699#ifdef DEBUG_sunlover
1700 Log(("vmmdevRequestDisplayChange: same=%d. new: xres=%d, yres=%d, bpp=%d, display=%d. old: xres=%d, yres=%d, bpp=%d, display=%d.\n",
1701 fSameResolution, xres, yres, bpp, display, pData->lastReadDisplayChangeRequest.xres, pData->lastReadDisplayChangeRequest.yres, pData->lastReadDisplayChangeRequest.bpp, pData->lastReadDisplayChangeRequest.display));
1702#endif /* DEBUG_sunlover */
1703
1704 if (!fSameResolution)
1705 {
1706 LogRel(("VMMDev::SetVideoModeHint: got a video mode hint (%dx%dx%d) at %d\n",
1707 xres, yres, bpp, display));
1708
1709 /* we could validate the information here but hey, the guest can do that as well! */
1710 pData->displayChangeRequest.xres = xres;
1711 pData->displayChangeRequest.yres = yres;
1712 pData->displayChangeRequest.bpp = bpp;
1713 pData->displayChangeRequest.display = display;
1714
1715 /* IRQ so the guest knows what's going on */
1716 VMMDevNotifyGuest (pData, VMMDEV_EVENT_DISPLAY_CHANGE_REQUEST);
1717 }
1718
1719 return VINF_SUCCESS;
1720}
1721
1722static DECLCALLBACK(int) vmmdevRequestSeamlessChange(PPDMIVMMDEVPORT pInterface, bool fEnabled)
1723{
1724 VMMDevState *pData = IVMMDEVPORT_2_VMMDEVSTATE(pInterface);
1725
1726 /* Verify that the new resolution is different and that guest does not yet know about it. */
1727 bool fSameMode = (pData->fLastSeamlessEnabled == fEnabled);
1728
1729 Log(("vmmdevRequestSeamlessChange: same=%d. new=%d\n", fSameMode, fEnabled));
1730
1731 if (!fSameMode)
1732 {
1733 /* we could validate the information here but hey, the guest can do that as well! */
1734 pData->fSeamlessEnabled = fEnabled;
1735
1736 /* IRQ so the guest knows what's going on */
1737 VMMDevNotifyGuest (pData, VMMDEV_EVENT_SEAMLESS_MODE_CHANGE_REQUEST);
1738 }
1739
1740 return VINF_SUCCESS;
1741}
1742
1743static DECLCALLBACK(int) vmmdevSetMemoryBalloon(PPDMIVMMDEVPORT pInterface, uint32_t ulBalloonSize)
1744{
1745 VMMDevState *pData = IVMMDEVPORT_2_VMMDEVSTATE(pInterface);
1746
1747 /* Verify that the new resolution is different and that guest does not yet know about it. */
1748 bool fSame = (pData->u32LastMemoryBalloonSize == ulBalloonSize);
1749
1750 Log(("vmmdevSetMemoryBalloon: old=%d. new=%d\n", pData->u32LastMemoryBalloonSize, ulBalloonSize));
1751
1752 if (!fSame)
1753 {
1754 /* we could validate the information here but hey, the guest can do that as well! */
1755 pData->u32MemoryBalloonSize = ulBalloonSize;
1756
1757 /* IRQ so the guest knows what's going on */
1758 VMMDevNotifyGuest (pData, VMMDEV_EVENT_BALLOON_CHANGE_REQUEST);
1759 }
1760
1761 return VINF_SUCCESS;
1762}
1763
1764static DECLCALLBACK(int) vmmdevVRDPChange(PPDMIVMMDEVPORT pInterface, bool fVRDPEnabled, uint32_t u32VRDPExperienceLevel)
1765{
1766 VMMDevState *pData = IVMMDEVPORT_2_VMMDEVSTATE(pInterface);
1767
1768 bool fSame = (pData->fVRDPEnabled == fVRDPEnabled);
1769
1770 Log(("vmmdevVRDPChange: old=%d. new=%d\n", pData->fVRDPEnabled, fVRDPEnabled));
1771
1772 if (!fSame)
1773 {
1774 pData->fVRDPEnabled = fVRDPEnabled;
1775 pData->u32VRDPExperienceLevel = u32VRDPExperienceLevel;
1776
1777 VMMDevNotifyGuest (pData, VMMDEV_EVENT_VRDP);
1778 }
1779
1780 return VINF_SUCCESS;
1781}
1782
1783static DECLCALLBACK(int) vmmdevSetStatisticsInterval(PPDMIVMMDEVPORT pInterface, uint32_t ulStatInterval)
1784{
1785 VMMDevState *pData = IVMMDEVPORT_2_VMMDEVSTATE(pInterface);
1786
1787 /* Verify that the new resolution is different and that guest does not yet know about it. */
1788 bool fSame = (pData->u32LastStatIntervalSize == ulStatInterval);
1789
1790 Log(("vmmdevSetStatisticsInterval: old=%d. new=%d\n", pData->u32LastStatIntervalSize, ulStatInterval));
1791
1792 if (!fSame)
1793 {
1794 /* we could validate the information here but hey, the guest can do that as well! */
1795 pData->u32StatIntervalSize = ulStatInterval;
1796
1797 /* IRQ so the guest knows what's going on */
1798 VMMDevNotifyGuest (pData, VMMDEV_EVENT_STATISTICS_INTERVAL_CHANGE_REQUEST);
1799 }
1800
1801 return VINF_SUCCESS;
1802}
1803
1804
1805static DECLCALLBACK(int) vmmdevSetCredentials(PPDMIVMMDEVPORT pInterface, const char *pszUsername,
1806 const char *pszPassword, const char *pszDomain,
1807 uint32_t u32Flags)
1808{
1809 VMMDevState *pData = IVMMDEVPORT_2_VMMDEVSTATE(pInterface);
1810
1811 /* logon mode? */
1812 if (u32Flags & VMMDEV_SETCREDENTIALS_GUESTLOGON)
1813 {
1814 /* memorize the data */
1815 strcpy(pData->credentialsLogon.szUserName, pszUsername);
1816 strcpy(pData->credentialsLogon.szPassword, pszPassword);
1817 strcpy(pData->credentialsLogon.szDomain, pszDomain);
1818 pData->credentialsLogon.fAllowInteractiveLogon = !(u32Flags & VMMDEV_SETCREDENTIALS_NOLOCALLOGON);
1819 }
1820 /* credentials verification mode? */
1821 else if (u32Flags & VMMDEV_SETCREDENTIALS_JUDGE)
1822 {
1823 /* memorize the data */
1824 strcpy(pData->credentialsJudge.szUserName, pszUsername);
1825 strcpy(pData->credentialsJudge.szPassword, pszPassword);
1826 strcpy(pData->credentialsJudge.szDomain, pszDomain);
1827
1828 VMMDevNotifyGuest (pData, VMMDEV_EVENT_JUDGE_CREDENTIALS);
1829 }
1830 else
1831 return VERR_INVALID_PARAMETER;
1832
1833 return VINF_SUCCESS;
1834}
1835
1836/**
1837 * Notification from the Display. Especially useful when
1838 * acceleration is disabled after a video mode change.
1839 *
1840 * @param fEnable Current acceleration status.
1841 */
1842static DECLCALLBACK(void) vmmdevVBVAChange(PPDMIVMMDEVPORT pInterface, bool fEnabled)
1843{
1844 VMMDevState *pData = IVMMDEVPORT_2_VMMDEVSTATE(pInterface);
1845
1846 Log(("vmmdevVBVAChange: fEnabled = %d\n", fEnabled));
1847
1848 if (pData)
1849 {
1850 pData->u32VideoAccelEnabled = fEnabled;
1851 }
1852
1853 return;
1854}
1855
1856
1857/* -=-=-=-=-=- IHGCMPort -=-=-=-=-=- */
1858
1859/** Converts a VMMDev port interface pointer to a VMMDev state pointer. */
1860#define IHGCMPORT_2_VMMDEVSTATE(pInterface) ( (VMMDevState*)((uintptr_t)pInterface - RT_OFFSETOF(VMMDevState, HGCMPort)) )
1861
1862
1863
1864#define VMMDEV_SSM_VERSION 5
1865
1866/**
1867 * Saves a state of the VMM device.
1868 *
1869 * @returns VBox status code.
1870 * @param pDevIns The device instance.
1871 * @param pSSMHandle The handle to save the state to.
1872 */
1873static DECLCALLBACK(int) vmmdevSaveState(PPDMDEVINS pDevIns, PSSMHANDLE pSSMHandle)
1874{
1875 VMMDevState *pData = PDMINS2DATA(pDevIns, VMMDevState*);
1876 SSMR3PutU32(pSSMHandle, pData->hypervisorSize);
1877 SSMR3PutU32(pSSMHandle, pData->mouseCapabilities);
1878 SSMR3PutU32(pSSMHandle, pData->mouseXAbs);
1879 SSMR3PutU32(pSSMHandle, pData->mouseYAbs);
1880
1881 SSMR3PutBool(pSSMHandle, pData->fNewGuestFilterMask);
1882 SSMR3PutU32(pSSMHandle, pData->u32NewGuestFilterMask);
1883 SSMR3PutU32(pSSMHandle, pData->u32GuestFilterMask);
1884 SSMR3PutU32(pSSMHandle, pData->u32HostEventFlags);
1885 // here be dragons (probably)
1886// SSMR3PutBool(pSSMHandle, pData->pVMMDevRAMHC->V.V1_04.fHaveEvents);
1887 SSMR3PutMem(pSSMHandle, &pData->pVMMDevRAMHC->V, sizeof (pData->pVMMDevRAMHC->V));
1888
1889 SSMR3PutMem(pSSMHandle, &pData->guestInfo, sizeof (pData->guestInfo));
1890 SSMR3PutU32(pSSMHandle, pData->fu32AdditionsOk);
1891 SSMR3PutU32(pSSMHandle, pData->u32VideoAccelEnabled);
1892
1893 SSMR3PutU32(pSSMHandle, pData->guestCaps);
1894
1895#ifdef VBOX_HGCM
1896 vmmdevHGCMSaveState (pData, pSSMHandle);
1897#endif /* VBOX_HGCM */
1898
1899 return VINF_SUCCESS;
1900}
1901
1902/**
1903 * Loads the saved VMM device state.
1904 *
1905 * @returns VBox status code.
1906 * @param pDevIns The device instance.
1907 * @param pSSMHandle The handle to the saved state.
1908 * @param u32Version The data unit version number.
1909 */
1910static DECLCALLBACK(int) vmmdevLoadState(PPDMDEVINS pDevIns, PSSMHANDLE pSSMHandle, uint32_t u32Version)
1911{
1912 VMMDevState *pData = PDMINS2DATA(pDevIns, VMMDevState*);
1913 if (u32Version != VMMDEV_SSM_VERSION)
1914 return VERR_SSM_UNSUPPORTED_DATA_UNIT_VERSION;
1915 SSMR3GetU32(pSSMHandle, &pData->hypervisorSize);
1916 SSMR3GetU32(pSSMHandle, &pData->mouseCapabilities);
1917 SSMR3GetU32(pSSMHandle, &pData->mouseXAbs);
1918 SSMR3GetU32(pSSMHandle, &pData->mouseYAbs);
1919
1920 SSMR3GetBool(pSSMHandle, &pData->fNewGuestFilterMask);
1921 SSMR3GetU32(pSSMHandle, &pData->u32NewGuestFilterMask);
1922 SSMR3GetU32(pSSMHandle, &pData->u32GuestFilterMask);
1923 SSMR3GetU32(pSSMHandle, &pData->u32HostEventFlags);
1924// SSMR3GetBool(pSSMHandle, &pData->pVMMDevRAMHC->fHaveEvents);
1925 // here be dragons (probably)
1926 SSMR3GetMem(pSSMHandle, &pData->pVMMDevRAMHC->V, sizeof (pData->pVMMDevRAMHC->V));
1927
1928 SSMR3GetMem(pSSMHandle, &pData->guestInfo, sizeof (pData->guestInfo));
1929 SSMR3GetU32(pSSMHandle, &pData->fu32AdditionsOk);
1930 SSMR3GetU32(pSSMHandle, &pData->u32VideoAccelEnabled);
1931
1932 SSMR3GetU32(pSSMHandle, &pData->guestCaps);
1933
1934#ifdef VBOX_HGCM
1935 vmmdevHGCMLoadState (pData, pSSMHandle);
1936#endif /* VBOX_HGCM */
1937
1938 /*
1939 * On a resume, we send the capabilities changed message so
1940 * that listeners can sync their state again
1941 */
1942 Log(("vmmdevLoadState: capabilities changed (%x), informing connector\n", pData->mouseCapabilities));
1943 if (pData->pDrv)
1944 pData->pDrv->pfnUpdateMouseCapabilities(pData->pDrv, pData->mouseCapabilities);
1945
1946 /* Reestablish the acceleration status. */
1947 if ( pData->u32VideoAccelEnabled
1948 && pData->pDrv)
1949 {
1950 pData->pDrv->pfnVideoAccelEnable (pData->pDrv, !!pData->u32VideoAccelEnabled, &pData->pVMMDevRAMHC->vbvaMemory);
1951 }
1952
1953 if (pData->fu32AdditionsOk)
1954 {
1955 LogRel(("Guest Additions information report: additionsVersion = 0x%08X osType = 0x%08X\n",
1956 pData->guestInfo.additionsVersion,
1957 pData->guestInfo.osType));
1958 if (pData->pDrv)
1959 pData->pDrv->pfnUpdateGuestVersion(pData->pDrv, &pData->guestInfo);
1960 }
1961 if (pData->pDrv)
1962 pData->pDrv->pfnUpdateGuestCapabilities(pData->pDrv, pData->guestCaps);
1963
1964 return VINF_SUCCESS;
1965}
1966
1967/**
1968 * Load state done callback. Notify guest of restore event.
1969 *
1970 * @returns VBox status code.
1971 * @param pDevIns The device instance.
1972 * @param pSSMHandle The handle to the saved state.
1973 */
1974static DECLCALLBACK(int) vmmdevLoadStateDone(PPDMDEVINS pDevIns, PSSMHANDLE pSSMHandle)
1975{
1976 VMMDevState *pData = PDMINS2DATA(pDevIns, VMMDevState*);
1977
1978#ifdef VBOX_HGCM
1979 vmmdevHGCMLoadStateDone (pData, pSSMHandle);
1980#endif /* VBOX_HGCM */
1981
1982 VMMDevNotifyGuest (pData, VMMDEV_EVENT_RESTORED);
1983
1984 return VINF_SUCCESS;
1985}
1986
1987/**
1988 * Construct a device instance for a VM.
1989 *
1990 * @returns VBox status.
1991 * @param pDevIns The device instance data.
1992 * If the registration structure is needed, pDevIns->pDevReg points to it.
1993 * @param iInstance Instance number. Use this to figure out which registers and such to use.
1994 * The device number is also found in pDevIns->iInstance, but since it's
1995 * likely to be freqently used PDM passes it as parameter.
1996 * @param pCfgHandle Configuration node handle for the device. Use this to obtain the configuration
1997 * of the device instance. It's also found in pDevIns->pCfgHandle, but like
1998 * iInstance it's expected to be used a bit in this function.
1999 */
2000static DECLCALLBACK(int) vmmdevConstruct(PPDMDEVINS pDevIns, int iInstance, PCFGMNODE pCfgHandle)
2001{
2002 int rc;
2003 VMMDevState *pData = PDMINS2DATA(pDevIns, VMMDevState *);
2004
2005 Assert(iInstance == 0);
2006
2007 /*
2008 * Validate and read the configuration.
2009 */
2010 if (!CFGMR3AreValuesValid(pCfgHandle, "GetHostTimeDisabled\0BackdoorLogDisabled\0"))
2011 return VERR_PDM_DEVINS_UNKNOWN_CFG_VALUES;
2012
2013 rc = CFGMR3QueryBool(pCfgHandle, "GetHostTimeDisabled", &pData->fGetHostTimeDisabled);
2014 if (rc == VERR_CFGM_VALUE_NOT_FOUND)
2015 pData->fGetHostTimeDisabled = false;
2016 else if (VBOX_FAILURE(rc))
2017 return PDMDEV_SET_ERROR(pDevIns, rc,
2018 N_("Configuration error: Failed querying \"GetHostTimeDisabled\" as a boolean"));
2019
2020 rc = CFGMR3QueryBool(pCfgHandle, "BackdoorLogDisabled", &pData->fBackdoorLogDisabled);
2021 if (rc == VERR_CFGM_VALUE_NOT_FOUND)
2022 pData->fBackdoorLogDisabled = false;
2023 else if (VBOX_FAILURE(rc))
2024 return PDMDEV_SET_ERROR(pDevIns, rc,
2025 N_("Configuration error: Failed querying \"BackdoorLogDisabled\" as a boolean"));
2026
2027 /*
2028 * Initialize data (most of it anyway).
2029 */
2030 /* Save PDM device instance data for future reference. */
2031 pData->pDevIns = pDevIns;
2032
2033 /* PCI vendor, just a free bogus value */
2034 pData->dev.config[0x00] = 0xee;
2035 pData->dev.config[0x01] = 0x80;
2036 /* device ID */
2037 pData->dev.config[0x02] = 0xfe;
2038 pData->dev.config[0x03] = 0xca;
2039 /* class sub code (other type of system peripheral) */
2040 pData->dev.config[0x0a] = 0x80;
2041 /* class base code (base system peripheral) */
2042 pData->dev.config[0x0b] = 0x08;
2043 /* header type */
2044 pData->dev.config[0x0e] = 0x00;
2045 /* interrupt on pin 0 */
2046 pData->dev.config[0x3d] = 0x01;
2047
2048 /*
2049 * Register the backdoor logging port
2050 */
2051 rc = PDMDevHlpIOPortRegister(pDevIns, RTLOG_DEBUG_PORT, 1, NULL, vmmdevBackdoorLog, NULL, NULL, NULL, "VMMDev backdoor logging");
2052 AssertRCReturn(rc, rc);
2053
2054#ifdef TIMESYNC_BACKDOOR
2055 /*
2056 * Alternative timesync source (temporary!)
2057 */
2058 rc = PDMDevHlpIOPortRegister(pDevIns, 0x505, 1, NULL, vmmdevTimesyncBackdoorWrite, vmmdevTimesyncBackdoorRead, NULL, NULL, "VMMDev timesync backdoor");
2059 AssertRCReturn(rc, rc);
2060#endif
2061
2062 /*
2063 * Register the PCI device.
2064 */
2065 rc = PDMDevHlpPCIRegister(pDevIns, &pData->dev);
2066 if (VBOX_FAILURE(rc))
2067 return rc;
2068 if (pData->dev.devfn == 32 || iInstance != 0)
2069 Log(("!!WARNING!!: pData->dev.devfn=%d (ignore if testcase or no started by Main)\n", pData->dev.devfn));
2070 rc = PDMDevHlpPCIIORegionRegister(pDevIns, 0, 0x20, PCI_ADDRESS_SPACE_IO, vmmdevIOPortRegionMap);
2071 if (VBOX_FAILURE(rc))
2072 return rc;
2073 rc = PDMDevHlpPCIIORegionRegister(pDevIns, 1, VMMDEV_RAM_SIZE, PCI_ADDRESS_SPACE_MEM, vmmdevIORAMRegionMap);
2074 if (VBOX_FAILURE(rc))
2075 return rc;
2076
2077 /*
2078 * Interfaces
2079 */
2080 /* Base */
2081 pData->Base.pfnQueryInterface = vmmdevPortQueryInterface;
2082
2083 /* VMMDev port */
2084 pData->Port.pfnQueryAbsoluteMouse = vmmdevQueryAbsoluteMouse;
2085 pData->Port.pfnSetAbsoluteMouse = vmmdevSetAbsoluteMouse;
2086 pData->Port.pfnQueryMouseCapabilities = vmmdevQueryMouseCapabilities;
2087 pData->Port.pfnSetMouseCapabilities = vmmdevSetMouseCapabilities;
2088 pData->Port.pfnRequestDisplayChange = vmmdevRequestDisplayChange;
2089 pData->Port.pfnSetCredentials = vmmdevSetCredentials;
2090 pData->Port.pfnVBVAChange = vmmdevVBVAChange;
2091 pData->Port.pfnRequestSeamlessChange = vmmdevRequestSeamlessChange;
2092 pData->Port.pfnSetMemoryBalloon = vmmdevSetMemoryBalloon;
2093 pData->Port.pfnSetStatisticsInterval = vmmdevSetStatisticsInterval;
2094 pData->Port.pfnVRDPChange = vmmdevVRDPChange;
2095
2096 /* Shared folder LED */
2097 pData->SharedFolders.Led.u32Magic = PDMLED_MAGIC;
2098 pData->SharedFolders.ILeds.pfnQueryStatusLed = vmmdevQueryStatusLed;
2099
2100#ifdef VBOX_HGCM
2101 /* HGCM port */
2102 pData->HGCMPort.pfnCompleted = hgcmCompleted;
2103#endif
2104
2105 /*
2106 * Get the corresponding connector interface
2107 */
2108 rc = PDMDevHlpDriverAttach(pDevIns, 0, &pData->Base, &pData->pDrvBase, "VMM Driver Port");
2109 if (VBOX_SUCCESS(rc))
2110 {
2111 pData->pDrv = (PPDMIVMMDEVCONNECTOR)pData->pDrvBase->pfnQueryInterface(pData->pDrvBase, PDMINTERFACE_VMMDEV_CONNECTOR);
2112 if (!pData->pDrv)
2113 AssertMsgFailedReturn(("LUN #0 doesn't have a VMMDev connector interface!\n"), VERR_PDM_MISSING_INTERFACE);
2114#ifdef VBOX_HGCM
2115 pData->pHGCMDrv = (PPDMIHGCMCONNECTOR)pData->pDrvBase->pfnQueryInterface(pData->pDrvBase, PDMINTERFACE_HGCM_CONNECTOR);
2116 if (!pData->pHGCMDrv)
2117 {
2118 Log(("LUN #0 doesn't have a HGCM connector interface, HGCM is not supported. rc=%Vrc\n", rc));
2119 /* this is not actually an error, just means that there is no support for HGCM */
2120 }
2121#endif
2122 }
2123 else if (rc == VERR_PDM_NO_ATTACHED_DRIVER)
2124 {
2125 Log(("%s/%d: warning: no driver attached to LUN #0!\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
2126 rc = VINF_SUCCESS;
2127 }
2128 else
2129 AssertMsgFailedReturn(("Failed to attach LUN #0! rc=%Vrc\n", rc), rc);
2130
2131 /*
2132 * Attach status driver for shared folders (optional).
2133 */
2134 PPDMIBASE pBase;
2135 rc = PDMDevHlpDriverAttach(pDevIns, PDM_STATUS_LUN, &pData->Base, &pBase, "Status Port");
2136 if (VBOX_SUCCESS(rc))
2137 pData->SharedFolders.pLedsConnector = (PPDMILEDCONNECTORS)
2138 pBase->pfnQueryInterface(pBase, PDMINTERFACE_LED_CONNECTORS);
2139 else if (rc != VERR_PDM_NO_ATTACHED_DRIVER)
2140 {
2141 AssertMsgFailed(("Failed to attach to status driver. rc=%Vrc\n", rc));
2142 return rc;
2143 }
2144
2145 /*
2146 * Register saved state and init the HGCM CmdList critsect.
2147 */
2148 rc = PDMDevHlpSSMRegister(pDevIns, "VMMDev", iInstance, VMMDEV_SSM_VERSION, sizeof(*pData),
2149 NULL, vmmdevSaveState, NULL,
2150 NULL, vmmdevLoadState, vmmdevLoadStateDone);
2151 AssertRCReturn(rc, rc);
2152
2153#ifdef VBOX_HGCM
2154 pData->pHGCMCmdList = NULL;
2155 rc = RTCritSectInit(&pData->critsectHGCMCmdList);
2156 AssertRCReturn(rc, rc);
2157 pData->u32HGCMEnabled = 0;
2158#endif /* VBOX_HGCM */
2159
2160 /*
2161 * Allocate the VMMDev RAM region.
2162 */
2163 /** @todo freeing of the RAM. */
2164 rc = SUPPageAlloc(VMMDEV_RAM_SIZE >> PAGE_SHIFT, (void **)&pData->pVMMDevRAMHC);
2165 AssertMsgRCReturn(rc, ("VMMDev SUPPageAlloc(%#x,) -> %Vrc\n", VMMDEV_RAM_SIZE, rc), rc);
2166
2167 /* initialize the VMMDev memory */
2168 pData->pVMMDevRAMHC->u32Size = sizeof (VMMDevMemory);
2169 pData->pVMMDevRAMHC->u32Version = VMMDEV_MEMORY_VERSION;
2170
2171 return rc;
2172}
2173
2174/**
2175 * Reset notification.
2176 *
2177 * @returns VBox status.
2178 * @param pDrvIns The driver instance data.
2179 */
2180static DECLCALLBACK(void) vmmdevReset(PPDMDEVINS pDevIns)
2181{
2182 VMMDevState *pData = PDMINS2DATA(pDevIns, VMMDevState*);
2183 /*
2184 * Reset the mouse integration feature bit
2185 */
2186 if (pData->mouseCapabilities & (VMMDEV_MOUSEGUESTWANTSABS|VMMDEV_MOUSEGUESTNEEDSHOSTCUR))
2187 {
2188 pData->mouseCapabilities &= ~VMMDEV_MOUSEGUESTWANTSABS;
2189 /* notify the connector */
2190 Log(("vmmdevReset: capabilities changed (%x), informing connector\n", pData->mouseCapabilities));
2191 pData->pDrv->pfnUpdateMouseCapabilities(pData->pDrv, pData->mouseCapabilities);
2192 }
2193
2194 pData->hypervisorSize = 0;
2195
2196 pData->u32HostEventFlags = 0;
2197
2198 if (pData->pVMMDevRAMHC)
2199 {
2200 /* re-initialize the VMMDev memory */
2201 memset (pData->pVMMDevRAMHC, 0, VMMDEV_RAM_SIZE);
2202 pData->pVMMDevRAMHC->u32Size = sizeof (VMMDevMemory);
2203 pData->pVMMDevRAMHC->u32Version = VMMDEV_MEMORY_VERSION;
2204 }
2205
2206 /* credentials have to go away */
2207 memset(pData->credentialsLogon.szUserName, '\0', VMMDEV_CREDENTIALS_STRLEN);
2208 memset(pData->credentialsLogon.szPassword, '\0', VMMDEV_CREDENTIALS_STRLEN);
2209 memset(pData->credentialsLogon.szDomain, '\0', VMMDEV_CREDENTIALS_STRLEN);
2210 memset(pData->credentialsJudge.szUserName, '\0', VMMDEV_CREDENTIALS_STRLEN);
2211 memset(pData->credentialsJudge.szPassword, '\0', VMMDEV_CREDENTIALS_STRLEN);
2212 memset(pData->credentialsJudge.szDomain, '\0', VMMDEV_CREDENTIALS_STRLEN);
2213
2214 /* Reset means that additions will report again. */
2215 pData->fu32AdditionsOk = false;
2216 memset (&pData->guestInfo, 0, sizeof (pData->guestInfo));
2217 pData->guestCaps = 0;
2218
2219 memset (&pData->lastReadDisplayChangeRequest, 0, sizeof (pData->lastReadDisplayChangeRequest));
2220
2221 /* disable seamless mode */
2222 pData->fLastSeamlessEnabled = false;
2223
2224 /* disabled memory ballooning */
2225 pData->u32LastMemoryBalloonSize = 0;
2226
2227 /* disabled statistics updating */
2228 pData->u32LastStatIntervalSize = 0;
2229
2230 /* Clear the event variables.
2231 *
2232 * Note: The pData->u32HostEventFlags is not cleared.
2233 * It is designed that way so host events do not
2234 * depend on guest resets.
2235 */
2236 pData->u32GuestFilterMask = 0;
2237 pData->u32NewGuestFilterMask = 0;
2238 pData->fNewGuestFilterMask = 0;
2239}
2240
2241
2242/**
2243 * The device registration structure.
2244 */
2245extern "C" const PDMDEVREG g_DeviceVMMDev =
2246{
2247 /* u32Version */
2248 PDM_DEVREG_VERSION,
2249 /* szDeviceName */
2250 "VMMDev",
2251 /* szGCMod */
2252 "",
2253 /* szR0Mod */
2254 "",
2255 /* pszDescription */
2256 "VirtualBox VMM Device\n",
2257 /* fFlags */
2258 PDM_DEVREG_FLAGS_HOST_BITS_DEFAULT | PDM_DEVREG_FLAGS_GUEST_BITS_32,
2259 /* fClass */
2260 PDM_DEVREG_CLASS_VMM_DEV,
2261 /* cMaxInstances */
2262 1,
2263 /* cbInstance */
2264 sizeof(VMMDevState),
2265 /* pfnConstruct */
2266 vmmdevConstruct,
2267 /* pfnDestruct */
2268 NULL,
2269 /* pfnRelocate */
2270 NULL,
2271 /* pfnIOCtl */
2272 NULL,
2273 /* pfnPowerOn */
2274 NULL,
2275 /* pfnReset */
2276 vmmdevReset,
2277 /* pfnSuspend */
2278 NULL,
2279 /* pfnResume */
2280 NULL,
2281 /* pfnAttach */
2282 NULL,
2283 /* pfnDetach */
2284 NULL,
2285 /* pfnQueryInterface. */
2286 NULL
2287};
2288#endif /* !VBOX_DEVICE_STRUCT_TESTCASE */
2289
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette