On 05/04/16 13:11, Laszlo Ersek wrote:
> On 05/04/16 02:58, Tian, Feng wrote:
>> Laszlo, 
>>
>> Could you explain more? 
>>
>> Usb Flash drive is managed by UsbMassStorage driver, which is irrelevant 
>> with UefiScsiLib lib or ScsiDisk driver.
> 
> Yeah, sorry about missing that part of the context.
> 
> So, the environment is the following:
> 
> - The USB flash drive with VendorId/ProductId 0x1516/0x6221 is plugged
> into a Linux host.
> 
> - The usb-storage driver in Linux presents the USB flash drive to the
> rest of the system as a SCSI disk. The device node that is generated for
> it looks like /dev/sd*, for example, /dev/sdi.
> 
> - This device node can be used like any other SCSI device.
> 
> - Using the virtio-scsi HBA, QEMU can provide a virtual machine with
> various types of virtual SCSI devices. One of those is "scsi-block",
> which is also known as "SCSI passthrough". It means that most of the
> SCSI commands are forwarded transparently from guest device to physical
> host device (/dev/sdi, for example), using the SG_IO ioctl() call. Only
> a few SCSI commands are captured and emulated by QEMU.
> 
> This feature is useful e.g. for burning physical optical media, or
> writing physical tapes, from a virtual machine.
> 
> - In this scenario, the USB stick that is plugged in the host is exposed
> to the guest with this feature. So, when the ScsiDiskInquiryDevice()
> function runs in the guest (as part of OVMF), the INQUIRY command
> (asking for the Supported VPD Pages" VPD page) is forwarded to the USB
> stick on the host. And that device returns garbage.
> 
> - It is important to note that the "garbage" is not inserted by either
> the host kernel's usb-storage driver, or by QEMU. Even without
> virtualization, the host kernel consciously avoids asking SCSI disks
> that are actually backed by USB mass-storage devices for VPD pages,
> because the kernel developers have realized that most (if not all) of
> USB mass-storage devices fail to respond correctly. Please see this host
> kernel commit:
> 
> http://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/?id=09b6b51b0b6c
> 
> - In <https://bugzilla.redhat.com/show_bug.cgi?id=1330955#c14>, I
> demonstrate what happens when such an INQUIRY is sent manually to the
> SCSI disk that is backed by the USB flash drive. For a genuine SCSI
> disk, the command completes:
> 
> # sg_vpd -v /dev/sda
> Supported VPD pages VPD page:
>     inquiry cdb: 12 01 00 00 fc 00
>    [PQual=0  Peripheral device type: disk]
>   Supported VPD pages [sv]
>   Unit serial number [sn]
>   Device identification [di]
>   ATA information (SAT) [ai]
>   Block limits (SBC) [bl]
>   Block device characteristics (SBC) [bdc]
>   Logical block provisioning (SBC) [lbpv]
> 
> Buth the USB flash drive responds with garbage:
> 
> # sg_vpd -v /dev/sdi
> Supported VPD pages VPD page:
>     inquiry cdb: 12 01 00 00 fc 00
> invalid VPD response; probably a STANDARD INQUIRY response
> First 32 bytes of bad response
>  00   00 80 06 02 1f 00 00 00  00 00 00 00 00 00 00 00  ................
>  10   00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  ................
> fetching VPD page failed
> 
> - So this patch is motivated by the case when a USB mass-storage device
> is presented as a SCSI disk, directly on the (virtual) hardware level,
> and it provides a bogus 0x00 VPD page.

I'm no longer certain that edk2's ScsiDiskDxe is the right place to fix
this problem. It seems that the usb-storage driver in Linux could be the
culprit -- it should be watching for INQUIRY commands with EVPD set, and
reject them before forwarding them to the device. That is the method
that complies with both SPC-4 and the UFI command spec. (And, edk2
handles this case correctly, already.) Please see
<https://bugzilla.redhat.com/show_bug.cgi?id=1330955#c17>.

So, for the time being, I'm withdrawing this patch.

Thanks!
Laszlo

> Thanks
> Laszlo
> 
>> Thanks
>> Feng
>>
>> -----Original Message-----
>> From: edk2-devel [mailto:edk2-devel-boun...@lists.01.org] On Behalf Of 
>> Laszlo Ersek
>> Sent: Wednesday, May 4, 2016 12:30 AM
>> To: edk2-devel-01 <edk2-de...@ml01.01.org>
>> Cc: Ni, Ruiyu <ruiyu...@intel.com>; Paolo Bonzini <pbonz...@redhat.com>; 
>> Tian, Feng <feng.t...@intel.com>; Zeng, Star <star.z...@intel.com>
>> Subject: [edk2] [PATCH] MdeModulePkg: ScsiDiskDxe: cope with broken 
>> "Supported VPD Pages" VPD page
>>
>> The USB flash drive with Vendor ID 0x1516 (CompUSA) and Product ID 0x6221 
>> returns a broken "Supported VPD Pages" VPD page. In particular, the 
>> PageLength field has the invalid value 0x0602 (decimal 1538).
>>
>> This prevents the loop from terminating that scans for the Block Limits VPD 
>> page code in ScsiDiskInquiryDevice():
>>
>>         for (Index = 0; Index < PageLength; Index++) {
>>
>> because the Index variable has type UINT8, and it wraps from 255 to 0, 
>> without ever reaching PageLength (1538), and because 
>> EFI_SCSI_PAGE_CODE_BLOCK_LIMITS_VPD does not occur at offsets 0 through 255.
>>
>> * The fix is not to change the type of Index to UINT16 or a wider type.
>>   Namely, section
>>
>>     7.8.14 Supported VPD Pages VPD page
>>
>>   in the "SCSI Primary Commands - 4" (SPC-4) specification names the
>>   following requirement:
>>
>>     The supported VPD page list shall contain a list of all VPD page codes
>>     (see 7.8) implemented by the logical unit in ascending order beginning
>>     with page code 00h.
>>
>>   Since page codes are 8-bit unsigned quantities, it follows that the
>>   maximum size for the Supported VPD Pages VPD page is 0x100 bytes, in
>>   which every possible page code (0x00 through 0xFF) will be found, before
>>   the UINT8 offset wraps around.
>>
>>   (EFI_SCSI_SUPPORTED_VPD_PAGES_VPD_PAGE.SupportedVpdPageList is correctly
>>   sized as well, in "MdePkg/Include/IndustryStandard/Scsi.h".)
>>
>> * Instead, add sanity checks that enforce the above requirement. If the
>>   device breaks the spec, simply fall back to the "Block Limits page
>>   absent" case.
>>
>> Cc: Feng Tian <feng.t...@intel.com>
>> Cc: Paolo Bonzini <pbonz...@redhat.com>
>> Cc: Ruiyu Ni <ruiyu...@intel.com>
>> Cc: Star Zeng <star.z...@intel.com>
>> Ref: https://bugzilla.redhat.com/show_bug.cgi?id=1330955
>> Contributed-under: TianoCore Contribution Agreement 1.0
>> Signed-off-by: Laszlo Ersek <ler...@redhat.com>
>> ---
>>  MdeModulePkg/Bus/Scsi/ScsiDiskDxe/ScsiDisk.c | 37 ++++++++++++++++++++
>>  1 file changed, 37 insertions(+)
>>
>> diff --git a/MdeModulePkg/Bus/Scsi/ScsiDiskDxe/ScsiDisk.c 
>> b/MdeModulePkg/Bus/Scsi/ScsiDiskDxe/ScsiDisk.c
>> index dfa5fa32e635..1b75d55231a6 100644
>> --- a/MdeModulePkg/Bus/Scsi/ScsiDiskDxe/ScsiDisk.c
>> +++ b/MdeModulePkg/Bus/Scsi/ScsiDiskDxe/ScsiDisk.c
>> @@ -1493,7 +1493,44 @@ ScsiDiskInquiryDevice (
>>        if (!EFI_ERROR (Status)) {
>>          PageLength = (SupportedVpdPages->PageLength2 << 8)
>>                     |  SupportedVpdPages->PageLength1;
>> +
>> +        //
>> +        // Sanity checks for coping with broken devices
>> +        //
>> +        if (PageLength > sizeof SupportedVpdPages->SupportedVpdPageList) {
>> +          DEBUG ((EFI_D_WARN,
>> +            "%a: invalid PageLength (%u) in Supported VPD Pages page\n",
>> +            __FUNCTION__, (UINT32)PageLength));
>> +          PageLength = 0;
>> +        }
>> +
>> +        if ((PageLength > 0) &&
>> +            (SupportedVpdPages->SupportedVpdPageList[0] !=
>> +             EFI_SCSI_PAGE_CODE_SUPPORTED_VPD)) {
>> +          DEBUG ((EFI_D_WARN,
>> +            "%a: Supported VPD Pages page doesn't start with code 0x%02x\n",
>> +            __FUNCTION__, EFI_SCSI_PAGE_CODE_SUPPORTED_VPD));
>> +          PageLength = 0;
>> +        }
>> +
>> +        //
>> +        // Locate the code for the Block Limits VPD page
>> +        //
>>          for (Index = 0; Index < PageLength; Index++) {
>> +          //
>> +          // Sanity check
>> +          //
>> +          if ((Index > 0) &&
>> +              (SupportedVpdPages->SupportedVpdPageList[Index] <=
>> +               SupportedVpdPages->SupportedVpdPageList[Index - 1])) {
>> +            DEBUG ((EFI_D_WARN,
>> +              "%a: non-ascending code in Supported VPD Pages page @ %u\n",
>> +              __FUNCTION__, Index));
>> +            Index = 0;
>> +            PageLength = 0;
>> +            break;
>> +          }
>> +
>>            if (SupportedVpdPages->SupportedVpdPageList[Index] == 
>> EFI_SCSI_PAGE_CODE_BLOCK_LIMITS_VPD) {
>>              break;
>>            }
>> --
>> 1.8.3.1
>>
>> _______________________________________________
>> edk2-devel mailing list
>> edk2-devel@lists.01.org
>> https://lists.01.org/mailman/listinfo/edk2-devel
>>
> 
> _______________________________________________
> edk2-devel mailing list
> edk2-devel@lists.01.org
> https://lists.01.org/mailman/listinfo/edk2-devel
> 

_______________________________________________
edk2-devel mailing list
edk2-devel@lists.01.org
https://lists.01.org/mailman/listinfo/edk2-devel

Reply via email to