From c39f81bb1b221da238502adb942f57979510454f Mon Sep 17 00:00:00 2001 From: Eric Weddington Date: Mon, 24 Feb 2003 17:56:42 +0000 Subject: [PATCH] Add giveio device driver source. Requires MS DDK to build. git-svn-id: svn://svn.savannah.nongnu.org/avrdude/trunk@228 81a1dc3b-b13d-400b-aceb-764788c761c2 --- avrdude/windows/giveio.c | 168 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 168 insertions(+) create mode 100644 avrdude/windows/giveio.c diff --git a/avrdude/windows/giveio.c b/avrdude/windows/giveio.c new file mode 100644 index 00000000..f752a293 --- /dev/null +++ b/avrdude/windows/giveio.c @@ -0,0 +1,168 @@ +/********************************************************************* + +Author: Dale Roberts +Date: 8/30/95 +Program: GIVEIO.SYS +Compile: Use DDK BUILD facility + +Purpose: Give direct port I/O access to a user mode process. + +*********************************************************************/ +#include + +/* + * The name of our device driver. + */ +#define DEVICE_NAME_STRING L"giveio" + +/* + * This is the "structure" of the IOPM. It is just a simple + * character array of length 0x2000. + * + * This holds 8K * 8 bits -> 64K bits of the IOPM, which maps the + * entire 64K I/O space of the x86 processor. Any 0 bits will give + * access to the corresponding port for user mode processes. Any 1 + * bits will disallow I/O access to the corresponding port. + */ +#define IOPM_SIZE 0x2000 +typedef UCHAR IOPM[IOPM_SIZE]; + +/* + * This will hold simply an array of 0's which will be copied + * into our actual IOPM in the TSS by Ke386SetIoAccessMap(). + * The memory is allocated at driver load time. + */ +IOPM *IOPM_local = 0; + +/* + * These are the two undocumented calls that we will use to give + * the calling process I/O access. + * + * Ke386IoSetAccessMap() copies the passed map to the TSS. + * + * Ke386IoSetAccessProcess() adjusts the IOPM offset pointer so that + * the newly copied map is actually used. Otherwise, the IOPM offset + * points beyond the end of the TSS segment limit, causing any I/O + * access by the user mode process to generate an exception. + */ +void Ke386SetIoAccessMap(int, IOPM *); +void Ke386QueryIoAccessMap(int, IOPM *); +void Ke386IoSetAccessProcess(PEPROCESS, int); + +/********************************************************************* + Release any allocated objects. +*********************************************************************/ +VOID GiveioUnload(IN PDRIVER_OBJECT DriverObject) +{ + WCHAR DOSNameBuffer[] = L"\\DosDevices\\" DEVICE_NAME_STRING; + UNICODE_STRING uniDOSString; + + if(IOPM_local) + MmFreeNonCachedMemory(IOPM_local, sizeof(IOPM)); + + RtlInitUnicodeString(&uniDOSString, DOSNameBuffer); + IoDeleteSymbolicLink (&uniDOSString); + IoDeleteDevice(DriverObject->DeviceObject); +} + +/********************************************************************* + Set the IOPM (I/O permission map) of the calling process so that it +is given full I/O access. Our IOPM_local[] array is all zeros, so +the IOPM will be all zeros. If OnFlag is 1, the process is given I/O +access. If it is 0, access is removed. +*********************************************************************/ +VOID SetIOPermissionMap(int OnFlag) +{ + Ke386IoSetAccessProcess(PsGetCurrentProcess(), OnFlag); + Ke386SetIoAccessMap(1, IOPM_local); +} + +void GiveIO(void) +{ + SetIOPermissionMap(1); +} + +/********************************************************************* + Service handler for a CreateFile() user mode call. + + This routine is entered in the driver object function call table by +the DriverEntry() routine. When the user mode application calls +CreateFile(), this routine gets called while still in the context of +the user mode application, but with the CPL (the processor's Current +Privelege Level) set to 0. This allows us to do kernel mode +operations. GiveIO() is called to give the calling process I/O +access. All the user mode application needs do to obtain I/O access +is open this device with CreateFile(). No other operations are +required. +*********************************************************************/ +NTSTATUS GiveioCreateDispatch( + IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp + ) +{ + GiveIO(); // give the calling process I/O access + + Irp->IoStatus.Information = 0; + Irp->IoStatus.Status = STATUS_SUCCESS; + IoCompleteRequest(Irp, IO_NO_INCREMENT); + return STATUS_SUCCESS; +} + +/********************************************************************* + Driver Entry routine. + + This routine is called only once after the driver is initially +loaded into memory. It allocates everything necessary for the +driver's operation. In our case, it allocates memory for our IOPM +array, and creates a device which user mode applications can open. +It also creates a symbolic link to the device driver. This allows +a user mode application to access our driver using the \\.\giveio +notation. +*********************************************************************/ +NTSTATUS DriverEntry( + IN PDRIVER_OBJECT DriverObject, + IN PUNICODE_STRING RegistryPath + ) +{ + PDEVICE_OBJECT deviceObject; + NTSTATUS status; + WCHAR NameBuffer[] = L"\\Device\\" DEVICE_NAME_STRING; + WCHAR DOSNameBuffer[] = L"\\DosDevices\\" DEVICE_NAME_STRING; + UNICODE_STRING uniNameString, uniDOSString; + + // + // Allocate a buffer for the local IOPM and zero it. + // + IOPM_local = MmAllocateNonCachedMemory(sizeof(IOPM)); + if(IOPM_local == 0) + return STATUS_INSUFFICIENT_RESOURCES; + RtlZeroMemory(IOPM_local, sizeof(IOPM)); + + // + // Set up device driver name and device object. + // + RtlInitUnicodeString(&uniNameString, NameBuffer); + RtlInitUnicodeString(&uniDOSString, DOSNameBuffer); + + status = IoCreateDevice(DriverObject, 0, + &uniNameString, + FILE_DEVICE_UNKNOWN, + 0, FALSE, &deviceObject); + + if(!NT_SUCCESS(status)) + return status; + + status = IoCreateSymbolicLink (&uniDOSString, &uniNameString); + + if (!NT_SUCCESS(status)) + return status; + + // + // Initialize the Driver Object with driver's entry points. + // All we require are the Create and Unload operations. + // + DriverObject->MajorFunction[IRP_MJ_CREATE] = GiveioCreateDispatch; + DriverObject->DriverUnload = GiveioUnload; + return STATUS_SUCCESS; +} +