]> git.proxmox.com Git - mirror_edk2.git/blobdiff - MdeModulePkg/Bus/Ufs/UfsPassThruDxe/UfsPassThruHci.c
MdeModulePkg/UfsPassThruDxe: Refactor private data to use UfsHcInfo
[mirror_edk2.git] / MdeModulePkg / Bus / Ufs / UfsPassThruDxe / UfsPassThruHci.c
index 81653af5a8ad2af41d9ff012a58c5120364f8773..74be3efc411b05b28133a0f970be94b64f2ae7dd 100644 (file)
@@ -2,14 +2,8 @@
   UfsPassThruDxe driver is used to produce EFI_EXT_SCSI_PASS_THRU protocol interface\r
   for upper layer application to execute UFS-supported SCSI cmds.\r
 \r
-  Copyright (c) 2014 - 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
-\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
+  Copyright (c) 2014 - 2019, Intel Corporation. All rights reserved.<BR>\r
+  SPDX-License-Identifier: BSD-2-Clause-Patent\r
 \r
 **/\r
 \r
@@ -157,35 +151,35 @@ DumpUicCmdExecResult (
       case 0x00:\r
         break;\r
       case 0x01:\r
-        DEBUG ((EFI_D_VERBOSE, "UIC configuration command fails - INVALID_MIB_ATTRIBUTE\n"));\r
+        DEBUG ((DEBUG_VERBOSE, "UIC configuration command fails - INVALID_MIB_ATTRIBUTE\n"));\r
         break;\r
       case 0x02:\r
-        DEBUG ((EFI_D_VERBOSE, "UIC configuration command fails - INVALID_MIB_ATTRIBUTE_VALUE\n"));\r
+        DEBUG ((DEBUG_VERBOSE, "UIC configuration command fails - INVALID_MIB_ATTRIBUTE_VALUE\n"));\r
         break;\r
       case 0x03:\r
-        DEBUG ((EFI_D_VERBOSE, "UIC configuration command fails - READ_ONLY_MIB_ATTRIBUTE\n"));\r
+        DEBUG ((DEBUG_VERBOSE, "UIC configuration command fails - READ_ONLY_MIB_ATTRIBUTE\n"));\r
         break;\r
       case 0x04:\r
-        DEBUG ((EFI_D_VERBOSE, "UIC configuration command fails - WRITE_ONLY_MIB_ATTRIBUTE\n"));\r
+        DEBUG ((DEBUG_VERBOSE, "UIC configuration command fails - WRITE_ONLY_MIB_ATTRIBUTE\n"));\r
         break;\r
       case 0x05:\r
-        DEBUG ((EFI_D_VERBOSE, "UIC configuration command fails - BAD_INDEX\n"));\r
+        DEBUG ((DEBUG_VERBOSE, "UIC configuration command fails - BAD_INDEX\n"));\r
         break;\r
       case 0x06:\r
-        DEBUG ((EFI_D_VERBOSE, "UIC configuration command fails - LOCKED_MIB_ATTRIBUTE\n"));\r
+        DEBUG ((DEBUG_VERBOSE, "UIC configuration command fails - LOCKED_MIB_ATTRIBUTE\n"));\r
         break;\r
       case 0x07:\r
-        DEBUG ((EFI_D_VERBOSE, "UIC configuration command fails - BAD_TEST_FEATURE_INDEX\n"));\r
+        DEBUG ((DEBUG_VERBOSE, "UIC configuration command fails - BAD_TEST_FEATURE_INDEX\n"));\r
         break;\r
       case 0x08:\r
-        DEBUG ((EFI_D_VERBOSE, "UIC configuration command fails - PEER_COMMUNICATION_FAILURE\n"));\r
-        break; \r
+        DEBUG ((DEBUG_VERBOSE, "UIC configuration command fails - PEER_COMMUNICATION_FAILURE\n"));\r
+        break;\r
       case 0x09:\r
-        DEBUG ((EFI_D_VERBOSE, "UIC configuration command fails - BUSY\n"));\r
+        DEBUG ((DEBUG_VERBOSE, "UIC configuration command fails - BUSY\n"));\r
         break;\r
       case 0x0A:\r
-        DEBUG ((EFI_D_VERBOSE, "UIC configuration command fails - DME_FAILURE\n"));\r
-        break;        \r
+        DEBUG ((DEBUG_VERBOSE, "UIC configuration command fails - DME_FAILURE\n"));\r
+        break;\r
       default :\r
         ASSERT (FALSE);\r
         break;\r
@@ -195,8 +189,8 @@ DumpUicCmdExecResult (
       case 0x00:\r
         break;\r
       case 0x01:\r
-        DEBUG ((EFI_D_VERBOSE, "UIC control command fails - FAILURE\n"));\r
-        break;     \r
+        DEBUG ((DEBUG_VERBOSE, "UIC control command fails - FAILURE\n"));\r
+        break;\r
       default :\r
         ASSERT (FALSE);\r
         break;\r
@@ -217,34 +211,34 @@ DumpQueryResponseResult (
 {\r
   switch (Result) {\r
     case 0xF6:\r
-      DEBUG ((EFI_D_VERBOSE, "Query Response with Parameter Not Readable\n"));\r
+      DEBUG ((DEBUG_VERBOSE, "Query Response with Parameter Not Readable\n"));\r
       break;\r
     case 0xF7:\r
-      DEBUG ((EFI_D_VERBOSE, "Query Response with Parameter Not Writeable\n"));\r
+      DEBUG ((DEBUG_VERBOSE, "Query Response with Parameter Not Writeable\n"));\r
       break;\r
     case 0xF8:\r
-      DEBUG ((EFI_D_VERBOSE, "Query Response with Parameter Already Written\n"));\r
+      DEBUG ((DEBUG_VERBOSE, "Query Response with Parameter Already Written\n"));\r
       break;\r
     case 0xF9:\r
-      DEBUG ((EFI_D_VERBOSE, "Query Response with Invalid Length\n"));\r
+      DEBUG ((DEBUG_VERBOSE, "Query Response with Invalid Length\n"));\r
       break;\r
     case 0xFA:\r
-      DEBUG ((EFI_D_VERBOSE, "Query Response with Invalid Value\n"));\r
+      DEBUG ((DEBUG_VERBOSE, "Query Response with Invalid Value\n"));\r
       break;\r
     case 0xFB:\r
-      DEBUG ((EFI_D_VERBOSE, "Query Response with Invalid Selector\n"));\r
+      DEBUG ((DEBUG_VERBOSE, "Query Response with Invalid Selector\n"));\r
       break;\r
     case 0xFC:\r
-      DEBUG ((EFI_D_VERBOSE, "Query Response with Invalid Index\n"));\r
+      DEBUG ((DEBUG_VERBOSE, "Query Response with Invalid Index\n"));\r
       break;\r
     case 0xFD:\r
-      DEBUG ((EFI_D_VERBOSE, "Query Response with Invalid Idn\n"));\r
+      DEBUG ((DEBUG_VERBOSE, "Query Response with Invalid Idn\n"));\r
       break;\r
     case 0xFE:\r
-      DEBUG ((EFI_D_VERBOSE, "Query Response with Invalid Opcode\n"));\r
-      break; \r
+      DEBUG ((DEBUG_VERBOSE, "Query Response with Invalid Opcode\n"));\r
+      break;\r
     case 0xFF:\r
-      DEBUG ((EFI_D_VERBOSE, "Query Response with General Failure\n"));\r
+      DEBUG ((DEBUG_VERBOSE, "Query Response with General Failure\n"));\r
       break;\r
     default :\r
       ASSERT (FALSE);\r
@@ -314,7 +308,7 @@ UfsFillTsfOfQueryReqUpiu (
       SwapLittleEndianToBigEndian ((UINT8*)&Length, sizeof (Length));\r
       TsfBase->Length = Length;\r
     }\r
-  \r
+\r
     if (Opcode == UtpQueryFuncOpcodeWrAttr) {\r
       SwapLittleEndianToBigEndian ((UINT8*)&Value, sizeof (Value));\r
       TsfBase->Value  = Value;\r
@@ -400,12 +394,13 @@ UfsInitUtpPrdt (
   UINT8      *Remaining;\r
   UINTN      PrdtNumber;\r
 \r
+  ASSERT (((UINTN)Buffer & (BIT0 | BIT1)) == 0);\r
+  ASSERT ((BufferSize & (BIT1 | BIT0)) == 0);\r
+\r
   if (BufferSize == 0) {\r
     return EFI_SUCCESS;\r
   }\r
 \r
-  ASSERT (((UINTN)Buffer & (BIT0 | BIT1)) == 0);\r
-\r
   RemainingLen = BufferSize;\r
   Remaining    = Buffer;\r
   PrdtNumber   = (UINTN)DivU64x32 ((UINT64)BufferSize + UFS_MAX_DATA_LEN_PER_PRD - 1, UFS_MAX_DATA_LEN_PER_PRD);\r
@@ -473,6 +468,9 @@ UfsInitQueryRequestUpiu (
 \r
   if (Opcode == UtpQueryFuncOpcodeWrDesc) {\r
     CopyMem (QueryReq + 1, Data, DataSize);\r
+\r
+    SwapLittleEndianToBigEndian ((UINT8*)&DataSize, sizeof (UINT16));\r
+    QueryReq->DataSegLen = (UINT16)DataSize;\r
   }\r
 \r
   return EFI_SUCCESS;\r
@@ -546,6 +544,7 @@ UfsCreateScsiCommandDesc (
   Trd->Int    = UFS_INTERRUPT_COMMAND;\r
   Trd->Dd     = DataDirection;\r
   Trd->Ct     = UFS_STORAGE_COMMAND_TYPE;\r
+  Trd->Ocs    = UFS_HC_TRD_OCS_INIT_VALUE;\r
   Trd->UcdBa  = (UINT32)RShiftU64 ((UINT64)CmdDescPhyAddr, 7);\r
   Trd->UcdBaU = (UINT32)RShiftU64 ((UINT64)CmdDescPhyAddr, 32);\r
   Trd->RuL    = (UINT16)DivU64x32 ((UINT64)ROUNDUP8 (sizeof (UTP_RESPONSE_UPIU)), sizeof (UINT32));\r
@@ -596,32 +595,13 @@ UfsCreateDMCommandDesc (
   }\r
 \r
   DataDirection = Packet->DataDirection;\r
-  if (DataDirection == UfsDataIn) {\r
-    DataSize = Packet->InTransferLength;\r
-    Data     = Packet->InDataBuffer;\r
-  } else if (DataDirection == UfsDataOut) {\r
-    DataSize = Packet->OutTransferLength;\r
-    Data     = Packet->OutDataBuffer;\r
-  } else {\r
-    DataSize = 0;\r
-    Data     = NULL;\r
-  }\r
-\r
-  if (((Opcode != UtpQueryFuncOpcodeSetFlag) && (Opcode != UtpQueryFuncOpcodeClrFlag) && (Opcode != UtpQueryFuncOpcodeTogFlag))\r
-    && ((DataSize == 0) || (Data == NULL))) {\r
-    return EFI_INVALID_PARAMETER;\r
-  }\r
-\r
-  if (((Opcode == UtpQueryFuncOpcodeSetFlag) || (Opcode == UtpQueryFuncOpcodeClrFlag) || (Opcode == UtpQueryFuncOpcodeTogFlag))\r
-    && ((DataSize != 0) || (Data != NULL))) {\r
-    return EFI_INVALID_PARAMETER;\r
-  }\r
-\r
-  if ((Opcode == UtpQueryFuncOpcodeWrAttr) && (DataSize != sizeof (UINT32))) {\r
-    return EFI_INVALID_PARAMETER;\r
-  }\r
+  DataSize      = Packet->TransferLength;\r
+  Data          = Packet->DataBuffer;\r
 \r
   if ((Opcode == UtpQueryFuncOpcodeWrDesc) || (Opcode == UtpQueryFuncOpcodeRdDesc)) {\r
+    if (DataSize == 0 || Data == NULL) {\r
+      return EFI_INVALID_PARAMETER;\r
+    }\r
     TotalLen = ROUNDUP8 (sizeof (UTP_QUERY_REQ_UPIU)) + ROUNDUP8 (sizeof (UTP_QUERY_RESP_UPIU)) + ROUNDUP8 (DataSize);\r
   } else {\r
     TotalLen = ROUNDUP8 (sizeof (UTP_QUERY_REQ_UPIU)) + ROUNDUP8 (sizeof (UTP_QUERY_RESP_UPIU));\r
@@ -655,14 +635,14 @@ UfsCreateDMCommandDesc (
   Trd->Int    = UFS_INTERRUPT_COMMAND;\r
   Trd->Dd     = DataDirection;\r
   Trd->Ct     = UFS_STORAGE_COMMAND_TYPE;\r
-  Trd->Ocs    = 0x0F;\r
+  Trd->Ocs    = UFS_HC_TRD_OCS_INIT_VALUE;\r
   Trd->UcdBa  = (UINT32)RShiftU64 ((UINT64)CmdDescPhyAddr, 7);\r
   Trd->UcdBaU = (UINT32)RShiftU64 ((UINT64)CmdDescPhyAddr, 32);\r
   if (Opcode == UtpQueryFuncOpcodeWrDesc) {\r
     Trd->RuL  = (UINT16)DivU64x32 ((UINT64)ROUNDUP8 (sizeof (UTP_QUERY_RESP_UPIU)), sizeof (UINT32));\r
-    Trd->RuO  = (UINT16)DivU64x32 ((UINT64)(ROUNDUP8 (sizeof (UTP_QUERY_REQ_UPIU)) + ROUNDUP8 (DataSize)), sizeof (UINT32));\r
+    Trd->RuO  = (UINT16)DivU64x32 ((UINT64)ROUNDUP8 (sizeof (UTP_QUERY_REQ_UPIU)) + ROUNDUP8 (DataSize), sizeof (UINT32));\r
   } else {\r
-    Trd->RuL  = (UINT16)DivU64x32 ((UINT64)(ROUNDUP8 (sizeof (UTP_QUERY_RESP_UPIU)) + ROUNDUP8 (DataSize)), sizeof (UINT32));\r
+    Trd->RuL  = (UINT16)DivU64x32 ((UINT64)ROUNDUP8 (sizeof (UTP_QUERY_RESP_UPIU)) + ROUNDUP8 (DataSize), sizeof (UINT32));\r
     Trd->RuO  = (UINT16)DivU64x32 ((UINT64)ROUNDUP8 (sizeof (UTP_QUERY_REQ_UPIU)), sizeof (UINT32));\r
   }\r
 \r
@@ -714,6 +694,7 @@ UfsCreateNopCommandDesc (
   Trd->Int    = UFS_INTERRUPT_COMMAND;\r
   Trd->Dd     = 0x00;\r
   Trd->Ct     = UFS_STORAGE_COMMAND_TYPE;\r
+  Trd->Ocs    = UFS_HC_TRD_OCS_INIT_VALUE;\r
   Trd->UcdBa  = (UINT32)RShiftU64 ((UINT64)CmdDescPhyAddr, 7);\r
   Trd->UcdBaU = (UINT32)RShiftU64 ((UINT64)CmdDescPhyAddr, 32);\r
   Trd->RuL    = (UINT16)DivU64x32 ((UINT64)ROUNDUP8 (sizeof (UTP_NOP_IN_UPIU)), sizeof (UINT32));\r
@@ -750,7 +731,7 @@ UfsFindAvailableSlotInTrl (
     return Status;\r
   }\r
 \r
-  Nutrs   = (UINT8)((Private->Capabilities & UFS_HC_CAP_NUTRS) + 1);\r
+  Nutrs   = (UINT8)((Private->UfsHcInfo.Capabilities & UFS_HC_CAP_NUTRS) + 1);\r
 \r
   for (Index = 0; Index < Nutrs; Index++) {\r
     if ((Data & (BIT0 << Index)) == 0) {\r
@@ -762,31 +743,6 @@ UfsFindAvailableSlotInTrl (
   return EFI_NOT_READY;\r
 }\r
 \r
-/**\r
-  Find out available slot in task management transfer list of a UFS device.\r
-\r
-  @param[in]  Private       The pointer to the UFS_PASS_THRU_PRIVATE_DATA data structure.\r
-  @param[out] Slot          The available slot.\r
-\r
-  @retval EFI_SUCCESS       The available slot was found successfully.\r
-\r
-**/\r
-EFI_STATUS\r
-UfsFindAvailableSlotInTmrl (\r
-  IN     UFS_PASS_THRU_PRIVATE_DATA   *Private,\r
-     OUT UINT8                        *Slot\r
-  )\r
-{\r
-  ASSERT ((Private != NULL) && (Slot != NULL));\r
-\r
-  //\r
-  // The simplest algo to always use slot 0.\r
-  // TODO: enhance it to support async transfer with multiple slot.\r
-  //\r
-  *Slot = 0;\r
-\r
-  return EFI_SUCCESS;\r
-}\r
 \r
 /**\r
   Start specified slot in transfer list of a UFS device.\r
@@ -799,7 +755,7 @@ EFI_STATUS
 UfsStartExecCmd (\r
   IN  UFS_PASS_THRU_PRIVATE_DATA   *Private,\r
   IN  UINT8                        Slot\r
-  ) \r
+  )\r
 {\r
   UINT32        Data;\r
   EFI_STATUS    Status;\r
@@ -835,7 +791,7 @@ EFI_STATUS
 UfsStopExecCmd (\r
   IN  UFS_PASS_THRU_PRIVATE_DATA   *Private,\r
   IN  UINT8                        Slot\r
-  ) \r
+  )\r
 {\r
   UINT32        Data;\r
   EFI_STATUS    Status;\r
@@ -861,60 +817,94 @@ UfsStopExecCmd (
 }\r
 \r
 /**\r
-  Read or write specified device descriptor of a UFS device.\r
+  Extracts return data from query response upiu.\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]      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]      DescSize      The size of device descriptor buffer.\r
+  @param[in] Packet     Pointer to the UFS_DEVICE_MANAGEMENT_REQUEST_PACKET.\r
+  @param[in] QueryResp  Pointer to the query response.\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
-  @retval EFI_TIMEOUT           A timeout occurred while waiting for the completion of r/w the device descriptor.\r
+  @retval EFI_INVALID_PARAMETER Packet or QueryResp are empty or opcode is invalid.\r
+  @retval EFI_DEVICE_ERROR      Data returned from device is invalid.\r
+  @retval EFI_SUCCESS           Data extracted.\r
 \r
 **/\r
 EFI_STATUS\r
-UfsRwDeviceDesc (\r
-  IN     UFS_PASS_THRU_PRIVATE_DATA   *Private,\r
-  IN     BOOLEAN                      Read,\r
-  IN     UINT8                        DescId,\r
-  IN     UINT8                        Index,\r
-  IN     UINT8                        Selector,\r
-  IN OUT VOID                         *Descriptor,\r
-  IN     UINT32                       DescSize\r
+UfsGetReturnDataFromQueryResponse (\r
+  IN UFS_DEVICE_MANAGEMENT_REQUEST_PACKET  *Packet,\r
+  IN UTP_QUERY_RESP_UPIU                   *QueryResp\r
   )\r
 {\r
-  EFI_STATUS                           Status;\r
-  UFS_DEVICE_MANAGEMENT_REQUEST_PACKET Packet;\r
-  UINT8                                Slot;\r
-  UTP_TRD                              *Trd;\r
-  UTP_QUERY_RESP_UPIU                  *QueryResp;\r
-  UINT32                               CmdDescSize;\r
-  UINT16                               ReturnDataSize;\r
-  VOID                                 *CmdDescHost;\r
-  VOID                                 *CmdDescMapping;\r
-  EDKII_UFS_HOST_CONTROLLER_PROTOCOL   *UfsHc;\r
+  UINT16  ReturnDataSize;\r
+  UINT32  ReturnData;\r
 \r
-  ZeroMem (&Packet, sizeof (UFS_DEVICE_MANAGEMENT_REQUEST_PACKET));\r
+  if (Packet == NULL || QueryResp == NULL) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
 \r
-  if (Read) {\r
-    Packet.DataDirection     = UfsDataIn;\r
-    Packet.InDataBuffer      = Descriptor;\r
-    Packet.InTransferLength  = DescSize;\r
-    Packet.Opcode            = UtpQueryFuncOpcodeRdDesc;\r
-  } else {\r
-    Packet.DataDirection     = UfsDataOut;\r
-    Packet.OutDataBuffer     = Descriptor;\r
-    Packet.OutTransferLength = DescSize;\r
-    Packet.Opcode            = UtpQueryFuncOpcodeWrDesc;\r
+  switch (Packet->Opcode) {\r
+    case UtpQueryFuncOpcodeRdDesc:\r
+      ReturnDataSize = QueryResp->Tsf.Length;\r
+      SwapLittleEndianToBigEndian ((UINT8*)&ReturnDataSize, sizeof (UINT16));\r
+      //\r
+      // Make sure the hardware device does not return more data than expected.\r
+      //\r
+      if (ReturnDataSize > Packet->TransferLength) {\r
+        return EFI_DEVICE_ERROR;\r
+      }\r
+\r
+      CopyMem (Packet->DataBuffer, (QueryResp + 1), ReturnDataSize);\r
+      Packet->TransferLength = ReturnDataSize;\r
+      break;\r
+    case UtpQueryFuncOpcodeWrDesc:\r
+      ReturnDataSize = QueryResp->Tsf.Length;\r
+      SwapLittleEndianToBigEndian ((UINT8*)&ReturnDataSize, sizeof (UINT16));\r
+      Packet->TransferLength = ReturnDataSize;\r
+      break;\r
+    case UtpQueryFuncOpcodeRdFlag:\r
+    case UtpQueryFuncOpcodeSetFlag:\r
+    case UtpQueryFuncOpcodeClrFlag:\r
+    case UtpQueryFuncOpcodeTogFlag:\r
+      CopyMem (Packet->DataBuffer, &QueryResp->Tsf.Value, sizeof (UINT8));\r
+      break;\r
+    case UtpQueryFuncOpcodeRdAttr:\r
+    case UtpQueryFuncOpcodeWrAttr:\r
+      ReturnData = QueryResp->Tsf.Value;\r
+      SwapLittleEndianToBigEndian ((UINT8*) &ReturnData, sizeof (UINT32));\r
+      CopyMem (Packet->DataBuffer, &ReturnData, sizeof (UINT32));\r
+      break;\r
+    default:\r
+      return EFI_INVALID_PARAMETER;\r
   }\r
-  Packet.DescId              = DescId;\r
-  Packet.Index               = Index;\r
-  Packet.Selector            = Selector;\r
-  Packet.Timeout             = UFS_TIMEOUT;\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  Creates Transfer Request descriptor and sends Query Request to the device.\r
+\r
+  @param[in] Private Pointer to the UFS_PASS_THRU_PRIVATE_DATA.\r
+  @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
+**/\r
+EFI_STATUS\r
+UfsSendDmRequestRetry (\r
+  IN UFS_PASS_THRU_PRIVATE_DATA            *Private,\r
+  IN UFS_DEVICE_MANAGEMENT_REQUEST_PACKET  *Packet\r
+  )\r
+{\r
+  UINT8                               Slot;\r
+  UTP_TRD                             *Trd;\r
+  VOID                                *CmdDescHost;\r
+  VOID                                *CmdDescMapping;\r
+  UINT32                              CmdDescSize;\r
+  EDKII_UFS_HOST_CONTROLLER_PROTOCOL  *UfsHc;\r
+  UTP_QUERY_RESP_UPIU                 *QueryResp;\r
+  EFI_STATUS                          Status;\r
 \r
   //\r
   // Find out which slot of transfer request list is available.\r
@@ -923,19 +913,17 @@ UfsRwDeviceDesc (
   if (EFI_ERROR (Status)) {\r
     return Status;\r
   }\r
-  \r
+\r
   Trd = ((UTP_TRD*)Private->UtpTrlBase) + Slot;\r
   //\r
   // Fill transfer request descriptor to this slot.\r
   //\r
-  Status = UfsCreateDMCommandDesc (Private, &Packet, Trd, &CmdDescHost, &CmdDescMapping);\r
+  Status = UfsCreateDMCommandDesc (Private, Packet, Trd, &CmdDescHost, &CmdDescMapping);\r
   if (EFI_ERROR (Status)) {\r
+    DEBUG ((DEBUG_ERROR, "Failed to create DM command descriptor\n"));\r
     return Status;\r
   }\r
 \r
-  //\r
-  // Check the transfer request result.\r
-  //\r
   UfsHc       = Private->UfsHostController;\r
   QueryResp   = (UTP_QUERY_RESP_UPIU*)((UINT8*)CmdDescHost + Trd->RuO * sizeof (UINT32));\r
   ASSERT (QueryResp != NULL);\r
@@ -948,30 +936,30 @@ UfsRwDeviceDesc (
 \r
   //\r
   // Wait for the completion of the transfer request.\r
-  //  \r
-  Status = UfsWaitMemSet (Private, UFS_HC_UTRLDBR_OFFSET, BIT0, 0, Packet.Timeout);\r
+  //\r
+  Status = UfsWaitMemSet (Private, UFS_HC_UTRLDBR_OFFSET, BIT0, 0, Packet->Timeout);\r
   if (EFI_ERROR (Status)) {\r
     goto Exit;\r
   }\r
 \r
-  if (QueryResp->QueryResp != 0) {\r
+  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
-    goto Exit;\r
-  }\r
-\r
-  if (Trd->Ocs == 0) {\r
-    ReturnDataSize = QueryResp->Tsf.Length;\r
-    SwapLittleEndianToBigEndian ((UINT8*)&ReturnDataSize, sizeof (UINT16));\r
 \r
-    if (Read) {\r
-      CopyMem (Packet.InDataBuffer, (QueryResp + 1), ReturnDataSize);\r
-      Packet.InTransferLength = ReturnDataSize;\r
+    if ((QueryResp->QueryResp == UfsUtpQueryResponseInvalidSelector) ||\r
+        (QueryResp->QueryResp == UfsUtpQueryResponseInvalidIndex) ||\r
+        (QueryResp->QueryResp == UfsUtpQueryResponseInvalidIdn)) {\r
+      Status = EFI_INVALID_PARAMETER;\r
     } else {\r
-      Packet.OutTransferLength = ReturnDataSize;\r
+      Status = EFI_DEVICE_ERROR;\r
     }\r
-  } else {\r
-    Status = EFI_DEVICE_ERROR;\r
+    goto Exit;\r
+  }\r
+\r
+  Status = UfsGetReturnDataFromQueryResponse (Packet, QueryResp);\r
+  if (EFI_ERROR (Status)) {\r
+    DEBUG ((DEBUG_ERROR, "Failed to get return data from query response\n"));\r
+    goto Exit;\r
   }\r
 \r
 Exit:\r
@@ -989,6 +977,105 @@ Exit:
   return Status;\r
 }\r
 \r
+/**\r
+  Sends Query Request to the device. Query is sent until device responds correctly or counter runs out.\r
+\r
+  @param[in] Private Pointer to the UFS_PASS_THRU_PRIVATE_DATA.\r
+  @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
+**/\r
+EFI_STATUS\r
+UfsSendDmRequest (\r
+  IN UFS_PASS_THRU_PRIVATE_DATA            *Private,\r
+  IN UFS_DEVICE_MANAGEMENT_REQUEST_PACKET  *Packet\r
+  )\r
+{\r
+  EFI_STATUS  Status;\r
+  UINT8       Retry;\r
+\r
+  Status = EFI_SUCCESS;\r
+\r
+  for (Retry = 0; Retry < 5; Retry ++) {\r
+    Status = UfsSendDmRequestRetry (Private, Packet);\r
+    if (!EFI_ERROR (Status)) {\r
+      return EFI_SUCCESS;\r
+    }\r
+  }\r
+\r
+  DEBUG ((DEBUG_ERROR, "Failed to get response from the device after %d retries\n", Retry));\r
+  return Status;\r
+}\r
+\r
+/**\r
+  Read or write specified device descriptor 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]      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 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
+**/\r
+EFI_STATUS\r
+UfsRwDeviceDesc (\r
+  IN     UFS_PASS_THRU_PRIVATE_DATA   *Private,\r
+  IN     BOOLEAN                      Read,\r
+  IN     UINT8                        DescId,\r
+  IN     UINT8                        Index,\r
+  IN     UINT8                        Selector,\r
+  IN OUT VOID                         *Descriptor,\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
+  if (Read) {\r
+    Packet.DataDirection     = UfsDataIn;\r
+    Packet.Opcode            = UtpQueryFuncOpcodeRdDesc;\r
+  } else {\r
+    Packet.DataDirection     = UfsDataOut;\r
+    Packet.Opcode            = UtpQueryFuncOpcodeWrDesc;\r
+  }\r
+  Packet.DataBuffer          = Descriptor;\r
+  Packet.TransferLength      = *DescSize;\r
+  Packet.DescId              = DescId;\r
+  Packet.Index               = Index;\r
+  Packet.Selector            = Selector;\r
+  Packet.Timeout             = UFS_TIMEOUT;\r
+\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
   Read or write specified attribute of a UFS device.\r
 \r
@@ -1000,6 +1087,8 @@ Exit:
   @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
@@ -1014,16 +1103,7 @@ UfsRwAttributes (
   IN OUT UINT32                       *Attributes\r
   )\r
 {\r
-  EFI_STATUS                           Status;\r
   UFS_DEVICE_MANAGEMENT_REQUEST_PACKET Packet;\r
-  UINT8                                Slot;\r
-  UTP_TRD                              *Trd;\r
-  UTP_QUERY_RESP_UPIU                  *QueryResp;\r
-  UINT32                               CmdDescSize;\r
-  UINT32                               ReturnData;\r
-  VOID                                 *CmdDescHost;\r
-  VOID                                 *CmdDescMapping;\r
-  EDKII_UFS_HOST_CONTROLLER_PROTOCOL   *UfsHc;\r
 \r
   ZeroMem (&Packet, sizeof (UFS_DEVICE_MANAGEMENT_REQUEST_PACKET));\r
 \r
@@ -1034,77 +1114,13 @@ UfsRwAttributes (
     Packet.DataDirection     = UfsDataOut;\r
     Packet.Opcode            = UtpQueryFuncOpcodeWrAttr;\r
   }\r
+  Packet.DataBuffer          = Attributes;\r
   Packet.DescId              = AttrId;\r
   Packet.Index               = Index;\r
   Packet.Selector            = Selector;\r
   Packet.Timeout             = UFS_TIMEOUT;\r
 \r
-  //\r
-  // Find out which slot of transfer request list is available.\r
-  //\r
-  Status = UfsFindAvailableSlotInTrl (Private, &Slot);\r
-  if (EFI_ERROR (Status)) {\r
-    return Status;\r
-  }\r
-  \r
-  Trd = ((UTP_TRD*)Private->UtpTrlBase) + Slot;\r
-  //\r
-  // Fill transfer request descriptor to this slot.\r
-  //\r
-  Status = UfsCreateDMCommandDesc (Private, &Packet, Trd, &CmdDescHost, &CmdDescMapping);\r
-  if (EFI_ERROR (Status)) {\r
-    return Status;\r
-  }\r
-\r
-  //\r
-  // Check the transfer request result.\r
-  //\r
-  UfsHc       = Private->UfsHostController;\r
-  QueryResp   = (UTP_QUERY_RESP_UPIU*)((UINT8*)CmdDescHost + Trd->RuO * sizeof (UINT32));\r
-  ASSERT (QueryResp != NULL);\r
-  CmdDescSize = Trd->RuO * sizeof (UINT32) + Trd->RuL * sizeof (UINT32);\r
-\r
-  //\r
-  // Start to execute the transfer request.\r
-  //\r
-  UfsStartExecCmd (Private, Slot);\r
-\r
-  //\r
-  // Wait for the completion of the transfer request.\r
-  //  \r
-  Status = UfsWaitMemSet (Private, UFS_HC_UTRLDBR_OFFSET, BIT0, 0, Packet.Timeout);\r
-  if (EFI_ERROR (Status)) {\r
-    goto Exit;\r
-  }\r
-\r
-  if (QueryResp->QueryResp != 0) {\r
-    DumpQueryResponseResult (QueryResp->QueryResp);\r
-    Status = EFI_DEVICE_ERROR;\r
-    goto Exit;\r
-  }\r
-\r
-  if (Trd->Ocs == 0) {\r
-    ReturnData = QueryResp->Tsf.Value;\r
-    SwapLittleEndianToBigEndian ((UINT8*)&ReturnData, sizeof (UINT32));\r
-    *Attributes = ReturnData;\r
-  } else {\r
-    Status = EFI_DEVICE_ERROR;\r
-  }\r
-\r
-Exit:\r
-  UfsHc->Flush (UfsHc);\r
-\r
-  UfsStopExecCmd (Private, Slot);\r
-\r
-  if (CmdDescMapping != NULL) {\r
-    UfsHc->Unmap (UfsHc, CmdDescMapping);\r
-  }\r
-\r
-  if (CmdDescHost != NULL) {\r
-    UfsHc->FreeBuffer (UfsHc, EFI_SIZE_TO_PAGES (CmdDescSize), CmdDescHost);\r
-  }\r
-\r
-  return Status;\r
+  return UfsSendDmRequest (Private, &Packet);\r
 }\r
 \r
 /**\r
@@ -1116,6 +1132,7 @@ Exit:
   @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
@@ -1125,107 +1142,38 @@ UfsRwFlags (
   IN     UFS_PASS_THRU_PRIVATE_DATA   *Private,\r
   IN     BOOLEAN                      Read,\r
   IN     UINT8                        FlagId,\r
-  IN OUT UINT8                        *Value\r
-  )\r
-{\r
-  EFI_STATUS                           Status;\r
-  UFS_DEVICE_MANAGEMENT_REQUEST_PACKET Packet;\r
-  UINT8                                Slot;\r
-  UTP_TRD                              *Trd;\r
-  UTP_QUERY_RESP_UPIU                  *QueryResp;\r
-  UINT32                               CmdDescSize;\r
-  VOID                                 *CmdDescHost;\r
-  VOID                                 *CmdDescMapping;\r
-  EDKII_UFS_HOST_CONTROLLER_PROTOCOL   *UfsHc;\r
-\r
-  if (Value == NULL) {\r
-    return EFI_INVALID_PARAMETER;\r
-  }\r
-\r
-  ZeroMem (&Packet, sizeof (UFS_DEVICE_MANAGEMENT_REQUEST_PACKET));\r
-\r
-  if (Read) {\r
-    ASSERT (Value != NULL);\r
-    Packet.DataDirection     = UfsDataIn;\r
-    Packet.Opcode            = UtpQueryFuncOpcodeRdFlag;\r
-  } else {\r
-    Packet.DataDirection     = UfsDataOut;\r
-    if (*Value == 1) {\r
-      Packet.Opcode          = UtpQueryFuncOpcodeSetFlag;\r
-    } else if (*Value == 0) {\r
-      Packet.Opcode          = UtpQueryFuncOpcodeClrFlag;\r
-    } else {\r
-      return EFI_INVALID_PARAMETER;\r
-    }\r
-  }\r
-  Packet.DescId              = FlagId;\r
-  Packet.Index               = 0;\r
-  Packet.Selector            = 0;\r
-  Packet.Timeout             = UFS_TIMEOUT;\r
-\r
-  //\r
-  // Find out which slot of transfer request list is available.\r
-  //\r
-  Status = UfsFindAvailableSlotInTrl (Private, &Slot);\r
-  if (EFI_ERROR (Status)) {\r
-    return Status;\r
-  }\r
-\r
-  //\r
-  // Fill transfer request descriptor to this slot.\r
-  //\r
-  Trd    = ((UTP_TRD*)Private->UtpTrlBase) + Slot;\r
-  Status = UfsCreateDMCommandDesc (Private, &Packet, Trd, &CmdDescHost, &CmdDescMapping);\r
-  if (EFI_ERROR (Status)) {\r
-    return Status;\r
-  }\r
-\r
-  //\r
-  // Check the transfer request result.\r
-  //\r
-  UfsHc       = Private->UfsHostController;\r
-  QueryResp   = (UTP_QUERY_RESP_UPIU*)((UINT8*)CmdDescHost + Trd->RuO * sizeof (UINT32));\r
-  ASSERT (QueryResp != NULL);\r
-  CmdDescSize = Trd->RuO * sizeof (UINT32) + Trd->RuL * sizeof (UINT32);\r
-\r
-  //\r
-  // Start to execute the transfer request.\r
-  //\r
-  UfsStartExecCmd (Private, Slot);\r
+  IN OUT UINT8                        *Value\r
+  )\r
+{\r
+  UFS_DEVICE_MANAGEMENT_REQUEST_PACKET Packet;\r
 \r
-  //\r
-  // Wait for the completion of the transfer request.\r
-  //  \r
-  Status = UfsWaitMemSet (Private, UFS_HC_UTRLDBR_OFFSET, BIT0, 0, Packet.Timeout);\r
-  if (EFI_ERROR (Status)) {\r
-    goto Exit;\r
+  if (Value == NULL) {\r
+    return EFI_INVALID_PARAMETER;\r
   }\r
 \r
-  if (QueryResp->QueryResp != 0) {\r
-    DumpQueryResponseResult (QueryResp->QueryResp);\r
-    Status = EFI_DEVICE_ERROR;\r
-    goto Exit;\r
-  }\r
+  ZeroMem (&Packet, sizeof (UFS_DEVICE_MANAGEMENT_REQUEST_PACKET));\r
 \r
-  if (Trd->Ocs == 0) {\r
-    *Value = (UINT8)QueryResp->Tsf.Value;\r
+  if (Read) {\r
+    ASSERT (Value != NULL);\r
+    Packet.DataDirection     = UfsDataIn;\r
+    Packet.Opcode            = UtpQueryFuncOpcodeRdFlag;\r
   } else {\r
-    Status = EFI_DEVICE_ERROR;\r
-  }\r
-\r
-Exit:\r
-  UfsHc->Flush (UfsHc);\r
-\r
-  UfsStopExecCmd (Private, Slot);\r
-\r
-  if (CmdDescMapping != NULL) {\r
-    UfsHc->Unmap (UfsHc, CmdDescMapping);\r
-  }\r
-  if (CmdDescHost != NULL) {\r
-    UfsHc->FreeBuffer (UfsHc, EFI_SIZE_TO_PAGES (CmdDescSize), CmdDescHost);\r
+    Packet.DataDirection     = UfsDataOut;\r
+    if (*Value == 1) {\r
+      Packet.Opcode          = UtpQueryFuncOpcodeSetFlag;\r
+    } else if (*Value == 0) {\r
+      Packet.Opcode          = UtpQueryFuncOpcodeClrFlag;\r
+    } else {\r
+      return EFI_INVALID_PARAMETER;\r
+    }\r
   }\r
+  Packet.DataBuffer          = Value;\r
+  Packet.DescId              = FlagId;\r
+  Packet.Index               = 0;\r
+  Packet.Selector            = 0;\r
+  Packet.Timeout             = UFS_TIMEOUT;\r
 \r
-  return Status;\r
+  return UfsSendDmRequest (Private, &Packet);\r
 }\r
 \r
 /**\r
@@ -1254,31 +1202,7 @@ UfsSetFlag (
   return Status;\r
 }\r
 \r
-/**\r
-  Clear specified flag to 0 on a UFS device.\r
-\r
-  @param[in]  Private           The pointer to the UFS_PASS_THRU_PRIVATE_DATA data structure.\r
-  @param[in]  FlagId            The ID of flag to be cleared.\r
-\r
-  @retval EFI_SUCCESS           The flag was cleared successfully.\r
-  @retval EFI_DEVICE_ERROR      A device error occurred while attempting to clear the flag.\r
-  @retval EFI_TIMEOUT           A timeout occurred while waiting for the completion of clearing the flag.\r
-\r
-**/\r
-EFI_STATUS\r
-UfsClearFlag (\r
-  IN  UFS_PASS_THRU_PRIVATE_DATA   *Private,\r
-  IN  UINT8                        FlagId\r
-  )\r
-{\r
-  EFI_STATUS             Status;\r
-  UINT8                  Value;\r
-\r
-  Value  = 0;\r
-  Status = UfsRwFlags (Private, FALSE, FlagId, &Value);\r
 \r
-  return Status;\r
-}\r
 \r
 /**\r
   Read specified flag from a UFS device.\r
@@ -1362,8 +1286,8 @@ UfsExecNopCmds (
 \r
   //\r
   // Wait for the completion of the transfer request.\r
-  //  \r
-  Status = UfsWaitMemSet (Private, UFS_HC_UTRLDBR_OFFSET, BIT0, 0, UFS_TIMEOUT);\r
+  //\r
+  Status = UfsWaitMemSet (Private, UFS_HC_UTRLDBR_OFFSET, BIT0 << Slot, 0, UFS_TIMEOUT);\r
   if (EFI_ERROR (Status)) {\r
     goto Exit;\r
   }\r
@@ -1389,6 +1313,143 @@ Exit:
   return Status;\r
 }\r
 \r
+/**\r
+  Cleanup data buffers after data transfer. This function\r
+  also takes care to copy all data to user memory pool for\r
+  unaligned data transfers.\r
+\r
+  @param[in] Private   Pointer to the UFS_PASS_THRU_PRIVATE_DATA\r
+  @param[in] TransReq  Pointer to the transfer request\r
+**/\r
+VOID\r
+UfsReconcileDataTransferBuffer (\r
+  IN UFS_PASS_THRU_PRIVATE_DATA  *Private,\r
+  IN UFS_PASS_THRU_TRANS_REQ     *TransReq\r
+  )\r
+{\r
+  if (TransReq->DataBufMapping != NULL) {\r
+    Private->UfsHostController->Unmap (\r
+                                  Private->UfsHostController,\r
+                                  TransReq->DataBufMapping\r
+                                  );\r
+  }\r
+\r
+  //\r
+  // Check if unaligned transfer was performed. If it was and we read\r
+  // data from device copy memory to user data buffers before cleanup.\r
+  // The assumption is if auxiliary aligned data buffer is not NULL then\r
+  // unaligned transfer has been performed.\r
+  //\r
+  if (TransReq->AlignedDataBuf != NULL) {\r
+    if (TransReq->Packet->DataDirection == EFI_EXT_SCSI_DATA_DIRECTION_READ) {\r
+      CopyMem (TransReq->Packet->InDataBuffer, TransReq->AlignedDataBuf, TransReq->Packet->InTransferLength);\r
+    }\r
+    //\r
+    // Wipe out the transfer buffer in case it contains sensitive data.\r
+    //\r
+    ZeroMem (TransReq->AlignedDataBuf, TransReq->AlignedDataBufSize);\r
+    FreeAlignedPages (TransReq->AlignedDataBuf, EFI_SIZE_TO_PAGES (TransReq->AlignedDataBufSize));\r
+    TransReq->AlignedDataBuf = NULL;\r
+  }\r
+}\r
+\r
+/**\r
+  Prepare data buffer for transfer.\r
+\r
+  @param[in]      Private   Pointer to the UFS_PASS_THRU_PRIVATE_DATA\r
+  @param[in, out] TransReq  Pointer to the transfer request\r
+\r
+  @retval EFI_DEVICE_ERROR  Failed to prepare buffer for transfer\r
+  @retval EFI_SUCCESS       Buffer ready for transfer\r
+**/\r
+EFI_STATUS\r
+UfsPrepareDataTransferBuffer (\r
+  IN     UFS_PASS_THRU_PRIVATE_DATA  *Private,\r
+  IN OUT UFS_PASS_THRU_TRANS_REQ     *TransReq\r
+  )\r
+{\r
+  EFI_STATUS                           Status;\r
+  VOID                                 *DataBuf;\r
+  UINT32                               DataLen;\r
+  UINTN                                MapLength;\r
+  EFI_PHYSICAL_ADDRESS                 DataBufPhyAddr;\r
+  EDKII_UFS_HOST_CONTROLLER_OPERATION  Flag;\r
+  UTP_TR_PRD                           *PrdtBase;\r
+\r
+  DataBufPhyAddr = 0;\r
+  DataBuf        = NULL;\r
+\r
+  //\r
+  // For unaligned data transfers we allocate auxiliary DWORD aligned memory pool.\r
+  // When command is finished auxiliary memory pool is copied into actual user memory.\r
+  // This is requiered to assure data transfer safety(DWORD alignment required by UFS spec.)\r
+  //\r
+  if (TransReq->Packet->DataDirection == EFI_EXT_SCSI_DATA_DIRECTION_READ) {\r
+    if (((UINTN)TransReq->Packet->InDataBuffer % 4 != 0) || (TransReq->Packet->InTransferLength % 4 != 0)) {\r
+      DataLen = TransReq->Packet->InTransferLength + (4 - (TransReq->Packet->InTransferLength % 4));\r
+      DataBuf = AllocateAlignedPages (EFI_SIZE_TO_PAGES (DataLen), 4);\r
+      if (DataBuf == NULL) {\r
+        return EFI_DEVICE_ERROR;\r
+      }\r
+      ZeroMem (DataBuf, DataLen);\r
+      TransReq->AlignedDataBuf = DataBuf;\r
+      TransReq->AlignedDataBufSize = DataLen;\r
+    } else {\r
+      DataLen       = TransReq->Packet->InTransferLength;\r
+      DataBuf       = TransReq->Packet->InDataBuffer;\r
+    }\r
+    Flag          = EdkiiUfsHcOperationBusMasterWrite;\r
+  } else {\r
+    if (((UINTN)TransReq->Packet->OutDataBuffer % 4 != 0) || (TransReq->Packet->OutTransferLength % 4 != 0)) {\r
+      DataLen = TransReq->Packet->OutTransferLength + (4 - (TransReq->Packet->OutTransferLength % 4));\r
+      DataBuf = AllocateAlignedPages (EFI_SIZE_TO_PAGES (DataLen), 4);\r
+      if (DataBuf == NULL) {\r
+        return EFI_DEVICE_ERROR;\r
+      }\r
+      CopyMem (DataBuf, TransReq->Packet->OutDataBuffer, TransReq->Packet->OutTransferLength);\r
+      TransReq->AlignedDataBuf = DataBuf;\r
+      TransReq->AlignedDataBufSize = DataLen;\r
+    } else {\r
+      DataLen       = TransReq->Packet->OutTransferLength;\r
+      DataBuf       = TransReq->Packet->OutDataBuffer;\r
+    }\r
+    Flag          = EdkiiUfsHcOperationBusMasterRead;\r
+  }\r
+\r
+  if (DataLen != 0) {\r
+    MapLength = DataLen;\r
+    Status    = Private->UfsHostController->Map (\r
+                                              Private->UfsHostController,\r
+                                              Flag,\r
+                                              DataBuf,\r
+                                              &MapLength,\r
+                                              &DataBufPhyAddr,\r
+                                              &TransReq->DataBufMapping\r
+                                              );\r
+\r
+    if (EFI_ERROR (Status) || (DataLen != MapLength)) {\r
+      if (TransReq->AlignedDataBuf != NULL) {\r
+        //\r
+        // Wipe out the transfer buffer in case it contains sensitive data.\r
+        //\r
+        ZeroMem (TransReq->AlignedDataBuf, TransReq->AlignedDataBufSize);\r
+        FreeAlignedPages (TransReq->AlignedDataBuf, EFI_SIZE_TO_PAGES (TransReq->AlignedDataBufSize));\r
+        TransReq->AlignedDataBuf = NULL;\r
+      }\r
+      return EFI_DEVICE_ERROR;\r
+    }\r
+  }\r
+\r
+  //\r
+  // Fill PRDT table of Command UPIU for executed SCSI cmd.\r
+  //\r
+  PrdtBase = (UTP_TR_PRD*)((UINT8*)TransReq->CmdDescHost + ROUNDUP8 (sizeof (UTP_COMMAND_UPIU)) + ROUNDUP8 (sizeof (UTP_RESPONSE_UPIU)));\r
+  ASSERT (PrdtBase != NULL);\r
+  UfsInitUtpPrdt (PrdtBase, (VOID*)(UINTN)DataBufPhyAddr, DataLen);\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
 /**\r
   Sends a UFS-supported SCSI Request Packet to a UFS device that is attached to the UFS host controller.\r
 \r
@@ -1425,25 +1486,19 @@ UfsExecScsiCmds (
   UTP_RESPONSE_UPIU                    *Response;\r
   UINT16                               SenseDataLen;\r
   UINT32                               ResTranCount;\r
-  VOID                                 *DataBuf;\r
-  EFI_PHYSICAL_ADDRESS                 DataBufPhyAddr;\r
-  UINT32                               DataLen;\r
-  UINTN                                MapLength;\r
-  EDKII_UFS_HOST_CONTROLLER_PROTOCOL   *UfsHc;\r
-  EDKII_UFS_HOST_CONTROLLER_OPERATION  Flag;\r
-  UFS_DATA_DIRECTION                   DataDirection;\r
-  UTP_TR_PRD                           *PrdtBase;\r
   EFI_TPL                              OldTpl;\r
   UFS_PASS_THRU_TRANS_REQ              *TransReq;\r
+  EDKII_UFS_HOST_CONTROLLER_PROTOCOL   *UfsHc;\r
 \r
-  TransReq       = AllocateZeroPool (sizeof (UFS_PASS_THRU_TRANS_REQ));\r
+  TransReq = AllocateZeroPool (sizeof (UFS_PASS_THRU_TRANS_REQ));\r
   if (TransReq == NULL) {\r
     return EFI_OUT_OF_RESOURCES;\r
   }\r
 \r
   TransReq->Signature     = UFS_PASS_THRU_TRANS_REQ_SIG;\r
   TransReq->TimeoutRemain = Packet->Timeout;\r
-  DataBufPhyAddr = 0;\r
+  TransReq->Packet        = Packet;\r
+\r
   UfsHc          = Private->UfsHostController;\r
   //\r
   // Find out which slot of transfer request list is available.\r
@@ -1472,48 +1527,16 @@ UfsExecScsiCmds (
 \r
   TransReq->CmdDescSize = TransReq->Trd->PrdtO * sizeof (UINT32) + TransReq->Trd->PrdtL * sizeof (UTP_TR_PRD);\r
 \r
-  if (Packet->DataDirection == EFI_EXT_SCSI_DATA_DIRECTION_READ) {\r
-    DataBuf       = Packet->InDataBuffer;\r
-    DataLen       = Packet->InTransferLength;\r
-    DataDirection = UfsDataIn;\r
-    Flag          = EdkiiUfsHcOperationBusMasterWrite;\r
-  } else {\r
-    DataBuf       = Packet->OutDataBuffer;\r
-    DataLen       = Packet->OutTransferLength;\r
-    DataDirection = UfsDataOut;\r
-    Flag          = EdkiiUfsHcOperationBusMasterRead;\r
-  }\r
-\r
-  if (DataLen == 0) {\r
-    DataDirection = UfsNoData;\r
-  } else {\r
-    MapLength = DataLen;\r
-    Status    = UfsHc->Map (\r
-                         UfsHc,\r
-                         Flag,\r
-                         DataBuf,\r
-                         &MapLength,\r
-                         &DataBufPhyAddr,\r
-                         &TransReq->DataBufMapping\r
-                         );\r
-\r
-    if (EFI_ERROR (Status) || (DataLen != MapLength)) {\r
-      goto Exit1;\r
-    }\r
+  Status = UfsPrepareDataTransferBuffer (Private, TransReq);\r
+  if (EFI_ERROR (Status)) {\r
+    goto Exit1;\r
   }\r
-  //\r
-  // Fill PRDT table of Command UPIU for executed SCSI cmd.\r
-  //\r
-  PrdtBase = (UTP_TR_PRD*)((UINT8*)TransReq->CmdDescHost + ROUNDUP8 (sizeof (UTP_COMMAND_UPIU)) + ROUNDUP8 (sizeof (UTP_RESPONSE_UPIU)));\r
-  ASSERT (PrdtBase != NULL);\r
-  UfsInitUtpPrdt (PrdtBase, (VOID*)(UINTN)DataBufPhyAddr, DataLen);\r
 \r
   //\r
   // Insert the async SCSI cmd to the Async I/O list\r
   //\r
   if (Event != NULL) {\r
-    OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
-    TransReq->Packet      = Packet;\r
+    OldTpl = gBS->RaiseTPL (TPL_NOTIFY);\r
     TransReq->CallerEvent = Event;\r
     InsertTailList (&Private->Queue, &TransReq->TransferList);\r
     gBS->RestoreTPL (OldTpl);\r
@@ -1533,8 +1556,8 @@ UfsExecScsiCmds (
 \r
   //\r
   // Wait for the completion of the transfer request.\r
-  // \r
-  Status = UfsWaitMemSet (Private, UFS_HC_UTRLDBR_OFFSET, BIT0, 0, Packet->Timeout);\r
+  //\r
+  Status = UfsWaitMemSet (Private, UFS_HC_UTRLDBR_OFFSET, BIT0 << TransReq->Slot, 0, Packet->Timeout);\r
   if (EFI_ERROR (Status)) {\r
     goto Exit;\r
   }\r
@@ -1546,10 +1569,17 @@ UfsExecScsiCmds (
   ASSERT (Response != NULL);\r
   SenseDataLen = Response->SenseDataLen;\r
   SwapLittleEndianToBigEndian ((UINT8*)&SenseDataLen, sizeof (UINT16));\r
-  \r
+\r
   if ((Packet->SenseDataLength != 0) && (Packet->SenseData != NULL)) {\r
-    CopyMem (Packet->SenseData, Response->SenseData, SenseDataLen);\r
-    Packet->SenseDataLength = (UINT8)SenseDataLen;\r
+    //\r
+    // Make sure the hardware device does not return more data than expected.\r
+    //\r
+    if (SenseDataLen <= Packet->SenseDataLength) {\r
+      CopyMem (Packet->SenseData, Response->SenseData, SenseDataLen);\r
+      Packet->SenseDataLength = (UINT8)SenseDataLen;\r
+    } else {\r
+      Packet->SenseDataLength = 0;\r
+    }\r
   }\r
 \r
   //\r
@@ -1557,7 +1587,7 @@ UfsExecScsiCmds (
   //\r
   Packet->TargetStatus = Response->Status;\r
   if (Response->Response != 0) {\r
-    DEBUG ((EFI_D_ERROR, "UfsExecScsiCmds() fails with Target Failure\n"));\r
+    DEBUG ((DEBUG_ERROR, "UfsExecScsiCmds() fails with Target Failure\n"));\r
     Status = EFI_DEVICE_ERROR;\r
     goto Exit;\r
   }\r
@@ -1585,9 +1615,7 @@ Exit:
 \r
   UfsStopExecCmd (Private, TransReq->Slot);\r
 \r
-  if (TransReq->DataBufMapping != NULL) {\r
-    UfsHc->Unmap (UfsHc, TransReq->DataBufMapping);\r
-  }\r
+  UfsReconcileDataTransferBuffer (Private, TransReq);\r
 \r
 Exit1:\r
   if (TransReq->CmdDescMapping != NULL) {\r
@@ -1602,28 +1630,20 @@ Exit1:
   return Status;\r
 }\r
 \r
-\r
 /**\r
-  Sent UIC DME_LINKSTARTUP command to start the link startup procedure.\r
+  Send UIC command.\r
 \r
-  @param[in] Private          The pointer to the UFS_PASS_THRU_PRIVATE_DATA data structure.\r
-  @param[in] UicOpcode        The opcode of the UIC command.\r
-  @param[in] Arg1             The value for 1st argument of the UIC command.\r
-  @param[in] Arg2             The value for 2nd argument of the UIC command.\r
-  @param[in] Arg3             The value for 3rd argument of the UIC command.\r
+  @param[in]      Private     The pointer to the UFS_PASS_THRU_PRIVATE_DATA data structure.\r
+  @param[in, out] UicCommand  UIC command descriptor. On exit contains UIC command results.\r
 \r
   @return EFI_SUCCESS      Successfully execute this UIC command and detect attached UFS device.\r
   @return EFI_DEVICE_ERROR Fail to execute this UIC command and detect attached UFS device.\r
-  @return EFI_NOT_FOUND    The presence of the UFS device isn't detected.\r
 \r
 **/\r
 EFI_STATUS\r
 UfsExecUicCommands (\r
   IN  UFS_PASS_THRU_PRIVATE_DATA    *Private,\r
-  IN  UINT8                         UicOpcode,\r
-  IN  UINT32                        Arg1,\r
-  IN  UINT32                        Arg2,\r
-  IN  UINT32                        Arg3\r
+  IN OUT EDKII_UIC_COMMAND          *UicCommand\r
   )\r
 {\r
   EFI_STATUS  Status;\r
@@ -1649,17 +1669,17 @@ UfsExecUicCommands (
   // only after all the UIC command argument registers (UICCMDARG1, UICCMDARG2 and UICCMDARG3)\r
   // are set.\r
   //\r
-  Status = UfsMmioWrite32 (Private, UFS_HC_UCMD_ARG1_OFFSET, Arg1);\r
+  Status = UfsMmioWrite32 (Private, UFS_HC_UCMD_ARG1_OFFSET, UicCommand->Arg1);\r
   if (EFI_ERROR (Status)) {\r
     return Status;\r
   }\r
 \r
-  Status = UfsMmioWrite32 (Private, UFS_HC_UCMD_ARG2_OFFSET, Arg2);\r
+  Status = UfsMmioWrite32 (Private, UFS_HC_UCMD_ARG2_OFFSET, UicCommand->Arg2);\r
   if (EFI_ERROR (Status)) {\r
     return Status;\r
   }\r
 \r
-  Status = UfsMmioWrite32 (Private, UFS_HC_UCMD_ARG3_OFFSET, Arg3);\r
+  Status = UfsMmioWrite32 (Private, UFS_HC_UCMD_ARG3_OFFSET, UicCommand->Arg3);\r
   if (EFI_ERROR (Status)) {\r
     return Status;\r
   }\r
@@ -1672,51 +1692,37 @@ UfsExecUicCommands (
     return Status;\r
   }\r
 \r
-  Status = UfsMmioWrite32 (Private, UFS_HC_UIC_CMD_OFFSET, (UINT32)UicOpcode);\r
+  Status = UfsMmioWrite32 (Private, UFS_HC_UIC_CMD_OFFSET, UicCommand->Opcode);\r
   if (EFI_ERROR (Status)) {\r
     return Status;\r
   }\r
 \r
   //\r
   // UFS 2.0 spec section 5.3.1 Offset:0x20 IS.Bit10 UIC Command Completion Status (UCCS)\r
-  // This bit is set to '1' by the host controller upon completion of a UIC command. \r
+  // This bit is set to '1' by the host controller upon completion of a UIC command.\r
   //\r
   Status  = UfsWaitMemSet (Private, UFS_HC_IS_OFFSET, UFS_HC_IS_UCCS, UFS_HC_IS_UCCS, UFS_TIMEOUT);\r
   if (EFI_ERROR (Status)) {\r
     return Status;\r
   }\r
 \r
-  if (UicOpcode != UfsUicDmeReset) {\r
-    Status = UfsMmioRead32 (Private, UFS_HC_UCMD_ARG2_OFFSET, &Data);\r
+  if (UicCommand->Opcode != UfsUicDmeReset) {\r
+    Status = UfsMmioRead32 (Private, UFS_HC_UCMD_ARG2_OFFSET, &UicCommand->Arg2);\r
+    if (EFI_ERROR (Status)) {\r
+      return Status;\r
+    }\r
+    Status = UfsMmioRead32 (Private, UFS_HC_UCMD_ARG3_OFFSET, &UicCommand->Arg3);\r
     if (EFI_ERROR (Status)) {\r
       return Status;\r
     }\r
-    if ((Data & 0xFF) != 0) {\r
+    if ((UicCommand->Arg2 & 0xFF) != 0) {\r
       DEBUG_CODE_BEGIN();\r
-        DumpUicCmdExecResult (UicOpcode, (UINT8)(Data & 0xFF));\r
+        DumpUicCmdExecResult ((UINT8)UicCommand->Opcode, (UINT8)(UicCommand->Arg2 & 0xFF));\r
       DEBUG_CODE_END();\r
       return EFI_DEVICE_ERROR;\r
     }\r
   }\r
 \r
-  //\r
-  // Check value of HCS.DP and make sure that there is a device attached to the Link.\r
-  //\r
-  Status = UfsMmioRead32 (Private, UFS_HC_STATUS_OFFSET, &Data);\r
-  if (EFI_ERROR (Status)) {\r
-    return Status;\r
-  }\r
-\r
-  if ((Data & UFS_HC_HCS_DP) == 0) {\r
-    Status  = UfsWaitMemSet (Private, UFS_HC_IS_OFFSET, UFS_HC_IS_ULSS, UFS_HC_IS_ULSS, UFS_TIMEOUT);\r
-    if (EFI_ERROR (Status)) {\r
-      return EFI_DEVICE_ERROR;\r
-    }\r
-    return EFI_NOT_FOUND;\r
-  }\r
-\r
-  DEBUG ((EFI_D_INFO, "UfsPassThruDxe: found a attached UFS device\n"));\r
-\r
   return EFI_SUCCESS;\r
 }\r
 \r
@@ -1748,10 +1754,10 @@ UfsAllocateAlignCommonBuffer (
   BOOLEAN                              Is32BitAddr;\r
   EDKII_UFS_HOST_CONTROLLER_PROTOCOL   *UfsHc;\r
 \r
-  if ((Private->Capabilities & UFS_HC_CAP_64ADDR) == UFS_HC_CAP_64ADDR) {\r
-    Is32BitAddr = TRUE;\r
-  } else {\r
+  if ((Private->UfsHcInfo.Capabilities & UFS_HC_CAP_64ADDR) == UFS_HC_CAP_64ADDR) {\r
     Is32BitAddr = FALSE;\r
+  } else {\r
+    Is32BitAddr = TRUE;\r
   }\r
 \r
   UfsHc  = Private->UfsHostController;\r
@@ -1890,31 +1896,41 @@ UfsDeviceDetection (
   IN  UFS_PASS_THRU_PRIVATE_DATA     *Private\r
   )\r
 {\r
-  UINTN                  Retry;\r
-  EFI_STATUS             Status;\r
+  UINTN              Retry;\r
+  EFI_STATUS         Status;\r
+  UINT32             Data;\r
+  EDKII_UIC_COMMAND  LinkStartupCommand;\r
 \r
   //\r
   // Start UFS device detection.\r
   // Try up to 3 times for establishing data link with device.\r
   //\r
   for (Retry = 0; Retry < 3; Retry++) {\r
-    Status = UfsExecUicCommands (Private, UfsUicDmeLinkStartup, 0, 0, 0);\r
-    if (!EFI_ERROR (Status)) {\r
-      break;\r
+    LinkStartupCommand.Opcode = UfsUicDmeLinkStartup;\r
+    LinkStartupCommand.Arg1 = 0;\r
+    LinkStartupCommand.Arg2 = 0;\r
+    LinkStartupCommand.Arg3 = 0;\r
+    Status = UfsExecUicCommands (Private, &LinkStartupCommand);\r
+    if (EFI_ERROR (Status)) {\r
+      return EFI_DEVICE_ERROR;\r
     }\r
 \r
-    if (Status == EFI_NOT_FOUND) {\r
-      continue;\r
+    Status = UfsMmioRead32 (Private, UFS_HC_STATUS_OFFSET, &Data);\r
+    if (EFI_ERROR (Status)) {\r
+      return EFI_DEVICE_ERROR;\r
     }\r
 \r
-    return EFI_DEVICE_ERROR;\r
-  }\r
-\r
-  if (Retry == 3) {\r
-    return EFI_NOT_FOUND;\r
+    if ((Data & UFS_HC_HCS_DP) == 0) {\r
+      Status = UfsWaitMemSet (Private, UFS_HC_IS_OFFSET, UFS_HC_IS_ULSS, UFS_HC_IS_ULSS, UFS_TIMEOUT);\r
+      if (EFI_ERROR (Status)) {\r
+        return EFI_DEVICE_ERROR;\r
+      }\r
+    } else {\r
+      return EFI_SUCCESS;\r
+    }\r
   }\r
 \r
-  return EFI_SUCCESS;\r
+  return EFI_NOT_FOUND;\r
 }\r
 \r
 /**\r
@@ -1931,13 +1947,12 @@ UfsInitTaskManagementRequestList (
   IN  UFS_PASS_THRU_PRIVATE_DATA     *Private\r
   )\r
 {\r
-  UINT32                 Data;\r
   UINT8                  Nutmrs;\r
   VOID                   *CmdDescHost;\r
   EFI_PHYSICAL_ADDRESS   CmdDescPhyAddr;\r
   VOID                   *CmdDescMapping;\r
   EFI_STATUS             Status;\r
-  \r
+\r
   //\r
   // Initial h/w and s/w context for future operations.\r
   //\r
@@ -1945,17 +1960,10 @@ UfsInitTaskManagementRequestList (
   CmdDescMapping = NULL;\r
   CmdDescPhyAddr = 0;\r
 \r
-  Status = UfsMmioRead32 (Private, UFS_HC_CAP_OFFSET, &Data);\r
-  if (EFI_ERROR (Status)) {\r
-    return Status;\r
-  }\r
-\r
-  Private->Capabilities = Data;\r
-\r
   //\r
   // Allocate and initialize UTP Task Management Request List.\r
   //\r
-  Nutmrs = (UINT8) (RShiftU64 ((Private->Capabilities & UFS_HC_CAP_NUTMRS), 16) + 1);\r
+  Nutmrs = (UINT8) (RShiftU64 ((Private->UfsHcInfo.Capabilities & UFS_HC_CAP_NUTMRS), 16) + 1);\r
   Status = UfsAllocateAlignCommonBuffer (Private, Nutmrs * sizeof (UTP_TMRD), &CmdDescHost, &CmdDescPhyAddr, &CmdDescMapping);\r
   if (EFI_ERROR (Status)) {\r
     return Status;\r
@@ -2004,11 +2012,10 @@ UfsInitTransferRequestList (
   IN  UFS_PASS_THRU_PRIVATE_DATA     *Private\r
   )\r
 {\r
-  UINT32                 Data;\r
   UINT8                  Nutrs;\r
   VOID                   *CmdDescHost;\r
   EFI_PHYSICAL_ADDRESS   CmdDescPhyAddr;\r
-  VOID                   *CmdDescMapping;  \r
+  VOID                   *CmdDescMapping;\r
   EFI_STATUS             Status;\r
 \r
   //\r
@@ -2018,17 +2025,10 @@ UfsInitTransferRequestList (
   CmdDescMapping = NULL;\r
   CmdDescPhyAddr = 0;\r
 \r
-  Status = UfsMmioRead32 (Private, UFS_HC_CAP_OFFSET, &Data);\r
-  if (EFI_ERROR (Status)) {\r
-    return Status;\r
-  }\r
-\r
-  Private->Capabilities = Data;\r
-\r
   //\r
   // Allocate and initialize UTP Transfer Request List.\r
   //\r
-  Nutrs  = (UINT8)((Private->Capabilities & UFS_HC_CAP_NUTRS) + 1);\r
+  Nutrs  = (UINT8)((Private->UfsHcInfo.Capabilities & UFS_HC_CAP_NUTRS) + 1);\r
   Status = UfsAllocateAlignCommonBuffer (Private, Nutrs * sizeof (UTP_TRD), &CmdDescHost, &CmdDescPhyAddr, &CmdDescMapping);\r
   if (EFI_ERROR (Status)) {\r
     return Status;\r
@@ -2049,7 +2049,7 @@ UfsInitTransferRequestList (
   }\r
 \r
   Private->UtpTrlBase = CmdDescHost;\r
-  Private->Nutrs      = Nutrs;  \r
+  Private->Nutrs      = Nutrs;\r
   Private->TrlMapping = CmdDescMapping;\r
 \r
   //\r
@@ -2082,29 +2082,29 @@ UfsControllerInit (
 \r
   Status = UfsEnableHostController (Private);\r
   if (EFI_ERROR (Status)) {\r
-    DEBUG ((EFI_D_ERROR, "UfsControllerInit: Enable Host Controller Fails, Status = %r\n", Status));\r
+    DEBUG ((DEBUG_ERROR, "UfsControllerInit: Enable Host Controller Fails, Status = %r\n", Status));\r
     return Status;\r
   }\r
 \r
   Status = UfsDeviceDetection (Private);\r
   if (EFI_ERROR (Status)) {\r
-    DEBUG ((EFI_D_ERROR, "UfsControllerInit: Device Detection Fails, Status = %r\n", Status));\r
+    DEBUG ((DEBUG_ERROR, "UfsControllerInit: Device Detection Fails, Status = %r\n", Status));\r
     return Status;\r
   }\r
 \r
   Status = UfsInitTaskManagementRequestList (Private);\r
   if (EFI_ERROR (Status)) {\r
-    DEBUG ((EFI_D_ERROR, "UfsControllerInit: Task management list initialization Fails, Status = %r\n", Status));\r
+    DEBUG ((DEBUG_ERROR, "UfsControllerInit: Task management list initialization Fails, Status = %r\n", Status));\r
     return Status;\r
   }\r
 \r
   Status = UfsInitTransferRequestList (Private);\r
   if (EFI_ERROR (Status)) {\r
-    DEBUG ((EFI_D_ERROR, "UfsControllerInit: Transfer list initialization Fails, Status = %r\n", Status));\r
+    DEBUG ((DEBUG_ERROR, "UfsControllerInit: Transfer list initialization Fails, Status = %r\n", Status));\r
     return Status;\r
   }\r
 \r
-  DEBUG ((EFI_D_INFO, "UfsControllerInit Finished\n"));\r
+  DEBUG ((DEBUG_INFO, "UfsControllerInit Finished\n"));\r
   return EFI_SUCCESS;\r
 }\r
 \r
@@ -2165,12 +2165,11 @@ UfsControllerStop (
     return EFI_DEVICE_ERROR;\r
   }\r
 \r
-  DEBUG ((EFI_D_INFO, "UfsController is stopped\n"));\r
+  DEBUG ((DEBUG_INFO, "UfsController is stopped\n"));\r
 \r
   return EFI_SUCCESS;\r
 }\r
 \r
-\r
 /**\r
   Internal helper function which will signal the caller event and clean up\r
   resources.\r
@@ -2202,9 +2201,7 @@ SignalCallerEvent (
 \r
   UfsStopExecCmd (Private, TransReq->Slot);\r
 \r
-  if (TransReq->DataBufMapping != NULL) {\r
-    UfsHc->Unmap (UfsHc, TransReq->DataBufMapping);\r
-  }\r
+  UfsReconcileDataTransferBuffer (Private, TransReq);\r
 \r
   if (TransReq->CmdDescMapping != NULL) {\r
     UfsHc->Unmap (UfsHc, TransReq->CmdDescMapping);\r
@@ -2272,7 +2269,7 @@ ProcessAsyncTaskList (
         // case.\r
         //\r
         Packet->HostAdapterStatus = EFI_EXT_SCSI_STATUS_HOST_ADAPTER_PHASE_ERROR;\r
-        DEBUG ((EFI_D_VERBOSE, "ProcessAsyncTaskList(): Signal Event %p UfsMmioRead32() Error.\n", TransReq->CallerEvent));\r
+        DEBUG ((DEBUG_VERBOSE, "ProcessAsyncTaskList(): Signal Event %p UfsMmioRead32() Error.\n", TransReq->CallerEvent));\r
         SignalCallerEvent (Private, TransReq);\r
         continue;\r
       }\r
@@ -2289,7 +2286,7 @@ ProcessAsyncTaskList (
           // Timeout occurs.\r
           //\r
           Packet->HostAdapterStatus = EFI_EXT_SCSI_STATUS_HOST_ADAPTER_TIMEOUT_COMMAND;\r
-          DEBUG ((EFI_D_VERBOSE, "ProcessAsyncTaskList(): Signal Event %p EFI_TIMEOUT.\n", TransReq->CallerEvent));\r
+          DEBUG ((DEBUG_VERBOSE, "ProcessAsyncTaskList(): Signal Event %p EFI_TIMEOUT.\n", TransReq->CallerEvent));\r
           SignalCallerEvent (Private, TransReq);\r
           continue;\r
         }\r
@@ -2305,8 +2302,15 @@ ProcessAsyncTaskList (
         SwapLittleEndianToBigEndian ((UINT8*)&SenseDataLen, sizeof (UINT16));\r
 \r
         if ((Packet->SenseDataLength != 0) && (Packet->SenseData != NULL)) {\r
-          CopyMem (Packet->SenseData, Response->SenseData, SenseDataLen);\r
-          Packet->SenseDataLength = (UINT8)SenseDataLen;\r
+          //\r
+          // Make sure the hardware device does not return more data than expected.\r
+          //\r
+          if (SenseDataLen <= Packet->SenseDataLength) {\r
+            CopyMem (Packet->SenseData, Response->SenseData, SenseDataLen);\r
+            Packet->SenseDataLength = (UINT8)SenseDataLen;\r
+          } else {\r
+            Packet->SenseDataLength = 0;\r
+          }\r
         }\r
 \r
         //\r
@@ -2314,7 +2318,7 @@ ProcessAsyncTaskList (
         //\r
         Packet->TargetStatus = Response->Status;\r
         if (Response->Response != 0) {\r
-          DEBUG ((EFI_D_VERBOSE, "ProcessAsyncTaskList(): Signal Event %p Target Failure.\n", TransReq->CallerEvent));\r
+          DEBUG ((DEBUG_VERBOSE, "ProcessAsyncTaskList(): Signal Event %p Target Failure.\n", TransReq->CallerEvent));\r
           SignalCallerEvent (Private, TransReq);\r
           continue;\r
         }\r
@@ -2334,15 +2338,48 @@ ProcessAsyncTaskList (
             }\r
           }\r
         } else {\r
-          DEBUG ((EFI_D_VERBOSE, "ProcessAsyncTaskList(): Signal Event %p Target Device Error.\n", TransReq->CallerEvent));\r
+          DEBUG ((DEBUG_VERBOSE, "ProcessAsyncTaskList(): Signal Event %p Target Device Error.\n", TransReq->CallerEvent));\r
           SignalCallerEvent (Private, TransReq);\r
           continue;\r
         }\r
 \r
-        DEBUG ((EFI_D_VERBOSE, "ProcessAsyncTaskList(): Signal Event %p Success.\n", TransReq->CallerEvent));\r
+        DEBUG ((DEBUG_VERBOSE, "ProcessAsyncTaskList(): Signal Event %p Success.\n", TransReq->CallerEvent));\r
         SignalCallerEvent (Private, TransReq);\r
       }\r
     }\r
   }\r
 }\r
 \r
+/**\r
+  Initializes UfsHcInfo field in private data.\r
+\r
+  @param[in] Private  Pointer to host controller private data.\r
+\r
+  @retval EFI_SUCCESS  UfsHcInfo initialized successfully.\r
+  @retval Others       Failed to initalize UfsHcInfo.\r
+**/\r
+EFI_STATUS\r
+GetUfsHcInfo (\r
+  IN UFS_PASS_THRU_PRIVATE_DATA  *Private\r
+  )\r
+{\r
+  UINT32      Data;\r
+  EFI_STATUS  Status;\r
+\r
+  Status = UfsMmioRead32 (Private, UFS_HC_VER_OFFSET, &Data);\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  Private->UfsHcInfo.Version = Data;\r
+\r
+  Status = UfsMmioRead32 (Private, UFS_HC_CAP_OFFSET, &Data);\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  Private->UfsHcInfo.Capabilities = Data;\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r