ed48e10 MdeModulePkg/ScsiBusDxe: don't produce ScsiIo for nonexistent LUNs, part 2

Authored and Committed by lersek 6 years ago
    MdeModulePkg/ScsiBusDxe: don't produce ScsiIo for nonexistent LUNs, part 2
    
    The SPC-4 says about INQUIRY,
    
    > In response to an INQUIRY command received by an incorrect logical unit,
    > the SCSI target device shall return the INQUIRY data with the peripheral
    > qualifier set to the value defined in 6.4.2. The INQUIRY command shall
    > return CHECK CONDITION status only when the device server is unable to
    > return the requested INQUIRY data.
    
    When a device server takes the second branch, and returns CHECK CONDITION
    for a nonexistent LUN, the InquiryData structure in the
    DiscoverScsiDevice() function remains filled with the original zeros.
    
    DiscoverScsiDevice() then sees zero in both Peripheral_Qualifier and
    Peripheral_Type, and therefore ScsiBusDxe produces a ScsiIo protocol
    instance with device type zero, for the nonexistent LUN.
    
    Device type zero is EFI_SCSI_TYPE_DISK. Thus ScsiDiskDxe binds the bogus
    ScsiIo protocol interface, and produces a similarly bogus BlockIo
    interface on top. This ripples up to BDS, where UefiBootManagerLib can
    auto-generate bogus UEFI boot options for the nonexistent LUNs.
    
    This has been encountered with QEMU, after commit ded6ddc5a7b9 ("scsi:
    clarify sense codes for LUN0 emulation", 2017-08-04). QEMU now answers
    INQUIRY commands that were directed to nonexistent LUNs with:
    
    > DiscoverScsiDevice:1361: Lun=2 HostAdapterStatus=0 TargetStatus=2
    >                          SenseDataLength=18 InquiryDataLength=96
    > Sense {
    > Sense 000000 70 00 05 00 00 00 00 0A 00 00 00 00 25 00 00 00
    > Sense 000010 00 00
    > Sense }
    > Inquiry {
    > Inquiry 000000 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
    > Inquiry 000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
    > Inquiry 000020 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
    > Inquiry 000030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
    > Inquiry 000040 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
    > Inquiry 000050 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
    > Inquiry }
    
    The interesting fields are:
    - HostAdapterStatus=0 (OK),
    - TargetStatus=2 (CHECK CONDITION),
    - Sense/Error_Code=0x70 (Current error, Fixed description)
    - Sense/Sense_Key=0x05 (ILLEGAL REQUEST)
    
    According to SPC-4 "Table 41 -- Sense key descriptions (part 2 of 2)",
    ILLEGAL REQUEST is justified when "the command was addressed to an
    incorrect logical unit number".
    
    Thus, recognize this kind of answer for nonexistent LUNs.
    
    (
    
    Checking the status fields and the sense data is justified anyway,
    according to the documentation of ScsiInquiryCommand():
    
    >   @retval EFI_SUCCESS                    The command was executed
    >                                          successfully. See
    >                                          HostAdapterStatus,
    >                                          TargetStatus, SenseDataLength,
    >                                          and SenseData in that order for
    >                                          additional status information.
    
    )
    
    Cc: Eric Dong <eric.dong@intel.com>
    Cc: Feng Tian <feng.tian@intel.com>
    Cc: Hannes Reinecke <hare@suse.com>
    Cc: Paolo Bonzini <pbonzini@redhat.com>
    Cc: Star Zeng <star.zeng@intel.com>
    Contributed-under: TianoCore Contribution Agreement 1.1
    Signed-off-by: Laszlo Ersek <lersek@redhat.com>