]> xenbits.xensource.com Git - pvdrivers/win/xenvbd.git/commitdiff
Fix SDV on xencrsh
authorOwen Smith <owen.smith@citrix.com>
Mon, 19 May 2014 12:51:10 +0000 (13:51 +0100)
committerOwen Smith <owen.smith@citrix.com>
Mon, 19 May 2014 12:51:10 +0000 (13:51 +0100)
Signed-off-by: Owen Smith <owen.smith@citrix.com>
build.py
proj/xencrsh/xencrsh.vcxproj
src/xencrsh/driver.c
src/xencrsh/frontend.c
src/xencrsh/pdo-inquiry.c [deleted file]
src/xencrsh/pdo-inquiry.h [deleted file]
src/xencrsh/pdo.c
src/xencrsh/pdoinquiry.c [new file with mode: 0644]
src/xencrsh/pdoinquiry.h [new file with mode: 0644]

index ec6222e82505f8d624b1af2e3dba1da9fe8f8c48..fcaacc09c8e76927347794770e4e2b1e6c7b0c7b 100644 (file)
--- a/build.py
+++ b/build.py
@@ -390,6 +390,7 @@ if __name__ == '__main__':
     symstore_add(driver, release, 'x64', debug[sys.argv[1]])
 
     if len(sys.argv) <= 2 or sdv[sys.argv[2]]:
+        run_sdv('xencrsh', driver)
         run_sdv('xenvbd', driver)
 
     archive(driver + '\\source.tgz', manifest().splitlines(), tgz=True)
index 4d7a1f77276ebf665e3cd675232f064edd5dfd0e..5ed744387561f13782f31375a1735646cd82032d 100644 (file)
@@ -72,7 +72,7 @@
                <ClCompile Include="..\..\src\xencrsh\hypercall_stub.c" />
                <ClCompile Include="..\..\src\xencrsh\log.c" />
                <ClCompile Include="..\..\src\xencrsh\pdo.c" />
-               <ClCompile Include="..\..\src\xencrsh\pdo-inquiry.c" />
+               <ClCompile Include="..\..\src\xencrsh\pdoinquiry.c" />
                <ClCompile Include="..\..\src\xencrsh\queue.c" />
                <ClCompile Include="..\..\src\xencrsh\store.c" />
        </ItemGroup>
