--- /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 "base64.h"
+
+#include "util.h"
+#include "debug.h"
+#include "assert.h"
+
+#define BASE64_POOL_TAG '46BX'
+
+static FORCEINLINE PVOID
+Base64Allocate(
+ IN ULONG Size
+ )
+{
+ PVOID Buffer;
+
+ Buffer = ExAllocatePoolWithTag(NonPagedPool,
+ Size,
+ BASE64_POOL_TAG);
+ if (Buffer)
+ RtlZeroMemory(Buffer, Size);
+
+ return Buffer;
+}
+
+VOID
+Base64Free(
+ IN PVOID Buffer
+ )
+{
+ ExFreePoolWithTag(Buffer, BASE64_POOL_TAG);
+}
+
+static FORCEINLINE UCHAR
+__DecodeChar(
+ IN CHAR Char
+ )
+{
+ if (Char >= 'A' && Char <= 'Z') return Char - 'A';
+ if (Char >= 'a' && Char <= 'z') return Char - 'a' + 26;
+ if (Char >= '0' && Char <= '9') return Char - '0' + 52;
+ if (Char == '+') return 62;
+ if (Char == '/') return 63;
+ if (Char == '=') return 0;
+ return 0xFF;
+}
+
+static DECLSPEC_NOINLINE CHAR
+__Decode(
+ IN PUCHAR Dst,
+ IN PCHAR Src,
+ IN ULONG Left
+ )
+{
+ UCHAR Values[4];
+
+ if (Left < 4)
+ return -1;
+
+ // take 4 Src chars -> 1, 2, or 3 Dest bytes
+ Values[0] = __DecodeChar(Src[0]);
+ Values[1] = __DecodeChar(Src[1]);
+ Values[2] = __DecodeChar(Src[2]);
+ Values[3] = __DecodeChar(Src[3]);
+
+ // sanity checks
+ if ((Src[0] == '=' || Src[1] == '=') ||
+ (Src[2] == '=' && Src[3] != '='))
+ return -2;
+ if (Values[0] == 0xFF || Values[1] == 0xFF ||
+ Values[2] == 0xFF || Values[3] == 0xFF)
+ return -3;
+
+ // convert
+ Dst[0] = (Values[1] >> 4) | (Values[0] << 2);
+ if (Src[2] == '=')
+ return 2;
+
+ Dst[1] = (Values[2] >> 2) | (Values[1] << 4);
+ if (Src[3] == '=')
+ return 1;
+
+ Dst[2] = (Values[3] ) | (Values[2] << 6);
+ return 0;
+}
+
+NTSTATUS
+Base64Decode(
+ IN PCHAR String,
+ OUT PVOID *Binary,
+ OUT PULONG Length
+ )
+{
+ ULONG StringLength;
+ ULONG BlockCount;
+ ULONG Index;
+ PUCHAR Buffer;
+ CHAR Padding;
+ NTSTATUS status;
+
+ StringLength = (ULONG)strlen(String);
+
+ status = STATUS_INVALID_PARAMETER;
+ if (StringLength % 4 != 0)
+ goto fail1;
+
+ BlockCount = StringLength / 4;
+ Buffer = Base64Allocate(BlockCount * 3);
+
+ status = STATUS_NO_MEMORY;
+ if (Buffer == NULL)
+ goto fail2;
+
+ Padding = 0;
+ status = STATUS_INVALID_PARAMETER;
+ for (Index = 0; Index < BlockCount; ++Index) {
+ if (Padding != 0)
+ goto fail3;
+ Padding = __Decode(&Buffer[Index * 3],
+ &String[Index * 4],
+ StringLength - (Index * 4));
+ if (Padding < 0 || Padding > 2)
+ goto fail4;
+ }
+
+ *Length = (BlockCount * 3) - Padding;
+ *Binary = Buffer;
+ return STATUS_SUCCESS;
+
+fail4:
+ Error("fail4\n");
+fail3:
+ Error("fail3\n");
+fail2:
+ Error("fail2\n");
+ Base64Free(Buffer);
+fail1:
+ Error("fail1 %08x\n", status);
+ *Binary = NULL;
+ *Length = 0;
+ return status;
+}
--- /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 _XENVBD_BASE64_H
+#define _XENVBD_BASE64_H
+
+#include <ntddk.h>
+
+extern VOID
+Base64Free(
+ IN PVOID Buffer
+ );
+
+extern NTSTATUS
+Base64Decode(
+ IN PCHAR String,
+ OUT PVOID *Binary,
+ OUT PULONG Length
+ );
+
+#endif // _XENVBD_BASE64_H
#include "registry.h"
#include "driver.h"
#include "adapter.h"
-#include "pdoinquiry.h"
#include "srbext.h"
#include "names.h"
#include "ring.h"
#include "granter.h"
#include "thread.h"
+#include "base64.h"
#include "debug.h"
#include "assert.h"
#include "util.h"
+typedef struct _XENVBD_PAGE {
+ PVOID Data;
+ ULONG Size;
+} XENVBD_PAGE, *PXENVBD_PAGE;
+
struct _XENVBD_FRONTEND {
// Frontend
PXENVBD_TARGET Target;
XENVBD_CAPS Caps;
XENVBD_FEATURES Features;
XENVBD_DISKINFO DiskInfo;
- PVOID Inquiry;
+ XENVBD_PAGE Page80;
+ XENVBD_PAGE Page83;
// Interfaces to XenBus
XENBUS_STORE_INTERFACE StoreInterface;
}
PVOID
-FrontendGetInquiry(
- __in PXENVBD_FRONTEND Frontend
+FrontendGetInquiryOverride(
+ IN PXENVBD_FRONTEND Frontend,
+ IN UCHAR PageCode,
+ OUT PULONG Length
)
{
- return Frontend->Inquiry;
+ switch (PageCode) {
+ case 0x80:
+ *Length = Frontend->Page80.Size;
+ return Frontend->Page80.Data;
+ case 0x83:
+ *Length = Frontend->Page83.Size;
+ return Frontend->Page83.Data;
+ default:
+ *Length = 0;
+ return NULL;
+ }
}
NTSTATUS
}
}
+static FORCEINLINE VOID
+FrontendReadInquiryOverrides(
+ IN PXENVBD_FRONTEND Frontend
+ )
+{
+ PCHAR Buffer;
+ NTSTATUS status;
+
+ status = XENBUS_STORE(Read,
+ &Frontend->StoreInterface,
+ NULL,
+ Frontend->BackendPath,
+ "sm-data/scsi/0x12/0x80",
+ &Buffer);
+ if (NT_SUCCESS(status)) {
+ (VOID) Base64Decode(Buffer,
+ &Frontend->Page80.Data,
+ &Frontend->Page80.Size);
+
+ XENBUS_STORE(Free,
+ &Frontend->StoreInterface,
+ Buffer);
+ }
+
+ status = XENBUS_STORE(Read,
+ &Frontend->StoreInterface,
+ NULL,
+ Frontend->BackendPath,
+ "sm-data/scsi/0x12/0x83",
+ &Buffer);
+ if (NT_SUCCESS(status)) {
+ (VOID) Base64Decode(Buffer,
+ &Frontend->Page83.Data,
+ &Frontend->Page83.Size);
+
+ XENBUS_STORE(Free,
+ &Frontend->StoreInterface,
+ Buffer);
+ }
+}
+
//=============================================================================
__drv_requiresIRQL(DISPATCH_LEVEL)
static NTSTATUS
if (BackendState != XenbusStateInitWait)
goto fail8;
- // read inquiry data
- if (Frontend->Inquiry == NULL)
- PdoReadInquiryData(Frontend, &Frontend->Inquiry);
- PdoUpdateInquiryData(Frontend, Frontend->Inquiry);
-
// read features and caps (removable, ring-order, ...)
Verbose("Target[%d] : BackendId %d (%s)\n",
Frontend->TargetId,
__ReadDiskInfo(Frontend);
FrontendReadDiskInfo(Frontend);
+ // read inquiry data
+ FrontendReadInquiryOverrides(Frontend);
+
// blkback doesnt write features before InitWait, blkback writes features before Connected!
FrontendReadFeatures(Frontend);
{
RingDisconnect(Frontend->Ring);
GranterDisconnect(Frontend->Granter);
+
+ Base64Free(Frontend->Page80.Data);
+ Frontend->Page80.Data = NULL;
+ Frontend->Page80.Size = 0;
+
+ Base64Free(Frontend->Page83.Data);
+ Frontend->Page83.Data = NULL;
+ Frontend->Page83.Size = 0;
}
__drv_requiresIRQL(DISPATCH_LEVEL)
static FORCEINLINE VOID
Trace("Target[%d] @ (%d) =====>\n", TargetId, KeGetCurrentIrql());
- PdoFreeInquiryData(Frontend->Inquiry);
- Frontend->Inquiry = NULL;
+ Base64Free(Frontend->Page80.Data);
+ Frontend->Page80.Data = NULL;
+ Frontend->Page80.Size = 0;
+
+ Base64Free(Frontend->Page83.Data);
+ Frontend->Page83.Data = NULL;
+ Frontend->Page83.Size = 0;
ThreadAlert(Frontend->BackendThread);
ThreadJoin(Frontend->BackendThread);
Frontend->Ring = NULL;
ASSERT3P(Frontend->BackendPath, ==, NULL);
- ASSERT3P(Frontend->Inquiry, ==, NULL);
ASSERT3P(Frontend->BackendWatch, ==, NULL);
__FrontendFree(Frontend);
);
extern PVOID
-FrontendGetInquiry(
- __in PXENVBD_FRONTEND Frontend
+FrontendGetInquiryOverride(
+ IN PXENVBD_FRONTEND Frontend,
+ IN UCHAR PageCode,
+ OUT PULONG Length
);
extern NTSTATUS
+++ /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 "pdoinquiry.h"
-#include "driver.h"
-#include "debug.h"
-#include "assert.h"
-#include "util.h"
-#include <xencdb.h>
-#include <xenvbd-ntstrsafe.h>
-#include <stdlib.h>
-
-// "00000000-0000-0000-0000-000000000000"
-#define GUID_LENGTH 36
-
-// 00 00 00 00 00 00 00 00 "XENSRC 00000000"
-#define PAGE83_MIN_SIZE (4 + 4 + 16)
-
-// 00 00 00 00 + GUID_LENGTH
-#define VDI_ID_LENGTH (4 + GUID_LENGTH)
-
-#define INQUIRY_POOL_TAG 'qnIX'
-
-typedef struct _XENVBD_PAGE {
- PCHAR Data;
- ULONG Length;
-} XENVBD_PAGE, *PXENVBD_PAGE;
-
-typedef struct _XENVBD_INQUIRY {
- XENVBD_PAGE Page80;
- XENVBD_PAGE Page83;
- CHAR VdiUuid[GUID_LENGTH + 1];
-} XENVBD_INQUIRY, *PXENVBD_INQUIRY;
-
-static FORCEINLINE ULONG
-__Min3(
- __in ULONG A,
- __in ULONG B,
- __in ULONG C
- )
-{
- return A < B ? __min(A, C) : __min(B, C);
-}
-
-__checkReturn
-__drv_allocatesMem(mem)
-__bcount(Size)
-static FORCEINLINE PVOID
-#pragma warning(suppress: 28195)
-__InquiryAlloc(
- __in SIZE_T Size
- )
-{
- return __AllocatePoolWithTag(NonPagedPool, Size, INQUIRY_POOL_TAG);
-}
-
-static FORCEINLINE VOID
-#pragma warning(suppress: 28197)
-__InquiryFree(
- __in __drv_freesMem(mem) PVOID Buffer
- )
-{
- if (Buffer != NULL)
- __FreePoolWithTag(Buffer, INQUIRY_POOL_TAG);
-}
-
-static FORCEINLINE UCHAR
-__DecodeChar(
- __in CHAR Char
- )
-{
- if (Char >= 'A' && Char <= 'Z') return Char - 'A';
- if (Char >= 'a' && Char <= 'z') return Char - 'a' + 26;
- if (Char >= '0' && Char <= '9') return Char - '0' + 52;
- if (Char == '+') return 62;
- if (Char == '/') return 63;
- if (Char == '=') return 0;
- return 0xFF;
-}
-static DECLSPEC_NOINLINE UCHAR
-__Decode(
- __in PUCHAR Dest,
- __in PCHAR Src,
- __in ULONG RemainingChars
- )
-{
- UCHAR Values[4];
-
- if (RemainingChars < 4)
- return 0xFF;
-
- // take 4 Src chars -> 1, 2, or 3 Dest bytes
- Values[0] = __DecodeChar(Src[0]);
- Values[1] = __DecodeChar(Src[1]);
- Values[2] = __DecodeChar(Src[2]);
- Values[3] = __DecodeChar(Src[3]);
-
- // sanity checks
- if ((Src[0] == '=' || Src[1] == '=') ||
- (Src[2] == '=' && Src[3] != '='))
- return 0xFF;
- if (Values[0] == 0xFF || Values[1] == 0xFF ||
- Values[2] == 0xFF || Values[3] == 0xFF)
- return 0xFF;
-
- // convert
- Dest[0] = (Values[1] >> 4) | (Values[0] << 2);
- if (Src[2] == '=') return 2;
- Dest[1] = (Values[2] >> 2) | (Values[1] << 4);
- if (Src[3] == '=') return 1;
- Dest[2] = (Values[3] ) | (Values[2] << 6);
- return 0;
-}
-__checkReturn
-static NTSTATUS
-__DecodeBase64(
- __in PCHAR Base64,
- __in ULONG Base64Length,
- __out PVOID *_Buffer,
- __out PULONG BufferLength
- )
-{
- // convert Base64(4chars) into Buffer(3bytes)
- PUCHAR Buffer;
- ULONG NumBlocks;
- ULONG i;
- UCHAR Pad = 0;
-
- NumBlocks = Base64Length / 4;
-
- Buffer = (PUCHAR)__InquiryAlloc(NumBlocks * 3);
- if (Buffer == NULL) {
- Error("__InquiryAlloc (STATUS_INSUFFICIENT_RESOURCES)\n");
- goto fail1;
- }
-
- for (i = 0; i < NumBlocks; ++i) {
- if (Pad) goto invalid_base64;
- Pad = __Decode(Buffer + (i * 3), Base64 + (i * 4), Base64Length - (i * 4));
- if (Pad > 2) goto invalid_base64;
- }
-
- *BufferLength = (NumBlocks * 3) - Pad;
- *_Buffer = Buffer;
- return STATUS_SUCCESS;
-
-invalid_base64:
- Error("Invalid BASE64 encoding\n");
- __InquiryFree((PVOID)Buffer);
- return STATUS_UNSUCCESSFUL;
-
-fail1:
- return STATUS_INSUFFICIENT_RESOURCES;
-}
-static DECLSPEC_NOINLINE BOOLEAN
-__ReadPage(
- __in PXENVBD_FRONTEND Frontend,
- __in PXENVBD_PAGE Page,
- __in PCHAR Path
- )
-{
- NTSTATUS Status;
- PCHAR Value;
-
- Status = FrontendStoreReadBackend(Frontend, Path, &Value);
- if (!NT_SUCCESS(Status))
- goto fail1;
-
- Status = __DecodeBase64(Value, (ULONG)strlen(Value), (PVOID*)&Page->Data, &Page->Length);
- if (!NT_SUCCESS(Status))
- goto fail2;
-
- FrontendStoreFree(Frontend, Value);
- return TRUE;
-
-fail2:
- FrontendStoreFree(Frontend, Value);
-fail1:
- Page->Data = NULL;
- Page->Length = 0;
- return FALSE;
-}
-
-static FORCEINLINE BOOLEAN
-__HandlePageStd(
- __in PSCSI_REQUEST_BLOCK Srb
- )
-{
- PINQUIRYDATA Data = (PINQUIRYDATA)Srb->DataBuffer;
- ULONG Length = Srb->DataTransferLength;
-
- if (Length < INQUIRYDATABUFFERSIZE)
- return FALSE;
-
- Data->DeviceType = DIRECT_ACCESS_DEVICE;
- Data->DeviceTypeQualifier = DEVICE_CONNECTED;
- Data->Versions = 4;
- Data->ResponseDataFormat = 2;
- Data->AdditionalLength = INQUIRYDATABUFFERSIZE - 4;
- Data->CommandQueue = 1;
- RtlCopyMemory(Data->VendorId, "XENSRC ", 8);
- RtlCopyMemory(Data->ProductId, "PVDISK ", 16);
- RtlCopyMemory(Data->ProductRevisionLevel, "2.0 ", 4);
-
- Srb->DataTransferLength = INQUIRYDATABUFFERSIZE;
- return TRUE;
-}
-static FORCEINLINE BOOLEAN
-__HandlePage00(
- __in PSCSI_REQUEST_BLOCK Srb
- )
-{
- PCHAR Data = (PCHAR)Srb->DataBuffer;
- ULONG Length = Srb->DataTransferLength;
-
- if (Length < 7)
- return FALSE;
- RtlZeroMemory(Data, Length);
-
- // 00 00 00 NumPages+1 00 [Page [...]]
- Data[3] = 3;
- Data[4] = 0x00;
- Data[5] = 0x80;
- Data[6] = 0x83;
- Srb->DataTransferLength = 7;
-
- return TRUE;
-}
-static FORCEINLINE BOOLEAN
-__HandlePage80(
- __in ULONG TargetId,
- __in PXENVBD_INQUIRY Inquiry,
- __in PSCSI_REQUEST_BLOCK Srb
- )
-{
- PCHAR Data = (PCHAR)Srb->DataBuffer;
- ULONG Length = Srb->DataTransferLength;
-
- RtlZeroMemory(Data, Length);
- if (Inquiry == NULL ||
- Inquiry->Page80.Data == NULL ||
- Inquiry->Page80.Length == 0) {
- // generate the serial number page
- PVPD_SERIAL_NUMBER_PAGE Serial;
- if (Length < sizeof(VPD_SERIAL_NUMBER_PAGE) + 4)
- return FALSE;
-
- Serial = (PVPD_SERIAL_NUMBER_PAGE)Data;
- Serial->PageCode = 0x80;
- Serial->PageLength = 4;
- (VOID) RtlStringCchPrintfA((PCHAR)Serial->SerialNumber, 5, "%04u", TargetId);
-
- Verbose("Target[%u] : INQUIRY Using Fake Page80 Data\n", TargetId);
-
- Srb->DataTransferLength = sizeof(VPD_SERIAL_NUMBER_PAGE) + 4;
- // VPD_SERIAL_NUMBER_PAGE includes 1 char already
- } else {
- if (Length < Inquiry->Page80.Length)
- return FALSE;
-
- RtlCopyMemory(Data, Inquiry->Page80.Data, Inquiry->Page80.Length);
- Srb->DataTransferLength = Inquiry->Page80.Length;
- }
-
- // if possible, append additional data
- //if (Inquiry && Length >= Srb->DataTransferLength + ADDITIONAL_LENGTH) {
- // Srb->DataTransferLength += ADDITIONAL_LENGTH;
- //}
- return TRUE;
-}
-static FORCEINLINE BOOLEAN
-__HandlePage83(
- __in ULONG TargetId,
- __in PXENVBD_INQUIRY Inquiry,
- __in PSCSI_REQUEST_BLOCK Srb
- )
-{
- PCHAR Data = (PCHAR)Srb->DataBuffer;
- ULONG Length = Srb->DataTransferLength;
-
- RtlZeroMemory(Data, Length);
- if (Inquiry == NULL ||
- Inquiry->Page83.Data == NULL ||
- Inquiry->Page83.Length == 0) {
- // generate the id page data
- PVPD_IDENTIFICATION_DESCRIPTOR Id;
- CHAR Buffer[17];
-
- if (Length < PAGE83_MIN_SIZE)
- return FALSE;
-
- Data[1] = 0x83;
- Data[3] = 16;
-
- Id = (PVPD_IDENTIFICATION_DESCRIPTOR)(Data + 4);
- Id->CodeSet = VpdCodeSetAscii;
- Id->IdentifierType = VpdIdentifierTypeVendorId;
- Id->IdentifierLength = 16;
- (VOID)RtlStringCchPrintfA(Buffer, 17, "XENSRC %08u", TargetId);
- RtlCopyMemory((PCHAR)Id->Identifier, Buffer, 16);
-
- Verbose("Target[%u] : INQUIRY Using Fake Page83 Data\n", TargetId);
-
- Srb->DataTransferLength = PAGE83_MIN_SIZE;
- } else {
- if (Length < Inquiry->Page83.Length)
- return FALSE;
-
- RtlCopyMemory(Data, Inquiry->Page83.Data, Inquiry->Page83.Length);
- Srb->DataTransferLength = Inquiry->Page83.Length;
- }
-
- // if possible, append vdi-uuid as VendorSpecific
- if (Inquiry && Length >= Srb->DataTransferLength + VDI_ID_LENGTH) {
- PVPD_IDENTIFICATION_DESCRIPTOR Id;
-
- // update internal size
- *(Data + 3) += VDI_ID_LENGTH;
-
- // copy new data
- Id = (PVPD_IDENTIFICATION_DESCRIPTOR)(Data + Srb->DataTransferLength);
- Id->CodeSet = VpdCodeSetAscii;
- Id->IdentifierType = VpdIdentifierTypeVendorSpecific;
- Id->IdentifierLength = GUID_LENGTH;
- RtlCopyMemory(Id->Identifier, Inquiry->VdiUuid, GUID_LENGTH);
-
- Srb->DataTransferLength += VDI_ID_LENGTH;
- }
- return TRUE;
-}
-
-#define MAX_BUFFER 64
-
-static FORCEINLINE VOID
-__TracePage80(
- __in ULONG TargetId,
- __in PXENVBD_INQUIRY Inquiry
- )
-{
- ULONG Length;
- CHAR Buffer[MAX_BUFFER+1];
-
- Length = __Min3(Inquiry->Page80.Data[3], MAX_BUFFER, Inquiry->Page80.Length - 4);
- RtlCopyMemory(Buffer, Inquiry->Page80.Data + 4, Length);
- Buffer[Length] = 0;
- Verbose("Target[%u] : SerialNumber = \"%s\"\n", TargetId, Buffer);
-}
-static FORCEINLINE VOID
-__TracePage83(
- __in ULONG TargetId,
- __in PXENVBD_INQUIRY Inquiry
- )
-{
- ULONG Length;
- ULONG Index;
- CHAR Buffer[MAX_BUFFER+1];
-
- for (Index = 4; Index < Inquiry->Page83.Length; ) {
- PVPD_IDENTIFICATION_DESCRIPTOR Identifier = (PVPD_IDENTIFICATION_DESCRIPTOR)&Inquiry->Page83.Data[Index];
-
- switch (Identifier->CodeSet) {
- case VpdCodeSetAscii:
- Length = __Min3(Identifier->IdentifierLength, MAX_BUFFER, Inquiry->Page83.Length - Index - 4);
- RtlCopyMemory(Buffer, Identifier->Identifier, Length);
- Buffer[Length] = 0;
- Verbose("Target[%u] : Identifier (ASCII, Type %02x, \"%s\")\n",
- TargetId, Identifier->IdentifierType, Buffer);
- break;
-
- default:
- Verbose("Target[%u] : Identifier (CodeSet %02x, Type %02x, Length %02x)\n",
- TargetId, Identifier->CodeSet, Identifier->IdentifierType, Identifier->IdentifierLength);
- break;
- }
-
- Index += (4 + Identifier->IdentifierLength);
- }
-}
-
-VOID
-#pragma warning(suppress: 28195)
-PdoReadInquiryData(
- __in PXENVBD_FRONTEND Frontend,
- __out __drv_allocatesMem(mem) PVOID* _Inquiry
- )
-{
- PXENVBD_INQUIRY Inquiry;
- const CHAR GuidNull[] = "00000000-0000-0000-0000-000000000000";
- const ULONG TargetId = FrontendGetTargetId(Frontend);
-
- *_Inquiry = NULL;
- Inquiry = (PXENVBD_INQUIRY)__InquiryAlloc(sizeof(XENVBD_INQUIRY));
- if (Inquiry == NULL) {
- Error("Target[%d] : Memory allocation getting INQUIRY data (%d bytes failed)\n",
- TargetId, sizeof(XENVBD_INQUIRY));
- return;
- }
-
- // initialize VDI-UUID
- RtlCopyMemory(Inquiry->VdiUuid, GuidNull, GUID_LENGTH);
- Inquiry->VdiUuid[GUID_LENGTH] = 0;
-
- // read page80
- if (!__ReadPage(Frontend, &Inquiry->Page80, "sm-data/scsi/0x12/0x80")) {
- Warning("Target[%d] : Failed to get Page80 data\n", TargetId);
- } else {
- __TracePage80(TargetId, Inquiry);
- }
-
- // read page83
- if (!__ReadPage(Frontend, &Inquiry->Page83, "sm-data/scsi/0x12/0x83")) {
- Warning("Target[%d] : Failed to get Page83 data\n", TargetId);
- } else {
- __TracePage83(TargetId, Inquiry);
- }
-
- *_Inquiry = Inquiry;
-}
-
-VOID
-PdoFreeInquiryData(
- __in __drv_freesMem(mem) PVOID _Inquiry
- )
-{
- PXENVBD_INQUIRY Inquiry = (PXENVBD_INQUIRY)_Inquiry;
-
- if (_Inquiry == NULL)
- return;
-
- __InquiryFree((PVOID)Inquiry->Page80.Data);
- __InquiryFree((PVOID)Inquiry->Page83.Data);
- __InquiryFree((PVOID)Inquiry);
-}
-
-VOID
-PdoUpdateInquiryData(
- __in PXENVBD_FRONTEND Frontend,
- __in PVOID _Inquiry
- )
-{
- PXENVBD_INQUIRY Inquiry = (PXENVBD_INQUIRY)_Inquiry;
- NTSTATUS Status;
- PCHAR Value;
- ULONG Length;
- const CHAR GuidNull[] = "00000000-0000-0000-0000-000000000000";
-
- if (_Inquiry == NULL)
- return;
-
- RtlCopyMemory(Inquiry->VdiUuid, GuidNull, GUID_LENGTH);
- Inquiry->VdiUuid[GUID_LENGTH] = 0;
-
- Status = FrontendStoreReadBackend(Frontend, "sm-data/vdi-uuid", &Value);
- if (NT_SUCCESS(Status)) {
- Length = (ULONG)strlen(Value);
-
- if (Length == GUID_LENGTH) {
- RtlCopyMemory(Inquiry->VdiUuid, Value, Length);
- Inquiry->VdiUuid[GUID_LENGTH] = 0;
- }
-
- FrontendStoreFree(Frontend, Value);
- }
-
- Verbose("Target[%u] : VDI-UUID = {%s}\n", FrontendGetTargetId(Frontend), Inquiry->VdiUuid);
-}
-
-VOID
-PdoInquiry(
- __in ULONG TargetId,
- __in PVOID Inquiry,
- __in PSCSI_REQUEST_BLOCK Srb
- )
-{
- BOOLEAN Success;
- const UCHAR Evpd = Cdb_EVPD(Srb);
- const UCHAR PageCode = Cdb_PageCode(Srb);
-
- Trace("Target[%d] : INQUIRY %02x%s\n", TargetId, PageCode, Evpd ? " EVPD" : "");
- if (Evpd) {
- switch (PageCode) {
- case 0x00: Success = __HandlePage00(Srb); break;
- case 0x80: Success = __HandlePage80(TargetId, (PXENVBD_INQUIRY)Inquiry, Srb); break;
- case 0x83: Success = __HandlePage83(TargetId, (PXENVBD_INQUIRY)Inquiry, Srb); break;
- default: Success = FALSE; break;
- }
- } else {
- switch (PageCode) {
- case 0x00: Success = __HandlePageStd(Srb); break;
- default: Success = FALSE; break;
- }
- }
-
- if (Success) {
- Srb->ScsiStatus = 0; /* SUCCESS */
- Srb->SrbStatus = SRB_STATUS_SUCCESS;
- } else {
- Error("Target[%d] : INQUIRY failed %02x%s\n", TargetId, PageCode, Evpd ? " EVPD" : "");
- Srb->ScsiStatus = 0x02; /* CHECK_CONDITION */
- Srb->SrbStatus = SRB_STATUS_ERROR;
- }
-}
+++ /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 _XENVBD_PDO_INQUIRY_H
-#define _XENVBD_PDO_INQUIRY_H
-
-#include <ntddk.h>
-#include <xenvbd-storport.h>
-#include "frontend.h"
-
-extern VOID
-PdoReadInquiryData(
- __in PXENVBD_FRONTEND Frontend,
- __out __drv_allocatesMem(mem) PVOID* _Inquiry
- );
-
-extern VOID
-PdoFreeInquiryData(
- __in __drv_freesMem(mem) PVOID Inquiry
- );
-
-extern VOID
-PdoUpdateInquiryData(
- __in PXENVBD_FRONTEND Frontend,
- __in PVOID _Inquiry
- );
-
-extern VOID
-PdoInquiry(
- __in ULONG TargetId,
- __in PVOID Inquiry,
- __in PSCSI_REQUEST_BLOCK Srb
- );
-
-#endif // _XENVBD_PDO_INQUIRY_H
-
* SUCH DAMAGE.
*/
+#include <ntddk.h>
+#include <ntstrsafe.h>
+#include <storport.h>
+#include <stdlib.h>
+
+#include <xencdb.h>
+#include <names.h>
+#include <store_interface.h>
+#include <evtchn_interface.h>
+#include <gnttab_interface.h>
+#include <debug_interface.h>
+#include <suspend_interface.h>
+
#include "target.h"
#include "driver.h"
#include "adapter.h"
#include "queue.h"
#include "srbext.h"
#include "buffer.h"
-#include "pdoinquiry.h"
+
#include "debug.h"
#include "assert.h"
#include "util.h"
-#include <xencdb.h>
-#include <names.h>
-#include <store_interface.h>
-#include <evtchn_interface.h>
-#include <gnttab_interface.h>
-#include <debug_interface.h>
-#include <suspend_interface.h>
-#include <stdlib.h>
#define TARGET_SIGNATURE 'odpX'
Srb->SrbStatus = SRB_STATUS_SUCCESS;
}
+static FORCEINLINE VOID
+TargetInquiryStd(
+ IN PXENVBD_TARGET Target,
+ IN PSCSI_REQUEST_BLOCK Srb
+ )
+{
+ PINQUIRYDATA Data = Srb->DataBuffer;
+ ULONG Length = Srb->DataTransferLength;
+
+ UNREFERENCED_PARAMETER(Target);
+
+ Srb->SrbStatus = SRB_STATUS_ERROR;
+ if (Length < INQUIRYDATABUFFERSIZE)
+ return;
+
+ RtlZeroMemory(Data, Length);
+ Data->DeviceType = DIRECT_ACCESS_DEVICE;
+ Data->DeviceTypeQualifier = DEVICE_CONNECTED;
+ Data->Versions = 4;
+ Data->ResponseDataFormat = 2;
+ Data->AdditionalLength = INQUIRYDATABUFFERSIZE - 4;
+ Data->CommandQueue = 1;
+ RtlCopyMemory(Data->VendorId, "XENSRC ", 8);
+ RtlCopyMemory(Data->ProductId, "PVDISK ", 16);
+ RtlCopyMemory(Data->ProductRevisionLevel, "2.0 ", 4);
+
+ Srb->DataTransferLength = INQUIRYDATABUFFERSIZE;
+ Srb->SrbStatus = SRB_STATUS_SUCCESS;
+}
+
+static FORCEINLINE VOID
+TargetInquiry00(
+ IN PXENVBD_TARGET Target,
+ IN PSCSI_REQUEST_BLOCK Srb
+ )
+{
+ PVPD_SUPPORTED_PAGES_PAGE Data = Srb->DataBuffer;
+ ULONG Length = Srb->DataTransferLength;
+
+ UNREFERENCED_PARAMETER(Target);
+
+ RtlZeroMemory(Data, Length);
+
+ Srb->SrbStatus = SRB_STATUS_ERROR;
+ if (Length < 7)
+ return;
+
+ Data->PageLength = 3;
+ Data->SupportedPageList[0] = 0x00;
+ Data->SupportedPageList[1] = 0x80;
+ Data->SupportedPageList[2] = 0x83;
+
+ Srb->DataTransferLength = 7;
+ Srb->SrbStatus = SRB_STATUS_SUCCESS;
+}
+
+static FORCEINLINE VOID
+TargetInquiry80(
+ IN PXENVBD_TARGET Target,
+ IN PSCSI_REQUEST_BLOCK Srb
+ )
+{
+ PVPD_SERIAL_NUMBER_PAGE Data = Srb->DataBuffer;
+ ULONG Length = Srb->DataTransferLength;
+ PVOID Page;
+ ULONG Size;
+
+ Page = FrontendGetInquiryOverride(Target->Frontend, 0x80, &Size);
+
+ RtlZeroMemory(Data, Length);
+
+ Srb->SrbStatus = SRB_STATUS_ERROR;
+ if (Page && Size) {
+ if (Length < Size)
+ return;
+
+ RtlCopyMemory(Data, Page, Size);
+
+ Srb->DataTransferLength = Size;
+ } else {
+ CHAR Serial[5];
+
+ if (Length < sizeof(VPD_SERIAL_NUMBER_PAGE) + 4)
+ return;
+
+ Data->PageCode = 0x80;
+ Data->PageLength = 4;
+ (VOID) RtlStringCbPrintfA(Serial,
+ sizeof(Serial),
+ "%04u",
+ TargetGetTargetId(Target));
+ RtlCopyMemory(Data->SerialNumber, Serial, 4);
+
+ Srb->DataTransferLength = sizeof(VPD_SERIAL_NUMBER_PAGE) + 4;
+ }
+
+ Srb->SrbStatus = SRB_STATUS_SUCCESS;
+}
+
+static FORCEINLINE VOID
+TargetInquiry83(
+ IN PXENVBD_TARGET Target,
+ IN PSCSI_REQUEST_BLOCK Srb
+ )
+{
+ PVPD_IDENTIFICATION_PAGE Data = Srb->DataBuffer;
+ ULONG Length = Srb->DataTransferLength;
+ PVOID Page;
+ ULONG Size;
+
+ Page = FrontendGetInquiryOverride(Target->Frontend, 0x83, &Size);
+
+ RtlZeroMemory(Data, Length);
+
+ Srb->SrbStatus = SRB_STATUS_ERROR;
+ if (Page && Size) {
+ if (Length < Size)
+ return;
+
+ RtlCopyMemory(Data, Page, Size);
+
+ Srb->DataTransferLength = Size;
+ } else {
+ PVPD_IDENTIFICATION_DESCRIPTOR Id = (PVPD_IDENTIFICATION_DESCRIPTOR)&Data->Descriptors[0];
+ CHAR Identifier[17];
+
+ if (Length < sizeof(VPD_IDENTIFICATION_PAGE) +
+ sizeof(VPD_IDENTIFICATION_DESCRIPTOR) + 16)
+ return;
+
+ Data->PageCode = 0x83;
+ Data->PageLength = sizeof(VPD_IDENTIFICATION_DESCRIPTOR) + 16;
+
+ Id->CodeSet = VpdCodeSetAscii;
+ Id->IdentifierType = VpdIdentifierTypeVendorId;
+ Id->IdentifierLength = 16;
+ (VOID) RtlStringCbPrintfA(Identifier,
+ sizeof(Identifier),
+ "XENSRC %08u",
+ TargetGetTargetId(Target));
+ RtlCopyMemory(Id->Identifier, Identifier, 16);
+
+ Srb->DataTransferLength = sizeof(VPD_IDENTIFICATION_PAGE) +
+ sizeof(VPD_IDENTIFICATION_DESCRIPTOR) + 16;
+ }
+
+ Srb->SrbStatus = SRB_STATUS_SUCCESS;
+}
+
+static DECLSPEC_NOINLINE VOID
+TargetInquiry(
+ IN PXENVBD_TARGET Target,
+ IN PSCSI_REQUEST_BLOCK Srb
+ )
+{
+ if (Cdb_EVPD(Srb)) {
+ switch (Cdb_PageCode(Srb)) {
+ case 0x00: TargetInquiry00(Target, Srb); break;
+ case 0x80: TargetInquiry80(Target, Srb); break;
+ case 0x83: TargetInquiry83(Target, Srb); break;
+ default: Srb->SrbStatus = SRB_STATUS_ERROR; break;
+ }
+ } else {
+ switch (Cdb_PageCode(Srb)) {
+ case 0x00: TargetInquiryStd(Target, Srb); break;
+ default: Srb->SrbStatus = SRB_STATUS_ERROR; break;
+ }
+ }
+}
+
static FORCEINLINE BOOLEAN
__ValidateSrbForTarget(
IN PXENVBD_TARGET Target,
case SCSIOP_INQUIRY:
AdapterSetDeviceQueueDepth(TargetGetAdapter(Target),
TargetGetTargetId(Target));
- PdoInquiry(TargetGetTargetId(Target),
- FrontendGetInquiry(Target->Frontend),
- Srb);
+ TargetInquiry(Target, Srb);
break;
case SCSIOP_MODE_SENSE:
<ClCompile Include="../../src/xenvbd/adapter.c" />
<ClCompile Include="../../src/xenvbd/frontend.c" />
<ClCompile Include="../../src/xenvbd/target.c" />
- <ClCompile Include="../../src/xenvbd/pdoinquiry.c" />
+ <ClCompile Include="../../src/xenvbd/base64.c" />
<ClCompile Include="../../src/xenvbd/queue.c" />
<ClCompile Include="../../src/xenvbd/thread.c" />
<ClCompile Include="../../src/xenvbd/ring.c" />