win-pvdrivers

view xenpci/xenpci.c @ 622:f905eb3f0545

Shut down threads properly on hibernate.
Added some debug to try and find where the hang happens when the verifier is enabled
Added the suspend event channel to allow triggering a suspend much earlier
author James Harper <james.harper@bendigoit.com.au>
date Wed Aug 05 19:09:55 2009 +1000 (2009-08-05)
parents f118fcbe5ca8
children 0b55299418ce
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 <stdlib.h>
24 #define SYSRQ_PATH "control/sysrq"
25 #define SHUTDOWN_PATH "control/shutdown"
26 #define BALLOON_PATH "memory/target"
28 #pragma warning(disable : 4200) // zero-sized array
30 static VOID
31 XenPci_EvtDeviceUsageNotification(WDFDEVICE device, WDF_SPECIAL_FILE_TYPE notification_type, BOOLEAN is_in_notification_path)
32 {
33 FUNCTION_ENTER();
35 UNREFERENCED_PARAMETER(device);
37 switch (notification_type)
38 {
39 case WdfSpecialFilePaging:
40 KdPrint((__DRIVER_NAME " notification_type = Paging, flag = %d\n", is_in_notification_path));
41 break;
42 case WdfSpecialFileHibernation:
43 KdPrint((__DRIVER_NAME " notification_type = Hibernation, flag = %d\n", is_in_notification_path));
44 break;
45 case WdfSpecialFileDump:
46 KdPrint((__DRIVER_NAME " notification_type = Dump, flag = %d\n", is_in_notification_path));
47 break;
48 default:
49 KdPrint((__DRIVER_NAME " notification_type = %d, flag = %d\n", notification_type, is_in_notification_path));
50 break;
51 }
53 FUNCTION_EXIT();
54 }
56 static NTSTATUS
57 XenPci_EvtDeviceAdd_XenPci(WDFDRIVER driver, PWDFDEVICE_INIT device_init)
58 {
59 NTSTATUS status;
60 // PDEVICE_OBJECT fdo = NULL;
61 // PNP_BUS_INFORMATION busInfo;
62 // DECLARE_CONST_UNICODE_STRING(DeviceName, L"\\Device\\XenShutdown");
63 // DECLARE_CONST_UNICODE_STRING(SymbolicName, L"\\DosDevices\\XenShutdown");
64 WDF_CHILD_LIST_CONFIG child_list_config;
65 WDFDEVICE device;
66 PXENPCI_DEVICE_DATA xpdd;
67 UNICODE_STRING reference;
68 WDF_OBJECT_ATTRIBUTES device_attributes;
69 PNP_BUS_INFORMATION pbi;
70 WDF_PNPPOWER_EVENT_CALLBACKS pnp_power_callbacks;
71 WDF_INTERRUPT_CONFIG interrupt_config;
72 WDF_OBJECT_ATTRIBUTES file_attributes;
73 WDF_FILEOBJECT_CONFIG file_config;
74 WDF_IO_QUEUE_CONFIG queue_config;
75 WDFKEY param_key;
76 DECLARE_CONST_UNICODE_STRING(veto_devices_name, L"veto_devices");
77 WDF_DEVICE_POWER_CAPABILITIES power_capabilities;
79 UNREFERENCED_PARAMETER(driver);
81 FUNCTION_ENTER();
83 WDF_PNPPOWER_EVENT_CALLBACKS_INIT(&pnp_power_callbacks);
84 pnp_power_callbacks.EvtDeviceD0Entry = XenPci_EvtDeviceD0Entry;
85 pnp_power_callbacks.EvtDeviceD0EntryPostInterruptsEnabled = XenPci_EvtDeviceD0EntryPostInterruptsEnabled;
86 pnp_power_callbacks.EvtDeviceD0Exit = XenPci_EvtDeviceD0Exit;
87 pnp_power_callbacks.EvtDeviceD0ExitPreInterruptsDisabled = XenPci_EvtDeviceD0ExitPreInterruptsDisabled;
88 pnp_power_callbacks.EvtDevicePrepareHardware = XenPci_EvtDevicePrepareHardware;
89 pnp_power_callbacks.EvtDeviceReleaseHardware = XenPci_EvtDeviceReleaseHardware;
90 pnp_power_callbacks.EvtDeviceQueryRemove = XenPci_EvtDeviceQueryRemove;
91 pnp_power_callbacks.EvtDeviceUsageNotification = XenPci_EvtDeviceUsageNotification;
93 WdfDeviceInitSetPnpPowerEventCallbacks(device_init, &pnp_power_callbacks);
95 WdfDeviceInitSetDeviceType(device_init, FILE_DEVICE_BUS_EXTENDER);
96 WdfDeviceInitSetExclusive(device_init, FALSE);
98 WDF_CHILD_LIST_CONFIG_INIT(&child_list_config, sizeof(XENPCI_PDO_IDENTIFICATION_DESCRIPTION), XenPci_EvtChildListCreateDevice);
99 child_list_config.EvtChildListScanForChildren = XenPci_EvtChildListScanForChildren;
100 WdfFdoInitSetDefaultChildListConfig(device_init, &child_list_config, WDF_NO_OBJECT_ATTRIBUTES);
102 WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&file_attributes, XENPCI_DEVICE_INTERFACE_DATA);
103 WDF_FILEOBJECT_CONFIG_INIT(&file_config, XenPci_EvtDeviceFileCreate, XenPci_EvtFileClose, XenPci_EvtFileCleanup);
104 WdfDeviceInitSetFileObjectConfig(device_init, &file_config, &file_attributes);
106 WdfDeviceInitSetIoType(device_init, WdfDeviceIoBuffered);
108 WdfDeviceInitSetPowerNotPageable(device_init);
110 WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&device_attributes, XENPCI_DEVICE_DATA);
111 status = WdfDeviceCreate(&device_init, &device_attributes, &device);
112 if (!NT_SUCCESS(status))
113 {
114 KdPrint(("Error creating device %08x\n", status));
115 return status;
116 }
118 xpdd = GetXpdd(device);
119 xpdd->wdf_device = device;
120 xpdd->child_list = WdfFdoGetDefaultChildList(device);
122 WdfCollectionCreate(WDF_NO_OBJECT_ATTRIBUTES, &xpdd->veto_devices);
123 status = WdfDriverOpenParametersRegistryKey(driver, KEY_QUERY_VALUE, WDF_NO_OBJECT_ATTRIBUTES, &param_key);
124 if (NT_SUCCESS(status))
125 {
126 status = WdfRegistryQueryMultiString(param_key, &veto_devices_name, WDF_NO_OBJECT_ATTRIBUTES, xpdd->veto_devices);
127 if (!NT_SUCCESS(status))
128 {
129 KdPrint(("Error reading parameters/veto_devices value %08x\n", status));
130 }
131 WdfRegistryClose(param_key);
132 }
133 else
134 {
135 KdPrint(("Error opening parameters key %08x\n", status));
136 }
138 WDF_DEVICE_POWER_CAPABILITIES_INIT(&power_capabilities);
139 power_capabilities.DeviceD1 = WdfTrue;
140 power_capabilities.WakeFromD1 = WdfTrue;
141 power_capabilities.DeviceWake = PowerDeviceD1;
142 power_capabilities.DeviceState[PowerSystemWorking] = PowerDeviceD1;
143 power_capabilities.DeviceState[PowerSystemSleeping1] = PowerDeviceD1;
144 power_capabilities.DeviceState[PowerSystemSleeping2] = PowerDeviceD2;
145 power_capabilities.DeviceState[PowerSystemSleeping3] = PowerDeviceD2;
146 power_capabilities.DeviceState[PowerSystemHibernate] = PowerDeviceD3;
147 power_capabilities.DeviceState[PowerSystemShutdown] = PowerDeviceD3;
148 WdfDeviceSetPowerCapabilities(device, &power_capabilities);
150 WdfDeviceSetSpecialFileSupport(device, WdfSpecialFilePaging, TRUE);
151 WdfDeviceSetSpecialFileSupport(device, WdfSpecialFileHibernation, TRUE);
152 WdfDeviceSetSpecialFileSupport(device, WdfSpecialFileDump, TRUE);
154 WDF_IO_QUEUE_CONFIG_INIT_DEFAULT_QUEUE(&queue_config, WdfIoQueueDispatchParallel);
155 queue_config.EvtIoRead = XenPci_EvtIoRead;
156 queue_config.EvtIoWrite = XenPci_EvtIoWrite;
157 status = WdfIoQueueCreate(device, &queue_config, WDF_NO_OBJECT_ATTRIBUTES, &xpdd->io_queue);
158 if (!NT_SUCCESS(status)) {
159 KdPrint(("Error creating queue 0x%x\n", status));
160 return status;
161 }
163 WDF_INTERRUPT_CONFIG_INIT(&interrupt_config, EvtChn_EvtInterruptIsr, NULL);
164 interrupt_config.EvtInterruptEnable = EvtChn_EvtInterruptEnable;
165 interrupt_config.EvtInterruptDisable = EvtChn_EvtInterruptDisable;
167 status = WdfInterruptCreate(device, &interrupt_config, WDF_NO_OBJECT_ATTRIBUTES, &xpdd->interrupt);
168 if (!NT_SUCCESS(status))
169 {
170 KdPrint(("Error creating interrupt 0x%x\n", status));
171 return status;
172 }
174 RtlInitUnicodeString(&reference, L"xenbus");
175 status = WdfDeviceCreateDeviceInterface(device, &GUID_DEVINTERFACE_XENBUS, &reference);
176 if (!NT_SUCCESS(status)) {
177 KdPrint(("Error registering device interface 0x%x\n", status));
178 return status;
179 }
181 pbi.BusTypeGuid = GUID_BUS_TYPE_XEN;
182 pbi.LegacyBusType = PNPBus;
183 pbi.BusNumber = 0;
184 WdfDeviceSetBusInformationForChildren(device, &pbi);
186 xpdd->removable = TRUE;
188 FUNCTION_EXIT();
189 return status;
190 }
192 NTSTATUS
193 XenHide_EvtDevicePrepareHardware (WDFDEVICE device, WDFCMRESLIST resources_raw, WDFCMRESLIST resources_translated)
194 {
195 UNREFERENCED_PARAMETER(device);
196 UNREFERENCED_PARAMETER(resources_raw);
197 UNREFERENCED_PARAMETER(resources_translated);
198 FUNCTION_ENTER();
199 FUNCTION_EXIT();
200 return STATUS_UNSUCCESSFUL;
201 }
203 static BOOLEAN
204 XenPci_IdSuffixMatches(PWDFDEVICE_INIT device_init, PWCHAR matching_id)
205 {
206 NTSTATUS status;
207 WDFMEMORY memory;
208 ULONG remaining;
209 size_t string_length;
210 PWCHAR ids;
211 PWCHAR ptr;
212 size_t ids_length;
213 ULONG properties[] = {DevicePropertyCompatibleIDs, DevicePropertyHardwareID};
214 int i;
216 // KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
217 for (i = 0; i < ARRAY_SIZE(properties); i++)
218 {
220 status = WdfFdoInitAllocAndQueryProperty(device_init, properties[i], NonPagedPool, WDF_NO_OBJECT_ATTRIBUTES, &memory);
221 if (!NT_SUCCESS(status))
222 continue;
223 ids = WdfMemoryGetBuffer(memory, &ids_length);
225 if (!NT_SUCCESS(status))
226 {
227 // KdPrint((__DRIVER_NAME " i = %d, status = %x, ids_length = %d\n", i, status, ids_length));
228 continue;
229 }
231 remaining = (ULONG)ids_length / 2;
232 for (ptr = ids; *ptr != 0; ptr += string_length + 1)
233 {
234 RtlStringCchLengthW(ptr, remaining, &string_length);
235 remaining -= (ULONG)string_length + 1;
236 if (string_length >= wcslen(matching_id))
237 {
238 ptr += string_length - wcslen(matching_id);
239 string_length = wcslen(matching_id);
240 }
241 // KdPrint((__DRIVER_NAME " Comparing '%S' and '%S'\n", ptr, matching_id));
242 if (wcscmp(ptr, matching_id) == 0)
243 {
244 //KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ " (Match)\n"));
245 WdfObjectDelete(memory);
246 return TRUE;
247 }
248 }
249 WdfObjectDelete(memory);
250 }
251 // KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ " (No match)\n"));
252 return FALSE;
253 }
255 ULONG qemu_filtered;
256 ULONG qemu_filtered_by_qemu;
258 static NTSTATUS
259 XenPci_EvtDeviceAdd_XenHide(WDFDRIVER driver, PWDFDEVICE_INIT device_init)
260 {
261 NTSTATUS status;
262 WDFMEMORY memory;
263 PWCHAR device_description;
264 WDF_PNPPOWER_EVENT_CALLBACKS pnp_power_callbacks;
265 WDF_OBJECT_ATTRIBUTES device_attributes;
266 BOOLEAN hide_required = FALSE;
267 WDFDEVICE device;
268 WDFKEY param_key;
269 DECLARE_CONST_UNICODE_STRING(hide_devices_name, L"hide_devices");
270 WDFCOLLECTION hide_devices;
271 ULONG i;
273 UNREFERENCED_PARAMETER(driver);
275 FUNCTION_ENTER();
277 WdfCollectionCreate(WDF_NO_OBJECT_ATTRIBUTES, &hide_devices);
278 status = WdfDriverOpenParametersRegistryKey(driver, KEY_QUERY_VALUE, WDF_NO_OBJECT_ATTRIBUTES, &param_key);
279 if (NT_SUCCESS(status))
280 {
281 status = WdfRegistryQueryMultiString(param_key, &hide_devices_name, WDF_NO_OBJECT_ATTRIBUTES, hide_devices);
282 if (!NT_SUCCESS(status))
283 {
284 KdPrint(("Error reading parameters/hide_devices value %08x\n", status));
285 }
286 WdfRegistryClose(param_key);
287 }
288 else
289 {
290 KdPrint(("Error opening parameters key %08x\n", status));
291 }
292 if (!WdfCollectionGetCount(hide_devices))
293 {
294 WDFSTRING wdf_string;
295 UNICODE_STRING unicode_string;
297 RtlInitUnicodeString(&unicode_string, L"VEN_8086&DEV_7010"); // Qemu IDE
298 WdfStringCreate(&unicode_string, WDF_NO_OBJECT_ATTRIBUTES, &wdf_string);
299 WdfCollectionAdd(hide_devices, wdf_string);
300 RtlInitUnicodeString(&unicode_string, L"VEN_1000&DEV_0012"); // Qemu SCSI
301 WdfStringCreate(&unicode_string, WDF_NO_OBJECT_ATTRIBUTES, &wdf_string);
302 WdfCollectionAdd(hide_devices, wdf_string);
303 RtlInitUnicodeString(&unicode_string, L"VEN_10EC&DEV_8139"); // Qemu Network
304 WdfStringCreate(&unicode_string, WDF_NO_OBJECT_ATTRIBUTES, &wdf_string);
305 WdfCollectionAdd(hide_devices, wdf_string);
306 }
307 status = WdfFdoInitAllocAndQueryProperty(device_init, DevicePropertyDeviceDescription, NonPagedPool, WDF_NO_OBJECT_ATTRIBUTES, &memory);
308 if (NT_SUCCESS(status))
309 {
310 device_description = WdfMemoryGetBuffer(memory, NULL);
311 }
312 else
313 {
314 device_description = L"<unknown device>";
315 }
317 for (i = 0; i < WdfCollectionGetCount(hide_devices); i++)
318 {
319 WDFSTRING wdf_string = WdfCollectionGetItem(hide_devices, i);
320 UNICODE_STRING unicode_string;
321 WdfStringGetUnicodeString(wdf_string, &unicode_string);
322 if (XenPci_IdSuffixMatches(device_init, unicode_string.Buffer))
323 {
324 hide_required = TRUE;
325 break;
326 }
327 }
328 #if 0
329 /* hide only specific devices */
330 if (XenPci_IdSuffixMatches(device_init, L"VEN_8086&DEV_7010")) // Qemu IDE
331 {
332 hide_required = TRUE;
333 }
334 else if (XenPci_IdSuffixMatches(device_init, L"VEN_1000&DEV_0012"))// Qemu SCSI
335 {
336 hide_required = TRUE;
337 }
338 else if (XenPci_IdSuffixMatches(device_init, L"VEN_10EC&DEV_8139")) // Qemu Network
339 {
340 hide_required = TRUE;
341 }
342 #endif
343 if (!hide_required)
344 {
345 WdfObjectDelete(memory);
346 KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ " (filter not required for %S)\n", device_description));
347 return STATUS_SUCCESS;
348 }
350 KdPrint((__DRIVER_NAME " Installing Filter for %S\n", device_description));
352 WdfFdoInitSetFilter(device_init);
353 WdfDeviceInitSetDeviceType(device_init, FILE_DEVICE_UNKNOWN);
354 WdfDeviceInitSetExclusive(device_init, FALSE);
356 WDF_PNPPOWER_EVENT_CALLBACKS_INIT(&pnp_power_callbacks);
357 pnp_power_callbacks.EvtDevicePrepareHardware = XenHide_EvtDevicePrepareHardware;
358 WdfDeviceInitSetPnpPowerEventCallbacks(device_init, &pnp_power_callbacks);
360 WDF_OBJECT_ATTRIBUTES_INIT(&device_attributes);
361 status = WdfDeviceCreate(&device_init, &device_attributes, &device);
362 if (!NT_SUCCESS(status))
363 {
364 KdPrint(("Error creating device %08x\n", status));
365 WdfObjectDelete(memory);
366 FUNCTION_EXIT();
367 return status;
368 }
370 WdfObjectDelete(memory);
371 FUNCTION_EXIT();
373 return status;
374 }
376 static NTSTATUS
377 XenPci_EvtDeviceAdd(WDFDRIVER driver, PWDFDEVICE_INIT device_init)
378 {
379 if (XenPci_IdSuffixMatches(device_init, L"VEN_5853&DEV_0001"))
380 {
381 KdPrint((__DRIVER_NAME " Xen PCI device found - must be fdo\n"));
382 return XenPci_EvtDeviceAdd_XenPci(driver, device_init);
383 }
384 else if (qemu_filtered && !qemu_filtered_by_qemu)
385 {
386 KdPrint((__DRIVER_NAME " Xen PCI device not found - must be filter\n"));
387 return XenPci_EvtDeviceAdd_XenHide(driver, device_init);
388 }
389 else
390 return STATUS_SUCCESS;
391 }
393 ULONG qemu_protocol_version;
394 ULONG tpr_patch_requested;
395 extern PULONG InitSafeBootMode;
397 VOID
398 XenPci_HideQemuDevices()
399 {
400 qemu_filtered_by_qemu = FALSE;
401 if (READ_PORT_USHORT(XEN_IOPORT_MAGIC) == 0x49d2)
402 {
403 qemu_protocol_version = READ_PORT_UCHAR(XEN_IOPORT_VERSION);
404 KdPrint((__DRIVER_NAME " Version = %d\n", qemu_protocol_version));
405 switch(qemu_protocol_version)
406 {
407 case 1:
408 WRITE_PORT_USHORT(XEN_IOPORT_PRODUCT, XEN_PV_PRODUCT_NUMBER);
409 WRITE_PORT_ULONG(XEN_IOPORT_BUILD, XEN_PV_PRODUCT_BUILD);
410 if (READ_PORT_USHORT(XEN_IOPORT_MAGIC) != 0x49d2)
411 {
412 KdPrint((__DRIVER_NAME " Blacklisted\n"));
413 break;
414 }
415 /* fall through */
416 case 0:
417 qemu_filtered_by_qemu = TRUE;
418 WRITE_PORT_USHORT(XEN_IOPORT_DEVICE_MASK, QEMU_UNPLUG_ALL_IDE_DISKS|QEMU_UNPLUG_ALL_NICS);
419 KdPrint((__DRIVER_NAME " Disabled qemu devices\n"));
420 break;
421 default:
422 KdPrint((__DRIVER_NAME " Unknown qemu version %d\n", qemu_protocol_version));
423 break;
424 }
425 }
426 }
428 /*
429 make sure the load order is System Reserved, Dummy Group, WdfLoadGroup, XenPCI, Boot Bus Extender
430 */
432 static VOID
433 XenPci_FixLoadOrder()
434 {
435 NTSTATUS status;
436 WDFCOLLECTION old_load_order, new_load_order;
437 DECLARE_CONST_UNICODE_STRING(sgo_name, L"\\Registry\\Machine\\SYSTEM\\CurrentControlSet\\Control\\ServiceGroupOrder");
438 DECLARE_CONST_UNICODE_STRING(list_name, L"List");
439 WDFKEY sgo_key;
440 ULONG i;
441 LONG dummy_group_index = -1;
442 LONG boot_bus_extender_index = -1;
443 LONG xenpci_group_index = -1;
444 LONG wdf_load_group_index = -1;
445 DECLARE_CONST_UNICODE_STRING(dummy_group_name, L"Dummy Group");
446 DECLARE_CONST_UNICODE_STRING(wdf_load_group_name, L"WdfLoadGroup");
447 DECLARE_CONST_UNICODE_STRING(xenpci_group_name, L"XenPCI Group");
448 DECLARE_CONST_UNICODE_STRING(boot_bus_extender_name, L"Boot Bus Extender");
450 FUNCTION_ENTER();
452 status = WdfRegistryOpenKey(NULL, &sgo_name, KEY_QUERY_VALUE, WDF_NO_OBJECT_ATTRIBUTES, &sgo_key);
453 if (!NT_SUCCESS(status))
454 {
455 KdPrint((__DRIVER_NAME " Error opening ServiceGroupOrder key %08x\n", status));
456 return;
457 }
458 WdfCollectionCreate(WDF_NO_OBJECT_ATTRIBUTES, &old_load_order);
459 WdfCollectionCreate(WDF_NO_OBJECT_ATTRIBUTES, &new_load_order);
460 status = WdfRegistryQueryMultiString(sgo_key, &list_name, WDF_NO_OBJECT_ATTRIBUTES, old_load_order);
461 if (!NT_SUCCESS(status))
462 {
463 KdPrint((__DRIVER_NAME " Error reading ServiceGroupOrder\\List value %08x\n", status));
464 WdfObjectDelete(new_load_order);
465 WdfObjectDelete(old_load_order);
466 return;
467 }
468 KdPrint((__DRIVER_NAME " Current Order:\n"));
469 for (i = 0; i < WdfCollectionGetCount(old_load_order); i++)
470 {
471 WDFOBJECT ws = WdfCollectionGetItem(old_load_order, i);
472 UNICODE_STRING val;
473 WdfStringGetUnicodeString(ws, &val);
474 if (!RtlCompareUnicodeString(&val, &dummy_group_name, TRUE))
475 dummy_group_index = (ULONG)i;
476 if (!RtlCompareUnicodeString(&val, &wdf_load_group_name, TRUE))
477 wdf_load_group_index = (ULONG)i;
478 if (!RtlCompareUnicodeString(&val, &xenpci_group_name, TRUE))
479 xenpci_group_index = (ULONG)i;
480 if (!RtlCompareUnicodeString(&val, &boot_bus_extender_name, TRUE))
481 boot_bus_extender_index = (ULONG)i;
482 KdPrint((__DRIVER_NAME " %wZ\n", &val));
483 }
484 KdPrint((__DRIVER_NAME " dummy_group_index = %d\n", dummy_group_index));
485 KdPrint((__DRIVER_NAME " wdf_load_group_index = %d\n", wdf_load_group_index));
486 KdPrint((__DRIVER_NAME " xenpci_group_index = %d\n", xenpci_group_index));
487 KdPrint((__DRIVER_NAME " boot_bus_extender_index = %d\n", boot_bus_extender_index));
488 if (boot_bus_extender_index == -1)
489 {
490 WdfObjectDelete(new_load_order);
491 WdfObjectDelete(old_load_order);
492 WdfRegistryClose(sgo_key);
493 return; /* something is very wrong */
494 }
495 if (dummy_group_index == 1 && (wdf_load_group_index == -1 ||
496 (dummy_group_index < wdf_load_group_index
497 && wdf_load_group_index < xenpci_group_index
498 && xenpci_group_index < boot_bus_extender_index)))
499 {
500 return; /* our work here is done */
501 }
502 for (i = 0; i < WdfCollectionGetCount(old_load_order); i++)
503 {
504 WDFOBJECT ws;
505 if (i == 1)
506 {
507 WDFSTRING tmp_wdf_string;
508 WdfStringCreate(&dummy_group_name, WDF_NO_OBJECT_ATTRIBUTES, &tmp_wdf_string);
509 WdfCollectionAdd(new_load_order, tmp_wdf_string);
510 WdfObjectDelete(tmp_wdf_string);
511 }
512 if (i == 1 && wdf_load_group_index != -1)
513 {
514 WDFSTRING tmp_wdf_string;
515 WdfStringCreate(&wdf_load_group_name, WDF_NO_OBJECT_ATTRIBUTES, &tmp_wdf_string);
516 WdfCollectionAdd(new_load_order, tmp_wdf_string);
517 WdfObjectDelete(tmp_wdf_string);
518 }
519 if (i == 1)
520 {
521 WDFSTRING tmp_wdf_string;
522 WdfStringCreate(&xenpci_group_name, WDF_NO_OBJECT_ATTRIBUTES, &tmp_wdf_string);
523 WdfCollectionAdd(new_load_order, tmp_wdf_string);
524 WdfObjectDelete(tmp_wdf_string);
525 }
526 if (i == (ULONG)dummy_group_index || i == (ULONG)wdf_load_group_index || i == (ULONG)xenpci_group_index)
527 continue;
528 ws = WdfCollectionGetItem(old_load_order, i);
529 WdfCollectionAdd(new_load_order, ws);
530 }
531 WdfRegistryAssignMultiString(sgo_key, &list_name, new_load_order);
532 KdPrint((__DRIVER_NAME " New Order:\n"));
533 for (i = 0; i < WdfCollectionGetCount(new_load_order); i++)
534 {
535 WDFOBJECT ws = WdfCollectionGetItem(new_load_order, i);
536 UNICODE_STRING val;
537 WdfStringGetUnicodeString(ws, &val);
538 KdPrint((__DRIVER_NAME " %wZ\n", &val));
539 }
540 WdfObjectDelete(new_load_order);
541 WdfObjectDelete(old_load_order);
542 WdfRegistryClose(sgo_key);
544 FUNCTION_EXIT();
546 return;
547 }
549 NTSTATUS
550 DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath)
551 {
552 NTSTATUS status = STATUS_SUCCESS;
553 WDF_DRIVER_CONFIG config;
554 WDFDRIVER driver;
555 PCONFIGURATION_INFORMATION conf_info;
556 WCHAR *SystemStartOptions;
557 UNICODE_STRING RegKeyName;
558 UNICODE_STRING RegValueName;
559 HANDLE RegHandle;
560 OBJECT_ATTRIBUTES RegObjectAttributes;
561 char Buf[300];// Sometimes bigger then 200 if system reboot from crash
562 ULONG BufLen = 300;
563 PKEY_VALUE_PARTIAL_INFORMATION KeyPartialValue;
564 #if 0
565 WDF_TIMER_CONFIG timer_config;
566 OBJECT_ATTRIBUTES timer_attributes;
567 #endif
569 UNREFERENCED_PARAMETER(RegistryPath);
571 FUNCTION_ENTER();
573 XenPci_FixLoadOrder();
575 RtlInitUnicodeString(&RegKeyName, L"\\Registry\\Machine\\System\\CurrentControlSet\\Control");
576 InitializeObjectAttributes(&RegObjectAttributes, &RegKeyName, OBJ_CASE_INSENSITIVE, NULL, NULL);
577 status = ZwOpenKey(&RegHandle, KEY_READ, &RegObjectAttributes);
578 if(!NT_SUCCESS(status))
579 {
580 KdPrint((__DRIVER_NAME " ZwOpenKey returned %08x\n", status));
581 }
583 RtlInitUnicodeString(&RegValueName, L"SystemStartOptions");
584 status = ZwQueryValueKey(RegHandle, &RegValueName, KeyValuePartialInformation, Buf, BufLen, &BufLen);
585 if(!NT_SUCCESS(status))
586 {
587 KdPrint((__DRIVER_NAME " ZwQueryKeyValue returned %08x\n", status));
588 }
589 else
590 ZwClose(RegHandle);
591 KeyPartialValue = (PKEY_VALUE_PARTIAL_INFORMATION)Buf;
592 SystemStartOptions = (WCHAR *)KeyPartialValue->Data;
594 KdPrint((__DRIVER_NAME " SystemStartOptions = %S\n", SystemStartOptions));
596 if (wcsstr(SystemStartOptions, L"PATCHTPR"))
597 {
598 KdPrint((__DRIVER_NAME " PATCHTPR found\n"));
599 tpr_patch_requested = TRUE;
600 }
602 if (wcsstr(SystemStartOptions, L"NOGPLPV"))
603 KdPrint((__DRIVER_NAME " NOGPLPV found\n"));
604 conf_info = IoGetConfigurationInformation();
605 if ((conf_info == NULL || conf_info->DiskCount == 0)
606 && !wcsstr(SystemStartOptions, L"NOGPLPV")
607 && !*InitSafeBootMode)
608 {
609 qemu_filtered = TRUE;
610 /* see if the qemu method of disabling the PCI devices exists */
611 XenPci_HideQemuDevices();
612 }
614 if (qemu_filtered)
615 KdPrint((__DRIVER_NAME " PV Devices Active\n"));
616 else
617 KdPrint((__DRIVER_NAME " PV Devices Inactive\n"));
619 WDF_DRIVER_CONFIG_INIT(&config, XenPci_EvtDeviceAdd);
620 status = WdfDriverCreate(DriverObject, RegistryPath, WDF_NO_OBJECT_ATTRIBUTES, &config, &driver);
622 if (!NT_SUCCESS(status)) {
623 KdPrint((__DRIVER_NAME " WdfDriverCreate failed with status 0x%x\n", status));
624 }
626 FUNCTION_EXIT();
628 return status;
629 }