]> git.proxmox.com Git - mirror_edk2.git/blobdiff - MdeModulePkg/Bus/Usb/UsbMassStorageDxe/UsbMassBoot.c
check the usage of %d,%x,%ld,%lx and so on in debug print statement.
[mirror_edk2.git] / MdeModulePkg / Bus / Usb / UsbMassStorageDxe / UsbMassBoot.c
index 980f8b289510854a88f826021d37efd7e98e87cb..589087accd9ed73141f1c54c4741ba4fa05f3740 100644 (file)
@@ -1,6 +1,9 @@
 /** @file\r
 \r
-Copyright (c) 2007, Intel Corporation\r
+  This file implement the command set of "USB Mass Storage Specification\r
+  for Bootability".\r
+\r
+Copyright (c) 2007 - 2008, Intel Corporation\r
 All rights reserved. This program and the accompanying materials\r
 are licensed and made available under the terms and conditions of the BSD License\r
 which accompanies this distribution.  The full text of the license may be found at\r
@@ -9,27 +12,34 @@ http://opensource.org/licenses/bsd-license.php
 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
 \r
-Module Name:\r
+**/\r
 \r
-  UsbMassBoot.c\r
+#include "UsbMassImpl.h"\r
 \r
-Abstract:\r
 \r
-  This file implement the command set of "USB Mass Storage Specification\r
-  for Bootability".\r
-\r
-Revision History\r
+/**\r
+  Return the current TPL.\r
 \r
+  @return Current TPL.\r
 \r
 **/\r
+EFI_TPL\r
+UsbGetCurrentTpl (\r
+  VOID\r
+  )\r
+{\r
+  EFI_TPL                 Tpl;\r
 \r
-#include "UsbMassImpl.h"\r
+  Tpl = gBS->RaiseTPL (TPL_HIGH_LEVEL);\r
+  gBS->RestoreTPL (Tpl);\r
 \r
+  return Tpl;\r
+}\r
 \r
 /**\r
   Read an UINT32 from the buffer to avoid byte alignment problems, then\r
   convert that to the little endia. The USB mass storage bootability spec\r
-  use big endia\r
+  use big endia.\r
 \r
   @param  Buf                    The buffer contains the first byte of the UINT32\r
                                  in big endia.\r
@@ -37,7 +47,6 @@ Revision History
   @return The UINT32 value read from the buffer in little endia.\r
 \r
 **/\r
