public inbox for devel@edk2.groups.io
 help / color / mirror / Atom feed
From: Laszlo Ersek <lersek@redhat.com>
To: edk2-devel-01 <edk2-devel@lists.01.org>
Cc: Eric Dong <eric.dong@intel.com>, Feng Tian <feng.tian@intel.com>,
	Hannes Reinecke <hare@suse.com>,
	Paolo Bonzini <pbonzini@redhat.com>,
	Star Zeng <star.zeng@intel.com>
Subject: [PATCH 3/3] MdeModulePkg/ScsiBusDxe: don't produce ScsiIo for nonexistent LUNs, part 2
Date: Fri, 18 Aug 2017 05:37:57 +0200	[thread overview]
Message-ID: <20170818033757.16153-4-lersek@redhat.com> (raw)
In-Reply-To: <20170818033757.16153-1-lersek@redhat.com>

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>
---
 MdeModulePkg/Bus/Scsi/ScsiBusDxe/ScsiBus.c | 24 ++++++++++++++++++--
 1 file changed, 22 insertions(+), 2 deletions(-)

diff --git a/MdeModulePkg/Bus/Scsi/ScsiBusDxe/ScsiBus.c b/MdeModulePkg/Bus/Scsi/ScsiBusDxe/ScsiBus.c
index 1068770cd87f..21034aab19f7 100644
--- a/MdeModulePkg/Bus/Scsi/ScsiBusDxe/ScsiBus.c
+++ b/MdeModulePkg/Bus/Scsi/ScsiBusDxe/ScsiBus.c
@@ -1297,42 +1297,61 @@ DiscoverScsiDevice (
   UINT8                 SenseDataLength;
   UINT8                 HostAdapterStatus;
   UINT8                 TargetStatus;
   EFI_SCSI_INQUIRY_DATA *InquiryData;
+  EFI_SCSI_SENSE_DATA   *SenseData;
   UINT8                 MaxRetry;
   UINT8                 Index;
   BOOLEAN               ScsiDeviceFound;
 
   HostAdapterStatus = 0;
   TargetStatus      = 0;
+  SenseData         = NULL;
 
   InquiryData = AllocateAlignedBuffer (ScsiIoDevice, sizeof (EFI_SCSI_INQUIRY_DATA));
   if (InquiryData == NULL) {
     ScsiDeviceFound = FALSE;
     goto Done;
   }
 
+  SenseData = AllocateAlignedBuffer (
+                ScsiIoDevice,
+                sizeof (EFI_SCSI_SENSE_DATA)
+                );
+  if (SenseData == NULL) {
+    ScsiDeviceFound = FALSE;
+    goto Done;
+  }
+
   //
   // Using Inquiry command to scan for the device
   //
   InquiryDataLength = sizeof (EFI_SCSI_INQUIRY_DATA);
-  SenseDataLength   = 0;
+  SenseDataLength   = sizeof (EFI_SCSI_SENSE_DATA);
   ZeroMem (InquiryData, InquiryDataLength);
+  ZeroMem (SenseData, SenseDataLength);
 
   MaxRetry = 2;
   for (Index = 0; Index < MaxRetry; Index++) {
     Status = ScsiInquiryCommand (
               &ScsiIoDevice->ScsiIo,
               SCSI_BUS_TIMEOUT,
-              NULL,
+              SenseData,
               &SenseDataLength,
               &HostAdapterStatus,
               &TargetStatus,
               (VOID *) InquiryData,
               &InquiryDataLength,
               FALSE
               );
     if (!EFI_ERROR (Status)) {
+      if ((HostAdapterStatus == EFI_SCSI_IO_STATUS_HOST_ADAPTER_OK) &&
+          (TargetStatus == EFI_SCSI_IO_STATUS_TARGET_CHECK_CONDITION) &&
+          (SenseData->Error_Code == 0x70) &&
+          (SenseData->Sense_Key == EFI_SCSI_SK_ILLEGAL_REQUEST)) {
+        ScsiDeviceFound = FALSE;
+        goto Done;
+      }
       break;
     }
     if ((Status == EFI_BAD_BUFFER_SIZE) ||
         (Status == EFI_INVALID_PARAMETER) ||
@@ -1376,8 +1395,9 @@ DiscoverScsiDevice (
 
   ScsiDeviceFound = TRUE;
 
 Done:
+  FreeAlignedBuffer (SenseData, sizeof (EFI_SCSI_SENSE_DATA));
   FreeAlignedBuffer (InquiryData, sizeof (EFI_SCSI_INQUIRY_DATA));
 
   return ScsiDeviceFound;
 }
-- 
2.14.1.3.gb7cf6e02401b



  parent reply	other threads:[~2017-08-18  3:35 UTC|newest]

Thread overview: 6+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2017-08-18  3:37 [PATCH 0/3] MdeModulePkg/ScsiBusDxe: don't produce ScsiIo for nonexistent LUNs Laszlo Ersek
2017-08-18  3:37 ` [PATCH 1/3] MdeModulePkg/ScsiBusDxe: don't produce ScsiIo for nonexistent LUNs, part 1 Laszlo Ersek
2017-08-18  3:37 ` [PATCH 2/3] MdeModulePkg/ScsiBusDxe: remove redundant "else" after "break" statement Laszlo Ersek
2017-08-18  3:37 ` Laszlo Ersek [this message]
2017-08-18 14:20 ` [PATCH 0/3] MdeModulePkg/ScsiBusDxe: don't produce ScsiIo for nonexistent LUNs Zeng, Star
2017-08-18 22:41   ` Laszlo Ersek

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-list from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20170818033757.16153-4-lersek@redhat.com \
    --to=devel@edk2.groups.io \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox