win-pvdrivers

view xenpci/xenpci.c @ 1030:37c0c84a42e8

Tidy up KdPrints
author James Harper <james.harper@bendigoit.com.au>
date Wed Feb 20 20:49:26 2013 +1100 (2013-02-20)
parents cd72cd0e1c19
children 0248483f90cc
line source
1 /*
2 PV Drivers for Windows Xen HVM Domains
3 Copyright (C) 2007 James Harper
5 This program is free software; you can redistribute it and/or
6 modify it under the terms of the GNU General Public License
7 as published by the Free Software Foundation; either version 2
8 of the License, or (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18 */
20 #define INITGUID
21 #include "xenpci.h"
22 #include <aux_klib.h>
23 #include <stdlib.h>
25 #define SYSRQ_PATH "control/sysrq"
26 #define SHUTDOWN_PATH "control/shutdown"
27 #define BALLOON_PATH "memory/target"
29 #pragma warning(disable : 4200) // zero-sized array
31 PMDL balloon_mdl_head = NULL;
33 /* Not really necessary but keeps PREfast happy */
34 DRIVER_INITIALIZE DriverEntry;
35 static EVT_WDF_DRIVER_UNLOAD XenPci_EvtDriverUnload;
36 static EVT_WDF_DRIVER_DEVICE_ADD XenPci_EvtDeviceAdd;
37 static EVT_WDF_DEVICE_USAGE_NOTIFICATION XenPci_EvtDeviceUsageNotification;
38 static EVT_WDF_DEVICE_PREPARE_HARDWARE XenHide_EvtDevicePrepareHardware;
40 #if (NTDDI_VERSION >= NTDDI_WS03SP1)
41 static KBUGCHECK_REASON_CALLBACK_ROUTINE XenPci_DebugHeaderDumpIoCallback;
43 /* this is supposed to be defined in wdm.h, but isn't */
44 NTSTATUS
45 KeInitializeCrashDumpHeader(
46 IN ULONG Type,
47 IN ULONG Flags,
48 OUT PVOID Buffer,
49 IN ULONG BufferSize,
50 OUT PULONG BufferNeeded OPTIONAL
51 );
52 #endif
54 #define DUMP_TYPE_FULL 1
56 static VOID
57 XenPci_EvtDeviceUsageNotification(WDFDEVICE device, WDF_SPECIAL_FILE_TYPE notification_type, BOOLEAN is_in_notification_path)
58 {
59 FUNCTION_ENTER();
61 UNREFERENCED_PARAMETER(device);
62 UNREFERENCED_PARAMETER(is_in_notification_path);
64 switch (notification_type)
65 {
66 case WdfSpecialFilePaging:
67 FUNCTION_MSG("notification_type = Paging, flag = %d\n", is_in_notification_path);
68 break;
69 case WdfSpecialFileHibernation:
70 FUNCTION_MSG("notification_type = Hibernation, flag = %d\n", is_in_notification_path);
71 break;
72 case WdfSpecialFileDump:
73 FUNCTION_MSG("notification_type = Dump, flag = %d\n", is_in_notification_path);
74 break;
75 default:
76 FUNCTION_MSG("notification_type = %d, flag = %d\n", notification_type, is_in_notification_path);
77 break;
78 }
80 FUNCTION_EXIT();
81 }
83 static NTSTATUS
84 XenPci_EvtDeviceAdd_XenPci(WDFDRIVER driver, PWDFDEVICE_INIT device_init)
85 {
86 NTSTATUS status;
87 // PDEVICE_OBJECT fdo = NULL;
88 // PNP_BUS_INFORMATION busInfo;
89 // DECLARE_CONST_UNICODE_STRING(DeviceName, L"\\Device\\XenShutdown");
90 // DECLARE_CONST_UNICODE_STRING(SymbolicName, L"\\DosDevices\\XenShutdown");
91 WDF_CHILD_LIST_CONFIG child_list_config;
92 WDFDEVICE device;
93 PXENPCI_DEVICE_DATA xpdd;
94 UNICODE_STRING reference;
95 WDF_OBJECT_ATTRIBUTES device_attributes;
96 PNP_BUS_INFORMATION pbi;
97 WDF_PNPPOWER_EVENT_CALLBACKS pnp_power_callbacks;
98 WDF_INTERRUPT_CONFIG interrupt_config;
99 WDF_OBJECT_ATTRIBUTES file_attributes;
100 WDF_FILEOBJECT_CONFIG file_config;
101 WDF_IO_QUEUE_CONFIG queue_config;
102 WDFCOLLECTION veto_devices;
103 WDFKEY param_key;
104 DECLARE_CONST_UNICODE_STRING(veto_devices_name, L"veto_devices");
105 WDF_DEVICE_POWER_CAPABILITIES power_capabilities;
106 PPHYSICAL_MEMORY_RANGE pmr_head, pmr;
107 int i;
109 UNREFERENCED_PARAMETER(driver);
111 FUNCTION_ENTER();
113 WDF_PNPPOWER_EVENT_CALLBACKS_INIT(&pnp_power_callbacks);
114 pnp_power_callbacks.EvtDeviceD0Entry = XenPci_EvtDeviceD0Entry;
115 pnp_power_callbacks.EvtDeviceD0EntryPostInterruptsEnabled = XenPci_EvtDeviceD0EntryPostInterruptsEnabled;
116 pnp_power_callbacks.EvtDeviceD0Exit = XenPci_EvtDeviceD0Exit;
117 pnp_power_callbacks.EvtDeviceD0ExitPreInterruptsDisabled = XenPci_EvtDeviceD0ExitPreInterruptsDisabled;
118 pnp_power_callbacks.EvtDevicePrepareHardware = XenPci_EvtDevicePrepareHardware;
119 pnp_power_callbacks.EvtDeviceReleaseHardware = XenPci_EvtDeviceReleaseHardware;
120 pnp_power_callbacks.EvtDeviceQueryRemove = XenPci_EvtDeviceQueryRemove;
121 pnp_power_callbacks.EvtDeviceUsageNotification = XenPci_EvtDeviceUsageNotification;
123 WdfDeviceInitSetPnpPowerEventCallbacks(device_init, &pnp_power_callbacks);
125 WdfDeviceInitSetDeviceType(device_init, FILE_DEVICE_BUS_EXTENDER);
126 WdfDeviceInitSetExclusive(device_init, FALSE);
128 WDF_CHILD_LIST_CONFIG_INIT(&child_list_config, sizeof(XENPCI_PDO_IDENTIFICATION_DESCRIPTION), XenPci_EvtChildListCreateDevice);
129 child_list_config.EvtChildListScanForChildren = XenPci_EvtChildListScanForChildren;
130 WdfFdoInitSetDefaultChildListConfig(device_init, &child_list_config, WDF_NO_OBJECT_ATTRIBUTES);
132 WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&file_attributes, XENPCI_DEVICE_INTERFACE_DATA);
133 WDF_FILEOBJECT_CONFIG_INIT(&file_config, XenPci_EvtDeviceFileCreate, XenPci_EvtFileClose, XenPci_EvtFileCleanup);
134 WdfDeviceInitSetFileObjectConfig(device_init, &file_config, &file_attributes);
136 WdfDeviceInitSetIoType(device_init, WdfDeviceIoBuffered);
138 WdfDeviceInitSetPowerNotPageable(device_init);
140 WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&device_attributes, XENPCI_DEVICE_DATA);
141 status = WdfDeviceCreate(&device_init, &device_attributes, &device);
142 if (!NT_SUCCESS(status)) {
143 FUNCTION_MSG("Error creating device %08x\n", status);
144 return status;
145 }
147 xpdd = GetXpdd(device);
148 xpdd->wdf_device = device;
149 xpdd->child_list = WdfFdoGetDefaultChildList(device);
151 /* this is not a documented function */
152 KeInitializeEvent(&xpdd->balloon_event, SynchronizationEvent, FALSE);
153 pmr_head = MmGetPhysicalMemoryRanges();
154 xpdd->current_memory_kb = 0;
155 for (pmr = pmr_head; !(pmr->BaseAddress.QuadPart == 0 && pmr->NumberOfBytes.QuadPart == 0); pmr++) {
156 xpdd->current_memory_kb += (ULONG)(pmr->NumberOfBytes.QuadPart / 1024);
157 }
158 FUNCTION_MSG("current_memory_kb = %d\n", xpdd->current_memory_kb);
159 /* round to MB increments because that is what balloon deals in */
160 xpdd->current_memory_kb = (xpdd->current_memory_kb + 0x1FF) & 0xFFFFFC00;
161 FUNCTION_MSG("current_memory_kb rounded to %d\n", xpdd->current_memory_kb);
163 ExInitializeFastMutex(&xpdd->suspend_mutex);
164 WdfCollectionCreate(WDF_NO_OBJECT_ATTRIBUTES, &veto_devices);
165 status = WdfDriverOpenParametersRegistryKey(driver, KEY_QUERY_VALUE, WDF_NO_OBJECT_ATTRIBUTES, &param_key);
166 if (NT_SUCCESS(status)) {
167 status = WdfRegistryQueryMultiString(param_key, &veto_devices_name, WDF_NO_OBJECT_ATTRIBUTES, veto_devices);
168 if (!NT_SUCCESS(status)) {
169 FUNCTION_MSG("Error reading parameters/veto_devices value %08x\n", status);
170 }
171 WdfRegistryClose(param_key);
172 } else {
173 FUNCTION_MSG("Error opening parameters key %08x\n", status);
174 }
176 InitializeListHead(&xpdd->veto_list);
177 for (i = 0; i < (int)WdfCollectionGetCount(veto_devices); i++) {
178 WDFOBJECT ws;
179 UNICODE_STRING val;
180 ANSI_STRING s;
181 PVOID entry;
182 ws = WdfCollectionGetItem(veto_devices, i);
183 WdfStringGetUnicodeString(ws, &val);
184 RtlUnicodeStringToAnsiString(&s, &val, TRUE);
185 entry = ExAllocatePoolWithTag(NonPagedPool, sizeof(LIST_ENTRY) + s.Length + 1, XENPCI_POOL_TAG);
186 memcpy((PUCHAR)entry + sizeof(LIST_ENTRY), s.Buffer, s.Length + 1);
187 RtlFreeAnsiString(&s);
188 InsertTailList(&xpdd->veto_list, (PLIST_ENTRY)entry);
189 }
190 WDF_DEVICE_POWER_CAPABILITIES_INIT(&power_capabilities);
191 power_capabilities.DeviceD1 = WdfTrue;
192 power_capabilities.WakeFromD1 = WdfTrue;
193 power_capabilities.DeviceWake = PowerDeviceD1;
194 power_capabilities.DeviceState[PowerSystemWorking] = PowerDeviceD0;
195 power_capabilities.DeviceState[PowerSystemSleeping1] = PowerDeviceD1;
196 power_capabilities.DeviceState[PowerSystemSleeping2] = PowerDeviceD2;
197 power_capabilities.DeviceState[PowerSystemSleeping3] = PowerDeviceD2;
198 power_capabilities.DeviceState[PowerSystemHibernate] = PowerDeviceD3;
199 power_capabilities.DeviceState[PowerSystemShutdown] = PowerDeviceD3;
200 WdfDeviceSetPowerCapabilities(device, &power_capabilities);
202 WdfDeviceSetSpecialFileSupport(device, WdfSpecialFilePaging, TRUE);
203 WdfDeviceSetSpecialFileSupport(device, WdfSpecialFileHibernation, TRUE);
204 WdfDeviceSetSpecialFileSupport(device, WdfSpecialFileDump, TRUE);
206 WDF_IO_QUEUE_CONFIG_INIT_DEFAULT_QUEUE(&queue_config, WdfIoQueueDispatchParallel);
207 queue_config.EvtIoDefault = XenPci_EvtIoDefault;
208 status = WdfIoQueueCreate(device, &queue_config, WDF_NO_OBJECT_ATTRIBUTES, &xpdd->io_queue);
209 if (!NT_SUCCESS(status)) {
210 FUNCTION_MSG("Error creating queue 0x%x\n", status);
211 return status;
212 }
214 WDF_INTERRUPT_CONFIG_INIT(&interrupt_config, EvtChn_EvtInterruptIsr, NULL);
215 interrupt_config.EvtInterruptEnable = EvtChn_EvtInterruptEnable;
216 interrupt_config.EvtInterruptDisable = EvtChn_EvtInterruptDisable;
218 status = WdfInterruptCreate(device, &interrupt_config, WDF_NO_OBJECT_ATTRIBUTES, &xpdd->interrupt);
219 if (!NT_SUCCESS(status))
220 {
221 FUNCTION_MSG("Error creating interrupt 0x%x\n", status);
222 return status;
223 }
225 RtlInitUnicodeString(&reference, L"xenbus");
226 status = WdfDeviceCreateDeviceInterface(device, &GUID_DEVINTERFACE_XENBUS, &reference);
227 if (!NT_SUCCESS(status)) {
228 FUNCTION_MSG("Error registering device interface 0x%x\n", status);
229 return status;
230 }
232 RtlInitUnicodeString(&reference, L"evtchn");
233 status = WdfDeviceCreateDeviceInterface(device, &GUID_DEVINTERFACE_EVTCHN, &reference);
234 if (!NT_SUCCESS(status)) {
235 FUNCTION_MSG("Error registering device interface 0x%x\n", status);
236 return status;
237 }
239 RtlInitUnicodeString(&reference, L"gntdev");
240 status = WdfDeviceCreateDeviceInterface(device, &GUID_DEVINTERFACE_GNTDEV, &reference);
241 if (!NT_SUCCESS(status)) {
242 FUNCTION_MSG("Error registering device interface 0x%x\n", status);
243 return status;
244 }
246 pbi.BusTypeGuid = GUID_BUS_TYPE_XEN;
247 pbi.LegacyBusType = PNPBus;
248 pbi.BusNumber = 0;
249 WdfDeviceSetBusInformationForChildren(device, &pbi);
251 xpdd->removable = TRUE;
253 FUNCTION_EXIT();
254 return status;
255 }
257 NTSTATUS
258 XenHide_EvtDevicePrepareHardware(WDFDEVICE device, WDFCMRESLIST resources_raw, WDFCMRESLIST resources_translated)
259 {
260 UNREFERENCED_PARAMETER(device);
261 UNREFERENCED_PARAMETER(resources_raw);
262 UNREFERENCED_PARAMETER(resources_translated);
263 FUNCTION_ENTER();
264 FUNCTION_EXIT();
265 return STATUS_UNSUCCESSFUL;
266 }
268 static BOOLEAN
269 XenPci_IdSuffixMatches(PWDFDEVICE_INIT device_init, PWCHAR matching_id) {
270 NTSTATUS status;
271 WDFMEMORY memory;
272 ULONG remaining;
273 size_t string_length;
274 PWCHAR ids;
275 PWCHAR ptr;
276 size_t ids_length;
277 ULONG properties[] = {DevicePropertyCompatibleIDs, DevicePropertyHardwareID};
278 int i;
280 // FUNCTION_ENTER();
281 for (i = 0; i < ARRAY_SIZE(properties); i++)
282 {
284 status = WdfFdoInitAllocAndQueryProperty(device_init, properties[i], NonPagedPool, WDF_NO_OBJECT_ATTRIBUTES, &memory);
285 if (!NT_SUCCESS(status))
286 continue;
287 ids = WdfMemoryGetBuffer(memory, &ids_length);
289 if (!NT_SUCCESS(status)) {
290 continue;
291 }
293 remaining = (ULONG)ids_length / 2;
294 for (ptr = ids; *ptr != 0; ptr += string_length + 1) {
295 RtlStringCchLengthW(ptr, remaining, &string_length);
296 remaining -= (ULONG)string_length + 1;
297 if (string_length >= wcslen(matching_id)) {
298 ptr += string_length - wcslen(matching_id);
299 string_length = wcslen(matching_id);
300 }
301 if (wcscmp(ptr, matching_id) == 0) {
302 WdfObjectDelete(memory);
303 return TRUE;
304 }
305 }
306 WdfObjectDelete(memory);
307 }
308 return FALSE;
309 }
311 WDFCOLLECTION qemu_hide_devices;
312 USHORT qemu_hide_flags_value;
314 static NTSTATUS
315 XenPci_EvtDeviceAdd_XenHide(WDFDRIVER driver, PWDFDEVICE_INIT device_init)
316 {
317 NTSTATUS status;
318 WDFMEMORY memory;
319 PWCHAR device_description;
320 WDF_PNPPOWER_EVENT_CALLBACKS pnp_power_callbacks;
321 WDF_OBJECT_ATTRIBUTES device_attributes;
322 BOOLEAN hide_required = FALSE;
323 WDFDEVICE device;
324 ULONG i;
326 UNREFERENCED_PARAMETER(driver);
328 FUNCTION_ENTER();
330 status = WdfFdoInitAllocAndQueryProperty(device_init, DevicePropertyDeviceDescription, NonPagedPool, WDF_NO_OBJECT_ATTRIBUTES, &memory);
331 if (NT_SUCCESS(status)) {
332 device_description = WdfMemoryGetBuffer(memory, NULL);
333 } else {
334 device_description = L"<unknown device>";
335 }
337 for (i = 0; i < WdfCollectionGetCount(qemu_hide_devices); i++) {
338 WDFSTRING wdf_string = WdfCollectionGetItem(qemu_hide_devices, i);
339 UNICODE_STRING unicode_string;
340 WdfStringGetUnicodeString(wdf_string, &unicode_string);
341 if (XenPci_IdSuffixMatches(device_init, unicode_string.Buffer)) {
342 hide_required = TRUE;
343 break;
344 }
345 }
346 if (!hide_required) {
347 FUNCTION_MSG("(filter not required for %S)\n", device_description);
348 WdfObjectDelete(memory);
349 return STATUS_SUCCESS;
350 }
352 FUNCTION_MSG("Installing Filter for %S\n", device_description);
354 WdfFdoInitSetFilter(device_init);
355 WdfDeviceInitSetDeviceType(device_init, FILE_DEVICE_UNKNOWN);
356 WdfDeviceInitSetExclusive(device_init, FALSE);
358 WDF_PNPPOWER_EVENT_CALLBACKS_INIT(&pnp_power_callbacks);
359 pnp_power_callbacks.EvtDevicePrepareHardware = XenHide_EvtDevicePrepareHardware;
360 WdfDeviceInitSetPnpPowerEventCallbacks(device_init, &pnp_power_callbacks);
362 WDF_OBJECT_ATTRIBUTES_INIT(&device_attributes);
363 status = WdfDeviceCreate(&device_init, &device_attributes, &device);
364 if (!NT_SUCCESS(status)) {
365 FUNCTION_MSG("Error creating device %08x\n", status);
366 WdfObjectDelete(memory);
367 FUNCTION_EXIT();
368 return status;
369 }
371 WdfObjectDelete(memory);
372 FUNCTION_EXIT();
374 return status;
375 }
377 static NTSTATUS
378 XenPci_EvtDeviceAdd(WDFDRIVER driver, PWDFDEVICE_INIT device_init)
379 {
380 if (XenPci_IdSuffixMatches(device_init, L"VEN_5853&DEV_0001")) {
381 FUNCTION_MSG("Xen PCI device found - must be fdo\n");
382 return XenPci_EvtDeviceAdd_XenPci(driver, device_init);
383 } else if (WdfCollectionGetCount(qemu_hide_devices) > 0) {
384 FUNCTION_MSG("Xen PCI device not found - must be filter\n");
385 return XenPci_EvtDeviceAdd_XenHide(driver, device_init);
386 } else {
387 return STATUS_SUCCESS;
388 }
389 }
391 ULONG qemu_protocol_version;
392 ULONG tpr_patch_requested;
393 extern PULONG InitSafeBootMode;
395 VOID
396 XenPci_HideQemuDevices() {
397 #pragma warning(suppress:28138)
398 WRITE_PORT_USHORT(XEN_IOPORT_DEVICE_MASK, (USHORT)qemu_hide_flags_value); //QEMU_UNPLUG_ALL_IDE_DISKS|QEMU_UNPLUG_ALL_NICS);
399 FUNCTION_MSG("Disabled qemu devices %02x\n", qemu_hide_flags_value);
400 }
402 static BOOLEAN
403 XenPci_CheckHideQemuDevices()
404 {
405 #pragma warning(suppress:28138)
406 if (READ_PORT_USHORT(XEN_IOPORT_MAGIC) == 0x49d2) {
407 #pragma warning(suppress:28138)
408 qemu_protocol_version = READ_PORT_UCHAR(XEN_IOPORT_VERSION);
409 FUNCTION_MSG("Version = %d\n", qemu_protocol_version);
410 switch(qemu_protocol_version) {
411 case 1:
412 #pragma warning(suppress:28138)
413 WRITE_PORT_USHORT(XEN_IOPORT_PRODUCT, XEN_PV_PRODUCT_NUMBER);
414 #pragma warning(suppress:28138)
415 WRITE_PORT_ULONG(XEN_IOPORT_BUILD, XEN_PV_PRODUCT_BUILD);
416 #pragma warning(suppress:28138)
417 if (READ_PORT_USHORT(XEN_IOPORT_MAGIC) != 0x49d2)
418 {
419 FUNCTION_MSG("Blacklisted\n");
420 break;
421 }
422 /* fall through */
423 case 0:
424 return TRUE;
425 default:
426 FUNCTION_MSG("Unknown qemu version %d\n", qemu_protocol_version);
427 break;
428 }
429 }
430 return FALSE;
431 }
433 /*
434 make sure the load order is System Reserved, Dummy Group, WdfLoadGroup, XenPCI, Boot Bus Extender
435 */
437 static VOID
438 XenPci_FixLoadOrder()
439 {
440 NTSTATUS status;
441 WDFCOLLECTION old_load_order, new_load_order;
442 DECLARE_CONST_UNICODE_STRING(sgo_name, L"\\Registry\\Machine\\SYSTEM\\CurrentControlSet\\Control\\ServiceGroupOrder");
443 DECLARE_CONST_UNICODE_STRING(list_name, L"List");
444 WDFKEY sgo_key;
445 ULONG i;
446 LONG dummy_group_index = -1;
447 LONG boot_bus_extender_index = -1;
448 LONG xenpci_group_index = -1;
449 LONG wdf_load_group_index = -1;
450 DECLARE_CONST_UNICODE_STRING(dummy_group_name, L"Dummy Group");
451 DECLARE_CONST_UNICODE_STRING(wdf_load_group_name, L"WdfLoadGroup");
452 DECLARE_CONST_UNICODE_STRING(xenpci_group_name, L"XenPCI Group");
453 DECLARE_CONST_UNICODE_STRING(boot_bus_extender_name, L"Boot Bus Extender");
455 FUNCTION_ENTER();
457 status = WdfRegistryOpenKey(NULL, &sgo_name, KEY_QUERY_VALUE, WDF_NO_OBJECT_ATTRIBUTES, &sgo_key);
458 if (!NT_SUCCESS(status))
459 {
460 FUNCTION_MSG("Error opening ServiceGroupOrder key %08x\n", status);
461 return;
462 }
463 WdfCollectionCreate(WDF_NO_OBJECT_ATTRIBUTES, &old_load_order);
464 WdfCollectionCreate(WDF_NO_OBJECT_ATTRIBUTES, &new_load_order);
465 status = WdfRegistryQueryMultiString(sgo_key, &list_name, WDF_NO_OBJECT_ATTRIBUTES, old_load_order);
466 if (!NT_SUCCESS(status))
467 {
468 FUNCTION_MSG("Error reading ServiceGroupOrder\\List value %08x\n", status);
469 WdfObjectDelete(new_load_order);
470 WdfObjectDelete(old_load_order);
471 return;
472 }
473 //FUNCTION_MSG("Current Order:\n");
474 for (i = 0; i < WdfCollectionGetCount(old_load_order); i++)
475 {
476 WDFOBJECT ws = WdfCollectionGetItem(old_load_order, i);
477 UNICODE_STRING val;
478 WdfStringGetUnicodeString(ws, &val);
479 if (!RtlCompareUnicodeString(&val, &dummy_group_name, TRUE))
480 dummy_group_index = (ULONG)i;
481 if (!RtlCompareUnicodeString(&val, &wdf_load_group_name, TRUE))
482 wdf_load_group_index = (ULONG)i;
483 if (!RtlCompareUnicodeString(&val, &xenpci_group_name, TRUE))
484 xenpci_group_index = (ULONG)i;
485 if (!RtlCompareUnicodeString(&val, &boot_bus_extender_name, TRUE))
486 boot_bus_extender_index = (ULONG)i;
487 //FUNCTION_MSG(" %wZ\n", &val);
488 }
489 FUNCTION_MSG("dummy_group_index = %d\n", dummy_group_index);
490 FUNCTION_MSG("wdf_load_group_index = %d\n", wdf_load_group_index);
491 FUNCTION_MSG("xenpci_group_index = %d\n", xenpci_group_index);
492 FUNCTION_MSG("boot_bus_extender_index = %d\n", boot_bus_extender_index);
493 if (boot_bus_extender_index == -1)
494 {
495 WdfObjectDelete(new_load_order);
496 WdfObjectDelete(old_load_order);
497 WdfRegistryClose(sgo_key);
498 return; /* something is very wrong */
499 }
500 if (dummy_group_index == 1 && wdf_load_group_index != -1 &&
501 (dummy_group_index < wdf_load_group_index
502 && wdf_load_group_index < xenpci_group_index
503 && xenpci_group_index < boot_bus_extender_index))
504 {
505 FUNCTION_EXIT();
506 return; /* our work here is done */
507 }
508 for (i = 0; i < WdfCollectionGetCount(old_load_order); i++)
509 {
510 WDFOBJECT ws;
511 if (i == 1)
512 {
513 WDFSTRING tmp_wdf_string;
514 WdfStringCreate(&dummy_group_name, WDF_NO_OBJECT_ATTRIBUTES, &tmp_wdf_string);
515 WdfCollectionAdd(new_load_order, tmp_wdf_string);
516 WdfObjectDelete(tmp_wdf_string);
517 }
518 if (i == 1)
519 {
520 WDFSTRING tmp_wdf_string;
521 WdfStringCreate(&wdf_load_group_name, WDF_NO_OBJECT_ATTRIBUTES, &tmp_wdf_string);
522 WdfCollectionAdd(new_load_order, tmp_wdf_string);
523 WdfObjectDelete(tmp_wdf_string);
524 }
525 if (i == 1)
526 {
527 WDFSTRING tmp_wdf_string;
528 WdfStringCreate(&xenpci_group_name, WDF_NO_OBJECT_ATTRIBUTES, &tmp_wdf_string);
529 WdfCollectionAdd(new_load_order, tmp_wdf_string);
530 WdfObjectDelete(tmp_wdf_string);
531 }
532 if (i == (ULONG)dummy_group_index || i == (ULONG)wdf_load_group_index || i == (ULONG)xenpci_group_index)
533 continue;
534 ws = WdfCollectionGetItem(old_load_order, i);
535 WdfCollectionAdd(new_load_order, ws);
536 }
537 WdfRegistryAssignMultiString(sgo_key, &list_name, new_load_order);
538 //FUNCTION_MSG("New Order:\n");
539 for (i = 0; i < WdfCollectionGetCount(new_load_order); i++)
540 {
541 WDFOBJECT ws = WdfCollectionGetItem(new_load_order, i);
542 UNICODE_STRING val;
543 WdfStringGetUnicodeString(ws, &val);
544 //FUNCTION_MSG(" %wZ\n", &val);
545 }
546 WdfObjectDelete(new_load_order);
547 WdfObjectDelete(old_load_order);
548 WdfRegistryClose(sgo_key);
550 FUNCTION_EXIT();
552 return;
553 }
555 VOID
556 XenPci_EvtDriverUnload(WDFDRIVER driver)
557 {
558 UNREFERENCED_PARAMETER(driver);
560 // #if DBG
561 // XenPci_UnHookDbgPrint();
562 // #endif
563 }
565 #if (NTDDI_VERSION >= NTDDI_WS03SP1)
566 /* this isn't freed on shutdown... perhaps it should be */
567 static PUCHAR dump_header;
568 static ULONG dump_header_size;
569 static ULONG dump_header_refreshed_flag = FALSE;
570 static KBUGCHECK_REASON_CALLBACK_RECORD callback_record;
571 #define DUMP_HEADER_PREFIX_SIZE 8
572 #define DUMP_HEADER_SUFFIX_SIZE 8
574 /* call KeInitializeCrashDumpHeader once on crash */
575 static VOID
576 XenPci_DebugHeaderDumpIoCallback(
577 KBUGCHECK_CALLBACK_REASON reason,
578 PKBUGCHECK_REASON_CALLBACK_RECORD record,
579 PVOID reason_specific_data,
580 ULONG reason_specific_data_length) {
581 UNREFERENCED_PARAMETER(reason);
582 UNREFERENCED_PARAMETER(record);
583 UNREFERENCED_PARAMETER(reason_specific_data);
584 UNREFERENCED_PARAMETER(reason_specific_data_length);
585 if (!dump_header_refreshed_flag) {
586 NTSTATUS status;
587 status = KeInitializeCrashDumpHeader(DUMP_TYPE_FULL, 0, dump_header + DUMP_HEADER_PREFIX_SIZE, dump_header_size, &dump_header_size);
588 /* copy bug check code in? */
589 dump_header_refreshed_flag = TRUE;
590 }
591 }
592 #endif
594 NTSTATUS
595 DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath)
596 {
597 NTSTATUS status = STATUS_SUCCESS;
598 WDF_DRIVER_CONFIG config;
599 WDFDRIVER driver;
600 WDF_OBJECT_ATTRIBUTES parent_attributes;
601 PCONFIGURATION_INFORMATION conf_info;
602 WDFKEY control_key;
603 WDFKEY param_key;
604 ULONG always_patch = 0;
605 ULONG always_hide = 0;
606 DECLARE_CONST_UNICODE_STRING(control_key_name, L"\\Registry\\Machine\\System\\CurrentControlSet\\Control");
607 DECLARE_CONST_UNICODE_STRING(system_start_options_name, L"SystemStartOptions");
608 DECLARE_CONST_UNICODE_STRING(txt_always_hide_name, L"txt_hide_qemu_always");
609 DECLARE_CONST_UNICODE_STRING(hide_devices_name, L"hide_devices");
610 DECLARE_CONST_UNICODE_STRING(txt_always_patch_name, L"txt_patch_tpr_always");
611 WDFSTRING wdf_system_start_options;
612 UNICODE_STRING system_start_options;
613 #if (NTDDI_VERSION >= NTDDI_WS03SP1)
614 PHYSICAL_ADDRESS dump_header_mem_max;
615 #endif
617 UNREFERENCED_PARAMETER(RegistryPath);
619 FUNCTION_ENTER();
621 FUNCTION_MSG(__DRIVER_NAME " " VER_FILEVERSION_STR "\n");
623 #if (NTDDI_VERSION >= NTDDI_WS03SP1)
624 status = KeInitializeCrashDumpHeader(DUMP_TYPE_FULL, 0, NULL, 0, &dump_header_size);
625 /* try and allocate contiguous memory as low as possible */
626 dump_header = NULL;
627 dump_header_mem_max.QuadPart = 0xFFFFF;
628 while (!dump_header && dump_header_mem_max.QuadPart != 0xFFFFFFFFFFFFFFFF) {
629 dump_header = MmAllocateContiguousMemory(DUMP_HEADER_PREFIX_SIZE + dump_header_size + DUMP_HEADER_SUFFIX_SIZE, dump_header_mem_max);
630 if (dump_header) {
631 FUNCTION_MSG("Allocated crash dump header < 0x%016I64x\n", dump_header_mem_max.QuadPart);
632 break;
633 }
634 dump_header_mem_max.QuadPart = (dump_header_mem_max.QuadPart << 4) | 0xF;
635 }
636 if (dump_header) {
637 status = KeInitializeCrashDumpHeader(DUMP_TYPE_FULL, 0, dump_header + DUMP_HEADER_PREFIX_SIZE, dump_header_size, &dump_header_size);
638 FUNCTION_MSG("KeInitializeCrashDumpHeader status = %08x, size = %d\n", status, dump_header_size);
639 memcpy(dump_header + 0, "XENXEN", 6); /* magic number */
640 *(PUSHORT)(dump_header + 6) = (USHORT)(INT_PTR)dump_header & (PAGE_SIZE - 1); /* store offset too as additional verification */
641 memcpy(dump_header + DUMP_HEADER_PREFIX_SIZE + dump_header_size, "XENXEN", 6);
642 *(PUSHORT)(dump_header + DUMP_HEADER_PREFIX_SIZE + dump_header_size + 6) = (USHORT)(INT_PTR)dump_header & (PAGE_SIZE - 1); /* store offset too as additional verification */
643 KeInitializeCallbackRecord(&callback_record);
644 KeRegisterBugCheckReasonCallback(&callback_record, XenPci_DebugHeaderDumpIoCallback, KbCallbackDumpIo, (PUCHAR)"XenPci_DebugHeaderDumpIoCallback");
645 } else {
646 FUNCTION_MSG("Failed to allocate memory for crash dump header\n");
647 }
648 #endif
650 WDF_DRIVER_CONFIG_INIT(&config, XenPci_EvtDeviceAdd);
651 config.EvtDriverUnload = XenPci_EvtDriverUnload;
652 status = WdfDriverCreate(DriverObject, RegistryPath, WDF_NO_OBJECT_ATTRIBUTES, &config, &driver);
653 if (!NT_SUCCESS(status)) {
654 FUNCTION_MSG("WdfDriverCreate failed with status 0x%x\n", status);
655 FUNCTION_EXIT();
656 //#if DBG
657 //XenPci_UnHookDbgPrint();
658 //#endif
659 return status;
660 }
661 WDF_OBJECT_ATTRIBUTES_INIT(&parent_attributes);
662 parent_attributes.ParentObject = driver;
664 status = WdfDriverOpenParametersRegistryKey(driver, KEY_QUERY_VALUE, &parent_attributes, &param_key);
665 if (!NT_SUCCESS(status)) {
666 FUNCTION_MSG("Error opening parameters key %08x\n", status);
667 goto error;
668 }
670 status = AuxKlibInitialize();
671 if(!NT_SUCCESS(status)) {
672 FUNCTION_MSG("AuxKlibInitialize failed %08x\n", status);
673 goto error;
674 }
676 XenPci_FixLoadOrder();
678 RtlInitUnicodeString(&system_start_options, L"failed to read");
679 status = WdfRegistryOpenKey(NULL, &control_key_name, GENERIC_READ, &parent_attributes, &control_key);
680 if (NT_SUCCESS(status)) {
681 status = WdfStringCreate(NULL, &parent_attributes, &wdf_system_start_options);
682 status = WdfRegistryQueryString(control_key, &system_start_options_name, wdf_system_start_options);
683 if (NT_SUCCESS(status))
684 WdfStringGetUnicodeString(wdf_system_start_options, &system_start_options);
685 }
686 WdfRegistryClose(control_key);
688 FUNCTION_MSG("SystemStartOptions = %wZ\n", &system_start_options);
690 always_patch = 0;
691 WdfRegistryQueryULong(param_key, &txt_always_patch_name, &always_patch);
692 if (always_patch || (system_start_options.Buffer && wcsstr(system_start_options.Buffer, L"PATCHTPR"))) {
693 DECLARE_CONST_UNICODE_STRING(verifier_key_name, L"\\Registry\\Machine\\System\\CurrentControlSet\\Control\\Session Manager\\Memory Management");
694 WDFKEY memory_key;
695 ULONG verifier_value;
697 FUNCTION_MSG("PATCHTPR found\n");
699 tpr_patch_requested = TRUE;
700 status = WdfRegistryOpenKey(NULL, &verifier_key_name, KEY_READ, &parent_attributes, &memory_key);
701 if (NT_SUCCESS(status))
702 {
703 DECLARE_CONST_UNICODE_STRING(verifier_value_name, L"VerifyDriverLevel");
704 status = WdfRegistryQueryULong(memory_key, &verifier_value_name, &verifier_value);
705 if (NT_SUCCESS(status) && verifier_value != 0)
706 {
707 FUNCTION_MSG("Verifier active - not patching\n");
708 tpr_patch_requested = FALSE;
709 }
710 WdfRegistryClose(memory_key);
711 }
712 }
714 WdfCollectionCreate(&parent_attributes, &qemu_hide_devices);
715 WdfRegistryQueryULong(param_key, &txt_always_hide_name, &always_hide);
716 conf_info = IoGetConfigurationInformation();
717 if (always_hide || ((conf_info == NULL || conf_info->DiskCount == 0)
718 && !(system_start_options.Buffer && wcsstr(system_start_options.Buffer, L"NOGPLPV"))
719 && !*InitSafeBootMode)) {
720 if (!(system_start_options.Buffer && wcsstr(system_start_options.Buffer, L"GPLPVUSEFILTERHIDE")) && XenPci_CheckHideQemuDevices()) {
721 DECLARE_CONST_UNICODE_STRING(qemu_hide_flags_name, L"qemu_hide_flags");
722 DECLARE_CONST_UNICODE_STRING(txt_qemu_hide_flags_name, L"txt_qemu_hide_flags");
723 WDFCOLLECTION qemu_hide_flags;
724 ULONG i;
726 WdfCollectionCreate(&parent_attributes, &qemu_hide_flags);
727 WdfRegistryQueryMultiString(param_key, &qemu_hide_flags_name, &parent_attributes, qemu_hide_flags);
728 WdfRegistryQueryMultiString(param_key, &txt_qemu_hide_flags_name, &parent_attributes, qemu_hide_flags);
729 for (i = 0; i < WdfCollectionGetCount(qemu_hide_flags); i++) {
730 ULONG value;
731 WDFSTRING wdf_string = WdfCollectionGetItem(qemu_hide_flags, i);
732 UNICODE_STRING unicode_string;
733 WdfStringGetUnicodeString(wdf_string, &unicode_string);
734 status = RtlUnicodeStringToInteger(&unicode_string, 0, &value);
735 qemu_hide_flags_value |= value;
736 }
737 WdfObjectDelete(qemu_hide_flags);
738 XenPci_HideQemuDevices();
739 } else {
740 WdfRegistryQueryMultiString(param_key, &hide_devices_name, &parent_attributes, qemu_hide_devices);
741 }
742 }
743 WdfRegistryClose(param_key);
744 FUNCTION_EXIT();
745 return STATUS_SUCCESS;
747 error:
748 FUNCTION_MSG("Failed, returning %08x\n", status);
749 FUNCTION_EXIT();
750 return status;
751 }