win-pvdrivers

annotate xenpci/xenpci.c @ 1001:c21dd04d3ae6

Less noise for xennet6
author James Harper <james.harper@bendigoit.com.au>
date Fri Dec 14 21:26:22 2012 +1100 (2012-12-14)
parents 58899e6ed48f
children 4f7d5a8636bd
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@861 31 PMDL balloon_mdl_head = NULL;
james@861 32
james@716 33 /* Not really necessary but keeps PREfast happy */
james@716 34 DRIVER_INITIALIZE DriverEntry;
james@818 35 static EVT_WDF_DRIVER_UNLOAD XenPci_EvtDriverUnload;
james@716 36 static EVT_WDF_DRIVER_DEVICE_ADD XenPci_EvtDeviceAdd;
james@716 37 static EVT_WDF_DEVICE_USAGE_NOTIFICATION XenPci_EvtDeviceUsageNotification;
james@716 38 static EVT_WDF_DEVICE_PREPARE_HARDWARE XenHide_EvtDevicePrepareHardware;
james@716 39
james@907 40 #if (NTDDI_VERSION >= NTDDI_WS03SP1)
james@987 41 static KBUGCHECK_REASON_CALLBACK_ROUTINE XenPci_DebugHeaderDumpIoCallback;
james@907 42
james@860 43 /* this is supposed to be defined in wdm.h, but isn't */
james@860 44 NTSTATUS
james@860 45 KeInitializeCrashDumpHeader(
james@860 46 IN ULONG Type,
james@860 47 IN ULONG Flags,
james@860 48 OUT PVOID Buffer,
james@860 49 IN ULONG BufferSize,
james@860 50 OUT PULONG BufferNeeded OPTIONAL
james@860 51 );
james@907 52 #endif
james@860 53
james@860 54 #define DUMP_TYPE_FULL 1
james@860 55
james@538 56 static VOID
james@538 57 XenPci_EvtDeviceUsageNotification(WDFDEVICE device, WDF_SPECIAL_FILE_TYPE notification_type, BOOLEAN is_in_notification_path)
james@538 58 {
james@538 59 FUNCTION_ENTER();
james@538 60
james@538 61 UNREFERENCED_PARAMETER(device);
james@700 62 UNREFERENCED_PARAMETER(is_in_notification_path);
james@538 63
james@538 64 switch (notification_type)
james@538 65 {
james@538 66 case WdfSpecialFilePaging:
james@538 67 KdPrint((__DRIVER_NAME " notification_type = Paging, flag = %d\n", is_in_notification_path));
james@538 68 break;
james@538 69 case WdfSpecialFileHibernation:
james@538 70 KdPrint((__DRIVER_NAME " notification_type = Hibernation, flag = %d\n", is_in_notification_path));
james@538 71 break;
james@538 72 case WdfSpecialFileDump:
james@538 73 KdPrint((__DRIVER_NAME " notification_type = Dump, flag = %d\n", is_in_notification_path));
james@538 74 break;
james@538 75 default:
james@538 76 KdPrint((__DRIVER_NAME " notification_type = %d, flag = %d\n", notification_type, is_in_notification_path));
james@538 77 break;
james@538 78 }
james@538 79
james@538 80 FUNCTION_EXIT();
james@538 81 }
james@538 82
james@536 83 static NTSTATUS
james@561 84 XenPci_EvtDeviceAdd_XenPci(WDFDRIVER driver, PWDFDEVICE_INIT device_init)
james@0 85 {
james@258 86 NTSTATUS status;
james@536 87 // PDEVICE_OBJECT fdo = NULL;
james@258 88 // PNP_BUS_INFORMATION busInfo;
james@258 89 // DECLARE_CONST_UNICODE_STRING(DeviceName, L"\\Device\\XenShutdown");
james@258 90 // DECLARE_CONST_UNICODE_STRING(SymbolicName, L"\\DosDevices\\XenShutdown");
james@536 91 WDF_CHILD_LIST_CONFIG child_list_config;
james@536 92 WDFDEVICE device;
andy@16 93 PXENPCI_DEVICE_DATA xpdd;
james@504 94 UNICODE_STRING reference;
james@536 95 WDF_OBJECT_ATTRIBUTES device_attributes;
james@536 96 PNP_BUS_INFORMATION pbi;
james@536 97 WDF_PNPPOWER_EVENT_CALLBACKS pnp_power_callbacks;
james@536 98 WDF_INTERRUPT_CONFIG interrupt_config;
james@536 99 WDF_OBJECT_ATTRIBUTES file_attributes;
james@536 100 WDF_FILEOBJECT_CONFIG file_config;
james@536 101 WDF_IO_QUEUE_CONFIG queue_config;
james@624 102 WDFCOLLECTION veto_devices;
james@538 103 WDFKEY param_key;
james@538 104 DECLARE_CONST_UNICODE_STRING(veto_devices_name, L"veto_devices");
james@538 105 WDF_DEVICE_POWER_CAPABILITIES power_capabilities;
james@624 106 int i;
james@536 107
james@536 108 UNREFERENCED_PARAMETER(driver);
james@258 109
andy@398 110 FUNCTION_ENTER();
james@561 111
james@536 112 WDF_PNPPOWER_EVENT_CALLBACKS_INIT(&pnp_power_callbacks);
james@536 113 pnp_power_callbacks.EvtDeviceD0Entry = XenPci_EvtDeviceD0Entry;
james@536 114 pnp_power_callbacks.EvtDeviceD0EntryPostInterruptsEnabled = XenPci_EvtDeviceD0EntryPostInterruptsEnabled;
james@536 115 pnp_power_callbacks.EvtDeviceD0Exit = XenPci_EvtDeviceD0Exit;
james@536 116 pnp_power_callbacks.EvtDeviceD0ExitPreInterruptsDisabled = XenPci_EvtDeviceD0ExitPreInterruptsDisabled;
james@536 117 pnp_power_callbacks.EvtDevicePrepareHardware = XenPci_EvtDevicePrepareHardware;
james@536 118 pnp_power_callbacks.EvtDeviceReleaseHardware = XenPci_EvtDeviceReleaseHardware;
james@537 119 pnp_power_callbacks.EvtDeviceQueryRemove = XenPci_EvtDeviceQueryRemove;
james@538 120 pnp_power_callbacks.EvtDeviceUsageNotification = XenPci_EvtDeviceUsageNotification;
james@538 121
james@536 122 WdfDeviceInitSetPnpPowerEventCallbacks(device_init, &pnp_power_callbacks);
james@536 123
james@536 124 WdfDeviceInitSetDeviceType(device_init, FILE_DEVICE_BUS_EXTENDER);
james@536 125 WdfDeviceInitSetExclusive(device_init, FALSE);
james@536 126
james@536 127 WDF_CHILD_LIST_CONFIG_INIT(&child_list_config, sizeof(XENPCI_PDO_IDENTIFICATION_DESCRIPTION), XenPci_EvtChildListCreateDevice);
james@536 128 child_list_config.EvtChildListScanForChildren = XenPci_EvtChildListScanForChildren;
james@536 129 WdfFdoInitSetDefaultChildListConfig(device_init, &child_list_config, WDF_NO_OBJECT_ATTRIBUTES);
james@536 130
james@536 131 WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&file_attributes, XENPCI_DEVICE_INTERFACE_DATA);
james@536 132 WDF_FILEOBJECT_CONFIG_INIT(&file_config, XenPci_EvtDeviceFileCreate, XenPci_EvtFileClose, XenPci_EvtFileCleanup);
james@536 133 WdfDeviceInitSetFileObjectConfig(device_init, &file_config, &file_attributes);
james@536 134
james@536 135 WdfDeviceInitSetIoType(device_init, WdfDeviceIoBuffered);
james@538 136
james@538 137 WdfDeviceInitSetPowerNotPageable(device_init);
james@536 138
james@536 139 WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&device_attributes, XENPCI_DEVICE_DATA);
james@536 140 status = WdfDeviceCreate(&device_init, &device_attributes, &device);
james@538 141 if (!NT_SUCCESS(status))
james@538 142 {
james@538 143 KdPrint(("Error creating device %08x\n", status));
james@538 144 return status;
james@536 145 }
james@536 146
james@536 147 xpdd = GetXpdd(device);
james@622 148 xpdd->wdf_device = device;
james@599 149 xpdd->child_list = WdfFdoGetDefaultChildList(device);
james@536 150
james@624 151 WdfCollectionCreate(WDF_NO_OBJECT_ATTRIBUTES, &veto_devices);
james@538 152 status = WdfDriverOpenParametersRegistryKey(driver, KEY_QUERY_VALUE, WDF_NO_OBJECT_ATTRIBUTES, &param_key);
james@538 153 if (NT_SUCCESS(status))
james@538 154 {
james@624 155 status = WdfRegistryQueryMultiString(param_key, &veto_devices_name, WDF_NO_OBJECT_ATTRIBUTES, veto_devices);
james@538 156 if (!NT_SUCCESS(status))
james@538 157 {
james@538 158 KdPrint(("Error reading parameters/veto_devices value %08x\n", status));
james@538 159 }
james@538 160 WdfRegistryClose(param_key);
james@538 161 }
james@538 162 else
james@538 163 {
james@538 164 KdPrint(("Error opening parameters key %08x\n", status));
james@538 165 }
james@624 166
james@624 167 InitializeListHead(&xpdd->veto_list);
james@637 168 for (i = 0; i < (int)WdfCollectionGetCount(veto_devices); i++)
james@624 169 {
james@624 170 WDFOBJECT ws;
james@624 171 UNICODE_STRING val;
james@624 172 ANSI_STRING s;
james@624 173 PVOID entry;
james@624 174 ws = WdfCollectionGetItem(veto_devices, i);
james@624 175 WdfStringGetUnicodeString(ws, &val);
james@624 176 RtlUnicodeStringToAnsiString(&s, &val, TRUE);
james@624 177 entry = ExAllocatePoolWithTag(NonPagedPool, sizeof(LIST_ENTRY) + s.Length + 1, XENPCI_POOL_TAG);
james@624 178 memcpy((PUCHAR)entry + sizeof(LIST_ENTRY), s.Buffer, s.Length + 1);
james@624 179 RtlFreeAnsiString(&s);
james@624 180 InsertTailList(&xpdd->veto_list, (PLIST_ENTRY)entry);
james@624 181 }
james@538 182 WDF_DEVICE_POWER_CAPABILITIES_INIT(&power_capabilities);
james@538 183 power_capabilities.DeviceD1 = WdfTrue;
james@538 184 power_capabilities.WakeFromD1 = WdfTrue;
james@538 185 power_capabilities.DeviceWake = PowerDeviceD1;
james@912 186 power_capabilities.DeviceState[PowerSystemWorking] = PowerDeviceD0;
james@538 187 power_capabilities.DeviceState[PowerSystemSleeping1] = PowerDeviceD1;
james@538 188 power_capabilities.DeviceState[PowerSystemSleeping2] = PowerDeviceD2;
james@538 189 power_capabilities.DeviceState[PowerSystemSleeping3] = PowerDeviceD2;
james@538 190 power_capabilities.DeviceState[PowerSystemHibernate] = PowerDeviceD3;
james@538 191 power_capabilities.DeviceState[PowerSystemShutdown] = PowerDeviceD3;
james@538 192 WdfDeviceSetPowerCapabilities(device, &power_capabilities);
james@538 193
james@536 194 WdfDeviceSetSpecialFileSupport(device, WdfSpecialFilePaging, TRUE);
james@536 195 WdfDeviceSetSpecialFileSupport(device, WdfSpecialFileHibernation, TRUE);
james@536 196 WdfDeviceSetSpecialFileSupport(device, WdfSpecialFileDump, TRUE);
james@536 197
james@536 198 WDF_IO_QUEUE_CONFIG_INIT_DEFAULT_QUEUE(&queue_config, WdfIoQueueDispatchParallel);
james@671 199 queue_config.EvtIoDefault = XenPci_EvtIoDefault;
james@536 200 status = WdfIoQueueCreate(device, &queue_config, WDF_NO_OBJECT_ATTRIBUTES, &xpdd->io_queue);
james@536 201 if (!NT_SUCCESS(status)) {
james@536 202 KdPrint(("Error creating queue 0x%x\n", status));
james@536 203 return status;
james@536 204 }
james@536 205
james@536 206 WDF_INTERRUPT_CONFIG_INIT(&interrupt_config, EvtChn_EvtInterruptIsr, NULL);
james@536 207 interrupt_config.EvtInterruptEnable = EvtChn_EvtInterruptEnable;
james@536 208 interrupt_config.EvtInterruptDisable = EvtChn_EvtInterruptDisable;
james@536 209
james@536 210 status = WdfInterruptCreate(device, &interrupt_config, WDF_NO_OBJECT_ATTRIBUTES, &xpdd->interrupt);
james@536 211 if (!NT_SUCCESS(status))
james@536 212 {
james@536 213 KdPrint(("Error creating interrupt 0x%x\n", status));
james@536 214 return status;
james@536 215 }
james@536 216
james@536 217 RtlInitUnicodeString(&reference, L"xenbus");
james@536 218 status = WdfDeviceCreateDeviceInterface(device, &GUID_DEVINTERFACE_XENBUS, &reference);
james@536 219 if (!NT_SUCCESS(status)) {
james@536 220 KdPrint(("Error registering device interface 0x%x\n", status));
james@536 221 return status;
james@536 222 }
james@536 223
james@671 224 RtlInitUnicodeString(&reference, L"evtchn");
james@671 225 status = WdfDeviceCreateDeviceInterface(device, &GUID_DEVINTERFACE_EVTCHN, &reference);
james@671 226 if (!NT_SUCCESS(status)) {
james@671 227 KdPrint(("Error registering device interface 0x%x\n", status));
james@671 228 return status;
james@671 229 }
james@671 230
james@671 231 RtlInitUnicodeString(&reference, L"gntdev");
james@671 232 status = WdfDeviceCreateDeviceInterface(device, &GUID_DEVINTERFACE_GNTDEV, &reference);
james@671 233 if (!NT_SUCCESS(status)) {
james@671 234 KdPrint(("Error registering device interface 0x%x\n", status));
james@671 235 return status;
james@671 236 }
james@671 237
james@536 238 pbi.BusTypeGuid = GUID_BUS_TYPE_XEN;
james@536 239 pbi.LegacyBusType = PNPBus;
james@536 240 pbi.BusNumber = 0;
james@536 241 WdfDeviceSetBusInformationForChildren(device, &pbi);
james@536 242
james@537 243 xpdd->removable = TRUE;
james@536 244
james@536 245 FUNCTION_EXIT();
james@536 246 return status;
james@258 247 }
james@258 248
james@561 249 NTSTATUS
james@747 250 XenHide_EvtDevicePrepareHardware(WDFDEVICE device, WDFCMRESLIST resources_raw, WDFCMRESLIST resources_translated)
james@561 251 {
james@561 252 UNREFERENCED_PARAMETER(device);
james@561 253 UNREFERENCED_PARAMETER(resources_raw);
james@561 254 UNREFERENCED_PARAMETER(resources_translated);
james@561 255 FUNCTION_ENTER();
james@561 256 FUNCTION_EXIT();
james@561 257 return STATUS_UNSUCCESSFUL;
james@561 258 }
james@561 259
james@561 260 static BOOLEAN
james@561 261 XenPci_IdSuffixMatches(PWDFDEVICE_INIT device_init, PWCHAR matching_id)
james@561 262 {
james@561 263 NTSTATUS status;
james@561 264 WDFMEMORY memory;
james@561 265 ULONG remaining;
james@561 266 size_t string_length;
james@561 267 PWCHAR ids;
james@561 268 PWCHAR ptr;
james@561 269 size_t ids_length;
james@561 270 ULONG properties[] = {DevicePropertyCompatibleIDs, DevicePropertyHardwareID};
james@561 271 int i;
james@561 272
james@561 273 // KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
james@561 274 for (i = 0; i < ARRAY_SIZE(properties); i++)
james@561 275 {
james@561 276
james@561 277 status = WdfFdoInitAllocAndQueryProperty(device_init, properties[i], NonPagedPool, WDF_NO_OBJECT_ATTRIBUTES, &memory);
james@561 278 if (!NT_SUCCESS(status))
james@561 279 continue;
james@561 280 ids = WdfMemoryGetBuffer(memory, &ids_length);
james@561 281
james@561 282 if (!NT_SUCCESS(status))
james@561 283 {
james@561 284 // KdPrint((__DRIVER_NAME " i = %d, status = %x, ids_length = %d\n", i, status, ids_length));
james@561 285 continue;
james@561 286 }
james@561 287
james@561 288 remaining = (ULONG)ids_length / 2;
james@561 289 for (ptr = ids; *ptr != 0; ptr += string_length + 1)
james@561 290 {
james@561 291 RtlStringCchLengthW(ptr, remaining, &string_length);
james@561 292 remaining -= (ULONG)string_length + 1;
james@561 293 if (string_length >= wcslen(matching_id))
james@561 294 {
james@561 295 ptr += string_length - wcslen(matching_id);
james@561 296 string_length = wcslen(matching_id);
james@561 297 }
james@561 298 // KdPrint((__DRIVER_NAME " Comparing '%S' and '%S'\n", ptr, matching_id));
james@561 299 if (wcscmp(ptr, matching_id) == 0)
james@561 300 {
james@561 301 //KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ " (Match)\n"));
james@561 302 WdfObjectDelete(memory);
james@561 303 return TRUE;
james@561 304 }
james@561 305 }
james@561 306 WdfObjectDelete(memory);
james@561 307 }
james@561 308 // KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ " (No match)\n"));
james@561 309 return FALSE;
james@561 310 }
james@561 311
james@747 312 WDFCOLLECTION qemu_hide_devices;
james@747 313 USHORT qemu_hide_flags_value;
james@561 314
james@561 315 static NTSTATUS
james@561 316 XenPci_EvtDeviceAdd_XenHide(WDFDRIVER driver, PWDFDEVICE_INIT device_init)
james@561 317 {
james@561 318 NTSTATUS status;
james@561 319 WDFMEMORY memory;
james@561 320 PWCHAR device_description;
james@561 321 WDF_PNPPOWER_EVENT_CALLBACKS pnp_power_callbacks;
james@561 322 WDF_OBJECT_ATTRIBUTES device_attributes;
james@561 323 BOOLEAN hide_required = FALSE;
james@561 324 WDFDEVICE device;
james@561 325 ULONG i;
james@747 326
james@561 327 UNREFERENCED_PARAMETER(driver);
james@561 328
james@561 329 FUNCTION_ENTER();
james@561 330
james@561 331 status = WdfFdoInitAllocAndQueryProperty(device_init, DevicePropertyDeviceDescription, NonPagedPool, WDF_NO_OBJECT_ATTRIBUTES, &memory);
james@561 332 if (NT_SUCCESS(status))
james@561 333 {
james@561 334 device_description = WdfMemoryGetBuffer(memory, NULL);
james@561 335 }
james@561 336 else
james@561 337 {
james@561 338 device_description = L"<unknown device>";
james@561 339 }
james@561 340
james@747 341 for (i = 0; i < WdfCollectionGetCount(qemu_hide_devices); i++)
james@561 342 {
james@747 343 WDFSTRING wdf_string = WdfCollectionGetItem(qemu_hide_devices, i);
james@561 344 UNICODE_STRING unicode_string;
james@561 345 WdfStringGetUnicodeString(wdf_string, &unicode_string);
james@561 346 if (XenPci_IdSuffixMatches(device_init, unicode_string.Buffer))
james@561 347 {
james@561 348 hide_required = TRUE;
james@561 349 break;
james@561 350 }
james@561 351 }
james@561 352 if (!hide_required)
james@561 353 {
james@561 354 WdfObjectDelete(memory);
james@561 355 KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ " (filter not required for %S)\n", device_description));
james@561 356 return STATUS_SUCCESS;
james@561 357 }
james@561 358
james@561 359 KdPrint((__DRIVER_NAME " Installing Filter for %S\n", device_description));
james@561 360
james@561 361 WdfFdoInitSetFilter(device_init);
james@561 362 WdfDeviceInitSetDeviceType(device_init, FILE_DEVICE_UNKNOWN);
james@561 363 WdfDeviceInitSetExclusive(device_init, FALSE);
james@561 364
james@561 365 WDF_PNPPOWER_EVENT_CALLBACKS_INIT(&pnp_power_callbacks);
james@561 366 pnp_power_callbacks.EvtDevicePrepareHardware = XenHide_EvtDevicePrepareHardware;
james@561 367 WdfDeviceInitSetPnpPowerEventCallbacks(device_init, &pnp_power_callbacks);
james@561 368
james@561 369 WDF_OBJECT_ATTRIBUTES_INIT(&device_attributes);
james@561 370 status = WdfDeviceCreate(&device_init, &device_attributes, &device);
james@561 371 if (!NT_SUCCESS(status))
james@561 372 {
james@561 373 KdPrint(("Error creating device %08x\n", status));
james@561 374 WdfObjectDelete(memory);
james@561 375 FUNCTION_EXIT();
james@561 376 return status;
james@561 377 }
james@561 378
james@561 379 WdfObjectDelete(memory);
james@561 380 FUNCTION_EXIT();
james@561 381
james@561 382 return status;
james@561 383 }
james@561 384
james@561 385 static NTSTATUS
james@561 386 XenPci_EvtDeviceAdd(WDFDRIVER driver, PWDFDEVICE_INIT device_init)
james@561 387 {
james@561 388 if (XenPci_IdSuffixMatches(device_init, L"VEN_5853&DEV_0001"))
james@561 389 {
james@561 390 KdPrint((__DRIVER_NAME " Xen PCI device found - must be fdo\n"));
james@561 391 return XenPci_EvtDeviceAdd_XenPci(driver, device_init);
james@561 392 }
james@747 393 else if (WdfCollectionGetCount(qemu_hide_devices) > 0)
james@561 394 {
james@561 395 KdPrint((__DRIVER_NAME " Xen PCI device not found - must be filter\n"));
james@561 396 return XenPci_EvtDeviceAdd_XenHide(driver, device_init);
james@561 397 }
james@561 398 else
james@561 399 return STATUS_SUCCESS;
james@561 400 }
james@561 401
james@497 402 ULONG qemu_protocol_version;
james@529 403 ULONG tpr_patch_requested;
james@495 404 extern PULONG InitSafeBootMode;
james@486 405
james@536 406 VOID
james@536 407 XenPci_HideQemuDevices()
james@533 408 {
james@979 409 #pragma warning(suppress:28138)
james@747 410 WRITE_PORT_USHORT(XEN_IOPORT_DEVICE_MASK, (USHORT)qemu_hide_flags_value); //QEMU_UNPLUG_ALL_IDE_DISKS|QEMU_UNPLUG_ALL_NICS);
james@800 411 KdPrint((__DRIVER_NAME " Disabled qemu devices %02x\n", qemu_hide_flags_value));
james@747 412 }
james@747 413
james@747 414 static BOOLEAN
james@747 415 XenPci_CheckHideQemuDevices()
james@747 416 {
james@979 417 #pragma warning(suppress:28138)
james@536 418 if (READ_PORT_USHORT(XEN_IOPORT_MAGIC) == 0x49d2)
james@533 419 {
james@979 420 #pragma warning(suppress:28138)
james@536 421 qemu_protocol_version = READ_PORT_UCHAR(XEN_IOPORT_VERSION);
james@536 422 KdPrint((__DRIVER_NAME " Version = %d\n", qemu_protocol_version));
james@536 423 switch(qemu_protocol_version)
james@533 424 {
james@536 425 case 1:
james@979 426 #pragma warning(suppress:28138)
james@536 427 WRITE_PORT_USHORT(XEN_IOPORT_PRODUCT, XEN_PV_PRODUCT_NUMBER);
james@979 428 #pragma warning(suppress:28138)
james@536 429 WRITE_PORT_ULONG(XEN_IOPORT_BUILD, XEN_PV_PRODUCT_BUILD);
james@979 430 #pragma warning(suppress:28138)
james@536 431 if (READ_PORT_USHORT(XEN_IOPORT_MAGIC) != 0x49d2)
james@536 432 {
james@536 433 KdPrint((__DRIVER_NAME " Blacklisted\n"));
james@536 434 break;
james@536 435 }
james@536 436 /* fall through */
james@536 437 case 0:
james@747 438 return TRUE;
james@536 439 default:
james@536 440 KdPrint((__DRIVER_NAME " Unknown qemu version %d\n", qemu_protocol_version));
james@536 441 break;
james@533 442 }
james@533 443 }
james@747 444 return FALSE;
james@533 445 }
james@533 446
james@539 447 /*
james@561 448 make sure the load order is System Reserved, Dummy Group, WdfLoadGroup, XenPCI, Boot Bus Extender
james@539 449 */
james@539 450
james@539 451 static VOID
james@539 452 XenPci_FixLoadOrder()
james@539 453 {
james@539 454 NTSTATUS status;
james@539 455 WDFCOLLECTION old_load_order, new_load_order;
james@539 456 DECLARE_CONST_UNICODE_STRING(sgo_name, L"\\Registry\\Machine\\SYSTEM\\CurrentControlSet\\Control\\ServiceGroupOrder");
james@539 457 DECLARE_CONST_UNICODE_STRING(list_name, L"List");
james@539 458 WDFKEY sgo_key;
james@539 459 ULONG i;
james@539 460 LONG dummy_group_index = -1;
james@539 461 LONG boot_bus_extender_index = -1;
james@561 462 LONG xenpci_group_index = -1;
james@539 463 LONG wdf_load_group_index = -1;
james@539 464 DECLARE_CONST_UNICODE_STRING(dummy_group_name, L"Dummy Group");
james@539 465 DECLARE_CONST_UNICODE_STRING(wdf_load_group_name, L"WdfLoadGroup");
james@561 466 DECLARE_CONST_UNICODE_STRING(xenpci_group_name, L"XenPCI Group");
james@539 467 DECLARE_CONST_UNICODE_STRING(boot_bus_extender_name, L"Boot Bus Extender");
james@539 468
james@539 469 FUNCTION_ENTER();
james@539 470
james@539 471 status = WdfRegistryOpenKey(NULL, &sgo_name, KEY_QUERY_VALUE, WDF_NO_OBJECT_ATTRIBUTES, &sgo_key);
james@539 472 if (!NT_SUCCESS(status))
james@539 473 {
james@539 474 KdPrint((__DRIVER_NAME " Error opening ServiceGroupOrder key %08x\n", status));
james@539 475 return;
james@539 476 }
james@539 477 WdfCollectionCreate(WDF_NO_OBJECT_ATTRIBUTES, &old_load_order);
james@539 478 WdfCollectionCreate(WDF_NO_OBJECT_ATTRIBUTES, &new_load_order);
james@539 479 status = WdfRegistryQueryMultiString(sgo_key, &list_name, WDF_NO_OBJECT_ATTRIBUTES, old_load_order);
james@539 480 if (!NT_SUCCESS(status))
james@539 481 {
james@539 482 KdPrint((__DRIVER_NAME " Error reading ServiceGroupOrder\\List value %08x\n", status));
james@539 483 WdfObjectDelete(new_load_order);
james@539 484 WdfObjectDelete(old_load_order);
james@539 485 return;
james@539 486 }
james@789 487 //KdPrint((__DRIVER_NAME " Current Order:\n"));
james@539 488 for (i = 0; i < WdfCollectionGetCount(old_load_order); i++)
james@539 489 {
james@539 490 WDFOBJECT ws = WdfCollectionGetItem(old_load_order, i);
james@539 491 UNICODE_STRING val;
james@539 492 WdfStringGetUnicodeString(ws, &val);
james@539 493 if (!RtlCompareUnicodeString(&val, &dummy_group_name, TRUE))
james@539 494 dummy_group_index = (ULONG)i;
james@539 495 if (!RtlCompareUnicodeString(&val, &wdf_load_group_name, TRUE))
james@539 496 wdf_load_group_index = (ULONG)i;
james@561 497 if (!RtlCompareUnicodeString(&val, &xenpci_group_name, TRUE))
james@561 498 xenpci_group_index = (ULONG)i;
james@539 499 if (!RtlCompareUnicodeString(&val, &boot_bus_extender_name, TRUE))
james@539 500 boot_bus_extender_index = (ULONG)i;
james@789 501 //KdPrint((__DRIVER_NAME " %wZ\n", &val));
james@539 502 }
james@539 503 KdPrint((__DRIVER_NAME " dummy_group_index = %d\n", dummy_group_index));
james@539 504 KdPrint((__DRIVER_NAME " wdf_load_group_index = %d\n", wdf_load_group_index));
james@561 505 KdPrint((__DRIVER_NAME " xenpci_group_index = %d\n", xenpci_group_index));
james@539 506 KdPrint((__DRIVER_NAME " boot_bus_extender_index = %d\n", boot_bus_extender_index));
james@539 507 if (boot_bus_extender_index == -1)
james@539 508 {
james@539 509 WdfObjectDelete(new_load_order);
james@539 510 WdfObjectDelete(old_load_order);
james@539 511 WdfRegistryClose(sgo_key);
james@539 512 return; /* something is very wrong */
james@539 513 }
james@827 514 if (dummy_group_index == 1 && wdf_load_group_index != -1 &&
james@561 515 (dummy_group_index < wdf_load_group_index
james@561 516 && wdf_load_group_index < xenpci_group_index
james@827 517 && xenpci_group_index < boot_bus_extender_index))
james@539 518 {
james@809 519 FUNCTION_EXIT();
james@539 520 return; /* our work here is done */
james@539 521 }
james@539 522 for (i = 0; i < WdfCollectionGetCount(old_load_order); i++)
james@539 523 {
james@539 524 WDFOBJECT ws;
james@539 525 if (i == 1)
james@539 526 {
james@539 527 WDFSTRING tmp_wdf_string;
james@539 528 WdfStringCreate(&dummy_group_name, WDF_NO_OBJECT_ATTRIBUTES, &tmp_wdf_string);
james@539 529 WdfCollectionAdd(new_load_order, tmp_wdf_string);
james@539 530 WdfObjectDelete(tmp_wdf_string);
james@539 531 }
james@827 532 if (i == 1)
james@539 533 {
james@539 534 WDFSTRING tmp_wdf_string;
james@539 535 WdfStringCreate(&wdf_load_group_name, WDF_NO_OBJECT_ATTRIBUTES, &tmp_wdf_string);
james@539 536 WdfCollectionAdd(new_load_order, tmp_wdf_string);
james@539 537 WdfObjectDelete(tmp_wdf_string);
james@539 538 }
james@561 539 if (i == 1)
james@561 540 {
james@561 541 WDFSTRING tmp_wdf_string;
james@561 542 WdfStringCreate(&xenpci_group_name, WDF_NO_OBJECT_ATTRIBUTES, &tmp_wdf_string);
james@561 543 WdfCollectionAdd(new_load_order, tmp_wdf_string);
james@561 544 WdfObjectDelete(tmp_wdf_string);
james@561 545 }
james@561 546 if (i == (ULONG)dummy_group_index || i == (ULONG)wdf_load_group_index || i == (ULONG)xenpci_group_index)
james@539 547 continue;
james@539 548 ws = WdfCollectionGetItem(old_load_order, i);
james@539 549 WdfCollectionAdd(new_load_order, ws);
james@539 550 }
james@539 551 WdfRegistryAssignMultiString(sgo_key, &list_name, new_load_order);
james@789 552 //KdPrint((__DRIVER_NAME " New Order:\n"));
james@539 553 for (i = 0; i < WdfCollectionGetCount(new_load_order); i++)
james@539 554 {
james@539 555 WDFOBJECT ws = WdfCollectionGetItem(new_load_order, i);
james@539 556 UNICODE_STRING val;
james@539 557 WdfStringGetUnicodeString(ws, &val);
james@789 558 //KdPrint((__DRIVER_NAME " %wZ\n", &val));
james@539 559 }
james@539 560 WdfObjectDelete(new_load_order);
james@539 561 WdfObjectDelete(old_load_order);
james@539 562 WdfRegistryClose(sgo_key);
james@539 563
james@539 564 FUNCTION_EXIT();
james@539 565
james@539 566 return;
james@539 567 }
james@539 568
james@800 569 VOID
james@800 570 XenPci_EvtDriverUnload(WDFDRIVER driver)
james@800 571 {
james@800 572 UNREFERENCED_PARAMETER(driver);
james@800 573
james@800 574 #if DBG
james@800 575 XenPci_UnHookDbgPrint();
james@800 576 #endif
james@800 577 }
james@800 578
james@860 579 /* we need to balloon down very early on in the case of PoD, so things get a little messy */
james@860 580 static PMDL
james@860 581 XenPci_InitialBalloonDown()
james@860 582 {
james@860 583 PVOID hypercall_stubs;
james@860 584 domid_t domid = DOMID_SELF;
james@860 585 ULONG maximum_reservation;
james@860 586 ULONG current_reservation;
james@860 587 ULONG extra_kb;
james@860 588 ULONG ret;
james@860 589 struct xen_memory_reservation reservation;
james@860 590 xen_pfn_t *pfns;
james@860 591 PMDL head = NULL;
james@860 592 PMDL mdl;
james@860 593 int i, j;
james@924 594 ULONG curr_pfns_offset;
james@924 595 PHYSICAL_ADDRESS alloc_low;
james@924 596 PHYSICAL_ADDRESS alloc_high;
james@924 597 PHYSICAL_ADDRESS alloc_skip;
james@860 598
james@860 599 FUNCTION_ENTER();
james@860 600
james@860 601 hypercall_stubs = hvm_get_hypercall_stubs();
james@860 602 if (!hypercall_stubs)
james@860 603 {
james@860 604 KdPrint((__DRIVER_NAME " Failed to copy hypercall stubs. Maybe not running under Xen?\n"));
james@954 605 FUNCTION_EXIT();
james@954 606 return NULL;
james@954 607 }
james@954 608 if (xen_version_major < 4)
james@954 609 {
james@954 610 FUNCTION_MSG("No support for PoD. Cannot do initial balloon down.\n");
james@954 611 FUNCTION_MSG("Expect a crash if maxmem is set much larger than memory.\n");
james@954 612 FUNCTION_EXIT();
james@860 613 return NULL;
james@860 614 }
james@860 615 ret = _HYPERVISOR_memory_op(hypercall_stubs, XENMEM_maximum_reservation, &domid);
james@860 616 KdPrint((__DRIVER_NAME " XENMEM_maximum_reservation = %d\n", ret));
james@860 617 maximum_reservation = ret;
james@860 618 ret = _HYPERVISOR_memory_op(hypercall_stubs, XENMEM_current_reservation, &domid);
james@860 619 KdPrint((__DRIVER_NAME " XENMEM_current_reservation = %d\n", ret));
james@860 620 current_reservation = ret;
james@860 621
james@860 622 extra_kb = (maximum_reservation - current_reservation) << 2;
james@860 623
james@924 624 alloc_low.QuadPart = 0;
james@924 625 alloc_high.QuadPart = 0xFFFFFFFFFFFFFFFFULL;
james@924 626 alloc_skip.QuadPart = PAGE_SIZE;
james@924 627
james@924 628 KdPrint((__DRIVER_NAME " Trying to give %d KB (%d MB) to Xen\n", extra_kb, extra_kb >> 10));
james@860 629
james@860 630 /* this code is mostly duplicated from the actual balloon thread... too hard to reuse */
james@924 631 pfns = ExAllocatePoolWithTag(NonPagedPool, max(BALLOON_UNIT_PAGES, (64 << 8)) * sizeof(xen_pfn_t), XENPCI_POOL_TAG);
james@979 632 if (!pfns) {
james@979 633 /* If we can't balloon down then we are going to crash in strange ways later. Better to bug check now. */
james@979 634 KdPrint((__DRIVER_NAME " Initial Balloon Down failed - no memory for pfn list\n"));
james@979 635 #pragma warning(suppress:28159)
james@979 636 KeBugCheckEx(('X' << 16)|('E' << 8)|('N'), 0x00000003, 0x00000000, 0x00000000, 0x00000000);
james@979 637 }
james@924 638 curr_pfns_offset = 0;
james@924 639 /* this makes sure we balloon up to the next multiple of BALLOON_UNITS_KB */
james@924 640 for (j = 0; j < (int)extra_kb; j += BALLOON_UNITS_KB)
james@924 641 {
james@860 642 #if (NTDDI_VERSION >= NTDDI_WS03SP1)
james@860 643 /* our contract says that we must zero pages before returning to xen, so we can't use MM_DONT_ZERO_ALLOCATION */
james@924 644 mdl = MmAllocatePagesForMdlEx(alloc_low, alloc_high, alloc_skip, BALLOON_UNITS_KB * 1024, MmCached, 0);
james@860 645 #else
james@924 646 mdl = MmAllocatePagesForMdl(alloc_low, alloc_high, alloc_skip, BALLOON_UNITS_KB * 1024);
james@860 647 #endif
james@924 648 if (!mdl || MmGetMdlByteCount(mdl) != BALLOON_UNITS_KB * 1024)
james@860 649 {
james@860 650 /* this should actually never happen. If we can't allocate the memory it means windows is using it, and if it was using it we would have crashed already... */
james@860 651 KdPrint((__DRIVER_NAME " Initial Balloon Down failed\n"));
james@979 652 #pragma warning(suppress:28159)
james@924 653 KeBugCheckEx(('X' << 16)|('E' << 8)|('N'), 0x00000002, extra_kb, j, 0x00000000);
james@860 654 }
james@860 655 else
james@860 656 {
james@924 657 /* sizeof(xen_pfn_t) may not be the same as PPFN_NUMBER */
james@924 658 for (i = 0; i < BALLOON_UNIT_PAGES; i++)
james@860 659 {
james@924 660 pfns[curr_pfns_offset] = (xen_pfn_t)(MmGetMdlPfnArray(mdl)[i]);
james@924 661 curr_pfns_offset++;
james@860 662 }
james@924 663 if (curr_pfns_offset == (ULONG)max(BALLOON_UNIT_PAGES, (64 << 8)) || j + BALLOON_UNITS_KB > (int)extra_kb)
james@924 664 {
james@924 665 reservation.address_bits = 0;
james@924 666 reservation.extent_order = 0;
james@924 667 reservation.domid = DOMID_SELF;
james@924 668 reservation.nr_extents = curr_pfns_offset;
james@924 669 #pragma warning(disable: 4127) /* conditional expression is constant */
james@924 670 set_xen_guest_handle(reservation.extent_start, pfns);
james@924 671 ret = _HYPERVISOR_memory_op(hypercall_stubs, XENMEM_decrease_reservation, &reservation);
james@924 672 if (ret != curr_pfns_offset)
james@924 673 FUNCTION_MSG("only decreased %d of %d pages\n", ret, curr_pfns_offset);
james@924 674 curr_pfns_offset = 0;
james@924 675 }
james@860 676 if (head)
james@860 677 {
james@860 678 mdl->Next = head;
james@860 679 head = mdl;
james@860 680 }
james@860 681 else
james@860 682 {
james@860 683 head = mdl;
james@860 684 }
james@860 685 }
james@924 686 //KdPrint((__DRIVER_NAME " C\n"));
james@860 687 }
james@924 688 ExFreePoolWithTag(pfns, XENPCI_POOL_TAG);
james@860 689 hvm_free_hypercall_stubs(hypercall_stubs);
james@860 690
james@860 691 FUNCTION_EXIT();
james@860 692
james@860 693 return head;
james@860 694 }
james@860 695
james@987 696 #if (NTDDI_VERSION >= NTDDI_WS03SP1)
james@979 697 /* this isn't freed on shutdown... perhaps it should be */
james@987 698 static PUCHAR dump_header;
james@987 699 static ULONG dump_header_size;
james@987 700 static ULONG dump_header_refreshed_flag = FALSE;
james@987 701 static KBUGCHECK_REASON_CALLBACK_RECORD callback_record;
james@987 702 #define DUMP_HEADER_PREFIX_SIZE 8
james@987 703 #define DUMP_HEADER_SUFFIX_SIZE 8
james@979 704
james@987 705 /* call KeInitializeCrashDumpHeader once on crash */
james@987 706 static VOID
james@987 707 XenPci_DebugHeaderDumpIoCallback(
james@987 708 KBUGCHECK_CALLBACK_REASON reason,
james@987 709 PKBUGCHECK_REASON_CALLBACK_RECORD record,
james@987 710 PVOID reason_specific_data,
james@987 711 ULONG reason_specific_data_length) {
james@987 712 UNREFERENCED_PARAMETER(reason);
james@987 713 UNREFERENCED_PARAMETER(record);
james@987 714 UNREFERENCED_PARAMETER(reason_specific_data);
james@987 715 UNREFERENCED_PARAMETER(reason_specific_data_length);
james@987 716 if (!dump_header_refreshed_flag) {
james@987 717 NTSTATUS status;
james@987 718 status = KeInitializeCrashDumpHeader(DUMP_TYPE_FULL, 0, dump_header + DUMP_HEADER_PREFIX_SIZE, dump_header_size, &dump_header_size);
james@987 719 /* copy bug check code in? */
james@987 720 dump_header_refreshed_flag = TRUE;
james@987 721 }
james@987 722 }
james@987 723 #endif
james@987 724
james@536 725 NTSTATUS
james@259 726 DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath)
james@258 727 {
james@258 728 NTSTATUS status = STATUS_SUCCESS;
james@536 729 WDF_DRIVER_CONFIG config;
james@536 730 WDFDRIVER driver;
james@809 731 WDF_OBJECT_ATTRIBUTES parent_attributes;
james@495 732 PCONFIGURATION_INFORMATION conf_info;
james@809 733 WDFKEY control_key;
james@793 734 WDFKEY param_key;
james@809 735 ULONG always_patch = 0;
james@809 736 ULONG always_hide = 0;
james@809 737 DECLARE_CONST_UNICODE_STRING(control_key_name, L"\\Registry\\Machine\\System\\CurrentControlSet\\Control");
james@809 738 DECLARE_CONST_UNICODE_STRING(system_start_options_name, L"SystemStartOptions");
james@809 739 DECLARE_CONST_UNICODE_STRING(txt_always_hide_name, L"txt_hide_qemu_always");
james@809 740 DECLARE_CONST_UNICODE_STRING(hide_devices_name, L"hide_devices");
james@809 741 DECLARE_CONST_UNICODE_STRING(txt_always_patch_name, L"txt_patch_tpr_always");
james@809 742 WDFSTRING wdf_system_start_options;
james@809 743 UNICODE_STRING system_start_options;
james@988 744 #if (NTDDI_VERSION >= NTDDI_WS03SP1)
james@987 745 PHYSICAL_ADDRESS dump_header_mem_max;
james@988 746 #endif
james@638 747
james@259 748 UNREFERENCED_PARAMETER(RegistryPath);
james@258 749
james@809 750 FUNCTION_ENTER();
james@809 751
james@987 752 FUNCTION_MSG(__DRIVER_NAME " " VER_FILEVERSION_STR "\n");
james@809 753
james@809 754 #if DBG
james@809 755 XenPci_HookDbgPrint();
james@809 756 #endif
james@818 757
james@992 758 NT_ASSERT(!balloon_mdl_head);
james@861 759 balloon_mdl_head = XenPci_InitialBalloonDown();
james@907 760
james@927 761 #if (NTDDI_VERSION >= NTDDI_WS03SP1)
james@965 762 status = KeInitializeCrashDumpHeader(DUMP_TYPE_FULL, 0, NULL, 0, &dump_header_size);
james@987 763 /* try and allocate contiguous memory as low as possible */
james@987 764 dump_header = NULL;
james@987 765 dump_header_mem_max.QuadPart = 0xFFFFF;
james@987 766 while (!dump_header && dump_header_mem_max.QuadPart != 0xFFFFFFFFFFFFFFFF) {
james@987 767 dump_header = MmAllocateContiguousMemory(DUMP_HEADER_PREFIX_SIZE + dump_header_size + DUMP_HEADER_SUFFIX_SIZE, dump_header_mem_max);
james@987 768 dump_header_mem_max.QuadPart = (dump_header_mem_max.QuadPart << 8) | 0xF;
james@987 769 }
james@987 770 if (dump_header) {
james@987 771 status = KeInitializeCrashDumpHeader(DUMP_TYPE_FULL, 0, dump_header + DUMP_HEADER_PREFIX_SIZE, dump_header_size, &dump_header_size);
james@987 772 FUNCTION_MSG("KeInitializeCrashDumpHeader status = %08x, size = %d\n", status, dump_header_size);
james@987 773 memcpy(dump_header + 0, "XENXEN", 6); /* magic number */
james@987 774 *(PUSHORT)(dump_header + 6) = (USHORT)(INT_PTR)dump_header & (PAGE_SIZE - 1); /* store offset too as additional verification */
james@987 775 memcpy(dump_header + DUMP_HEADER_PREFIX_SIZE + dump_header_size, "XENXEN", 6);
james@987 776 *(PUSHORT)(dump_header + DUMP_HEADER_PREFIX_SIZE + dump_header_size + 6) = (USHORT)(INT_PTR)dump_header & (PAGE_SIZE - 1); /* store offset too as additional verification */
james@987 777 KeInitializeCallbackRecord(&callback_record);
james@987 778 KeRegisterBugCheckReasonCallback(&callback_record, XenPci_DebugHeaderDumpIoCallback, KbCallbackDumpIo, (PUCHAR)"XenPci_DebugHeaderDumpIoCallback");
james@987 779 } else {
james@987 780 FUNCTION_MSG("Failed to allocate memory for crash dump header\n");
james@987 781 }
james@907 782 #endif
james@860 783
james@809 784 /* again after enabling DbgPrint hooking */
james@700 785 KdPrint((__DRIVER_NAME " " VER_FILEVERSION_STR "\n"));
james@666 786
james@860 787
james@809 788 WDF_DRIVER_CONFIG_INIT(&config, XenPci_EvtDeviceAdd);
james@809 789 config.EvtDriverUnload = XenPci_EvtDriverUnload;
james@809 790 status = WdfDriverCreate(DriverObject, RegistryPath, WDF_NO_OBJECT_ATTRIBUTES, &config, &driver);
james@809 791 if (!NT_SUCCESS(status))
james@809 792 {
james@809 793 KdPrint((__DRIVER_NAME " WdfDriverCreate failed with status 0x%x\n", status));
james@809 794 FUNCTION_EXIT();
james@809 795 #if DBG
james@809 796 XenPci_UnHookDbgPrint();
james@809 797 #endif
james@809 798 return status;
james@809 799 }
james@809 800 WDF_OBJECT_ATTRIBUTES_INIT(&parent_attributes);
james@809 801 parent_attributes.ParentObject = driver;
james@809 802
james@809 803 status = WdfDriverOpenParametersRegistryKey(driver, KEY_QUERY_VALUE, &parent_attributes, &param_key);
james@809 804 if (!NT_SUCCESS(status))
james@809 805 {
james@809 806 KdPrint(("Error opening parameters key %08x\n", status));
james@809 807 goto error;
james@809 808 }
james@638 809
james@638 810 status = AuxKlibInitialize();
james@638 811 if(!NT_SUCCESS(status))
james@638 812 {
james@809 813 KdPrint((__DRIVER_NAME " AuxKlibInitialize failed %08x\n", status));
james@809 814 goto error;
james@638 815 }
james@716 816
james@539 817 XenPci_FixLoadOrder();
james@533 818
james@809 819 RtlInitUnicodeString(&system_start_options, L"failed to read");
james@809 820 status = WdfRegistryOpenKey(NULL, &control_key_name, GENERIC_READ, &parent_attributes, &control_key);
james@809 821 if (NT_SUCCESS(status))
james@495 822 {
james@809 823 status = WdfStringCreate(NULL, &parent_attributes, &wdf_system_start_options);
james@809 824 status = WdfRegistryQueryString(control_key, &system_start_options_name, wdf_system_start_options);
james@809 825 if (NT_SUCCESS(status))
james@809 826 WdfStringGetUnicodeString(wdf_system_start_options, &system_start_options);
james@495 827 }
james@809 828 WdfRegistryClose(control_key);
james@495 829
james@908 830 KdPrint((__DRIVER_NAME " SystemStartOptions = %wZ\n", &system_start_options));
james@529 831
james@809 832 always_patch = 0;
james@809 833 WdfRegistryQueryULong(param_key, &txt_always_patch_name, &always_patch);
james@809 834 if (always_patch || (system_start_options.Buffer && wcsstr(system_start_options.Buffer, L"PATCHTPR")))
james@529 835 {
james@809 836 DECLARE_CONST_UNICODE_STRING(verifier_key_name, L"\\Registry\\Machine\\System\\CurrentControlSet\\Control\\Session Manager\\Memory Management");
james@638 837 WDFKEY memory_key;
james@638 838 ULONG verifier_value;
james@638 839
james@529 840 KdPrint((__DRIVER_NAME " PATCHTPR found\n"));
james@638 841
james@809 842 tpr_patch_requested = TRUE;
james@809 843 status = WdfRegistryOpenKey(NULL, &verifier_key_name, KEY_READ, &parent_attributes, &memory_key);
james@809 844 if (NT_SUCCESS(status))
james@638 845 {
james@809 846 DECLARE_CONST_UNICODE_STRING(verifier_value_name, L"VerifyDriverLevel");
james@638 847 status = WdfRegistryQueryULong(memory_key, &verifier_value_name, &verifier_value);
james@638 848 if (NT_SUCCESS(status) && verifier_value != 0)
james@638 849 {
james@638 850 KdPrint((__DRIVER_NAME " Verifier active - not patching\n"));
james@809 851 tpr_patch_requested = FALSE;
james@638 852 }
james@638 853 WdfRegistryClose(memory_key);
james@638 854 }
james@529 855 }
james@747 856
james@809 857 WdfCollectionCreate(&parent_attributes, &qemu_hide_devices);
james@809 858 WdfRegistryQueryULong(param_key, &txt_always_hide_name, &always_hide);
james@809 859 conf_info = IoGetConfigurationInformation();
james@809 860 if (always_hide || ((conf_info == NULL || conf_info->DiskCount == 0)
james@809 861 && !(system_start_options.Buffer && wcsstr(system_start_options.Buffer, L"NOGPLPV"))
james@809 862 && !*InitSafeBootMode))
james@495 863 {
james@809 864 if (!(system_start_options.Buffer && wcsstr(system_start_options.Buffer, L"GPLPVUSEFILTERHIDE")) && XenPci_CheckHideQemuDevices())
james@747 865 {
james@809 866 DECLARE_CONST_UNICODE_STRING(qemu_hide_flags_name, L"qemu_hide_flags");
james@809 867 DECLARE_CONST_UNICODE_STRING(txt_qemu_hide_flags_name, L"txt_qemu_hide_flags");
james@809 868 WDFCOLLECTION qemu_hide_flags;
james@809 869 ULONG i;
james@809 870
james@809 871 WdfCollectionCreate(&parent_attributes, &qemu_hide_flags);
james@809 872 WdfRegistryQueryMultiString(param_key, &qemu_hide_flags_name, &parent_attributes, qemu_hide_flags);
james@809 873 WdfRegistryQueryMultiString(param_key, &txt_qemu_hide_flags_name, &parent_attributes, qemu_hide_flags);
james@809 874 for (i = 0; i < WdfCollectionGetCount(qemu_hide_flags); i++)
james@747 875 {
james@809 876 ULONG value;
james@809 877 WDFSTRING wdf_string = WdfCollectionGetItem(qemu_hide_flags, i);
james@809 878 UNICODE_STRING unicode_string;
james@809 879 WdfStringGetUnicodeString(wdf_string, &unicode_string);
james@809 880 status = RtlUnicodeStringToInteger(&unicode_string, 0, &value);
james@809 881 qemu_hide_flags_value |= value;
james@747 882 }
james@809 883 WdfObjectDelete(qemu_hide_flags);
james@809 884 XenPci_HideQemuDevices();
james@809 885 }
james@809 886 else
james@809 887 {
james@809 888 WdfRegistryQueryMultiString(param_key, &hide_devices_name, &parent_attributes, qemu_hide_devices);
james@747 889 }
james@793 890 }
james@809 891 WdfRegistryClose(param_key);
james@809 892 FUNCTION_EXIT();
james@809 893 return STATUS_SUCCESS;
james@536 894
james@809 895 error:
james@809 896 #if DBG
james@809 897 XenPci_UnHookDbgPrint();
james@809 898 #endif
james@809 899 KdPrint(("Failed, returning %08x\n", status));
andy@398 900 FUNCTION_EXIT();
james@809 901 return status;
andy@324 902 }