[edk2] [PATCH 1/2] MdeModulePkg/UfsPassThruDxe: Add impl of UFS Device Config Protocol

Hao Wu posted 2 patches 7 years, 5 months ago
[edk2] [PATCH 1/2] MdeModulePkg/UfsPassThruDxe: Add impl of UFS Device Config Protocol
Posted by Hao Wu 7 years, 5 months ago
Cc: Star Zeng <star.zeng@intel.com>
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Hao Wu <hao.a.wu@intel.com>
---
 MdeModulePkg/Bus/Ufs/UfsPassThruDxe/UfsDevConfigProtocol.c | 196 ++++++++++++++++++++
 MdeModulePkg/Bus/Ufs/UfsPassThruDxe/UfsPassThru.c          |  24 ++-
 MdeModulePkg/Bus/Ufs/UfsPassThruDxe/UfsPassThru.h          | 133 ++++++++++++-
 MdeModulePkg/Bus/Ufs/UfsPassThruDxe/UfsPassThruDxe.inf     |   4 +-
 MdeModulePkg/Bus/Ufs/UfsPassThruDxe/UfsPassThruHci.c       |  40 +++-
 5 files changed, 383 insertions(+), 14 deletions(-)

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

_______________________________________________
edk2-devel mailing list
edk2-devel@lists.01.org
https://lists.01.org/mailman/listinfo/edk2-devel