#include <xencrsh_interface.h>
#include <xenvbd-ntstrsafe.h>
+// Feature Overrides From Registry Values
+typedef struct _XENVBD_FEATURE_OVERRIDE {
+ const CHAR *Name;
+ ULONG Value;
+ BOOLEAN Present;
+} XENVBD_FEATURE_OVERRIDE, *PXENVBD_FEATURE_OVERRIDE;
+
typedef struct _XENVBD_DRIVER {
- HANDLE ParametersKey;
- PDRIVER_DISPATCH StorPortDispatchPnp;
- PDRIVER_DISPATCH StorPortDispatchPower;
- PDRIVER_UNLOAD StorPortDriverUnload;
- PXENVBD_FDO Fdo;
- KSPIN_LOCK Lock;
+ HANDLE ParametersKey;
+ PDRIVER_DISPATCH StorPortDispatchPnp;
+ PDRIVER_DISPATCH StorPortDispatchPower;
+ PDRIVER_UNLOAD StorPortDriverUnload;
+ PXENVBD_FDO Fdo;
+ KSPIN_LOCK Lock;
+ XENVBD_FEATURE_OVERRIDE FeatureOverride[NumberOfFeatures];
} XENVBD_DRIVER;
static XENVBD_DRIVER Driver;
Trace("<=== (Irql=%d)\n", KeGetCurrentIrql());
}
-DRIVER_INITIALIZE DriverEntry;
+__drv_requiresIRQL(PASSIVE_LEVEL)
+static FORCEINLINE VOID
+__DriverInitializeOverrides(
+ VOID
+ )
+{
+ ULONG Index;
+ struct {
+ const CHAR *Name;
+ XENVBD_FEATURE Feature;
+ } Mapping[] =
+ {
+ { "removable" , FeatureRemovable },
+ { "feature-persistent", FeaturePersistent },
+ { "feature-max-indirect-segments", FeatureMaxIndirectSegments },
+ { "feature-barrier", FeatureBarrier },
+ { "feature-flush-cache", FeatureFlushCache },
+ { "feature-discard", FeatureDiscard },
+ { "discard-enable", FeatureDiscardEnable },
+ { "discard-secure", FeatureDiscardSecure },
+ { "discard-alignment", FeatureDiscardAlignment },
+ { "discard-granularity", FeatureDiscardGranularity }
+ };
+
+ for (Index = 0; Index < ARRAYSIZE(Mapping); Index++) {
+ XENVBD_FEATURE Feature = Mapping[Index].Feature;
+ const CHAR *Name = Mapping[Index].Name;
+ ULONG Value;
+ NTSTATUS status;
+
+ Driver.FeatureOverride[Feature].Name = Name;
+
+ status = RegistryQueryDwordValue(__DriverGetParametersKey(),
+ (PCHAR)Name,
+ &Value);
+
+ if (!NT_SUCCESS(status))
+ continue;
+
+ Driver.FeatureOverride[Feature].Present = TRUE;
+ Driver.FeatureOverride[Feature].Value = Value;
+ }
+}
+
+__checkReturn
+_Success_(return)
+BOOLEAN
+DriverGetFeatureOverride(
+ IN XENVBD_FEATURE Feature,
+ OUT PULONG Value
+ )
+{
+ BOOLEAN Present = FALSE;
+
+ if (Feature < ARRAYSIZE(Driver.FeatureOverride)) {
+ Present = Driver.FeatureOverride[Feature].Present;
+ *Value = Driver.FeatureOverride[Feature].Value;
+ }
+
+ return Present;
+}
+
+__checkReturn
+const CHAR *
+DriverGetFeatureName(
+ IN XENVBD_FEATURE Feature
+ )
+{
+ return (Feature < ARRAYSIZE(Driver.FeatureOverride)) ?
+ Driver.FeatureOverride[Feature].Name :
+ NULL;
+}
+
+DRIVER_INITIALIZE DriverEntry;
NTSTATUS
DriverEntry(
__DriverParseOption("XENVBD:PVCDROM=",
&DriverParameters.PVCDRom);
+ __DriverInitializeOverrides();
+
RtlZeroMemory(&InitData, sizeof(InitData));
InitData.HwInitializationDataSize = sizeof(InitData);
static FORCEINLINE BOOLEAN
FrontendReadFeature(
- IN PXENVBD_FRONTEND Frontend,
- IN PCHAR Name,
- IN PBOOLEAN Value
+ IN PXENVBD_FRONTEND Frontend,
+ IN XENVBD_FEATURE Feature,
+ IN PBOOLEAN Value
+)
+{
+ NTSTATUS status;
+ PCHAR Buffer;
+ ULONG Override;
+ BOOLEAN Old = *Value;
+ const CHAR *Name;
+
+ Name = DriverGetFeatureName(Feature);
+ if (Name == NULL) {
+ Trace("Target[%d] : Could not find Feature %u.\n", Frontend->TargetId, Feature);
+ return FALSE;
+ }
+
+ if (DriverGetFeatureOverride(Feature, &Override)) {
+ *Value = !!Override;
+ } else {
+ status = XENBUS_STORE(Read,
+ Frontend->Store,
+ NULL,
+ Frontend->BackendPath,
+ (PCHAR)Name,
+ &Buffer);
+ if (!NT_SUCCESS(status))
+ return FALSE; // no value, unchanged
+
+ *Value = !!(strtoul(Buffer, NULL, 10));
+
+ XENBUS_STORE(Free,
+ Frontend->Store,
+ Buffer);
+ }
+
+ return Old != *Value;
+}
+
+static FORCEINLINE BOOLEAN
+FrontendReadDiskFeature(
+ IN PXENVBD_FRONTEND Frontend,
+ IN PCHAR Name,
+ IN PBOOLEAN Value
)
{
- NTSTATUS status;
- PCHAR Buffer;
- ULONG Override;
- BOOLEAN Old = *Value;
+ NTSTATUS status;
+ PCHAR Buffer;
+ BOOLEAN Old = *Value;
status = XENBUS_STORE(Read,
Frontend->Store,
return FALSE; // no value, unchanged
*Value = !!(strtoul(Buffer, NULL, 10));
+
XENBUS_STORE(Free,
Frontend->Store,
Buffer);
+ return Old != *Value;
+}
+
+static FORCEINLINE BOOLEAN
+FrontendReadValue32(
+ IN PXENVBD_FRONTEND Frontend,
+ IN XENVBD_FEATURE Feature,
+ IN BOOLEAN AllowOverride,
+ IN PULONG Value
+)
+{
+ NTSTATUS status;
+ PCHAR Buffer;
+ ULONG Override;
+ ULONG Old = *Value;
+ const CHAR *Name;
+
+ Name = DriverGetFeatureName(Feature);
+ if (Name == NULL) {
+ Trace("Target[%d] : Could not find Feature %u.\n", Frontend->TargetId, Feature);
+ return FALSE;
+ }
+
// check registry for disable-override
- status = RegistryQueryDwordValue(DriverGetParametersKey(),
- Name,
- &Override);
- if (NT_SUCCESS(status)) {
- if (Override == 0)
- *Value = FALSE;
+ if (AllowOverride && DriverGetFeatureOverride(Feature, &Override)) {
+ *Value = Override;
+ } else {
+ status = XENBUS_STORE(Read,
+ Frontend->Store,
+ NULL,
+ Frontend->BackendPath,
+ (PCHAR)Name,
+ &Buffer);
+ if (!NT_SUCCESS(status))
+ return FALSE; // no value, unchanged
+
+ *Value = strtoul(Buffer, NULL, 10);
+
+ XENBUS_STORE(Free,
+ Frontend->Store,
+ Buffer);
}
return Old != *Value;
}
static FORCEINLINE BOOLEAN
-FrontendReadValue32(
- IN PXENVBD_FRONTEND Frontend,
- IN PCHAR Name,
- IN BOOLEAN AllowOverride,
- IN PULONG Value
- )
+FrontendReadDiskValue32(
+ IN PXENVBD_FRONTEND Frontend,
+ IN PCHAR Name,
+ IN PULONG Value
+)
{
- NTSTATUS status;
- PCHAR Buffer;
- ULONG Override;
- ULONG Old = *Value;
+ NTSTATUS status;
+ PCHAR Buffer;
+ ULONG Old = *Value;
status = XENBUS_STORE(Read,
Frontend->Store,
Frontend->Store,
Buffer);
- // check registry for disable-override
- if (AllowOverride) {
- status = RegistryQueryDwordValue(DriverGetParametersKey(),
- Name,
- &Override);
- if (NT_SUCCESS(status)) {
- *Value = Override;
- }
- }
-
return Old != *Value;
}
static FORCEINLINE BOOLEAN
FrontendReadValue64(
- IN PXENVBD_FRONTEND Frontend,
- IN PCHAR Name,
- IN OUT PULONG64 Value
+ IN PXENVBD_FRONTEND Frontend,
+ IN PCHAR Name,
+ IN OUT PULONG64 Value
)
{
- NTSTATUS status;
- PCHAR Buffer;
- ULONG64 Old = *Value;
+ NTSTATUS status;
+ PCHAR Buffer;
+ ULONG64 Old = *Value;
status = XENBUS_STORE(Read,
Frontend->Store,
return FALSE; // no value, unchanged
*Value = _strtoui64(Buffer, NULL, 10);
+
XENBUS_STORE(Free,
Frontend->Store,
Buffer);
static FORCEINLINE ULONG
__Size(
- __in PXENVBD_DISKINFO Info
+ __in PXENVBD_DISKINFO Info
)
{
- ULONG64 MBytes = (Info->SectorSize * Info->SectorCount) >> 20; // / (1024 * 1024);
+ ULONG64 MBytes = (Info->SectorSize * Info->SectorCount) >> 20; // / (1024 * 1024);
+
if (MBytes < 10240)
return (ULONG)MBytes;
+
return (ULONG)(MBytes >> 10); // / 1024
}
static FORCEINLINE PCHAR
__Units(
- __in PXENVBD_DISKINFO Info
+ __in PXENVBD_DISKINFO Info
)
{
- ULONG64 MBytes = (Info->SectorSize * Info->SectorCount) >> 20; // / (1024 * 1024);
+ ULONG64 MBytes = (Info->SectorSize * Info->SectorCount) >> 20; // / (1024 * 1024);
+
if (MBytes < 10240)
return "MB";
+
return "GB";
}
__drv_requiresIRQL(DISPATCH_LEVEL)
static VOID
__ReadDiskInfo(
- __in PXENVBD_FRONTEND Frontend
+ __in PXENVBD_FRONTEND Frontend
)
{
- BOOLEAN Changed = FALSE;
-
- Changed |= FrontendReadValue32(Frontend,
- "info",
- FALSE,
- &Frontend->DiskInfo.DiskInfo);
- Changed |= FrontendReadValue32(Frontend,
- "sector-size",
- FALSE,
- &Frontend->DiskInfo.SectorSize);
- Changed |= FrontendReadValue32(Frontend,
- "physical-sector-size",
- FALSE,
- &Frontend->DiskInfo.PhysSectorSize);
+ BOOLEAN Changed;
+
+ Changed = FrontendReadDiskValue32(Frontend,
+ "info",
+ &Frontend->DiskInfo.DiskInfo);
+ Changed |= FrontendReadDiskValue32(Frontend,
+ "sector-size",
+ &Frontend->DiskInfo.SectorSize);
+ Changed |= FrontendReadDiskValue32(Frontend,
+ "physical-sector-size",
+ &Frontend->DiskInfo.PhysSectorSize);
Changed |= FrontendReadValue64(Frontend,
- "sectors",
- &Frontend->DiskInfo.SectorCount);
+ "sectors",
+ &Frontend->DiskInfo.SectorCount);
if (!Changed)
return;
// dump actual values
Verbose("Target[%d] : %lld sectors of %d bytes (%d)\n", Frontend->TargetId,
- Frontend->DiskInfo.SectorCount, Frontend->DiskInfo.SectorSize,
- Frontend->DiskInfo.PhysSectorSize);
+ Frontend->DiskInfo.SectorCount, Frontend->DiskInfo.SectorSize,
+ Frontend->DiskInfo.PhysSectorSize);
Verbose("Target[%d] : %d %s (%08x) %s\n", Frontend->TargetId,
- __Size(&Frontend->DiskInfo), __Units(&Frontend->DiskInfo),
- Frontend->DiskInfo.DiskInfo,
- Frontend->Caps.SurpriseRemovable ? "SURPRISE_REMOVABLE" : "");
+ __Size(&Frontend->DiskInfo), __Units(&Frontend->DiskInfo),
+ Frontend->DiskInfo.DiskInfo,
+ Frontend->Caps.SurpriseRemovable ? "SURPRISE_REMOVABLE" : "");
}
static FORCEINLINE VOID
FrontendReadFeatures(
- IN PXENVBD_FRONTEND Frontend
+ IN PXENVBD_FRONTEND Frontend
)
{
- BOOLEAN Changed = FALSE;
+ BOOLEAN Changed;
- Changed |= FrontendReadFeature(Frontend,
- "removable",
- &Frontend->Caps.Removable);
+ Changed = FrontendReadFeature(Frontend,
+ FeatureRemovable,
+ &Frontend->Caps.Removable);
Changed |= FrontendReadValue32(Frontend,
- "feature-max-indirect-segments",
+ FeatureMaxIndirectSegments,
TRUE,
&Frontend->Features.Indirect);
Changed |= FrontendReadFeature(Frontend,
- "feature-persistent",
+ FeaturePersistent,
&Frontend->Features.Persistent);
if (!Changed)
return;
Verbose("Target[%d] : Features: %s%s%s\n",
- Frontend->TargetId,
- Frontend->Features.Persistent ? "PERSISTENT " : "",
- Frontend->Features.Indirect ? "INDIRECT " : "",
- Frontend->Caps.Removable ? "REMOVABLE" : "");
+ Frontend->TargetId,
+ Frontend->Features.Persistent ? "PERSISTENT " : "",
+ Frontend->Features.Indirect ? "INDIRECT " : "",
+ Frontend->Caps.Removable ? "REMOVABLE" : "");
+
if (Frontend->Features.Indirect) {
Verbose("Target[%d] : INDIRECT %x\n",
Frontend->TargetId,
static FORCEINLINE VOID
FrontendReadDiskInfo(
- IN PXENVBD_FRONTEND Frontend
+ IN PXENVBD_FRONTEND Frontend
)
{
- BOOLEAN Changed = FALSE;
- BOOLEAN Discard;
- BOOLEAN DiscardFeature = FALSE;
- BOOLEAN DiscardEnable = TRUE;
-
+ BOOLEAN Changed;
+ BOOLEAN Discard;
+ BOOLEAN DiscardFeature = FALSE;
+ BOOLEAN DiscardEnable = TRUE;
+
+ Changed = FrontendReadFeature(Frontend,
+ FeatureBarrier,
+ &Frontend->DiskInfo.Barrier);
Changed |= FrontendReadFeature(Frontend,
- "feature-barrier",
- &Frontend->DiskInfo.Barrier);
- Changed |= FrontendReadFeature(Frontend,
- "feature-flush-cache",
+ FeatureFlushCache,
&Frontend->DiskInfo.FlushCache);
// discard related
FrontendReadFeature(Frontend,
- "feature-discard",
+ FeatureDiscard,
&DiscardFeature);
FrontendReadFeature(Frontend,
- "discard-enable",
+ FeatureDiscardEnable,
&DiscardEnable);
+
Discard = DiscardFeature && DiscardEnable;
+
Changed |= (Discard != Frontend->DiskInfo.Discard);
+
Frontend->DiskInfo.Discard = Discard;
+
Changed |= FrontendReadFeature(Frontend,
- "discard-secure",
+ FeatureDiscardSecure,
&Frontend->DiskInfo.DiscardSecure);
Changed |= FrontendReadValue32(Frontend,
- "discard-alignment",
+ FeatureDiscardAlignment,
TRUE,
&Frontend->DiskInfo.DiscardAlignment);
Changed |= FrontendReadValue32(Frontend,
- "discard-granularity",
+ FeatureDiscardGranularity,
TRUE,
&Frontend->DiskInfo.DiscardGranularity);
Frontend->DiskInfo.Barrier ? "BARRIER " : "",
Frontend->DiskInfo.FlushCache ? "FLUSH " : "",
Frontend->DiskInfo.Discard ? "DISCARD " : "");
+
if (Frontend->DiskInfo.Discard) {
Verbose("Target[%d] : DISCARD %s%x/%x\n",
Frontend->TargetId,
//=============================================================================
// Init/Term
+_IRQL_requires_(DISPATCH_LEVEL)
+_Requires_lock_held_(Frontend->StateLock)
static DECLSPEC_NOINLINE NTSTATUS
__FrontendSetState(
__in PXENVBD_FRONTEND Frontend,
PdoPreResume(Frontend->Pdo);
// dont acquire state lock - called at DISPATCH on 1 vCPU with interrupts enabled
+#pragma warning(suppress: 26110) // warning C26110: Caller failing to hold lock <lock> before calling function <func>.
Status = __FrontendSetState(Frontend, XENVBD_CLOSED);
if (!NT_SUCCESS(Status)) {
Error("Target[%d] : SetState CLOSED (%08x)\n", Frontend->TargetId, Status);
}
// dont acquire state lock - called at DISPATCH on 1 vCPU with interrupts enabled
+#pragma warning(suppress: 26110) // warning C26110: Caller failing to hold lock <lock> before calling function <func>.
Status = __FrontendSetState(Frontend, State);
if (!NT_SUCCESS(Status)) {
Error("Target[%d] : SetState %s (%08x)\n", Frontend->TargetId, __XenvbdStateName(State), Status);
RegistryPath.MaximumLength = RegistryPath.Length = 0;
}
+__drv_requiresIRQL(PASSIVE_LEVEL)
NTSTATUS
RegistryOpenKey(
IN HANDLE Parent,
return status;
}
+__drv_requiresIRQL(PASSIVE_LEVEL)
static NTSTATUS
RegistryOpenRoot(
IN PWCHAR Path,
return status;
}
+__drv_requiresIRQL(PASSIVE_LEVEL)
NTSTATUS
RegistryCreateKey(
IN HANDLE Root,
return status;
}
+__drv_requiresIRQL(PASSIVE_LEVEL)
NTSTATUS
RegistryOpenServiceKey(
IN ACCESS_MASK DesiredAccess,
return RegistryOpenKey(NULL, &RegistryPath, DesiredAccess, Key);
}
+__drv_requiresIRQL(PASSIVE_LEVEL)
NTSTATUS
RegistryCreateServiceKey(
OUT PHANDLE Key
return RegistryCreateKey(NULL, &RegistryPath, REG_OPTION_NON_VOLATILE, Key);
}
+__drv_requiresIRQL(PASSIVE_LEVEL)
NTSTATUS
RegistryOpenSoftwareKey(
IN PDEVICE_OBJECT DeviceObject,
return status;
}
+__drv_requiresIRQL(PASSIVE_LEVEL)
NTSTATUS
RegistryOpenHardwareKey(
IN PDEVICE_OBJECT DeviceObject,
return status;
}
+__drv_requiresIRQL(PASSIVE_LEVEL)
NTSTATUS
RegistryOpenSubKey(
IN PHANDLE Key,
return status;
}
+__drv_requiresIRQL(PASSIVE_LEVEL)
NTSTATUS
RegistryCreateSubKey(
IN PHANDLE Key,
return status;
}
+__drv_requiresIRQL(PASSIVE_LEVEL)
NTSTATUS
RegistryDeleteSubKey(
IN PHANDLE Key,
return status;
}
+__drv_requiresIRQL(PASSIVE_LEVEL)
NTSTATUS
RegistryEnumerateSubKeys(
IN HANDLE Key,
return status;
}
+__drv_requiresIRQL(PASSIVE_LEVEL)
NTSTATUS
RegistryEnumerateValues(
IN HANDLE Key,
return status;
}
+__drv_requiresIRQL(PASSIVE_LEVEL)
NTSTATUS
RegistryDeleteValue(
IN PHANDLE Key,
return status;
}
+__drv_requiresIRQL(PASSIVE_LEVEL)
NTSTATUS
RegistryQueryDwordValue(
IN HANDLE Key,
return status;
}
+__drv_requiresIRQL(PASSIVE_LEVEL)
NTSTATUS
RegistryUpdateDwordValue(
IN HANDLE Key,
return status;
}
+__drv_requiresIRQL(PASSIVE_LEVEL)
static PANSI_STRING
RegistrySzToAnsi(
IN PWCHAR Buffer
return NULL;
}
+__drv_requiresIRQL(PASSIVE_LEVEL)
static PANSI_STRING
RegistryMultiSzToAnsi(
IN PWCHAR Buffer
return NULL;
}
+__drv_requiresIRQL(PASSIVE_LEVEL)
NTSTATUS
RegistryQuerySzValue(
IN HANDLE Key,
return status;
}
+__drv_requiresIRQL(PASSIVE_LEVEL)
NTSTATUS
RegistryQueryBinaryValue(
IN HANDLE Key,
return status;
}
+__drv_requiresIRQL(PASSIVE_LEVEL)
NTSTATUS
RegistryUpdateBinaryValue(
IN HANDLE Key,
return status;
}
+__drv_requiresIRQL(PASSIVE_LEVEL)
NTSTATUS
RegistryQueryKeyName(
IN HANDLE Key,
return status;
}
+__drv_requiresIRQL(PASSIVE_LEVEL)
NTSTATUS
RegistryQuerySystemStartOption(
IN const CHAR *Prefix,
return status;
}
+__drv_requiresIRQL(PASSIVE_LEVEL)
static PKEY_VALUE_PARTIAL_INFORMATION
RegistryAnsiToSz(
PANSI_STRING Ansi
return NULL;
}
+__drv_requiresIRQL(PASSIVE_LEVEL)
static PKEY_VALUE_PARTIAL_INFORMATION
RegistryAnsiToMultiSz(
PANSI_STRING Ansi
return NULL;
}
+__drv_requiresIRQL(PASSIVE_LEVEL)
NTSTATUS
RegistryUpdateSzValue(
IN HANDLE Key,
__RegistryFree(Buffer);
}
+__drv_requiresIRQL(PASSIVE_LEVEL)
VOID
RegistryCloseKey(
IN HANDLE Key