VirtualBox

source: vbox/trunk/src/VBox/Additions/WINNT/VBoxGuest/Helper.cpp@ 18019

Last change on this file since 18019 was 18019, checked in by vboxsync, 16 years ago

VBoxGuest/Windows: Added bugcheck detection + details (not enabled by default yet).

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 11.3 KB
Line 
1/** @file
2 *
3 * VBoxGuest -- VirtualBox Win32 guest support driver
4 *
5 * Copyright (C) 2006-2007 Sun Microsystems, Inc.
6 *
7 * This file is part of VirtualBox Open Source Edition (OSE), as
8 * available from http://www.virtualbox.org. This file is free software;
9 * you can redistribute it and/or modify it under the terms of the GNU
10 * General Public License (GPL) as published by the Free Software
11 * Foundation, in version 2 as it comes in the "COPYING" file of the
12 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
13 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
14 *
15 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
16 * Clara, CA 95054 USA or visit http://www.sun.com if you need
17 * additional information or have any questions.
18 */
19
20//#define LOG_ENABLED
21
22#include "VBoxGuest_Internal.h"
23#include "Helper.h"
24#include <VBox/err.h>
25#include <VBox/log.h>
26#include <VBox/VBoxGuestLib.h>
27
28#ifdef VBOX_WITH_GUEST_BUGCHECK_DETECTION
29 #ifndef TARGET_NT4
30 #include <aux_klib.h>
31 #endif
32#endif
33
34#ifdef ALLOC_PRAGMA
35#pragma alloc_text (PAGE, VBoxScanPCIResourceList)
36#endif
37
38/* CM_RESOURCE_MEMORY_* flags which were used on XP or earlier. */
39#define VBOX_CM_PRE_VISTA_MASK (0x3f)
40
41/**
42 * Helper to scan the PCI resource list and remember stuff.
43 *
44 * @param pResList Resource list
45 * @param pDevExt Device extension
46 */
47NTSTATUS VBoxScanPCIResourceList(PCM_RESOURCE_LIST pResList, PVBOXGUESTDEVEXT pDevExt)
48{
49 NTSTATUS rc = STATUS_SUCCESS;
50 PCM_PARTIAL_RESOURCE_DESCRIPTOR partialData;
51
52 // enumerate the resource list
53 dprintf(("found %d resources\n", pResList->List->PartialResourceList.Count));
54 ULONG rangeCount = 0;
55 ULONG cMMIORange = 0;
56 PBASE_ADDRESS baseAddress = pDevExt->baseAddress;
57 for (ULONG i = 0; i < pResList->List->PartialResourceList.Count; i++)
58 {
59 partialData = &pResList->List->PartialResourceList.PartialDescriptors[i];
60 switch (partialData->Type)
61 {
62 case CmResourceTypePort:
63 {
64 // overflow protection
65 if (rangeCount < PCI_TYPE0_ADDRESSES)
66 {
67 dprintf(("I/O range: Base = %08x : %08x Length = %08x \n",
68 partialData->u.Port.Start.HighPart,
69 partialData->u.Port.Start.LowPart,
70 partialData->u.Port.Length));
71 //@todo not so gut
72 dprintf(("I got all I want, my dear port, oh!\n"));
73 pDevExt->startPortAddress = (ULONG)partialData->u.Port.Start.LowPart;
74 // save resource information
75 baseAddress->RangeStart = partialData->u.Port.Start;
76 baseAddress->RangeLength = partialData->u.Port.Length;
77 baseAddress->RangeInMemory = FALSE;
78 baseAddress->ResourceMapped = FALSE;
79 // next item
80 rangeCount++; baseAddress++;
81 }
82 break;
83 }
84
85 case CmResourceTypeInterrupt:
86 {
87 dprintf(("Interrupt: Level = %x Vector = %x Mode = %x \n",
88 partialData->u.Interrupt.Level,
89 partialData->u.Interrupt.Vector,
90 partialData->Flags));
91 // save information
92 pDevExt->interruptLevel = partialData->u.Interrupt.Level;
93 pDevExt->interruptVector = partialData->u.Interrupt.Vector;
94 pDevExt->interruptAffinity = partialData->u.Interrupt.Affinity;
95 // check interrupt mode
96 if (partialData->Flags & CM_RESOURCE_INTERRUPT_LATCHED)
97 {
98 pDevExt->interruptMode = Latched;
99 }
100 else
101 {
102 pDevExt->interruptMode = LevelSensitive;
103 }
104 break;
105 }
106
107 case CmResourceTypeMemory:
108 {
109 // overflow protection
110 if (rangeCount < PCI_TYPE0_ADDRESSES)
111 {
112 dprintf(("Memory range: Base = %08x : %08x Length = %08x \n",
113 partialData->u.Memory.Start.HighPart,
114 partialData->u.Memory.Start.LowPart,
115 partialData->u.Memory.Length));
116 // we only care about read/write memory
117 /** @todo reconsider memory type */
118 if ( cMMIORange == 0 /* only care about the first mmio range (!!!) */
119 && (partialData->Flags & VBOX_CM_PRE_VISTA_MASK) == CM_RESOURCE_MEMORY_READ_WRITE)
120 {
121 pDevExt->memoryAddress = partialData->u.Memory.Start;
122 pDevExt->memoryLength = (ULONG)partialData->u.Memory.Length;
123 // save resource information
124 baseAddress->RangeStart = partialData->u.Memory.Start;
125 baseAddress->RangeLength = partialData->u.Memory.Length;
126 baseAddress->RangeInMemory = TRUE;
127 baseAddress->ResourceMapped = FALSE;
128 // next item
129 rangeCount++; baseAddress++;cMMIORange++;
130 } else
131 {
132 dprintf(("Ignoring memory: flags = %08x \n", partialData->Flags));
133 }
134 }
135 break;
136 }
137
138 case CmResourceTypeDma:
139 {
140 dprintf(("DMA resource found. Hmm...\n"));
141 break;
142 }
143
144 default:
145 {
146 dprintf(("Unexpected resource found %d. Hmm...\n", partialData->Type));
147 break;
148 }
149 }
150 }
151 // memorize the number of resources found
152 pDevExt->addressCount = rangeCount;
153
154 return rc;
155}
156
157
158NTSTATUS hlpVBoxMapVMMDevMemory (PVBOXGUESTDEVEXT pDevExt)
159{
160 NTSTATUS rc = STATUS_SUCCESS;
161
162 if (pDevExt->memoryLength != 0)
163 {
164 pDevExt->pVMMDevMemory = (VMMDevMemory *)MmMapIoSpace (pDevExt->memoryAddress, pDevExt->memoryLength, MmNonCached);
165 dprintf(("VBoxGuest::VBoxGuestPnp: VMMDevMemory: ptr = 0x%x\n", pDevExt->pVMMDevMemory));
166 if (pDevExt->pVMMDevMemory)
167 {
168 dprintf(("VBoxGuest::VBoxGuestPnp: VMMDevMemory: version = 0x%x, size = %d\n", pDevExt->pVMMDevMemory->u32Version, pDevExt->pVMMDevMemory->u32Size));
169
170 /* Check version of the structure */
171 if (pDevExt->pVMMDevMemory->u32Version != VMMDEV_MEMORY_VERSION)
172 {
173 /* Not our version, refuse operation and unmap the memory */
174 hlpVBoxUnmapVMMDevMemory (pDevExt);
175
176 rc = STATUS_UNSUCCESSFUL;
177 }
178 }
179 else
180 {
181 rc = STATUS_UNSUCCESSFUL;
182 }
183 }
184
185 return rc;
186}
187
188void hlpVBoxUnmapVMMDevMemory (PVBOXGUESTDEVEXT pDevExt)
189{
190 if (pDevExt->pVMMDevMemory)
191 {
192 MmUnmapIoSpace (pDevExt->pVMMDevMemory, pDevExt->memoryLength);
193 pDevExt->pVMMDevMemory = NULL;
194 }
195
196 pDevExt->memoryAddress.QuadPart = 0;
197 pDevExt->memoryLength = 0;
198}
199
200NTSTATUS hlpVBoxReportGuestInfo (PVBOXGUESTDEVEXT pDevExt)
201{
202 VMMDevReportGuestInfo *req = NULL;
203
204 int rc = VbglGRAlloc ((VMMDevRequestHeader **)&req, sizeof (VMMDevReportGuestInfo), VMMDevReq_ReportGuestInfo);
205
206 dprintf(("hlpVBoxReportGuestInfo: VbglGRAlloc rc = %d\n", rc));
207
208 if (RT_SUCCESS(rc))
209 {
210 req->guestInfo.additionsVersion = VMMDEV_VERSION;
211
212 /* we've already determined the Windows product before */
213 switch (winVersion)
214 {
215 case WINNT4:
216 req->guestInfo.osType = VBOXOSTYPE_WinNT4;
217 break;
218 case WIN2K:
219 req->guestInfo.osType = VBOXOSTYPE_Win2k;
220 break;
221 case WINXP:
222 req->guestInfo.osType = VBOXOSTYPE_WinXP;
223 break;
224 case WIN2K3:
225 req->guestInfo.osType = VBOXOSTYPE_Win2k3;
226 break;
227 case WINVISTA:
228 req->guestInfo.osType = VBOXOSTYPE_WinVista;
229 break;
230 default:
231 /* we don't know, therefore NT family */
232 req->guestInfo.osType = VBOXOSTYPE_WinNT;
233 break;
234 }
235
236 /** @todo registry lookup for additional information */
237
238
239 rc = VbglGRPerform (&req->header);
240
241 if (RT_FAILURE(rc) || RT_FAILURE(req->header.rc))
242 {
243 dprintf(("VBoxGuest::hlpVBoxReportGuestInfo: error reporting guest info to VMMDev."
244 "rc = %d, VMMDev rc = %Rrc\n", rc, req->header.rc));
245 }
246
247 rc = RT_SUCCESS(rc) ? req->header.rc : rc;
248
249 VbglGRFree (&req->header);
250 }
251
252 return RT_FAILURE(rc) ? STATUS_UNSUCCESSFUL : STATUS_SUCCESS;
253}
254
255#ifdef VBOX_WITH_GUEST_BUGCHECK_DETECTION
256NTSTATUS hlpRegisterBugCheckCallback (PVBOXGUESTDEVEXT pDevExt)
257{
258 int rc = STATUS_SUCCESS;
259
260 #ifndef TARGET_NT4
261 rc = AuxKlibInitialize();
262 if (NT_ERROR(rc))
263 {
264 dprintf(("VBoxGuest::VBoxGuestAddDevice: Unabled to initialize AuxKlib!\n"));
265 return STATUS_DRIVER_UNABLE_TO_LOAD;
266 }
267 #endif
268
269 /*
270 * Setup bugcheck callback routine ASAP.
271 */
272 pDevExt->bBugcheckCallbackRegistered = FALSE;
273 pDevExt->bugcheckContext = (VBOXBUGCHECKCONTEXT*)ExAllocatePool(NonPagedPool, sizeof(VBOXBUGCHECKCONTEXT));
274 if(!pDevExt->bugcheckContext)
275 {
276 dprintf(("VBoxGuest::VBoxGuestAddDevice: Not enough memory for bugcheck context!\n"));
277 return STATUS_INSUFFICIENT_RESOURCES;
278 }
279
280 KeInitializeCallbackRecord(&pDevExt->bugcheckContext->bugcheckRecord);
281 if (FALSE == KeRegisterBugCheckCallback(&pDevExt->bugcheckContext->bugcheckRecord,
282 &hlpVBoxGuestBugCheckCallback,
283 pDevExt->bugcheckContext,
284 sizeof(VBOXBUGCHECKCONTEXT),
285 (PUCHAR)"VBoxGuest"))
286 {
287 LogRelBackdoor(("Could not register bugcheck callback routine!\n"));
288 }
289 else
290 {
291 pDevExt->bBugcheckCallbackRegistered = TRUE;
292 dprintf(("VBoxGuest::VBoxGuestAddDevice: Bugcheck callback registered.\n"));
293 }
294
295 return rc;
296}
297
298VOID hlpVBoxGuestBugCheckCallback(PVOID pvBuffer, ULONG ulLength)
299{
300 NTSTATUS rc = 0;
301 PVBOXBUGCHECKCONTEXT pContext = (PVBOXBUGCHECKCONTEXT)pvBuffer;
302
303 LogRelBackdoor(("Windows bugcheck (bluescreen) detected!\n"));
304
305#ifndef TARGET_NT4
306 KBUGCHECK_DATA bugcheckData;
307 bugcheckData.BugCheckDataSize = sizeof(KBUGCHECK_DATA);
308 rc = AuxKlibGetBugCheckData(&bugcheckData);
309 if (!RT_SUCCESS(rc))
310 {
311 LogRelBackdoor(("Unable to retrieve bugcheck details! Error: %d\n", rc));
312 return;
313 }
314
315 LogRelBackdoor(("Bugcheck code: 0x%08x\n", bugcheckData.BugCheckCode));
316 LogRelBackdoor(("Bugcheck parameters: 1=%ld 2=%ld 3=%ld 4=%ld\n",
317 bugcheckData.Parameter1,
318 bugcheckData.Parameter2,
319 bugcheckData.Parameter3,
320 bugcheckData.Parameter4));
321#else
322 LogRelBackdoor(("No additional information for Windows NT 4.0 bugcheck available.\n"));
323#endif
324
325 if (pvBuffer)
326 {
327 /* @todo - Not used yet. */
328 }
329
330 /* @todo Notify the host somehow over DevVMM. */
331}
332#endif
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