// G - XENBUS_GNTTAB_INTERFACE
// EM - XENFILT_EMULATED_INTERFACE
-// REVISION S SI E D ST R C G EM
-#define DEFINE_REVISION_TABLE \
- DEFINE_REVISION(0x08000008, 1, 2, 4, 1, 1, 1, 1, 1, 1)
+// REVISION S SI E D ST R C G U EM
+#define DEFINE_REVISION_TABLE \
+ DEFINE_REVISION(0x08000009, 1, 2, 4, 1, 1, 1, 1, 1, 1, 1)
#endif // _REVISION_H
*/
/*! \file unplug_interface.h
- \brief XENFILT UNPLUG Interface
+ \brief XENBUS UNPLUG Interface
- This interface provides a primitive to re-unplug emulated devices,
- which is required on resume-from-suspend
+ This interface provides a method to request emulated device unplug
*/
-#ifndef _XENFILT_UNPLUG_INTERFACE_H
-#define _XENFILT_UNPLUG_INTERFACE_H
+#ifndef _XENBUS_UNPLUG_INTERFACE_H
+#define _XENBUS_UNPLUG_INTERFACE_H
#ifndef _WINDLL
-/*! \typedef XENFILT_UNPLUG_ACQUIRE
+/*! \typedef XENBUS_UNPLUG_ACQUIRE
\brief Acquire a reference to the UNPLUG interface
\param Interface The interface header
*/
typedef NTSTATUS
-(*XENFILT_UNPLUG_ACQUIRE)(
+(*XENBUS_UNPLUG_ACQUIRE)(
IN PINTERFACE Interface
);
-/*! \typedef XENFILT_UNPLUG_RELEASE
+/*! \typedef XENBUS_UNPLUG_RELEASE
\brief Release a reference to the UNPLUG interface
\param Interface The interface header
*/
typedef VOID
-(*XENFILT_UNPLUG_RELEASE)(
+(*XENBUS_UNPLUG_RELEASE)(
IN PINTERFACE Interface
);
-/*! \typedef XENFILT_UNPLUG_REPLAY
- \brief Re-unplug emulated devices that were previously unplugged
- at boot time
+/*! \enum _XENBUS_UNPLUG_DEVICE_TYPE
+ \brief Type of device to be unplugged
+*/
+typedef enum _XENBUS_UNPLUG_DEVICE_TYPE {
+ XENBUS_UNPLUG_DEVICE_TYPE_INVALID = 0,
+ XENBUS_UNPLUG_DEVICE_TYPE_NICS, /*!< NICs */
+ XENBUS_UNPLUG_DEVICE_TYPE_DISKS, /*!< Disks */
+} XENBUS_UNPLUG_DEVICE_TYPE, *PXENBUS_UNPLUG_DEVICE_TYPE;
+
+/*! \typedef XENBUS_UNPLUG_REQUEST
+ \brief Request unplug of a type of emulated device
\param Interface The interface header
+ \param Type The type of device
+ \param Make Set to TRUE if the request is being made, FALSE if it is
+ being revoked.
*/
typedef VOID
-(*XENFILT_UNPLUG_REPLAY)(
- IN PINTERFACE Interface
+(*XENBUS_UNPLUG_REQUEST)(
+ IN PINTERFACE Interface,
+ IN XENBUS_UNPLUG_DEVICE_TYPE Type,
+ IN BOOLEAN Make
);
-// {D5657CFD-3DB5-4A23-A94F-61FD89247FE7}
-DEFINE_GUID(GUID_XENFILT_UNPLUG_INTERFACE,
-0xd5657cfd, 0x3db5, 0x4a23, 0xa9, 0x4f, 0x61, 0xfd, 0x89, 0x24, 0x7f, 0xe7);
+// {73db6517-3d06-4937-989f-199b7501e229}
+DEFINE_GUID(GUID_XENBUS_UNPLUG_INTERFACE,
+0x73db6517, 0x3d06, 0x4937, 0x98, 0x9f, 0x19, 0x9b, 0x75, 0x01, 0xe2, 0x29);
-/*! \struct _XENFILT_UNPLUG_INTERFACE_V1
+/*! \struct _XENBUS_UNPLUG_INTERFACE_V1
\brief UNPLUG interface version 1
\ingroup interfaces
*/
-struct _XENFILT_UNPLUG_INTERFACE_V1 {
+struct _XENBUS_UNPLUG_INTERFACE_V1 {
INTERFACE Interface;
- XENFILT_UNPLUG_ACQUIRE Acquire;
- XENFILT_UNPLUG_RELEASE Release;
- XENFILT_UNPLUG_REPLAY Replay;
+ XENBUS_UNPLUG_ACQUIRE UnplugAcquire;
+ XENBUS_UNPLUG_RELEASE UnplugRelease;
+ XENBUS_UNPLUG_REQUEST UnplugRequest;
};
-typedef struct _XENFILT_UNPLUG_INTERFACE_V1 XENFILT_UNPLUG_INTERFACE, *PXENFILT_UNPLUG_INTERFACE;
+typedef struct _XENBUS_UNPLUG_INTERFACE_V1 XENBUS_UNPLUG_INTERFACE, *PXENBUS_UNPLUG_INTERFACE;
-/*! \def XENFILT_UNPLUG
+/*! \def XENBUS_UNPLUG
\brief Macro at assist in method invocation
*/
-#define XENFILT_UNPLUG(_Method, _Interface, ...) \
- (_Interface)-> ## _Method((PINTERFACE)(_Interface), __VA_ARGS__)
+#define XENBUS_UNPLUG(_Method, _Interface, ...) \
+ (_Interface)->Unplug ## _Method((PINTERFACE)(_Interface), __VA_ARGS__)
#endif // _WINDLL
-#define XENFILT_UNPLUG_INTERFACE_VERSION_MIN 1
-#define XENFILT_UNPLUG_INTERFACE_VERSION_MAX 1
+#define XENBUS_UNPLUG_INTERFACE_VERSION_MIN 1
+#define XENBUS_UNPLUG_INTERFACE_VERSION_MAX 1
-#endif // _XENFILT_UNPLUG_INTERFACE_H
+#endif // _XENBUS_UNPLUG_INTERFACE_H
OUT PULONG_PTR Offset
);
+// UNPLUG
+
+typedef enum _UNPLUG_TYPE {
+ UNPLUG_DISKS = 0,
+ UNPLUG_NICS,
+ UNPLUG_TYPE_COUNT
+} UNPLUG_TYPE, *PUNPLUG_TYPE;
+
+XEN_API
+VOID
+UnplugDevices(
+ VOID
+ );
+
+XEN_API
+NTSTATUS
+UnplugIncrementValue(
+ IN UNPLUG_TYPE Type
+ );
+
+XEN_API
+NTSTATUS
+UnplugDecrementValue(
+ IN UNPLUG_TYPE Type
+ );
+
// LOG
typedef enum _LOG_LEVEL {
return FALSE;
}
-#define DEFINE_REVISION(_N, _S, _SI, _E, _D, _ST, _R, _C, _G, _EM) \
+#define DEFINE_REVISION(_N, _S, _SI, _E, _D, _ST, _R, _C, _G, _U, _EM) \
(_N)
static DWORD DeviceRevision[] = {
return status;
}
+NTSTATUS
+RegistryCreateKey(
+ IN HANDLE Parent,
+ IN PUNICODE_STRING Path,
+ IN ULONG Options,
+ OUT PHANDLE Key
+ )
+{
+ OBJECT_ATTRIBUTES Attributes;
+ NTSTATUS status;
+
+ InitializeObjectAttributes(&Attributes,
+ Path,
+ OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
+ Parent,
+ NULL);
+
+ status = ZwCreateKey(Key,
+ KEY_ALL_ACCESS,
+ &Attributes,
+ 0,
+ NULL,
+ Options,
+ NULL
+ );
+ if (!NT_SUCCESS(status))
+ goto fail1;
+
+ return STATUS_SUCCESS;
+
+fail1:
+ return status;
+}
+
NTSTATUS
RegistryOpenServiceKey(
IN ACCESS_MASK DesiredAccess,
return RegistryOpenKey(NULL, &RegistryPath, DesiredAccess, Key);
}
+NTSTATUS
+RegistryCreateServiceKey(
+ OUT PHANDLE Key
+ )
+{
+ return RegistryCreateKey(NULL, &RegistryPath, REG_OPTION_NON_VOLATILE, Key);
+}
+
NTSTATUS
RegistryOpenSoftwareKey(
IN PDEVICE_OBJECT DeviceObject,
OUT PHANDLE Key
);
+extern NTSTATUS
+RegistryCreateKey(
+ IN HANDLE Parent,
+ IN PUNICODE_STRING Path,
+ IN ULONG Options,
+ OUT PHANDLE Key
+ );
+
extern NTSTATUS
RegistryOpenServiceKey(
IN ACCESS_MASK DesiredAccess,
OUT PHANDLE Key
);
+extern NTSTATUS
+RegistryCreateServiceKey(
+ OUT PHANDLE Key
+ );
+
extern NTSTATUS
RegistryOpenSoftwareKey(
IN PDEVICE_OBJECT DeviceObject,
extern NTSTATUS
RegistryCreateSubKey(
IN HANDLE Key,
- IN PCHAR Name,
- IN ULONG Options,
+ IN PCHAR Name, IN ULONG Options,
OUT PHANDLE SubKey
);
#include <procgrp.h>
#include <xen.h>
+#include "registry.h"
+#include "driver.h"
#include "hypercall.h"
#include "log.h"
#include "module.h"
#include "process.h"
#include "system.h"
#include "acpi.h"
+#include "unplug.h"
#include "bug_check.h"
#include "dbg_print.h"
#include "assert.h"
typedef struct _XEN_DRIVER {
PLOG_DISPOSITION TraceDisposition;
PLOG_DISPOSITION InfoDisposition;
+ HANDLE UnplugKey;
} XEN_DRIVER, *PXEN_DRIVER;
static XEN_DRIVER Driver;
return STATUS_INCOMPATIBLE_DRIVER_BLOCKED;
}
+static FORCEINLINE VOID
+__DriverSetUnplugKey(
+ IN HANDLE Key
+ )
+{
+ Driver.UnplugKey = Key;
+}
+
+static FORCEINLINE HANDLE
+__DriverGetUnplugKey(
+ VOID
+ )
+{
+ return Driver.UnplugKey;
+}
+
+HANDLE
+DriverGetUnplugKey(
+ VOID
+ )
+{
+ return __DriverGetUnplugKey();
+}
+
static VOID
DriverOutputBuffer(
IN PVOID Argument,
IN PUNICODE_STRING RegistryPath
)
{
- NTSTATUS status;
-
- UNREFERENCED_PARAMETER(RegistryPath);
+ HANDLE ServiceKey;
+ HANDLE UnplugKey;
+ NTSTATUS status;
ExInitializeDriverRuntime(DrvRtPoolNxOptIn);
WdmlibProcgrpInitialize();
MONTH,
YEAR);
- status = AcpiInitialize();
+ status = RegistryInitialize(RegistryPath);
if (!NT_SUCCESS(status))
goto fail2;
- status = SystemInitialize();
+ status = RegistryCreateServiceKey(&ServiceKey);
if (!NT_SUCCESS(status))
goto fail3;
- status = HypercallInitialize();
+ status = RegistryCreateSubKey(ServiceKey,
+ "Unplug",
+ REG_OPTION_NON_VOLATILE,
+ &UnplugKey);
if (!NT_SUCCESS(status))
goto fail4;
- status = BugCheckInitialize();
+ __DriverSetUnplugKey(UnplugKey);
+
+ status = AcpiInitialize();
if (!NT_SUCCESS(status))
goto fail5;
- status = ModuleInitialize();
+ status = SystemInitialize();
if (!NT_SUCCESS(status))
goto fail6;
- status = ProcessInitialize();
+ status = HypercallInitialize();
if (!NT_SUCCESS(status))
goto fail7;
+ status = BugCheckInitialize();
+ if (!NT_SUCCESS(status))
+ goto fail8;
+
+ status = ModuleInitialize();
+ if (!NT_SUCCESS(status))
+ goto fail9;
+
+ status = ProcessInitialize();
+ if (!NT_SUCCESS(status))
+ goto fail10;
+
+ status = UnplugInitialize();
+ if (!NT_SUCCESS(status))
+ goto fail11;
+
+ RegistryCloseKey(ServiceKey);
+
done:
Trace("<====\n");
return STATUS_SUCCESS;
+fail11:
+ Error("fail11\n");
+
+ ProcessTeardown();
+
+fail10:
+ Error("fail10\n");
+
+ ModuleTeardown();
+
+fail9:
+ Error("fail9\n");
+
+ BugCheckTeardown();
+
+fail8:
+ Error("fail8\n");
+
+ HypercallTeardown();
+
fail7:
Error("fail7\n");
- ModuleTeardown();
+ SystemTeardown();
fail6:
Error("fail6\n");
- BugCheckTeardown();
+ AcpiTeardown();
fail5:
Error("fail5\n");
- HypercallTeardown();
+ RegistryCloseKey(UnplugKey);
+ __DriverSetUnplugKey(NULL);
fail4:
Error("fail4\n");
- SystemTeardown();
+ RegistryCloseKey(ServiceKey);
fail3:
Error("fail3\n");
- AcpiTeardown();
+ RegistryTeardown();
fail2:
Error("fail2\n");
LogTeardown();
fail1:
- Error("fail1 (%08x)", status);
+ Error("fail1 (%08x)\n", status);
ASSERT(IsZeroMemory(&Driver, sizeof (XEN_DRIVER)));
VOID
)
{
+ HANDLE UnplugKey;
+
Trace("====>\n");
if (*InitSafeBootMode > 0)
goto done;
+ UnplugTeardown();
+
ProcessTeardown();
ModuleTeardown();
SystemTeardown();
+ UnplugKey = __DriverGetUnplugKey();
+
+ RegistryCloseKey(UnplugKey);
+ __DriverSetUnplugKey(NULL);
+
+ RegistryTeardown();
+
Info("XEN %d.%d.%d (%d) (%02d.%02d.%04d)\n",
MAJOR_VERSION,
MINOR_VERSION,
--- /dev/null
+/* Copyright (c) Citrix Systems Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms,
+ * with or without modification, are permitted provided
+ * that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the
+ * following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the
+ * following disclaimer in the documentation and/or other
+ * materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef _XEN_DRIVER_H
+#define _XEN_DRIVER_H
+
+extern HANDLE
+DriverGetUnplugKey(
+ VOID
+ );
+
+#endif // _XEN_DRIVER_H
--- /dev/null
+/* Copyright (c) Citrix Systems Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms,
+ * with or without modification, are permitted provided
+ * that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the
+ * following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the
+ * following disclaimer in the documentation and/or other
+ * materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#define XEN_API __declspec(dllexport)
+
+#include <ntddk.h>
+#include <ntstrsafe.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <xen.h>
+#include <version.h>
+
+#include "driver.h"
+#include "high.h"
+#include "registry.h"
+#include "unplug.h"
+#include "dbg_print.h"
+#include "assert.h"
+#include "util.h"
+
+#define UNPLUG_TAG 'LPNU'
+
+typedef struct _UNPLUG_CONTEXT {
+ LONG References;
+ HIGH_LOCK Lock;
+ BOOLEAN BlackListed;
+ BOOLEAN Request[UNPLUG_TYPE_COUNT];
+ BOOLEAN BootEmulated;
+} UNPLUG_CONTEXT, *PUNPLUG_CONTEXT;
+
+static UNPLUG_CONTEXT UnplugContext;
+
+static FORCEINLINE PVOID
+__UnplugAllocate(
+ IN ULONG Length
+ )
+{
+ return __AllocatePoolWithTag(NonPagedPool, Length, UNPLUG_TAG);
+}
+
+static FORCEINLINE VOID
+__UnplugFree(
+ IN PVOID Buffer
+ )
+{
+ ExFreePoolWithTag(Buffer, UNPLUG_TAG);
+}
+
+static VOID
+UnplugSetBootEmulated(
+ VOID
+ )
+{
+ PUNPLUG_CONTEXT Context = &UnplugContext;
+ CHAR Key[] = "XEN:BOOT_EMULATED=";
+ PANSI_STRING Option;
+ PCHAR Value;
+ NTSTATUS status;
+
+ status = RegistryQuerySystemStartOption(Key, &Option);
+ if (!NT_SUCCESS(status))
+ return;
+
+ Value = Option->Buffer + sizeof (Key) - 1;
+
+ if (strcmp(Value, "TRUE") == 0)
+ Context->BootEmulated = TRUE;
+
+ RegistryFreeSzValue(Option);
+}
+
+static VOID
+UnplugDeviceType(
+ IN UNPLUG_TYPE Type
+ )
+{
+ PUNPLUG_CONTEXT Context = &UnplugContext;
+
+ switch (Type) {
+ case UNPLUG_DISKS:
+ if (Context->BootEmulated) {
+#pragma prefast(suppress:28138)
+ WRITE_PORT_USHORT((PUSHORT)0x10, 0x0004);
+
+ LogPrintf(LOG_LEVEL_WARNING, "UNPLUG: AUX DISKS\n");
+ } else {
+#pragma prefast(suppress:28138)
+ WRITE_PORT_USHORT((PUSHORT)0x10, 0x0001);
+
+ LogPrintf(LOG_LEVEL_WARNING, "UNPLUG: DISKS\n");
+ }
+ break;
+ case UNPLUG_NICS:
+#pragma prefast(suppress:28138)
+ WRITE_PORT_USHORT((PUSHORT)0x10, 0x0002);
+
+ LogPrintf(LOG_LEVEL_WARNING, "UNPLUG: NICS\n");
+ break;
+ default:
+ ASSERT(FALSE);
+ }
+}
+
+static NTSTATUS
+UnplugPreamble(
+ VOID
+ )
+{
+ PUNPLUG_CONTEXT Context = &UnplugContext;
+ USHORT Magic;
+ UCHAR Version;
+ NTSTATUS status;
+
+ // See docs/misc/hvm-emulated-unplug.markdown for details of the
+ // protocol in use here
+
+#pragma prefast(suppress:28138)
+ Magic = READ_PORT_USHORT((PUSHORT)0x10);
+
+ if (Magic == 0xd249) {
+ Context->BlackListed = TRUE;
+ goto done;
+ }
+
+ status = STATUS_NOT_SUPPORTED;
+ if (Magic != 0x49d2)
+ goto fail1;
+
+#pragma prefast(suppress:28138)
+ Version = READ_PORT_UCHAR((PUCHAR)0x12);
+ if (Version != 0) {
+#pragma prefast(suppress:28138)
+ WRITE_PORT_USHORT((PUSHORT)0x12, 0xFFFF); // FIXME
+
+#pragma prefast(suppress:28138)
+ WRITE_PORT_ULONG((PULONG)0x10,
+ (MAJOR_VERSION << 16) |
+ (MINOR_VERSION << 8) |
+ MICRO_VERSION);
+
+#pragma prefast(suppress:28138)
+ Magic = READ_PORT_USHORT((PUSHORT)0x10);
+ if (Magic == 0xd249)
+ Context->BlackListed = TRUE;
+ }
+
+done:
+ LogPrintf(LOG_LEVEL_WARNING,
+ "UNPLUG: PRE-AMBLE (DRIVERS %s)\n",
+ (Context->BlackListed) ? "BLACKLISTED" : "NOT BLACKLISTED");
+
+ return STATUS_SUCCESS;
+
+fail1:
+ return status;
+}
+
+static VOID
+UnplugSetRequest(
+ IN UNPLUG_TYPE Type
+ )
+{
+ PUNPLUG_CONTEXT Context = &UnplugContext;
+ HANDLE UnplugKey;
+ PCHAR ValueName;
+ ULONG Value;
+ KIRQL Irql;
+ NTSTATUS status;
+
+ Trace("====>\n");
+
+ ASSERT3U(KeGetCurrentIrql(), ==, PASSIVE_LEVEL);
+
+ UnplugKey = DriverGetUnplugKey();
+
+ switch (Type) {
+ case UNPLUG_DISKS:
+ ValueName = "DISKS";
+ break;
+ case UNPLUG_NICS:
+ ValueName = "NICS";
+ break;
+ default:
+ ValueName = NULL;
+ ASSERT(FALSE);
+ }
+
+ status = RegistryQueryDwordValue(UnplugKey,
+ ValueName,
+ &Value);
+ if (!NT_SUCCESS(status))
+ goto done;
+
+ (VOID) RegistryDeleteValue(UnplugKey, ValueName);
+
+ Info("%s\n", ValueName);
+
+ AcquireHighLock(&Context->Lock, &Irql);
+ Context->Request[Type] = (Value != 0) ? TRUE : FALSE;
+ ReleaseHighLock(&Context->Lock, Irql);
+
+done:
+ Trace("<====\n");
+}
+
+XEN_API
+NTSTATUS
+UnplugIncrementValue(
+ IN UNPLUG_TYPE Type
+ )
+{
+ HANDLE UnplugKey;
+ PCHAR ValueName;
+ ULONG Value;
+ NTSTATUS status;
+
+ ASSERT3U(KeGetCurrentIrql(), ==, PASSIVE_LEVEL);
+
+ UnplugKey = DriverGetUnplugKey();
+
+ switch (Type) {
+ case UNPLUG_DISKS:
+ ValueName = "DISKS";
+ break;
+ case UNPLUG_NICS:
+ ValueName = "NICS";
+ break;
+ default:
+ ValueName = NULL;
+ ASSERT(FALSE);
+ }
+
+ status = RegistryQueryDwordValue(UnplugKey,
+ ValueName,
+ &Value);
+ if (!NT_SUCCESS(status))
+ Value = 0;
+
+ Value++;
+
+ status = RegistryUpdateDwordValue(UnplugKey,
+ ValueName,
+ Value);
+ if (!NT_SUCCESS(status))
+ goto fail1;
+
+ Info("%s %u\n", ValueName, Value);
+
+ return STATUS_SUCCESS;
+
+fail1:
+ Error("fail1 (%08x)\n", status);
+
+ return status;
+}
+
+XEN_API
+NTSTATUS
+UnplugDecrementValue(
+ IN UNPLUG_TYPE Type
+ )
+{
+ HANDLE UnplugKey;
+ PCHAR ValueName;
+ LONG Value;
+ NTSTATUS status;
+
+ ASSERT3U(KeGetCurrentIrql(), ==, PASSIVE_LEVEL);
+
+ UnplugKey = DriverGetUnplugKey();
+
+ switch (Type) {
+ case UNPLUG_DISKS:
+ ValueName = "DISKS";
+ break;
+ case UNPLUG_NICS:
+ ValueName = "NICS";
+ break;
+ default:
+ ValueName = NULL;
+ ASSERT(FALSE);
+ }
+
+ status = RegistryQueryDwordValue(UnplugKey,
+ ValueName,
+ (PULONG)&Value);
+ if (!NT_SUCCESS(status))
+ goto fail1;
+
+ status = STATUS_INVALID_PARAMETER;
+ if (--Value < 0)
+ goto fail2;
+
+ status = RegistryUpdateDwordValue(UnplugKey,
+ ValueName,
+ (ULONG)Value);
+ if (!NT_SUCCESS(status))
+ goto fail3;
+
+ Info("%s %u\n", ValueName, (ULONG)Value);
+
+ return STATUS_SUCCESS;
+
+fail3:
+ Error("fail3\n");
+
+fail2:
+ Error("fail2\n");
+
+fail1:
+ Error("fail1 (%08x)\n", status);
+
+ return status;
+}
+
+XEN_API
+VOID
+UnplugDevices(
+ VOID
+ )
+{
+ PUNPLUG_CONTEXT Context = &UnplugContext;
+ UNPLUG_TYPE Type;
+ KIRQL Irql;
+ NTSTATUS status;
+
+ AcquireHighLock(&Context->Lock, &Irql);
+
+ status = UnplugPreamble();
+ ASSERT(NT_SUCCESS(status));
+
+ for (Type = 0; Type < UNPLUG_TYPE_COUNT; Type++) {
+ if (Context->Request[Type])
+ UnplugDeviceType(Type);
+ }
+
+ ReleaseHighLock(&Context->Lock, Irql);
+}
+
+NTSTATUS
+UnplugInitialize(
+ VOID
+ )
+{
+ PUNPLUG_CONTEXT Context = &UnplugContext;
+ LONG References;
+ UNPLUG_TYPE Type;
+ NTSTATUS status;
+
+ References = InterlockedIncrement(&Context->References);
+
+ status = STATUS_OBJECTID_EXISTS;
+ if (References != 1)
+ goto fail1;
+
+ InitializeHighLock(&Context->Lock);
+
+ for (Type = 0; Type < UNPLUG_TYPE_COUNT; Type++)
+ UnplugSetRequest(Type);
+
+ UnplugSetBootEmulated();
+
+ return STATUS_SUCCESS;
+
+fail1:
+ Error("fail1 (%08x)\n", status);
+
+ (VOID) InterlockedDecrement(&Context->References);
+
+ ASSERT(IsZeroMemory(Context, sizeof (UNPLUG_CONTEXT)));
+
+ return status;
+}
+
+VOID
+UnplugTeardown(
+ VOID
+ )
+{
+ PUNPLUG_CONTEXT Context = &UnplugContext;
+ UNPLUG_TYPE Type;
+
+ Context->BootEmulated = FALSE;
+
+ for (Type = 0; Type < UNPLUG_TYPE_COUNT; Type++)
+ Context->Request[Type] = FALSE;
+
+ RtlZeroMemory(&Context->Lock, sizeof (HIGH_LOCK));
+
+ (VOID) InterlockedDecrement(&Context->References);
+
+ ASSERT(IsZeroMemory(Context, sizeof (UNPLUG_CONTEXT)));
+}
--- /dev/null
+/* Copyright (c) Citrix Systems Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms,
+ * with or without modification, are permitted provided
+ * that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the
+ * following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the
+ * following disclaimer in the documentation and/or other
+ * materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef _XEN_UNPLUG_H
+#define _XEN_UNPLUG_H
+
+#include <ntddk.h>
+#include <xen.h>
+
+extern NTSTATUS
+UnplugInitialize(
+ VOID
+ );
+
+extern VOID
+UnplugTeardown(
+ VOID
+ );
+
+#endif // _XEN_UNPLUG_H
[XenBus_Inst]
CopyFiles=XenBus_Copyfiles
-[XenBus_Inst.Services]
-AddService=xenbus,0x02,XenBus_Service,
+[XenBus_Inst.Services]
+AddService=xenbus,0x02,XenBus_Service
AddService=xenfilt,,XenFilt_Service,
[XenBus_Service]
ErrorControl=%SERVICE_ERROR_NORMAL%
ServiceBinary=%12%\xenbus.sys
LoadOrderGroup="Boot Bus Extender"
-AddReg = XenBus_Parameters, XenBus_Interfaces, XenBus_Interrupts
+AddReg = XenBus_Parameters, XenBus_Interrupts
[XenBus_Parameters]
HKR,"Parameters",,0x00000010
HKR,"Parameters","SupportedClasses",0x00010000,"VIF","VBD","IFACE"
HKR,"Parameters","SyntheticClasses",0x00010000,"IFACE"
-[XenBus_Interfaces]
-HKR,"Interfaces",,0x00000010
-
[XenBus_Interrupts]
HKR,"Interrupt Management",,0x00000010
HKR,"Interrupt Management\MessageSignaledInterruptProperties",,0x00000010
ErrorControl=%SERVICE_ERROR_NORMAL%
ServiceBinary=%12%\xenfilt.sys
LoadOrderGroup="Boot Bus Extender"
-AddReg = XenFilt_Parameters, XenFilt_Unplug, XenFilt_Interfaces
+AddReg = XenFilt_Parameters
[XenFilt_Parameters]
HKR,"Parameters",,0x00000010
HKR,"Parameters","ACPI\PNP0A03",0x00000000,"DEVICE"
HKR,"Parameters","PCIIDE\IDEChannel",0x00000000,"DISK"
-[XenFilt_Unplug]
-HKR,"Unplug",,0x00000010
-
-[XenFilt_Interfaces]
-HKR,"Interfaces",,0x00000010
-
[XenBus_Inst.CoInstallers]
CopyFiles=CoInst_CopyFiles
AddReg=CoInst_AddReg
#include <stdlib.h>
#include <xen.h>
-#include <unplug_interface.h>
-
#include "names.h"
#include "registry.h"
#include "fdo.h"
#include "balloon.h"
#include "driver.h"
#include "range_set.h"
+#include "unplug.h"
#include "dbg_print.h"
#include "assert.h"
#include "util.h"
PXENBUS_RANGE_SET_CONTEXT RangeSetContext;
PXENBUS_CACHE_CONTEXT CacheContext;
PXENBUS_GNTTAB_CONTEXT GnttabContext;
+ PXENBUS_UNPLUG_CONTEXT UnplugContext;
PXENBUS_BALLOON_CONTEXT BalloonContext;
XENBUS_DEBUG_INTERFACE DebugInterface;
XENBUS_STORE_INTERFACE StoreInterface;
XENBUS_RANGE_SET_INTERFACE RangeSetInterface;
XENBUS_BALLOON_INTERFACE BalloonInterface;
- XENFILT_UNPLUG_INTERFACE UnplugInterface;
PXENBUS_RANGE_SET RangeSet;
LIST_ENTRY List;
DEFINE_FDO_GET_CONTEXT(RangeSet, PXENBUS_RANGE_SET_CONTEXT)
DEFINE_FDO_GET_CONTEXT(Cache, PXENBUS_CACHE_CONTEXT)
DEFINE_FDO_GET_CONTEXT(Gnttab, PXENBUS_GNTTAB_CONTEXT)
+DEFINE_FDO_GET_CONTEXT(Unplug, PXENBUS_UNPLUG_CONTEXT)
DEFINE_FDO_GET_CONTEXT(Balloon, PXENBUS_BALLOON_CONTEXT)
__drv_functionClass(IO_COMPLETION_ROUTINE)
goto fail7;
}
- if (Fdo->UnplugInterface.Interface.Context != NULL) {
- status = XENFILT_UNPLUG(Acquire, &Fdo->UnplugInterface);
- if (!NT_SUCCESS(status))
- goto fail8;
- }
-
status = __FdoD3ToD0(Fdo);
if (!NT_SUCCESS(status))
- goto fail9;
+ goto fail8;
status = XENBUS_SUSPEND(Register,
&Fdo->SuspendInterface,
Fdo,
&Fdo->SuspendCallbackLate);
if (!NT_SUCCESS(status))
- goto fail10;
+ goto fail9;
KeLowerIrql(Irql);
return STATUS_SUCCESS;
-fail10:
- Error("fail10\n");
-
- __FdoD0ToD3(Fdo);
-
fail9:
Error("fail9\n");
- if (Fdo->UnplugInterface.Interface.Context != NULL)
- XENFILT_UNPLUG(Release, &Fdo->UnplugInterface);
+ __FdoD0ToD3(Fdo);
fail8:
Error("fail8\n");
__FdoD0ToD3(Fdo);
- if (Fdo->UnplugInterface.Interface.Context != NULL)
- XENFILT_UNPLUG(Release, &Fdo->UnplugInterface);
-
if (Fdo->BalloonInterface.Interface.Context != NULL)
XENBUS_BALLOON(Release, &Fdo->BalloonInterface);
HypercallPopulate();
- if (Fdo->UnplugInterface.Interface.Context != NULL)
- XENFILT_UNPLUG(Replay, &Fdo->UnplugInterface);
+ UnplugDevices();
KeLowerIrql(Irql);
(_Size), \
(_Optional))
-VOID
-FdoGetUnplugInterface(
- IN PXENBUS_FDO Fdo,
- OUT PXENFILT_UNPLUG_INTERFACE UnplugInterface
- )
-{
- *UnplugInterface = Fdo->UnplugInterface;
-}
-
static BOOLEAN
FdoIsBalloonEnabled(
IN PXENBUS_FDO Fdo
if (!__FdoIsActive(Fdo))
goto done;
- status = FDO_QUERY_INTERFACE(Fdo,
- XENFILT,
- UNPLUG,
- (PINTERFACE)&Fdo->UnplugInterface,
- sizeof (Fdo->UnplugInterface),
- TRUE);
+ status = DebugInitialize(Fdo, &Fdo->DebugContext);
if (!NT_SUCCESS(status))
goto fail7;
- status = DebugInitialize(Fdo, &Fdo->DebugContext);
+ status = SuspendInitialize(Fdo, &Fdo->SuspendContext);
if (!NT_SUCCESS(status))
goto fail8;
- status = SuspendInitialize(Fdo, &Fdo->SuspendContext);
+ status = SharedInfoInitialize(Fdo, &Fdo->SharedInfoContext);
if (!NT_SUCCESS(status))
goto fail9;
- status = SharedInfoInitialize(Fdo, &Fdo->SharedInfoContext);
+ status = EvtchnInitialize(Fdo, &Fdo->EvtchnContext);
if (!NT_SUCCESS(status))
goto fail10;
- status = EvtchnInitialize(Fdo, &Fdo->EvtchnContext);
+ status = StoreInitialize(Fdo, &Fdo->StoreContext);
if (!NT_SUCCESS(status))
goto fail11;
- status = StoreInitialize(Fdo, &Fdo->StoreContext);
+ status = RangeSetInitialize(Fdo, &Fdo->RangeSetContext);
if (!NT_SUCCESS(status))
goto fail12;
- status = RangeSetInitialize(Fdo, &Fdo->RangeSetContext);
+ status = CacheInitialize(Fdo, &Fdo->CacheContext);
if (!NT_SUCCESS(status))
goto fail13;
- status = CacheInitialize(Fdo, &Fdo->CacheContext);
+ status = GnttabInitialize(Fdo, &Fdo->GnttabContext);
if (!NT_SUCCESS(status))
goto fail14;
- status = GnttabInitialize(Fdo, &Fdo->GnttabContext);
+ status = UnplugInitialize(Fdo, &Fdo->UnplugContext);
if (!NT_SUCCESS(status))
goto fail15;
fail16:
Error("fail16\n");
- GnttabTeardown(Fdo->GnttabContext);
- Fdo->GnttabContext = NULL;
+ UnplugTeardown(Fdo->UnplugContext);
+ Fdo->UnplugContext = NULL;
fail15:
Error("fail15\n");
- CacheTeardown(Fdo->CacheContext);
- Fdo->CacheContext = NULL;
+ GnttabTeardown(Fdo->GnttabContext);
+ Fdo->GnttabContext = NULL;
fail14:
Error("fail14\n");
- RangeSetTeardown(Fdo->RangeSetContext);
- Fdo->RangeSetContext = NULL;
+ CacheTeardown(Fdo->CacheContext);
+ Fdo->CacheContext = NULL;
fail13:
Error("fail13\n");
- StoreTeardown(Fdo->StoreContext);
- Fdo->StoreContext = NULL;
+ RangeSetTeardown(Fdo->RangeSetContext);
+ Fdo->RangeSetContext = NULL;
fail12:
Error("fail12\n");
- EvtchnTeardown(Fdo->EvtchnContext);
- Fdo->EvtchnContext = NULL;
+ StoreTeardown(Fdo->StoreContext);
+ Fdo->StoreContext = NULL;
fail11:
Error("fail11\n");
- SharedInfoTeardown(Fdo->SharedInfoContext);
- Fdo->SharedInfoContext = NULL;
+ EvtchnTeardown(Fdo->EvtchnContext);
+ Fdo->EvtchnContext = NULL;
fail10:
Error("fail10\n");
- SuspendTeardown(Fdo->SuspendContext);
- Fdo->SuspendContext = NULL;
+ SharedInfoTeardown(Fdo->SharedInfoContext);
+ Fdo->SharedInfoContext = NULL;
fail9:
Error("fail9\n");
- DebugTeardown(Fdo->DebugContext);
- Fdo->DebugContext = NULL;
+ SuspendTeardown(Fdo->SuspendContext);
+ Fdo->SuspendContext = NULL;
fail8:
Error("fail8\n");
- RtlZeroMemory(&Fdo->UnplugInterface,
- sizeof (XENFILT_UNPLUG_INTERFACE));
+ DebugTeardown(Fdo->DebugContext);
+ Fdo->DebugContext = NULL;
fail7:
Error("fail7\n");
Fdo->BalloonContext = NULL;
}
+ UnplugTeardown(Fdo->UnplugContext);
+ Fdo->UnplugContext = NULL;
+
GnttabTeardown(Fdo->GnttabContext);
Fdo->GnttabContext = NULL;
DebugTeardown(Fdo->DebugContext);
Fdo->DebugContext = NULL;
- RtlZeroMemory(&Fdo->UnplugInterface,
- sizeof (XENFILT_UNPLUG_INTERFACE));
-
__FdoSetActive(Fdo, FALSE);
}
#define _XENBUS_FDO_H
#include <ntddk.h>
-#include <unplug_interface.h>
#include "driver.h"
#include "types.h"
IN PXENBUS_FDO Fdo
);
-extern VOID
-FdoGetUnplugInterface(
- IN PXENBUS_FDO Fdo,
- OUT PXENFILT_UNPLUG_INTERFACE UnplugInterface
+#include "unplug.h"
+
+extern PXENBUS_UNPLUG_CONTEXT
+FdoGetUnplugContext(
+ IN PXENBUS_FDO Fdo
);
extern NTSTATUS
ULONG RangeSetInterfaceVersion;
ULONG CacheInterfaceVersion;
ULONG GnttabInterfaceVersion;
+ ULONG UnplugInterfaceVersion;
ULONG EmulatedInterfaceVersion;
} XENBUS_PDO_REVISION, *PXENBUS_PDO_REVISION;
-#define DEFINE_REVISION(_N, _S, _SI, _E, _D, _ST, _R, _C, _G, _EM) \
- { (_N), (_S), (_SI), (_E), (_D), (_ST), (_R), (_C), (_G), (_EM) }
+#define DEFINE_REVISION(_N, _S, _SI, _E, _D, _ST, _R, _C, _G, _U, _EM) \
+ { (_N), (_S), (_SI), (_E), (_D), (_ST), (_R), (_C), (_G), (_U), (_EM) }
static XENBUS_PDO_REVISION PdoRevision[] = {
DEFINE_REVISION_TABLE
ASSERT(IMPLY(Index == ARRAYSIZE(PdoRevision) - 1,
Revision->GnttabInterfaceVersion == XENBUS_GNTTAB_INTERFACE_VERSION_MAX));
+ ASSERT3U(Revision->UnplugInterfaceVersion, >=, XENBUS_UNPLUG_INTERFACE_VERSION_MIN);
+ ASSERT3U(Revision->UnplugInterfaceVersion, <=, XENBUS_UNPLUG_INTERFACE_VERSION_MAX);
+ ASSERT(IMPLY(Index == ARRAYSIZE(PdoRevision) - 1,
+ Revision->UnplugInterfaceVersion == XENBUS_UNPLUG_INTERFACE_VERSION_MAX));
+
ASSERT3U(Revision->EmulatedInterfaceVersion, >=, XENFILT_EMULATED_INTERFACE_VERSION_MIN);
ASSERT3U(Revision->EmulatedInterfaceVersion, <=, XENFILT_EMULATED_INTERFACE_VERSION_MAX);
ASSERT(IMPLY(Index == ARRAYSIZE(PdoRevision) - 1,
"RANGE_SET v%u "
"CACHE v%u "
"GNTTAB v%u "
+ "UNPLUG v%u\n"
"EMULATED v%u\n",
Revision->Number,
Revision->SuspendInterfaceVersion,
Revision->RangeSetInterfaceVersion,
Revision->CacheInterfaceVersion,
Revision->GnttabInterfaceVersion,
+ Revision->UnplugInterfaceVersion,
Revision->EmulatedInterfaceVersion);
}
}
DEFINE_PDO_QUERY_INTERFACE(RangeSet)
DEFINE_PDO_QUERY_INTERFACE(Cache)
DEFINE_PDO_QUERY_INTERFACE(Gnttab)
+DEFINE_PDO_QUERY_INTERFACE(Unplug)
struct _INTERFACE_ENTRY {
const GUID *Guid;
{ &GUID_XENBUS_RANGE_SET_INTERFACE, "RANGE_SET_INTERFACE", PdoQueryRangeSetInterface },
{ &GUID_XENBUS_CACHE_INTERFACE, "CACHE_INTERFACE", PdoQueryCacheInterface },
{ &GUID_XENBUS_GNTTAB_INTERFACE, "GNTTAB_INTERFACE", PdoQueryGnttabInterface },
+ { &GUID_XENBUS_UNPLUG_INTERFACE, "UNPLUG_INTERFACE", PdoQueryUnplugInterface },
{ &GUID_XENFILT_EMULATED_INTERFACE, "EMULATED_INTERFACE", PdoDelegateIrp },
{ NULL, NULL, NULL }
};
#include <stdarg.h>
#include <xen.h>
-#include <unplug_interface.h>
-
#include "suspend.h"
#include "thread.h"
#include "fdo.h"
LIST_ENTRY LateList;
XENBUS_DEBUG_INTERFACE DebugInterface;
PXENBUS_DEBUG_CALLBACK DebugCallback;
- XENFILT_UNPLUG_INTERFACE UnplugInterface;
};
#define XENBUS_SUSPEND_TAG 'PSUS'
KIRQL Irql;
NTSTATUS status;
- status = STATUS_NOT_SUPPORTED;
- if (Context->UnplugInterface.Interface.Context == NULL)
- goto fail1;
-
KeRaiseIrql(DISPATCH_LEVEL, &Irql);
LogPrintf(LOG_LEVEL_INFO,
HypercallPopulate();
- XENFILT_UNPLUG(Replay, &Context->UnplugInterface);
+ UnplugDevices();
for (ListEntry = Context->EarlyList.Flink;
ListEntry != &Context->EarlyList;
KeLowerIrql(Irql);
return STATUS_SUCCESS;
-
-fail1:
- Error("fail1 (%08x)\n", status);
-
- return status;
}
static ULONG
if (!NT_SUCCESS(status))
goto fail2;
- if (Context->UnplugInterface.Interface.Context != NULL) {
- status = XENFILT_UNPLUG(Acquire, &Context->UnplugInterface);
-
- if (!NT_SUCCESS(status))
- goto fail3;
- }
-
Trace("<====\n");
done:
return STATUS_SUCCESS;
-fail3:
- Error("fail3\n");
-
- XENBUS_DEBUG(Deregister,
- &Context->DebugInterface,
- Context->DebugCallback);
- Context->DebugCallback = NULL;
-
fail2:
Error("fail2\n");
Context->Count = 0;
- if (Context->UnplugInterface.Interface.Context != NULL)
- XENFILT_UNPLUG(Release, &Context->UnplugInterface);
-
XENBUS_DEBUG(Deregister,
&Context->DebugInterface,
Context->DebugCallback);
sizeof ((*Context)->DebugInterface));
ASSERT(NT_SUCCESS(status));
- FdoGetUnplugInterface(Fdo, &(*Context)->UnplugInterface);
-
InitializeListHead(&(*Context)->EarlyList);
InitializeListHead(&(*Context)->LateList);
KeInitializeSpinLock(&(*Context)->Lock);
Context->Fdo = NULL;
- RtlZeroMemory(&Context->UnplugInterface,
- sizeof (XENFILT_UNPLUG_INTERFACE));
-
RtlZeroMemory(&Context->DebugInterface,
sizeof (XENBUS_DEBUG_INTERFACE));
--- /dev/null
+/* Copyright (c) Citrix Systems Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms,
+ * with or without modification, are permitted provided
+ * that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the
+ * following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the
+ * following disclaimer in the documentation and/or other
+ * materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <ntddk.h>
+#include <ntstrsafe.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <xen.h>
+
+#include "unplug.h"
+#include "fdo.h"
+#include "mutex.h"
+#include "dbg_print.h"
+#include "assert.h"
+#include "util.h"
+
+struct _XENBUS_UNPLUG_CONTEXT {
+ KSPIN_LOCK Lock;
+ LONG References;
+ MUTEX Mutex;
+};
+
+#define XENBUS_UNPLUG_TAG 'LPNU'
+
+static FORCEINLINE PVOID
+__UnplugAllocate(
+ IN ULONG Length
+ )
+{
+ return __AllocatePoolWithTag(NonPagedPool, Length, XENBUS_UNPLUG_TAG);
+}
+
+static FORCEINLINE VOID
+__UnplugFree(
+ IN PVOID Buffer
+ )
+{
+ ExFreePoolWithTag(Buffer, XENBUS_UNPLUG_TAG);
+}
+
+static VOID
+UnplugRequest(
+ IN PINTERFACE Interface,
+ IN XENBUS_UNPLUG_DEVICE_TYPE Type,
+ IN BOOLEAN Make
+ )
+{
+ PXENBUS_UNPLUG_CONTEXT Context = Interface->Context;
+
+ ASSERT3U(KeGetCurrentIrql(), ==, PASSIVE_LEVEL);
+
+ AcquireMutex(&Context->Mutex);
+
+ switch (Type) {
+ case XENBUS_UNPLUG_DEVICE_TYPE_NICS:
+ Info("NICS (%s)\n", (Make) ? "MAKE" : "REVOKE");
+
+ if (Make)
+ (VOID) UnplugIncrementValue(UNPLUG_NICS);
+ else
+ (VOID) UnplugDecrementValue(UNPLUG_NICS);
+
+ break;
+
+ case XENBUS_UNPLUG_DEVICE_TYPE_DISKS:
+ Info("DISKS (%s)\n", (Make) ? "MAKE" : "REVOKE");
+
+ if (Make)
+ (VOID) UnplugIncrementValue(UNPLUG_DISKS);
+ else
+ (VOID) UnplugDecrementValue(UNPLUG_DISKS);
+
+ break;
+
+ default:
+ ASSERT(FALSE);
+ break;
+ }
+
+ ReleaseMutex(&Context->Mutex);
+}
+
+static NTSTATUS
+UnplugAcquire(
+ IN PINTERFACE Interface
+ )
+{
+ PXENBUS_UNPLUG_CONTEXT Context = Interface->Context;
+ KIRQL Irql;
+
+ KeAcquireSpinLock(&Context->Lock, &Irql);
+
+ if (Context->References++ != 0)
+ goto done;
+
+ Trace("<===>\n");
+
+done:
+ KeReleaseSpinLock(&Context->Lock, Irql);
+
+ return STATUS_SUCCESS;
+}
+
+static VOID
+UnplugRelease(
+ IN PINTERFACE Interface
+ )
+{
+ PXENBUS_UNPLUG_CONTEXT Context = Interface->Context;
+ KIRQL Irql;
+
+ KeAcquireSpinLock(&Context->Lock, &Irql);
+
+ if (--Context->References > 0)
+ goto done;
+
+ Trace("<===>\n");
+
+done:
+ KeReleaseSpinLock(&Context->Lock, Irql);
+}
+
+static struct _XENBUS_UNPLUG_INTERFACE_V1 UnplugInterfaceVersion1 = {
+ { sizeof (struct _XENBUS_UNPLUG_INTERFACE_V1), 1, NULL, NULL, NULL },
+ UnplugAcquire,
+ UnplugRelease,
+ UnplugRequest
+};
+
+NTSTATUS
+UnplugInitialize(
+ IN PXENBUS_FDO Fdo,
+ OUT PXENBUS_UNPLUG_CONTEXT *Context
+ )
+{
+ NTSTATUS status;
+
+ UNREFERENCED_PARAMETER(Fdo);
+
+ Trace("====>\n");
+
+ *Context = __UnplugAllocate(sizeof (XENBUS_UNPLUG_CONTEXT));
+
+ status = STATUS_NO_MEMORY;
+ if (*Context == NULL)
+ goto fail1;
+
+ KeInitializeSpinLock(&(*Context)->Lock);
+ InitializeMutex(&(*Context)->Mutex);
+
+ Trace("<====\n");
+
+ return STATUS_SUCCESS;
+
+fail1:
+ Error("fail1 (%08x)\n", status);
+
+ return status;
+}
+
+NTSTATUS
+UnplugGetInterface(
+ IN PXENBUS_UNPLUG_CONTEXT Context,
+ IN ULONG Version,
+ IN OUT PINTERFACE Interface,
+ IN ULONG Size
+ )
+{
+ NTSTATUS status;
+
+ ASSERT(Context != NULL);
+
+ switch (Version) {
+ case 1: {
+ struct _XENBUS_UNPLUG_INTERFACE_V1 *UnplugInterface;
+
+ UnplugInterface = (struct _XENBUS_UNPLUG_INTERFACE_V1 *)Interface;
+
+ status = STATUS_BUFFER_OVERFLOW;
+ if (Size < sizeof (struct _XENBUS_UNPLUG_INTERFACE_V1))
+ break;
+
+ *UnplugInterface = UnplugInterfaceVersion1;
+
+ ASSERT3U(Interface->Version, ==, Version);
+ Interface->Context = Context;
+
+ status = STATUS_SUCCESS;
+ break;
+ }
+ default:
+ status = STATUS_NOT_SUPPORTED;
+ break;
+ }
+
+ return status;
+}
+
+VOID
+UnplugTeardown(
+ IN PXENBUS_UNPLUG_CONTEXT Context
+ )
+{
+ Trace("====>\n");
+
+ RtlZeroMemory(&Context->Mutex, sizeof (MUTEX));
+ RtlZeroMemory(&Context->Lock, sizeof (KSPIN_LOCK));
+
+ ASSERT(IsZeroMemory(Context, sizeof (XENBUS_UNPLUG_CONTEXT)));
+ __UnplugFree(Context);
+
+ Trace("<====\n");
+}
--- /dev/null
+/* Copyright (c) Citrix Systems Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms,
+ * with or without modification, are permitted provided
+ * that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the
+ * following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the
+ * following disclaimer in the documentation and/or other
+ * materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef _XENBUS_UNPLUG_H
+#define _XENBUS_UNPLUG_H
+
+#include <ntddk.h>
+#include <xen.h>
+#include <unplug_interface.h>
+
+typedef struct _XENBUS_UNPLUG_CONTEXT XENBUS_UNPLUG_CONTEXT, *PXENBUS_UNPLUG_CONTEXT;
+
+#include "fdo.h"
+
+extern NTSTATUS
+UnplugInitialize(
+ IN PXENBUS_FDO Fdo,
+ OUT PXENBUS_UNPLUG_CONTEXT *Context
+ );
+
+extern NTSTATUS
+UnplugGetInterface(
+ IN PXENBUS_UNPLUG_CONTEXT Context,
+ IN ULONG Version,
+ IN OUT PINTERFACE Interface,
+ IN ULONG Size
+ );
+
+extern VOID
+UnplugTeardown(
+ IN PXENBUS_UNPLUG_CONTEXT Context
+ );
+
+#endif // _XENBUS_UNPLUG_H
#include "pdo.h"
#include "driver.h"
#include "emulated.h"
-#include "unplug.h"
#include "mutex.h"
#include "dbg_print.h"
#include "assert.h"
typedef struct _XENFILT_DRIVER {
PDRIVER_OBJECT DriverObject;
HANDLE ParametersKey;
- HANDLE UnplugKey;
PCHAR ActiveDeviceID;
PCHAR ActiveInstanceID;
XENFILT_FILTER_STATE FilterState;
PXENFILT_EMULATED_CONTEXT EmulatedContext;
- PXENFILT_UNPLUG_CONTEXT UnplugContext;
-
XENFILT_EMULATED_INTERFACE EmulatedInterface;
- XENFILT_UNPLUG_INTERFACE UnplugInterface;
-
- BOOLEAN UnplugAcquired;
} XENFILT_DRIVER, *PXENFILT_DRIVER;
static XENFILT_DRIVER Driver;
}
static FORCEINLINE VOID
-__DriverSetUnplugKey(
- IN HANDLE Key
+__DriverSetEmulatedContext(
+ IN PXENFILT_EMULATED_CONTEXT Context
)
{
- Driver.UnplugKey = Key;
+ Driver.EmulatedContext = Context;
}
-static FORCEINLINE HANDLE
-__DriverGetUnplugKey(
+static FORCEINLINE PXENFILT_EMULATED_CONTEXT
+__DriverGetEmulatedContext(
VOID
)
{
- return Driver.UnplugKey;
+ return Driver.EmulatedContext;
}
-HANDLE
-DriverGetUnplugKey(
+PXENFILT_EMULATED_CONTEXT
+DriverGetEmulatedContext(
VOID
)
{
- return __DriverGetUnplugKey();
+ return __DriverGetEmulatedContext();
}
static FORCEINLINE VOID
--Driver.References;
}
-#define DEFINE_DRIVER_GET_CONTEXT(_Interface, _Type) \
-static FORCEINLINE _Type \
-__DriverGet ## _Interface ## Context( \
- VOID \
- ) \
-{ \
- return Driver. ## _Interface ## Context; \
-} \
- \
-_Type \
-DriverGet ## _Interface ## Context( \
- VOID \
- ) \
-{ \
- return __DriverGet ## _Interface ## Context(); \
-}
-
-DEFINE_DRIVER_GET_CONTEXT(Emulated, PXENFILT_EMULATED_CONTEXT)
-DEFINE_DRIVER_GET_CONTEXT(Unplug, PXENFILT_UNPLUG_CONTEXT)
-
#define SERVICES_KEY L"\\Registry\\Machine\\SYSTEM\\CurrentControlSet\\Services"
#define SERVICE_KEY(_Driver) \
case XENFILT_FILTER_ENABLED: {
PLIST_ENTRY ListEntry;
BOOLEAN Present;
- NTSTATUS status;
// Assume all FDOs have enumerated until we know otherwise
Driver.FilterState = XENFILT_FILTER_PENDING;
Info("ACTIVE DEVICE %sPRESENT\n", (!Present) ? "NOT " : "");
- if (Present) {
- status = XENFILT_UNPLUG(Acquire, &Driver.UnplugInterface);
- Driver.UnplugAcquired = NT_SUCCESS(status) ? TRUE : FALSE;
- }
+ if (Present)
+ UnplugDevices();
Info("PENDING\n");
break;
)
{
HANDLE ParametersKey;
- HANDLE UnplugKey;
ASSERT3P(DriverObject, ==, __DriverGetDriverObject());
RtlZeroMemory(&Driver.List, sizeof (LIST_ENTRY));
RtlZeroMemory(&Driver.Mutex, sizeof (MUTEX));
- if (Driver.UnplugAcquired) {
- XENFILT_UNPLUG(Release, &Driver.UnplugInterface);
-
- Driver.UnplugAcquired = FALSE;
- }
-
XENFILT_EMULATED(Release, &Driver.EmulatedInterface);
- RtlZeroMemory(&Driver.UnplugInterface,
- sizeof (XENFILT_UNPLUG_INTERFACE));
-
RtlZeroMemory(&Driver.EmulatedInterface,
sizeof (XENFILT_EMULATED_INTERFACE));
- UnplugTeardown(Driver.UnplugContext);
- Driver.UnplugContext = NULL;
-
EmulatedTeardown(Driver.EmulatedContext);
Driver.EmulatedContext = NULL;
Driver.ActiveInstanceID = NULL;
}
- UnplugKey = __DriverGetUnplugKey();
- __DriverSetUnplugKey(NULL);
- RegistryCloseKey(UnplugKey);
-
ParametersKey = __DriverGetParametersKey();
__DriverSetParametersKey(NULL);
RegistryCloseKey(ParametersKey);
NTSTATUS
DriverEntry(
- IN PDRIVER_OBJECT DriverObject,
- IN PUNICODE_STRING RegistryPath
+ IN PDRIVER_OBJECT DriverObject,
+ IN PUNICODE_STRING RegistryPath
)
{
- HANDLE ServiceKey;
- HANDLE ParametersKey;
- HANDLE UnplugKey;
- ULONG Index;
- NTSTATUS status;
+ HANDLE ServiceKey;
+ HANDLE ParametersKey;
+ PXENFILT_EMULATED_CONTEXT EmulatedContext;
+ ULONG Index;
+ NTSTATUS status;
ASSERT3P(__DriverGetDriverObject(), ==, NULL);
__DriverSetParametersKey(ParametersKey);
- status = RegistryOpenSubKey(ServiceKey, "Unplug", KEY_READ, &UnplugKey);
+ status = DriverSetActiveDeviceInstance();
if (!NT_SUCCESS(status))
goto fail4;
- __DriverSetUnplugKey(UnplugKey);
-
- status = DriverSetActiveDeviceInstance();
+ status = EmulatedInitialize(&EmulatedContext);
if (!NT_SUCCESS(status))
goto fail5;
- status = EmulatedInitialize(&Driver.EmulatedContext);
- if (!NT_SUCCESS(status))
- goto fail6;
-
- status = UnplugInitialize(&Driver.UnplugContext);
- if (!NT_SUCCESS(status))
- goto fail7;
+ __DriverSetEmulatedContext(EmulatedContext);
status = EmulatedGetInterface(__DriverGetEmulatedContext(),
XENFILT_EMULATED_INTERFACE_VERSION_MAX,
ASSERT(NT_SUCCESS(status));
ASSERT(Driver.EmulatedInterface.Interface.Context != NULL);
- status = UnplugGetInterface(__DriverGetUnplugContext(),
- XENFILT_UNPLUG_INTERFACE_VERSION_MAX,
- (PINTERFACE)&Driver.UnplugInterface,
- sizeof (Driver.UnplugInterface));
- ASSERT(NT_SUCCESS(status));
- ASSERT(Driver.UnplugInterface.Interface.Context != NULL);
-
status = XENFILT_EMULATED(Acquire, &Driver.EmulatedInterface);
if (!NT_SUCCESS(status))
- goto fail8;
+ goto fail6;
RegistryCloseKey(ServiceKey);
Trace("<====\n");
return STATUS_SUCCESS;
-fail8:
- Error("fail8\n");
-
- RtlZeroMemory(&Driver.UnplugInterface,
- sizeof (XENFILT_UNPLUG_INTERFACE));
-
- RtlZeroMemory(&Driver.EmulatedInterface,
- sizeof (XENFILT_EMULATED_INTERFACE));
-
- UnplugTeardown(Driver.UnplugContext);
- Driver.UnplugContext = NULL;
-
-fail7:
- Error("fail7\n");
+fail6:
+ Error("fail6\n");
EmulatedTeardown(Driver.EmulatedContext);
Driver.EmulatedContext = NULL;
-fail6:
- Error("fail6\n");
+fail5:
+ Error("fail5\n");
if (Driver.ActiveDeviceID != NULL) {
__DriverFree(Driver.ActiveDeviceID);
Driver.ActiveInstanceID = NULL;
}
-fail5:
- Error("fail5\n");
-
- __DriverSetUnplugKey(NULL);
- RegistryCloseKey(UnplugKey);
-
fail4:
Error("fail4\n");
VOID
);
-extern HANDLE
-DriverGetUnplugKey(
- VOID
- );
-
extern PCHAR
DriverGetActiveDeviceID(
VOID
VOID
);
-#include "unplug.h"
-
-PXENFILT_UNPLUG_CONTEXT
-DriverGetUnplugContext(
- VOID
- );
-
typedef struct _XENFILT_FDO XENFILT_FDO, *PXENFILT_FDO;
typedef struct _XENFILT_PDO XENFILT_PDO, *PXENFILT_PDO;
} \
DEFINE_PDO_QUERY_INTERFACE(Emulated)
-DEFINE_PDO_QUERY_INTERFACE(Unplug)
struct _INTERFACE_ENTRY {
const GUID *Guid;
struct _INTERFACE_ENTRY PdoInterfaceTable[] = {
DEFINE_INTERFACE_ENTRY(EMULATED_INTERFACE, Emulated),
- DEFINE_INTERFACE_ENTRY(UNPLUG_INTERFACE, Unplug),
{ NULL, NULL, NULL }
};
+++ /dev/null
-/* Copyright (c) Citrix Systems Inc.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms,
- * with or without modification, are permitted provided
- * that the following conditions are met:
- *
- * * Redistributions of source code must retain the above
- * copyright notice, this list of conditions and the
- * following disclaimer.
- * * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the
- * following disclaimer in the documentation and/or other
- * materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
- * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
- * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
- * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#include <ntddk.h>
-#include <ntstrsafe.h>
-#include <stdlib.h>
-#include <stdarg.h>
-#include <xen.h>
-#include <version.h>
-
-#include "driver.h"
-#include "high.h"
-#include "registry.h"
-#include "unplug.h"
-#include "dbg_print.h"
-#include "assert.h"
-#include "util.h"
-
-struct _XENFILT_UNPLUG_CONTEXT {
- KSPIN_LOCK Lock;
- LONG References;
- HIGH_LOCK UnplugLock;
- BOOLEAN BlackListed;
- BOOLEAN UnplugDisks;
- BOOLEAN UnplugNics;
- BOOLEAN BootEmulated;
-};
-
-typedef enum _XENFILT_UNPLUG_TYPE {
- XENFILT_UNPLUG_DISKS = 0,
- XENFILT_UNPLUG_NICS
-} XENFILT_UNPLUG_TYPE, *PXENFILT_UNPLUG_TYPE;
-
-#define XENFILT_UNPLUG_TAG 'LPNU'
-
-static FORCEINLINE PVOID
-__UnplugAllocate(
- IN ULONG Length
- )
-{
- return __AllocatePoolWithTag(NonPagedPool, Length, XENFILT_UNPLUG_TAG);
-}
-
-static FORCEINLINE VOID
-__UnplugFree(
- IN PVOID Buffer
- )
-{
- ExFreePoolWithTag(Buffer, XENFILT_UNPLUG_TAG);
-}
-
-static VOID
-UnplugGetFlags(
- IN PXENFILT_UNPLUG_CONTEXT Context
- )
-{
- HANDLE Key;
- DWORD Value;
- NTSTATUS status;
-
- Context->BootEmulated = FALSE;
-
- Key = DriverGetParametersKey();
-
- status = RegistryQueryDwordValue(Key,
- "BootEmulated",
- &Value);
- if (NT_SUCCESS(status)) {
- LogPrintf(LOG_LEVEL_WARNING,
- "UNPLUG: BOOT_EMULATED %d\n",
- Value);
-
- Context->BootEmulated = (Value == 1) ? TRUE : FALSE;
- }
-}
-
-static VOID
-UnplugRequest(
- IN PXENFILT_UNPLUG_CONTEXT Context,
- IN XENFILT_UNPLUG_TYPE Type
- )
-{
- switch (Type) {
- case XENFILT_UNPLUG_DISKS:
- if (Context->BootEmulated) {
-#pragma prefast(suppress:28138)
- WRITE_PORT_USHORT((PUSHORT)0x10, 0x0004);
-
- LogPrintf(LOG_LEVEL_WARNING, "UNPLUG: AUX DISKS\n");
- } else {
-#pragma prefast(suppress:28138)
- WRITE_PORT_USHORT((PUSHORT)0x10, 0x0001);
-
- LogPrintf(LOG_LEVEL_WARNING, "UNPLUG: DISKS\n");
- }
- break;
- case XENFILT_UNPLUG_NICS:
-#pragma prefast(suppress:28138)
- WRITE_PORT_USHORT((PUSHORT)0x10, 0x0002);
-
- LogPrintf(LOG_LEVEL_WARNING, "UNPLUG: NICS\n");
- break;
- default:
- ASSERT(FALSE);
- }
-}
-
-static NTSTATUS
-UnplugPreamble(
- IN PXENFILT_UNPLUG_CONTEXT Context
- )
-{
- USHORT Magic;
- UCHAR Version;
- NTSTATUS status;
-
- // See docs/misc/hvm-emulated-unplug.markdown for details of the
- // protocol in use here
-
-#pragma prefast(suppress:28138)
- Magic = READ_PORT_USHORT((PUSHORT)0x10);
-
- if (Magic == 0xd249) {
- Context->BlackListed = TRUE;
- goto done;
- }
-
- status = STATUS_NOT_SUPPORTED;
- if (Magic != 0x49d2)
- goto fail1;
-
-#pragma prefast(suppress:28138)
- Version = READ_PORT_UCHAR((PUCHAR)0x12);
- if (Version != 0) {
-#pragma prefast(suppress:28138)
- WRITE_PORT_USHORT((PUSHORT)0x12, 0xFFFF); // FIXME
-
-#pragma prefast(suppress:28138)
- WRITE_PORT_ULONG((PULONG)0x10,
- (MAJOR_VERSION << 16) |
- (MINOR_VERSION << 8) |
- MICRO_VERSION);
-
-#pragma prefast(suppress:28138)
- Magic = READ_PORT_USHORT((PUSHORT)0x10);
- if (Magic == 0xd249)
- Context->BlackListed = TRUE;
- }
-
-done:
- LogPrintf(LOG_LEVEL_WARNING,
- "UNPLUG: PRE-AMBLE (DRIVERS %s)\n",
- (Context->BlackListed) ? "BLACKLISTED" : "NOT BLACKLISTED");
-
- return STATUS_SUCCESS;
-
-fail1:
- return status;
-}
-
-#define HKEY_LOCAL_MACHINE "\\Registry\\Machine"
-#define SERVICES_KEY HKEY_LOCAL_MACHINE "\\SYSTEM\\CurrentControlSet\\Services"
-
-static VOID
-UnplugCheckForPVDisks(
- IN PXENFILT_UNPLUG_CONTEXT Context
- )
-{
- HANDLE UnplugKey;
- PANSI_STRING ServiceNames;
- ULONG Count;
- ULONG Index;
- KIRQL Irql;
- NTSTATUS status;
-
- ASSERT3U(KeGetCurrentIrql(), ==, PASSIVE_LEVEL);
-
- UnplugKey = DriverGetUnplugKey();
-
- ServiceNames = NULL;
-
- status = RegistryQuerySzValue(UnplugKey,
- "DISKS",
- &ServiceNames);
- if (!NT_SUCCESS(status))
- goto done;
-
- Count = 0;
- for (Index = 0; ServiceNames[Index].Buffer != NULL; Index++)
- if (_stricmp(ServiceNames[Index].Buffer, "XENVBD") == 0)
- Count++;
-
- if (Count < 1)
- goto done;
-
- AcquireHighLock(&Context->UnplugLock, &Irql);
- Context->UnplugDisks = TRUE;
- ReleaseHighLock(&Context->UnplugLock, Irql);
-
-done:
- Info("%s\n", (Context->UnplugDisks) ? "PRESENT" : "NOT PRESENT");
-
- if (ServiceNames != NULL)
- RegistryFreeSzValue(ServiceNames);
-}
-
-static VOID
-UnplugCheckForPVNics(
- IN PXENFILT_UNPLUG_CONTEXT Context
- )
-{
- HANDLE UnplugKey;
- PANSI_STRING ServiceNames;
- ULONG Count;
- ULONG Index;
- KIRQL Irql;
- NTSTATUS status;
-
- ASSERT3U(KeGetCurrentIrql(), ==, PASSIVE_LEVEL);
-
- UnplugKey = DriverGetUnplugKey();
-
- ServiceNames = NULL;
-
- status = RegistryQuerySzValue(UnplugKey,
- "NICS",
- &ServiceNames);
- if (!NT_SUCCESS(status))
- goto done;
-
- Count = 0;
- for (Index = 0; ServiceNames[Index].Buffer != NULL; Index++)
- if (_stricmp(ServiceNames[Index].Buffer, "XENVIF") == 0 ||
- _stricmp(ServiceNames[Index].Buffer, "XENNET") == 0)
- Count++;
-
- if (Count < 2)
- goto done;
-
- AcquireHighLock(&Context->UnplugLock, &Irql);
- Context->UnplugNics = TRUE;
- ReleaseHighLock(&Context->UnplugLock, Irql);
-
-done:
- Info("%s\n", (Context->UnplugNics) ? "PRESENT" : "NOT PRESENT");
-
- if (ServiceNames != NULL)
- RegistryFreeSzValue(ServiceNames);
-}
-
-static VOID
-UnplugReplay(
- IN PINTERFACE Interface
- )
-{
- PXENFILT_UNPLUG_CONTEXT Context = Interface->Context;
- KIRQL Irql;
- NTSTATUS status;
-
- AcquireHighLock(&Context->UnplugLock, &Irql);
-
- status = UnplugPreamble(Context);
- ASSERT(NT_SUCCESS(status));
-
- if (Context->UnplugDisks)
- UnplugRequest(Context, XENFILT_UNPLUG_DISKS);
-
- if (Context->UnplugNics)
- UnplugRequest(Context, XENFILT_UNPLUG_NICS);
-
- ReleaseHighLock(&Context->UnplugLock, Irql);
-}
-
-NTSTATUS
-UnplugAcquire(
- IN PINTERFACE Interface
- )
-{
- PXENFILT_UNPLUG_CONTEXT Context = Interface->Context;
- KIRQL Irql;
- NTSTATUS status;
-
- KeAcquireSpinLock(&Context->Lock, &Irql);
-
- if (Context->References++ != 0)
- goto done;
-
- Trace("====>\n");
-
- (VOID)__AcquireHighLock(&Context->UnplugLock);
-
- status = UnplugPreamble(Context);
- if (!NT_SUCCESS(status))
- goto fail1;
-
- if (Context->UnplugDisks)
- UnplugRequest(Context, XENFILT_UNPLUG_DISKS);
-
- if (Context->UnplugNics)
- UnplugRequest(Context, XENFILT_UNPLUG_NICS);
-
- ReleaseHighLock(&Context->UnplugLock, DISPATCH_LEVEL);
-
- Trace("<====\n");
-
-done:
- KeReleaseSpinLock(&Context->Lock, Irql);
-
- return STATUS_SUCCESS;
-
-fail1:
- Error("fail1 (%08x)\n", status);
-
- ReleaseHighLock(&Context->UnplugLock, DISPATCH_LEVEL);
-
- KeReleaseSpinLock(&Context->Lock, Irql);
-
- return status;
-}
-
-VOID
-UnplugRelease(
- IN PINTERFACE Interface
- )
-{
- PXENFILT_UNPLUG_CONTEXT Context = Interface->Context;
- KIRQL Irql;
-
- KeAcquireSpinLock(&Context->Lock, &Irql);
-
- if (--Context->References > 0)
- goto done;
-
- Trace("====>\n");
-
- Context->BlackListed = FALSE;
-
- Trace("<====\n");
-
-done:
- KeReleaseSpinLock(&Context->Lock, Irql);
-}
-
-static struct _XENFILT_UNPLUG_INTERFACE_V1 UnplugInterfaceVersion1 = {
- { sizeof (struct _XENFILT_UNPLUG_INTERFACE_V1), 1, NULL, NULL, NULL },
- UnplugAcquire,
- UnplugRelease,
- UnplugReplay
-};
-
-NTSTATUS
-UnplugInitialize(
- OUT PXENFILT_UNPLUG_CONTEXT *Context
- )
-{
- NTSTATUS status;
-
- Trace("====>\n");
-
- *Context = __UnplugAllocate(sizeof (XENFILT_UNPLUG_CONTEXT));
-
- status = STATUS_NO_MEMORY;
- if (*Context == NULL)
- goto fail1;
-
- UnplugCheckForPVDisks(*Context);
- UnplugCheckForPVNics(*Context);
- UnplugGetFlags(*Context);
-
- KeInitializeSpinLock(&(*Context)->Lock);
- InitializeHighLock(&(*Context)->UnplugLock);
-
- Trace("<====\n");
-
- return STATUS_SUCCESS;
-
-fail1:
- Error("fail1 (%08x)\n", status);
-
- return status;
-}
-
-NTSTATUS
-UnplugGetInterface(
- IN PXENFILT_UNPLUG_CONTEXT Context,
- IN ULONG Version,
- IN OUT PINTERFACE Interface,
- IN ULONG Size
- )
-{
- NTSTATUS status;
-
- ASSERT(Context != NULL);
-
- switch (Version) {
- case 1: {
- struct _XENFILT_UNPLUG_INTERFACE_V1 *UnplugInterface;
-
- UnplugInterface = (struct _XENFILT_UNPLUG_INTERFACE_V1 *)Interface;
-
- status = STATUS_BUFFER_OVERFLOW;
- if (Size < sizeof (struct _XENFILT_UNPLUG_INTERFACE_V1))
- break;
-
- *UnplugInterface = UnplugInterfaceVersion1;
-
- ASSERT3U(Interface->Version, ==, Version);
- Interface->Context = Context;
-
- status = STATUS_SUCCESS;
- break;
- }
- default:
- status = STATUS_NOT_SUPPORTED;
- break;
- }
-
- return status;
-}
-
-VOID
-UnplugTeardown(
- IN PXENFILT_UNPLUG_CONTEXT Context
- )
-{
- Trace("====>\n");
-
- Context->BootEmulated = FALSE;
- Context->UnplugNics = FALSE;
- Context->UnplugDisks = FALSE;
-
- RtlZeroMemory(&Context->UnplugLock, sizeof (HIGH_LOCK));
- RtlZeroMemory(&Context->Lock, sizeof (KSPIN_LOCK));
-
- ASSERT(IsZeroMemory(Context, sizeof (XENFILT_UNPLUG_CONTEXT)));
- __UnplugFree(Context);
-
- Trace("<====\n");
-}
+++ /dev/null
-/* Copyright (c) Citrix Systems Inc.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms,
- * with or without modification, are permitted provided
- * that the following conditions are met:
- *
- * * Redistributions of source code must retain the above
- * copyright notice, this list of conditions and the
- * following disclaimer.
- * * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the
- * following disclaimer in the documentation and/or other
- * materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
- * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
- * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
- * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#ifndef _XENFILT_UNPLUG_H
-#define _XENFILT_UNPLUG_H
-
-#include <ntddk.h>
-#include <xen.h>
-#include <unplug_interface.h>
-
-typedef struct _XENFILT_UNPLUG_CONTEXT XENFILT_UNPLUG_CONTEXT, *PXENFILT_UNPLUG_CONTEXT;
-
-extern NTSTATUS
-UnplugInitialize(
- OUT PXENFILT_UNPLUG_CONTEXT *Context
- );
-
-extern NTSTATUS
-UnplugGetInterface(
- IN PXENFILT_UNPLUG_CONTEXT Context,
- IN ULONG Version,
- IN OUT PINTERFACE Interface,
- IN ULONG Size
- );
-
-extern VOID
-UnplugTeardown(
- IN PXENFILT_UNPLUG_CONTEXT Context
- );
-
-#endif // _XENFILT_UNPLUG_H
<ClCompile Include="..\..\src\xen\process.c" />
<ClCompile Include="..\..\src\xen\acpi.c" />
<ClCompile Include="..\..\src\xen\system.c" />
+ <ClCompile Include="..\..\src\xen\unplug.c" />
</ItemGroup>
<ItemGroup>
<MASM Include="..\..\src\xen\amd64\hypercall_thunk.asm">
<ClCompile Include="..\..\src\xenbus\balloon.c" />
<ClCompile Include="..\..\src\xenbus\cache.c" />
<ClCompile Include="..\..\src\xenbus\hash_table.c" />
+ <ClCompile Include="..\..\src\xenbus\unplug.c" />
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="..\..\src\xenbus\xenbus.rc" />
<ItemGroup>
<ClCompile Include="../../src/common/registry.c" />
<ClCompile Include="../../src/xenfilt/driver.c" />
- <ClCompile Include="../../src/xenfilt/unplug.c" />
<ClCompile Include="../../src/xenfilt/emulated.c" />
<ClCompile Include="../../src/xenfilt/fdo.c" />
<ClCompile Include="../../src/xenfilt/pdo.c" />
<ClCompile Include="..\..\src\xen\process.c" />
<ClCompile Include="..\..\src\xen\acpi.c" />
<ClCompile Include="..\..\src\xen\system.c" />
+ <ClCompile Include="..\..\src\xen\unplug.c" />
</ItemGroup>
<ItemGroup>
<MASM Include="..\..\src\xen\amd64\hypercall_thunk.asm">
<ClCompile Include="..\..\src\xenbus\balloon.c" />
<ClCompile Include="..\..\src\xenbus\cache.c" />
<ClCompile Include="..\..\src\xenbus\hash_table.c" />
+ <ClCompile Include="..\..\src\xenbus\unplug.c" />
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="..\..\src\xenbus\xenbus.rc" />
<ItemGroup>
<ClCompile Include="../../src/common/registry.c" />
<ClCompile Include="../../src/xenfilt/driver.c" />
- <ClCompile Include="../../src/xenfilt/unplug.c" />
<ClCompile Include="../../src/xenfilt/emulated.c" />
<ClCompile Include="../../src/xenfilt/fdo.c" />
<ClCompile Include="../../src/xenfilt/pdo.c" />