]> git.proxmox.com Git - mirror_edk2.git/blobdiff - MdeModulePkg/Bus/Ufs/UfsBlockIoPei/UfsHci.c
MdeModulePkg: Replace BSD License with BSD+Patent License
[mirror_edk2.git] / MdeModulePkg / Bus / Ufs / UfsBlockIoPei / UfsHci.c
index 1ef6c8878bf9875e5f882f91d06cbe1835b0945d..e8ef0c2a7aa367049a2c1ab39689addf15ab7e2e 100644 (file)
@@ -1,13 +1,7 @@
 /** @file\r
 \r
-  Copyright (c) 2014 - 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
+  Copyright (c) 2014 - 2018, Intel Corporation. All rights reserved.<BR>\r
+  SPDX-License-Identifier: BSD-2-Clause-Patent\r
 \r
 **/\r
 \r
@@ -108,13 +102,13 @@ DumpUicCmdExecResult (
         break;\r
       case 0x08:\r
         DEBUG ((EFI_D_VERBOSE, "UIC configuration command fails - PEER_COMMUNICATION_FAILURE\n"));\r
-        break; \r
+        break;\r
       case 0x09:\r
         DEBUG ((EFI_D_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
+        break;\r
       default :\r
         ASSERT (FALSE);\r
         break;\r
@@ -125,7 +119,7 @@ DumpUicCmdExecResult (
         break;\r
       case 0x01:\r
         DEBUG ((EFI_D_VERBOSE, "UIC control command fails - FAILURE\n"));\r
-        break;     \r
+        break;\r
       default :\r
         ASSERT (FALSE);\r
         break;\r
@@ -171,7 +165,7 @@ DumpQueryResponseResult (
       break;\r
     case 0xFE:\r
       DEBUG ((EFI_D_VERBOSE, "Query Response with Invalid Opcode\n"));\r
-      break; \r
+      break;\r
     case 0xFF:\r
       DEBUG ((EFI_D_VERBOSE, "Query Response with General Failure\n"));\r
       break;\r
@@ -243,7 +237,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
@@ -407,6 +401,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
@@ -419,6 +416,7 @@ UfsInitQueryRequestUpiu (
   @param[in]  Lun               The Lun on which the SCSI command is executed.\r
   @param[in]  Packet            The pointer to the UFS_SCSI_REQUEST_PACKET data structure.\r
   @param[in]  Trd               The pointer to the UTP Transfer Request Descriptor.\r
+  @param[out] BufferMap         A resulting value, if not NULL, to pass to IoMmuUnmap().\r
 \r
   @retval EFI_SUCCESS           The creation succeed.\r
   @retval EFI_DEVICE_ERROR      The creation failed.\r
@@ -427,10 +425,11 @@ UfsInitQueryRequestUpiu (
 **/\r
 EFI_STATUS\r
 UfsCreateScsiCommandDesc (\r
-  IN  UFS_PEIM_HC_PRIVATE_DATA            *Private,\r
-  IN  UINT8                               Lun,\r
-  IN  UFS_SCSI_REQUEST_PACKET             *Packet,\r
-  IN  UTP_TRD                             *Trd\r
+  IN     UFS_PEIM_HC_PRIVATE_DATA         *Private,\r
+  IN     UINT8                            Lun,\r
+  IN     UFS_SCSI_REQUEST_PACKET          *Packet,\r
+  IN     UTP_TRD                          *Trd,\r
+     OUT VOID                             **BufferMap\r
   )\r
 {\r
   UINT8                    *CommandDesc;\r
@@ -441,21 +440,37 @@ UfsCreateScsiCommandDesc (
   UTP_COMMAND_UPIU         *CommandUpiu;\r
   UTP_TR_PRD               *PrdtBase;\r
   UFS_DATA_DIRECTION       DataDirection;\r
+  EFI_STATUS               Status;\r
+  EDKII_IOMMU_OPERATION    MapOp;\r
+  UINTN                    MapLength;\r
+  EFI_PHYSICAL_ADDRESS     BufferPhyAddr;\r
 \r
   ASSERT ((Private != NULL) && (Packet != NULL) && (Trd != NULL));\r
 \r
+  BufferPhyAddr = 0;\r
+\r
   if (Packet->DataDirection == UfsDataIn) {\r
-    Buffer = Packet->InDataBuffer;\r
-    Length = Packet->InTransferLength;\r
+    Buffer        = Packet->InDataBuffer;\r
+    Length        = Packet->InTransferLength;\r
     DataDirection = UfsDataIn;\r
+    MapOp         = EdkiiIoMmuOperationBusMasterWrite;\r
   } else {\r
     Buffer = Packet->OutDataBuffer;\r
     Length = Packet->OutTransferLength;\r
     DataDirection = UfsDataOut;\r
+    MapOp         = EdkiiIoMmuOperationBusMasterRead;\r
   }\r
 \r
   if (Length == 0) {\r
     DataDirection = UfsNoData;\r
+  } else {\r
+    MapLength = Length;\r
+    Status = IoMmuMap (MapOp, Buffer, &MapLength, &BufferPhyAddr, BufferMap);\r
+\r
+    if (EFI_ERROR (Status) || (MapLength != Length)) {\r
+      DEBUG ((DEBUG_ERROR, "UfsCreateScsiCommandDesc: Fail to map data buffer.\n"));\r
+      return EFI_OUT_OF_RESOURCES;\r
+    }\r
   }\r
 \r
   PrdtNumber = (UINTN)DivU64x32 ((UINT64)Length + UFS_MAX_DATA_LEN_PER_PRD - 1, UFS_MAX_DATA_LEN_PER_PRD);\r
@@ -470,7 +485,7 @@ UfsCreateScsiCommandDesc (
   PrdtBase     = (UTP_TR_PRD*)(CommandDesc + ROUNDUP8 (sizeof (UTP_COMMAND_UPIU)) + ROUNDUP8 (sizeof (UTP_RESPONSE_UPIU)));\r
 \r
   UfsInitCommandUpiu (CommandUpiu, Lun, Private->TaskTag++, Packet->Cdb, Packet->CdbLength, DataDirection, Length);\r
-  UfsInitUtpPrdt (PrdtBase, Buffer, Length);\r
+  UfsInitUtpPrdt (PrdtBase, (VOID*)(UINTN)BufferPhyAddr, Length);\r
 \r
   //\r
   // Fill UTP_TRD associated fields\r
@@ -673,31 +688,7 @@ UfsFindAvailableSlotInTrl (
   return EFI_SUCCESS;\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_PEIM_HC_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_PEIM_HC_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
@@ -710,7 +701,7 @@ VOID
 UfsStartExecCmd (\r
   IN  UFS_PEIM_HC_PRIVATE_DATA     *Private,\r
   IN  UINT8                        Slot\r
-  ) \r
+  )\r
 {\r
   UINTN         UfsHcBase;\r
   UINTN         Address;\r
@@ -718,7 +709,7 @@ UfsStartExecCmd (
 \r
   UfsHcBase = Private->UfsHcBase;\r
 \r
-  Address = UfsHcBase + UFS_HC_UTRLRSR_OFFSET;  \r
+  Address = UfsHcBase + UFS_HC_UTRLRSR_OFFSET;\r
   Data    = MmioRead32 (Address);\r
   if ((Data & UFS_HC_UTRLRSR) != UFS_HC_UTRLRSR) {\r
     MmioWrite32 (Address, UFS_HC_UTRLRSR);\r
@@ -739,7 +730,7 @@ VOID
 UfsStopExecCmd (\r
   IN  UFS_PEIM_HC_PRIVATE_DATA     *Private,\r
   IN  UINT8                        Slot\r
-  ) \r
+  )\r
 {\r
   UINTN         UfsHcBase;\r
   UINTN         Address;\r
@@ -747,10 +738,10 @@ UfsStopExecCmd (
 \r
   UfsHcBase = Private->UfsHcBase;\r
 \r
-  Address = UfsHcBase + UFS_HC_UTRLDBR_OFFSET;  \r
+  Address = UfsHcBase + UFS_HC_UTRLDBR_OFFSET;\r
   Data    = MmioRead32 (Address);\r
   if ((Data & (BIT0 << Slot)) != 0) {\r
-    Address = UfsHcBase + UFS_HC_UTRLCLR_OFFSET;  \r
+    Address = UfsHcBase + UFS_HC_UTRLCLR_OFFSET;\r
     Data    = MmioRead32 (Address);\r
     MmioWrite32 (Address, (Data & ~(BIT0 << Slot)));\r
   }\r
@@ -818,7 +809,7 @@ 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
@@ -842,8 +833,8 @@ UfsRwDeviceDesc (
 \r
   //\r
   // Wait for the completion of the transfer request.\r
-  //  \r
-  Address = Private->UfsHcBase + UFS_HC_UTRLDBR_OFFSET;  \r
+  //\r
+  Address = Private->UfsHcBase + UFS_HC_UTRLDBR_OFFSET;\r
   Status = UfsWaitMemSet (Address, BIT0 << Slot, 0, Packet.Timeout);\r
   if (EFI_ERROR (Status)) {\r
     goto Exit;\r
@@ -860,6 +851,14 @@ UfsRwDeviceDesc (
     SwapLittleEndianToBigEndian ((UINT8*)&ReturnDataSize, sizeof (UINT16));\r
 \r
     if (Read) {\r
+      //\r
+      // Make sure the hardware device does not return more data than expected.\r
+      //\r
+      if (ReturnDataSize > Packet.InTransferLength) {\r
+        Status = EFI_DEVICE_ERROR;\r
+        goto Exit;\r
+      }\r
+\r
       CopyMem (Packet.InDataBuffer, (QueryResp + 1), ReturnDataSize);\r
       Packet.InTransferLength = ReturnDataSize;\r
     } else {\r
@@ -876,113 +875,7 @@ Exit:
   return Status;\r
 }\r
 \r
-/**\r
-  Read or write specified attribute of a UFS device.\r
-\r
-  @param[in]      Private       The pointer to the UFS_PEIM_HC_PRIVATE_DATA data structure.\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] Attributes    The value of Attribute to be read or written.\r
-\r
-  @retval EFI_SUCCESS           The Attribute was read/written successfully.\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
-**/\r
-EFI_STATUS\r
-UfsRwAttributes (\r
-  IN     UFS_PEIM_HC_PRIVATE_DATA     *Private,\r
-  IN     BOOLEAN                      Read,\r
-  IN     UINT8                        AttrId,\r
-  IN     UINT8                        Index,\r
-  IN     UINT8                        Selector,\r
-  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
-  UINTN                                Address;\r
-  UTP_QUERY_RESP_UPIU                  *QueryResp;\r
-  UINT8                                *CmdDescBase;\r
-  UINT32                               CmdDescSize;\r
-  UINT32                               ReturnData;\r
-\r
-  ZeroMem (&Packet, sizeof (UFS_DEVICE_MANAGEMENT_REQUEST_PACKET));\r
-\r
-  if (Read) {\r
-    Packet.DataDirection     = UfsDataIn;\r
-    Packet.Opcode            = UtpQueryFuncOpcodeRdAttr;\r
-  } else {\r
-    Packet.DataDirection     = UfsDataOut;\r
-    Packet.Opcode            = UtpQueryFuncOpcodeWrAttr;\r
-  }\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);\r
-  if (EFI_ERROR (Status)) {\r
-    return Status;\r
-  }\r
-\r
-  //\r
-  // Check the transfer request result.\r
-  //\r
-  CmdDescBase = (UINT8 *)(UINTN)(LShiftU64 ((UINT64)Trd->UcdBaU, 32) | LShiftU64 ((UINT64)Trd->UcdBa, 7));\r
-  QueryResp   = (UTP_QUERY_RESP_UPIU*)(CmdDescBase + Trd->RuO * sizeof (UINT32));\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
-  Address = Private->UfsHcBase + UFS_HC_UTRLDBR_OFFSET;  \r
-  Status = UfsWaitMemSet (Address, BIT0 << Slot, 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
-  UfsStopExecCmd (Private, Slot);\r
-  UfsPeimFreeMem (Private->Pool, CmdDescBase, CmdDescSize);\r
 \r
-  return Status;\r
-}\r
 \r
 /**\r
   Read or write specified flag of a UFS device.\r
@@ -1070,8 +963,8 @@ UfsRwFlags (
 \r
   //\r
   // Wait for the completion of the transfer request.\r
-  //  \r
-  Address = Private->UfsHcBase + UFS_HC_UTRLDBR_OFFSET;  \r
+  //\r
+  Address = Private->UfsHcBase + UFS_HC_UTRLDBR_OFFSET;\r
   Status = UfsWaitMemSet (Address, BIT0 << Slot, 0, Packet.Timeout);\r
   if (EFI_ERROR (Status)) {\r
     goto Exit;\r
@@ -1122,57 +1015,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_PEIM_HC_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_PEIM_HC_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
-\r
-  @param[in]  Private           The pointer to the UFS_PEIM_HC_PRIVATE_DATA data structure.\r
-  @param[in]  FlagId            The ID of flag to be read.\r
-  @param[out] Value             The flag's value.\r
-\r
-  @retval EFI_SUCCESS           The flag was read successfully.\r
-  @retval EFI_DEVICE_ERROR      A device error occurred while attempting to read the flag.\r
-  @retval EFI_TIMEOUT           A timeout occurred while waiting for the completion of reading the flag.\r
-\r
-**/\r
-EFI_STATUS\r
-UfsReadFlag (\r
-  IN     UFS_PEIM_HC_PRIVATE_DATA     *Private,\r
-  IN     UINT8                        FlagId,\r
-     OUT UINT8                        *Value\r
-  )\r
-{\r
-  EFI_STATUS                           Status;\r
-\r
-  Status = UfsRwFlags (Private, TRUE, FlagId, Value);\r
 \r
-  return Status;\r
-}\r
 \r
 /**\r
   Sends NOP IN cmd to a UFS device for initialization process request.\r
@@ -1228,8 +1071,8 @@ UfsExecNopCmds (
 \r
   //\r
   // Wait for the completion of the transfer request.\r
-  //  \r
-  Address = Private->UfsHcBase + UFS_HC_UTRLDBR_OFFSET;  \r
+  //\r
+  Address = Private->UfsHcBase + UFS_HC_UTRLDBR_OFFSET;\r
   Status = UfsWaitMemSet (Address, BIT0 << Slot, 0, UFS_TIMEOUT);\r
   if (EFI_ERROR (Status)) {\r
     goto Exit;\r
@@ -1283,6 +1126,7 @@ UfsExecScsiCmds (
   UTP_RESPONSE_UPIU                    *Response;\r
   UINT16                               SenseDataLen;\r
   UINT32                               ResTranCount;\r
+  VOID                                 *PacketBufferMap;\r
 \r
   //\r
   // Find out which slot of transfer request list is available.\r
@@ -1293,11 +1137,12 @@ UfsExecScsiCmds (
   }\r
 \r
   Trd = ((UTP_TRD*)Private->UtpTrlBase) + Slot;\r
+  PacketBufferMap = NULL;\r
 \r
   //\r
   // Fill transfer request descriptor to this slot.\r
   //\r
-  Status = UfsCreateScsiCommandDesc (Private, Lun, Packet, Trd);\r
+  Status = UfsCreateScsiCommandDesc (Private, Lun, Packet, Trd, &PacketBufferMap);\r
   if (EFI_ERROR (Status)) {\r
     return Status;\r
   }\r
@@ -1312,8 +1157,8 @@ UfsExecScsiCmds (
 \r
   //\r
   // Wait for the completion of the transfer request.\r
-  //  \r
-  Address = Private->UfsHcBase + UFS_HC_UTRLDBR_OFFSET;  \r
+  //\r
+  Address = Private->UfsHcBase + UFS_HC_UTRLDBR_OFFSET;\r
   Status = UfsWaitMemSet (Address, BIT0 << Slot, 0, Packet->Timeout);\r
   if (EFI_ERROR (Status)) {\r
     goto Exit;\r
@@ -1325,10 +1170,17 @@ UfsExecScsiCmds (
   Response     = (UTP_RESPONSE_UPIU*)(CmdDescBase + Trd->RuO * sizeof (UINT32));\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
@@ -1359,6 +1211,9 @@ UfsExecScsiCmds (
   }\r
 \r
 Exit:\r
+  if (PacketBufferMap != NULL) {\r
+    IoMmuUnmap (PacketBufferMap);\r
+  }\r
   UfsStopExecCmd (Private, Slot);\r
   UfsPeimFreeMem (Private->Pool, CmdDescBase, CmdDescSize);\r
 \r
@@ -1432,7 +1287,7 @@ UfsExecUicCommands (
 \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
   Address = UfsHcBase + UFS_HC_IS_OFFSET;\r
   Data    = MmioRead32 (Address);\r
@@ -1455,7 +1310,7 @@ UfsExecUicCommands (
   //\r
   // Check value of HCS.DP and make sure that there is a device attached to the Link.\r
   //\r
-  Address = UfsHcBase + UFS_HC_STATUS_OFFSET;  \r
+  Address = UfsHcBase + UFS_HC_STATUS_OFFSET;\r
   Data    = MmioRead32 (Address);\r
   if ((Data & UFS_HC_HCS_DP) == 0) {\r
     Address = UfsHcBase + UFS_HC_IS_OFFSET;\r
@@ -1584,13 +1439,15 @@ UfsInitTaskManagementRequestList (
   UINTN                  Address;\r
   UINT32                 Data;\r
   UINT8                  Nutmrs;\r
-  EFI_PHYSICAL_ADDRESS   Buffer;\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
-  Address = Private->UfsHcBase + UFS_HC_CAP_OFFSET;  \r
+  Address = Private->UfsHcBase + UFS_HC_CAP_OFFSET;\r
   Data    = MmioRead32 (Address);\r
   Private->Capabilities = Data;\r
 \r
@@ -1598,34 +1455,35 @@ UfsInitTaskManagementRequestList (
   // Allocate and initialize UTP Task Management Request List.\r
   //\r
   Nutmrs = (UINT8) (RShiftU64 ((Private->Capabilities & UFS_HC_CAP_NUTMRS), 16) + 1);\r
-  Status = PeiServicesAllocatePages (\r
-             EfiBootServicesCode,\r
+  Status = IoMmuAllocateBuffer (\r
              EFI_SIZE_TO_PAGES (Nutmrs * sizeof (UTP_TMRD)),\r
-             &Buffer\r
+             &CmdDescHost,\r
+             &CmdDescPhyAddr,\r
+             &CmdDescMapping\r
              );\r
-\r
   if (EFI_ERROR (Status)) {\r
     return EFI_DEVICE_ERROR;\r
   }\r
 \r
-  ZeroMem ((VOID*)(UINTN)Buffer, EFI_PAGES_TO_SIZE (EFI_SIZE_TO_PAGES (Nutmrs * sizeof (UTP_TMRD))));\r
+  ZeroMem (CmdDescHost, EFI_PAGES_TO_SIZE (EFI_SIZE_TO_PAGES (Nutmrs * sizeof (UTP_TMRD))));\r
 \r
   //\r
   // Program the UTP Task Management Request List Base Address and UTP Task Management\r
   // Request List Base Address with a 64-bit address allocated at step 6.\r
   //\r
-  Address = Private->UfsHcBase + UFS_HC_UTMRLBA_OFFSET;  \r
-  MmioWrite32 (Address, (UINT32)(UINTN)Buffer);\r
-  Address = Private->UfsHcBase + UFS_HC_UTMRLBAU_OFFSET;  \r
-  MmioWrite32 (Address, (UINT32)RShiftU64 ((UINT64)Buffer, 32));\r
-  Private->UtpTmrlBase = (VOID*)(UINTN)Buffer;\r
+  Address = Private->UfsHcBase + UFS_HC_UTMRLBA_OFFSET;\r
+  MmioWrite32 (Address, (UINT32)(UINTN)CmdDescPhyAddr);\r
+  Address = Private->UfsHcBase + UFS_HC_UTMRLBAU_OFFSET;\r
+  MmioWrite32 (Address, (UINT32)RShiftU64 ((UINT64)CmdDescPhyAddr, 32));\r
+  Private->UtpTmrlBase = (VOID*)(UINTN)CmdDescHost;\r
   Private->Nutmrs      = Nutmrs;\r
+  Private->TmrlMapping = CmdDescMapping;\r
 \r
   //\r
   // Enable the UTP Task Management Request List by setting the UTP Task Management\r
   // Request List RunStop Register (UTMRLRSR) to '1'.\r
   //\r
-  Address = Private->UfsHcBase + UFS_HC_UTMRLRSR_OFFSET;  \r
+  Address = Private->UfsHcBase + UFS_HC_UTMRLRSR_OFFSET;\r
   MmioWrite32 (Address, UFS_HC_UTMRLRSR);\r
 \r
   return EFI_SUCCESS;\r
@@ -1648,13 +1506,15 @@ UfsInitTransferRequestList (
   UINTN                  Address;\r
   UINT32                 Data;\r
   UINT8                  Nutrs;\r
-  EFI_PHYSICAL_ADDRESS   Buffer;\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
-  Address = Private->UfsHcBase + UFS_HC_CAP_OFFSET;  \r
+  Address = Private->UfsHcBase + UFS_HC_CAP_OFFSET;\r
   Data    = MmioRead32 (Address);\r
   Private->Capabilities = Data;\r
 \r
@@ -1662,34 +1522,35 @@ UfsInitTransferRequestList (
   // Allocate and initialize UTP Transfer Request List.\r
   //\r
   Nutrs  = (UINT8)((Private->Capabilities & UFS_HC_CAP_NUTRS) + 1);\r
-  Status = PeiServicesAllocatePages (\r
-             EfiBootServicesCode,\r
+  Status = IoMmuAllocateBuffer (\r
              EFI_SIZE_TO_PAGES (Nutrs * sizeof (UTP_TRD)),\r
-             &Buffer\r
+             &CmdDescHost,\r
+             &CmdDescPhyAddr,\r
+             &CmdDescMapping\r
              );\r
-\r
   if (EFI_ERROR (Status)) {\r
     return EFI_DEVICE_ERROR;\r
   }\r
 \r
-  ZeroMem ((VOID*)(UINTN)Buffer, EFI_PAGES_TO_SIZE (EFI_SIZE_TO_PAGES (Nutrs * sizeof (UTP_TRD))));\r
+  ZeroMem (CmdDescHost, EFI_PAGES_TO_SIZE (EFI_SIZE_TO_PAGES (Nutrs * sizeof (UTP_TRD))));\r
 \r
   //\r
   // Program the UTP Transfer Request List Base Address and UTP Transfer Request List\r
   // Base Address with a 64-bit address allocated at step 8.\r
   //\r
-  Address = Private->UfsHcBase + UFS_HC_UTRLBA_OFFSET;  \r
-  MmioWrite32 (Address, (UINT32)(UINTN)Buffer);\r
-  Address = Private->UfsHcBase + UFS_HC_UTRLBAU_OFFSET;  \r
-  MmioWrite32 (Address, (UINT32)RShiftU64 ((UINT64)Buffer, 32));\r
-  Private->UtpTrlBase = (VOID*)(UINTN)Buffer;\r
+  Address = Private->UfsHcBase + UFS_HC_UTRLBA_OFFSET;\r
+  MmioWrite32 (Address, (UINT32)(UINTN)CmdDescPhyAddr);\r
+  Address = Private->UfsHcBase + UFS_HC_UTRLBAU_OFFSET;\r
+  MmioWrite32 (Address, (UINT32)RShiftU64 ((UINT64)CmdDescPhyAddr, 32));\r
+  Private->UtpTrlBase = (VOID*)(UINTN)CmdDescHost;\r
   Private->Nutrs      = Nutrs;\r
-  \r
+  Private->TrlMapping = CmdDescMapping;\r
+\r
   //\r
   // Enable the UTP Transfer Request List by setting the UTP Transfer Request List\r
   // RunStop Register (UTRLRSR) to '1'.\r
   //\r
-  Address = Private->UfsHcBase + UFS_HC_UTRLRSR_OFFSET;  \r
+  Address = Private->UfsHcBase + UFS_HC_UTRLRSR_OFFSET;\r
   MmioWrite32 (Address, UFS_HC_UTRLRSR);\r
 \r
   return EFI_SUCCESS;\r
@@ -1732,6 +1593,16 @@ UfsControllerInit (
   Status = UfsInitTransferRequestList (Private);\r
   if (EFI_ERROR (Status)) {\r
     DEBUG ((EFI_D_ERROR, "UfsDevicePei: Transfer list initialization Fails, Status = %r\n", Status));\r
+\r
+    if (Private->TmrlMapping != NULL) {\r
+      IoMmuFreeBuffer (\r
+        EFI_SIZE_TO_PAGES (Private->Nutmrs * sizeof (UTP_TMRD)),\r
+        Private->UtpTmrlBase,\r
+        Private->TmrlMapping\r
+        );\r
+      Private->TmrlMapping = NULL;\r
+    }\r
+\r
     return Status;\r
   }\r
 \r
@@ -1761,14 +1632,14 @@ UfsControllerStop (
   // Enable the UTP Task Management Request List by setting the UTP Task Management\r
   // Request List RunStop Register (UTMRLRSR) to '1'.\r
   //\r
-  Address = Private->UfsHcBase + UFS_HC_UTMRLRSR_OFFSET;  \r
+  Address = Private->UfsHcBase + UFS_HC_UTMRLRSR_OFFSET;\r
   MmioWrite32 (Address, 0);\r
 \r
   //\r
   // Enable the UTP Transfer Request List by setting the UTP Transfer Request List\r
   // RunStop Register (UTRLRSR) to '1'.\r
   //\r
-  Address = Private->UfsHcBase + UFS_HC_UTRLRSR_OFFSET;  \r
+  Address = Private->UfsHcBase + UFS_HC_UTRLRSR_OFFSET;\r
   MmioWrite32 (Address, 0);\r
 \r
   //\r