]> git.proxmox.com Git - mirror_edk2.git/blobdiff - SourceLevelDebugPkg/Library/DebugCommunicationLibUsb3/DebugCommunicationLibUsb3Transfer.c
UefiCpuPkg: Move AsmRelocateApLoopStart from Mpfuncs.nasm to AmdSev.nasm
[mirror_edk2.git] / SourceLevelDebugPkg / Library / DebugCommunicationLibUsb3 / DebugCommunicationLibUsb3Transfer.c
index dbff493624077f88655be0a9a529ad7d50d38d45..a651e8827112fe85fa0eea6a8e671398006734fa 100644 (file)
@@ -1,14 +1,8 @@
 /** @file\r
   Debug Port Library implementation based on usb3 debug port.\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 - 2018, Intel Corporation. All rights reserved.<BR>\r
+  SPDX-License-Identifier: BSD-2-Clause-Patent\r
 \r
 **/\r
 #include "DebugCommunicationLibUsb3Internal.h"\r
 EFI_STATUS\r
 EFIAPI\r
 XhcSyncTrsRing (\r
-  IN USB3_DEBUG_PORT_HANDLE    *Handle,\r
-  IN TRANSFER_RING             *TrsRing\r
+  IN USB3_DEBUG_PORT_HANDLE  *Handle,\r
+  IN TRANSFER_RING           *TrsRing\r
   )\r
 {\r
-  UINTN               Index;\r
-  TRB_TEMPLATE        *TrsTrb;\r
-  UINT32              CycleBit;\r
+  UINTN         Index;\r
+  TRB_TEMPLATE  *TrsTrb;\r
+  UINT32        CycleBit;\r
 \r
   ASSERT (TrsRing != NULL);\r
 \r
   //\r
   // Calculate the latest RingEnqueue and RingPCS\r
   //\r
-  TrsTrb = (TRB_TEMPLATE *)(UINTN) TrsRing->RingEnqueue;\r
+  TrsTrb = (TRB_TEMPLATE *)(UINTN)TrsRing->RingEnqueue;\r
 \r
   ASSERT (TrsTrb != NULL);\r
-  \r
+\r
   for (Index = 0; Index < TrsRing->TrbNumber; Index++) {\r
     if (TrsTrb->CycleBit != (TrsRing->RingPCS & BIT0)) {\r
       break;\r
     }\r
+\r
     TrsTrb++;\r
-    if ((UINT8) TrsTrb->Type == TRB_TYPE_LINK) {\r
-      ASSERT (((LINK_TRB*)TrsTrb)->TC != 0);\r
+    if ((UINT8)TrsTrb->Type == TRB_TYPE_LINK) {\r
+      ASSERT (((LINK_TRB *)TrsTrb)->TC != 0);\r
       //\r
       // set cycle bit in Link TRB as normal\r
       //\r
-      ((LINK_TRB*)TrsTrb)->CycleBit = TrsRing->RingPCS & BIT0;\r
+      ((LINK_TRB *)TrsTrb)->CycleBit = TrsRing->RingPCS & BIT0;\r
       //\r
       // Toggle PCS maintained by software\r
       //\r
@@ -60,10 +55,11 @@ XhcSyncTrsRing (
       TrsTrb           = (TRB_TEMPLATE *)(UINTN)((TrsTrb->Parameter1 | LShiftU64 ((UINT64)TrsTrb->Parameter2, 32)) & ~0x0F);\r
     }\r
   }\r
+\r
   ASSERT (Index != TrsRing->TrbNumber);\r
 \r
-  if ((EFI_PHYSICAL_ADDRESS)(UINTN) TrsTrb != TrsRing->RingEnqueue) {\r
-    TrsRing->RingEnqueue = (EFI_PHYSICAL_ADDRESS)(UINTN) TrsTrb;\r
+  if ((EFI_PHYSICAL_ADDRESS)(UINTN)TrsTrb != TrsRing->RingEnqueue) {\r
+    TrsRing->RingEnqueue = (EFI_PHYSICAL_ADDRESS)(UINTN)TrsTrb;\r
   }\r
 \r
   //\r
@@ -89,11 +85,11 @@ EFI_STATUS
 EFIAPI\r
 XhcSyncEventRing (\r
   IN USB3_DEBUG_PORT_HANDLE  *Handle,\r
-  IN EVENT_RING                *EvtRing\r
+  IN EVENT_RING              *EvtRing\r
   )\r
 {\r
-  UINTN               Index;\r
-  TRB_TEMPLATE        *EvtTrb1;\r
+  UINTN         Index;\r
+  TRB_TEMPLATE  *EvtTrb1;\r
 \r
   ASSERT (EvtRing != NULL);\r
 \r
@@ -101,7 +97,7 @@ XhcSyncEventRing (
   // Calculate the EventRingEnqueue and EventRingCCS.\r
   // Note: only support single Segment\r
   //\r
-  EvtTrb1 = (TRB_TEMPLATE *)(UINTN) EvtRing->EventRingDequeue;\r
+  EvtTrb1 = (TRB_TEMPLATE *)(UINTN)EvtRing->EventRingDequeue;\r
 \r
   for (Index = 0; Index < EvtRing->TrbNumber; Index++) {\r
     if (EvtTrb1->CycleBit != EvtRing->EventRingCCS) {\r
@@ -110,8 +106,8 @@ XhcSyncEventRing (
 \r
     EvtTrb1++;\r
 \r
-    if ((UINTN)EvtTrb1 >= ((UINTN) EvtRing->EventRingSeg0 + sizeof (TRB_TEMPLATE) * EvtRing->TrbNumber)) {\r
-      EvtTrb1 = (TRB_TEMPLATE *)(UINTN) EvtRing->EventRingSeg0;\r
+    if ((UINTN)EvtTrb1 >= ((UINTN)EvtRing->EventRingSeg0 + sizeof (TRB_TEMPLATE) * EvtRing->TrbNumber)) {\r
+      EvtTrb1               = (TRB_TEMPLATE *)(UINTN)EvtRing->EventRingSeg0;\r
       EvtRing->EventRingCCS = (EvtRing->EventRingCCS) ? 0 : 1;\r
     }\r
   }\r
@@ -139,18 +135,16 @@ XhcSyncEventRing (
 EFI_STATUS\r
 EFIAPI\r
 XhcCheckNewEvent (\r
-  IN  USB3_DEBUG_PORT_HANDLE   *Handle,\r
-  IN  EVENT_RING               *EvtRing,\r
-  OUT TRB_TEMPLATE             **NewEvtTrb\r
+  IN  USB3_DEBUG_PORT_HANDLE  *Handle,\r
+  IN  EVENT_RING              *EvtRing,\r
+  OUT TRB_TEMPLATE            **NewEvtTrb\r
   )\r
 {\r
-  EFI_STATUS          Status;\r
-  TRB_TEMPLATE        *EvtTrb;\r
+  EFI_STATUS  Status;\r
 \r
   ASSERT (EvtRing != NULL);\r
 \r
-  EvtTrb     = (TRB_TEMPLATE *)(UINTN) EvtRing->EventRingDequeue;\r
-  *NewEvtTrb = (TRB_TEMPLATE *)(UINTN) EvtRing->EventRingDequeue;\r
+  *NewEvtTrb = (TRB_TEMPLATE *)(UINTN)EvtRing->EventRingDequeue;\r
 \r
   if (EvtRing->EventRingDequeue == EvtRing->EventRingEnqueue) {\r
     return EFI_NOT_READY;\r
@@ -160,9 +154,9 @@ XhcCheckNewEvent (
 \r
   EvtRing->EventRingDequeue += sizeof (TRB_TEMPLATE);\r
   //\r
-  // If the dequeue pointer is beyond the ring, then roll-back it to the begining of the ring.\r
+  // If the dequeue pointer is beyond the ring, then roll-back it to the beginning of the ring.\r
   //\r
-  if ((UINTN)EvtRing->EventRingDequeue >= ((UINTN) EvtRing->EventRingSeg0 + sizeof (TRB_TEMPLATE) * EvtRing->TrbNumber)) {\r
+  if ((UINTN)EvtRing->EventRingDequeue >= ((UINTN)EvtRing->EventRingSeg0 + sizeof (TRB_TEMPLATE) * EvtRing->TrbNumber)) {\r
     EvtRing->EventRingDequeue = EvtRing->EventRingSeg0;\r
   }\r
 \r
@@ -181,21 +175,22 @@ XhcCheckNewEvent (
 **/\r
 BOOLEAN\r
 IsTrbInTrsRing (\r
-  IN  TRANSFER_RING       *Ring,\r
-  IN  TRB_TEMPLATE        *Trb\r
+  IN  TRANSFER_RING  *Ring,\r
+  IN  TRB_TEMPLATE   *Trb\r
   )\r
 {\r
   TRB_TEMPLATE  *CheckedTrb;\r
   UINTN         Index;\r
-  \r
-  CheckedTrb = (TRB_TEMPLATE *)(UINTN) Ring->RingSeg0;\r
-  \r
+\r
+  CheckedTrb = (TRB_TEMPLATE *)(UINTN)Ring->RingSeg0;\r
+\r
   ASSERT (Ring->TrbNumber == TR_RING_TRB_NUMBER);\r
 \r
   for (Index = 0; Index < Ring->TrbNumber; Index++) {\r
     if (Trb == CheckedTrb) {\r
       return TRUE;\r
     }\r
+\r
     CheckedTrb++;\r
   }\r
 \r
@@ -212,19 +207,19 @@ IsTrbInTrsRing (
 **/\r
 VOID\r
 XhcCheckUrbResult (\r
-  IN  USB3_DEBUG_PORT_HANDLE *Handle,\r
-  IN  URB                      *Urb\r
+  IN  USB3_DEBUG_PORT_HANDLE  *Handle,\r
+  IN  URB                     *Urb\r
   )\r
 {\r
-  EVT_TRB_TRANSFER        *EvtTrb;\r
-  TRB_TEMPLATE            *TRBPtr;\r
-  UINTN                   Index;\r
-  EFI_STATUS              Status;\r
-  URB                     *CheckedUrb;\r
-  UINT64                  XhcDequeue;\r
-  UINT32                  High;\r
-  UINT32                  Low;\r
-  \r
+  EVT_TRB_TRANSFER  *EvtTrb;\r
+  TRB_TEMPLATE      *TRBPtr;\r
+  UINTN             Index;\r
+  EFI_STATUS        Status;\r
+  URB               *CheckedUrb;\r
+  UINT64            XhcDequeue;\r
+  UINT32            High;\r
+  UINT32            Low;\r
+\r
   ASSERT ((Handle != NULL) && (Urb != NULL));\r
 \r
   if (Urb->Finished) {\r
@@ -232,14 +227,13 @@ XhcCheckUrbResult (
   }\r
 \r
   EvtTrb = NULL;\r
-  \r
+\r
   //\r
   // Traverse the event ring to find out all new events from the previous check.\r
   //\r
   XhcSyncEventRing (Handle, &Handle->EventRing);\r
-  \r
-  for (Index = 0; Index < Handle->EventRing.TrbNumber; Index++) {\r
 \r
+  for (Index = 0; Index < Handle->EventRing.TrbNumber; Index++) {\r
     Status = XhcCheckNewEvent (Handle, &Handle->EventRing, ((TRB_TEMPLATE **)&EvtTrb));\r
     if (Status == EFI_NOT_READY) {\r
       //\r
@@ -247,13 +241,13 @@ XhcCheckUrbResult (
       //\r
       goto EXIT;\r
     }\r
-    \r
+\r
     if ((EvtTrb->Type != TRB_TYPE_COMMAND_COMPLT_EVENT) && (EvtTrb->Type != TRB_TYPE_TRANS_EVENT)) {\r
       continue;\r
     }\r
-    \r
-    TRBPtr = (TRB_TEMPLATE *)(UINTN)(EvtTrb->TRBPtrLo | LShiftU64 ((UINT64) EvtTrb->TRBPtrHi, 32));\r
-    \r
+\r
+    TRBPtr = (TRB_TEMPLATE *)(UINTN)(EvtTrb->TRBPtrLo | LShiftU64 ((UINT64)EvtTrb->TRBPtrHi, 32));\r
+\r
     if (IsTrbInTrsRing ((TRANSFER_RING *)(UINTN)(Urb->Ring), TRBPtr)) {\r
       CheckedUrb = Urb;\r
     } else if (IsTrbInTrsRing ((TRANSFER_RING *)(UINTN)(Handle->UrbIn.Ring), TRBPtr)) {\r
@@ -261,7 +255,7 @@ XhcCheckUrbResult (
       // If it is read event and it should be generated by poll, and current operation is write, we need save data into internal buffer.\r
       // Internal buffer is used by next read.\r
       //\r
-      Handle->DataCount = (UINT8) (Handle->UrbIn.DataLen - EvtTrb->Length);\r
+      Handle->DataCount = (UINT8)(Handle->UrbIn.DataLen - EvtTrb->Length);\r
       CopyMem ((VOID *)(UINTN)Handle->Data, (VOID *)(UINTN)Handle->UrbIn.Data, Handle->DataCount);\r
       //\r
       // Fill this TRB complete with CycleBit, otherwise next read will fail with old TRB.\r
@@ -271,16 +265,18 @@ XhcCheckUrbResult (
     } else {\r
       continue;\r
     }\r
-    \r
+\r
     if ((EvtTrb->Completecode == TRB_COMPLETION_SHORT_PACKET) ||\r
-        (EvtTrb->Completecode == TRB_COMPLETION_SUCCESS)) {\r
+        (EvtTrb->Completecode == TRB_COMPLETION_SUCCESS))\r
+    {\r
       //\r
       // The length of data which were transferred.\r
       //\r
-      CheckedUrb->Completed += (((TRANSFER_TRB_NORMAL*)TRBPtr)->Length - EvtTrb->Length);\r
+      CheckedUrb->Completed += (((TRANSFER_TRB_NORMAL *)TRBPtr)->Length - EvtTrb->Length);\r
     } else {\r
-      CheckedUrb->Result  |= EFI_USB_ERR_TIMEOUT;\r
+      CheckedUrb->Result |= EFI_USB_ERR_TIMEOUT;\r
     }\r
+\r
     //\r
     // This Urb has been processed\r
     //\r
@@ -294,9 +290,9 @@ EXIT:
   // Some 3rd party XHCI external cards don't support single 64-bytes width register access,\r
   // So divide it to two 32-bytes width register access.\r
   //\r
-  Low  = XhcReadDebugReg (Handle, XHC_DC_DCERDP);\r
-  High = XhcReadDebugReg (Handle, XHC_DC_DCERDP + 4);\r
-  XhcDequeue = (UINT64)(LShiftU64((UINT64)High, 32) | Low);\r
+  Low        = XhcReadDebugReg (Handle, XHC_DC_DCERDP);\r
+  High       = XhcReadDebugReg (Handle, XHC_DC_DCERDP + 4);\r
+  XhcDequeue = (UINT64)(LShiftU64 ((UINT64)High, 32) | Low);\r
 \r
   if ((XhcDequeue & (~0x0F)) != ((UINT64)(UINTN)Handle->EventRing.EventRingDequeue & (~0x0F))) {\r
     //\r
@@ -320,17 +316,17 @@ EXIT:
 EFI_STATUS\r
 EFIAPI\r
 XhcRingDoorBell (\r
-  IN USB3_DEBUG_PORT_HANDLE    *Handle,\r
-  IN URB                       *Urb\r
+  IN USB3_DEBUG_PORT_HANDLE  *Handle,\r
+  IN URB                     *Urb\r
   )\r
 {\r
-  UINT32      Dcdb;\r
+  UINT32  Dcdb;\r
 \r
   //\r
   // 7.6.8.2 DCDB Register\r
-  //  \r
+  //\r
   Dcdb = (Urb->Direction == EfiUsbDataIn) ? 0x100 : 0x0;\r
-  \r
+\r
   XhcWriteDebugReg (\r
     Handle,\r
     XHC_DC_DCDB,\r
@@ -350,20 +346,21 @@ XhcRingDoorBell (
 **/\r
 VOID\r
 XhcExecTransfer (\r
-  IN  USB3_DEBUG_PORT_HANDLE   *Handle,\r
-  IN  URB                      *Urb,\r
-  IN  UINTN                    Timeout\r
+  IN  USB3_DEBUG_PORT_HANDLE  *Handle,\r
+  IN  URB                     *Urb,\r
+  IN  UINTN                   Timeout\r
   )\r
 {\r
-  TRANSFER_RING           *Ring;\r
-  TRB_TEMPLATE            *Trb;\r
-  UINTN                   Loop;\r
-  UINTN                   Index;\r
+  TRANSFER_RING  *Ring;\r
+  TRB_TEMPLATE   *Trb;\r
+  UINTN          Loop;\r
+  UINTN          Index;\r
 \r
   Loop = Timeout / XHC_DEBUG_PORT_1_MILLISECOND;\r
   if (Timeout == 0) {\r
     Loop = 0xFFFFFFFF;\r
   }\r
+\r
   XhcRingDoorBell (Handle, Urb);\r
   //\r
   // Event Ring Not Empty bit can only be set to 1 by XHC after ringing door bell with some delay.\r
@@ -373,19 +370,22 @@ XhcExecTransfer (
     if (Urb->Finished) {\r
       break;\r
     }\r
+\r
     MicroSecondDelay (XHC_DEBUG_PORT_1_MILLISECOND);\r
   }\r
+\r
   if (Index == Loop) {\r
     //\r
     // If time out occurs.\r
     //\r
     Urb->Result |= EFI_USB_ERR_TIMEOUT;\r
-  } \r
+  }\r
+\r
   //\r
   // If URB transfer is error, restore transfer ring to original value before URB transfer\r
   // This will make the current transfer TRB is always at the latest unused one in transfer ring.\r
   //\r
-  Ring = (TRANSFER_RING *)(UINTN) Urb->Ring;\r
+  Ring = (TRANSFER_RING *)(UINTN)Urb->Ring;\r
   if ((Urb->Result != EFI_USB_NOERROR) && (Urb->Direction == EfiUsbDataIn)) {\r
     //\r
     // Adjust Enqueue pointer\r
@@ -394,7 +394,7 @@ XhcExecTransfer (
     //\r
     // Clear CCS flag for next use\r
     //\r
-    Trb = (TRB_TEMPLATE *)(UINTN) Urb->Trb;\r
+    Trb           = (TRB_TEMPLATE *)(UINTN)Urb->Trb;\r
     Trb->CycleBit = ((~Ring->RingPCS) & BIT0);\r
   } else {\r
     //\r
@@ -415,24 +415,24 @@ XhcExecTransfer (
 **/\r
 EFI_STATUS\r
 XhcCreateTransferTrb (\r
-  IN USB3_DEBUG_PORT_HANDLE   *Handle,\r
-  IN URB                        *Urb\r
+  IN USB3_DEBUG_PORT_HANDLE  *Handle,\r
+  IN URB                     *Urb\r
   )\r
 {\r
-  TRANSFER_RING                 *EPRing;\r
-  TRB                           *Trb;\r
+  TRANSFER_RING  *EPRing;\r
+  TRB            *Trb;\r
 \r
   if (Urb->Direction == EfiUsbDataIn) {\r
     EPRing = &Handle->TransferRingIn;\r
   } else {\r
     EPRing = &Handle->TransferRingOut;\r
   }\r
-  \r
-  Urb->Ring = (EFI_PHYSICAL_ADDRESS)(UINTN) EPRing;\r
+\r
+  Urb->Ring = (EFI_PHYSICAL_ADDRESS)(UINTN)EPRing;\r
   XhcSyncTrsRing (Handle, EPRing);\r
 \r
-  Urb->Trb = EPRing->RingEnqueue;\r
-  Trb = (TRB *)(UINTN)EPRing->RingEnqueue;\r
+  Urb->Trb                 = EPRing->RingEnqueue;\r
+  Trb                      = (TRB *)(UINTN)EPRing->RingEnqueue;\r
   Trb->TrbNormal.TRBPtrLo  = XHC_LOW_32BIT (Urb->Data);\r
   Trb->TrbNormal.TRBPtrHi  = XHC_HIGH_32BIT (Urb->Data);\r
   Trb->TrbNormal.Length    = Urb->DataLen;\r
@@ -441,12 +441,12 @@ XhcCreateTransferTrb (
   Trb->TrbNormal.ISP       = 1;\r
   Trb->TrbNormal.IOC       = 1;\r
   Trb->TrbNormal.Type      = TRB_TYPE_NORMAL;\r
-  \r
+\r
   //\r
   // Update the cycle bit to indicate this TRB has been consumed.\r
   //\r
   Trb->TrbNormal.CycleBit = EPRing->RingPCS & BIT0;\r
-  \r
+\r
   return EFI_SUCCESS;\r
 }\r
 \r
@@ -461,50 +461,50 @@ XhcCreateTransferTrb (
   @return Created URB or NULL\r
 \r
 **/\r
-URB*\r
+URB *\r
 XhcCreateUrb (\r
-  IN USB3_DEBUG_PORT_HANDLE             *Handle,\r
-  IN EFI_USB_DATA_DIRECTION             Direction,\r
-  IN VOID                               *Data,\r
-  IN UINTN                              DataLen\r
+  IN USB3_DEBUG_PORT_HANDLE  *Handle,\r
+  IN EFI_USB_DATA_DIRECTION  Direction,\r
+  IN VOID                    *Data,\r
+  IN UINTN                   DataLen\r
   )\r
 {\r
-  EFI_STATUS                    Status;\r
-  URB                           *Urb;\r
-  EFI_PHYSICAL_ADDRESS          UrbData;\r
-  \r
+  EFI_STATUS            Status;\r
+  URB                   *Urb;\r
+  EFI_PHYSICAL_ADDRESS  UrbData;\r
+\r
   if (Direction == EfiUsbDataIn) {\r
     Urb = &Handle->UrbIn;\r
   } else {\r
     Urb = &Handle->UrbOut;\r
   }\r
 \r
-  UrbData  = Urb->Data;\r
-  \r
+  UrbData = Urb->Data;\r
+\r
   ZeroMem (Urb, sizeof (URB));\r
   Urb->Direction = Direction;\r
-  \r
+\r
   //\r
   // Allocate memory to move data from CAR or SMRAM to normal memory\r
   // to make XHCI DMA successfully\r
   // re-use the pre-allocate buffer in PEI to avoid DXE memory service or gBS are not ready\r
   //\r
-  Urb->Data  = UrbData;\r
-  \r
+  Urb->Data = UrbData;\r
+\r
   if (Direction == EfiUsbDataIn) {\r
     //\r
     // Do not break URB data in buffer as it may contain the data which were just put in via DMA by XHC\r
     //\r
-    Urb->DataLen  = (UINT32) DataLen;\r
+    Urb->DataLen = (UINT32)DataLen;\r
   } else {\r
     //\r
     // Put data into URB data out buffer which will create TRBs\r
     //\r
-    ZeroMem ((VOID*)(UINTN) Urb->Data, DataLen);\r
-    CopyMem ((VOID*)(UINTN) Urb->Data, Data, DataLen);\r
-    Urb->DataLen  = (UINT32) DataLen;\r
+    ZeroMem ((VOID *)(UINTN)Urb->Data, DataLen);\r
+    CopyMem ((VOID *)(UINTN)Urb->Data, Data, DataLen);\r
+    Urb->DataLen = (UINT32)DataLen;\r
   }\r
-  \r
+\r
   Status = XhcCreateTransferTrb (Handle, Urb);\r
   ASSERT_EFI_ERROR (Status);\r
 \r
@@ -518,7 +518,7 @@ XhcCreateUrb (
   @param  Direction             The direction of data transfer.\r
   @param  Data                  Array of pointers to the buffers of data to transmit\r
                                 from or receive into.\r
-  @param  DataLength            The lenght of the data buffer.\r
+  @param  DataLength            The length of the data buffer.\r
   @param  Timeout               Indicates the maximum time, in microsecond, which\r
                                 the transfer is allowed to complete.\r
 \r
@@ -532,16 +532,16 @@ XhcCreateUrb (
 EFI_STATUS\r
 EFIAPI\r
 XhcDataTransfer (\r
-  IN     USB3_DEBUG_PORT_HANDLE              *Handle,\r
-  IN     EFI_USB_DATA_DIRECTION              Direction,\r
-  IN OUT VOID                                *Data,\r
-  IN OUT UINTN                               *DataLength,\r
-  IN     UINTN                               Timeout\r
+  IN     USB3_DEBUG_PORT_HANDLE  *Handle,\r
+  IN     EFI_USB_DATA_DIRECTION  Direction,\r
+  IN OUT VOID                    *Data,\r
+  IN OUT UINTN                   *DataLength,\r
+  IN     UINTN                   Timeout\r
   )\r
 {\r
-  URB                     *Urb;\r
-  EFI_STATUS              Status;\r
-  \r
+  URB         *Urb;\r
+  EFI_STATUS  Status;\r
+\r
   //\r
   // Validate the parameters\r
   //\r
@@ -558,13 +558,20 @@ XhcDataTransfer (
 \r
   XhcExecTransfer (Handle, Urb, Timeout);\r
 \r
-  *DataLength     = Urb->Completed;\r
+  //\r
+  // Make sure the data received from HW can fit in the received buffer.\r
+  //\r
+  if (Urb->Completed > *DataLength) {\r
+    return EFI_DEVICE_ERROR;\r
+  }\r
+\r
+  *DataLength = Urb->Completed;\r
 \r
   Status = EFI_TIMEOUT;\r
   if (Urb->Result == EFI_USB_NOERROR) {\r
     Status = EFI_SUCCESS;\r
   }\r
-  \r
+\r
   if (Direction == EfiUsbDataIn) {\r
     //\r
     // Move data from internal buffer to outside buffer (outside buffer may be in SMRAM...)\r
@@ -575,4 +582,3 @@ XhcDataTransfer (
 \r
   return Status;\r
 }\r
-\r