]> git.proxmox.com Git - mirror_edk2.git/commitdiff
MdeModulePkg/UfsPassThruDxe: Add impl of UFS Device Config Protocol
authorHao Wu <hao.a.wu@intel.com>
Mon, 19 Jun 2017 02:53:34 +0000 (10:53 +0800)
committerHao Wu <hao.a.wu@intel.com>
Wed, 2 Aug 2017 12:56:45 +0000 (20:56 +0800)
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Hao Wu <hao.a.wu@intel.com>
Reviewed-by: Star Zeng <star.zeng@intel.com>
MdeModulePkg/Bus/Ufs/UfsPassThruDxe/UfsDevConfigProtocol.c [new file with mode: 0644]
MdeModulePkg/Bus/Ufs/UfsPassThruDxe/UfsPassThru.c
MdeModulePkg/Bus/Ufs/UfsPassThruDxe/UfsPassThru.h
MdeModulePkg/Bus/Ufs/UfsPassThruDxe/UfsPassThruDxe.inf
MdeModulePkg/Bus/Ufs/UfsPassThruDxe/UfsPassThruHci.c

diff --git a/MdeModulePkg/Bus/Ufs/UfsPassThruDxe/UfsDevConfigProtocol.c b/MdeModulePkg/Bus/Ufs/UfsPassThruDxe/UfsDevConfigProtocol.c
new file mode 100644 (file)
index 0000000..1b5a7ce
--- /dev/null
@@ -0,0 +1,196 @@
+/** @file\r
+  The implementation of the EFI UFS Device Config Protocol.\r
+\r
+  Copyright (c) 2017, 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
+\r
+  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
+**/\r
+\r
+#include "UfsPassThru.h"\r
+\r
+/**\r
+  Read or write specified device descriptor of a UFS device.\r
+\r
+  The function is used to read/write UFS device descriptors. The consumer of this API is\r
+  responsible for allocating the data buffer pointed by Descriptor.\r
+\r
+  @param[in]      This          The pointer to the EFI_UFS_DEVICE_CONFIG_PROTOCOL instance.\r
+  @param[in]      Read          The boolean variable to show r/w direction.\r
+  @param[in]      DescId        The ID of device descriptor.\r
+  @param[in]      Index         The Index of device descriptor.\r
+  @param[in]      Selector      The Selector of device descriptor.\r
+  @param[in, out] Descriptor    The buffer of device descriptor to be read or written.\r
+  @param[in, out] DescSize      The size of device descriptor buffer. On input, the size, in bytes,\r
+                                of the data buffer specified by Descriptor. On output, the number\r
+                                of bytes that were actually transferred.\r
+\r
+  @retval EFI_SUCCESS           The device descriptor is read/written successfully.\r
+  @retval EFI_INVALID_PARAMETER This is NULL or Descriptor is NULL or DescSize is NULL.\r
+                                DescId, Index and Selector are invalid combination to point to a\r
+                                type of UFS device descriptor.\r
+  @retval EFI_DEVICE_ERROR      The device descriptor is not read/written successfully.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+UfsRwUfsDescriptor (\r
+  IN EFI_UFS_DEVICE_CONFIG_PROTOCOL    *This,\r
+  IN BOOLEAN                           Read,\r
+  IN UINT8                             DescId,\r
+  IN UINT8                             Index,\r
+  IN UINT8                             Selector,\r
+  IN OUT UINT8                         *Descriptor,\r
+  IN OUT UINT32                        *DescSize\r
+  )\r
+{\r
+  EFI_STATUS                    Status;\r
+  UFS_PASS_THRU_PRIVATE_DATA    *Private;\r
+\r
+  Private = UFS_PASS_THRU_PRIVATE_DATA_FROM_DEV_CONFIG (This);\r
+\r
+  if ((This == NULL) || (Descriptor == NULL) || (DescSize == NULL)) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  Status = UfsRwDeviceDesc (\r
+             Private,\r
+             Read,\r
+             DescId,\r
+             Index,\r
+             Selector,\r
+             Descriptor,\r
+             DescSize\r
+             );\r
+  if (Status == EFI_TIMEOUT) {\r
+    Status = EFI_DEVICE_ERROR;\r
+  }\r
+  return Status;\r
+}\r
+\r
+/**\r
+  Read or write specified flag of a UFS device.\r
+\r
+  The function is used to read/write UFS flag descriptors. The consumer of this API is responsible\r
+  for allocating the buffer pointed by Flag. The buffer size is 1 byte as UFS flag descriptor is\r
+  just a single Boolean value that represents a TRUE or FALSE, '0' or '1', ON or OFF type of value.\r
+\r
+  @param[in]      This          The pointer to the EFI_UFS_DEVICE_CONFIG_PROTOCOL instance.\r
+  @param[in]      Read          The boolean variable to show r/w direction.\r
+  @param[in]      FlagId        The ID of flag to be read or written.\r
+  @param[in, out] Flag          The buffer to set or clear flag.\r
+\r
+  @retval EFI_SUCCESS           The flag descriptor is set/clear successfully.\r
+  @retval EFI_INVALID_PARAMETER This is NULL or Flag is NULL.\r
+                                FlagId is an invalid UFS flag ID.\r
+  @retval EFI_DEVICE_ERROR      The flag is not set/clear successfully.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+UfsRwUfsFlag (\r
+  IN EFI_UFS_DEVICE_CONFIG_PROTOCOL    *This,\r
+  IN BOOLEAN                           Read,\r
+  IN UINT8                             FlagId,\r
+  IN OUT UINT8                         *Flag\r
+  )\r
+{\r
+  EFI_STATUS                    Status;\r
+  UFS_PASS_THRU_PRIVATE_DATA    *Private;\r
+\r
+  Private = UFS_PASS_THRU_PRIVATE_DATA_FROM_DEV_CONFIG (This);\r
+\r
+  if ((This == NULL) || (Flag == NULL)) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  Status = UfsRwFlags (Private, Read, FlagId, Flag);\r
+  if (Status == EFI_TIMEOUT) {\r
+    Status = EFI_DEVICE_ERROR;\r
+  }\r
+  return Status;\r
+}\r
+\r
+/**\r
+  Read or write specified attribute of a UFS device.\r
+\r
+  The function is used to read/write UFS attributes. The consumer of this API is responsible for\r
+  allocating the data buffer pointed by Attribute.\r
+\r
+  @param[in]      This          The pointer to the EFI_UFS_DEVICE_CONFIG_PROTOCOL instance.\r
+  @param[in]      Read          The boolean variable to show r/w direction.\r
+  @param[in]      AttrId        The ID of Attribute.\r
+  @param[in]      Index         The Index of Attribute.\r
+  @param[in]      Selector      The Selector of Attribute.\r
+  @param[in, out] Attribute     The buffer of Attribute to be read or written.\r
+  @param[in, out] AttrSize      The size of Attribute buffer. On input, the size, in bytes, of the\r
+                                data buffer specified by Attribute. On output, the number of bytes\r
+                                that were actually transferred.\r
+\r
+  @retval EFI_SUCCESS           The attribute is read/written successfully.\r
+  @retval EFI_INVALID_PARAMETER This is NULL or Attribute is NULL or AttrSize is NULL.\r
+                                AttrId, Index and Selector are invalid combination to point to a\r
+                                type of UFS attribute.\r
+  @retval EFI_DEVICE_ERROR      The attribute is not read/written successfully.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+UfsRwUfsAttribute (\r
+  IN EFI_UFS_DEVICE_CONFIG_PROTOCOL    *This,\r
+  IN BOOLEAN                           Read,\r
+  IN UINT8                             AttrId,\r
+  IN UINT8                             Index,\r
+  IN UINT8                             Selector,\r
+  IN OUT UINT8                         *Attribute,\r
+  IN OUT UINT32                        *AttrSize\r
+  )\r
+{\r
+  EFI_STATUS                    Status;\r
+  UFS_PASS_THRU_PRIVATE_DATA    *Private;\r
+  UINT32                        Attribute32;\r
+\r
+  Private = UFS_PASS_THRU_PRIVATE_DATA_FROM_DEV_CONFIG (This);\r
+  Attribute32 = 0;\r
+\r
+  if ((This == NULL) || (Attribute == NULL) || (AttrSize == NULL)) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  //\r
+  // According to UFS Version 2.1 Spec (JESD220C) Section 14.3, the size of a attribute will not\r
+  // exceed 32-bit.\r
+  //\r
+  if (*AttrSize > 4) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  if (!Read) {\r
+    CopyMem (&Attribute32, Attribute, *AttrSize);\r
+  }\r
+\r
+  Status = UfsRwAttributes (\r
+             Private,\r
+             Read,\r
+             AttrId,\r
+             Index,\r
+             Selector,\r
+             &Attribute32\r
+             );\r
+  if (!EFI_ERROR (Status)) {\r
+    if (Read) {\r
+      CopyMem (Attribute, &Attribute32, *AttrSize);\r
+    }\r
+  } else {\r
+    *AttrSize = 0;\r
+    if (Status == EFI_TIMEOUT) {\r
+      Status = EFI_DEVICE_ERROR;\r
+    }\r
+  }\r
+  return Status;\r
+}\r
index e27f4fbab175a2d53e2e58017680bbfc3d9a5388..e24eb40333be558cf50cc0cdb1d5b72444f51630 100644 (file)
@@ -34,6 +34,11 @@ UFS_PASS_THRU_PRIVATE_DATA gUfsPassThruTemplate = {
     UfsPassThruResetTargetLun,\r
     UfsPassThruGetNextTarget\r
   },\r
+  {                               // UfsDevConfig\r
+    UfsRwUfsDescriptor,\r
+    UfsRwUfsFlag,\r
+    UfsRwUfsAttribute\r
+  },\r
   0,                              // UfsHostController\r
   0,                              // UfsHcBase\r
   0,                              // Capabilities\r
@@ -820,6 +825,7 @@ UfsPassThruDriverBindingStart (
   UINTN                                 UfsHcBase;\r
   UINT32                                Index;\r
   UFS_UNIT_DESC                         UnitDescriptor;\r
+  UINT32                                UnitDescriptorSize;\r
 \r
   Status    = EFI_SUCCESS;\r
   UfsHc     = NULL;\r
@@ -896,8 +902,9 @@ UfsPassThruDriverBindingStart (
   // Check if 8 common luns are active and set corresponding bit mask.\r
   // TODO: Parse device descriptor to decide if exposing RPMB LUN to upper layer for authentication access.\r
   //\r
+  UnitDescriptorSize = sizeof (UFS_UNIT_DESC);\r
   for (Index = 0; Index < 8; Index++) {\r
-    Status = UfsRwDeviceDesc (Private, TRUE, UfsUnitDesc, (UINT8) Index, 0, &UnitDescriptor, sizeof (UFS_UNIT_DESC));\r
+    Status = UfsRwDeviceDesc (Private, TRUE, UfsUnitDesc, (UINT8) Index, 0, &UnitDescriptor, &UnitDescriptorSize);\r
     if (EFI_ERROR (Status)) {\r
       DEBUG ((DEBUG_ERROR, "Failed to read unit descriptor, index = %X, status = %r\n", Index, Status));\r
       continue;\r
@@ -933,11 +940,13 @@ UfsPassThruDriverBindingStart (
     goto Error;\r
   }\r
 \r
-  Status = gBS->InstallProtocolInterface (\r
+  Status = gBS->InstallMultipleProtocolInterfaces (\r
                   &Controller,\r
                   &gEfiExtScsiPassThruProtocolGuid,\r
-                  EFI_NATIVE_INTERFACE,\r
-                  &(Private->ExtScsiPassThru)\r
+                  &(Private->ExtScsiPassThru),\r
+                  &gEfiUfsDeviceConfigProtocolGuid,\r
+                  &(Private->UfsDevConfig),\r
+                  NULL\r
                   );\r
   ASSERT_EFI_ERROR (Status);\r
 \r
@@ -1057,10 +1066,13 @@ UfsPassThruDriverBindingStop (
     }\r
   }\r
 \r
-  Status = gBS->UninstallProtocolInterface (\r
+  Status = gBS->UninstallMultipleProtocolInterfaces (\r
                   Controller,\r
                   &gEfiExtScsiPassThruProtocolGuid,\r
-                  &(Private->ExtScsiPassThru)\r
+                  &(Private->ExtScsiPassThru),\r
+                  &gEfiUfsDeviceConfigProtocolGuid,\r
+                  &(Private->UfsDevConfig),\r
+                  NULL\r
                   );\r
 \r
   if (EFI_ERROR (Status)) {\r
index bdc64f779309039f9c451cf94c4e0ea1649bfbbc..6c7198325839d67cfcad9c24a77d0e841e925525 100644 (file)
@@ -17,6 +17,7 @@
 #include <Uefi.h>\r
 \r
 #include <Protocol/ScsiPassThruExt.h>\r
+#include <Protocol/UfsDeviceConfig.h>\r
 #include <Protocol/UfsHostController.h>\r
 \r
 #include <Library/DebugLib.h>\r
@@ -63,6 +64,7 @@ typedef struct _UFS_PASS_THRU_PRIVATE_DATA {
   EFI_HANDLE                          Handle;\r
   EFI_EXT_SCSI_PASS_THRU_MODE         ExtScsiPassThruMode;\r
   EFI_EXT_SCSI_PASS_THRU_PROTOCOL     ExtScsiPassThru;\r
+  EFI_UFS_DEVICE_CONFIG_PROTOCOL      UfsDevConfig;\r
   EDKII_UFS_HOST_CONTROLLER_PROTOCOL  *UfsHostController;\r
   UINTN                               UfsHcBase;\r
   UINT32                              Capabilities;\r
@@ -120,6 +122,13 @@ typedef struct {
       UFS_PASS_THRU_SIG \\r
       )\r
 \r
+#define UFS_PASS_THRU_PRIVATE_DATA_FROM_DEV_CONFIG(a) \\r
+  CR (a, \\r
+      UFS_PASS_THRU_PRIVATE_DATA, \\r
+      UfsDevConfig, \\r
+      UFS_PASS_THRU_SIG \\r
+      )\r
+\r
 typedef struct _UFS_DEVICE_MANAGEMENT_REQUEST_PACKET {\r
   UINT64           Timeout;\r
   VOID             *DataBuffer;\r
@@ -732,6 +741,27 @@ UfsReadFlag (
      OUT UINT8                        *Value\r
   );\r
 \r
+/**\r
+  Read or write specified flag of a UFS device.\r
+\r
+  @param[in]      Private       The pointer to the UFS_PASS_THRU_PRIVATE_DATA data structure.\r
+  @param[in]      Read          The boolean variable to show r/w direction.\r
+  @param[in]      FlagId        The ID of flag to be read or written.\r
+  @param[in, out] Value         The value to set or clear flag.\r
+\r
+  @retval EFI_SUCCESS           The flag was read/written successfully.\r
+  @retval EFI_DEVICE_ERROR      A device error occurred while attempting to r/w the flag.\r
+  @retval EFI_TIMEOUT           A timeout occurred while waiting for the completion of r/w the flag.\r
+\r
+**/\r
+EFI_STATUS\r
+UfsRwFlags (\r
+  IN     UFS_PASS_THRU_PRIVATE_DATA   *Private,\r
+  IN     BOOLEAN                      Read,\r
+  IN     UINT8                        FlagId,\r
+  IN OUT UINT8                        *Value\r
+  );\r
+\r
 /**\r
   Read or write specified device descriptor of a UFS device.\r
 \r
@@ -741,7 +771,9 @@ UfsReadFlag (
   @param[in]      Index         The Index of device descriptor.\r
   @param[in]      Selector      The Selector of device descriptor.\r
   @param[in, out] Descriptor    The buffer of device descriptor to be read or written.\r
-  @param[in]      DescSize      The size of device descriptor buffer.\r
+  @param[in, out] DescSize      The size of device descriptor buffer. On input, the size, in bytes,\r
+                                of the data buffer specified by Descriptor. On output, the number\r
+                                of bytes that were actually transferred.\r
 \r
   @retval EFI_SUCCESS           The device descriptor was read/written successfully.\r
   @retval EFI_DEVICE_ERROR      A device error occurred while attempting to r/w the device descriptor.\r
@@ -756,7 +788,7 @@ UfsRwDeviceDesc (
   IN     UINT8                        Index,\r
   IN     UINT8                        Selector,\r
   IN OUT VOID                         *Descriptor,\r
-  IN     UINT32                       DescSize\r
+  IN OUT UINT32                       *DescSize\r
   );\r
 \r
 /**\r
@@ -833,6 +865,103 @@ SignalCallerEvent (
   IN UFS_PASS_THRU_TRANS_REQ         *TransReq\r
   );\r
 \r
+/**\r
+  Read or write specified device descriptor of a UFS device.\r
+\r
+  The function is used to read/write UFS device descriptors. The consumer of this API is\r
+  responsible for allocating the data buffer pointed by Descriptor.\r
+\r
+  @param[in]      This          The pointer to the EFI_UFS_DEVICE_CONFIG_PROTOCOL instance.\r
+  @param[in]      Read          The boolean variable to show r/w direction.\r
+  @param[in]      DescId        The ID of device descriptor.\r
+  @param[in]      Index         The Index of device descriptor.\r
+  @param[in]      Selector      The Selector of device descriptor.\r
+  @param[in, out] Descriptor    The buffer of device descriptor to be read or written.\r
+  @param[in, out] DescSize      The size of device descriptor buffer. On input, the size, in bytes,\r
+                                of the data buffer specified by Descriptor. On output, the number\r
+                                of bytes that were actually transferred.\r
+\r
+  @retval EFI_SUCCESS           The device descriptor is read/written successfully.\r
+  @retval EFI_INVALID_PARAMETER This is NULL or Descriptor is NULL or DescSize is NULL.\r
+                                DescId, Index and Selector are invalid combination to point to a\r
+                                type of UFS device descriptor.\r
+  @retval EFI_DEVICE_ERROR      The device descriptor is not read/written successfully.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+UfsRwUfsDescriptor (\r
+  IN EFI_UFS_DEVICE_CONFIG_PROTOCOL    *This,\r
+  IN BOOLEAN                           Read,\r
+  IN UINT8                             DescId,\r
+  IN UINT8                             Index,\r
+  IN UINT8                             Selector,\r
+  IN OUT UINT8                         *Descriptor,\r
+  IN OUT UINT32                        *DescSize\r
+  );\r
+\r
+/**\r
+  Read or write specified flag of a UFS device.\r
+\r
+  The function is used to read/write UFS flag descriptors. The consumer of this API is responsible\r
+  for allocating the buffer pointed by Flag. The buffer size is 1 byte as UFS flag descriptor is\r
+  just a single Boolean value that represents a TRUE or FALSE, '0' or '1', ON or OFF type of value.\r
+\r
+  @param[in]      This          The pointer to the EFI_UFS_DEVICE_CONFIG_PROTOCOL instance.\r
+  @param[in]      Read          The boolean variable to show r/w direction.\r
+  @param[in]      FlagId        The ID of flag to be read or written.\r
+  @param[in, out] Flag          The buffer to set or clear flag.\r
+\r
+  @retval EFI_SUCCESS           The flag descriptor is set/clear successfully.\r
+  @retval EFI_INVALID_PARAMETER This is NULL or Flag is NULL.\r
+                                FlagId is an invalid UFS flag ID.\r
+  @retval EFI_DEVICE_ERROR      The flag is not set/clear successfully.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+UfsRwUfsFlag (\r
+  IN EFI_UFS_DEVICE_CONFIG_PROTOCOL    *This,\r
+  IN BOOLEAN                           Read,\r
+  IN UINT8                             FlagId,\r
+  IN OUT UINT8                         *Flag\r
+  );\r
+\r
+/**\r
+  Read or write specified attribute of a UFS device.\r
+\r
+  The function is used to read/write UFS attributes. The consumer of this API is responsible for\r
+  allocating the data buffer pointed by Attribute.\r
+\r
+  @param[in]      This          The pointer to the EFI_UFS_DEVICE_CONFIG_PROTOCOL instance.\r
+  @param[in]      Read          The boolean variable to show r/w direction.\r
+  @param[in]      AttrId        The ID of Attribute.\r
+  @param[in]      Index         The Index of Attribute.\r
+  @param[in]      Selector      The Selector of Attribute.\r
+  @param[in, out] Attribute     The buffer of Attribute to be read or written.\r
+  @param[in, out] AttrSize      The size of Attribute buffer. On input, the size, in bytes, of the\r
+                                data buffer specified by Attribute. On output, the number of bytes\r
+                                that were actually transferred.\r
+\r
+  @retval EFI_SUCCESS           The attribute is read/written successfully.\r
+  @retval EFI_INVALID_PARAMETER This is NULL or Attribute is NULL or AttrSize is NULL.\r
+                                AttrId, Index and Selector are invalid combination to point to a\r
+                                type of UFS attribute.\r
+  @retval EFI_DEVICE_ERROR      The attribute is not read/written successfully.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+UfsRwUfsAttribute (\r
+  IN EFI_UFS_DEVICE_CONFIG_PROTOCOL    *This,\r
+  IN BOOLEAN                           Read,\r
+  IN UINT8                             AttrId,\r
+  IN UINT8                             Index,\r
+  IN UINT8                             Selector,\r
+  IN OUT UINT8                         *Attribute,\r
+  IN OUT UINT32                        *AttrSize\r
+  );\r
+\r
 extern EFI_COMPONENT_NAME_PROTOCOL  gUfsPassThruComponentName;\r
 extern EFI_COMPONENT_NAME2_PROTOCOL gUfsPassThruComponentName2;\r
 extern EFI_DRIVER_BINDING_PROTOCOL  gUfsPassThruDriverBinding;\r
index c90c72f9150dc8931e3ae5e2526262af3982980f..467c533cebf3d4c26efaced2bbe2af00b0968497 100644 (file)
@@ -1,7 +1,7 @@
 ## @file\r
 # Description file for the Universal Flash Storage (UFS) Pass Thru driver.\r
 #\r
-# Copyright (c) 2014 - 2015, Intel Corporation. All rights reserved.<BR>\r
+# Copyright (c) 2014 - 2017, Intel Corporation. All rights reserved.<BR>\r
 #\r
 #  This program and the accompanying materials\r
 #  are licensed and made available under the terms and conditions of the BSD License\r
@@ -34,6 +34,7 @@
 \r
 [Sources]\r
   ComponentName.c\r
+  UfsDevConfigProtocol.c\r
   UfsPassThru.c\r
   UfsPassThru.h\r
   UfsPassThruHci.c\r
@@ -56,6 +57,7 @@
 \r
 [Protocols]\r
   gEfiExtScsiPassThruProtocolGuid               ## BY_START\r
+  gEfiUfsDeviceConfigProtocolGuid               ## BY_START\r
   gEdkiiUfsHostControllerProtocolGuid           ## TO_START\r
 \r
 [UserExtensions.TianoCore."ExtraFiles"]\r
index a19bdcc3cc397fdd36ab07aebbd58775b7870b6d..5fa635523aeb02c4f2c33ca60cdc3c7d0dd84c4c 100644 (file)
@@ -909,6 +909,8 @@ UfsGetReturnDataFromQueryResponse (
   @param[in] Packet  Pointer to the UFS_DEVICE_MANAGEMENT_REQUEST_PACKET.\r
 \r
   @retval EFI_SUCCESS           The device descriptor was read/written successfully.\r
+  @retval EFI_INVALID_PARAMETER The DescId, Index and Selector fields in Packet are invalid\r
+                                combination to point to a type of UFS device descriptor.\r
   @retval EFI_DEVICE_ERROR      A device error occurred while attempting to r/w the device descriptor.\r
   @retval EFI_TIMEOUT           A timeout occurred while waiting for the completion of r/w the device descriptor.\r
 \r
@@ -967,7 +969,14 @@ UfsSendDmRequestRetry (
   if (Trd->Ocs != 0 || QueryResp->QueryResp != UfsUtpQueryResponseSuccess) {\r
     DEBUG ((DEBUG_ERROR, "Failed to send query request, OCS = %X, QueryResp = %X\n", Trd->Ocs, QueryResp->QueryResp));\r
     DumpQueryResponseResult (QueryResp->QueryResp);\r
-    Status = EFI_DEVICE_ERROR;\r
+\r
+    if ((QueryResp->QueryResp == UfsUtpQueryResponseInvalidSelector) ||\r
+        (QueryResp->QueryResp == UfsUtpQueryResponseInvalidIndex) ||\r
+        (QueryResp->QueryResp == UfsUtpQueryResponseInvalidIdn)) {\r
+      Status = EFI_INVALID_PARAMETER;\r
+    } else {\r
+      Status = EFI_DEVICE_ERROR;\r
+    }\r
     goto Exit;\r
   }\r
 \r
@@ -999,6 +1008,8 @@ Exit:
   @param[in] Packet  Pointer to the UFS_DEVICE_MANAGEMENT_PACKET.\r
 \r
   @retval EFI_SUCCESS           The device responded correctly to the Query request.\r
+  @retval EFI_INVALID_PARAMETER The DescId, Index and Selector fields in Packet are invalid\r
+                                combination to point to a type of UFS device descriptor.\r
   @retval EFI_DEVICE_ERROR      A device error occurred while waiting for the response from the device.\r
   @retval EFI_TIMEOUT           A timeout occurred while waiting for the completion of the operation.\r
 \r
@@ -1034,9 +1045,13 @@ UfsSendDmRequest (
   @param[in]      Index         The Index of device descriptor.\r
   @param[in]      Selector      The Selector of device descriptor.\r
   @param[in, out] Descriptor    The buffer of device descriptor to be read or written.\r
-  @param[in]      DescSize      The size of device descriptor buffer.\r
+  @param[in, out] DescSize      The size of device descriptor buffer. On input, the size, in bytes,\r
+                                of the data buffer specified by Descriptor. On output, the number\r
+                                of bytes that were actually transferred.\r
 \r
   @retval EFI_SUCCESS           The device descriptor was read/written successfully.\r
+  @retval EFI_INVALID_PARAMETER DescId, Index and Selector are invalid combination to point to a\r
+                                type of UFS device descriptor.\r
   @retval EFI_DEVICE_ERROR      A device error occurred while attempting to r/w the device descriptor.\r
   @retval EFI_TIMEOUT           A timeout occurred while waiting for the completion of r/w the device descriptor.\r
 \r
@@ -1049,10 +1064,15 @@ UfsRwDeviceDesc (
   IN     UINT8                        Index,\r
   IN     UINT8                        Selector,\r
   IN OUT VOID                         *Descriptor,\r
-  IN     UINT32                       DescSize\r
+  IN OUT UINT32                       *DescSize\r
   )\r
 {\r
   UFS_DEVICE_MANAGEMENT_REQUEST_PACKET Packet;\r
+  EFI_STATUS                           Status;\r
+\r
+  if (DescSize == NULL) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
 \r
   ZeroMem (&Packet, sizeof (UFS_DEVICE_MANAGEMENT_REQUEST_PACKET));\r
 \r
@@ -1064,13 +1084,20 @@ UfsRwDeviceDesc (
     Packet.Opcode            = UtpQueryFuncOpcodeWrDesc;\r
   }\r
   Packet.DataBuffer          = Descriptor;\r
-  Packet.TransferLength      = DescSize;\r
+  Packet.TransferLength      = *DescSize;\r
   Packet.DescId              = DescId;\r
   Packet.Index               = Index;\r
   Packet.Selector            = Selector;\r
   Packet.Timeout             = UFS_TIMEOUT;\r
 \r
-  return UfsSendDmRequest (Private, &Packet);\r
+  Status = UfsSendDmRequest (Private, &Packet);\r
+  if (EFI_ERROR (Status)) {\r
+    *DescSize = 0;\r
+  } else {\r
+    *DescSize = Packet.TransferLength;\r
+  }\r
+\r
+  return Status;\r
 }\r
 \r
 /**\r
@@ -1084,6 +1111,8 @@ UfsRwDeviceDesc (
   @param[in, out] Attributes    The value of Attribute to be read or written.\r
 \r
   @retval EFI_SUCCESS           The Attribute was read/written successfully.\r
+  @retval EFI_INVALID_PARAMETER AttrId, Index and Selector are invalid combination to point to a\r
+                                type of UFS device descriptor.\r
   @retval EFI_DEVICE_ERROR      A device error occurred while attempting to r/w the Attribute.\r
   @retval EFI_TIMEOUT           A timeout occurred while waiting for the completion of r/w the Attribute.\r
 \r
@@ -1127,6 +1156,7 @@ UfsRwAttributes (
   @param[in, out] Value         The value to set or clear flag.\r
 \r
   @retval EFI_SUCCESS           The flag was read/written successfully.\r
+  @retval EFI_INVALID_PARAMETER FlagId is an invalid UFS flag ID.\r
   @retval EFI_DEVICE_ERROR      A device error occurred while attempting to r/w the flag.\r
   @retval EFI_TIMEOUT           A timeout occurred while waiting for the completion of r/w the flag.\r
 \r