win-pvdrivers

view xenpci/xenpci.c @ 643:1794a52f415d

Added tag 0.10.0.94 for changeset 51de599aa482
author James Harper <james.harper@bendigoit.com.au>
date Mon Aug 24 21:21:37 2009 +1000 (2009-08-24)
parents 70c3a7839b4e
children 0ce79d5ace51
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 static VOID
32 XenPci_EvtDeviceUsageNotification(WDFDEVICE device, WDF_SPECIAL_FILE_TYPE notification_type, BOOLEAN is_in_notification_path)
33 {
34 FUNCTION_ENTER();
36 UNREFERENCED_PARAMETER(device);
38 switch (notification_type)
39 {
40 case WdfSpecialFilePaging:
41 KdPrint((__DRIVER_NAME " notification_type = Paging, flag = %d\n", is_in_notification_path));
42 break;
43 case WdfSpecialFileHibernation:
44 KdPrint((__DRIVER_NAME " notification_type = Hibernation, flag = %d\n", is_in_notification_path));
45 break;
46 case WdfSpecialFileDump:
47 KdPrint((__DRIVER_NAME " notification_type = Dump, flag = %d\n", is_in_notification_path));
48 break;
49 default:
50 KdPrint((__DRIVER_NAME " notification_type = %d, flag = %d\n", notification_type, is_in_notification_path));
51 break;
52 }
54 FUNCTION_EXIT();
55 }
57 static NTSTATUS
58 XenPci_EvtDeviceAdd_XenPci(WDFDRIVER driver, PWDFDEVICE_INIT device_init)
59 {
60 NTSTATUS status;
61 // PDEVICE_OBJECT fdo = NULL;
62 // PNP_BUS_INFORMATION busInfo;
63 // DECLARE_CONST_UNICODE_STRING(DeviceName, L"\\Device\\XenShutdown");
64 // DECLARE_CONST_UNICODE_STRING(SymbolicName, L"\\DosDevices\\XenShutdown");
65 WDF_CHILD_LIST_CONFIG child_list_config;
66 WDFDEVICE device;
67 PXENPCI_DEVICE_DATA xpdd;
68 UNICODE_STRING reference;
69 WDF_OBJECT_ATTRIBUTES device_attributes;
70 PNP_BUS_INFORMATION pbi;
71 WDF_PNPPOWER_EVENT_CALLBACKS pnp_power_callbacks;
72 WDF_INTERRUPT_CONFIG interrupt_config;
73 WDF_OBJECT_ATTRIBUTES file_attributes;
74 WDF_FILEOBJECT_CONFIG file_config;
75 WDF_IO_QUEUE_CONFIG queue_config;
76 WDFCOLLECTION veto_devices;
77 WDFKEY param_key;
78 DECLARE_CONST_UNICODE_STRING(veto_devices_name, L"veto_devices");
79 WDF_DEVICE_POWER_CAPABILITIES power_capabilities;
80 int i;
82 UNREFERENCED_PARAMETER(driver);
84 FUNCTION_ENTER();
86 WDF_PNPPOWER_EVENT_CALLBACKS_INIT(&pnp_power_callbacks);
87 pnp_power_callbacks.EvtDeviceD0Entry = XenPci_EvtDeviceD0Entry;
88 pnp_power_callbacks.EvtDeviceD0EntryPostInterruptsEnabled = XenPci_EvtDeviceD0EntryPostInterruptsEnabled;
89 pnp_power_callbacks.EvtDeviceD0Exit = XenPci_EvtDeviceD0Exit;
90 pnp_power_callbacks.EvtDeviceD0ExitPreInterruptsDisabled = XenPci_EvtDeviceD0ExitPreInterruptsDisabled;
91 pnp_power_callbacks.EvtDevicePrepareHardware = XenPci_EvtDevicePrepareHardware;
92 pnp_power_callbacks.EvtDeviceReleaseHardware = XenPci_EvtDeviceReleaseHardware;
93 pnp_power_callbacks.EvtDeviceQueryRemove = XenPci_EvtDeviceQueryRemove;
94 pnp_power_callbacks.EvtDeviceUsageNotification = XenPci_EvtDeviceUsageNotification;
96 WdfDeviceInitSetPnpPowerEventCallbacks(device_init, &pnp_power_callbacks);
98 WdfDeviceInitSetDeviceType(device_init, FILE_DEVICE_BUS_EXTENDER);
99 WdfDeviceInitSetExclusive(device_init, FALSE);
101 WDF_CHILD_LIST_CONFIG_INIT(&child_list_config, sizeof(XENPCI_PDO_IDENTIFICATION_DESCRIPTION), XenPci_EvtChildListCreateDevice);
102 child_list_config.EvtChildListScanForChildren = XenPci_EvtChildListScanForChildren;
103 WdfFdoInitSetDefaultChildListConfig(device_init, &child_list_config, WDF_NO_OBJECT_ATTRIBUTES);
105 WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&file_attributes, XENPCI_DEVICE_INTERFACE_DATA);
106 WDF_FILEOBJECT_CONFIG_INIT(&file_config, XenPci_EvtDeviceFileCreate, XenPci_EvtFileClose, XenPci_EvtFileCleanup);
107 WdfDeviceInitSetFileObjectConfig(device_init, &file_config, &file_attributes);
109 WdfDeviceInitSetIoType(device_init, WdfDeviceIoBuffered);
111 WdfDeviceInitSetPowerNotPageable(device_init);
113 WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&device_attributes, XENPCI_DEVICE_DATA);
114 status = WdfDeviceCreate(&device_init, &device_attributes, &device);
115 if (!NT_SUCCESS(status))
116 {
117 KdPrint(("Error creating device %08x\n", status));
118 return status;
119 }
121 xpdd = GetXpdd(device);
122 xpdd->wdf_device = device;
123 xpdd->child_list = WdfFdoGetDefaultChildList(device);
125 WdfCollectionCreate(WDF_NO_OBJECT_ATTRIBUTES, &veto_devices);
126 status = WdfDriverOpenParametersRegistryKey(driver, KEY_QUERY_VALUE, WDF_NO_OBJECT_ATTRIBUTES, &param_key);
127 if (NT_SUCCESS(status))
128 {
129 status = WdfRegistryQueryMultiString(param_key, &veto_devices_name, WDF_NO_OBJECT_ATTRIBUTES, veto_devices);
130 if (!NT_SUCCESS(status))
131 {
132 KdPrint(("Error reading parameters/veto_devices value %08x\n", status));
133 }
134 WdfRegistryClose(param_key);
135 }
136 else
137 {
138 KdPrint(("Error opening parameters key %08x\n", status));
139 }
141 InitializeListHead(&xpdd->veto_list);
142 for (i = 0; i < (int)WdfCollectionGetCount(veto_devices); i++)
143 {
144 WDFOBJECT ws;
145 UNICODE_STRING val;
146 ANSI_STRING s;
147 PVOID entry;
148 ws = WdfCollectionGetItem(veto_devices, i);
149 WdfStringGetUnicodeString(ws, &val);
150 RtlUnicodeStringToAnsiString(&s, &val, TRUE);
151 entry = ExAllocatePoolWithTag(NonPagedPool, sizeof(LIST_ENTRY) + s.Length + 1, XENPCI_POOL_TAG);
152 memcpy((PUCHAR)entry + sizeof(LIST_ENTRY), s.Buffer, s.Length + 1);
153 RtlFreeAnsiString(&s);
154 InsertTailList(&xpdd->veto_list, (PLIST_ENTRY)entry);
155 }
156 WDF_DEVICE_POWER_CAPABILITIES_INIT(&power_capabilities);
157 power_capabilities.DeviceD1 = WdfTrue;
158 power_capabilities.WakeFromD1 = WdfTrue;
159 power_capabilities.DeviceWake = PowerDeviceD1;
160 power_capabilities.DeviceState[PowerSystemWorking] = PowerDeviceD1;
161 power_capabilities.DeviceState[PowerSystemSleeping1] = PowerDeviceD1;
162 power_capabilities.DeviceState[PowerSystemSleeping2] = PowerDeviceD2;
163 power_capabilities.DeviceState[PowerSystemSleeping3] = PowerDeviceD2;
164 power_capabilities.DeviceState[PowerSystemHibernate] = PowerDeviceD3;
165 power_capabilities.DeviceState[PowerSystemShutdown] = PowerDeviceD3;
166 WdfDeviceSetPowerCapabilities(device, &power_capabilities);
168 WdfDeviceSetSpecialFileSupport(device, WdfSpecialFilePaging, TRUE);
169 WdfDeviceSetSpecialFileSupport(device, WdfSpecialFileHibernation, TRUE);
170 WdfDeviceSetSpecialFileSupport(device, WdfSpecialFileDump, TRUE);
172 WDF_IO_QUEUE_CONFIG_INIT_DEFAULT_QUEUE(&queue_config, WdfIoQueueDispatchParallel);
173 queue_config.EvtIoRead = XenPci_EvtIoRead;
174 queue_config.EvtIoWrite = XenPci_EvtIoWrite;
175 status = WdfIoQueueCreate(device, &queue_config, WDF_NO_OBJECT_ATTRIBUTES, &xpdd->io_queue);
176 if (!NT_SUCCESS(status)) {
177 KdPrint(("Error creating queue 0x%x\n", status));
178 return status;
179 }
181 WDF_INTERRUPT_CONFIG_INIT(&interrupt_config, EvtChn_EvtInterruptIsr, NULL);
182 interrupt_config.EvtInterruptEnable = EvtChn_EvtInterruptEnable;
183 interrupt_config.EvtInterruptDisable = EvtChn_EvtInterruptDisable;
185 status = WdfInterruptCreate(device, &interrupt_config, WDF_NO_OBJECT_ATTRIBUTES, &xpdd->interrupt);
186 if (!NT_SUCCESS(status))
187 {
188 KdPrint(("Error creating interrupt 0x%x\n", status));
189 return status;
190 }
192 RtlInitUnicodeString(&reference, L"xenbus");
193 status = WdfDeviceCreateDeviceInterface(device, &GUID_DEVINTERFACE_XENBUS, &reference);
194 if (!NT_SUCCESS(status)) {
195 KdPrint(("Error registering device interface 0x%x\n", status));
196 return status;
197 }
199 pbi.BusTypeGuid = GUID_BUS_TYPE_XEN;
200 pbi.LegacyBusType = PNPBus;
201 pbi.BusNumber = 0;
202 WdfDeviceSetBusInformationForChildren(device, &pbi);
204 xpdd->removable = TRUE;
206 FUNCTION_EXIT();
207 return status;
208 }
210 NTSTATUS
211 XenHide_EvtDevicePrepareHardware (WDFDEVICE device, WDFCMRESLIST resources_raw, WDFCMRESLIST resources_translated)
212 {
213 UNREFERENCED_PARAMETER(device);
214 UNREFERENCED_PARAMETER(resources_raw);
215 UNREFERENCED_PARAMETER(resources_translated);
216 FUNCTION_ENTER();
217 FUNCTION_EXIT();
218 return STATUS_UNSUCCESSFUL;
219 }
221 static BOOLEAN
222 XenPci_IdSuffixMatches(PWDFDEVICE_INIT device_init, PWCHAR matching_id)
223 {
224 NTSTATUS status;
225 WDFMEMORY memory;
226 ULONG remaining;
227 size_t string_length;
228 PWCHAR ids;
229 PWCHAR ptr;
230 size_t ids_length;
231 ULONG properties[] = {DevicePropertyCompatibleIDs, DevicePropertyHardwareID};
232 int i;
234 // KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
235 for (i = 0; i < ARRAY_SIZE(properties); i++)
236 {
238 status = WdfFdoInitAllocAndQueryProperty(device_init, properties[i], NonPagedPool, WDF_NO_OBJECT_ATTRIBUTES, &memory);
239 if (!NT_SUCCESS(status))
240 continue;
241 ids = WdfMemoryGetBuffer(memory, &ids_length);
243 if (!NT_SUCCESS(status))
244 {
245 // KdPrint((__DRIVER_NAME " i = %d, status = %x, ids_length = %d\n", i, status, ids_length));
246 continue;
247 }
249 remaining = (ULONG)ids_length / 2;
250 for (ptr = ids; *ptr != 0; ptr += string_length + 1)
251 {
252 RtlStringCchLengthW(ptr, remaining, &string_length);
253 remaining -= (ULONG)string_length + 1;
254 if (string_length >= wcslen(matching_id))
255 {
256 ptr += string_length - wcslen(matching_id);
257 string_length = wcslen(matching_id);
258 }
259 // KdPrint((__DRIVER_NAME " Comparing '%S' and '%S'\n", ptr, matching_id));
260 if (wcscmp(ptr, matching_id) == 0)
261 {
262 //KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ " (Match)\n"));
263 WdfObjectDelete(memory);
264 return TRUE;
265 }
266 }
267 WdfObjectDelete(memory);
268 }
269 // KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ " (No match)\n"));
270 return FALSE;
271 }
273 ULONG qemu_filtered;
274 ULONG qemu_filtered_by_qemu;
276 static NTSTATUS
277 XenPci_EvtDeviceAdd_XenHide(WDFDRIVER driver, PWDFDEVICE_INIT device_init)
278 {
279 NTSTATUS status;
280 WDFMEMORY memory;
281 PWCHAR device_description;
282 WDF_PNPPOWER_EVENT_CALLBACKS pnp_power_callbacks;
283 WDF_OBJECT_ATTRIBUTES device_attributes;
284 BOOLEAN hide_required = FALSE;
285 WDFDEVICE device;
286 WDFKEY param_key;
287 DECLARE_CONST_UNICODE_STRING(hide_devices_name, L"hide_devices");
288 WDFCOLLECTION hide_devices;
289 ULONG i;
291 UNREFERENCED_PARAMETER(driver);
293 FUNCTION_ENTER();
295 WdfCollectionCreate(WDF_NO_OBJECT_ATTRIBUTES, &hide_devices);
296 status = WdfDriverOpenParametersRegistryKey(driver, KEY_QUERY_VALUE, WDF_NO_OBJECT_ATTRIBUTES, &param_key);
297 if (NT_SUCCESS(status))
298 {
299 status = WdfRegistryQueryMultiString(param_key, &hide_devices_name, WDF_NO_OBJECT_ATTRIBUTES, hide_devices);
300 if (!NT_SUCCESS(status))
301 {
302 KdPrint(("Error reading parameters/hide_devices value %08x\n", status));
303 }
304 WdfRegistryClose(param_key);
305 }
306 else
307 {
308 KdPrint(("Error opening parameters key %08x\n", status));
309 }
310 status = WdfFdoInitAllocAndQueryProperty(device_init, DevicePropertyDeviceDescription, NonPagedPool, WDF_NO_OBJECT_ATTRIBUTES, &memory);
311 if (NT_SUCCESS(status))
312 {
313 device_description = WdfMemoryGetBuffer(memory, NULL);
314 }
315 else
316 {
317 device_description = L"<unknown device>";
318 }
320 for (i = 0; i < WdfCollectionGetCount(hide_devices); i++)
321 {
322 WDFSTRING wdf_string = WdfCollectionGetItem(hide_devices, i);
323 UNICODE_STRING unicode_string;
324 WdfStringGetUnicodeString(wdf_string, &unicode_string);
325 if (XenPci_IdSuffixMatches(device_init, unicode_string.Buffer))
326 {
327 hide_required = TRUE;
328 break;
329 }
330 }
331 #if 0
332 /* hide only specific devices */
333 if (XenPci_IdSuffixMatches(device_init, L"VEN_8086&DEV_7010")) // Qemu IDE
334 {
335 hide_required = TRUE;
336 }
337 else if (XenPci_IdSuffixMatches(device_init, L"VEN_1000&DEV_0012"))// Qemu SCSI
338 {
339 hide_required = TRUE;
340 }
341 else if (XenPci_IdSuffixMatches(device_init, L"VEN_10EC&DEV_8139")) // Qemu Network
342 {
343 hide_required = TRUE;
344 }
345 #endif
346 if (!hide_required)
347 {
348 WdfObjectDelete(memory);
349 KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ " (filter not required for %S)\n", device_description));
350 return STATUS_SUCCESS;
351 }
353 KdPrint((__DRIVER_NAME " Installing Filter for %S\n", device_description));
355 WdfFdoInitSetFilter(device_init);
356 WdfDeviceInitSetDeviceType(device_init, FILE_DEVICE_UNKNOWN);
357 WdfDeviceInitSetExclusive(device_init, FALSE);
359 WDF_PNPPOWER_EVENT_CALLBACKS_INIT(&pnp_power_callbacks);
360 pnp_power_callbacks.EvtDevicePrepareHardware = XenHide_EvtDevicePrepareHardware;
361 WdfDeviceInitSetPnpPowerEventCallbacks(device_init, &pnp_power_callbacks);
363 WDF_OBJECT_ATTRIBUTES_INIT(&device_attributes);
364 status = WdfDeviceCreate(&device_init, &device_attributes, &device);
365 if (!NT_SUCCESS(status))
366 {
367 KdPrint(("Error creating device %08x\n", status));
368 WdfObjectDelete(memory);
369 FUNCTION_EXIT();
370 return status;
371 }
373 WdfObjectDelete(memory);
374 FUNCTION_EXIT();
376 return status;
377 }
379 static NTSTATUS
380 XenPci_EvtDeviceAdd(WDFDRIVER driver, PWDFDEVICE_INIT device_init)
381 {
382 if (XenPci_IdSuffixMatches(device_init, L"VEN_5853&DEV_0001"))
383 {
384 KdPrint((__DRIVER_NAME " Xen PCI device found - must be fdo\n"));
385 return XenPci_EvtDeviceAdd_XenPci(driver, device_init);
386 }
387 else if (qemu_filtered && !qemu_filtered_by_qemu)
388 {
389 KdPrint((__DRIVER_NAME " Xen PCI device not found - must be filter\n"));
390 return XenPci_EvtDeviceAdd_XenHide(driver, device_init);
391 }
392 else
393 return STATUS_SUCCESS;
394 }
396 ULONG qemu_protocol_version;
397 ULONG tpr_patch_requested;
398 extern PULONG InitSafeBootMode;
400 VOID
401 XenPci_HideQemuDevices()
402 {
403 qemu_filtered_by_qemu = FALSE;
404 if (READ_PORT_USHORT(XEN_IOPORT_MAGIC) == 0x49d2)
405 {
406 qemu_protocol_version = READ_PORT_UCHAR(XEN_IOPORT_VERSION);
407 KdPrint((__DRIVER_NAME " Version = %d\n", qemu_protocol_version));
408 switch(qemu_protocol_version)
409 {
410 case 1:
411 WRITE_PORT_USHORT(XEN_IOPORT_PRODUCT, XEN_PV_PRODUCT_NUMBER);
412 WRITE_PORT_ULONG(XEN_IOPORT_BUILD, XEN_PV_PRODUCT_BUILD);
413 if (READ_PORT_USHORT(XEN_IOPORT_MAGIC) != 0x49d2)
414 {
415 KdPrint((__DRIVER_NAME " Blacklisted\n"));
416 break;
417 }
418 /* fall through */
419 case 0:
420 qemu_filtered_by_qemu = TRUE;
421 WRITE_PORT_USHORT(XEN_IOPORT_DEVICE_MASK, QEMU_UNPLUG_ALL_IDE_DISKS|QEMU_UNPLUG_ALL_NICS);
422 KdPrint((__DRIVER_NAME " Disabled qemu devices\n"));
423 break;
424 default:
425 KdPrint((__DRIVER_NAME " Unknown qemu version %d\n", qemu_protocol_version));
426 break;
427 }
428 }
429 }
431 /*
432 make sure the load order is System Reserved, Dummy Group, WdfLoadGroup, XenPCI, Boot Bus Extender
433 */
435 static VOID
436 XenPci_FixLoadOrder()
437 {
438 NTSTATUS status;
439 WDFCOLLECTION old_load_order, new_load_order;
440 DECLARE_CONST_UNICODE_STRING(sgo_name, L"\\Registry\\Machine\\SYSTEM\\CurrentControlSet\\Control\\ServiceGroupOrder");
441 DECLARE_CONST_UNICODE_STRING(list_name, L"List");
442 WDFKEY sgo_key;
443 ULONG i;
444 LONG dummy_group_index = -1;
445 LONG boot_bus_extender_index = -1;
446 LONG xenpci_group_index = -1;
447 LONG wdf_load_group_index = -1;
448 DECLARE_CONST_UNICODE_STRING(dummy_group_name, L"Dummy Group");
449 DECLARE_CONST_UNICODE_STRING(wdf_load_group_name, L"WdfLoadGroup");
450 DECLARE_CONST_UNICODE_STRING(xenpci_group_name, L"XenPCI Group");
451 DECLARE_CONST_UNICODE_STRING(boot_bus_extender_name, L"Boot Bus Extender");
453 FUNCTION_ENTER();
455 status = WdfRegistryOpenKey(NULL, &sgo_name, KEY_QUERY_VALUE, WDF_NO_OBJECT_ATTRIBUTES, &sgo_key);
456 if (!NT_SUCCESS(status))
457 {
458 KdPrint((__DRIVER_NAME " Error opening ServiceGroupOrder key %08x\n", status));
459 return;
460 }
461 WdfCollectionCreate(WDF_NO_OBJECT_ATTRIBUTES, &old_load_order);
462 WdfCollectionCreate(WDF_NO_OBJECT_ATTRIBUTES, &new_load_order);
463 status = WdfRegistryQueryMultiString(sgo_key, &list_name, WDF_NO_OBJECT_ATTRIBUTES, old_load_order);
464 if (!NT_SUCCESS(status))
465 {
466 KdPrint((__DRIVER_NAME " Error reading ServiceGroupOrder\\List value %08x\n", status));
467 WdfObjectDelete(new_load_order);
468 WdfObjectDelete(old_load_order);
469 return;
470 }
471 KdPrint((__DRIVER_NAME " Current Order:\n"));
472 for (i = 0; i < WdfCollectionGetCount(old_load_order); i++)
473 {
474 WDFOBJECT ws = WdfCollectionGetItem(old_load_order, i);
475 UNICODE_STRING val;
476 WdfStringGetUnicodeString(ws, &val);
477 if (!RtlCompareUnicodeString(&val, &dummy_group_name, TRUE))
478 dummy_group_index = (ULONG)i;
479 if (!RtlCompareUnicodeString(&val, &wdf_load_group_name, TRUE))
480 wdf_load_group_index = (ULONG)i;
481 if (!RtlCompareUnicodeString(&val, &xenpci_group_name, TRUE))
482 xenpci_group_index = (ULONG)i;
483 if (!RtlCompareUnicodeString(&val, &boot_bus_extender_name, TRUE))
484 boot_bus_extender_index = (ULONG)i;
485 KdPrint((__DRIVER_NAME " %wZ\n", &val));
486 }
487 KdPrint((__DRIVER_NAME " dummy_group_index = %d\n", dummy_group_index));
488 KdPrint((__DRIVER_NAME " wdf_load_group_index = %d\n", wdf_load_group_index));
489 KdPrint((__DRIVER_NAME " xenpci_group_index = %d\n", xenpci_group_index));
490 KdPrint((__DRIVER_NAME " boot_bus_extender_index = %d\n", boot_bus_extender_index));
491 if (boot_bus_extender_index == -1)
492 {
493 WdfObjectDelete(new_load_order);
494 WdfObjectDelete(old_load_order);
495 WdfRegistryClose(sgo_key);
496 return; /* something is very wrong */
497 }
498 if (dummy_group_index == 1 && (wdf_load_group_index == -1 ||
499 (dummy_group_index < wdf_load_group_index
500 && wdf_load_group_index < xenpci_group_index
501 && xenpci_group_index < boot_bus_extender_index)))
502 {
503 return; /* our work here is done */
504 }
505 for (i = 0; i < WdfCollectionGetCount(old_load_order); i++)
506 {
507 WDFOBJECT ws;
508 if (i == 1)
509 {
510 WDFSTRING tmp_wdf_string;
511 WdfStringCreate(&dummy_group_name, WDF_NO_OBJECT_ATTRIBUTES, &tmp_wdf_string);
512 WdfCollectionAdd(new_load_order, tmp_wdf_string);
513 WdfObjectDelete(tmp_wdf_string);
514 }
515 if (i == 1 && wdf_load_group_index != -1)
516 {
517 WDFSTRING tmp_wdf_string;
518 WdfStringCreate(&wdf_load_group_name, WDF_NO_OBJECT_ATTRIBUTES, &tmp_wdf_string);
519 WdfCollectionAdd(new_load_order, tmp_wdf_string);
520 WdfObjectDelete(tmp_wdf_string);
521 }
522 if (i == 1)
523 {
524 WDFSTRING tmp_wdf_string;
525 WdfStringCreate(&xenpci_group_name, WDF_NO_OBJECT_ATTRIBUTES, &tmp_wdf_string);
526 WdfCollectionAdd(new_load_order, tmp_wdf_string);
527 WdfObjectDelete(tmp_wdf_string);
528 }
529 if (i == (ULONG)dummy_group_index || i == (ULONG)wdf_load_group_index || i == (ULONG)xenpci_group_index)
530 continue;
531 ws = WdfCollectionGetItem(old_load_order, i);
532 WdfCollectionAdd(new_load_order, ws);
533 }
534 WdfRegistryAssignMultiString(sgo_key, &list_name, new_load_order);
535 KdPrint((__DRIVER_NAME " New Order:\n"));
536 for (i = 0; i < WdfCollectionGetCount(new_load_order); i++)
537 {
538 WDFOBJECT ws = WdfCollectionGetItem(new_load_order, i);
539 UNICODE_STRING val;
540 WdfStringGetUnicodeString(ws, &val);
541 KdPrint((__DRIVER_NAME " %wZ\n", &val));
542 }
543 WdfObjectDelete(new_load_order);
544 WdfObjectDelete(old_load_order);
545 WdfRegistryClose(sgo_key);
547 FUNCTION_EXIT();
549 return;
550 }
552 KBUGCHECK_CALLBACK_RECORD callback_record;
554 static VOID
555 XenPci_BugcheckCallback(PVOID buffer, ULONG length)
556 {
557 NTSTATUS status;
558 KBUGCHECK_DATA bugcheck_data;
560 UNREFERENCED_PARAMETER(buffer);
561 UNREFERENCED_PARAMETER(length);
563 bugcheck_data.BugCheckDataSize = sizeof(bugcheck_data);
564 status = AuxKlibGetBugCheckData(&bugcheck_data);
565 if(!NT_SUCCESS(status))
566 {
567 KdPrint((__DRIVER_NAME " AuxKlibGetBugCheckData returned %08x\n", status));
568 return;
569 }
570 KdPrint((__DRIVER_NAME " Bug check 0x%08X (0x%p, 0x%p, 0x%p, 0x%p)\n",
571 bugcheck_data.BugCheckCode, bugcheck_data.Parameter1, bugcheck_data.Parameter2, bugcheck_data.Parameter3, bugcheck_data.Parameter4));
572 }
574 NTSTATUS
575 DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath)
576 {
577 NTSTATUS status = STATUS_SUCCESS;
578 WDF_DRIVER_CONFIG config;
579 WDFDRIVER driver;
580 PCONFIGURATION_INFORMATION conf_info;
581 WCHAR *SystemStartOptions;
582 UNICODE_STRING RegKeyName;
583 UNICODE_STRING RegValueName;
584 HANDLE RegHandle;
585 OBJECT_ATTRIBUTES RegObjectAttributes;
586 char Buf[300];// Sometimes bigger then 200 if system reboot from crash
587 ULONG BufLen = 300;
588 PKEY_VALUE_PARTIAL_INFORMATION KeyPartialValue;
590 UNREFERENCED_PARAMETER(RegistryPath);
592 FUNCTION_ENTER();
594 status = AuxKlibInitialize();
595 if(!NT_SUCCESS(status))
596 {
597 KdPrint((__DRIVER_NAME " AuxKlibInitialize failed %08x - expect a crash soon\n", status));
598 }
600 KeInitializeCallbackRecord(&callback_record);
601 if (!KeRegisterBugCheckCallback(&callback_record, XenPci_BugcheckCallback, NULL, 0, (PUCHAR)"XenPci"))
602 {
603 KdPrint((__DRIVER_NAME " KeRegisterBugCheckCallback failed\n"));
604 }
606 XenPci_FixLoadOrder();
608 RtlInitUnicodeString(&RegKeyName, L"\\Registry\\Machine\\System\\CurrentControlSet\\Control");
609 InitializeObjectAttributes(&RegObjectAttributes, &RegKeyName, OBJ_CASE_INSENSITIVE, NULL, NULL);
610 status = ZwOpenKey(&RegHandle, KEY_READ, &RegObjectAttributes);
611 if(!NT_SUCCESS(status))
612 {
613 KdPrint((__DRIVER_NAME " ZwOpenKey returned %08x\n", status));
614 }
616 RtlInitUnicodeString(&RegValueName, L"SystemStartOptions");
617 status = ZwQueryValueKey(RegHandle, &RegValueName, KeyValuePartialInformation, Buf, BufLen, &BufLen);
618 if(!NT_SUCCESS(status))
619 {
620 KdPrint((__DRIVER_NAME " ZwQueryKeyValue returned %08x\n", status));
621 }
622 else
623 ZwClose(RegHandle);
624 KeyPartialValue = (PKEY_VALUE_PARTIAL_INFORMATION)Buf;
625 SystemStartOptions = (WCHAR *)KeyPartialValue->Data;
627 KdPrint((__DRIVER_NAME " SystemStartOptions = %S\n", SystemStartOptions));
629 if (wcsstr(SystemStartOptions, L"PATCHTPR"))
630 {
631 WDFKEY memory_key;
632 UNICODE_STRING verifier_key_name;
633 UNICODE_STRING verifier_value_name;
634 ULONG verifier_value;
636 KdPrint((__DRIVER_NAME " PATCHTPR found\n"));
638 RtlInitUnicodeString(&verifier_key_name, L"\\Registry\\Machine\\System\\CurrentControlSet\\Control\\Session Manager\\Memory Management");
639 status = WdfRegistryOpenKey(NULL, &verifier_key_name, KEY_READ, WDF_NO_OBJECT_ATTRIBUTES, &memory_key);
640 if (!NT_SUCCESS(status))
641 {
642 tpr_patch_requested = TRUE;
643 }
644 else
645 {
646 RtlInitUnicodeString(&verifier_value_name, L"VerifyDriverLevel");
647 status = WdfRegistryQueryULong(memory_key, &verifier_value_name, &verifier_value);
648 if (NT_SUCCESS(status) && verifier_value != 0)
649 {
650 KdPrint((__DRIVER_NAME " Verifier active - not patching\n"));
651 }
652 else
653 {
654 tpr_patch_requested = TRUE;
655 }
656 WdfRegistryClose(memory_key);
657 }
658 }
660 if (wcsstr(SystemStartOptions, L"NOGPLPV"))
661 KdPrint((__DRIVER_NAME " NOGPLPV found\n"));
662 conf_info = IoGetConfigurationInformation();
663 if ((conf_info == NULL || conf_info->DiskCount == 0)
664 && !wcsstr(SystemStartOptions, L"NOGPLPV")
665 && !*InitSafeBootMode)
666 {
667 qemu_filtered = TRUE;
668 /* see if the qemu method of disabling the PCI devices exists */
669 XenPci_HideQemuDevices();
670 }
672 if (qemu_filtered)
673 KdPrint((__DRIVER_NAME " PV Devices Active\n"));
674 else
675 KdPrint((__DRIVER_NAME " PV Devices Inactive\n"));
677 WDF_DRIVER_CONFIG_INIT(&config, XenPci_EvtDeviceAdd);
678 status = WdfDriverCreate(DriverObject, RegistryPath, WDF_NO_OBJECT_ATTRIBUTES, &config, &driver);
680 if (!NT_SUCCESS(status)) {
681 KdPrint((__DRIVER_NAME " WdfDriverCreate failed with status 0x%x\n", status));
682 }
684 FUNCTION_EXIT();
686 return status;
687 }