#include <ntddk.h>
#include <procgrp.h>
+#include <ntstrsafe.h>
#include <xen.h>
#include "registry.h"
#include "bug_check.h"
#include "dbg_print.h"
#include "assert.h"
+#include "util.h"
#include "version.h"
#define DEFAULT_XEN_LOG_LEVEL LOG_LEVEL_CRITICAL
PLOG_DISPOSITION XenDisposition;
PLOG_DISPOSITION QemuDisposition;
HANDLE UnplugKey;
+ HANDLE MemoryKey;
} XEN_DRIVER, *PXEN_DRIVER;
static XEN_DRIVER Driver;
+#define XEN_DRIVER_TAG 'VIRD'
+
extern PULONG InitSafeBootMode;
+static FORCEINLINE PVOID
+__DriverAllocate(
+ IN ULONG Length
+ )
+{
+ return __AllocatePoolWithTag(NonPagedPool, Length, XEN_DRIVER_TAG);
+}
+
+static FORCEINLINE VOID
+__DriverFree(
+ IN PVOID Buffer
+ )
+{
+ __FreePoolWithTag(Buffer, XEN_DRIVER_TAG);
+}
+
static FORCEINLINE BOOLEAN
__DriverSafeMode(
VOID
return __DriverGetUnplugKey();
}
+static FORCEINLINE VOID
+__DriverSetMemoryKey(
+ IN HANDLE Key
+ )
+{
+ Driver.MemoryKey = Key;
+}
+
+static FORCEINLINE HANDLE
+__DriverGetMemoryKey(
+ VOID
+ )
+{
+ return Driver.MemoryKey;
+}
+
+#define MAXNAMELEN 128
+
+static FORCEINLINE NTSTATUS
+__DriverSetPfnArray(
+ IN PCHAR Name,
+ IN ULONG Count,
+ IN PFN_NUMBER PfnArray[]
+ )
+{
+ HANDLE Key = __DriverGetMemoryKey();
+ LONG Index;
+ NTSTATUS status;
+
+ Index = 0;
+ while (Index < (LONG)Count) {
+ CHAR ValueName[MAXNAMELEN];
+ PVOID Value;
+ ULONG Length;
+
+ status = RtlStringCbPrintfA(ValueName,
+ MAXNAMELEN,
+ "%s_%u",
+ Name,
+ Index);
+ ASSERT(NT_SUCCESS(status));
+
+ Value = &PfnArray[Index];
+ Length = sizeof (PFN_NUMBER);
+
+ status = RegistryUpdateBinaryValue(Key,
+ ValueName,
+ Value,
+ Length);
+ if (!NT_SUCCESS(status))
+ goto fail1;
+
+ Info("%s %p\n", ValueName, (PVOID)PfnArray[Index]);
+
+ Index++;
+ }
+
+ return STATUS_SUCCESS;
+
+fail1:
+ Error("fail1 (%08x)\n", status);
+
+ while (--Index >= 0) {
+ CHAR ValueName[MAXNAMELEN];
+
+ status = RtlStringCbPrintfA(ValueName,
+ MAXNAMELEN,
+ "%s_%u",
+ Name,
+ Index);
+ ASSERT(NT_SUCCESS(status));
+
+ (VOID) RegistryDeleteValue(Key, ValueName);
+ }
+
+ return status;
+}
+
+static FORCEINLINE NTSTATUS
+__DriverAllocatePfnArray(
+ IN PCHAR Name,
+ IN ULONG Count,
+ OUT PFN_NUMBER PfnArray[]
+ )
+{
+ PHYSICAL_ADDRESS LowAddress;
+ PHYSICAL_ADDRESS HighAddress;
+ LARGE_INTEGER SkipBytes;
+ SIZE_T TotalBytes;
+ PMDL Mdl;
+ NTSTATUS status;
+
+ LowAddress.QuadPart = 0ull;
+ HighAddress.QuadPart = ~0ull;
+ SkipBytes.QuadPart = 0ull;
+ TotalBytes = PAGE_SIZE * Count;
+
+ Mdl = MmAllocatePagesForMdlEx(LowAddress,
+ HighAddress,
+ SkipBytes,
+ TotalBytes,
+ MmCached,
+ MM_ALLOCATE_FULLY_REQUIRED);
+
+ status = STATUS_NO_MEMORY;
+ if (Mdl == NULL)
+ goto fail1;
+
+ if (Mdl->ByteCount < TotalBytes)
+ goto fail2;
+
+ ASSERT((Mdl->MdlFlags & (MDL_MAPPED_TO_SYSTEM_VA |
+ MDL_PARTIAL_HAS_BEEN_MAPPED |
+ MDL_PARTIAL |
+ MDL_PARENT_MAPPED_SYSTEM_VA |
+ MDL_SOURCE_IS_NONPAGED_POOL |
+ MDL_IO_SPACE)) == 0);
+
+ status = __DriverSetPfnArray(Name, Count, MmGetMdlPfnArray(Mdl));
+ if (!NT_SUCCESS(status))
+ goto fail3;
+
+ RtlCopyMemory(PfnArray, MmGetMdlPfnArray(Mdl), sizeof (PFN_NUMBER) * Count);
+
+ ExFreePool(Mdl);
+
+ return STATUS_SUCCESS;
+
+fail3:
+ Error("fail3\n");
+
+fail2:
+ Error("fail2\n");
+
+ MmFreePagesFromMdl(Mdl);
+ ExFreePool(Mdl);
+
+fail1:
+ Error("fail1 (%08x)\n", status);
+
+ return status;
+}
+
+static FORCEINLINE NTSTATUS
+__DriverGetPfnArray(
+ IN PCHAR Name,
+ IN ULONG Count,
+ OUT PFN_NUMBER PfnArray[]
+ )
+{
+ HANDLE Key = __DriverGetMemoryKey();
+ ULONG Index;
+ NTSTATUS status;
+
+ for (Index = 0; Index < Count; Index++) {
+ CHAR ValueName[MAXNAMELEN];
+ PVOID Value;
+ ULONG Length;
+
+ status = RtlStringCbPrintfA(ValueName,
+ MAXNAMELEN,
+ "%s_%u",
+ Name,
+ Index);
+ ASSERT(NT_SUCCESS(status));
+
+ status = RegistryQueryBinaryValue(Key,
+ ValueName,
+ &Value,
+ &Length);
+ if (!NT_SUCCESS(status))
+ goto fail1;
+
+ status = STATUS_UNSUCCESSFUL;
+ if (Length != sizeof (PFN_NUMBER))
+ goto fail2;
+
+ PfnArray[Index] = *(PPFN_NUMBER)Value;
+
+ RegistryFreeBinaryValue(Value);
+
+ Info("%s %p\n", Name, (PVOID)PfnArray[Index]);
+ }
+
+ return STATUS_SUCCESS;
+
+fail2:
+ Error("fail2\n");
+
+fail1:
+ Error("fail1 (%08x)\n", status);
+
+ return status;
+}
+
+PMDL
+DriverGetNamedPages(
+ IN PCHAR Name,
+ IN ULONG Count
+ )
+{
+ ULONG Size;
+ PMDL Mdl;
+ PUCHAR MdlMappedSystemVa;
+ NTSTATUS status;
+
+ Size = sizeof (MDL) + (sizeof (PFN_NUMBER) * Count);
+ Mdl = __DriverAllocate(Size);
+
+ status = STATUS_NO_MEMORY;
+ if (Mdl == NULL)
+ goto fail1;
+
+#pragma warning(push)
+#pragma warning(disable:28145) // modifying struct MDL
+
+ Mdl->Size = (USHORT)Size;
+ Mdl->MdlFlags = MDL_PAGES_LOCKED;
+ Mdl->ByteCount = PAGE_SIZE * Count;
+
+#pragma warning(pop)
+
+ status = __DriverGetPfnArray(Name, Count, MmGetMdlPfnArray(Mdl));
+ if (!NT_SUCCESS(status)) {
+ if (status == STATUS_OBJECT_NAME_NOT_FOUND)
+ status = __DriverAllocatePfnArray(Name, Count,
+ MmGetMdlPfnArray(Mdl));
+
+ if (!NT_SUCCESS(status))
+ goto fail2;
+ }
+
+ MdlMappedSystemVa = MmMapLockedPagesSpecifyCache(Mdl,
+ KernelMode,
+ MmCached,
+ NULL,
+ FALSE,
+ NormalPagePriority);
+
+ status = STATUS_UNSUCCESSFUL;
+ if (MdlMappedSystemVa == NULL)
+ goto fail3;
+
+ Mdl->StartVa = PAGE_ALIGN(MdlMappedSystemVa);
+
+ return Mdl;
+
+fail3:
+ Error("fail3\n");
+
+fail2:
+ Error("fail2\n");
+
+ __DriverFree(Mdl);
+
+fail1:
+ Error("fail1 (%08x)\n", status);
+
+ return NULL;
+}
+
+VOID
+DriverPutNamedPages(
+ IN PMDL Mdl
+ )
+{
+ PUCHAR MdlMappedSystemVa;
+
+ ASSERT(Mdl->MdlFlags & MDL_MAPPED_TO_SYSTEM_VA);
+ MdlMappedSystemVa = Mdl->MappedSystemVa;
+
+ MmUnmapLockedPages(MdlMappedSystemVa, Mdl);
+
+ // DO NOT FREE PAGES
+
+ __DriverFree(Mdl);
+}
+
XEN_API
NTSTATUS
XenTouch(
)
{
HANDLE ServiceKey;
- HANDLE UnplugKey;
HANDLE ParametersKey;
+ HANDLE UnplugKey;
+ HANDLE MemoryKey;
LOG_LEVEL LogLevel;
NTSTATUS status;
goto fail3;
status = RegistryCreateSubKey(ServiceKey,
- "Parameters",
- REG_OPTION_NON_VOLATILE,
- &ParametersKey);
+ "Parameters",
+ REG_OPTION_NON_VOLATILE,
+ &ParametersKey);
if (!NT_SUCCESS(status))
goto fail4;
__DriverSetUnplugKey(UnplugKey);
+ status = RegistryCreateSubKey(ServiceKey,
+ "Memory",
+ REG_OPTION_VOLATILE,
+ &MemoryKey);
+ if (!NT_SUCCESS(status))
+ goto fail6;
+
+ __DriverSetMemoryKey(MemoryKey);
+
HypercallInitialize();
status = AcpiInitialize();
if (!NT_SUCCESS(status))
- goto fail6;
+ goto fail7;
status = SystemInitialize();
if (!NT_SUCCESS(status))
- goto fail7;
+ goto fail8;
status = BugCheckInitialize();
if (!NT_SUCCESS(status))
- goto fail8;
+ goto fail9;
status = ModuleInitialize();
if (!NT_SUCCESS(status))
- goto fail9;
+ goto fail10;
status = ProcessInitialize();
if (!NT_SUCCESS(status))
- goto fail10;
+ goto fail11;
status = UnplugInitialize();
if (!NT_SUCCESS(status))
- goto fail11;
+ goto fail12;
RegistryCloseKey(ParametersKey);
return STATUS_SUCCESS;
+fail12:
+ Error("fail12\n");
+
+ ProcessTeardown();
+
fail11:
Error("fail11\n");
- ProcessTeardown();
+ ModuleTeardown();
fail10:
Error("fail10\n");
- ModuleTeardown();
+ BugCheckTeardown();
fail9:
Error("fail9\n");
- BugCheckTeardown();
+ SystemTeardown();
fail8:
Error("fail8\n");
- SystemTeardown();
+ AcpiTeardown();
fail7:
Error("fail7\n");
- AcpiTeardown();
+ HypercallTeardown();
+
+ RegistryCloseKey(MemoryKey);
+ __DriverSetMemoryKey(NULL);
fail6:
Error("fail6\n");
- HypercallTeardown();
-
RegistryCloseKey(UnplugKey);
__DriverSetUnplugKey(NULL);
VOID
)
{
+ HANDLE MemoryKey;
HANDLE UnplugKey;
Trace("====>\n");
HypercallTeardown();
+ MemoryKey = __DriverGetMemoryKey();
+
+ RegistryCloseKey(MemoryKey);
+ __DriverSetMemoryKey(NULL);
+
UnplugKey = __DriverGetUnplugKey();
RegistryCloseKey(UnplugKey);