win-pvdrivers

view xenconfig/xenconfig.c @ 310:60372bd2582d

First cut of putting xenbus config details in the .inf file - xenvbd may yet pass WHQL
author James Harper <james.harper@bendigoit.com.au>
date Fri Jun 13 14:16:50 2008 +1000 (2008-06-13)
parents
children bb891f6d10e4
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 NTSTATUS
43 DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath)
44 {
45 NTSTATUS status = STATUS_SUCCESS;
46 int i;
48 UNREFERENCED_PARAMETER(RegistryPath);
50 KdPrint((__DRIVER_NAME " --> DriverEntry\n"));
52 for (i = 0; i <= IRP_MJ_MAXIMUM_FUNCTION; i++)
53 DriverObject->MajorFunction[i] = XenConfig_Pass;
54 DriverObject->MajorFunction[IRP_MJ_PNP] = XenConfig_Pnp;
55 DriverObject->DriverExtension->AddDevice = XenConfig_AddDevice;
57 KdPrint((__DRIVER_NAME " <-- DriverEntry\n"));
59 return status;
60 }
62 static NTSTATUS
63 XenConfig_AddDevice(
64 PDRIVER_OBJECT DriverObject,
65 PDEVICE_OBJECT PhysicalDeviceObject
66 )
67 {
68 NTSTATUS status;
69 PDEVICE_OBJECT device_object = NULL;
70 PXENCONFIG_DEVICE_DATA xcdd;
72 KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
74 status = IoCreateDevice (DriverObject,
75 sizeof(XENCONFIG_DEVICE_DATA),
76 NULL,
77 FILE_DEVICE_UNKNOWN,
78 FILE_DEVICE_SECURE_OPEN,
79 FALSE,
80 &device_object);
82 xcdd = (PXENCONFIG_DEVICE_DATA)device_object->DeviceExtension;
84 xcdd->pdo = PhysicalDeviceObject;
85 xcdd->lower_do = IoAttachDeviceToDeviceStack(
86 device_object, PhysicalDeviceObject);
87 device_object->Flags |= xcdd->lower_do->Flags;
89 device_object->DeviceType = xcdd->lower_do->DeviceType;
91 device_object->Characteristics =
92 xcdd->lower_do->Characteristics;
94 xcdd->filter_do = device_object;
96 device_object->Flags &= ~DO_DEVICE_INITIALIZING;
98 KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
100 return STATUS_SUCCESS;
101 }
103 static NTSTATUS
104 XenConfig_Pass(PDEVICE_OBJECT DeviceObject, PIRP Irp)
105 {
106 PXENCONFIG_DEVICE_DATA xcdd = (PXENCONFIG_DEVICE_DATA)DeviceObject->DeviceExtension;
107 NTSTATUS status;
109 IoSkipCurrentIrpStackLocation(Irp);
110 status = IoCallDriver(xcdd->lower_do, Irp);
111 return status;
112 }
114 static NTSTATUS
115 XenConfig_Pnp_IoCompletion(PDEVICE_OBJECT device_object, PIRP irp, PVOID context)
116 {
117 PKEVENT event = (PKEVENT)context;
119 UNREFERENCED_PARAMETER(device_object);
121 // KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
123 if (irp->PendingReturned)
124 {
125 KeSetEvent(event, IO_NO_INCREMENT, FALSE);
126 }
128 // KdPrint((__DRIVER_NAME " <-- " __FUNCTION__"\n"));
130 return STATUS_MORE_PROCESSING_REQUIRED;
131 }
133 static NTSTATUS
134 XenConfig_SendAndWaitForIrp(PDEVICE_OBJECT device_object, PIRP irp)
135 {
136 NTSTATUS status;
137 PXENCONFIG_DEVICE_DATA xcdd = (PXENCONFIG_DEVICE_DATA)device_object->DeviceExtension;
138 KEVENT event;
140 UNREFERENCED_PARAMETER(device_object);
142 // KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
144 KeInitializeEvent(&event, NotificationEvent, FALSE);
146 IoCopyCurrentIrpStackLocationToNext(irp);
147 IoSetCompletionRoutine(irp, XenConfig_Pnp_IoCompletion, &event, TRUE, TRUE, TRUE);
149 status = IoCallDriver(xcdd->lower_do, irp);
151 if (status == STATUS_PENDING)
152 {
153 // KdPrint((__DRIVER_NAME " waiting ...\n"));
154 KeWaitForSingleObject(&event, Executive, KernelMode, FALSE, NULL);
155 // KdPrint((__DRIVER_NAME " ... done\n"));
156 status = irp->IoStatus.Status;
157 }
159 // KdPrint((__DRIVER_NAME " <-- " __FUNCTION__"\n"));
161 return status;
162 }
164 static VOID
165 XenConfig_Pnp_StartDeviceCallback(PDEVICE_OBJECT device_object, PVOID context)
166 {
167 NTSTATUS status = STATUS_SUCCESS;
168 PXENCONFIG_DEVICE_DATA xcdd = device_object->DeviceExtension;
169 PIRP irp = context;
171 KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
173 irp->IoStatus.Status = status;
175 IoCompleteRequest(irp, IO_NO_INCREMENT);
177 KdPrint((__DRIVER_NAME " <-- " __FUNCTION__"\n"));
178 }
180 static PMDL
181 XenConfig_MakeConfigPage(PDEVICE_OBJECT device_object)
182 {
183 NTSTATUS status;
184 PXENCONFIG_DEVICE_DATA xcdd = (PXENCONFIG_DEVICE_DATA)device_object->DeviceExtension;
185 HANDLE hwkey_handle, xenkey_handle, confkey_handle;
186 ULONG length;
187 PKEY_BASIC_INFORMATION key_info;
188 PKEY_VALUE_PARTIAL_INFORMATION type_info;
189 PKEY_VALUE_PARTIAL_INFORMATION value_info;
190 UNICODE_STRING xenkey_name, confkey_name;
191 UNICODE_STRING type_name, value_name;
192 UNICODE_STRING tmp_unicode_string;
193 //UNICODE_STRING typekey_value, valuekey_value;
194 //UNICODE_STRING value_value;
195 OBJECT_ATTRIBUTES oa;
196 ULONG info_length = 1000;
197 PMDL mdl;
198 UCHAR type;
199 ANSI_STRING setting;
200 ANSI_STRING value;
201 PUCHAR ptr;
202 int i;
204 status = IoOpenDeviceRegistryKey(xcdd->pdo, PLUGPLAY_REGKEY_DEVICE, KEY_READ, &hwkey_handle);
206 if (!NT_SUCCESS(status))
207 {
208 KdPrint((__DRIVER_NAME " cannot get hardware key\n"));
209 return NULL;
210 }
211 RtlInitUnicodeString(&xenkey_name, L"XenConfig");
212 InitializeObjectAttributes(&oa, &xenkey_name, 0, hwkey_handle, NULL);
213 status = ZwOpenKey(&xenkey_handle, KEY_READ, &oa);
214 if (!NT_SUCCESS(status))
215 {
216 // close key_handle
217 KdPrint((__DRIVER_NAME " cannot get XenConfig key\n"));
218 return NULL;
219 }
220 // XenConfig key exists, so we go ahead and make fake memory resources
221 mdl = AllocateUncachedPage();
222 ptr = MmGetMdlVirtualAddress(mdl);
223 RtlInitUnicodeString(&type_name, L"type");
224 RtlInitUnicodeString(&value_name, L"value");
225 key_info = ExAllocatePoolWithTag(PagedPool, info_length, XENCONFIG_POOL_TAG);
226 type_info = ExAllocatePoolWithTag(PagedPool, info_length, XENCONFIG_POOL_TAG);
227 value_info = ExAllocatePoolWithTag(PagedPool, info_length, XENCONFIG_POOL_TAG);
228 //value.Buffer = ExAllocatePoolWithTag(PagedPool, info_length, XENCONFIG_POOL_TAG);
229 //value.MaximumLength = info_length;
230 setting.Buffer = ExAllocatePoolWithTag(PagedPool, info_length, XENCONFIG_POOL_TAG);
231 setting.MaximumLength = (USHORT)info_length;
233 for (i = 0; ZwEnumerateKey(xenkey_handle, i, KeyBasicInformation, key_info, info_length, &length) == STATUS_SUCCESS; i++)
234 {
235 confkey_name.Length = (USHORT)key_info->NameLength;
236 confkey_name.MaximumLength = (USHORT)key_info->NameLength;
237 confkey_name.Buffer = key_info->Name;
238 RtlUnicodeStringToAnsiString(&setting, &confkey_name, FALSE);
239 setting.Buffer[setting.Length] = 0;
240 KdPrint((__DRIVER_NAME " config key name = '%wZ'\n", &confkey_name));
241 InitializeObjectAttributes(&oa, &confkey_name, 0, xenkey_handle, NULL);
242 status = ZwOpenKey(&confkey_handle, KEY_READ, &oa);
243 if (!NT_SUCCESS(status))
244 {
245 KdPrint((__DRIVER_NAME " cannot get handle for XenConfig\\%wZ\n", &confkey_name));
246 continue;
247 }
249 status = ZwQueryValueKey(confkey_handle, &type_name, KeyValuePartialInformation, type_info, info_length, &length);
250 // make sure type is dword
251 type = (UCHAR)*(ULONG *)type_info->Data;
252 status = ZwQueryValueKey(confkey_handle, &value_name, KeyValuePartialInformation, value_info, info_length, &length);
253 if (!NT_SUCCESS(status))
254 {
255 ADD_XEN_INIT_REQ(&ptr, type, setting.Buffer, NULL);
256 }
257 else
258 {
259 switch(value_info->Type)
260 {
261 case REG_DWORD:
262 ADD_XEN_INIT_REQ(&ptr, type, setting.Buffer, UlongToPtr(*(PULONG)value_info->Data));
263 break;
265 case REG_SZ:
266 tmp_unicode_string.Length = (USHORT)value_info->DataLength;
267 tmp_unicode_string.MaximumLength = (USHORT)value_info->DataLength;
268 tmp_unicode_string.Buffer = (PWCHAR)value_info->Data;
269 RtlUnicodeStringToAnsiString(&value, &tmp_unicode_string, FALSE);
270 value.Buffer[value.Length] = 0;
271 ADD_XEN_INIT_REQ(&ptr, type, setting.Buffer, value.Buffer);
272 break;
274 default:
275 // report error here
276 break;
277 }
278 }
279 }
280 ADD_XEN_INIT_REQ(&ptr, XEN_INIT_TYPE_END, NULL, NULL);
282 ExFreePoolWithTag(key_info, XENCONFIG_POOL_TAG);
284 return mdl;
285 }
287 static NTSTATUS
288 XenConfig_QueueWorkItem(PDEVICE_OBJECT device_object, PIO_WORKITEM_ROUTINE routine, PVOID context)
289 {
290 PIO_WORKITEM work_item;
291 NTSTATUS status = STATUS_SUCCESS;
293 work_item = IoAllocateWorkItem(device_object);
294 IoQueueWorkItem(work_item, routine, DelayedWorkQueue, context);
296 return status;
297 }
299 static NTSTATUS
300 XenConfig_Pnp_StartDevice(PDEVICE_OBJECT device_object, PIRP irp)
301 {
302 NTSTATUS status;
303 PXENCONFIG_DEVICE_DATA xcdd = (PXENCONFIG_DEVICE_DATA)device_object->DeviceExtension;
304 PIO_STACK_LOCATION stack;
305 PMDL mdl;
306 PCM_RESOURCE_LIST old_crl, new_crl;
307 PCM_PARTIAL_RESOURCE_LIST prl;
308 PCM_PARTIAL_RESOURCE_DESCRIPTOR prd;
309 ULONG old_length, new_length;
311 UNREFERENCED_PARAMETER(device_object);
313 KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
315 stack = IoGetCurrentIrpStackLocation(irp);
317 if ((mdl = XenConfig_MakeConfigPage(device_object)) != NULL)
318 {
319 old_crl = stack->Parameters.StartDevice.AllocatedResourcesTranslated;
320 old_length = FIELD_OFFSET(CM_RESOURCE_LIST, List) +
321 FIELD_OFFSET(CM_FULL_RESOURCE_DESCRIPTOR, PartialResourceList) +
322 FIELD_OFFSET(CM_PARTIAL_RESOURCE_LIST, PartialDescriptors) +
323 sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR) * old_crl->List[0].PartialResourceList.Count;
324 new_length = old_length + sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR) * 1;
325 new_crl = ExAllocatePoolWithTag(PagedPool, new_length, XENCONFIG_POOL_TAG);
326 memcpy(new_crl, old_crl, old_length);
327 prl = &new_crl->List[0].PartialResourceList;
328 prd = &prl->PartialDescriptors[prl->Count++];
329 prd->Type = CmResourceTypeMemory;
330 prd->ShareDisposition = CmResourceShareDeviceExclusive;
331 prd->Flags = CM_RESOURCE_MEMORY_READ_WRITE;
332 KdPrint((__DRIVER_NAME " PFN[0] = %p\n", MmGetMdlPfnArray(mdl)[0]));
333 prd->u.Memory.Start.QuadPart = MmGetMdlPfnArray(mdl)[0] << PAGE_SHIFT;
334 prd->u.Memory.Length = PAGE_SIZE;
335 KdPrint((__DRIVER_NAME " Start = %08x:%08x, Length = %d\n", prd->u.Memory.Start.HighPart, prd->u.Memory.Start.LowPart, prd->u.Memory.Length));
336 stack->Parameters.StartDevice.AllocatedResourcesTranslated = new_crl;
338 old_crl = stack->Parameters.StartDevice.AllocatedResources;
339 new_crl = ExAllocatePoolWithTag(PagedPool, new_length, XENCONFIG_POOL_TAG);
340 memcpy(new_crl, old_crl, old_length);
341 prl = &new_crl->List[0].PartialResourceList;
342 prd = &prl->PartialDescriptors[prl->Count++];
343 prd->Type = CmResourceTypeMemory;
344 prd->ShareDisposition = CmResourceShareDeviceExclusive;
345 prd->Flags = CM_RESOURCE_MEMORY_READ_WRITE;
346 prd->u.Memory.Start.QuadPart = MmGetMdlPfnArray(mdl)[0] << PAGE_SHIFT;
347 prd->u.Memory.Length = PAGE_SIZE;
348 stack->Parameters.StartDevice.AllocatedResources = new_crl;
350 // free the original resource lists???
351 }
353 IoMarkIrpPending(irp);
354 status = XenConfig_SendAndWaitForIrp(device_object, irp);
356 XenConfig_QueueWorkItem(device_object, XenConfig_Pnp_StartDeviceCallback, irp);
358 KdPrint((__DRIVER_NAME " <-- " __FUNCTION__"\n"));
360 return STATUS_PENDING;
361 }
363 static NTSTATUS
364 XenConfig_Pnp(PDEVICE_OBJECT device_object, PIRP irp)
365 {
366 NTSTATUS status = STATUS_SUCCESS;
367 PIO_STACK_LOCATION stack;
368 PXENCONFIG_DEVICE_DATA xcdd = (PXENCONFIG_DEVICE_DATA)device_object->DeviceExtension;
370 // KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
372 stack = IoGetCurrentIrpStackLocation(irp);
374 switch (stack->MinorFunction) {
375 case IRP_MN_START_DEVICE:
376 return XenConfig_Pnp_StartDevice(device_object, irp);
377 case IRP_MN_QUERY_CAPABILITIES:
378 // KdPrint((__DRIVER_NAME " IRP_MN_QUERY_CAPABILITIES\n"));
379 stack->Parameters.DeviceCapabilities.Capabilities->NoDisplayInUI = 1;
380 status = XenConfig_SendAndWaitForIrp(device_object, irp);
381 status = irp->IoStatus.Status = STATUS_SUCCESS;
382 IoCompleteRequest(irp, IO_NO_INCREMENT);
383 // KdPrint((__DRIVER_NAME " <-- " __FUNCTION__"\n"));
384 return status;
385 default:
386 IoSkipCurrentIrpStackLocation(irp);
387 status = IoCallDriver(xcdd->lower_do, irp);
388 break;
389 }
391 // KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ " (returning with status %08x)\n", status));
393 return status;
394 }