]> git.proxmox.com Git - mirror_edk2.git/blobdiff - SourceLevelDebugPkg/Library/DebugAgent/DebugAgentCommon/DebugAgent.c
SourceLevelDebugPkg: Fix Serial Port connection cannot be setup
[mirror_edk2.git] / SourceLevelDebugPkg / Library / DebugAgent / DebugAgentCommon / DebugAgent.c
index e6be20aa1edc7141a6e570ab5b871ebe6148d038..10dd302694bb19d74c0df114207c4c52ec01a014 100644 (file)
@@ -293,7 +293,7 @@ TriggerSoftInterrupt (
 }\r
 \r
 /**\r
-  Caculate Mailbox checksum and update the checksum field.\r
+  Calculate Mailbox checksum and update the checksum field.\r
 \r
   @param[in]  Mailbox  Debug Agent Mailbox pointer.\r
 \r
@@ -380,10 +380,92 @@ UpdateMailboxContent (
                                               - CalculateSum8 ((UINT8 *)&Value, sizeof(UINT8));\r
     Mailbox->HostSequenceNo = (UINT8) Value;\r
     break;\r
+  case DEBUG_MAILBOX_DEBUG_TIMER_FREQUENCY:\r
+    Mailbox->ToBeCheckSum = Mailbox->CheckSum + CalculateSum8 ((UINT8 *)&Mailbox->DebugTimerFrequency, sizeof(UINT32))\r
+                                              - CalculateSum8 ((UINT8 *)&Value, sizeof(UINT32));\r
+    Mailbox->DebugTimerFrequency = (UINT32) Value;\r
+    break;\r
   }\r
   UpdateMailboxChecksum (Mailbox);\r
   ReleaseMpSpinLock (&mDebugMpContext.MailboxSpinLock);\r
 }\r
+\r
+/**\r
+  Read data from debug device and save the data in buffer.\r
+\r
+  Reads NumberOfBytes data bytes from a debug device into the buffer\r
+  specified by Buffer. The number of bytes actually read is returned.\r
+  If the return value is less than NumberOfBytes, then the rest operation failed.\r
+  If NumberOfBytes is zero, then return 0.\r
+\r
+  @param  Handle           Debug port handle.\r
+  @param  Buffer           Pointer to the data buffer to store the data read from the debug device.\r
+  @param  NumberOfBytes    Number of bytes which will be read.\r
+  @param  Timeout          Timeout value for reading from debug device. It unit is Microsecond.\r
+\r
+  @retval 0                Read data failed, no data is to be read.\r
+  @retval >0               Actual number of bytes read from debug device.\r
+\r
+**/\r
+UINTN\r
+DebugAgentReadBuffer (\r
+  IN DEBUG_PORT_HANDLE     Handle,\r
+  IN UINT8                 *Buffer,\r
+  IN UINTN                 NumberOfBytes,\r
+  IN UINTN                 Timeout\r
+  )\r
+{\r
+  UINTN                    Index;\r
+  UINT32                   Begin;\r
+  UINT32                   TimeoutTicker;\r
+  UINT32                   TimerRound;\r
+  UINT32                   TimerFrequency;\r
+  UINT32                   TimerCycle;\r
+  \r
+  Begin         = 0;\r
+  TimeoutTicker = 0;  \r
+  TimerRound    = 0;\r
+  TimerFrequency = GetMailboxPointer()->DebugTimerFrequency;\r
+  TimerCycle = GetApicTimerInitCount ();\r
+\r
+  if (Timeout != 0) {\r
+    Begin = GetApicTimerCurrentCount ();\r
+    TimeoutTicker = (UINT32) DivU64x32 (\r
+                      MultU64x64 (\r
+                        TimerFrequency,\r
+                        Timeout\r
+                        ),\r
+                      1000000u\r
+                      );\r
+    TimerRound = (UINT32) DivU64x32Remainder (TimeoutTicker,  TimerCycle / 2, &TimeoutTicker);\r
+  }\r
+  Index = 0;\r
+  while (Index < NumberOfBytes) {\r
+    if (DebugPortPollBuffer (Handle)) {\r
+      DebugPortReadBuffer (Handle, Buffer + Index, 1, 0);\r
+      Index ++; \r
+      continue;\r
+    }\r
+    if (Timeout != 0) {\r
+      if (TimerRound == 0) {\r
+        if (IsDebugTimerTimeout (TimerCycle, Begin, TimeoutTicker)) {\r
+          //\r
+          // If time out occurs.\r
+          //\r
+          return 0;\r
+        }\r
+      } else {\r
+        if (IsDebugTimerTimeout (TimerCycle, Begin, TimerCycle / 2)) {\r
+          TimerRound --;\r
+          Begin = GetApicTimerCurrentCount ();\r
+        }\r
+      }\r
+    }\r
+  }\r
+\r
+  return Index;\r
+}\r
+\r
 /**\r
   Set debug flag in mailbox.\r
 \r
@@ -589,7 +671,7 @@ ReadRemainingBreakPacket (
   //\r
   // Has received start symbol, try to read the rest part\r
   //\r
-  if (DebugPortReadBuffer (Handle, (UINT8 *)DebugHeader + OFFSET_OF (DEBUG_PACKET_HEADER, Command), sizeof (DEBUG_PACKET_HEADER) - OFFSET_OF (DEBUG_PACKET_HEADER, Command), READ_PACKET_TIMEOUT) == 0) {\r
+  if (DebugAgentReadBuffer (Handle, (UINT8 *)DebugHeader + OFFSET_OF (DEBUG_PACKET_HEADER, Command), sizeof (DEBUG_PACKET_HEADER) - OFFSET_OF (DEBUG_PACKET_HEADER, Command), READ_PACKET_TIMEOUT) == 0) {\r
     //\r
     // Timeout occur, exit\r
     //\r
@@ -703,7 +785,7 @@ CommandGo (
 }\r
 \r
 /**\r
-  Exectue Stepping command.\r
+  Execute Stepping command.\r
 \r
   @param[in] CpuContext        Pointer to saved CPU context.\r
 \r
@@ -718,6 +800,39 @@ CommandStepping (
   Eflags = (IA32_EFLAGS32 *) &CpuContext->Eflags;\r
   Eflags->Bits.TF = 1;\r
   Eflags->Bits.RF = 1;\r
+  //\r
+  // Save and clear EFLAGS.IF to avoid interrupt happen when executing Stepping\r
+  //\r
+  SetDebugFlag (DEBUG_AGENT_FLAG_INTERRUPT_FLAG, Eflags->Bits.IF);\r
+  Eflags->Bits.IF = 0;\r
+  //\r
+  // Set Stepping Flag\r
+  //\r
+  SetDebugFlag (DEBUG_AGENT_FLAG_STEPPING, 1);\r
+}\r
+\r
+/**\r
+  Do some cleanup after Stepping command done.\r
+\r
+  @param[in] CpuContext        Pointer to saved CPU context.\r
+\r
+**/\r
+VOID\r
+CommandSteppingCleanup (\r
+  IN DEBUG_CPU_CONTEXT          *CpuContext\r
+  )\r
+{\r
+  IA32_EFLAGS32                *Eflags;\r
+\r
+  Eflags = (IA32_EFLAGS32 *) &CpuContext->Eflags;\r
+  //\r
+  // Restore EFLAGS.IF\r
+  //\r
+  Eflags->Bits.IF = GetDebugFlag (DEBUG_AGENT_FLAG_INTERRUPT_FLAG);\r
+  //\r
+  // Clear Stepping flag\r
+  //\r
+  SetDebugFlag (DEBUG_AGENT_FLAG_STEPPING, 0);\r
 }\r
 \r
 /**\r
@@ -1046,9 +1161,9 @@ ReceivePacket (
     //\r
     // Find the valid start symbol\r
     //\r
-    Received = DebugPortReadBuffer (Handle, &DebugHeader->StartSymbol, sizeof (DebugHeader->StartSymbol), TimeoutForStartSymbol);\r
+    Received = DebugAgentReadBuffer (Handle, &DebugHeader->StartSymbol, sizeof (DebugHeader->StartSymbol), TimeoutForStartSymbol);\r
     if (Received < sizeof (DebugHeader->StartSymbol)) {\r
-      DebugAgentMsgPrint (DEBUG_AGENT_WARNING, "DebugPortReadBuffer(StartSymbol) timeout\n");\r
+      DebugAgentMsgPrint (DEBUG_AGENT_WARNING, "DebugAgentReadBuffer(StartSymbol) timeout\n");\r
       return RETURN_TIMEOUT;\r
     }\r
 \r
@@ -1060,14 +1175,14 @@ ReceivePacket (
     //\r
     // Read Package header till field Length\r
     //\r
-    Received = DebugPortReadBuffer (\r
+    Received = DebugAgentReadBuffer (\r
                  Handle,\r
                  (UINT8 *) DebugHeader + OFFSET_OF (DEBUG_PACKET_HEADER, Command),\r
                  OFFSET_OF (DEBUG_PACKET_HEADER, Length) + sizeof (DebugHeader->Length) - sizeof (DebugHeader->StartSymbol),\r
                  Timeout\r
                  );\r
     if (Received == 0) {\r
-      DebugAgentMsgPrint (DEBUG_AGENT_ERROR, "DebugPortReadBuffer(Command) timeout\n");\r
+      DebugAgentMsgPrint (DEBUG_AGENT_ERROR, "DebugAgentReadBuffer(Command) timeout\n");\r
       return RETURN_TIMEOUT;\r
     }\r
     if (DebugHeader->Length < sizeof (DEBUG_PACKET_HEADER)) {\r
@@ -1086,9 +1201,9 @@ ReceivePacket (
       //\r
       // Read the payload data include the CRC field\r
       //\r
-      Received = DebugPortReadBuffer (Handle, &DebugHeader->SequenceNo, (UINT8) (DebugHeader->Length - OFFSET_OF (DEBUG_PACKET_HEADER, SequenceNo)), Timeout);\r
+      Received = DebugAgentReadBuffer (Handle, &DebugHeader->SequenceNo, (UINT8) (DebugHeader->Length - OFFSET_OF (DEBUG_PACKET_HEADER, SequenceNo)), Timeout);\r
       if (Received == 0) {\r
-        DebugAgentMsgPrint (DEBUG_AGENT_ERROR, "DebugPortReadBuffer(SequenceNo) timeout\n");\r
+        DebugAgentMsgPrint (DEBUG_AGENT_ERROR, "DebugAgentReadBuffer(SequenceNo) timeout\n");\r
         return RETURN_TIMEOUT;\r
       }\r
       //\r
@@ -1220,8 +1335,12 @@ GetBreakCause (
       if ((CpuContext->Dr6 & BIT14) != 0) {\r
         Cause = DEBUG_DATA_BREAK_CAUSE_STEPPING;\r
         //\r
-        // If it's single step, no need to check DR0, to ensure single step work in PeCoffExtraActionLib\r
-        // (right after triggering a breakpoint to report image load/unload).\r
+        // DR6.BIT14 Indicates (when set) that the debug exception was\r
+        // triggered by the single step execution mode.\r
+        // The single-step mode is the highest priority debug exception.\r
+        // This is single step, no need to check DR0, to ensure single step\r
+        // work in PeCoffExtraActionLib (right after triggering a breakpoint\r
+        // to report image load/unload).\r
         //\r
         return Cause;\r
 \r
@@ -1352,31 +1471,32 @@ CopyMemByWidth (
   2. Compute the CRC of the compressed data buffer;\r
   3. Compress the data and send to the debug channel.\r
 \r
+  @param[in]  Handle           The debug channel handle to send the compressed data buffer.\r
   @param[in]  Data             The data buffer.\r
   @param[in]  Length           The length of the data buffer.\r
+  @param[in]  Send             TRUE to send the compressed data buffer.\r
   @param[out] CompressedLength Return the length of the compressed data buffer.\r
                                It may be larger than the Length in some cases.\r
   @param[out] CompressedCrc    Return the CRC of the compressed data buffer.\r
-  @param[in]  Handle           The debug channel handle to send the compressed data buffer.\r
 **/\r
 VOID\r
