win-pvdrivers

annotate xenpci/xenpci.c @ 747:f43c89df09b2

Big changes to the way the device hiding works. Should fix the way Vista and above need a reboot into safe mode after install.
author James Harper <james.harper@bendigoit.com.au>
date Sun Jan 10 10:07:32 2010 +1100 (2010-01-10)
parents 7f984f45dfe4
children 65a687a0933e
rev   line source
james@0 1 /*
james@0 2 PV Drivers for Windows Xen HVM Domains
james@0 3 Copyright (C) 2007 James Harper
james@0 4
james@0 5 This program is free software; you can redistribute it and/or
james@0 6 modify it under the terms of the GNU General Public License
james@0 7 as published by the Free Software Foundation; either version 2
james@0 8 of the License, or (at your option) any later version.
james@0 9
james@0 10 This program is distributed in the hope that it will be useful,
james@0 11 but WITHOUT ANY WARRANTY; without even the implied warranty of
james@0 12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
james@0 13 GNU General Public License for more details.
james@0 14
james@0 15 You should have received a copy of the GNU General Public License
james@0 16 along with this program; if not, write to the Free Software
james@0 17 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
james@0 18 */
james@0 19
andy@346 20 #define INITGUID
james@0 21 #include "xenpci.h"
james@638 22 #include <aux_klib.h>
james@0 23 #include <stdlib.h>
james@0 24
james@116 25 #define SYSRQ_PATH "control/sysrq"
james@0 26 #define SHUTDOWN_PATH "control/shutdown"
james@4 27 #define BALLOON_PATH "memory/target"
james@0 28
andy@88 29 #pragma warning(disable : 4200) // zero-sized array
andy@88 30
james@716 31 /* Not really necessary but keeps PREfast happy */
james@716 32 DRIVER_INITIALIZE DriverEntry;
james@716 33 static EVT_WDF_DRIVER_DEVICE_ADD XenPci_EvtDeviceAdd;
james@716 34 static EVT_WDF_DEVICE_USAGE_NOTIFICATION XenPci_EvtDeviceUsageNotification;
james@716 35 static EVT_WDF_DEVICE_PREPARE_HARDWARE XenHide_EvtDevicePrepareHardware;
james@716 36
james@538 37 static VOID
james@538 38 XenPci_EvtDeviceUsageNotification(WDFDEVICE device, WDF_SPECIAL_FILE_TYPE notification_type, BOOLEAN is_in_notification_path)
james@538 39 {
james@538 40 FUNCTION_ENTER();
james@538 41
james@538 42 UNREFERENCED_PARAMETER(device);
james@700 43 UNREFERENCED_PARAMETER(is_in_notification_path);
james@538 44
james@538 45 switch (notification_type)
james@538 46 {
james@538 47 case WdfSpecialFilePaging:
james@538 48 KdPrint((__DRIVER_NAME " notification_type = Paging, flag = %d\n", is_in_notification_path));
james@538 49 break;
james@538 50 case WdfSpecialFileHibernation:
james@538 51 KdPrint((__DRIVER_NAME " notification_type = Hibernation, flag = %d\n", is_in_notification_path));
james@538 52 break;
james@538 53 case WdfSpecialFileDump:
james@538 54 KdPrint((__DRIVER_NAME " notification_type = Dump, flag = %d\n", is_in_notification_path));
james@538 55 break;
james@538 56 default:
james@538 57 KdPrint((__DRIVER_NAME " notification_type = %d, flag = %d\n", notification_type, is_in_notification_path));
james@538 58 break;
james@538 59 }
james@538 60
james@538 61 FUNCTION_EXIT();
james@538 62 }
james@538 63
james@536 64 static NTSTATUS
james@561 65 XenPci_EvtDeviceAdd_XenPci(WDFDRIVER driver, PWDFDEVICE_INIT device_init)
james@0 66 {
james@258 67 NTSTATUS status;
james@536 68 // PDEVICE_OBJECT fdo = NULL;
james@258 69 // PNP_BUS_INFORMATION busInfo;
james@258 70 // DECLARE_CONST_UNICODE_STRING(DeviceName, L"\\Device\\XenShutdown");
james@258 71 // DECLARE_CONST_UNICODE_STRING(SymbolicName, L"\\DosDevices\\XenShutdown");
james@536 72 WDF_CHILD_LIST_CONFIG child_list_config;
james@536 73 WDFDEVICE device;
andy@16 74 PXENPCI_DEVICE_DATA xpdd;
james@504 75 UNICODE_STRING reference;
james@536 76 WDF_OBJECT_ATTRIBUTES device_attributes;
james@536 77 PNP_BUS_INFORMATION pbi;
james@536 78 WDF_PNPPOWER_EVENT_CALLBACKS pnp_power_callbacks;
james@536 79 WDF_INTERRUPT_CONFIG interrupt_config;
james@536 80 WDF_OBJECT_ATTRIBUTES file_attributes;
james@536 81 WDF_FILEOBJECT_CONFIG file_config;
james@536 82 WDF_IO_QUEUE_CONFIG queue_config;
james@624 83 WDFCOLLECTION veto_devices;
james@538 84 WDFKEY param_key;
james@538 85 DECLARE_CONST_UNICODE_STRING(veto_devices_name, L"veto_devices");
james@538 86 WDF_DEVICE_POWER_CAPABILITIES power_capabilities;
james@624 87 int i;
james@536 88
james@536 89 UNREFERENCED_PARAMETER(driver);
james@0 90
andy@398 91 FUNCTION_ENTER();
james@561 92
james@536 93 WDF_PNPPOWER_EVENT_CALLBACKS_INIT(&pnp_power_callbacks);
james@536 94 pnp_power_callbacks.EvtDeviceD0Entry = XenPci_EvtDeviceD0Entry;
james@536 95 pnp_power_callbacks.EvtDeviceD0EntryPostInterruptsEnabled = XenPci_EvtDeviceD0EntryPostInterruptsEnabled;
james@536 96 pnp_power_callbacks.EvtDeviceD0Exit = XenPci_EvtDeviceD0Exit;
james@536 97 pnp_power_callbacks.EvtDeviceD0ExitPreInterruptsDisabled = XenPci_EvtDeviceD0ExitPreInterruptsDisabled;
james@536 98 pnp_power_callbacks.EvtDevicePrepareHardware = XenPci_EvtDevicePrepareHardware;
james@536 99 pnp_power_callbacks.EvtDeviceReleaseHardware = XenPci_EvtDeviceReleaseHardware;
james@537 100 pnp_power_callbacks.EvtDeviceQueryRemove = XenPci_EvtDeviceQueryRemove;
james@538 101 pnp_power_callbacks.EvtDeviceUsageNotification = XenPci_EvtDeviceUsageNotification;
james@538 102
james@536 103 WdfDeviceInitSetPnpPowerEventCallbacks(device_init, &pnp_power_callbacks);
james@536 104
james@536 105 WdfDeviceInitSetDeviceType(device_init, FILE_DEVICE_BUS_EXTENDER);
james@536 106 WdfDeviceInitSetExclusive(device_init, FALSE);
james@536 107
james@536 108 WDF_CHILD_LIST_CONFIG_INIT(&child_list_config, sizeof(XENPCI_PDO_IDENTIFICATION_DESCRIPTION), XenPci_EvtChildListCreateDevice);
james@536 109 child_list_config.EvtChildListScanForChildren = XenPci_EvtChildListScanForChildren;
james@536 110 WdfFdoInitSetDefaultChildListConfig(device_init, &child_list_config, WDF_NO_OBJECT_ATTRIBUTES);
james@536 111
james@536 112 WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&file_attributes, XENPCI_DEVICE_INTERFACE_DATA);
james@536 113 WDF_FILEOBJECT_CONFIG_INIT(&file_config, XenPci_EvtDeviceFileCreate, XenPci_EvtFileClose, XenPci_EvtFileCleanup);
james@536 114 WdfDeviceInitSetFileObjectConfig(device_init, &file_config, &file_attributes);
james@536 115
james@536 116 WdfDeviceInitSetIoType(device_init, WdfDeviceIoBuffered);
james@538 117
james@538 118 WdfDeviceInitSetPowerNotPageable(device_init);
james@536 119
james@536 120 WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&device_attributes, XENPCI_DEVICE_DATA);
james@536 121 status = WdfDeviceCreate(&device_init, &device_attributes, &device);
james@538 122 if (!NT_SUCCESS(status))
james@538 123 {
james@538 124 KdPrint(("Error creating device %08x\n", status));
james@538 125 return status;
james@536 126 }
james@536 127
james@536 128 xpdd = GetXpdd(device);
james@622 129 xpdd->wdf_device = device;
james@599 130 xpdd->child_list = WdfFdoGetDefaultChildList(device);
james@536 131
james@624 132 WdfCollectionCreate(WDF_NO_OBJECT_ATTRIBUTES, &veto_devices);
james@538 133 status = WdfDriverOpenParametersRegistryKey(driver, KEY_QUERY_VALUE, WDF_NO_OBJECT_ATTRIBUTES, &param_key);
james@538 134 if (NT_SUCCESS(status))
james@538 135 {
james@624 136 status = WdfRegistryQueryMultiString(param_key, &veto_devices_name, WDF_NO_OBJECT_ATTRIBUTES, veto_devices);
james@538 137 if (!NT_SUCCESS(status))
james@538 138 {
james@538 139 KdPrint(("Error reading parameters/veto_devices value %08x\n", status));
james@538 140 }
james@538 141 WdfRegistryClose(param_key);
james@538 142 }
james@538 143 else
james@538 144 {
james@538 145 KdPrint(("Error opening parameters key %08x\n", status));
james@538 146 }
james@624 147
james@624 148 InitializeListHead(&xpdd->veto_list);
james@637 149 for (i = 0; i < (int)WdfCollectionGetCount(veto_devices); i++)
james@624 150 {
james@624 151 WDFOBJECT ws;
james@624 152 UNICODE_STRING val;
james@624 153 ANSI_STRING s;
james@624 154 PVOID entry;
james@624 155 ws = WdfCollectionGetItem(veto_devices, i);
james@624 156 WdfStringGetUnicodeString(ws, &val);
james@624 157 RtlUnicodeStringToAnsiString(&s, &val, TRUE);
james@624 158 entry = ExAllocatePoolWithTag(NonPagedPool, sizeof(LIST_ENTRY) + s.Length + 1, XENPCI_POOL_TAG);
james@624 159 memcpy((PUCHAR)entry + sizeof(LIST_ENTRY), s.Buffer, s.Length + 1);
james@624 160 RtlFreeAnsiString(&s);
james@624 161 InsertTailList(&xpdd->veto_list, (PLIST_ENTRY)entry);
james@624 162 }
james@538 163 WDF_DEVICE_POWER_CAPABILITIES_INIT(&power_capabilities);
james@538 164 power_capabilities.DeviceD1 = WdfTrue;
james@538 165 power_capabilities.WakeFromD1 = WdfTrue;
james@538 166 power_capabilities.DeviceWake = PowerDeviceD1;
james@538 167 power_capabilities.DeviceState[PowerSystemWorking] = PowerDeviceD1;
james@538 168 power_capabilities.DeviceState[PowerSystemSleeping1] = PowerDeviceD1;
james@538 169 power_capabilities.DeviceState[PowerSystemSleeping2] = PowerDeviceD2;
james@538 170 power_capabilities.DeviceState[PowerSystemSleeping3] = PowerDeviceD2;
james@538 171 power_capabilities.DeviceState[PowerSystemHibernate] = PowerDeviceD3;
james@538 172 power_capabilities.DeviceState[PowerSystemShutdown] = PowerDeviceD3;
james@538 173 WdfDeviceSetPowerCapabilities(device, &power_capabilities);
james@538 174
james@536 175 WdfDeviceSetSpecialFileSupport(device, WdfSpecialFilePaging, TRUE);
james@536 176 WdfDeviceSetSpecialFileSupport(device, WdfSpecialFileHibernation, TRUE);
james@536 177 WdfDeviceSetSpecialFileSupport(device, WdfSpecialFileDump, TRUE);
james@536 178
james@536 179 WDF_IO_QUEUE_CONFIG_INIT_DEFAULT_QUEUE(&queue_config, WdfIoQueueDispatchParallel);
james@671 180 queue_config.EvtIoDefault = XenPci_EvtIoDefault;
james@536 181 status = WdfIoQueueCreate(device, &queue_config, WDF_NO_OBJECT_ATTRIBUTES, &xpdd->io_queue);
james@536 182 if (!NT_SUCCESS(status)) {
james@536 183 KdPrint(("Error creating queue 0x%x\n", status));
james@536 184 return status;
james@536 185 }
james@536 186
james@536 187 WDF_INTERRUPT_CONFIG_INIT(&interrupt_config, EvtChn_EvtInterruptIsr, NULL);
james@536 188 interrupt_config.EvtInterruptEnable = EvtChn_EvtInterruptEnable;
james@536 189 interrupt_config.EvtInterruptDisable = EvtChn_EvtInterruptDisable;
james@536 190
james@536 191 status = WdfInterruptCreate(device, &interrupt_config, WDF_NO_OBJECT_ATTRIBUTES, &xpdd->interrupt);
james@536 192 if (!NT_SUCCESS(status))
james@536 193 {
james@536 194 KdPrint(("Error creating interrupt 0x%x\n", status));
james@536 195 return status;
james@536 196 }
james@536 197
james@536 198 RtlInitUnicodeString(&reference, L"xenbus");
james@536 199 status = WdfDeviceCreateDeviceInterface(device, &GUID_DEVINTERFACE_XENBUS, &reference);
james@536 200 if (!NT_SUCCESS(status)) {
james@536 201 KdPrint(("Error registering device interface 0x%x\n", status));
james@536 202 return status;
james@536 203 }
james@536 204
james@671 205 RtlInitUnicodeString(&reference, L"evtchn");
james@671 206 status = WdfDeviceCreateDeviceInterface(device, &GUID_DEVINTERFACE_EVTCHN, &reference);
james@671 207 if (!NT_SUCCESS(status)) {
james@671 208 KdPrint(("Error registering device interface 0x%x\n", status));
james@671 209 return status;
james@671 210 }
james@671 211
james@671 212 RtlInitUnicodeString(&reference, L"gntdev");
james@671 213 status = WdfDeviceCreateDeviceInterface(device, &GUID_DEVINTERFACE_GNTDEV, &reference);
james@671 214 if (!NT_SUCCESS(status)) {
james@671 215 KdPrint(("Error registering device interface 0x%x\n", status));
james@671 216 return status;
james@671 217 }
james@671 218
james@536 219 pbi.BusTypeGuid = GUID_BUS_TYPE_XEN;
james@536 220 pbi.LegacyBusType = PNPBus;
james@536 221 pbi.BusNumber = 0;
james@536 222 WdfDeviceSetBusInformationForChildren(device, &pbi);
james@536 223
james@537 224 xpdd->removable = TRUE;
james@536 225
james@536 226 FUNCTION_EXIT();
james@536 227 return status;
james@0 228 }
james@0 229
james@561 230 NTSTATUS
james@747 231 XenHide_EvtDevicePrepareHardware(WDFDEVICE device, WDFCMRESLIST resources_raw, WDFCMRESLIST resources_translated)
james@561 232 {
james@561 233 UNREFERENCED_PARAMETER(device);
james@561 234 UNREFERENCED_PARAMETER(resources_raw);
james@561 235 UNREFERENCED_PARAMETER(resources_translated);
james@561 236 FUNCTION_ENTER();
james@561 237 FUNCTION_EXIT();
james@561 238 return STATUS_UNSUCCESSFUL;
james@561 239 }
james@561 240
james@561 241 static BOOLEAN
james@561 242 XenPci_IdSuffixMatches(PWDFDEVICE_INIT device_init, PWCHAR matching_id)
james@561 243 {
james@561 244 NTSTATUS status;
james@561 245 WDFMEMORY memory;
james@561 246 ULONG remaining;
james@561 247 size_t string_length;
james@561 248 PWCHAR ids;
james@561 249 PWCHAR ptr;
james@561 250 size_t ids_length;
james@561 251 ULONG properties[] = {DevicePropertyCompatibleIDs, DevicePropertyHardwareID};
james@561 252 int i;
james@561 253
james@561 254 // KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
james@561 255 for (i = 0; i < ARRAY_SIZE(properties); i++)
james@561 256 {
james@561 257
james@561 258 status = WdfFdoInitAllocAndQueryProperty(device_init, properties[i], NonPagedPool, WDF_NO_OBJECT_ATTRIBUTES, &memory);
james@561 259 if (!NT_SUCCESS(status))
james@561 260 continue;
james@561 261 ids = WdfMemoryGetBuffer(memory, &ids_length);
james@561 262
james@561 263 if (!NT_SUCCESS(status))
james@561 264 {
james@561 265 // KdPrint((__DRIVER_NAME " i = %d, status = %x, ids_length = %d\n", i, status, ids_length));
james@561 266 continue;
james@561 267 }
james@561 268
james@561 269 remaining = (ULONG)ids_length / 2;
james@561 270 for (ptr = ids; *ptr != 0; ptr += string_length + 1)
james@561 271 {
james@561 272 RtlStringCchLengthW(ptr, remaining, &string_length);
james@561 273 remaining -= (ULONG)string_length + 1;
james@561 274 if (string_length >= wcslen(matching_id))
james@561 275 {
james@561 276 ptr += string_length - wcslen(matching_id);
james@561 277 string_length = wcslen(matching_id);
james@561 278 }
james@561 279 // KdPrint((__DRIVER_NAME " Comparing '%S' and '%S'\n", ptr, matching_id));
james@561 280 if (wcscmp(ptr, matching_id) == 0)
james@561 281 {
james@561 282 //KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ " (Match)\n"));
james@561 283 WdfObjectDelete(memory);
james@561 284 return TRUE;
james@561 285 }
james@561 286 }
james@561 287 WdfObjectDelete(memory);
james@561 288 }
james@561 289 // KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ " (No match)\n"));
james@561 290 return FALSE;
james@561 291 }
james@561 292
james@747 293 WDFCOLLECTION qemu_hide_devices;
james@747 294 USHORT qemu_hide_flags_value;
james@561 295
james@561 296 static NTSTATUS
james@561 297 XenPci_EvtDeviceAdd_XenHide(WDFDRIVER driver, PWDFDEVICE_INIT device_init)
james@561 298 {
james@561 299 NTSTATUS status;
james@561 300 WDFMEMORY memory;
james@561 301 PWCHAR device_description;
james@561 302 WDF_PNPPOWER_EVENT_CALLBACKS pnp_power_callbacks;
james@561 303 WDF_OBJECT_ATTRIBUTES device_attributes;
james@561 304 BOOLEAN hide_required = FALSE;
james@561 305 WDFDEVICE device;
james@561 306 ULONG i;
james@747 307
james@561 308 UNREFERENCED_PARAMETER(driver);
james@561 309
james@561 310 FUNCTION_ENTER();
james@561 311
james@561 312 status = WdfFdoInitAllocAndQueryProperty(device_init, DevicePropertyDeviceDescription, NonPagedPool, WDF_NO_OBJECT_ATTRIBUTES, &memory);
james@561 313 if (NT_SUCCESS(status))
james@561 314 {
james@561 315 device_description = WdfMemoryGetBuffer(memory, NULL);
james@561 316 }
james@561 317 else
james@561 318 {
james@561 319 device_description = L"<unknown device>";
james@561 320 }
james@561 321
james@747 322 for (i = 0; i < WdfCollectionGetCount(qemu_hide_devices); i++)
james@561 323 {
james@747 324 WDFSTRING wdf_string = WdfCollectionGetItem(qemu_hide_devices, i);
james@561 325 UNICODE_STRING unicode_string;
james@561 326 WdfStringGetUnicodeString(wdf_string, &unicode_string);
james@561 327 if (XenPci_IdSuffixMatches(device_init, unicode_string.Buffer))
james@561 328 {
james@561 329 hide_required = TRUE;
james@561 330 break;
james@561 331 }
james@561 332 }
james@561 333 if (!hide_required)
james@561 334 {
james@561 335 WdfObjectDelete(memory);
james@561 336 KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ " (filter not required for %S)\n", device_description));
james@561 337 return STATUS_SUCCESS;
james@561 338 }
james@561 339
james@561 340 KdPrint((__DRIVER_NAME " Installing Filter for %S\n", device_description));
james@561 341
james@561 342 WdfFdoInitSetFilter(device_init);
james@561 343 WdfDeviceInitSetDeviceType(device_init, FILE_DEVICE_UNKNOWN);
james@561 344 WdfDeviceInitSetExclusive(device_init, FALSE);
james@561 345
james@561 346 WDF_PNPPOWER_EVENT_CALLBACKS_INIT(&pnp_power_callbacks);
james@561 347 pnp_power_callbacks.EvtDevicePrepareHardware = XenHide_EvtDevicePrepareHardware;
james@561 348 WdfDeviceInitSetPnpPowerEventCallbacks(device_init, &pnp_power_callbacks);
james@561 349
james@561 350 WDF_OBJECT_ATTRIBUTES_INIT(&device_attributes);
james@561 351 status = WdfDeviceCreate(&device_init, &device_attributes, &device);
james@561 352 if (!NT_SUCCESS(status))
james@561 353 {
james@561 354 KdPrint(("Error creating device %08x\n", status));
james@561 355 WdfObjectDelete(memory);
james@561 356 FUNCTION_EXIT();
james@561 357 return status;
james@561 358 }
james@561 359
james@561 360 WdfObjectDelete(memory);
james@561 361 FUNCTION_EXIT();
james@561 362
james@561 363 return status;
james@561 364 }
james@561 365
james@561 366 static NTSTATUS
james@561 367 XenPci_EvtDeviceAdd(WDFDRIVER driver, PWDFDEVICE_INIT device_init)
james@561 368 {
james@561 369 if (XenPci_IdSuffixMatches(device_init, L"VEN_5853&DEV_0001"))
james@561 370 {
james@561 371 KdPrint((__DRIVER_NAME " Xen PCI device found - must be fdo\n"));
james@561 372 return XenPci_EvtDeviceAdd_XenPci(driver, device_init);
james@561 373 }
james@747 374 else if (WdfCollectionGetCount(qemu_hide_devices) > 0)
james@561 375 {
james@561 376 KdPrint((__DRIVER_NAME " Xen PCI device not found - must be filter\n"));
james@561 377 return XenPci_EvtDeviceAdd_XenHide(driver, device_init);
james@561 378 }
james@561 379 else
james@561 380 return STATUS_SUCCESS;
james@561 381 }
james@561 382
james@497 383 ULONG qemu_protocol_version;
james@529 384 ULONG tpr_patch_requested;
james@495 385 extern PULONG InitSafeBootMode;
james@486 386
james@536 387 VOID
james@536 388 XenPci_HideQemuDevices()
james@533 389 {
james@747 390 WRITE_PORT_USHORT(XEN_IOPORT_DEVICE_MASK, (USHORT)qemu_hide_flags_value); //QEMU_UNPLUG_ALL_IDE_DISKS|QEMU_UNPLUG_ALL_NICS);
james@747 391 KdPrint((__DRIVER_NAME " Disabled qemu devices\n"));\
james@747 392 }
james@747 393
james@747 394 static BOOLEAN
james@747 395 XenPci_CheckHideQemuDevices()
james@747 396 {
james@536 397 if (READ_PORT_USHORT(XEN_IOPORT_MAGIC) == 0x49d2)
james@533 398 {
james@536 399 qemu_protocol_version = READ_PORT_UCHAR(XEN_IOPORT_VERSION);
james@536 400 KdPrint((__DRIVER_NAME " Version = %d\n", qemu_protocol_version));
james@536 401 switch(qemu_protocol_version)
james@533 402 {
james@536 403 case 1:
james@536 404 WRITE_PORT_USHORT(XEN_IOPORT_PRODUCT, XEN_PV_PRODUCT_NUMBER);
james@536 405 WRITE_PORT_ULONG(XEN_IOPORT_BUILD, XEN_PV_PRODUCT_BUILD);
james@536 406 if (READ_PORT_USHORT(XEN_IOPORT_MAGIC) != 0x49d2)
james@536 407 {
james@536 408 KdPrint((__DRIVER_NAME " Blacklisted\n"));
james@536 409 break;
james@536 410 }
james@536 411 /* fall through */
james@536 412 case 0:
james@747 413 return TRUE;
james@536 414 default:
james@536 415 KdPrint((__DRIVER_NAME " Unknown qemu version %d\n", qemu_protocol_version));
james@536 416 break;
james@533 417 }
james@533 418 }
james@747 419 return FALSE;
james@533 420 }
james@533 421
james@539 422 /*
james@561 423 make sure the load order is System Reserved, Dummy Group, WdfLoadGroup, XenPCI, Boot Bus Extender
james@539 424 */
james@539 425
james@539 426 static VOID
james@539 427 XenPci_FixLoadOrder()
james@539 428 {
james@539 429 NTSTATUS status;
james@539 430 WDFCOLLECTION old_load_order, new_load_order;
james@539 431 DECLARE_CONST_UNICODE_STRING(sgo_name, L"\\Registry\\Machine\\SYSTEM\\CurrentControlSet\\Control\\ServiceGroupOrder");
james@539 432 DECLARE_CONST_UNICODE_STRING(list_name, L"List");
james@539 433 WDFKEY sgo_key;
james@539 434 ULONG i;
james@539 435 LONG dummy_group_index = -1;
james@539 436 LONG boot_bus_extender_index = -1;
james@561 437 LONG xenpci_group_index = -1;
james@539 438 LONG wdf_load_group_index = -1;
james@539 439 DECLARE_CONST_UNICODE_STRING(dummy_group_name, L"Dummy Group");
james@539 440 DECLARE_CONST_UNICODE_STRING(wdf_load_group_name, L"WdfLoadGroup");
james@561 441 DECLARE_CONST_UNICODE_STRING(xenpci_group_name, L"XenPCI Group");
james@539 442 DECLARE_CONST_UNICODE_STRING(boot_bus_extender_name, L"Boot Bus Extender");
james@539 443
james@539 444 FUNCTION_ENTER();
james@539 445
james@539 446 status = WdfRegistryOpenKey(NULL, &sgo_name, KEY_QUERY_VALUE, WDF_NO_OBJECT_ATTRIBUTES, &sgo_key);
james@539 447 if (!NT_SUCCESS(status))
james@539 448 {
james@539 449 KdPrint((__DRIVER_NAME " Error opening ServiceGroupOrder key %08x\n", status));
james@539 450 return;
james@539 451 }
james@539 452 WdfCollectionCreate(WDF_NO_OBJECT_ATTRIBUTES, &old_load_order);
james@539 453 WdfCollectionCreate(WDF_NO_OBJECT_ATTRIBUTES, &new_load_order);
james@539 454 status = WdfRegistryQueryMultiString(sgo_key, &list_name, WDF_NO_OBJECT_ATTRIBUTES, old_load_order);
james@539 455 if (!NT_SUCCESS(status))
james@539 456 {
james@539 457 KdPrint((__DRIVER_NAME " Error reading ServiceGroupOrder\\List value %08x\n", status));
james@539 458 WdfObjectDelete(new_load_order);
james@539 459 WdfObjectDelete(old_load_order);
james@539 460 return;
james@539 461 }
james@539 462 KdPrint((__DRIVER_NAME " Current Order:\n"));
james@539 463 for (i = 0; i < WdfCollectionGetCount(old_load_order); i++)
james@539 464 {
james@539 465 WDFOBJECT ws = WdfCollectionGetItem(old_load_order, i);
james@539 466 UNICODE_STRING val;
james@539 467 WdfStringGetUnicodeString(ws, &val);
james@539 468 if (!RtlCompareUnicodeString(&val, &dummy_group_name, TRUE))
james@539 469 dummy_group_index = (ULONG)i;
james@539 470 if (!RtlCompareUnicodeString(&val, &wdf_load_group_name, TRUE))
james@539 471 wdf_load_group_index = (ULONG)i;
james@561 472 if (!RtlCompareUnicodeString(&val, &xenpci_group_name, TRUE))
james@561 473 xenpci_group_index = (ULONG)i;
james@539 474 if (!RtlCompareUnicodeString(&val, &boot_bus_extender_name, TRUE))
james@539 475 boot_bus_extender_index = (ULONG)i;
james@539 476 KdPrint((__DRIVER_NAME " %wZ\n", &val));
james@539 477 }
james@539 478 KdPrint((__DRIVER_NAME " dummy_group_index = %d\n", dummy_group_index));
james@539 479 KdPrint((__DRIVER_NAME " wdf_load_group_index = %d\n", wdf_load_group_index));
james@561 480 KdPrint((__DRIVER_NAME " xenpci_group_index = %d\n", xenpci_group_index));
james@539 481 KdPrint((__DRIVER_NAME " boot_bus_extender_index = %d\n", boot_bus_extender_index));
james@539 482 if (boot_bus_extender_index == -1)
james@539 483 {
james@539 484 WdfObjectDelete(new_load_order);
james@539 485 WdfObjectDelete(old_load_order);
james@539 486 WdfRegistryClose(sgo_key);
james@539 487 return; /* something is very wrong */
james@539 488 }
james@561 489 if (dummy_group_index == 1 && (wdf_load_group_index == -1 ||
james@561 490 (dummy_group_index < wdf_load_group_index
james@561 491 && wdf_load_group_index < xenpci_group_index
james@561 492 && xenpci_group_index < boot_bus_extender_index)))
james@539 493 {
james@539 494 return; /* our work here is done */
james@539 495 }
james@539 496 for (i = 0; i < WdfCollectionGetCount(old_load_order); i++)
james@539 497 {
james@539 498 WDFOBJECT ws;
james@539 499 if (i == 1)
james@539 500 {
james@539 501 WDFSTRING tmp_wdf_string;
james@539 502 WdfStringCreate(&dummy_group_name, WDF_NO_OBJECT_ATTRIBUTES, &tmp_wdf_string);
james@539 503 WdfCollectionAdd(new_load_order, tmp_wdf_string);
james@539 504 WdfObjectDelete(tmp_wdf_string);
james@539 505 }
james@540 506 if (i == 1 && wdf_load_group_index != -1)
james@539 507 {
james@539 508 WDFSTRING tmp_wdf_string;
james@539 509 WdfStringCreate(&wdf_load_group_name, WDF_NO_OBJECT_ATTRIBUTES, &tmp_wdf_string);
james@539 510 WdfCollectionAdd(new_load_order, tmp_wdf_string);
james@539 511 WdfObjectDelete(tmp_wdf_string);
james@539 512 }
james@561 513 if (i == 1)
james@561 514 {
james@561 515 WDFSTRING tmp_wdf_string;
james@561 516 WdfStringCreate(&xenpci_group_name, WDF_NO_OBJECT_ATTRIBUTES, &tmp_wdf_string);
james@561 517 WdfCollectionAdd(new_load_order, tmp_wdf_string);
james@561 518 WdfObjectDelete(tmp_wdf_string);
james@561 519 }
james@561 520 if (i == (ULONG)dummy_group_index || i == (ULONG)wdf_load_group_index || i == (ULONG)xenpci_group_index)
james@539 521 continue;
james@539 522 ws = WdfCollectionGetItem(old_load_order, i);
james@539 523 WdfCollectionAdd(new_load_order, ws);
james@539 524 }
james@539 525 WdfRegistryAssignMultiString(sgo_key, &list_name, new_load_order);
james@539 526 KdPrint((__DRIVER_NAME " New Order:\n"));
james@539 527 for (i = 0; i < WdfCollectionGetCount(new_load_order); i++)
james@539 528 {
james@539 529 WDFOBJECT ws = WdfCollectionGetItem(new_load_order, i);
james@539 530 UNICODE_STRING val;
james@539 531 WdfStringGetUnicodeString(ws, &val);
james@539 532 KdPrint((__DRIVER_NAME " %wZ\n", &val));
james@539 533 }
james@539 534 WdfObjectDelete(new_load_order);
james@539 535 WdfObjectDelete(old_load_order);
james@539 536 WdfRegistryClose(sgo_key);
james@539 537
james@539 538 FUNCTION_EXIT();
james@539 539
james@539 540 return;
james@539 541 }
james@539 542
james@536 543 NTSTATUS
james@259 544 DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath)
james@258 545 {
james@258 546 NTSTATUS status = STATUS_SUCCESS;
james@536 547 WDF_DRIVER_CONFIG config;
james@536 548 WDFDRIVER driver;
james@495 549 PCONFIGURATION_INFORMATION conf_info;
james@495 550 WCHAR *SystemStartOptions;
james@495 551 UNICODE_STRING RegKeyName;
james@495 552 UNICODE_STRING RegValueName;
james@495 553 HANDLE RegHandle;
james@495 554 OBJECT_ATTRIBUTES RegObjectAttributes;
james@495 555 char Buf[300];// Sometimes bigger then 200 if system reboot from crash
james@495 556 ULONG BufLen = 300;
james@495 557 PKEY_VALUE_PARTIAL_INFORMATION KeyPartialValue;
james@638 558
james@259 559 UNREFERENCED_PARAMETER(RegistryPath);
andy@90 560
james@700 561 KdPrint((__DRIVER_NAME " " VER_FILEVERSION_STR "\n"));
james@666 562
andy@398 563 FUNCTION_ENTER();
james@638 564
james@638 565 status = AuxKlibInitialize();
james@638 566 if(!NT_SUCCESS(status))
james@638 567 {
james@638 568 KdPrint((__DRIVER_NAME " AuxKlibInitialize failed %08x - expect a crash soon\n", status));
james@638 569 }
james@539 570
james@700 571 XenPci_HookDbgPrint();
james@716 572
james@539 573 XenPci_FixLoadOrder();
james@533 574
james@495 575 RtlInitUnicodeString(&RegKeyName, L"\\Registry\\Machine\\System\\CurrentControlSet\\Control");
james@495 576 InitializeObjectAttributes(&RegObjectAttributes, &RegKeyName, OBJ_CASE_INSENSITIVE, NULL, NULL);
james@495 577 status = ZwOpenKey(&RegHandle, KEY_READ, &RegObjectAttributes);
james@495 578 if(!NT_SUCCESS(status))
james@495 579 {
james@495 580 KdPrint((__DRIVER_NAME " ZwOpenKey returned %08x\n", status));
james@495 581 }
james@495 582
james@495 583 RtlInitUnicodeString(&RegValueName, L"SystemStartOptions");
james@495 584 status = ZwQueryValueKey(RegHandle, &RegValueName, KeyValuePartialInformation, Buf, BufLen, &BufLen);
james@495 585 if(!NT_SUCCESS(status))
james@495 586 {
james@495 587 KdPrint((__DRIVER_NAME " ZwQueryKeyValue returned %08x\n", status));
james@495 588 }
james@495 589 else
james@495 590 ZwClose(RegHandle);
james@495 591 KeyPartialValue = (PKEY_VALUE_PARTIAL_INFORMATION)Buf;
james@495 592 SystemStartOptions = (WCHAR *)KeyPartialValue->Data;
james@495 593
james@536 594 KdPrint((__DRIVER_NAME " SystemStartOptions = %S\n", SystemStartOptions));
james@529 595
james@529 596 if (wcsstr(SystemStartOptions, L"PATCHTPR"))
james@529 597 {
james@638 598 WDFKEY memory_key;
james@638 599 UNICODE_STRING verifier_key_name;
james@638 600 UNICODE_STRING verifier_value_name;
james@638 601 ULONG verifier_value;
james@638 602
james@529 603 KdPrint((__DRIVER_NAME " PATCHTPR found\n"));
james@638 604
james@638 605 RtlInitUnicodeString(&verifier_key_name, L"\\Registry\\Machine\\System\\CurrentControlSet\\Control\\Session Manager\\Memory Management");
james@638 606 status = WdfRegistryOpenKey(NULL, &verifier_key_name, KEY_READ, WDF_NO_OBJECT_ATTRIBUTES, &memory_key);
james@638 607 if (!NT_SUCCESS(status))
james@638 608 {
james@638 609 tpr_patch_requested = TRUE;
james@638 610 }
james@638 611 else
james@638 612 {
james@638 613 RtlInitUnicodeString(&verifier_value_name, L"VerifyDriverLevel");
james@638 614 status = WdfRegistryQueryULong(memory_key, &verifier_value_name, &verifier_value);
james@638 615 if (NT_SUCCESS(status) && verifier_value != 0)
james@638 616 {
james@638 617 KdPrint((__DRIVER_NAME " Verifier active - not patching\n"));
james@638 618 }
james@638 619 else
james@638 620 {
james@638 621 tpr_patch_requested = TRUE;
james@638 622 }
james@638 623 WdfRegistryClose(memory_key);
james@638 624 }
james@529 625 }
james@529 626
james@747 627 WDF_DRIVER_CONFIG_INIT(&config, XenPci_EvtDeviceAdd);
james@747 628 status = WdfDriverCreate(DriverObject, RegistryPath, WDF_NO_OBJECT_ATTRIBUTES, &config, &driver);
james@747 629
james@747 630 WdfCollectionCreate(WDF_NO_OBJECT_ATTRIBUTES, &qemu_hide_devices);
james@747 631
james@747 632 if (!NT_SUCCESS(status)) {
james@747 633 KdPrint((__DRIVER_NAME " WdfDriverCreate failed with status 0x%x\n", status));
james@747 634 FUNCTION_EXIT();
james@747 635 return status;
james@747 636 }
james@747 637
james@747 638 qemu_hide_flags_value = 0;
james@747 639
james@495 640 if (wcsstr(SystemStartOptions, L"NOGPLPV"))
james@495 641 KdPrint((__DRIVER_NAME " NOGPLPV found\n"));
james@495 642 conf_info = IoGetConfigurationInformation();
james@495 643 if ((conf_info == NULL || conf_info->DiskCount == 0)
james@495 644 && !wcsstr(SystemStartOptions, L"NOGPLPV")
james@495 645 && !*InitSafeBootMode)
james@495 646 {
james@747 647 if (wcsstr(SystemStartOptions, L"GPLPVUSEFILTERHIDE") == 0 && XenPci_CheckHideQemuDevices())
james@747 648 {
james@747 649 DECLARE_CONST_UNICODE_STRING(qemu_hide_flags_name, L"qemu_hide_flags");
james@747 650 WDFCOLLECTION qemu_hide_flags;
james@747 651 WDFKEY param_key;
james@747 652 ULONG i;
james@747 653
james@747 654 WdfCollectionCreate(WDF_NO_OBJECT_ATTRIBUTES, &qemu_hide_flags);
james@747 655 status = WdfDriverOpenParametersRegistryKey(driver, KEY_QUERY_VALUE, WDF_NO_OBJECT_ATTRIBUTES, &param_key);
james@747 656 if (NT_SUCCESS(status))
james@747 657 {
james@747 658 status = WdfRegistryQueryMultiString(param_key, &qemu_hide_flags_name, WDF_NO_OBJECT_ATTRIBUTES, qemu_hide_flags);
james@747 659 if (!NT_SUCCESS(status))
james@747 660 {
james@747 661 KdPrint(("Error reading parameters/qemu_hide_flags value %08x\n", status));
james@747 662 }
james@747 663 else
james@747 664 {
james@747 665 for (i = 0; i < WdfCollectionGetCount(qemu_hide_flags); i++)
james@747 666 {
james@747 667 ULONG value;
james@747 668 WDFSTRING wdf_string = WdfCollectionGetItem(qemu_hide_flags, i);
james@747 669 UNICODE_STRING unicode_string;
james@747 670 WdfStringGetUnicodeString(wdf_string, &unicode_string);
james@747 671 KdPrint(("\n", status));
james@747 672 status = RtlUnicodeStringToInteger(&unicode_string, 0, &value);
james@747 673 qemu_hide_flags_value |= value;
james@747 674 }
james@747 675 }
james@747 676 WdfRegistryClose(param_key);
james@747 677 }
james@747 678 else
james@747 679 {
james@747 680 KdPrint(("Error opening parameters key %08x\n", status));
james@747 681 }
james@747 682 XenPci_HideQemuDevices();
james@747 683 }
james@747 684 else
james@747 685 {
james@747 686 DECLARE_CONST_UNICODE_STRING(hide_devices_name, L"hide_devices");
james@747 687 WDFKEY param_key;
james@747 688 status = WdfDriverOpenParametersRegistryKey(driver, KEY_QUERY_VALUE, WDF_NO_OBJECT_ATTRIBUTES, &param_key);
james@747 689 if (NT_SUCCESS(status))
james@747 690 {
james@747 691 status = WdfRegistryQueryMultiString(param_key, &hide_devices_name, WDF_NO_OBJECT_ATTRIBUTES, qemu_hide_devices);
james@747 692 if (!NT_SUCCESS(status))
james@747 693 {
james@747 694 KdPrint(("Error reading parameters/hide_devices value %08x\n", status));
james@747 695 }
james@747 696 WdfRegistryClose(param_key);
james@747 697 }
james@747 698 else
james@747 699 {
james@747 700 KdPrint(("Error opening parameters key %08x\n", status));
james@747 701 }
james@747 702 }
james@536 703 }
james@536 704
andy@398 705 FUNCTION_EXIT();
james@191 706
james@747 707 return STATUS_SUCCESS;
andy@324 708 }