win-pvdrivers

view xenconfig/xenconfig.c @ 947:a05b13795cb2

storport calls StartIo even when the adapter fails to initialise. Make sure this doesn't crash.
author James Harper <james.harper@bendigoit.com.au>
date Mon Aug 22 23:14:01 2011 +1000 (2011-08-22)
parents 0c0efefd40f4
children
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 #include "xenconfig.h"
21 #include <stdlib.h>
23 DRIVER_INITIALIZE DriverEntry;
24 static NTSTATUS
25 XenConfig_AddDevice(PDRIVER_OBJECT DriverObject, PDEVICE_OBJECT PhysicalDeviceObject);
26 static NTSTATUS
27 XenConfig_Pass(PDEVICE_OBJECT DeviceObject, PIRP Irp);
28 static NTSTATUS
29 XenConfig_Pnp(PDEVICE_OBJECT DeviceObject, PIRP Irp);
30 static NTSTATUS
31 XenConfig_AddDevice();
32 //static NTSTATUS
33 //XenConfig_Unload();
35 #ifdef ALLOC_PRAGMA
36 #pragma alloc_text (INIT, DriverEntry)
37 #pragma alloc_text (PAGE, XenConfig_AddDevice)
38 #endif
40 static BOOLEAN gplpv;
42 static NTSTATUS
43 XenConfig_Power(PDEVICE_OBJECT device_object, PIRP irp)
44 {
45 NTSTATUS status;
46 PXENCONFIG_DEVICE_DATA xcdd = device_object->DeviceExtension;
48 PoStartNextPowerIrp(irp);
49 IoSkipCurrentIrpStackLocation(irp);
50 status = PoCallDriver(xcdd->lower_do, irp);
51 return status;
52 }
54 NTSTATUS
55 DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath)
56 {
57 NTSTATUS status = STATUS_SUCCESS;
58 int i;
60 UNREFERENCED_PARAMETER(RegistryPath);
62 KdPrint((__DRIVER_NAME " --> DriverEntry\n"));
64 for (i = 0; i <= IRP_MJ_MAXIMUM_FUNCTION; i++)
65 DriverObject->MajorFunction[i] = XenConfig_Pass;
66 DriverObject->MajorFunction[IRP_MJ_PNP] = XenConfig_Pnp;
67 DriverObject->MajorFunction[IRP_MJ_POWER] = XenConfig_Power;
68 DriverObject->DriverExtension->AddDevice = XenConfig_AddDevice;
70 KdPrint((__DRIVER_NAME " <-- DriverEntry\n"));
72 return status;
73 }
75 static NTSTATUS
76 XenConfig_AddDevice(
77 PDRIVER_OBJECT DriverObject,
78 PDEVICE_OBJECT PhysicalDeviceObject
79 )
80 {
81 NTSTATUS status;
82 PDEVICE_OBJECT device_object = NULL;
83 PXENCONFIG_DEVICE_DATA xcdd;
85 KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
87 status = IoCreateDevice (DriverObject,
88 sizeof(XENCONFIG_DEVICE_DATA),
89 NULL,
90 FILE_DEVICE_UNKNOWN,
91 FILE_DEVICE_SECURE_OPEN,
92 FALSE,
93 &device_object);
95 xcdd = (PXENCONFIG_DEVICE_DATA)device_object->DeviceExtension;
97 xcdd->pdo = PhysicalDeviceObject;
98 xcdd->lower_do = IoAttachDeviceToDeviceStack(
99 device_object, PhysicalDeviceObject);
100 device_object->Flags |= xcdd->lower_do->Flags;
102 device_object->DeviceType = xcdd->lower_do->DeviceType;
104 device_object->Characteristics =
105 xcdd->lower_do->Characteristics;
107 xcdd->filter_do = device_object;
109 device_object->Flags &= ~DO_DEVICE_INITIALIZING;
111 KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
113 return STATUS_SUCCESS;
114 }
116 static NTSTATUS
117 XenConfig_Pass(PDEVICE_OBJECT DeviceObject, PIRP Irp)
118 {
119 PXENCONFIG_DEVICE_DATA xcdd = (PXENCONFIG_DEVICE_DATA)DeviceObject->DeviceExtension;
120 NTSTATUS status;
122 IoSkipCurrentIrpStackLocation(Irp);
123 status = IoCallDriver(xcdd->lower_do, Irp);
124 return status;
125 }
127 static NTSTATUS
128 XenConfig_Pnp_IoCompletion(PDEVICE_OBJECT device_object, PIRP irp, PVOID context)
129 {
130 PKEVENT event = (PKEVENT)context;
132 UNREFERENCED_PARAMETER(device_object);
134 // KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
136 if (irp->PendingReturned)
137 {
138 KeSetEvent(event, IO_NO_INCREMENT, FALSE);
139 }
141 // KdPrint((__DRIVER_NAME " <-- " __FUNCTION__"\n"));
143 return STATUS_MORE_PROCESSING_REQUIRED;
144 }
146 static NTSTATUS
147 XenConfig_SendAndWaitForIrp(PDEVICE_OBJECT device_object, PIRP irp)
148 {
149 NTSTATUS status;
150 PXENCONFIG_DEVICE_DATA xcdd = (PXENCONFIG_DEVICE_DATA)device_object->DeviceExtension;
151 KEVENT event;
153 UNREFERENCED_PARAMETER(device_object);
155 // KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
157 KeInitializeEvent(&event, NotificationEvent, FALSE);
159 IoCopyCurrentIrpStackLocationToNext(irp);
160 IoSetCompletionRoutine(irp, XenConfig_Pnp_IoCompletion, &event, TRUE, TRUE, TRUE);
162 status = IoCallDriver(xcdd->lower_do, irp);
164 if (status == STATUS_PENDING)
165 {
166 // KdPrint((__DRIVER_NAME " waiting ...\n"));
167 KeWaitForSingleObject(&event, Executive, KernelMode, FALSE, NULL);
168 // KdPrint((__DRIVER_NAME " ... done\n"));
169 status = irp->IoStatus.Status;
170 }
172 // KdPrint((__DRIVER_NAME " <-- " __FUNCTION__"\n"));
174 return status;
175 }
177 static VOID
178 XenConfig_Pnp_StartDeviceCallback(PDEVICE_OBJECT device_object, PVOID context)
179 {
180 NTSTATUS status = STATUS_SUCCESS;
181 //PXENCONFIG_DEVICE_DATA xcdd = device_object->DeviceExtension;
182 PIRP irp = context;
184 UNREFERENCED_PARAMETER(device_object);
186 KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
188 irp->IoStatus.Status = status;
190 IoCompleteRequest(irp, IO_NO_INCREMENT);
192 KdPrint((__DRIVER_NAME " <-- " __FUNCTION__"\n"));
193 }
195 static PMDL
196 XenConfig_MakeConfigPage(PDEVICE_OBJECT device_object)
197 {
198 NTSTATUS status;
199 PXENCONFIG_DEVICE_DATA xcdd = (PXENCONFIG_DEVICE_DATA)device_object->DeviceExtension;
200 HANDLE hwkey_handle, xenkey_handle, confkey_handle;
201 ULONG length;
202 PKEY_BASIC_INFORMATION key_info;
203 PKEY_VALUE_PARTIAL_INFORMATION type_info;
204 PKEY_VALUE_PARTIAL_INFORMATION value_info;
205 UNICODE_STRING xenkey_name, confkey_name;
206 UNICODE_STRING type_name, value_name;
207 UNICODE_STRING tmp_unicode_string;
208 //UNICODE_STRING typekey_value, valuekey_value;
209 //UNICODE_STRING value_value;
210 OBJECT_ATTRIBUTES oa;
211 ULONG info_length = 1000;
212 PMDL mdl;
213 UCHAR type;
214 ANSI_STRING setting;
215 ANSI_STRING value;
216 PUCHAR ptr;
217 int i;
219 mdl = AllocateUncachedPage();
220 ptr = MmGetMdlVirtualAddress(mdl);
222 status = IoOpenDeviceRegistryKey(xcdd->pdo, PLUGPLAY_REGKEY_DEVICE, KEY_READ, &hwkey_handle);
224 if (!NT_SUCCESS(status))
225 {
226 KdPrint((__DRIVER_NAME " cannot get hardware key\n"));
227 ADD_XEN_INIT_REQ(&ptr, XEN_INIT_TYPE_END, NULL, NULL);
228 return mdl;
229 }
230 RtlInitUnicodeString(&xenkey_name, L"XenConfig");
231 InitializeObjectAttributes(&oa, &xenkey_name, 0, hwkey_handle, NULL);
232 status = ZwOpenKey(&xenkey_handle, KEY_READ, &oa);
233 if (!NT_SUCCESS(status))
234 {
235 // close key_handle
236 KdPrint((__DRIVER_NAME " cannot get XenConfig key\n"));
237 ADD_XEN_INIT_REQ(&ptr, XEN_INIT_TYPE_END, NULL, NULL);
238 return mdl;
239 }
240 // XenConfig key exists, so we go ahead and make fake memory resources
241 RtlInitUnicodeString(&type_name, L"type");
242 RtlInitUnicodeString(&value_name, L"value");
243 key_info = ExAllocatePoolWithTag(PagedPool, info_length, XENCONFIG_POOL_TAG);
244 type_info = ExAllocatePoolWithTag(PagedPool, info_length, XENCONFIG_POOL_TAG);
245 value_info = ExAllocatePoolWithTag(PagedPool, info_length, XENCONFIG_POOL_TAG);
246 //value.Buffer = ExAllocatePoolWithTag(PagedPool, info_length, XENCONFIG_POOL_TAG);
247 //value.MaximumLength = info_length;
248 setting.Buffer = ExAllocatePoolWithTag(PagedPool, info_length, XENCONFIG_POOL_TAG);
249 setting.MaximumLength = (USHORT)info_length;
251 ADD_XEN_INIT_REQ(&ptr, XEN_INIT_TYPE_RUN, NULL, NULL);
252 for (i = 0; ZwEnumerateKey(xenkey_handle, i, KeyBasicInformation, key_info, info_length, &length) == STATUS_SUCCESS; i++)
253 {
254 confkey_name.Length = (USHORT)key_info->NameLength;
255 confkey_name.MaximumLength = (USHORT)key_info->NameLength;
256 confkey_name.Buffer = key_info->Name;
257 RtlUnicodeStringToAnsiString(&setting, &confkey_name, FALSE);
258 setting.Buffer[setting.Length] = 0;
259 KdPrint((__DRIVER_NAME " config key name = '%wZ'\n", &confkey_name));
260 InitializeObjectAttributes(&oa, &confkey_name, 0, xenkey_handle, NULL);
261 status = ZwOpenKey(&confkey_handle, KEY_READ, &oa);
262 if (!NT_SUCCESS(status))
263 {
264 KdPrint((__DRIVER_NAME " cannot get handle for XenConfig\\%wZ\n", &confkey_name));
265 continue;
266 }
268 status = ZwQueryValueKey(confkey_handle, &type_name, KeyValuePartialInformation, type_info, info_length, &length);
269 // make sure type is dword
270 type = (UCHAR)*(ULONG *)type_info->Data;
271 status = ZwQueryValueKey(confkey_handle, &value_name, KeyValuePartialInformation, value_info, info_length, &length);
272 if (!NT_SUCCESS(status))
273 {
274 ADD_XEN_INIT_REQ(&ptr, type, setting.Buffer, NULL);
275 }
276 else
277 {
278 switch(value_info->Type)
279 {
280 case REG_DWORD:
281 ADD_XEN_INIT_REQ(&ptr, type, setting.Buffer, UlongToPtr(*(PULONG)value_info->Data));
282 break;
284 case REG_SZ:
285 tmp_unicode_string.Length = (USHORT)value_info->DataLength;
286 tmp_unicode_string.MaximumLength = (USHORT)value_info->DataLength;
287 tmp_unicode_string.Buffer = (PWCHAR)value_info->Data;
288 RtlUnicodeStringToAnsiString(&value, &tmp_unicode_string, FALSE);
289 value.Buffer[value.Length] = 0;
290 ADD_XEN_INIT_REQ(&ptr, type, setting.Buffer, value.Buffer);
291 break;
293 default:
294 // report error here
295 break;
296 }
297 }
298 }
299 ADD_XEN_INIT_REQ(&ptr, XEN_INIT_TYPE_END, NULL, NULL);
301 ExFreePoolWithTag(key_info, XENCONFIG_POOL_TAG);
303 return mdl;
304 }
306 static NTSTATUS
307 XenConfig_QueueWorkItem(PDEVICE_OBJECT device_object, PIO_WORKITEM_ROUTINE routine, PVOID context)
308 {
309 PIO_WORKITEM work_item;
310 NTSTATUS status = STATUS_SUCCESS;
312 work_item = IoAllocateWorkItem(device_object);
313 IoQueueWorkItem(work_item, routine, DelayedWorkQueue, context);
315 return status;
316 }
318 static NTSTATUS
319 XenConfig_Pnp_StartDevice(PDEVICE_OBJECT device_object, PIRP irp)
320 {
321 NTSTATUS status;
322 //PXENCONFIG_DEVICE_DATA xcdd = (PXENCONFIG_DEVICE_DATA)device_object->DeviceExtension;
323 PIO_STACK_LOCATION stack;
324 PMDL mdl;
325 PCM_RESOURCE_LIST old_crl, new_crl;
326 PCM_PARTIAL_RESOURCE_LIST prl;
327 PCM_PARTIAL_RESOURCE_DESCRIPTOR prd;
328 ULONG old_length, new_length;
330 UNREFERENCED_PARAMETER(device_object);
332 KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
334 stack = IoGetCurrentIrpStackLocation(irp);
336 if ((mdl = XenConfig_MakeConfigPage(device_object)) != NULL)
337 {
338 old_crl = stack->Parameters.StartDevice.AllocatedResourcesTranslated;
339 old_length = FIELD_OFFSET(CM_RESOURCE_LIST, List) +
340 FIELD_OFFSET(CM_FULL_RESOURCE_DESCRIPTOR, PartialResourceList) +
341 FIELD_OFFSET(CM_PARTIAL_RESOURCE_LIST, PartialDescriptors) +
342 sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR) * old_crl->List[0].PartialResourceList.Count;
343 new_length = old_length + sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR) * 1;
344 new_crl = ExAllocatePoolWithTag(PagedPool, new_length, XENCONFIG_POOL_TAG);
345 memcpy(new_crl, old_crl, old_length);
346 prl = &new_crl->List[0].PartialResourceList;
347 prd = &prl->PartialDescriptors[prl->Count++];
348 prd->Type = CmResourceTypeMemory;
349 prd->ShareDisposition = CmResourceShareDeviceExclusive;
350 prd->Flags = CM_RESOURCE_MEMORY_READ_WRITE;
351 KdPrint((__DRIVER_NAME " PFN[0] = %p\n", MmGetMdlPfnArray(mdl)[0]));
352 prd->u.Memory.Start.QuadPart = ((ULONGLONG)MmGetMdlPfnArray(mdl)[0]) << PAGE_SHIFT;
353 prd->u.Memory.Length = PAGE_SIZE;
354 KdPrint((__DRIVER_NAME " Start = %08x:%08x, Length = %d\n", prd->u.Memory.Start.HighPart, prd->u.Memory.Start.LowPart, prd->u.Memory.Length));
355 stack->Parameters.StartDevice.AllocatedResourcesTranslated = new_crl;
357 old_crl = stack->Parameters.StartDevice.AllocatedResources;
358 new_crl = ExAllocatePoolWithTag(PagedPool, new_length, XENCONFIG_POOL_TAG);
359 memcpy(new_crl, old_crl, old_length);
360 prl = &new_crl->List[0].PartialResourceList;
361 prd = &prl->PartialDescriptors[prl->Count++];
362 prd->Type = CmResourceTypeMemory;
363 prd->ShareDisposition = CmResourceShareDeviceExclusive;
364 prd->Flags = CM_RESOURCE_MEMORY_READ_WRITE;
365 prd->u.Memory.Start.QuadPart = (ULONGLONG)MmGetMdlPfnArray(mdl)[0] << PAGE_SHIFT;
366 prd->u.Memory.Length = PAGE_SIZE;
367 stack->Parameters.StartDevice.AllocatedResources = new_crl;
369 // free the original resource lists???
370 }
372 IoMarkIrpPending(irp);
373 status = XenConfig_SendAndWaitForIrp(device_object, irp);
375 XenConfig_QueueWorkItem(device_object, XenConfig_Pnp_StartDeviceCallback, irp);
377 KdPrint((__DRIVER_NAME " <-- " __FUNCTION__"\n"));
379 return STATUS_PENDING;
380 }
382 static NTSTATUS
383 XenConfig_Pnp(PDEVICE_OBJECT device_object, PIRP irp)
384 {
385 NTSTATUS status = STATUS_SUCCESS;
386 PIO_STACK_LOCATION stack;
387 PXENCONFIG_DEVICE_DATA xcdd = (PXENCONFIG_DEVICE_DATA)device_object->DeviceExtension;
389 // KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
391 stack = IoGetCurrentIrpStackLocation(irp);
393 switch (stack->MinorFunction) {
394 #if 0
395 case IRP_MN_START_DEVICE:
396 return XenConfig_Pnp_StartDevice(device_object, irp);
397 case IRP_MN_QUERY_CAPABILITIES:
398 // KdPrint((__DRIVER_NAME " IRP_MN_QUERY_CAPABILITIES\n"));
399 stack->Parameters.DeviceCapabilities.Capabilities->NoDisplayInUI = 1;
400 status = XenConfig_SendAndWaitForIrp(device_object, irp);
401 status = irp->IoStatus.Status = STATUS_SUCCESS;
402 IoCompleteRequest(irp, IO_NO_INCREMENT);
403 // KdPrint((__DRIVER_NAME " <-- " __FUNCTION__"\n"));
404 return status;
405 #endif
406 default:
407 IoSkipCurrentIrpStackLocation(irp);
408 status = IoCallDriver(xcdd->lower_do, irp);
409 break;
410 }
412 // KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ " (returning with status %08x)\n", status));
414 return status;
415 }