-CompressDataThenSend (\r
+CompressData (\r
+  IN  DEBUG_PORT_HANDLE Handle,\r
   IN  UINT8             *Data,\r
   IN  UINT8             Length,\r
+  IN  BOOLEAN           Send,\r
   OUT UINTN             *CompressedLength,  OPTIONAL\r
-  OUT UINT16            *CompressedCrc,     OPTIONAL\r
-  IN  DEBUG_PORT_HANDLE Handle              OPTIONAL\r
+  OUT UINT16            *CompressedCrc      OPTIONAL\r
   )\r
 {\r
-  UINTN  Index;\r
-  UINT8  LastChar;\r
-  UINT8  LastCharCount;\r
-  UINT8  CurrentChar;\r
-  UINTN  CompressedIndex;\r
+  UINTN                 Index;\r
+  UINT8                 LastChar;\r
+  UINT8                 LastCharCount;\r
+  UINT8                 CurrentChar;\r
+  UINTN                 CompressedIndex;\r
 \r
   ASSERT (Length > 0);\r
-\r
-  LastChar = Data[0] + 1; // Just ensure it's different from the first byte.\r
+  LastChar      = Data[0] + 1; // Just ensure it's different from the first byte.\r
   LastCharCount = 0;\r
 \r
   for (Index = 0, CompressedIndex = 0; Index <= Length; Index++) {\r
@@ -1391,7 +1511,7 @@ CompressDataThenSend (
         if (CompressedCrc != NULL) {\r
           *CompressedCrc = CalculateCrc16 (&LastChar, 1, *CompressedCrc);\r
         }\r
-        if (Handle != NULL) {\r
+        if (Send) {\r
           DebugPortWriteBuffer (Handle, &LastChar, 1);\r
         }\r
         \r
@@ -1403,7 +1523,7 @@ CompressDataThenSend (
           *CompressedCrc = CalculateCrc16 (&LastChar, 1, *CompressedCrc);\r
           *CompressedCrc = CalculateCrc16 (&LastCharCount, 1, *CompressedCrc);\r
         }\r
-        if (Handle != NULL) {\r
+        if (Send) {\r
           DebugPortWriteBuffer (Handle, &LastChar, 1);\r
           DebugPortWriteBuffer (Handle, &LastChar, 1);\r
           DebugPortWriteBuffer (Handle, &LastCharCount, 1);\r
@@ -1486,11 +1606,12 @@ ReadMemoryAndSendResponsePacket (
       //\r
       // Get the compressed data size without modifying the packet.\r
       //\r
-      CompressDataThenSend (\r
+      CompressData (\r
+        Handle,\r
         (UINT8 *) (DebugHeader + 1),\r
         CurrentDataSize,\r
+        FALSE,\r
         &CompressedDataSize,\r
-        NULL,\r
         NULL\r
         );\r
     } else {\r
@@ -1503,12 +1624,13 @@ ReadMemoryAndSendResponsePacket (
       // Compute the CRC of the packet head without modifying the packet.\r
       //\r
       DebugHeader->Crc = CalculateCrc16 ((UINT8 *) DebugHeader, sizeof (DEBUG_PACKET_HEADER), 0);\r
-      CompressDataThenSend (\r
+      CompressData (\r
+        Handle,\r
         (UINT8 *) (DebugHeader + 1),\r
         CurrentDataSize,\r
+        FALSE,\r
         NULL,\r
-        &DebugHeader->Crc,\r
-        NULL\r
+        &DebugHeader->Crc\r
         );\r
       //\r
       // Send out the packet head.\r
@@ -1517,12 +1639,13 @@ ReadMemoryAndSendResponsePacket (
       //\r
       // Compress and send out the packet data.\r
       //\r
-      CompressDataThenSend (\r
+      CompressData (\r
+        Handle,\r
         (UINT8 *) (DebugHeader + 1),\r
         CurrentDataSize,\r
+        TRUE,\r
         NULL,\r
-        NULL,\r
-        Handle\r
+        NULL\r
         );\r
     } else {\r
 \r
@@ -1681,7 +1804,7 @@ SendBreakPacketToHost (
     // Poll Attach symbols from HOST and ack OK\r
     //\r
     do {\r
-      DebugPortReadBuffer (Handle, &InputCharacter, 1, 0);\r
+      DebugAgentReadBuffer (Handle, &InputCharacter, 1, 0);\r
     } while (InputCharacter != DEBUG_STARTING_SYMBOL_ATTACH);\r
     SendAckPacket (DEBUG_COMMAND_OK);\r
 \r
@@ -1870,10 +1993,6 @@ CommandCommunication (
       if (Data8 == DEBUG_DATA_BREAK_CAUSE_IMAGE_LOAD || Data8 == DEBUG_DATA_BREAK_CAUSE_IMAGE_UNLOAD) {\r
         CpuContext->Dr0 = 0;\r
       }\r
-      //\r
-      // Clear Stepping Flag\r
-      //\r
-      SetDebugFlag (DEBUG_AGENT_FLAG_STEPPING, 0);\r
 \r
       if (!HaltDeferred) {\r
         //\r
@@ -1988,10 +2107,6 @@ CommandCommunication (
       }\r
 \r
       mDebugMpContext.BreakAtCpuIndex = (UINT32) (-1);\r
-      //\r
-      // Set Stepping Flag\r
-      //\r
-      SetDebugFlag (DEBUG_AGENT_FLAG_STEPPING, 1);\r
       ReleaseMpSpinLock (&mDebugMpContext.DebugPortSpinLock);\r
       //\r
       // Executing stepping command directly without sending ACK packet,\r
@@ -2285,9 +2400,16 @@ InterruptProcess (
     // Check if this exception is issued by Debug Agent itself\r
     // If yes, fill the debug agent exception buffer and LongJump() back to\r
     // the saved CPU content in CommandCommunication()\r
+    // If exception is issued when executing Stepping, will be handled in\r
+    // exception handle procedure.\r
     //\r
     if (GetDebugFlag (DEBUG_AGENT_FLAG_AGENT_IN_PROGRESS) == 1) {\r
-      DebugAgentMsgPrint (DEBUG_AGENT_ERROR, "Debug agent meet one Exception, ExceptionNum is %d, EIP = 0x%x.\n", Vector, (UINTN)CpuContext->Eip);\r
+      DebugAgentMsgPrint (\r
+        DEBUG_AGENT_ERROR,\r
+        "Debug agent meet one Exception, ExceptionNum is %d, EIP = 0x%x.\n",\r
+        Vector,\r
+        (UINTN)CpuContext->Eip\r
+        );\r
       ExceptionBuffer = (DEBUG_AGENT_EXCEPTION_BUFFER *) (UINTN) GetMailboxPointer()->ExceptionBufferPointer;\r
       ExceptionBuffer->ExceptionContent.ExceptionNum  = (UINT8) Vector;\r
       ExceptionBuffer->ExceptionContent.ExceptionData = (UINT32) CpuContext->ExceptionData;\r
@@ -2327,6 +2449,10 @@ InterruptProcess (
       if (MultiProcessorDebugSupport()) {\r
         mDebugMpContext.BreakAtCpuIndex = ProcessorIndex;\r
       }\r
+      //\r
+      // Clear Stepping Flag and restore EFLAGS.IF\r
+      //\r
+      CommandSteppingCleanup (CpuContext);\r
       SendAckPacket (DEBUG_COMMAND_OK);\r
       CommandCommunication (Vector, CpuContext, BreakReceived);\r
       break;\r
@@ -2408,7 +2534,7 @@ InterruptProcess (
         //\r
         CurrentDebugTimerInitCount = GetApicTimerInitCount ();\r
         if (mDebugMpContext.DebugTimerInitCount != CurrentDebugTimerInitCount) {\r
-          InitializeDebugTimer ();\r
+          InitializeDebugTimer (NULL);\r
         }\r
       }\r
 \r
@@ -2493,13 +2619,24 @@ InterruptProcess (
 \r
   default:\r
     if (Vector <= DEBUG_EXCEPT_SIMD) {\r
+      DebugAgentMsgPrint (\r
+        DEBUG_AGENT_ERROR,\r
+        "Exception happened, ExceptionNum is %d, EIP = 0x%x.\n",\r
+        Vector,\r
+        (UINTN) CpuContext->Eip\r
+        );\r
       if (BreakCause == DEBUG_DATA_BREAK_CAUSE_STEPPING) {\r
         //\r
-        // Stepping is finished, send Ack package.\r
+        // If exception happened when executing Stepping, send Ack package.\r
+        // HOST consider Stepping command was finished.\r
         //\r
         if (MultiProcessorDebugSupport()) {\r
           mDebugMpContext.BreakAtCpuIndex = ProcessorIndex;\r
         }\r
+        //\r
+        // Clear Stepping flag and restore EFLAGS.IF\r
+        //\r
+        CommandSteppingCleanup (CpuContext);\r
         SendAckPacket (DEBUG_COMMAND_OK);\r
       } else {\r
         //\r