]> git.proxmox.com Git - mirror_edk2.git/blobdiff - SourceLevelDebugPkg/Library/DebugCommunicationLibUsb3/DebugCommunicationLibUsb3Transfer.c
SourceLevelDebugPkg/Usb3: Make sure data from HW can fit in buffer
[mirror_edk2.git] / SourceLevelDebugPkg / Library / DebugCommunicationLibUsb3 / DebugCommunicationLibUsb3Transfer.c
index deb802e4adf4d9cd35a3fe6445de77190e6d6d28..fda43279a32cea01ffdfb6def4d56aaff1590750 100644 (file)
@@ -1,7 +1,7 @@
 /** @file\r
   Debug Port Library implementation based on usb3 debug port.\r
 \r
-  Copyright (c) 2014 - 2015, Intel Corporation. All rights reserved.<BR>\r
+  Copyright (c) 2014 - 2018, 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
@@ -41,7 +41,7 @@ XhcSyncTrsRing (
   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
@@ -145,11 +145,9 @@ XhcCheckNewEvent (
   )\r
 {\r
   EFI_STATUS          Status;\r
-  TRB_TEMPLATE        *EvtTrb;\r
 \r
   ASSERT (EvtRing != NULL);\r
 \r
-  EvtTrb     = (TRB_TEMPLATE *)(UINTN) EvtRing->EventRingDequeue;\r
   *NewEvtTrb = (TRB_TEMPLATE *)(UINTN) EvtRing->EventRingDequeue;\r
 \r
   if (EvtRing->EventRingDequeue == EvtRing->EventRingEnqueue) {\r
@@ -187,9 +185,9 @@ IsTrbInTrsRing (
 {\r
   TRB_TEMPLATE  *CheckedTrb;\r
   UINTN         Index;\r
-  \r
+\r
   CheckedTrb = (TRB_TEMPLATE *)(UINTN) Ring->RingSeg0;\r
-  \r
+\r
   ASSERT (Ring->TrbNumber == TR_RING_TRB_NUMBER);\r
 \r
   for (Index = 0; Index < Ring->TrbNumber; Index++) {\r
@@ -224,7 +222,7 @@ XhcCheckUrbResult (
   UINT64                  XhcDequeue;\r
   UINT32                  High;\r
   UINT32                  Low;\r
-  \r
+\r
   ASSERT ((Handle != NULL) && (Urb != NULL));\r
 \r
   if (Urb->Finished) {\r
@@ -232,12 +230,12 @@ 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
+\r
   for (Index = 0; Index < Handle->EventRing.TrbNumber; Index++) {\r
 \r
     Status = XhcCheckNewEvent (Handle, &Handle->EventRing, ((TRB_TEMPLATE **)&EvtTrb));\r
@@ -247,13 +245,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
+\r
     TRBPtr = (TRB_TEMPLATE *)(UINTN)(EvtTrb->TRBPtrLo | LShiftU64 ((UINT64) EvtTrb->TRBPtrHi, 32));\r
-    \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
@@ -271,13 +269,13 @@ XhcCheckUrbResult (
     } else {\r
       continue;\r
     }\r
-    \r
+\r
     if ((EvtTrb->Completecode == TRB_COMPLETION_SHORT_PACKET) ||\r
         (EvtTrb->Completecode == TRB_COMPLETION_SUCCESS)) {\r
       //\r
       // The length of data which were transferred.\r
       //\r
-      CheckedUrb->Completed += (CheckedUrb->DataLen - EvtTrb->Length);\r
+      CheckedUrb->Completed += (((TRANSFER_TRB_NORMAL*)TRBPtr)->Length - EvtTrb->Length);\r
     } else {\r
       CheckedUrb->Result  |= EFI_USB_ERR_TIMEOUT;\r
     }\r
@@ -328,9 +326,9 @@ XhcRingDoorBell (
 \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
@@ -356,58 +354,31 @@ XhcExecTransfer (
   )\r
 {\r
   TRANSFER_RING           *Ring;\r
-  UINT64                  Begin;\r
-  UINT64                  TimeoutTicker;\r
-  UINT64                  TimerRound;\r
   TRB_TEMPLATE            *Trb;\r
+  UINTN                   Loop;\r
+  UINTN                   Index;\r
 \r
-  Begin         = 0;\r
-  TimeoutTicker = 0;  \r
-  TimerRound    = 0;\r
-\r
-  XhcRingDoorBell (Handle, Urb);\r
-\r
-  if (Timeout != 0) {\r
-    Begin = GetPerformanceCounter ();\r
-    TimeoutTicker = DivU64x32 (\r
-                      MultU64x64 (\r
-                        Handle->TimerFrequency,\r
-                        Timeout\r
-                        ),\r
-                      1000000u\r
-                      );\r
-    TimerRound = DivU64x64Remainder (\r
-                   TimeoutTicker,\r
-                   DivU64x32 (Handle->TimerCycle, 2),\r
-                   &TimeoutTicker\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
   //\r
-  while (TRUE) {\r
-    if (Timeout != 0) {\r
-      if (TimerRound == 0) {\r
-        if (IsTimerTimeout (Handle, Begin, TimeoutTicker)) {\r
-          //\r
-          // If time out occurs.\r
-          //\r
-          Urb->Result |= EFI_USB_ERR_TIMEOUT;\r
-          break;\r
-        }\r
-      } else {\r
-        if (IsTimerTimeout (Handle, Begin, DivU64x32 (Handle->TimerCycle, 2))) {\r
-          TimerRound --;\r
-        }\r
-      }\r
-    }\r
+  for (Index = 0; Index < Loop; Index++) {\r
     XhcCheckUrbResult (Handle, Urb);\r
     if (Urb->Finished) {\r
       break;\r
     }\r
+    MicroSecondDelay (XHC_DEBUG_PORT_1_MILLISECOND);\r
+  }\r
+  if (Index == Loop) {\r
+    //\r
+    // If time out occurs.\r
+    //\r
+    Urb->Result |= EFI_USB_ERR_TIMEOUT;\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
@@ -454,7 +425,7 @@ XhcCreateTransferTrb (
   } else {\r
     EPRing = &Handle->TransferRingOut;\r
   }\r
-  \r
+\r
   Urb->Ring = (EFI_PHYSICAL_ADDRESS)(UINTN) EPRing;\r
   XhcSyncTrsRing (Handle, EPRing);\r
 \r
@@ -468,12 +439,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
@@ -499,7 +470,7 @@ XhcCreateUrb (
   EFI_STATUS                    Status;\r
   URB                           *Urb;\r
   EFI_PHYSICAL_ADDRESS          UrbData;\r
-  \r
+\r
   if (Direction == EfiUsbDataIn) {\r
     Urb = &Handle->UrbIn;\r
   } else {\r
@@ -507,17 +478,17 @@ XhcCreateUrb (
   }\r
 \r
   UrbData  = Urb->Data;\r
-  \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
+\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
@@ -531,7 +502,7 @@ XhcCreateUrb (
     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
@@ -568,7 +539,7 @@ XhcDataTransfer (
 {\r
   URB                     *Urb;\r
   EFI_STATUS              Status;\r
-  \r
+\r
   //\r
   // Validate the parameters\r
   //\r
@@ -585,13 +556,20 @@ XhcDataTransfer (
 \r
   XhcExecTransfer (Handle, Urb, Timeout);\r
 \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