win-pvdrivers

view xenpci/xenpci.c @ 607:c2aea3e060a7

Missed a line in cut&paste in previous checksum fix
author James Harper <james.harper@bendigoit.com.au>
date Sun Jul 05 21:06:26 2009 +1000 (2009-07-05)
parents f118fcbe5ca8
children f905eb3f0545
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->child_list = WdfFdoGetDefaultChildList(device);
121 WdfCollectionCreate(WDF_NO_OBJECT_ATTRIBUTES, &xpdd->veto_devices);
122 status = WdfDriverOpenParametersRegistryKey(driver, KEY_QUERY_VALUE, WDF_NO_OBJECT_ATTRIBUTES, &param_key);
123 if (NT_SUCCESS(status))
124 {
125 status = WdfRegistryQueryMultiString(param_key, &veto_devices_name, WDF_NO_OBJECT_ATTRIBUTES, xpdd->veto_devices);
126 if (!NT_SUCCESS(status))
127 {
128 KdPrint(("Error reading parameters/veto_devices value %08x\n", status));
129 }
130 WdfRegistryClose(param_key);
131 }
132 else
133 {
134 KdPrint(("Error opening parameters key %08x\n", status));
135 }
137 WDF_DEVICE_POWER_CAPABILITIES_INIT(&power_capabilities);
138 power_capabilities.DeviceD1 = WdfTrue;
139 power_capabilities.WakeFromD1 = WdfTrue;
140 power_capabilities.DeviceWake = PowerDeviceD1;
141 power_capabilities.DeviceState[PowerSystemWorking] = PowerDeviceD1;
142 power_capabilities.DeviceState[PowerSystemSleeping1] = PowerDeviceD1;
143 power_capabilities.DeviceState[PowerSystemSleeping2] = PowerDeviceD2;
144 power_capabilities.DeviceState[PowerSystemSleeping3] = PowerDeviceD2;
145 power_capabilities.DeviceState[PowerSystemHibernate] = PowerDeviceD3;
146 power_capabilities.DeviceState[PowerSystemShutdown] = PowerDeviceD3;
147 WdfDeviceSetPowerCapabilities(device, &power_capabilities);
149 WdfDeviceSetSpecialFileSupport(device, WdfSpecialFilePaging, TRUE);
150 WdfDeviceSetSpecialFileSupport(device, WdfSpecialFileHibernation, TRUE);
151 WdfDeviceSetSpecialFileSupport(device, WdfSpecialFileDump, TRUE);
153 WDF_IO_QUEUE_CONFIG_INIT_DEFAULT_QUEUE(&queue_config, WdfIoQueueDispatchParallel);
154 queue_config.EvtIoRead = XenPci_EvtIoRead;
155 queue_config.EvtIoWrite = XenPci_EvtIoWrite;
156 status = WdfIoQueueCreate(device, &queue_config, WDF_NO_OBJECT_ATTRIBUTES, &xpdd->io_queue);
157 if (!NT_SUCCESS(status)) {
158 KdPrint(("Error creating queue 0x%x\n", status));
159 return status;
160 }
162 WDF_INTERRUPT_CONFIG_INIT(&interrupt_config, EvtChn_EvtInterruptIsr, NULL);
163 interrupt_config.EvtInterruptEnable = EvtChn_EvtInterruptEnable;
164 interrupt_config.EvtInterruptDisable = EvtChn_EvtInterruptDisable;
166 status = WdfInterruptCreate(device, &interrupt_config, WDF_NO_OBJECT_ATTRIBUTES, &xpdd->interrupt);
167 if (!NT_SUCCESS(status))
168 {
169 KdPrint(("Error creating interrupt 0x%x\n", status));
170 return status;
171 }
173 RtlInitUnicodeString(&reference, L"xenbus");
174 status = WdfDeviceCreateDeviceInterface(device, &GUID_DEVINTERFACE_XENBUS, &reference);
175 if (!NT_SUCCESS(status)) {
176 KdPrint(("Error registering device interface 0x%x\n", status));
177 return status;
178 }
180 pbi.BusTypeGuid = GUID_BUS_TYPE_XEN;
181 pbi.LegacyBusType = PNPBus;
182 pbi.BusNumber = 0;
183 WdfDeviceSetBusInformationForChildren(device, &pbi);
185 xpdd->removable = TRUE;
187 FUNCTION_EXIT();
188 return status;
189 }
191 NTSTATUS
192 XenHide_EvtDevicePrepareHardware (WDFDEVICE device, WDFCMRESLIST resources_raw, WDFCMRESLIST resources_translated)
193 {
194 UNREFERENCED_PARAMETER(device);
195 UNREFERENCED_PARAMETER(resources_raw);
196 UNREFERENCED_PARAMETER(resources_translated);
197 FUNCTION_ENTER();
198 FUNCTION_EXIT();
199 return STATUS_UNSUCCESSFUL;
200 }
202 static BOOLEAN
203 XenPci_IdSuffixMatches(PWDFDEVICE_INIT device_init, PWCHAR matching_id)
204 {
205 NTSTATUS status;
206 WDFMEMORY memory;
207 ULONG remaining;
208 size_t string_length;
209 PWCHAR ids;
210 PWCHAR ptr;
211 size_t ids_length;
212 ULONG properties[] = {DevicePropertyCompatibleIDs, DevicePropertyHardwareID};
213 int i;
215 // KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
216 for (i = 0; i < ARRAY_SIZE(properties); i++)
217 {
219 status = WdfFdoInitAllocAndQueryProperty(device_init, properties[i], NonPagedPool, WDF_NO_OBJECT_ATTRIBUTES, &memory);
220 if (!NT_SUCCESS(status))
221 continue;
222 ids = WdfMemoryGetBuffer(memory, &ids_length);
224 if (!NT_SUCCESS(status))
225 {
226 // KdPrint((__DRIVER_NAME " i = %d, status = %x, ids_length = %d\n", i, status, ids_length));
227 continue;
228 }
230 remaining = (ULONG)ids_length / 2;
231 for (ptr = ids; *ptr != 0; ptr += string_length + 1)
232 {
233 RtlStringCchLengthW(ptr, remaining, &string_length);
234 remaining -= (ULONG)string_length + 1;
235 if (string_length >= wcslen(matching_id))
236 {
237 ptr += string_length - wcslen(matching_id);
238 string_length = wcslen(matching_id);
239 }
240 // KdPrint((__DRIVER_NAME " Comparing '%S' and '%S'\n", ptr, matching_id));
241 if (wcscmp(ptr, matching_id) == 0)
242 {
243 //KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ " (Match)\n"));
244 WdfObjectDelete(memory);
245 return TRUE;
246 }
247 }
248 WdfObjectDelete(memory);
249 }
250 // KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ " (No match)\n"));
251 return FALSE;
252 }
254 ULONG qemu_filtered;
255 ULONG qemu_filtered_by_qemu;
257 static NTSTATUS
258 XenPci_EvtDeviceAdd_XenHide(WDFDRIVER driver, PWDFDEVICE_INIT device_init)
259 {
260 NTSTATUS status;
261 WDFMEMORY memory;
262 PWCHAR device_description;
263 WDF_PNPPOWER_EVENT_CALLBACKS pnp_power_callbacks;
264 WDF_OBJECT_ATTRIBUTES device_attributes;
265 BOOLEAN hide_required = FALSE;
266 WDFDEVICE device;
267 WDFKEY param_key;
268 DECLARE_CONST_UNICODE_STRING(hide_devices_name, L"hide_devices");
269 WDFCOLLECTION hide_devices;
270 ULONG i;
272 UNREFERENCED_PARAMETER(driver);
274 FUNCTION_ENTER();
276 WdfCollectionCreate(WDF_NO_OBJECT_ATTRIBUTES, &hide_devices);
277 status = WdfDriverOpenParametersRegistryKey(driver, KEY_QUERY_VALUE, WDF_NO_OBJECT_ATTRIBUTES, &param_key);
278 if (NT_SUCCESS(status))
279 {
280 status = WdfRegistryQueryMultiString(param_key, &hide_devices_name, WDF_NO_OBJECT_ATTRIBUTES, hide_devices);
281 if (!NT_SUCCESS(status))
282 {
283 KdPrint(("Error reading parameters/hide_devices value %08x\n", status));
284 }
285 WdfRegistryClose(param_key);
286 }
287 else
288 {
289 KdPrint(("Error opening parameters key %08x\n", status));
290 }
291 if (!WdfCollectionGetCount(hide_devices))
292 {
293 WDFSTRING wdf_string;
294 UNICODE_STRING unicode_string;
296 RtlInitUnicodeString(&unicode_string, L"VEN_8086&DEV_7010"); // Qemu IDE
297 WdfStringCreate(&unicode_string, WDF_NO_OBJECT_ATTRIBUTES, &wdf_string);
298 WdfCollectionAdd(hide_devices, wdf_string);
299 RtlInitUnicodeString(&unicode_string, L"VEN_1000&DEV_0012"); // Qemu SCSI
300 WdfStringCreate(&unicode_string, WDF_NO_OBJECT_ATTRIBUTES, &wdf_string);
301 WdfCollectionAdd(hide_devices, wdf_string);
302 RtlInitUnicodeString(&unicode_string, L"VEN_10EC&DEV_8139"); // Qemu Network
303 WdfStringCreate(&unicode_string, WDF_NO_OBJECT_ATTRIBUTES, &wdf_string);
304 WdfCollectionAdd(hide_devices, wdf_string);
305 }
306 status = WdfFdoInitAllocAndQueryProperty(device_init, DevicePropertyDeviceDescription, NonPagedPool, WDF_NO_OBJECT_ATTRIBUTES, &memory);
307 if (NT_SUCCESS(status))
308 {
309 device_description = WdfMemoryGetBuffer(memory, NULL);
310 }
311 else
312 {
313 device_description = L"<unknown device>";
314 }
316 for (i = 0; i < WdfCollectionGetCount(hide_devices); i++)
317 {
318 WDFSTRING wdf_string = WdfCollectionGetItem(hide_devices, i);
319 UNICODE_STRING unicode_string;
320 WdfStringGetUnicodeString(wdf_string, &unicode_string);
321 if (XenPci_IdSuffixMatches(device_init, unicode_string.Buffer))
322 {
323 hide_required = TRUE;
324 break;
325 }
326 }
327 #if 0
328 /* hide only specific devices */
329 if (XenPci_IdSuffixMatches(device_init, L"VEN_8086&DEV_7010")) // Qemu IDE
330 {
331 hide_required = TRUE;
332 }
333 else if (XenPci_IdSuffixMatches(device_init, L"VEN_1000&DEV_0012"))// Qemu SCSI
334 {
335 hide_required = TRUE;
336 }
337 else if (XenPci_IdSuffixMatches(device_init, L"VEN_10EC&DEV_8139")) // Qemu Network
338 {
339 hide_required = TRUE;
340 }
341 #endif
342 if (!hide_required)
343 {
344 WdfObjectDelete(memory);
345 KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ " (filter not required for %S)\n", device_description));
346 return STATUS_SUCCESS;
347 }
349 KdPrint((__DRIVER_NAME " Installing Filter for %S\n", device_description));
351 WdfFdoInitSetFilter(device_init);
352 WdfDeviceInitSetDeviceType(device_init, FILE_DEVICE_UNKNOWN);
353 WdfDeviceInitSetExclusive(device_init, FALSE);
355 WDF_PNPPOWER_EVENT_CALLBACKS_INIT(&pnp_power_callbacks);
356 pnp_power_callbacks.EvtDevicePrepareHardware = XenHide_EvtDevicePrepareHardware;
357 WdfDeviceInitSetPnpPowerEventCallbacks(device_init, &pnp_power_callbacks);
359 WDF_OBJECT_ATTRIBUTES_INIT(&device_attributes);
360 status = WdfDeviceCreate(&device_init, &device_attributes, &device);
361 if (!NT_SUCCESS(status))
362 {
363 KdPrint(("Error creating device %08x\n", status));
364 WdfObjectDelete(memory);
365 FUNCTION_EXIT();
366 return status;
367 }
369 WdfObjectDelete(memory);
370 FUNCTION_EXIT();
372 return status;
373 }
375 static NTSTATUS
376 XenPci_EvtDeviceAdd(WDFDRIVER driver, PWDFDEVICE_INIT device_init)
377 {
378 if (XenPci_IdSuffixMatches(device_init, L"VEN_5853&DEV_0001"))
379 {
380 KdPrint((__DRIVER_NAME " Xen PCI device found - must be fdo\n"));
381 return XenPci_EvtDeviceAdd_XenPci(driver, device_init);
382 }
383 else if (qemu_filtered && !qemu_filtered_by_qemu)
384 {
385 KdPrint((__DRIVER_NAME " Xen PCI device not found - must be filter\n"));
386 return XenPci_EvtDeviceAdd_XenHide(driver, device_init);
387 }
388 else
389 return STATUS_SUCCESS;
390 }
392 ULONG qemu_protocol_version;
393 ULONG tpr_patch_requested;
394 extern PULONG InitSafeBootMode;
396 VOID
397 XenPci_HideQemuDevices()
398 {
399 qemu_filtered_by_qemu = FALSE;
400 if (READ_PORT_USHORT(XEN_IOPORT_MAGIC) == 0x49d2)
401 {
402 qemu_protocol_version = READ_PORT_UCHAR(XEN_IOPORT_VERSION);
403 KdPrint((__DRIVER_NAME " Version = %d\n", qemu_protocol_version));
404 switch(qemu_protocol_version)
405 {
406 case 1:
407 WRITE_PORT_USHORT(XEN_IOPORT_PRODUCT, XEN_PV_PRODUCT_NUMBER);
408 WRITE_PORT_ULONG(XEN_IOPORT_BUILD, XEN_PV_PRODUCT_BUILD);
409 if (READ_PORT_USHORT(XEN_IOPORT_MAGIC) != 0x49d2)
410 {
411 KdPrint((__DRIVER_NAME " Blacklisted\n"));
412 break;
413 }
414 /* fall through */
415 case 0:
416 qemu_filtered_by_qemu = TRUE;
417 WRITE_PORT_USHORT(XEN_IOPORT_DEVICE_MASK, QEMU_UNPLUG_ALL_IDE_DISKS|QEMU_UNPLUG_ALL_NICS);
418 KdPrint((__DRIVER_NAME " Disabled qemu devices\n"));
419 break;
420 default:
421 KdPrint((__DRIVER_NAME " Unknown qemu version %d\n", qemu_protocol_version));
422 break;
423 }
424 }
425 }
427 /*
428 make sure the load order is System Reserved, Dummy Group, WdfLoadGroup, XenPCI, Boot Bus Extender
429 */
431 static VOID
432 XenPci_FixLoadOrder()
433 {
434 NTSTATUS status;
435 WDFCOLLECTION old_load_order, new_load_order;
436 DECLARE_CONST_UNICODE_STRING(sgo_name, L"\\Registry\\Machine\\SYSTEM\\CurrentControlSet\\Control\\ServiceGroupOrder");
437 DECLARE_CONST_UNICODE_STRING(list_name, L"List");
438 WDFKEY sgo_key;
439 ULONG i;
440 LONG dummy_group_index = -1;
441 LONG boot_bus_extender_index = -1;
442 LONG xenpci_group_index = -1;
443 LONG wdf_load_group_index = -1;
444 DECLARE_CONST_UNICODE_STRING(dummy_group_name, L"Dummy Group");
445 DECLARE_CONST_UNICODE_STRING(wdf_load_group_name, L"WdfLoadGroup");
446 DECLARE_CONST_UNICODE_STRING(xenpci_group_name, L"XenPCI Group");
447 DECLARE_CONST_UNICODE_STRING(boot_bus_extender_name, L"Boot Bus Extender");
449 FUNCTION_ENTER();
451 status = WdfRegistryOpenKey(NULL, &sgo_name, KEY_QUERY_VALUE, WDF_NO_OBJECT_ATTRIBUTES, &sgo_key);
452 if (!NT_SUCCESS(status))
453 {
454 KdPrint((__DRIVER_NAME " Error opening ServiceGroupOrder key %08x\n", status));
455 return;
456 }
457 WdfCollectionCreate(WDF_NO_OBJECT_ATTRIBUTES, &old_load_order);
458 WdfCollectionCreate(WDF_NO_OBJECT_ATTRIBUTES, &new_load_order);
459 status = WdfRegistryQueryMultiString(sgo_key, &list_name, WDF_NO_OBJECT_ATTRIBUTES, old_load_order);
460 if (!NT_SUCCESS(status))
461 {
462 KdPrint((__DRIVER_NAME " Error reading ServiceGroupOrder\\List value %08x\n", status));
463 WdfObjectDelete(new_load_order);
464 WdfObjectDelete(old_load_order);
465 return;
466 }
467 KdPrint((__DRIVER_NAME " Current Order:\n"));
468 for (i = 0; i < WdfCollectionGetCount(old_load_order); i++)
469 {
470 WDFOBJECT ws = WdfCollectionGetItem(old_load_order, i);
471 UNICODE_STRING val;
472 WdfStringGetUnicodeString(ws, &val);
473 if (!RtlCompareUnicodeString(&val, &dummy_group_name, TRUE))
474 dummy_group_index = (ULONG)i;
475 if (!RtlCompareUnicodeString(&val, &wdf_load_group_name, TRUE))
476 wdf_load_group_index = (ULONG)i;
477 if (!RtlCompareUnicodeString(&val, &xenpci_group_name, TRUE))
478 xenpci_group_index = (ULONG)i;
479 if (!RtlCompareUnicodeString(&val, &boot_bus_extender_name, TRUE))
480 boot_bus_extender_index = (ULONG)i;
481 KdPrint((__DRIVER_NAME " %wZ\n", &val));
482 }
483 KdPrint((__DRIVER_NAME " dummy_group_index = %d\n", dummy_group_index));
484 KdPrint((__DRIVER_NAME " wdf_load_group_index = %d\n", wdf_load_group_index));
485 KdPrint((__DRIVER_NAME " xenpci_group_index = %d\n", xenpci_group_index));
486 KdPrint((__DRIVER_NAME " boot_bus_extender_index = %d\n", boot_bus_extender_index));
487 if (boot_bus_extender_index == -1)
488 {
489 WdfObjectDelete(new_load_order);
490 WdfObjectDelete(old_load_order);
491 WdfRegistryClose(sgo_key);
492 return; /* something is very wrong */
493 }
494 if (dummy_group_index == 1 && (wdf_load_group_index == -1 ||
495 (dummy_group_index < wdf_load_group_index
496 && wdf_load_group_index < xenpci_group_index
497 && xenpci_group_index < boot_bus_extender_index)))
498 {
499 return; /* our work here is done */
500 }
501 for (i = 0; i < WdfCollectionGetCount(old_load_order); i++)
502 {
503 WDFOBJECT ws;
504 if (i == 1)
505 {
506 WDFSTRING tmp_wdf_string;
507 WdfStringCreate(&dummy_group_name, WDF_NO_OBJECT_ATTRIBUTES, &tmp_wdf_string);
508 WdfCollectionAdd(new_load_order, tmp_wdf_string);
509 WdfObjectDelete(tmp_wdf_string);
510 }
511 if (i == 1 && wdf_load_group_index != -1)
512 {
513 WDFSTRING tmp_wdf_string;
514 WdfStringCreate(&wdf_load_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(&xenpci_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 == (ULONG)dummy_group_index || i == (ULONG)wdf_load_group_index || i == (ULONG)xenpci_group_index)
526 continue;
527 ws = WdfCollectionGetItem(old_load_order, i);
528 WdfCollectionAdd(new_load_order, ws);
529 }
530 WdfRegistryAssignMultiString(sgo_key, &list_name, new_load_order);
531 KdPrint((__DRIVER_NAME " New Order:\n"));
532 for (i = 0; i < WdfCollectionGetCount(new_load_order); i++)
533 {
534 WDFOBJECT ws = WdfCollectionGetItem(new_load_order, i);
535 UNICODE_STRING val;
536 WdfStringGetUnicodeString(ws, &val);
537 KdPrint((__DRIVER_NAME " %wZ\n", &val));
538 }
539 WdfObjectDelete(new_load_order);
540 WdfObjectDelete(old_load_order);
541 WdfRegistryClose(sgo_key);
543 FUNCTION_EXIT();
545 return;
546 }
548 NTSTATUS
549 DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath)
550 {
551 NTSTATUS status = STATUS_SUCCESS;
552 WDF_DRIVER_CONFIG config;
553 WDFDRIVER driver;
554 PCONFIGURATION_INFORMATION conf_info;
555 WCHAR *SystemStartOptions;
556 UNICODE_STRING RegKeyName;
557 UNICODE_STRING RegValueName;
558 HANDLE RegHandle;
559 OBJECT_ATTRIBUTES RegObjectAttributes;
560 char Buf[300];// Sometimes bigger then 200 if system reboot from crash
561 ULONG BufLen = 300;
562 PKEY_VALUE_PARTIAL_INFORMATION KeyPartialValue;
563 #if 0
564 WDF_TIMER_CONFIG timer_config;
565 OBJECT_ATTRIBUTES timer_attributes;
566 #endif
568 UNREFERENCED_PARAMETER(RegistryPath);
570 FUNCTION_ENTER();
572 XenPci_FixLoadOrder();
574 RtlInitUnicodeString(&RegKeyName, L"\\Registry\\Machine\\System\\CurrentControlSet\\Control");
575 InitializeObjectAttributes(&RegObjectAttributes, &RegKeyName, OBJ_CASE_INSENSITIVE, NULL, NULL);
576 status = ZwOpenKey(&RegHandle, KEY_READ, &RegObjectAttributes);
577 if(!NT_SUCCESS(status))
578 {
579 KdPrint((__DRIVER_NAME " ZwOpenKey returned %08x\n", status));
580 }
582 RtlInitUnicodeString(&RegValueName, L"SystemStartOptions");
583 status = ZwQueryValueKey(RegHandle, &RegValueName, KeyValuePartialInformation, Buf, BufLen, &BufLen);
584 if(!NT_SUCCESS(status))
585 {
586 KdPrint((__DRIVER_NAME " ZwQueryKeyValue returned %08x\n", status));
587 }
588 else
589 ZwClose(RegHandle);
590 KeyPartialValue = (PKEY_VALUE_PARTIAL_INFORMATION)Buf;
591 SystemStartOptions = (WCHAR *)KeyPartialValue->Data;
593 KdPrint((__DRIVER_NAME " SystemStartOptions = %S\n", SystemStartOptions));
595 if (wcsstr(SystemStartOptions, L"PATCHTPR"))
596 {
597 KdPrint((__DRIVER_NAME " PATCHTPR found\n"));
598 tpr_patch_requested = TRUE;
599 }
601 if (wcsstr(SystemStartOptions, L"NOGPLPV"))
602 KdPrint((__DRIVER_NAME " NOGPLPV found\n"));
603 conf_info = IoGetConfigurationInformation();
604 if ((conf_info == NULL || conf_info->DiskCount == 0)
605 && !wcsstr(SystemStartOptions, L"NOGPLPV")
606 && !*InitSafeBootMode)
607 {
608 qemu_filtered = TRUE;
609 /* see if the qemu method of disabling the PCI devices exists */
610 XenPci_HideQemuDevices();
611 }
613 if (qemu_filtered)
614 KdPrint((__DRIVER_NAME " PV Devices Active\n"));
615 else
616 KdPrint((__DRIVER_NAME " PV Devices Inactive\n"));
618 WDF_DRIVER_CONFIG_INIT(&config, XenPci_EvtDeviceAdd);
619 status = WdfDriverCreate(DriverObject, RegistryPath, WDF_NO_OBJECT_ATTRIBUTES, &config, &driver);
621 if (!NT_SUCCESS(status)) {
622 KdPrint((__DRIVER_NAME " WdfDriverCreate failed with status 0x%x\n", status));
623 }
625 FUNCTION_EXIT();
627 return status;
628 }