]> git.proxmox.com Git - mirror_edk2.git/blobdiff - MdeModulePkg/Bus/Usb/UsbMassStorageDxe/UsbMassImpl.c
MdeModulePkg/UsbBusDxe: Add UsbControlTransfer() error check
[mirror_edk2.git] / MdeModulePkg / Bus / Usb / UsbMassStorageDxe / UsbMassImpl.c
index f80895bda4567afb58c29f65bf1297377383c1d6..9d1bb25fb39d630b73ae4bd9a7c0e8f1e53ed2e6 100644 (file)
@@ -1,8 +1,8 @@
 /** @file\r
   USB Mass Storage Driver that manages USB Mass Storage Device and produces Block I/O Protocol.\r
 \r
-Copyright (c) 2007 - 2008, Intel Corporation\r
-All rights reserved. This program and the accompanying materials\r
+Copyright (c) 2007 - 2015, Intel Corporation. All rights reserved.<BR>\r
+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
 http://opensource.org/licenses/bsd-license.php\r
@@ -12,7 +12,7 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 \r
 **/\r
 \r
-#include "UsbMassImpl.h"\r
+#include "UsbMass.h"\r
 \r
 #define USB_MASS_TRANSPORT_COUNT    3\r
 //\r
@@ -63,7 +63,7 @@ UsbMassReset (
   // Raise TPL to TPL_NOTIFY to serialize all its operations\r
   // to protect shared data structures.\r
   //\r
-  OldTpl  = gBS->RaiseTPL (TPL_NOTIFY);\r
+  OldTpl  = gBS->RaiseTPL (TPL_CALLBACK);\r
 \r
   UsbMass = USB_MASS_DEVICE_FROM_BLOCK_IO (This);\r
   Status  = UsbMass->Transport->Reset (UsbMass->Context, ExtendedVerification);\r
@@ -113,18 +113,11 @@ UsbMassReadBlocks (
   EFI_TPL             OldTpl;\r
   UINTN               TotalBlock;\r
 \r
-  //\r
-  // First, validate the parameters\r
-  //\r
-  if ((Buffer == NULL) || (BufferSize == 0)) {\r
-    return EFI_INVALID_PARAMETER;\r
-  }\r
-\r
   //\r
   // Raise TPL to TPL_NOTIFY to serialize all its operations\r
   // to protect shared data structures.\r
   //\r
-  OldTpl  = gBS->RaiseTPL (TPL_NOTIFY);\r
+  OldTpl  = gBS->RaiseTPL (TPL_CALLBACK);\r
   UsbMass = USB_MASS_DEVICE_FROM_BLOCK_IO (This);\r
   Media   = &UsbMass->BlockIoMedia;\r
 \r
@@ -140,6 +133,26 @@ UsbMassReadBlocks (
     }\r
   }\r
 \r
+  if (!(Media->MediaPresent)) {\r
+    Status = EFI_NO_MEDIA;\r
+    goto ON_EXIT;\r
+  }\r
+\r
+  if (MediaId != Media->MediaId) {\r
+    Status = EFI_MEDIA_CHANGED;\r
+    goto ON_EXIT;\r
+  }\r
+\r
+  if (BufferSize == 0) {\r
+    Status = EFI_SUCCESS;\r
+    goto ON_EXIT;\r
+  }\r
+\r
+  if (Buffer == NULL) {\r
+    Status = EFI_INVALID_PARAMETER;\r
+    goto ON_EXIT;\r
+  }\r
+\r
   //\r
   // BufferSize must be a multiple of the intrinsic block size of the device.\r
   //\r
@@ -158,17 +171,12 @@ UsbMassReadBlocks (
     goto ON_EXIT;\r
   }\r
 \r
-  if (!(Media->MediaPresent)) {\r
-    Status = EFI_NO_MEDIA;\r
-    goto ON_EXIT;\r
-  }\r
-\r
-  if (MediaId != Media->MediaId) {\r
-    Status = EFI_MEDIA_CHANGED;\r
-    goto ON_EXIT;\r
+  if (UsbMass->Cdb16Byte) {\r
+    Status = UsbBootReadBlocks16 (UsbMass, Lba, TotalBlock, Buffer);\r
+  } else {\r
+    Status = UsbBootReadBlocks (UsbMass, (UINT32) Lba, TotalBlock, Buffer);\r
   }\r
 \r
-  Status = UsbBootReadBlocks (UsbMass, (UINT32) Lba, TotalBlock, Buffer);\r
   if (EFI_ERROR (Status)) {\r
     DEBUG ((EFI_D_ERROR, "UsbMassReadBlocks: UsbBootReadBlocks (%r) -> Reset\n", Status));\r
     UsbMassReset (This, TRUE);\r
@@ -221,18 +229,11 @@ UsbMassWriteBlocks (
   EFI_TPL             OldTpl;\r
   UINTN               TotalBlock;\r
 \r
-  //\r
-  // First, validate the parameters\r
-  //\r
-  if ((Buffer == NULL) || (BufferSize == 0)) {\r
-    return EFI_INVALID_PARAMETER;\r
-  }\r
-\r
   //\r
   // Raise TPL to TPL_NOTIFY to serialize all its operations\r
   // to protect shared data structures.\r
   //\r
-  OldTpl  = gBS->RaiseTPL (TPL_NOTIFY);\r
+  OldTpl  = gBS->RaiseTPL (TPL_CALLBACK);\r
   UsbMass = USB_MASS_DEVICE_FROM_BLOCK_IO (This);\r
   Media   = &UsbMass->BlockIoMedia;\r
 \r
@@ -248,6 +249,26 @@ UsbMassWriteBlocks (
     }\r
   }\r
 \r
+  if (!(Media->MediaPresent)) {\r
+    Status = EFI_NO_MEDIA;\r
+    goto ON_EXIT;\r
+  }\r
+\r
+  if (MediaId != Media->MediaId) {\r
+    Status = EFI_MEDIA_CHANGED;\r
+    goto ON_EXIT;\r
+  }\r
+\r
+  if (BufferSize == 0) {\r
+    Status = EFI_SUCCESS;\r
+    goto ON_EXIT;\r
+  }\r
+\r
+  if (Buffer == NULL) {\r
+    Status = EFI_INVALID_PARAMETER;\r
+    goto ON_EXIT;\r
+  }\r
+\r
   //\r
   // BufferSize must be a multiple of the intrinsic block size of the device.\r
   //\r
@@ -266,21 +287,16 @@ UsbMassWriteBlocks (
     goto ON_EXIT;\r
   }\r
 \r
-  if (!(Media->MediaPresent)) {\r
-    Status = EFI_NO_MEDIA;\r
-    goto ON_EXIT;\r
-  }\r
-\r
-  if (MediaId != Media->MediaId) {\r
-    Status = EFI_MEDIA_CHANGED;\r
-    goto ON_EXIT;\r
-  }\r
-\r
   //\r
   // Try to write the data even the device is marked as ReadOnly,\r
   // and clear the status should the write succeed.\r
   //\r
-  Status = UsbBootWriteBlocks (UsbMass, (UINT32) Lba, TotalBlock, Buffer);\r
+  if (UsbMass->Cdb16Byte) {\r
+    Status = UsbBootWriteBlocks16 (UsbMass, Lba, TotalBlock, Buffer);\r
+  } else {\r
+    Status = UsbBootWriteBlocks (UsbMass, (UINT32) Lba, TotalBlock, Buffer);\r
+  }  \r
+\r
   if (EFI_ERROR (Status)) {\r
     DEBUG ((EFI_D_ERROR, "UsbMassWriteBlocks: UsbBootWriteBlocks (%r) -> Reset\n", Status));\r
     UsbMassReset (This, TRUE);\r
@@ -330,7 +346,6 @@ UsbMassInitMedia (
 {\r
   EFI_BLOCK_IO_MEDIA          *Media;\r
   EFI_STATUS                  Status;\r
-  UINTN                       Index;\r
 \r
   Media = &UsbMass->BlockIoMedia;\r
 \r
@@ -345,25 +360,7 @@ UsbMassInitMedia (
   Media->IoAlign          = 0;\r
   Media->MediaId          = 1;\r
 \r
-  //\r
-  // Some device may spend several seconds before it is ready.\r
-  // Try several times before giving up. Wait 5s at most.\r
-  //\r
-  Status = EFI_SUCCESS;\r
-\r
-  for (Index = 0; Index < USB_BOOT_INIT_MEDIA_RETRY; Index++) {\r
-\r
-    Status = UsbBootGetParams (UsbMass);\r
-    if ((Status != EFI_MEDIA_CHANGED) && (Status != EFI_NOT_READY) && (Status != EFI_TIMEOUT)) {\r
-      break;\r
-    }\r
-\r
-    Status = UsbBootIsUnitReady (UsbMass);\r
-    if (EFI_ERROR (Status)) {\r
-      gBS->Stall (USB_BOOT_RETRY_UNIT_READY_STALL * (Index + 1));\r
-    }\r
-  }\r
-\r
+  Status = UsbBootGetParams (UsbMass);\r
   return Status;\r
 }\r
 \r
@@ -467,8 +464,7 @@ ON_EXIT:
   @param  MaxLun               The max LUN number.\r
 \r
   @retval EFI_SUCCESS          At least one LUN is initialized successfully.\r
-  @retval EFI_OUT_OF_RESOURCES Out of resource while creating device path node.\r
-  @retval Other                Initialization fails.\r
+  @retval EFI_NOT_FOUND        Fail to initialize any of multiple LUNs.\r
 \r
 **/\r
 EFI_STATUS\r
@@ -486,8 +482,10 @@ UsbMassInitMultiLun (
   DEVICE_LOGICAL_UNIT_DEVICE_PATH  LunNode;\r
   UINT8                            Index;\r
   EFI_STATUS                       Status;\r
+  EFI_STATUS                       ReturnStatus;\r
 \r
   ASSERT (MaxLun > 0);\r
+  ReturnStatus = EFI_NOT_FOUND;\r
 \r
   for (Index = 0; Index <= MaxLun; Index++) { \r
 \r
@@ -513,21 +511,10 @@ UsbMassInitMultiLun (
     // Initialize the media parameter data for EFI_BLOCK_IO_MEDIA of Block I/O Protocol.\r
     //\r
     Status = UsbMassInitMedia (UsbMass);\r
-    if (!EFI_ERROR (Status)) {\r
-      //\r
-      // According to USB Mass Storage Specification for Bootability, only following\r
-      // 4 Peripheral Device Types are in spec.\r
-      //\r
-      if ((UsbMass->Pdt != USB_PDT_DIRECT_ACCESS) && \r
-           (UsbMass->Pdt != USB_PDT_CDROM) &&\r
-           (UsbMass->Pdt != USB_PDT_OPTICAL) && \r
-           (UsbMass->Pdt != USB_PDT_SIMPLE_DIRECT)) {\r
-        DEBUG ((EFI_D_ERROR, "UsbMassInitMultiLun: Found an unsupported peripheral type[%d]\n", UsbMass->Pdt));\r
-        goto ON_ERROR;\r
-      }\r
-    } else if (Status != EFI_NO_MEDIA){\r
+    if ((EFI_ERROR (Status)) && (Status != EFI_NO_MEDIA)) {\r
       DEBUG ((EFI_D_ERROR, "UsbMassInitMultiLun: UsbMassInitMedia (%r)\n", Status));\r
-      goto ON_ERROR;\r
+      FreePool (UsbMass);\r
+      continue;\r
     }\r
 \r
     //\r
@@ -543,11 +530,13 @@ UsbMassInitMultiLun (
   \r
     if (UsbMass->DevicePath == NULL) {\r
       DEBUG ((EFI_D_ERROR, "UsbMassInitMultiLun: failed to create device logic unit device path\n"));\r
-  \r
       Status = EFI_OUT_OF_RESOURCES;\r
-      goto ON_ERROR;\r
+      FreePool (UsbMass);\r
+      continue;\r
     }\r
 \r
+    InitializeDiskInfo (UsbMass);\r
+\r
     //\r
     // Create a new handle for each LUN, and install Block I/O Protocol and Device Path Protocol.\r
     //\r
@@ -557,12 +546,16 @@ UsbMassInitMultiLun (
                     UsbMass->DevicePath,\r
                     &gEfiBlockIoProtocolGuid,\r
                     &UsbMass->BlockIo,\r
+                    &gEfiDiskInfoProtocolGuid,\r
+                    &UsbMass->DiskInfo,\r
                     NULL\r
                     );\r
     \r
     if (EFI_ERROR (Status)) {\r
       DEBUG ((EFI_D_ERROR, "UsbMassInitMultiLun: InstallMultipleProtocolInterfaces (%r)\n", Status));\r
-      goto ON_ERROR;\r
+      FreePool (UsbMass->DevicePath);\r
+      FreePool (UsbMass);\r
+      continue;\r
     }\r
 \r
     //\r
@@ -585,40 +578,19 @@ UsbMassInitMultiLun (
              UsbMass->DevicePath,\r
              &gEfiBlockIoProtocolGuid,\r
              &UsbMass->BlockIo,\r
+             &gEfiDiskInfoProtocolGuid,\r
+             &UsbMass->DiskInfo,\r
              NULL\r
              );\r
-      goto ON_ERROR;\r
+      FreePool (UsbMass->DevicePath);\r
+      FreePool (UsbMass);\r
+      continue;\r
     }\r
-    \r
+    ReturnStatus = EFI_SUCCESS;\r
     DEBUG ((EFI_D_INFO, "UsbMassInitMultiLun: Success to initialize No.%d logic unit\n", Index));\r
   }\r
   \r
-  return EFI_SUCCESS;\r
-\r
-ON_ERROR:\r
-  if (UsbMass != NULL) {\r
-    if (UsbMass->DevicePath != NULL) {\r
-      FreePool (UsbMass->DevicePath);\r
-    }\r
-    FreePool (UsbMass);\r
-  }\r
-  if (UsbIo != NULL) {\r
-    gBS->CloseProtocol (\r
-           Controller,\r
-           &gEfiUsbIoProtocolGuid,\r
-           This->DriverBindingHandle,\r
-           UsbMass->Controller\r
-           );\r
-  }\r
-\r
-  //\r
-  // Return EFI_SUCCESS if at least one LUN is initialized successfully.\r
-  //\r
-  if (Index > 0) {\r
-    return EFI_SUCCESS; \r
-  } else {\r
-    return Status;\r
-  } \r
+  return ReturnStatus;\r
 }\r
 \r
 /**\r
@@ -679,28 +651,20 @@ UsbMassInitNonLun (
   // Initialize the media parameter data for EFI_BLOCK_IO_MEDIA of Block I/O Protocol.\r
   //\r
   Status = UsbMassInitMedia (UsbMass);\r
-  if (!EFI_ERROR (Status)) {\r
-    //\r
-    // According to USB Mass Storage Specification for Bootability, only following\r
-    // 4 Peripheral Device Types are in spec.\r
-    //\r
-    if ((UsbMass->Pdt != USB_PDT_DIRECT_ACCESS) && \r
-         (UsbMass->Pdt != USB_PDT_CDROM) &&\r
-         (UsbMass->Pdt != USB_PDT_OPTICAL) && \r
-         (UsbMass->Pdt != USB_PDT_SIMPLE_DIRECT)) {\r
-      DEBUG ((EFI_D_ERROR, "UsbMassInitNonLun: Found an unsupported peripheral type[%d]\n", UsbMass->Pdt));\r
-      goto ON_ERROR;\r
-    }\r
-  } else if (Status != EFI_NO_MEDIA){\r
+  if ((EFI_ERROR (Status)) && (Status != EFI_NO_MEDIA)) {\r
     DEBUG ((EFI_D_ERROR, "UsbMassInitNonLun: UsbMassInitMedia (%r)\n", Status));\r
     goto ON_ERROR;\r
   }\r
     \r
-  Status = gBS->InstallProtocolInterface (\r
+  InitializeDiskInfo (UsbMass);\r
+\r
+  Status = gBS->InstallMultipleProtocolInterfaces (\r
                   &Controller,\r
                   &gEfiBlockIoProtocolGuid,\r
-                  EFI_NATIVE_INTERFACE,\r
-                  &UsbMass->BlockIo\r
+                  &UsbMass->BlockIo,\r
+                  &gEfiDiskInfoProtocolGuid,\r
+                  &UsbMass->DiskInfo,\r
+                  NULL\r
                   );\r
   if (EFI_ERROR (Status)) {\r
     goto ON_ERROR;\r
@@ -712,12 +676,14 @@ ON_ERROR:
   if (UsbMass != NULL) {\r
     FreePool (UsbMass);\r
   }\r
-  gBS->CloseProtocol (\r
-         Controller,\r
-         &gEfiUsbIoProtocolGuid,\r
-         This->DriverBindingHandle,\r
-         Controller\r
-         );\r
+  if (UsbIo != NULL) {\r
+    gBS->CloseProtocol (\r
+           Controller,\r
+           &gEfiUsbIoProtocolGuid,\r
+           This->DriverBindingHandle,\r
+           Controller\r
+           );\r
+  }\r
   return Status;  \r
 }\r
 \r
@@ -830,7 +796,11 @@ USBMassDriverBindingStart (
   VOID                          *Context;\r
   UINT8                         MaxLun;\r
   EFI_STATUS                    Status;\r
-  \r
+  EFI_USB_IO_PROTOCOL           *UsbIo; \r
+  EFI_TPL                       OldTpl;\r
+\r
+  OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
+\r
   Transport = NULL;\r
   Context   = NULL;\r
   MaxLun    = 0;\r
@@ -839,7 +809,7 @@ USBMassDriverBindingStart (
 \r
   if (EFI_ERROR (Status)) {\r
     DEBUG ((EFI_D_ERROR, "USBMassDriverBindingStart: UsbMassInitTransport (%r)\n", Status));\r
-    return Status;\r
+    goto Exit;\r
   }\r
   if (MaxLun == 0) {\r
     //\r
@@ -864,24 +834,52 @@ USBMassDriverBindingStart (
   \r
     if (EFI_ERROR (Status)) {\r
       DEBUG ((EFI_D_ERROR, "USBMassDriverBindingStart: OpenDevicePathProtocol By Driver (%r)\n", Status));\r
-      return Status;\r
+      goto Exit;\r
+    }\r
+\r
+    Status = gBS->OpenProtocol (\r
+                    Controller,\r
+                    &gEfiUsbIoProtocolGuid,\r
+                    (VOID **) &UsbIo,\r
+                    This->DriverBindingHandle,\r
+                    Controller,\r
+                    EFI_OPEN_PROTOCOL_BY_DRIVER\r
+                    );\r
+  \r
+    if (EFI_ERROR (Status)) {\r
+      DEBUG ((EFI_D_ERROR, "USBMassDriverBindingStart: OpenUsbIoProtocol By Driver (%r)\n", Status));\r
+      gBS->CloseProtocol (\r
+             Controller,\r
+             &gEfiDevicePathProtocolGuid,\r
+             This->DriverBindingHandle,\r
+             Controller\r
+             );\r
+      goto Exit;\r
     }\r
 \r
     //\r
-    // Initialize data for device that supports multiple LUNSs.\r
+    // Initialize data for device that supports multiple LUNs.\r
     // EFI_SUCCESS is returned if at least 1 LUN is initialized successfully.\r
     //\r
     Status = UsbMassInitMultiLun (This, Controller, Transport, Context, DevicePath, MaxLun);\r
     if (EFI_ERROR (Status)) {\r
-     gBS->CloseProtocol (\r
-            Controller,\r
-            &gEfiDevicePathProtocolGuid,\r
-            This->DriverBindingHandle,\r
-            Controller\r
-            );\r
+      gBS->CloseProtocol (\r
+              Controller,\r
+              &gEfiDevicePathProtocolGuid,\r
+              This->DriverBindingHandle,\r
+              Controller\r
+              );\r
+      gBS->CloseProtocol (\r
+              Controller,\r
+              &gEfiUsbIoProtocolGuid,\r
+              This->DriverBindingHandle,\r
+              Controller\r
+              );\r
       DEBUG ((EFI_D_ERROR, "USBMassDriverBindingStart: UsbMassInitMultiLun (%r) with Maxlun=%d\n", Status, MaxLun));\r
     }\r
   }\r
+Exit:\r
+  gBS->RestoreTPL (OldTpl);\r
   return Status;\r
 }\r
 \r
@@ -919,9 +917,9 @@ USBMassDriverBindingStop (
   //\r
   // This is a bus driver stop function since multi-lun is supported.\r
   // There are three kinds of device handles that might be passed:\r
-  // 1st is a handle with Device Path & USB I/O & Block I/O installed (non-multi-lun)\r
+  // 1st is a handle with USB I/O & Block I/O installed (non-multi-lun)\r
   // 2nd is a handle with Device Path & USB I/O installed (multi-lun root)\r
-  // 3rd is a handle with Device Path & Block I/O installed (multi-lun).\r
+  // 3rd is a handle with Device Path & USB I/O & Block I/O installed (multi-lun).\r
   //\r
   if (NumberOfChildren == 0) {\r
     //\r
@@ -938,8 +936,8 @@ USBMassDriverBindingStop (
   \r
     if (EFI_ERROR(Status)) {\r
       //\r
-      // This is a 2nd type handle(multi-lun root), which only needs to close \r
-      // Device Path Protocol.\r
+      // This is a 2nd type handle(multi-lun root), it needs to close devicepath\r
+      // and usbio protocol.\r
       //\r
       gBS->CloseProtocol (\r
             Controller,\r
@@ -947,6 +945,12 @@ USBMassDriverBindingStop (
             This->DriverBindingHandle,\r
             Controller\r
             );\r
+      gBS->CloseProtocol (\r
+            Controller,\r
+            &gEfiUsbIoProtocolGuid,\r
+            This->DriverBindingHandle,\r
+            Controller\r
+            );\r
       DEBUG ((EFI_D_INFO, "Success to stop multi-lun root handle\n"));\r
       return EFI_SUCCESS;\r
     }\r
@@ -961,10 +965,13 @@ USBMassDriverBindingStop (
     // Uninstall Block I/O protocol from the device handle,\r
     // then call the transport protocol to stop itself.\r
     //\r
-    Status = gBS->UninstallProtocolInterface (\r
+    Status = gBS->UninstallMultipleProtocolInterfaces (\r
                     Controller,\r
                     &gEfiBlockIoProtocolGuid,\r
-                    &UsbMass->BlockIo\r
+                    &UsbMass->BlockIo,\r
+                    &gEfiDiskInfoProtocolGuid,\r
+                    &UsbMass->DiskInfo,\r
+                    NULL\r
                     );\r
     if (EFI_ERROR (Status)) {\r
       return Status;\r
@@ -1022,6 +1029,8 @@ USBMassDriverBindingStop (
                     UsbMass->DevicePath,\r
                     &gEfiBlockIoProtocolGuid,\r
                     &UsbMass->BlockIo,\r
+                    &gEfiDiskInfoProtocolGuid,\r
+                    &UsbMass->DiskInfo,\r
                     NULL\r
                     );\r
     \r