27 #include "intrinsics.h"
29 #define WIN32_NAME L"\\DosDevices\\Aken"
30 #define DEVICE_NAME L"\\Device\\Aken"
43 #pragma alloc_text(INIT, DriverEntry) // => discardable
44 #pragma code_seg(push, "PAGE")
85 static int IsMemoryUncacheable(DWORD64 physicalAddress64)
90 if(physicalAddress64 < 0x100000)
96 static NTSTATUS
AkenMapPhysicalMemory(
const DWORD64 physicalAddress64,
const DWORD64 numBytes64, DWORD64* virtualAddress64)
100 LARGE_INTEGER physicalAddress;
101 physicalAddress.QuadPart = physicalAddress64;
107 OBJECT_ATTRIBUTES objectAttributes;
108 UNICODE_STRING objectName = RTL_CONSTANT_STRING(L
"\\Device\\PhysicalMemory");
109 const ULONG attributes = OBJ_CASE_INSENSITIVE;
110 const HANDLE rootDirectory = 0;
111 InitializeObjectAttributes(&objectAttributes, &objectName, attributes, rootDirectory, (PSECURITY_DESCRIPTOR)0);
112 ntStatus = ZwOpenSection(&hMemory, SECTION_ALL_ACCESS, &objectAttributes);
113 if(!NT_SUCCESS(ntStatus))
115 KdPrint((
"AkenMapPhysicalMemory: ZwOpenSection failed\n"));
122 PVOID physicalMemorySection = NULL;
123 const POBJECT_TYPE objectType = 0;
124 ntStatus = ObReferenceObjectByHandle(hMemory, SECTION_ALL_ACCESS, objectType, KernelMode, &physicalMemorySection, 0);
125 if(!NT_SUCCESS(ntStatus))
127 KdPrint((
"AkenMapPhysicalMemory: ObReferenceObjectByHandle failed\n"));
139 PVOID virtualBaseAddress = 0;
140 const ULONG zeroBits = 0;
141 SIZE_T mappedSize = (SIZE_T)numBytes64;
142 LARGE_INTEGER physicalBaseAddress = physicalAddress;
143 const SECTION_INHERIT inheritDisposition = ViewShare;
144 const ULONG allocationType = 0;
145 ULONG protect = PAGE_READWRITE;
146 if(IsMemoryUncacheable(physicalAddress64))
147 protect |= PAGE_NOCACHE;
148 ntStatus = ZwMapViewOfSection(hMemory, hProcess, &virtualBaseAddress, zeroBits, mappedSize, &physicalBaseAddress, &mappedSize, inheritDisposition, allocationType, protect);
149 if(!NT_SUCCESS(ntStatus))
152 protect ^= PAGE_NOCACHE;
153 ntStatus = ZwMapViewOfSection(hMemory, hProcess, &virtualBaseAddress, zeroBits, mappedSize, &physicalBaseAddress, &mappedSize, inheritDisposition, allocationType, protect);
154 if(!NT_SUCCESS(ntStatus))
156 KdPrint((
"AkenMapPhysicalMemory: ZwMapViewOfSection failed\n"));
164 const DWORD32 numBytesRoundedDown = physicalAddress.LowPart - physicalBaseAddress.LowPart;
165 ASSERT(numBytesRoundedDown < 0x10000);
166 *virtualAddress64 = (DWORD64)virtualBaseAddress + numBytesRoundedDown;
170 ntStatus = STATUS_SUCCESS;
188 PVOID baseAddress = (PVOID)virtualAddress;
189 NTSTATUS ntStatus = ZwUnmapViewOfSection(hProcess, baseAddress);
190 if(!NT_SUCCESS(ntStatus))
192 KdPrint((
"AkenUnmapPhysicalMemory: ZwUnmapViewOfSection failed\n"));
197 return STATUS_SUCCESS;
212 return STATUS_BUFFER_TOO_SMALL;
217 const UCHAR numBytes = in->
numBytes;
221 value = (DWORD32)READ_PORT_UCHAR((PUCHAR)port);
224 value = (DWORD32)READ_PORT_USHORT((PUSHORT)port);
227 value = (DWORD32)READ_PORT_ULONG((PULONG)port);
230 return STATUS_INVALID_PARAMETER;
238 return STATUS_SUCCESS;
246 return STATUS_BUFFER_TOO_SMALL;
250 const DWORD32 value = in->
value;
252 const UCHAR numBytes = in->
numBytes;
256 WRITE_PORT_UCHAR((PUCHAR)port, (UCHAR)(value & 0xFF));
259 WRITE_PORT_USHORT((PUSHORT)port, (
USHORT)(value & 0xFFFF));
262 WRITE_PORT_ULONG((PULONG)port, value);
265 return STATUS_INVALID_PARAMETER;
269 return STATUS_SUCCESS;
273 static NTSTATUS
AkenIoctlMap(PVOID buf,
const ULONG inSize, ULONG* outSize)
275 DWORD64 virtualAddress;
281 return STATUS_BUFFER_TOO_SMALL;
286 const DWORD64 numBytes = in->
numBytes;
304 return STATUS_BUFFER_TOO_SMALL;
323 return STATUS_BUFFER_TOO_SMALL;
327 const DWORD64 reg = in->
reg;
328 value = __readmsr((
int)reg);
336 return STATUS_SUCCESS;
344 return STATUS_BUFFER_TOO_SMALL;
348 const DWORD64 reg = in->
reg;
349 const DWORD64 value = in->
value;
350 __writemsr((
unsigned long)reg, value);
353 return STATUS_SUCCESS;
363 return STATUS_BUFFER_TOO_SMALL;
367 const DWORD64 reg = in->
reg;
368 value = __readpmc((
unsigned long)reg);
376 return STATUS_SUCCESS;
384 KdPrint((
"AkenIoctlUnknown\n"));
387 return STATUS_INVALID_DEVICE_REQUEST;
391 typedef NTSTATUS (*
AkenIoctl)(PVOID buf, ULONG inSize, ULONG* outSize);
424 static NTSTATUS
AkenCreate(IN PDEVICE_OBJECT deviceObject, IN PIRP irp)
428 irp->IoStatus.Status = STATUS_SUCCESS;
429 irp->IoStatus.Information = 0;
430 IoCompleteRequest(irp, IO_NO_INCREMENT);
431 return STATUS_SUCCESS;
435 static NTSTATUS
AkenClose(IN PDEVICE_OBJECT deviceObject, IN PIRP irp)
440 irp->IoStatus.Status = STATUS_SUCCESS;
441 irp->IoStatus.Information = 0;
442 IoCompleteRequest(irp, IO_NO_INCREMENT);
443 return STATUS_SUCCESS;
454 PVOID buf = irp->AssociatedIrp.SystemBuffer;
455 PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation(irp);
456 ULONG ioctlCode = irpStack->Parameters.DeviceIoControl.IoControlCode;
457 const ULONG inSize = irpStack->Parameters.DeviceIoControl.InputBufferLength;
458 ULONG outSize = irpStack->Parameters.DeviceIoControl.OutputBufferLength;
461 const NTSTATUS ntStatus = akenIoctl(buf, inSize, &outSize);
463 irp->IoStatus.Information = outSize;
464 irp->IoStatus.Status = ntStatus;
465 IoCompleteRequest(irp, IO_NO_INCREMENT);
475 KdPrint((
"AkenUnload\n"));
478 UNICODE_STRING win32Name = RTL_CONSTANT_STRING(
WIN32_NAME);
479 IoDeleteSymbolicLink(&win32Name);
482 if(driverObject->DeviceObject)
483 IoDeleteDevice(driverObject->DeviceObject);
487 #pragma code_seg(pop) // make sure we don't countermand the alloc_text
489 NTSTATUS
DriverEntry(IN PDRIVER_OBJECT driverObject, IN PUNICODE_STRING registryPath)
491 UNICODE_STRING deviceName = RTL_CONSTANT_STRING(
DEVICE_NAME);
494 PDEVICE_OBJECT deviceObject;
496 const ULONG deviceExtensionSize = 0;
497 const ULONG deviceCharacteristics = FILE_DEVICE_SECURE_OPEN;
498 const BOOLEAN exlusive = TRUE;
499 NTSTATUS ntStatus = IoCreateDevice(driverObject, deviceExtensionSize, &deviceName,
FILE_DEVICE_AKEN, deviceCharacteristics, exlusive, &deviceObject);
500 if(!NT_SUCCESS(ntStatus))
502 KdPrint((
"DriverEntry: IoCreateDevice failed\n"));
508 driverObject->MajorFunction[IRP_MJ_CREATE] =
AkenCreate;
509 driverObject->MajorFunction[IRP_MJ_CLOSE] =
AkenClose;
515 UNICODE_STRING win32Name = RTL_CONSTANT_STRING(
WIN32_NAME);
516 NTSTATUS ntStatus = IoCreateSymbolicLink(&win32Name, &deviceName);
517 if(!NT_SUCCESS(ntStatus))
519 KdPrint((
"DriverEntry: IoCreateSymbolicLink failed\n"));
520 IoDeleteDevice(deviceObject);
525 return STATUS_SUCCESS;
DRIVER_INITIALIZE DriverEntry
static NTSTATUS AkenUnmapPhysicalMemory(const DWORD64 virtualAddress)
static NTSTATUS AkenIoctlUnknown(PVOID buf, const ULONG inSize, ULONG *outSize)
static void out(const wchar_t *fmt,...)
static NTSTATUS AkenIoctlReadPerformanceMonitoringCounter(PVOID buf, const ULONG inSize, ULONG *outSize)
#define IOCTL_AKEN_READ_MSR
static NTSTATUS AkenIoctlReadPort(PVOID buf, const ULONG inSize, ULONG *outSize)
#define ASSERT(expr)
same as ENSURE in debug mode, does nothing in release mode.
NTSTATUS(* AkenIoctl)(PVOID buf, ULONG inSize, ULONG *outSize)
static NTSTATUS AkenIoctlMap(PVOID buf, const ULONG inSize, ULONG *outSize)
static NTSTATUS AkenIoctlWritePort(PVOID buf, const ULONG inSize, ULONG *outSize)
static NTSTATUS AkenIoctlUnmap(PVOID buf, const ULONG inSize, ULONG *outSize)
static NTSTATUS AkenClose(IN PDEVICE_OBJECT deviceObject, IN PIRP irp)
__drv_dispatchType(IRP_MJ_CREATE)
static NTSTATUS AkenIoctlWriteModelSpecificRegister(PVOID buf, const ULONG inSize, ULONG *outSize)
static NTSTATUS AkenMapPhysicalMemory(const DWORD64 physicalAddress64, const DWORD64 numBytes64, DWORD64 *virtualAddress64)
static NTSTATUS AkenIoctlReadModelSpecificRegister(PVOID buf, const ULONG inSize, ULONG *outSize)
static AkenIoctl AkenIoctlFromCode(ULONG ioctlCode)
static VOID AkenUnload(IN PDRIVER_OBJECT driverObject)
#define IOCTL_AKEN_READ_PORT
static NTSTATUS AkenCreate(IN PDEVICE_OBJECT deviceObject, IN PIRP irp)
static NTSTATUS AkenDeviceControl(IN PDEVICE_OBJECT deviceObject, IN PIRP irp)
#define IOCTL_AKEN_WRITE_PORT
#define IOCTL_AKEN_WRITE_MSR