-STATIC\r
 UINT32\r
 UsbBootGetUint32 (\r
   IN UINT8                  *Buf\r
@@ -54,13 +63,12 @@ UsbBootGetUint32 (
   Put an UINT32 in little endia to the buffer. The data is converted to\r
   big endia before writing.\r
 \r
-  @param  Buf                    The buffer to write data to\r
+  @param  Buf                    The buffer to write data to.\r
   @param  Data32                 The data to write.\r
 \r
-  @return None\r
+  @return None.\r
 \r
 **/\r
-STATIC\r
 VOID\r
 UsbBootPutUint32 (\r
   IN UINT8                  *Buf,\r
@@ -71,37 +79,38 @@ UsbBootPutUint32 (
   CopyMem (Buf, &Data32, sizeof (UINT32));\r
 }\r
 \r
-\r
 /**\r
   Put an UINT16 in little endia to the buffer. The data is converted to\r
   big endia before writing.\r
 \r
-  @param  Buf                    The buffer to write data to\r
-  @param  Data16                 The data to write\r
+  @param  Buf                    The buffer to write data to.\r
+  @param  Data16                 The data to write.\r
 \r
-  @return None\r
+  @return None.\r
 \r
 **/\r
-STATIC\r
 VOID\r
 UsbBootPutUint16 (\r
   IN UINT8                   *Buf,\r
   IN UINT16                  Data16\r
   )\r
 {\r
-  Data16 = USB_BOOT_SWAP16 (Data16);\r
+  Data16 = (UINT16) (USB_BOOT_SWAP16 (Data16));\r
   CopyMem (Buf, &Data16, sizeof (UINT16));\r
 }\r
 \r
-\r
 /**\r
   Request sense information via sending Request Sense\r
   Packet Command.\r
 \r
-  @param  UsbMass                The device to be requested sense data\r
+  @param  UsbMass                The device to be requested sense data.\r
 \r
-  @retval EFI_DEVICE_ERROR       Hardware error\r
-  @retval EFI_SUCCESS            Success\r
+  @retval EFI_SUCCESS            The command is excuted OK.\r
+  @retval EFI_DEVICE_ERROR       Failed to request sense.\r
+  @retval EFI_NO_RESPONSE        The device media doesn't response this request.\r
+  @retval EFI_INVALID_PARAMETER  The command has some invalid parameters.\r
+  @retval EFI_WRITE_PROTECTED    The device is write protected.\r
+  @retval EFI_MEDIA_CHANGED      The device media has been changed.\r
 \r
 **/\r
 EFI_STATUS\r
@@ -125,7 +134,7 @@ UsbBootRequestSense (
   ZeroMem (&SenseData, sizeof (USB_BOOT_REQUEST_SENSE_DATA));\r
 \r
   SenseCmd.OpCode   = USB_BOOT_REQUEST_SENSE_OPCODE;\r
-  SenseCmd.Lun      = USB_BOOT_LUN (UsbMass->Lun);\r
+  SenseCmd.Lun      = (UINT8) (USB_BOOT_LUN (UsbMass->Lun));\r
   SenseCmd.AllocLen = sizeof (USB_BOOT_REQUEST_SENSE_DATA);\r
 \r
   Status = Transport->ExecCommand (\r
@@ -135,12 +144,13 @@ UsbBootRequestSense (
                         EfiUsbDataIn,\r
                         &SenseData,\r
                         sizeof (USB_BOOT_REQUEST_SENSE_DATA),\r
+                        UsbMass->Lun,\r
                         USB_BOOT_GENERAL_CMD_TIMEOUT,\r
                         &CmdResult\r
                         );\r
   if (EFI_ERROR (Status) || CmdResult != USB_MASS_CMD_SUCCESS) {\r
-    DEBUG ((mUsbMscError, "UsbBootRequestSense: (%r) CmdResult=0x%x\n", Status, CmdResult));\r
-    return EFI_DEVICE_ERROR;\r
+    DEBUG ((EFI_D_ERROR, "UsbBootRequestSense: (%r) CmdResult=0x%x\n", Status, CmdResult));\r
+    return Status;\r
   }\r
 \r
   //\r
@@ -151,6 +161,9 @@ UsbBootRequestSense (
   switch (USB_BOOT_SENSE_KEY (SenseData.SenseKey)) {\r
 \r
   case USB_BOOT_SENSE_NO_SENSE:\r
+    Status = EFI_NO_RESPONSE;\r
+    break;\r
+\r
   case USB_BOOT_SENSE_RECOVERED:\r
     //\r
     // Suppose hardware can handle this case, and recover later by itself\r
@@ -159,26 +172,12 @@ UsbBootRequestSense (
     break;\r
 \r
   case USB_BOOT_SENSE_NOT_READY:\r
-    switch (SenseData.ASC) {\r
-    case USB_BOOT_ASC_NO_MEDIA:\r
-      Status              = EFI_NO_MEDIA;\r
-      Media->MediaPresent = FALSE;\r
-      break;\r
-\r
-    case USB_BOOT_ASC_MEDIA_UPSIDE_DOWN:\r
-      Status              = EFI_DEVICE_ERROR;\r
-      Media->MediaPresent = FALSE;\r
-      break;\r
-\r
-    case USB_BOOT_ASC_NOT_READY:\r
-      if (SenseData.ASCQ == USB_BOOT_ASCQ_IN_PROGRESS ||\r
-          SenseData.ASCQ == USB_BOOT_ASCQ_DEVICE_BUSY) {\r
-        //\r
-        // Regular timeout, and need retry once more\r
-        //\r
-        DEBUG ((mUsbMscInfo, "UsbBootRequestSense: Not ready and need retry once more\n"));\r
-        Status = EFI_NOT_READY;\r
-      }\r
+    Status = EFI_DEVICE_ERROR;\r
+    if (SenseData.ASC == USB_BOOT_ASC_NO_MEDIA) {\r
+          Media->MediaPresent = FALSE;\r
+          Status              = EFI_NO_MEDIA;\r
+    } else if (SenseData.ASC == USB_BOOT_ASC_NOT_READY) {\r
+      Status              = EFI_NOT_READY;\r
     }\r
     break;\r
 \r
@@ -189,14 +188,18 @@ UsbBootRequestSense (
   case USB_BOOT_SENSE_UNIT_ATTENTION:\r
     Status = EFI_DEVICE_ERROR;\r
     if (SenseData.ASC == USB_BOOT_ASC_MEDIA_CHANGE) {\r
-      Status = EFI_MEDIA_CHANGED;\r
-      UsbMass->BlockIoMedia.MediaId++;\r
+      //\r
+      // If MediaChange, reset ReadOnly and new MediId\r
+      //\r
+      Status          = EFI_MEDIA_CHANGED;\r
+      Media->ReadOnly = FALSE;\r
+      Media->MediaId++;\r
     }\r
     break;\r
 \r
   case USB_BOOT_SNESE_DATA_PROTECT:\r
-    Status                          = EFI_WRITE_PROTECTED;\r
-    UsbMass->BlockIoMedia.ReadOnly  = TRUE;\r
+    Status          = EFI_WRITE_PROTECTED;\r
+    Media->ReadOnly = TRUE;\r
     break;\r
 \r
   default:\r
@@ -204,7 +207,7 @@ UsbBootRequestSense (
     break;\r
   }\r
 \r
-  DEBUG ((mUsbMscInfo, "UsbBootRequestSense: (%r) with sense key %x/%x/%x\n",\r
+  DEBUG ((EFI_D_INFO, "UsbBootRequestSense: (%r) with sense key %x/%x/%x\n",\r
           Status,\r
           USB_BOOT_SENSE_KEY (SenseData.SenseKey),\r
           SenseData.ASC,\r
@@ -235,7 +238,6 @@ UsbBootRequestSense (
   @retval EFI_MEDIA_CHANGED      The device media has been changed\r
 \r
 **/\r
-STATIC\r
 EFI_STATUS\r
 UsbBootExecCmd (\r
   IN USB_MASS_DEVICE            *UsbMass,\r
@@ -259,6 +261,7 @@ UsbBootExecCmd (
                            DataDir,\r
                            Data,\r
                            DataLen,\r
+                           UsbMass->Lun,\r
                            Timeout,\r
                            &CmdResult\r
                            );\r
@@ -270,6 +273,9 @@ UsbBootExecCmd (
     return EFI_SUCCESS;\r
   }\r
 \r
+  DEBUG ((EFI_D_INFO, "UsbBootExecCmd: Fail to Exec 0x%x Cmd /w %r\n",\r
+          *(UINT8 *)Cmd ,Status));\r
+\r
   return UsbBootRequestSense (UsbMass);\r
 }\r
 \r
@@ -285,6 +291,7 @@ UsbBootExecCmd (
   @param  DataDir                The direction of data transfer\r
   @param  Data                   The buffer to hold the data\r
   @param  DataLen                The length of expected data\r
+  @param  Timeout                The timeout used to transfer\r
 \r
   @retval EFI_SUCCESS            The command is excuted OK\r
   @retval EFI_DEVICE_ERROR       Failed to request sense\r
@@ -293,7 +300,6 @@ UsbBootExecCmd (
   @retval EFI_MEDIA_CHANGED      The device media has been changed\r
 \r
 **/\r
-STATIC\r
 EFI_STATUS\r
 UsbBootExecCmdWithRetry (\r
   IN USB_MASS_DEVICE          *UsbMass,\r
@@ -325,7 +331,7 @@ UsbBootExecCmdWithRetry (
                DataDir,\r
                Data,\r
                DataLen,\r
-               Timeout * (Index + 1)\r
+               Timeout\r
                );\r
     if (Status == EFI_SUCCESS ||\r
         Status == EFI_MEDIA_CHANGED) {\r
@@ -343,7 +349,6 @@ UsbBootExecCmdWithRetry (
 }\r
 \r
 \r
-\r
 /**\r
   Use the TEST UNIT READY command to check whether it is ready.\r
   If it is ready, update the parameters.\r
@@ -364,7 +369,7 @@ UsbBootIsUnitReady (
   ZeroMem (&TestCmd, sizeof (USB_BOOT_TEST_UNIT_READY_CMD));\r
 \r
   TestCmd.OpCode  = USB_BOOT_TEST_UNIT_READY_OPCODE;\r
-  TestCmd.Lun     = USB_BOOT_LUN (UsbMass->Lun);\r
+  TestCmd.Lun     = (UINT8) (USB_BOOT_LUN (UsbMass->Lun));\r
 \r
   return UsbBootExecCmdWithRetry (\r
            UsbMass,\r
@@ -407,7 +412,7 @@ UsbBootInquiry (
   ZeroMem (&InquiryData, sizeof (USB_BOOT_INQUIRY_DATA));\r
 \r
   InquiryCmd.OpCode   = USB_BOOT_INQUIRY_OPCODE;\r
-  InquiryCmd.Lun      = USB_BOOT_LUN (UsbMass->Lun);\r
+  InquiryCmd.Lun      = (UINT8) (USB_BOOT_LUN (UsbMass->Lun));\r
   InquiryCmd.AllocLen = sizeof (InquiryData);\r
 \r
   Status = UsbBootExecCmdWithRetry (\r
@@ -417,14 +422,14 @@ UsbBootInquiry (
              EfiUsbDataIn,\r
              &InquiryData,\r
              sizeof (USB_BOOT_INQUIRY_DATA),\r
-             USB_BOOT_INQUIRY_CMD_TIMEOUT\r
+             USB_BOOT_GENERAL_CMD_TIMEOUT\r
              );\r
   if (EFI_ERROR (Status)) {\r
     return Status;\r
   }\r
 \r
-  UsbMass->Pdt          = USB_BOOT_PDT (InquiryData.Pdt);\r
-  Media->RemovableMedia = USB_BOOT_REMOVABLE (InquiryData.Removable);\r
+  UsbMass->Pdt          = (UINT8) (USB_BOOT_PDT (InquiryData.Pdt));\r
+  Media->RemovableMedia = (BOOLEAN) (USB_BOOT_REMOVABLE (InquiryData.Removable));\r
   //\r
   // Default value 512 Bytes, in case no media present at first time\r
   //\r
@@ -445,7 +450,8 @@ UsbBootInquiry (
 \r
   @retval EFI_SUCCESS            The disk gemotric is successfully retrieved.\r
   @retval EFI_DEVICE_ERROR       Something is inconsistent with the disk gemotric.\r
-\r
+  @retval Other                  Read capacity request fails.\r
\r
 **/\r
 EFI_STATUS\r
 UsbBootReadCapacity (\r
@@ -466,7 +472,7 @@ UsbBootReadCapacity (
   ZeroMem (&CapacityData, sizeof (USB_BOOT_READ_CAPACITY_DATA));\r
 \r
   CapacityCmd.OpCode = USB_BOOT_READ_CAPACITY_OPCODE;\r
-  CapacityCmd.Lun    = USB_BOOT_LUN (UsbMass->Lun);\r
+  CapacityCmd.Lun    = (UINT8) (USB_BOOT_LUN (UsbMass->Lun));\r
 \r
   Status = UsbBootExecCmdWithRetry (\r
              UsbMass,\r
@@ -485,65 +491,66 @@ UsbBootReadCapacity (
   Media->LastBlock    = UsbBootGetUint32 (CapacityData.LastLba);\r
   Media->BlockSize    = UsbBootGetUint32 (CapacityData.BlockLen);\r
 \r
-  DEBUG ((mUsbMscInfo, "UsbBootReadCapacity Success LBA=%d BlockSize=%d\n",\r
-    Media->LastBlock, Media->BlockSize));\r
+  if (Media->BlockSize == 0) {\r
+    return EFI_NOT_READY;\r
+  }\r
+\r
+  DEBUG ((EFI_D_INFO, "UsbBootReadCapacity Success LBA=%ld BlockSize=%d\n",\r
+          Media->LastBlock, Media->BlockSize));\r
 \r
   return EFI_SUCCESS;\r
 }\r
 \r
-\r
 /**\r
   Retrieves mode sense information via sending Mode Sense\r
   Packet Command.\r
 \r
   @param  UsbMass                The USB_FLOPPY_DEV instance.\r
 \r
-  @retval EFI_DEVICE_ERROR       Hardware error\r
   @retval EFI_SUCCESS            Success\r
+  @retval Other                  Execute Request command fails.\r
 \r
 **/\r
 EFI_STATUS\r
-UsbBootModeSense (\r
+UsbScsiModeSense (\r
   IN USB_MASS_DEVICE          *UsbMass\r
   )\r
 {\r
-  EFI_STATUS                Status;\r
-  USB_BOOT_MODE_SENSE_CMD   ModeSenseCmd;\r
-  USB_BOOT_MODE_PARA_HEADER ModeParaHeader;\r
-  UINT8                     CommandSet;\r
+  EFI_STATUS                       Status;\r
+  USB_SCSI_MODE_SENSE6_CMD         ModeSenseCmd;\r
+  USB_SCSI_MODE_SENSE6_PARA_HEADER ModeParaHeader;\r
+  EFI_BLOCK_IO_MEDIA               *Media;\r
 \r
-  ZeroMem (&ModeSenseCmd, sizeof (USB_BOOT_MODE_SENSE_CMD));\r
-  ZeroMem (&ModeParaHeader, sizeof (USB_BOOT_MODE_PARA_HEADER));\r
+  Media   = &UsbMass->BlockIoMedia;\r
+\r
+  ZeroMem (&ModeSenseCmd, sizeof (USB_SCSI_MODE_SENSE6_CMD));\r
+  ZeroMem (&ModeParaHeader, sizeof (USB_SCSI_MODE_SENSE6_PARA_HEADER));\r
 \r
   //\r
-  // overuse Context Pointer, the first field of Bot or Cbi is EFI_USB_INTERFACE_DESCRIPTOR\r
+  // ModeSense6 command is defined in [SCSI2Spec-Page151]\r
   //\r
-  CommandSet = ((EFI_USB_INTERFACE_DESCRIPTOR *) (UsbMass->Context))->InterfaceSubClass;\r
-\r
-  if (CommandSet == USB_MASS_STORE_SCSI) {\r
-    //\r
-    // Not UFI Command Set, no ModeSense Command\r
-    //\r
-    return EFI_SUCCESS;\r
-  }\r
-\r
-  ModeSenseCmd.OpCode         = USB_BOOT_MODE_SENSE10_OPCODE;\r
-  ModeSenseCmd.PageCode       = 0x3f;\r
-  ModeSenseCmd.ParaListLenLsb = (UINT8) sizeof (USB_BOOT_MODE_PARA_HEADER);\r
+  ModeSenseCmd.OpCode         = USB_SCSI_MODE_SENSE6_OPCODE;\r
+  ModeSenseCmd.Lun            = (UINT8) USB_BOOT_LUN (UsbMass->Lun);\r
+  ModeSenseCmd.PageCode       = 0x3F;\r
+  ModeSenseCmd.AllocateLen    = (UINT8) sizeof (USB_SCSI_MODE_SENSE6_PARA_HEADER);\r
 \r
   Status = UsbBootExecCmdWithRetry (\r
              UsbMass,\r
              &ModeSenseCmd,\r
-             sizeof (USB_BOOT_MODE_SENSE_CMD),\r
+             sizeof (USB_SCSI_MODE_SENSE6_CMD),\r
              EfiUsbDataIn,\r
              &ModeParaHeader,\r
-             sizeof (USB_BOOT_MODE_PARA_HEADER),\r
+             sizeof (USB_SCSI_MODE_SENSE6_PARA_HEADER),\r
              USB_BOOT_GENERAL_CMD_TIMEOUT\r
              );\r
+\r
   //\r
-  // Did nothing with the Header here\r
-  // But probably should\r
+  // ModeSense(6) is used to get the information of WriteProtected. While only some of\r
+  // devices support this command, so have a try here.\r
   //\r
+  if (!EFI_ERROR (Status)) {\r
+    Media->ReadOnly = (BOOLEAN) (((ModeParaHeader.DevicePara & 0x80) != 0) ? TRUE : FALSE);\r
+  }\r
 \r
   return Status;\r
 }\r
@@ -560,7 +567,7 @@ UsbBootModeSense (
   @param  UsbMass                The device to retireve disk gemotric.\r
 \r
   @retval EFI_SUCCESS            The disk gemotric is successfully retrieved.\r
-  @retval EFI_DEVICE_ERROR       Something is inconsistent with the disk gemotric.\r
+  @retval Other                  Get the parameters failed.\r
 \r
 **/\r
 EFI_STATUS\r
@@ -570,36 +577,41 @@ UsbBootGetParams (
 {\r
   EFI_BLOCK_IO_MEDIA          *Media;\r
   EFI_STATUS                  Status;\r
+  UINT8                       CmdSet;\r
+\r
+  Media  = &(UsbMass->BlockIoMedia);\r
+  CmdSet = ((EFI_USB_INTERFACE_DESCRIPTOR *) (UsbMass->Context))->InterfaceSubClass;\r
 \r
   Status = UsbBootInquiry (UsbMass);\r
   if (EFI_ERROR (Status)) {\r
-    DEBUG ((mUsbMscError, "UsbBootGetParams: UsbBootInquiry (%r)\n", Status));\r
+    DEBUG ((EFI_D_ERROR, "UsbBootGetParams: UsbBootInquiry (%r)\n", Status));\r
     return Status;\r
   }\r
 \r
-  Media = &(UsbMass->BlockIoMedia);\r
   //\r
   // Don't use the Removable bit in inquirydata to test whether the media\r
   // is removable because many flash disks wrongly set this bit.\r
   //\r
   if ((UsbMass->Pdt == USB_PDT_CDROM) || (UsbMass->Pdt == USB_PDT_OPTICAL)) {\r
     //\r
-    // CD-Rom or Optical device\r
+    // CD-Rom device and Non-CD optical device\r
     //\r
     UsbMass->OpticalStorage = TRUE;\r
     //\r
     // Default value 2048 Bytes, in case no media present at first time\r
     //\r
     Media->BlockSize        = 0x0800;\r
-  } else {\r
+  }\r
+\r
+  if ((UsbMass->Pdt != USB_PDT_CDROM) && (CmdSet == USB_MASS_STORE_SCSI)) {\r
     //\r
-    // Non CD-Rom device need ModeSenseCmd between InquiryCmd and ReadCapacityCmd\r
+    // ModeSense is required for the device with PDT of 0x00/0x07/0x0E,\r
+    // which is from [MassStorageBootabilitySpec-Page7].\r
+    // ModeSense(10) is useless here, while ModeSense(6) defined in SCSI\r
+    // could get the information of WriteProtected.\r
+    // Since not all device support this command, so skip if fail.\r
     //\r
-    Status = UsbBootModeSense (UsbMass);\r
-    if (EFI_ERROR (Status)) {\r
-      DEBUG ((mUsbMscError, "UsbBootGetParams: UsbBootModeSense (%r)\n", Status));\r
-      return Status;\r
-    }\r
+    UsbScsiModeSense (UsbMass);\r
   }\r
 \r
   return UsbBootReadCapacity (UsbMass);\r
@@ -613,7 +625,7 @@ UsbBootGetParams (
   @param  UsbMass                The device to retireve disk gemotric.\r
 \r
   @retval EFI_SUCCESS            The disk gemotric is successfully retrieved.\r
-  @retval EFI_DEVICE_ERROR       Something is inconsistent with the disk gemotric.\r
+  @retval Other                  Decect media fails.\r
 \r
 **/\r
 EFI_STATUS\r
@@ -623,59 +635,92 @@ UsbBootDetectMedia (
 {\r
   EFI_BLOCK_IO_MEDIA        OldMedia;\r
   EFI_BLOCK_IO_MEDIA        *Media;\r
+  UINT8                     CmdSet;\r
+  EFI_TPL                   OldTpl;\r
   EFI_STATUS                Status;\r
 \r
   Media    = &UsbMass->BlockIoMedia;\r
-  OldMedia = UsbMass->BlockIoMedia;\r
 \r
-  //\r
-  // First test whether the device is ready and get status\r
-  // If media changed or ready, need read the device's capacity\r
-  //\r
+  CopyMem (\r
+    &OldMedia,\r
+    &(UsbMass->BlockIoMedia),\r
+    sizeof (EFI_BLOCK_IO_MEDIA)\r
+    );\r
+\r
+  CmdSet = ((EFI_USB_INTERFACE_DESCRIPTOR *) (UsbMass->Context))->InterfaceSubClass;\r
+\r
   Status = UsbBootIsUnitReady (UsbMass);\r
-  if ((Status == EFI_SUCCESS && Media->MediaPresent) ||\r
-      (Status == EFI_MEDIA_CHANGED)) {\r
-    if ((UsbMass->Pdt != USB_PDT_CDROM) &&\r
-        (UsbMass->Pdt != USB_PDT_OPTICAL)) {\r
-      //\r
-      // Non CD-Rom device need ModeSenseCmd between InquiryCmd and ReadCapacityCmd\r
-      //\r
-      UsbBootModeSense (UsbMass);\r
-    }\r
-    DEBUG ((mUsbMscInfo, "UsbBootDetectMedia: Need Read Capacity\n"));\r
-    Status = UsbBootReadCapacity (UsbMass);\r
+  if (EFI_ERROR (Status)) {\r
+    DEBUG ((EFI_D_ERROR, "UsbBootDetectMedia: UsbBootIsUnitReady (%r)\n", Status));\r
+    goto ON_ERROR;\r
+  }\r
+\r
+  if ((UsbMass->Pdt != USB_PDT_CDROM) && (CmdSet == USB_MASS_STORE_SCSI)) {\r
+    //\r
+    // ModeSense is required for the device with PDT of 0x00/0x07/0x0E,\r
+    // which is from [MassStorageBootabilitySpec-Page7].\r
+    // ModeSense(10) is useless here, while ModeSense(6) defined in SCSI\r
+    // could get the information of WriteProtected.\r
+    // Since not all device support this command, so skip if fail.\r
+    //\r
+    UsbScsiModeSense (UsbMass);\r
   }\r
+\r
+  Status = UsbBootReadCapacity (UsbMass);\r
   if (EFI_ERROR (Status)) {\r
-    return Status;\r
+    DEBUG ((EFI_D_ERROR, "UsbBootDetectMedia: UsbBootReadCapacity (%r)\n", Status));\r
+    goto ON_ERROR;\r
   }\r
 \r
+  return EFI_SUCCESS;\r
+\r
+ON_ERROR:\r
   //\r
   // Detect whether it is necessary to reinstall the BlockIO\r
   //\r
+  // MediaId may change in RequestSense for MediaChanged\r
+  // MediaPresent may change in RequestSense for NoMedia\r
+  // MediaReadOnly may change in RequestSense for WriteProtected or MediaChanged\r
+  // MediaPresent/BlockSize/LastBlock may change in ReadCapacity\r
+  //\r
   if ((Media->MediaId != OldMedia.MediaId) ||\r
       (Media->MediaPresent != OldMedia.MediaPresent) ||\r
       (Media->ReadOnly != OldMedia.ReadOnly) ||\r
       (Media->BlockSize != OldMedia.BlockSize) ||\r
       (Media->LastBlock != OldMedia.LastBlock)) {\r
-    DEBUG ((mUsbMscInfo, "UsbBootDetectMedia: Need reinstall BlockIoProtocol\n"));\r
-    Media->MediaId++;\r
+\r
+    OldTpl = UsbGetCurrentTpl ();\r
+    DEBUG ((EFI_D_ERROR, "UsbBootDetectMedia: TPL before reinstall BlockIoProtocol is %d\n", (UINT32)OldTpl));\r
+\r
+    gBS->RestoreTPL (TPL_CALLBACK);\r
+\r
     gBS->ReinstallProtocolInterface (\r
            UsbMass->Controller,\r
            &gEfiBlockIoProtocolGuid,\r
            &UsbMass->BlockIo,\r
            &UsbMass->BlockIo\r
            );\r
+\r
+    DEBUG ((EFI_D_ERROR, "UsbBootDetectMedia: TPL after reinstall is %d\n", (UINT32)UsbGetCurrentTpl()));\r
+    ASSERT (UsbGetCurrentTpl () == TPL_CALLBACK);\r
+\r
+    gBS->RaiseTPL (OldTpl);\r
+\r
     //\r
-    // Check whether media present or media changed or write protected\r
+    // Update MediaId after reinstall BLOCK_IO_PROTOCOL\r
     //\r
-    if (Media->MediaPresent == FALSE) {\r
-      Status = EFI_NO_MEDIA;\r
-    }\r
-    if (Media->MediaId != OldMedia.MediaId) {\r
-      Status = EFI_MEDIA_CHANGED;\r
+    if (Media->MediaPresent != OldMedia.MediaPresent) {\r
+      if (Media->MediaPresent == TRUE) {\r
+        Media->MediaId = 1;\r
+      } else {\r
+        Media->MediaId = 0;\r
+      }\r
     }\r
-    if (Media->ReadOnly != OldMedia.ReadOnly) {\r
-      Status = EFI_WRITE_PROTECTED;\r
+\r
+    if ((Media->ReadOnly != OldMedia.ReadOnly) ||\r
+        (Media->BlockSize != OldMedia.BlockSize) ||\r
+        (Media->LastBlock != OldMedia.LastBlock)) {\r
+      Media->MediaId++;\r
     }\r
   }\r
 \r
@@ -723,13 +768,9 @@ UsbBootReadBlocks (
     ByteSize  = (UINT32)Count * BlockSize;\r
 \r
     //\r
-    // Optical device need longer timeout than other device\r
+    // USB command's upper limit timeout is 5s. [USB2.0-9.2.6.1]\r
     //\r
-    if (UsbMass->OpticalStorage == TRUE) {\r
-      Timeout = (UINT32)Count * USB_BOOT_OPTICAL_BLOCK_TIMEOUT;\r
-    } else {\r
-      Timeout = (UINT32)Count * USB_BOOT_GENERAL_BLOCK_TIMEOUT;\r
-    }\r
+    Timeout = (UINT32) USB_BOOT_GENERAL_CMD_TIMEOUT;\r
 \r
     //\r
     // Fill in the command then execute\r
@@ -737,7 +778,7 @@ UsbBootReadBlocks (
     ZeroMem (&ReadCmd, sizeof (USB_BOOT_READ10_CMD));\r
 \r
     ReadCmd.OpCode  = USB_BOOT_READ10_OPCODE;\r
-    ReadCmd.Lun     = USB_BOOT_LUN (UsbMass->Lun);\r
+    ReadCmd.Lun     = (UINT8) (USB_BOOT_LUN (UsbMass->Lun));\r
     UsbBootPutUint32 (ReadCmd.Lba, Lba);\r
     UsbBootPutUint16 (ReadCmd.TransferLen, Count);\r
 \r
@@ -803,13 +844,9 @@ UsbBootWriteBlocks (
     ByteSize  = (UINT32)Count * BlockSize;\r
 \r
     //\r
-    // Optical device need longer timeout than other device\r
+    // USB command's upper limit timeout is 5s. [USB2.0-9.2.6.1]\r
     //\r
-    if (UsbMass->OpticalStorage == TRUE) {\r
-      Timeout = (UINT32)Count * USB_BOOT_OPTICAL_BLOCK_TIMEOUT;\r
-    } else {\r
-      Timeout = (UINT32)Count * USB_BOOT_GENERAL_BLOCK_TIMEOUT;\r
-    }\r
+    Timeout = (UINT32) USB_BOOT_GENERAL_CMD_TIMEOUT;\r
 \r
     //\r
     // Fill in the write10 command block\r
@@ -817,7 +854,7 @@ UsbBootWriteBlocks (
     ZeroMem (&WriteCmd, sizeof (USB_BOOT_WRITE10_CMD));\r
 \r
     WriteCmd.OpCode = USB_BOOT_WRITE10_OPCODE;\r
-    WriteCmd.Lun    = USB_BOOT_LUN (UsbMass->Lun);\r
+    WriteCmd.Lun    = (UINT8) (USB_BOOT_LUN (UsbMass->Lun));\r
     UsbBootPutUint32 (WriteCmd.Lba, Lba);\r
     UsbBootPutUint16 (WriteCmd.TransferLen, Count);\r
 \r
@@ -870,7 +907,7 @@ UsbClearEndpointStall (
   Request.Value       = USB_FEATURE_ENDPOINT_HALT;\r
   Request.Index       = EndpointAddr;\r
   Request.Length      = 0;\r
-  Timeout             = USB_BOOT_GENERAL_CMD_TIMEOUT / USB_MASS_STALL_1_MS;\r
+  Timeout             = USB_BOOT_GENERAL_CMD_TIMEOUT / USB_MASS_1_MILLISECOND;\r
 \r
   Status = UsbIo->UsbControlTransfer (\r
                     UsbIo,\r