index 6411ba3c71bd8e46ddf1186e6a140ca397368071..8b15f27ed354639478aa2a52f2d828a33a173a65 100644 (file)
@@ -138,6 +138,8 @@ DriverFormat(
 
 //=============================================================================
 // StorPort redirections
+HW_INITIALIZE       HwInitialize;
+
 BOOLEAN 
 HwInitialize(
     IN  PVOID   HwDeviceExtension
@@ -147,6 +149,8 @@ HwInitialize(
     return TRUE;
 }
 
+HW_INTERRUPT        HwInterrupt;
+
 BOOLEAN 
 HwInterrupt(
     IN  PVOID   HwDeviceExtension
@@ -160,6 +164,8 @@ HwInterrupt(
     return TRUE;
 }
 
+HW_RESET_BUS        HwResetBus;
+
 BOOLEAN 
 HwResetBus(
     IN  PVOID   HwDeviceExtension,
@@ -170,6 +176,8 @@ HwResetBus(
     return FdoResetBus((PXENVBD_FDO)HwDeviceExtension);
 }
 
+HW_ADAPTER_CONTROL  HwAdapterControl;
+
 SCSI_ADAPTER_CONTROL_STATUS
 HwAdapterControl(
     IN  PVOID                       HwDeviceExtension,
@@ -180,6 +188,8 @@ HwAdapterControl(
     return FdoAdapterControl((PXENVBD_FDO)HwDeviceExtension, ControlType, Parameters);
 }
 
+HW_FIND_ADAPTER     HwFindAdapter;
+
 ULONG
 HwFindAdapter(
     IN  PVOID                               HwDeviceExtension,
@@ -198,6 +208,8 @@ HwFindAdapter(
     return FdoFindAdapter((PXENVBD_FDO)HwDeviceExtension, ConfigInfo);
 }
 
+HW_BUILDIO          HwBuildIo;
+
 BOOLEAN 
 HwBuildIo(
     IN  PVOID               HwDeviceExtension,
@@ -207,6 +219,8 @@ HwBuildIo(
     return FdoBuildIo((PXENVBD_FDO)HwDeviceExtension, Srb);
 }
 
+HW_STARTIO          HwStartIo;
+
 BOOLEAN 
 HwStartIo(
     IN  PVOID               HwDeviceExtension,
@@ -284,6 +298,7 @@ __ToUpper(
         return Ch - L'a' + L'A';
     return Ch;
 }
+
 static FORCEINLINE BOOLEAN
 __StrStarts(
     IN  PWCHAR  Str,
@@ -298,6 +313,7 @@ __StrStarts(
     }
     return TRUE;
 }
+
 NTSTATUS
 DllInitialize(
     IN  PUNICODE_STRING RegistryPath
@@ -323,6 +339,7 @@ DllInitialize(
     LogTrace("<=== (%08x)\n", Status);
     return Status;
 }
+
 NTSTATUS
 DllUnload(
     VOID
@@ -343,4 +360,14 @@ DriverEntry(
     UNREFERENCED_PARAMETER(RegistryPath);
 
     return STATUS_SUCCESS;
-}
\ No newline at end of file
+}
+
+DRIVER_UNLOAD               DriverUnload;
+
+VOID
+DriverUnload(
+    IN PDRIVER_OBJECT  _DriverObject
+    )
+{
+    UNREFERENCED_PARAMETER(_DriverObject);
+}
index a0903b8ac6d23dd2d1f538c1d6bf8cfe2bd5b89d..20f733aa4b53395766e11104d5c7de1e06f26c74 100644 (file)
@@ -33,7 +33,7 @@
 
 #include "driver.h"
 #include "fdo.h"
-#include "pdo-inquiry.h"
+#include "pdoinquiry.h"
 
 #include "austere.h"
 #include "store.h"
diff --git a/src/xencrsh/pdo-inquiry.c b/src/xencrsh/pdo-inquiry.c
deleted file mode 100644 (file)
index dc33136..0000000
+++ /dev/null
@@ -1,765 +0,0 @@
-/* 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 "pdo-inquiry.h"
-
-#include "store.h"
-#include "austere.h"
-
-#include <xencdb.h>
-#include "log.h"
-#include "assert.h"
-#include "util.h"
-
-#include <stdlib.h>
-
-typedef struct _XENVBD_PAGE {
-    LIST_ENTRY  List;
-
-    UCHAR       PageCode;
-    PVOID       Data;
-    ULONG       Length;
-} XENVBD_PAGE, *PXENVBD_PAGE;
-
-typedef struct _XENVBD_INQUIRY {
-    LIST_ENTRY  ListHead;
-
-    XENVBD_PAGE StandardPage;
-
-    XENVBD_PAGE Page00;
-} XENVBD_INQUIRY, *PXENVBD_INQUIRY;
-
-#define INQUIRY_POOL_TAG 'IBVX'
-
-static VOID
-__DefaultInquiry(
-    IN  PSCSI_REQUEST_BLOCK Srb
-    )
-{
-    const UCHAR Evpd = Cdb_EVPD(Srb);
-    const UCHAR PageCode = Cdb_PageCode(Srb);
-
-    if (Evpd == 0)
-    {
-        if (PageCode == 0 && Srb->DataTransferLength >= INQUIRYDATABUFFERSIZE)
-        {
-            PINQUIRYDATA InqData = (PINQUIRYDATA)Srb->DataBuffer;
-            // setup inquiry data
-            InqData->Versions = 4;
-            InqData->ResponseDataFormat = 2;
-            InqData->AdditionalLength = 0;
-            InqData->CommandQueue = 1;
-            RtlCopyMemory(&InqData->VendorId,             "XENSRC  ", 8);
-            RtlCopyMemory(&InqData->ProductId,            "PVDISK          ", 16);
-            RtlCopyMemory(&InqData->ProductRevisionLevel, "2.0 ", 4);
-            // succeed
-            Srb->SrbStatus = SRB_STATUS_SUCCESS;
-            Srb->DataTransferLength = INQUIRYDATABUFFERSIZE;
-        }
-    } else
-    {
-        PUCHAR Buffer = (PUCHAR)Srb->DataBuffer;
-        switch (PageCode) 
-        {
-        case 0x00:
-            if (Srb->DataTransferLength >= 7)
-            {
-                Buffer[0] = 0x00;
-                Buffer[1] = PageCode;
-                Buffer[2] = 0x00;
-                Buffer[3] = 3;
-                Buffer[4] = 0x00;
-                Buffer[5] = 0x80;
-                Buffer[6] = 0x83;
-                Srb->SrbStatus = SRB_STATUS_SUCCESS;
-                Srb->DataTransferLength = 7;
-            }
-            break;
-        case 0x80:
-            if (Srb->DataTransferLength >= 5)
-            {
-                Buffer[0] = 0x00;
-                Buffer[1] = PageCode;
-                Buffer[2] = 0x00;
-                Buffer[3] = 1;
-                Buffer[4] = ' ';
-                Srb->SrbStatus = SRB_STATUS_SUCCESS;
-                Srb->DataTransferLength = 5;
-            }
-            break;
-        case 0x83:
-            if (Srb->DataTransferLength >= 4)
-            {
-                Buffer[0] = 0x00;
-                Buffer[1] = PageCode;
-                Buffer[2] = 0x00;
-                Buffer[3] = 0;
-                Srb->SrbStatus = SRB_STATUS_SUCCESS;
-                Srb->DataTransferLength = 4;
-            }
-            break;
-        }
-    }
-}
-
-static FORCEINLINE PXENVBD_PAGE
-__FindPage(
-    IN  PXENVBD_INQUIRY Inquiry,
-    IN  UCHAR           Evpd,
-    IN  UCHAR           PageCode
-    )
-{
-    PLIST_ENTRY     Entry;
-    PXENVBD_PAGE    Page = NULL;
-
-    if (Evpd == 0) {
-        if (PageCode == 0) {
-            Page = &Inquiry->StandardPage;
-        }
-    } else {
-        if (PageCode == 0) {
-            Page = &Inquiry->Page00;
-        } else {
-            for (Entry = Inquiry->ListHead.Flink; Entry != &Inquiry->ListHead; Entry = Entry->Flink) {
-                PXENVBD_PAGE ThisPage = CONTAINING_RECORD(Entry, XENVBD_PAGE, List);
-                if (ThisPage->PageCode == PageCode) {
-                    Page = ThisPage;
-                    break;
-                }
-            }
-        }
-    }
-    if (Page && Page->Data && Page->Length) {
-        return Page;
-    } else {
-        LogTrace("Inquiry Page %d:%d not found\n", Evpd, PageCode);
-        return NULL;
-    }
-}
-
-
-static VOID
-__FreeInquiryData(
-    IN  PXENVBD_INQUIRY     Inquiry
-    )
-{
-    PLIST_ENTRY     Entry;
-    PXENVBD_PAGE    Page;
-
-    // free standard page
-    if (Inquiry->StandardPage.Data) {
-        AustereFree(Inquiry->StandardPage.Data);
-    }
-    // free page00
-    if (Inquiry->Page00.Data) {
-        AustereFree(Inquiry->Page00.Data);
-    }
-
-    // free other pages
-    while ((Entry = RemoveHeadList(&Inquiry->ListHead)) != &Inquiry->ListHead) {
-        Page = CONTAINING_RECORD(Entry, XENVBD_PAGE, List);
-        if (Page->Data) {
-            AustereFree(Page->Data);
-        }
-        AustereFree(Page);
-    }
-
-    // free data
-    AustereFree(Inquiry);
-}
-
-
-static FORCEINLINE UCHAR
-__PageCode(
-    IN  PCHAR   PageCode
-    )
-{
-    ULONG Ret;
-    if (PageCode[0] == '0' && PageCode[1] == 'x')
-        Ret = strtoul(PageCode + 2, NULL, 16);
-    else
-        Ret = strtoul(PageCode, NULL, 10);
-    ASSERT3U(Ret, <, 256);
-    return (UCHAR)Ret;
-}
-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 FORCEINLINE 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;
-}
-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)AustereAllocate(NumBlocks * 3);
-    if (!Buffer) {
-        LogError("AustereAllocate (STATUS_INSUFFICIENT_RESOURCES)\n");
-        goto fail1;
-    }
-    RtlZeroMemory(Buffer, NumBlocks * 3);
-
-    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:
-    LogError("Invalid BASE64 encoding\n");
-    AustereFree(Buffer);
-    return STATUS_UNSUCCESSFUL;
-
-fail1:
-    return STATUS_INSUFFICIENT_RESOURCES;
-}
-static NTSTATUS
-__ReadPage(
-    IN  PXENVBD_INQUIRY         Inquiry,
-    IN  PCHAR                   BasePath,
-    IN  PCHAR                   PageCode
-    )
-{
-    NTSTATUS        Status;
-    PCHAR           Base64;
-    ULONG           Base64Length;
-    PVOID           Buffer;
-    ULONG           BufferLength;
-    PXENVBD_PAGE    Page;
-
-    Status = StoreRead(NULL, BasePath, PageCode, &Base64);
-    if (!NT_SUCCESS(Status)) {
-        LogError("STORE:Read %s/%s (%08x)\n", BasePath, PageCode, Status);
-        goto fail1;
-    }
-    Base64Length = (ULONG)strlen(Base64);
-
-    Status = __DecodeBase64(Base64, Base64Length, &Buffer, &BufferLength);
-    if (!NT_SUCCESS(Status)) {
-        goto fail2;
-    }
-    AustereFree(Base64);
-
-    if (!strcmp(PageCode, "default")) {
-        Inquiry->StandardPage.PageCode = 0;
-        Inquiry->StandardPage.Data = Buffer;
-        Inquiry->StandardPage.Length = BufferLength;
-    } else {
-        Page = (PXENVBD_PAGE)AustereAllocate(sizeof(XENVBD_PAGE));
-        if (!Page) {
-            Status = STATUS_INSUFFICIENT_RESOURCES;
-            LogError("AustereAllocate (STATUS_INSUFFICIENT_RESOURCES)\n");
-            goto fail3;
-        }
-        RtlZeroMemory(Page, sizeof(XENVBD_PAGE));
-
-        Page->PageCode = __PageCode(PageCode);
-        if (Page->PageCode == 0) {
-            LogError("PageCode %s is not Valid\n", PageCode);
-            goto fail4;
-        }
-        Page->Data = Buffer;
-        Page->Length = BufferLength;
-
-        InsertHeadList(&Inquiry->ListHead, &Page->List);
-    }
-
-    return STATUS_SUCCESS;
-
-fail4:
-    AustereFree(Page);
-
-fail3:
-    AustereFree(Buffer);
-
-fail2:
-    AustereFree(Base64);
-
-fail1:
-    return Status;
-}
-static NTSTATUS
-__GeneratePage83(
-    IN  PXENVBD_INQUIRY         Inquiry
-    )
-{
-    PXENVBD_PAGE    Page;
-    PUCHAR          Data;
-
-    Page = (PXENVBD_PAGE)AustereAllocate(sizeof(XENVBD_PAGE));
-    if (!Page) {
-        LogError("AustereAllocate (STATUS_INSUFFICIENT_RESOURCES)\n");
-        goto fail1;
-    }
-    RtlZeroMemory(Page, sizeof(XENVBD_PAGE));
-
-    Page->PageCode = 0x83;
-    Page->Length = 4;
-    Page->Data = AustereAllocate(Page->Length);
-    if (!Page->Data) {
-        LogError("AustereAllocate (STATUS_INSUFFICIENT_RESOURCES)\n");
-        goto fail2;
-    }
-    RtlZeroMemory(Page->Data, Page->Length);
-    Data =  (PUCHAR)Page->Data;
-
-    Data[1] = 0x83;
-
-    InsertHeadList(&Inquiry->ListHead, &Page->List);
-    return STATUS_SUCCESS;
-
-fail2:
-    AustereFree(Page);
-fail1:
-    return STATUS_INSUFFICIENT_RESOURCES;
-}
-static NTSTATUS
-__GeneratePage80(
-    IN  PXENVBD_INQUIRY         Inquiry
-    )
-{
-    PXENVBD_PAGE            Page;
-    PVPD_SERIAL_NUMBER_PAGE Data;
-
-    Page = (PXENVBD_PAGE)AustereAllocate(sizeof(XENVBD_PAGE));
-    if (!Page) {
-        LogError("AustereAllocate (STATUS_INSUFFICIENT_RESOURCES)\n");
-        goto fail1;
-    }
-    RtlZeroMemory(Page, sizeof(XENVBD_PAGE));
-
-    Page->PageCode = 0x80;
-    Page->Length = sizeof(VPD_SERIAL_NUMBER_PAGE) + 1;
-    Page->Data = AustereAllocate(Page->Length);
-    if (!Page->Data) {
-        LogError("AustereAllocate (STATUS_INSUFFICIENT_RESOURCES)\n");
-        goto fail2;
-    }
-    RtlZeroMemory(Page->Data, Page->Length);
-    Data =  (PVPD_SERIAL_NUMBER_PAGE)Page->Data;
-
-    Data->PageCode          = VPD_SERIAL_NUMBER;
-    Data->PageLength        = 1;
-    Data->SerialNumber[0]   = ' ';
-
-    InsertHeadList(&Inquiry->ListHead, &Page->List);
-    return STATUS_SUCCESS;
-
-fail2:
-    AustereFree(Page);
-fail1:
-    return STATUS_INSUFFICIENT_RESOURCES;
-}
-static FORCEINLINE NTSTATUS
-__GeneratePageStd(
-    IN  PXENVBD_INQUIRY         Inquiry
-    )
-{
-    INQUIRYDATA     *Data;
-
-    Inquiry->StandardPage.PageCode = 0;
-    Inquiry->StandardPage.Length = sizeof(INQUIRYDATA);
-    Inquiry->StandardPage.Data = AustereAllocate(sizeof(INQUIRYDATA));
-    if (!Inquiry->StandardPage.Data) {
-        LogError("AustereAllocate (STATUS_INSUFFICIENT_RESOURCES)\n");
-        goto fail1;
-    }
-    RtlZeroMemory(Inquiry->StandardPage.Data, Inquiry->StandardPage.Length);
-    Data = (PINQUIRYDATA)Inquiry->StandardPage.Data;
-
-    // fill in some bits
-    Data->DeviceType            = DIRECT_ACCESS_DEVICE;
-    Data->DeviceTypeQualifier   = DEVICE_CONNECTED;
-    Data->Versions              = 4;
-    Data->ResponseDataFormat    = 2;
-    Data->AdditionalLength      = sizeof(INQUIRYDATA) - 5;
-    Data->CommandQueue          = 1;
-    RtlCopyMemory(Data->VendorId,               "XENSRC  ", 8);
-    RtlCopyMemory(Data->ProductId,              "PVDISK          ", 16);
-    RtlCopyMemory(Data->ProductRevisionLevel,   "2.0 ", 4);
-
-    return STATUS_SUCCESS;
-
-fail1:
-    return STATUS_INSUFFICIENT_RESOURCES;
-}
-static NTSTATUS
-__GeneratePage00(
-    IN  PXENVBD_INQUIRY         Inquiry
-    )
-{
-    PUCHAR          Buffer;
-    ULONG           PageNum;
-    PLIST_ENTRY     Entry;
-    PXENVBD_PAGE    Page;
-    ULONG           NumPages = 0;
-    
-    for (Entry = Inquiry->ListHead.Flink; Entry != &Inquiry->ListHead; Entry = Entry->Flink) {
-        ++NumPages;
-    }
-
-    Inquiry->Page00.PageCode = 0;
-    Inquiry->Page00.Length = 5 + NumPages;
-    Inquiry->Page00.Data = AustereAllocate(Inquiry->Page00.Length);
-    if (!Inquiry->Page00.Data) {
-        LogError("AustereAllocate (STATUS_INSUFFICIENT_RESOURCES)\n");
-        goto fail1;
-    }
-    RtlZeroMemory(Inquiry->Page00.Data, Inquiry->Page00.Length);
-    Buffer = (PUCHAR)Inquiry->Page00.Data;
-    
-    if (Inquiry->Page00.Length < 5 + NumPages) {
-        // PREFAST:Warning suppress
-        goto fail2;
-    }
-    // 00 00 00 NumPages+1 00 [Page [...]]
-    Buffer[3] = (UCHAR)(NumPages + 1);
-
-    ASSERT(Inquiry->Page00.Length == 5 + NumPages);
-
-    PageNum = 0;
-    for (Entry = Inquiry->ListHead.Flink; Entry != &Inquiry->ListHead; Entry = Entry->Flink) {
-        Page = CONTAINING_RECORD(Entry, XENVBD_PAGE, List);
-        Buffer[5 + PageNum] = Page->PageCode;
-        ++PageNum;
-    }
-
-    return STATUS_SUCCESS;
-
-fail2:
-    AustereFree(Inquiry->Page00.Data);
-    Inquiry->Page00.Data = NULL;
-    Inquiry->Page00.Length = 0;
-
-fail1:
-    return STATUS_INSUFFICIENT_RESOURCES;
-}
-static NTSTATUS
-__ReadInquiry(
-    IN  PCHAR                   Path,
-    OUT PVOID*                  _Inquiry
-    )
-{
-    NTSTATUS        Status;
-    PXENVBD_INQUIRY Inquiry;
-    PCHAR           InquiryPath;
-    PCHAR           PageList;
-    PCHAR           ThisPage;
-
-    Status = STATUS_INSUFFICIENT_RESOURCES;
-    InquiryPath = DriverFormat("%s/sm-data/scsi/0x12", Path);
-    if (!InquiryPath) {
-        goto fail1;
-    }
-
-    Inquiry = (PXENVBD_INQUIRY)AustereAllocate(sizeof(XENVBD_INQUIRY));
-    if (!Inquiry) {
-        AustereFree(InquiryPath);
-        goto fail2;
-    }
-    RtlZeroMemory(Inquiry, sizeof(XENVBD_INQUIRY));
-    InitializeListHead(&Inquiry->ListHead);
-
-    Status = StoreDirectory(NULL, NULL, InquiryPath, &PageList);
-    if (!NT_SUCCESS(Status)) {
-        AustereFree(InquiryPath);
-        goto fail3;
-    }
-
-    ThisPage = PageList;
-    while (*ThisPage != '\0') {
-        Status = __ReadPage(Inquiry, InquiryPath, ThisPage);
-        if (!NT_SUCCESS(Status)) {
-            AustereFree(PageList);
-            goto fail4;
-        }
-        // Advance to next page
-        for ( ; *ThisPage; ++ThisPage)  ;
-        ++ThisPage;
-    }
-    AustereFree(PageList);
-
-    // generate Page 0x83
-    if (!__FindPage(Inquiry, 1, 0x83)) {
-        Status = __GeneratePage83(Inquiry);
-        if (!NT_SUCCESS(Status)) {
-            goto fail4;
-        }
-    }
-    // generate Page 0x80
-    if (!__FindPage(Inquiry, 1, 0x80)) {
-        Status = __GeneratePage80(Inquiry);
-        if (!NT_SUCCESS(Status)) {
-            goto fail4;
-        }
-    }
-    // generate StdPage
-    if (!__FindPage(Inquiry, 0, 0x00)) {
-        Status = __GeneratePageStd(Inquiry);
-        if (!NT_SUCCESS(Status)) {
-            goto fail4;
-        }
-    }
-
-    // generate Page 0x00
-    Status = __GeneratePage00(Inquiry);
-    if (!NT_SUCCESS(Status)) {
-        goto fail4;
-    }
-
-    // Succeed
-    AustereFree(InquiryPath);
-    *_Inquiry = Inquiry;
-    return STATUS_SUCCESS;
-
-fail4:
-    LogError("Fail4\n");
-fail3:
-    LogError("Fail3\n");
-    __FreeInquiryData(Inquiry);
-fail2:
-    LogError("Fail2\n");
-    AustereFree(InquiryPath);
-fail1:
-    LogError("Fail1 (%08x)\n", Status);
-    return Status;
-}
-
-static FORCEINLINE ULONG
-__Min(
-    IN  ULONG   A,
-    IN  ULONG   B
-    )
-{
-    return A < B ? A : B;
-}
-static FORCEINLINE VOID
-__DumpBytes(
-    IN  PUCHAR  Bytes,
-    IN  ULONG   Length
-    )
-{
-    ULONG ThisTime, Index;
-
-    for (Index = 0; Index < Length; ) {
-        ThisTime = __Min(Length - Index, 8);
-        switch (ThisTime) {
-        case 1:
-            LogTrace("[%02x-%02x] : %02x\n", Index, Index + 0, Bytes[Index + 0]);
-            break;
-        case 2:
-            LogTrace("[%02x-%02x] : %02x %02x\n", Index, Index + 1, Bytes[Index + 0], Bytes[Index + 1]);
-            break;
-        case 3:
-            LogTrace("[%02x-%02x] : %02x %02x %02x\n", Index, Index + 2, 
-                Bytes[Index + 0], Bytes[Index + 1], Bytes[Index + 2]);
-            break;
-        case 4:
-            LogTrace("[%02x-%02x] : %02x %02x %02x %02x\n", Index, Index + 3, 
-                Bytes[Index + 0], Bytes[Index + 1], Bytes[Index + 2], Bytes[Index + 3]);
-            break;
-        case 5:
-            LogTrace("[%02x-%02x] : %02x %02x %02x %02x %02x\n", Index, Index + 4, 
-                Bytes[Index + 0], Bytes[Index + 1], Bytes[Index + 2], Bytes[Index + 3],
-                Bytes[Index + 4]);
-            break;
-        case 6:
-            LogTrace("[%02x-%02x] : %02x %02x %02x %02x %02x %02x\n", Index, Index + 5, 
-                Bytes[Index + 0], Bytes[Index + 1], Bytes[Index + 2], Bytes[Index + 3],
-                Bytes[Index + 4], Bytes[Index + 5]);
-            break;
-        case 7:
-            LogTrace("[%02x-%02x] : %02x %02x %02x %02x %02x %02x %02x\n", Index, Index + 6, 
-                Bytes[Index + 0], Bytes[Index + 1], Bytes[Index + 2], Bytes[Index + 3],
-                Bytes[Index + 4], Bytes[Index + 5], Bytes[Index + 6]);
-            break;
-        case 8:
-            LogTrace("[%02x-%02x] : %02x %02x %02x %02x %02x %02x %02x %02x\n", Index, Index + 7, 
-                Bytes[Index + 0], Bytes[Index + 1], Bytes[Index + 2], Bytes[Index + 3],
-                Bytes[Index + 4], Bytes[Index + 5], Bytes[Index + 6], Bytes[Index + 7]);
-            break;
-        }
-        Index += ThisTime;
-    }
-}
-static FORCEINLINE VOID
-__DumpPage(
-    IN  PXENVBD_PAGE    Page
-    )
-{
-    LogTrace("PAGE_CODE : %02x\n", Page->PageCode);
-    LogTrace("Length    : %d bytes\n", Page->Length);
-    __DumpBytes((PUCHAR)Page->Data, Page->Length);
-}
-static FORCEINLINE VOID
-__DumpPageStandard(
-    IN  PXENVBD_PAGE    Page
-    )
-{
-    LogTrace("PAGE_CODE : %02x STANDARD\n", Page->PageCode);
-    LogTrace("Length    : %d bytes\n", Page->Length);
-    __DumpBytes((PUCHAR)Page->Data, Page->Length);
-}
-static FORCEINLINE VOID
-__DumpInquiry(
-    IN  PVOID           _Inquiry
-    )
-{
-    PLIST_ENTRY     Entry;
-    PXENVBD_INQUIRY Inquiry = (PXENVBD_INQUIRY)_Inquiry;
-
-    __DumpPageStandard(&Inquiry->StandardPage);
-
-    __DumpPage(&Inquiry->Page00);
-
-    for (Entry = Inquiry->ListHead.Flink; Entry != &Inquiry->ListHead; Entry = Entry->Flink) {
-        PXENVBD_PAGE Page = CONTAINING_RECORD(Entry, XENVBD_PAGE, List);
-        __DumpPage(Page);
-    }
-}
-
-VOID
-PdoReadInquiryData(
-    IN  PXENVBD_FRONTEND        Frontend,
-    OUT PVOID*                  _Inquiry
-    )
-{
-    NTSTATUS        Status;
-
-    Status = __ReadInquiry(Frontend->BackendPath, _Inquiry);
-    if (!NT_SUCCESS(Status))
-        goto fail;
-
-    __DumpInquiry(*_Inquiry);
-    return;
-
-fail:
-    LogError("Fail (%08x)\n", Status);
-}
-
-VOID
-PdoFreeInquiryData(
-    IN  PVOID                   Inquiry
-    )
-{
-    __FreeInquiryData((PXENVBD_INQUIRY)Inquiry);
-}
-
-VOID
-PdoInquiry(
-    IN  PVOID                   Inquiry,
-    IN  PSCSI_REQUEST_BLOCK     Srb
-    )
-{
-    ULONG           Length;
-    PXENVBD_PAGE    Page;
-    const UCHAR     Evpd = Cdb_EVPD(Srb);
-    const UCHAR     PageCode = Cdb_PageCode(Srb);
-
-    if (Inquiry) {
-        Page = __FindPage((PXENVBD_INQUIRY)Inquiry, Evpd, PageCode);
-        if (Page) {
-            Length = Page->Length;
-            if (Srb->DataTransferLength < Length)
-                Length = Srb->DataTransferLength;
-            RtlCopyMemory(Srb->DataBuffer, Page->Data, Length);
-            Srb->DataTransferLength = Length;
-            Srb->SrbStatus = SRB_STATUS_SUCCESS;
-        }
-    } else {
-        __DefaultInquiry(Srb);
-    }
-}
-
diff --git a/src/xencrsh/pdo-inquiry.h b/src/xencrsh/pdo-inquiry.h
deleted file mode 100644 (file)
index e87a882..0000000
+++ /dev/null
@@ -1,59 +0,0 @@
-/* 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 <wdm.h>
-#include <xenvbd-storport.h>
-
-
-#include "frontend.h"
-
-extern VOID
-PdoReadInquiryData(
-    IN  PXENVBD_FRONTEND        Frontend,
-    OUT PVOID*                  _Inquiry
-    );
-
-extern VOID
-PdoFreeInquiryData(
-    IN  PVOID                   Inquiry
-    );
-
-extern VOID
-PdoInquiry(
-    IN  PVOID                   Inquiry,
-    IN  PSCSI_REQUEST_BLOCK     Srb
-    );
-
-#endif // _XENVBD_PDO_INQUIRY_H
-
index 654671a260f5b5225b2bc98f7e4161575cf61d06..2ab764b600c7ffeab4316c50add6fc4fd24c9c50 100644 (file)
@@ -38,7 +38,7 @@
 #include "ring.h"
 #include "srbext.h"
 #include "buffer.h"
-#include "pdo-inquiry.h"
+#include "pdoinquiry.h"
 
 #include "austere.h"
 #include "store.h"
diff --git a/src/xencrsh/pdoinquiry.c b/src/xencrsh/pdoinquiry.c
new file mode 100644 (file)
index 0000000..b72bcf8
--- /dev/null
@@ -0,0 +1,765 @@
+/* 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 "store.h"
+#include "austere.h"
+
+#include <xencdb.h>
+#include "log.h"
+#include "assert.h"
+#include "util.h"
+
+#include <stdlib.h>
+
+typedef struct _XENVBD_PAGE {
+    LIST_ENTRY  List;
+
+    UCHAR       PageCode;
+    PVOID       Data;
+    ULONG       Length;
+} XENVBD_PAGE, *PXENVBD_PAGE;
+
+typedef struct _XENVBD_INQUIRY {
+    LIST_ENTRY  ListHead;
+
+    XENVBD_PAGE StandardPage;
+
+    XENVBD_PAGE Page00;
+} XENVBD_INQUIRY, *PXENVBD_INQUIRY;
+
+#define INQUIRY_POOL_TAG 'IBVX'
+
+static VOID
+__DefaultInquiry(
+    IN  PSCSI_REQUEST_BLOCK Srb
+    )
+{
+    const UCHAR Evpd = Cdb_EVPD(Srb);
+    const UCHAR PageCode = Cdb_PageCode(Srb);
+
+    if (Evpd == 0)
+    {
+        if (PageCode == 0 && Srb->DataTransferLength >= INQUIRYDATABUFFERSIZE)
+        {
+            PINQUIRYDATA InqData = (PINQUIRYDATA)Srb->DataBuffer;
+            // setup inquiry data
+            InqData->Versions = 4;
+            InqData->ResponseDataFormat = 2;
+            InqData->AdditionalLength = 0;
+            InqData->CommandQueue = 1;
+            RtlCopyMemory(&InqData->VendorId,             "XENSRC  ", 8);
+            RtlCopyMemory(&InqData->ProductId,            "PVDISK          ", 16);
+            RtlCopyMemory(&InqData->ProductRevisionLevel, "2.0 ", 4);
+            // succeed
+            Srb->SrbStatus = SRB_STATUS_SUCCESS;
+            Srb->DataTransferLength = INQUIRYDATABUFFERSIZE;
+        }
+    } else
+    {
+        PUCHAR Buffer = (PUCHAR)Srb->DataBuffer;
+        switch (PageCode) 
+        {
+        case 0x00:
+            if (Srb->DataTransferLength >= 7)
+            {
+                Buffer[0] = 0x00;
+                Buffer[1] = PageCode;
+                Buffer[2] = 0x00;
+                Buffer[3] = 3;
+                Buffer[4] = 0x00;
+                Buffer[5] = 0x80;
+                Buffer[6] = 0x83;
+                Srb->SrbStatus = SRB_STATUS_SUCCESS;
+                Srb->DataTransferLength = 7;
+            }
+            break;
+        case 0x80:
+            if (Srb->DataTransferLength >= 5)
+            {
+                Buffer[0] = 0x00;
+                Buffer[1] = PageCode;
+                Buffer[2] = 0x00;
+                Buffer[3] = 1;
+                Buffer[4] = ' ';
+                Srb->SrbStatus = SRB_STATUS_SUCCESS;
+                Srb->DataTransferLength = 5;
+            }
+            break;
+        case 0x83:
+            if (Srb->DataTransferLength >= 4)
+            {
+                Buffer[0] = 0x00;
+                Buffer[1] = PageCode;
+                Buffer[2] = 0x00;
+                Buffer[3] = 0;
+                Srb->SrbStatus = SRB_STATUS_SUCCESS;
+                Srb->DataTransferLength = 4;
+            }
+            break;
+        }
+    }
+}
+
+static FORCEINLINE PXENVBD_PAGE
+__FindPage(
+    IN  PXENVBD_INQUIRY Inquiry,
+    IN  UCHAR           Evpd,
+    IN  UCHAR           PageCode
+    )
+{
+    PLIST_ENTRY     Entry;
+    PXENVBD_PAGE    Page = NULL;
+
+    if (Evpd == 0) {
+        if (PageCode == 0) {
+            Page = &Inquiry->StandardPage;
+        }
+    } else {
+        if (PageCode == 0) {
+            Page = &Inquiry->Page00;
+        } else {
+            for (Entry = Inquiry->ListHead.Flink; Entry != &Inquiry->ListHead; Entry = Entry->Flink) {
+                PXENVBD_PAGE ThisPage = CONTAINING_RECORD(Entry, XENVBD_PAGE, List);
+                if (ThisPage->PageCode == PageCode) {
+                    Page = ThisPage;
+                    break;
+                }
+            }
+        }
+    }
+    if (Page && Page->Data && Page->Length) {
+        return Page;
+    } else {
+        LogTrace("Inquiry Page %d:%d not found\n", Evpd, PageCode);
+        return NULL;
+    }
+}
+
+
+static VOID
+__FreeInquiryData(
+    IN  PXENVBD_INQUIRY     Inquiry
+    )
+{
+    PLIST_ENTRY     Entry;
+    PXENVBD_PAGE    Page;
+
+    // free standard page
+    if (Inquiry->StandardPage.Data) {
+        AustereFree(Inquiry->StandardPage.Data);
+    }
+    // free page00
+    if (Inquiry->Page00.Data) {
+        AustereFree(Inquiry->Page00.Data);
+    }
+
+    // free other pages
+    while ((Entry = RemoveHeadList(&Inquiry->ListHead)) != &Inquiry->ListHead) {
+        Page = CONTAINING_RECORD(Entry, XENVBD_PAGE, List);
+        if (Page->Data) {
+            AustereFree(Page->Data);
+        }
+        AustereFree(Page);
+    }
+
+    // free data
+    AustereFree(Inquiry);
+}
+
+
+static FORCEINLINE UCHAR
+__PageCode(
+    IN  PCHAR   PageCode
+    )
+{
+    ULONG Ret;
+    if (PageCode[0] == '0' && PageCode[1] == 'x')
+        Ret = strtoul(PageCode + 2, NULL, 16);
+    else
+        Ret = strtoul(PageCode, NULL, 10);
+    ASSERT3U(Ret, <, 256);
+    return (UCHAR)Ret;
+}
+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 FORCEINLINE 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;
+}
+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)AustereAllocate(NumBlocks * 3);
+    if (!Buffer) {
+        LogError("AustereAllocate (STATUS_INSUFFICIENT_RESOURCES)\n");
+        goto fail1;
+    }
+    RtlZeroMemory(Buffer, NumBlocks * 3);
+
+    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:
+    LogError("Invalid BASE64 encoding\n");
+    AustereFree(Buffer);
+    return STATUS_UNSUCCESSFUL;
+
+fail1:
+    return STATUS_INSUFFICIENT_RESOURCES;
+}
+static NTSTATUS
+__ReadPage(
+    IN  PXENVBD_INQUIRY         Inquiry,
+    IN  PCHAR                   BasePath,
+    IN  PCHAR                   PageCode
+    )
+{
+    NTSTATUS        Status;
+    PCHAR           Base64;
+    ULONG           Base64Length;
+    PVOID           Buffer;
+    ULONG           BufferLength;
+    PXENVBD_PAGE    Page;
+
+    Status = StoreRead(NULL, BasePath, PageCode, &Base64);
+    if (!NT_SUCCESS(Status)) {
+        LogError("STORE:Read %s/%s (%08x)\n", BasePath, PageCode, Status);
+        goto fail1;
+    }
+    Base64Length = (ULONG)strlen(Base64);
+
+    Status = __DecodeBase64(Base64, Base64Length, &Buffer, &BufferLength);
+    if (!NT_SUCCESS(Status)) {
+        goto fail2;
+    }
+    AustereFree(Base64);
+
+    if (!strcmp(PageCode, "default")) {
+        Inquiry->StandardPage.PageCode = 0;
+        Inquiry->StandardPage.Data = Buffer;
+        Inquiry->StandardPage.Length = BufferLength;
+    } else {
+        Page = (PXENVBD_PAGE)AustereAllocate(sizeof(XENVBD_PAGE));
+        if (!Page) {
+            Status = STATUS_INSUFFICIENT_RESOURCES;
+            LogError("AustereAllocate (STATUS_INSUFFICIENT_RESOURCES)\n");
+            goto fail3;
+        }
+        RtlZeroMemory(Page, sizeof(XENVBD_PAGE));
+
+        Page->PageCode = __PageCode(PageCode);
+        if (Page->PageCode == 0) {
+            LogError("PageCode %s is not Valid\n", PageCode);
+            goto fail4;
+        }
+        Page->Data = Buffer;
+        Page->Length = BufferLength;
+
+        InsertHeadList(&Inquiry->ListHead, &Page->List);
+    }
+
+    return STATUS_SUCCESS;
+
+fail4:
+    AustereFree(Page);
+
+fail3:
+    AustereFree(Buffer);
+
+fail2:
+    AustereFree(Base64);
+
+fail1:
+    return Status;
+}
+static NTSTATUS
+__GeneratePage83(
+    IN  PXENVBD_INQUIRY         Inquiry
+    )
+{
+    PXENVBD_PAGE    Page;
+    PUCHAR          Data;
+
+    Page = (PXENVBD_PAGE)AustereAllocate(sizeof(XENVBD_PAGE));
+    if (!Page) {
+        LogError("AustereAllocate (STATUS_INSUFFICIENT_RESOURCES)\n");
+        goto fail1;
+    }
+    RtlZeroMemory(Page, sizeof(XENVBD_PAGE));
+
+    Page->PageCode = 0x83;
+    Page->Length = 4;
+    Page->Data = AustereAllocate(Page->Length);
+    if (!Page->Data) {
+        LogError("AustereAllocate (STATUS_INSUFFICIENT_RESOURCES)\n");
+        goto fail2;
+    }
+    RtlZeroMemory(Page->Data, Page->Length);
+    Data =  (PUCHAR)Page->Data;
+
+    Data[1] = 0x83;
+
+    InsertHeadList(&Inquiry->ListHead, &Page->List);
+    return STATUS_SUCCESS;
+
+fail2:
+    AustereFree(Page);
+fail1:
+    return STATUS_INSUFFICIENT_RESOURCES;
+}
+static NTSTATUS
+__GeneratePage80(
+    IN  PXENVBD_INQUIRY         Inquiry
+    )
+{
+    PXENVBD_PAGE            Page;
+    PVPD_SERIAL_NUMBER_PAGE Data;
+
+    Page = (PXENVBD_PAGE)AustereAllocate(sizeof(XENVBD_PAGE));
+    if (!Page) {
+        LogError("AustereAllocate (STATUS_INSUFFICIENT_RESOURCES)\n");
+        goto fail1;
+    }
+    RtlZeroMemory(Page, sizeof(XENVBD_PAGE));
+
+    Page->PageCode = 0x80;
+    Page->Length = sizeof(VPD_SERIAL_NUMBER_PAGE) + 1;
+    Page->Data = AustereAllocate(Page->Length);
+    if (!Page->Data) {
+        LogError("AustereAllocate (STATUS_INSUFFICIENT_RESOURCES)\n");
+        goto fail2;
+    }
+    RtlZeroMemory(Page->Data, Page->Length);
+    Data =  (PVPD_SERIAL_NUMBER_PAGE)Page->Data;
+
+    Data->PageCode          = VPD_SERIAL_NUMBER;
+    Data->PageLength        = 1;
+    Data->SerialNumber[0]   = ' ';
+
+    InsertHeadList(&Inquiry->ListHead, &Page->List);
+    return STATUS_SUCCESS;
+
+fail2:
+    AustereFree(Page);
+fail1:
+    return STATUS_INSUFFICIENT_RESOURCES;
+}
+static FORCEINLINE NTSTATUS
+__GeneratePageStd(
+    IN  PXENVBD_INQUIRY         Inquiry
+    )
+{
+    INQUIRYDATA     *Data;
+
+    Inquiry->StandardPage.PageCode = 0;
+    Inquiry->StandardPage.Length = sizeof(INQUIRYDATA);
+    Inquiry->StandardPage.Data = AustereAllocate(sizeof(INQUIRYDATA));
+    if (!Inquiry->StandardPage.Data) {
+        LogError("AustereAllocate (STATUS_INSUFFICIENT_RESOURCES)\n");
+        goto fail1;
+    }
+    RtlZeroMemory(Inquiry->StandardPage.Data, Inquiry->StandardPage.Length);
+    Data = (PINQUIRYDATA)Inquiry->StandardPage.Data;
+
+    // fill in some bits
+    Data->DeviceType            = DIRECT_ACCESS_DEVICE;
+    Data->DeviceTypeQualifier   = DEVICE_CONNECTED;
+    Data->Versions              = 4;
+    Data->ResponseDataFormat    = 2;
+    Data->AdditionalLength      = sizeof(INQUIRYDATA) - 5;
+    Data->CommandQueue          = 1;
+    RtlCopyMemory(Data->VendorId,               "XENSRC  ", 8);
+    RtlCopyMemory(Data->ProductId,              "PVDISK          ", 16);
+    RtlCopyMemory(Data->ProductRevisionLevel,   "2.0 ", 4);
+
+    return STATUS_SUCCESS;
+
+fail1:
+    return STATUS_INSUFFICIENT_RESOURCES;
+}
+static NTSTATUS
+__GeneratePage00(
+    IN  PXENVBD_INQUIRY         Inquiry
+    )
+{
+    PUCHAR          Buffer;
+    ULONG           PageNum;
+    PLIST_ENTRY     Entry;
+    PXENVBD_PAGE    Page;
+    ULONG           NumPages = 0;
+    
+    for (Entry = Inquiry->ListHead.Flink; Entry != &Inquiry->ListHead; Entry = Entry->Flink) {
+        ++NumPages;
+    }
+
+    Inquiry->Page00.PageCode = 0;
+    Inquiry->Page00.Length = 5 + NumPages;
+    Inquiry->Page00.Data = AustereAllocate(Inquiry->Page00.Length);
+    if (!Inquiry->Page00.Data) {
+        LogError("AustereAllocate (STATUS_INSUFFICIENT_RESOURCES)\n");
+        goto fail1;
+    }
+    RtlZeroMemory(Inquiry->Page00.Data, Inquiry->Page00.Length);
+    Buffer = (PUCHAR)Inquiry->Page00.Data;
+    
+    if (Inquiry->Page00.Length < 5 + NumPages) {
+        // PREFAST:Warning suppress
+        goto fail2;
+    }
+    // 00 00 00 NumPages+1 00 [Page [...]]
+    Buffer[3] = (UCHAR)(NumPages + 1);
+
+    ASSERT(Inquiry->Page00.Length == 5 + NumPages);
+
+    PageNum = 0;
+    for (Entry = Inquiry->ListHead.Flink; Entry != &Inquiry->ListHead; Entry = Entry->Flink) {
+        Page = CONTAINING_RECORD(Entry, XENVBD_PAGE, List);
+        Buffer[5 + PageNum] = Page->PageCode;
+        ++PageNum;
+    }
+
+    return STATUS_SUCCESS;
+
+fail2:
+    AustereFree(Inquiry->Page00.Data);
+    Inquiry->Page00.Data = NULL;
+    Inquiry->Page00.Length = 0;
+
+fail1:
+    return STATUS_INSUFFICIENT_RESOURCES;
+}
+static NTSTATUS
+__ReadInquiry(
+    IN  PCHAR                   Path,
+    OUT PVOID*                  _Inquiry
+    )
+{
+    NTSTATUS        Status;
+    PXENVBD_INQUIRY Inquiry;
+    PCHAR           InquiryPath;
+    PCHAR           PageList;
+    PCHAR           ThisPage;
+
+    Status = STATUS_INSUFFICIENT_RESOURCES;
+    InquiryPath = DriverFormat("%s/sm-data/scsi/0x12", Path);
+    if (!InquiryPath) {
+        goto fail1;
+    }
+
+    Inquiry = (PXENVBD_INQUIRY)AustereAllocate(sizeof(XENVBD_INQUIRY));
+    if (!Inquiry) {
+        AustereFree(InquiryPath);
+        goto fail2;
+    }
+    RtlZeroMemory(Inquiry, sizeof(XENVBD_INQUIRY));
+    InitializeListHead(&Inquiry->ListHead);
+
+    Status = StoreDirectory(NULL, NULL, InquiryPath, &PageList);
+    if (!NT_SUCCESS(Status)) {
+        AustereFree(InquiryPath);
+        goto fail3;
+    }
+
+    ThisPage = PageList;
+    while (*ThisPage != '\0') {
+        Status = __ReadPage(Inquiry, InquiryPath, ThisPage);
+        if (!NT_SUCCESS(Status)) {
+            AustereFree(PageList);
+            goto fail4;
+        }
+        // Advance to next page
+        for ( ; *ThisPage; ++ThisPage)  ;
+        ++ThisPage;
+    }
+    AustereFree(PageList);
+
+    // generate Page 0x83
+    if (!__FindPage(Inquiry, 1, 0x83)) {
+        Status = __GeneratePage83(Inquiry);
+        if (!NT_SUCCESS(Status)) {
+            goto fail4;
+        }
+    }
+    // generate Page 0x80
+    if (!__FindPage(Inquiry, 1, 0x80)) {
+        Status = __GeneratePage80(Inquiry);
+        if (!NT_SUCCESS(Status)) {
+            goto fail4;
+        }
+    }
+    // generate StdPage
+    if (!__FindPage(Inquiry, 0, 0x00)) {
+        Status = __GeneratePageStd(Inquiry);
+        if (!NT_SUCCESS(Status)) {
+            goto fail4;
+        }
+    }
+
+    // generate Page 0x00
+    Status = __GeneratePage00(Inquiry);
+    if (!NT_SUCCESS(Status)) {
+        goto fail4;
+    }
+
+    // Succeed
+    AustereFree(InquiryPath);
+    *_Inquiry = Inquiry;
+    return STATUS_SUCCESS;
+
+fail4:
+    LogError("Fail4\n");
+fail3:
+    LogError("Fail3\n");
+    __FreeInquiryData(Inquiry);
+fail2:
+    LogError("Fail2\n");
+    AustereFree(InquiryPath);
+fail1:
+    LogError("Fail1 (%08x)\n", Status);
+    return Status;
+}
+
+static FORCEINLINE ULONG
+__Min(
+    IN  ULONG   A,
+    IN  ULONG   B
+    )
+{
+    return A < B ? A : B;
+}
+static FORCEINLINE VOID
+__DumpBytes(
+    IN  PUCHAR  Bytes,
+    IN  ULONG   Length
+    )
+{
+    ULONG ThisTime, Index;
+
+    for (Index = 0; Index < Length; ) {
+        ThisTime = __Min(Length - Index, 8);
+        switch (ThisTime) {
+        case 1:
+            LogTrace("[%02x-%02x] : %02x\n", Index, Index + 0, Bytes[Index + 0]);
+            break;
+        case 2:
+            LogTrace("[%02x-%02x] : %02x %02x\n", Index, Index + 1, Bytes[Index + 0], Bytes[Index + 1]);
+            break;
+        case 3:
+            LogTrace("[%02x-%02x] : %02x %02x %02x\n", Index, Index + 2, 
+                Bytes[Index + 0], Bytes[Index + 1], Bytes[Index + 2]);
+            break;
+        case 4:
+            LogTrace("[%02x-%02x] : %02x %02x %02x %02x\n", Index, Index + 3, 
+                Bytes[Index + 0], Bytes[Index + 1], Bytes[Index + 2], Bytes[Index + 3]);
+            break;
+        case 5:
+            LogTrace("[%02x-%02x] : %02x %02x %02x %02x %02x\n", Index, Index + 4, 
+                Bytes[Index + 0], Bytes[Index + 1], Bytes[Index + 2], Bytes[Index + 3],
+                Bytes[Index + 4]);
+            break;
+        case 6:
+            LogTrace("[%02x-%02x] : %02x %02x %02x %02x %02x %02x\n", Index, Index + 5, 
+                Bytes[Index + 0], Bytes[Index + 1], Bytes[Index + 2], Bytes[Index + 3],
+                Bytes[Index + 4], Bytes[Index + 5]);
+            break;
+        case 7:
+            LogTrace("[%02x-%02x] : %02x %02x %02x %02x %02x %02x %02x\n", Index, Index + 6, 
+                Bytes[Index + 0], Bytes[Index + 1], Bytes[Index + 2], Bytes[Index + 3],
+                Bytes[Index + 4], Bytes[Index + 5], Bytes[Index + 6]);
+            break;
+        case 8:
+            LogTrace("[%02x-%02x] : %02x %02x %02x %02x %02x %02x %02x %02x\n", Index, Index + 7, 
+                Bytes[Index + 0], Bytes[Index + 1], Bytes[Index + 2], Bytes[Index + 3],
+                Bytes[Index + 4], Bytes[Index + 5], Bytes[Index + 6], Bytes[Index + 7]);
+            break;
+        }
+        Index += ThisTime;
+    }
+}
+static FORCEINLINE VOID
+__DumpPage(
+    IN  PXENVBD_PAGE    Page
+    )
+{
+    LogTrace("PAGE_CODE : %02x\n", Page->PageCode);
+    LogTrace("Length    : %d bytes\n", Page->Length);
+    __DumpBytes((PUCHAR)Page->Data, Page->Length);
+}
+static FORCEINLINE VOID
+__DumpPageStandard(
+    IN  PXENVBD_PAGE    Page
+    )
+{
+    LogTrace("PAGE_CODE : %02x STANDARD\n", Page->PageCode);
+    LogTrace("Length    : %d bytes\n", Page->Length);
+    __DumpBytes((PUCHAR)Page->Data, Page->Length);
+}
+static FORCEINLINE VOID
+__DumpInquiry(
+    IN  PVOID           _Inquiry
+    )
+{
+    PLIST_ENTRY     Entry;
+    PXENVBD_INQUIRY Inquiry = (PXENVBD_INQUIRY)_Inquiry;
+
+    __DumpPageStandard(&Inquiry->StandardPage);
+
+    __DumpPage(&Inquiry->Page00);
+
+    for (Entry = Inquiry->ListHead.Flink; Entry != &Inquiry->ListHead; Entry = Entry->Flink) {
+        PXENVBD_PAGE Page = CONTAINING_RECORD(Entry, XENVBD_PAGE, List);
+        __DumpPage(Page);
+    }
+}
+
+VOID
+PdoReadInquiryData(
+    IN  PXENVBD_FRONTEND        Frontend,
+    OUT PVOID*                  _Inquiry
+    )
+{
+    NTSTATUS        Status;
+
+    Status = __ReadInquiry(Frontend->BackendPath, _Inquiry);
+    if (!NT_SUCCESS(Status))
+        goto fail;
+
+    __DumpInquiry(*_Inquiry);
+    return;
+
+fail:
+    LogError("Fail (%08x)\n", Status);
+}
+
+VOID
+PdoFreeInquiryData(
+    IN  PVOID                   Inquiry
+    )
+{
+    __FreeInquiryData((PXENVBD_INQUIRY)Inquiry);
+}
+
+VOID
+PdoInquiry(
+    IN  PVOID                   Inquiry,
+    IN  PSCSI_REQUEST_BLOCK     Srb
+    )
+{
+    ULONG           Length;
+    PXENVBD_PAGE    Page;
+    const UCHAR     Evpd = Cdb_EVPD(Srb);
+    const UCHAR     PageCode = Cdb_PageCode(Srb);
+
+    if (Inquiry) {
+        Page = __FindPage((PXENVBD_INQUIRY)Inquiry, Evpd, PageCode);
+        if (Page) {
+            Length = Page->Length;
+            if (Srb->DataTransferLength < Length)
+                Length = Srb->DataTransferLength;
+            RtlCopyMemory(Srb->DataBuffer, Page->Data, Length);
+            Srb->DataTransferLength = Length;
+            Srb->SrbStatus = SRB_STATUS_SUCCESS;
+        }
+    } else {
+        __DefaultInquiry(Srb);
+    }
+}
+
diff --git a/src/xencrsh/pdoinquiry.h b/src/xencrsh/pdoinquiry.h
new file mode 100644 (file)
index 0000000..e87a882
--- /dev/null
@@ -0,0 +1,59 @@
+/* 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 <wdm.h>
+#include <xenvbd-storport.h>
+
+
+#include "frontend.h"
+
+extern VOID
+PdoReadInquiryData(
+    IN  PXENVBD_FRONTEND        Frontend,
+    OUT PVOID*                  _Inquiry
+    );
+
+extern VOID
+PdoFreeInquiryData(
+    IN  PVOID                   Inquiry
+    );
+
+extern VOID
+PdoInquiry(
+    IN  PVOID                   Inquiry,
+    IN  PSCSI_REQUEST_BLOCK     Srb
+    );
+
+#endif // _XENVBD_PDO_INQUIRY_H
+