]> git.proxmox.com Git - mirror_edk2.git/blobdiff - SourceLevelDebugPkg/Library/DebugAgent/DebugAgentCommon/DebugAgent.c
Refine code to make it more safely.
[mirror_edk2.git] / SourceLevelDebugPkg / Library / DebugAgent / DebugAgentCommon / DebugAgent.c
index f4039f49952cc051e27d06f6849db5259783a460..48bc38ca547cbb6fa1eb47477c23962899bde3b1 100644 (file)
@@ -4,7 +4,7 @@
   read/write debug packet to communication with HOST based on transfer\r
   protocol.\r
 \r
-  Copyright (c) 2010 - 2013, Intel Corporation. All rights reserved.<BR>\r
+  Copyright (c) 2010 - 2014, 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
 #include "Ia32/DebugException.h"\r
 \r
 CHAR8 mErrorMsgVersionAlert[]       = "\rThe SourceLevelDebugPkg you are using requires a newer version of the Intel(R) UDK Debugger Tool.\r\n";\r
-CHAR8 mErrorMsgSendInitPacket[]     = "\rSend INIT break packet and try to connect the HOST (Intel(R) UDK Debugger Tool v1.3) ...\r\n";\r
+CHAR8 mErrorMsgSendInitPacket[]     = "\rSend INIT break packet and try to connect the HOST (Intel(R) UDK Debugger Tool v1.4) ...\r\n";\r
 CHAR8 mErrorMsgConnectOK[]          = "HOST connection is successful!\r\n";\r
 CHAR8 mErrorMsgConnectFail[]        = "HOST connection is failed!\r\n";\r
 CHAR8 mWarningMsgIngoreBreakpoint[] = "Ignore break point in SMM for SMI issued during DXE debugging!\r\n";\r
 \r
+//\r
+// Vector Handoff Info list used by Debug Agent for persist\r
+//\r
+EFI_VECTOR_HANDOFF_INFO mVectorHandoffInfoDebugAgent[] = {\r
+  {\r
+    DEBUG_EXCEPT_DIVIDE_ERROR,         // Vector 0\r
+    EFI_VECTOR_HANDOFF_HOOK_BEFORE,\r
+    EFI_DEBUG_AGENT_GUID\r
+  },\r
+  {\r
+    DEBUG_EXCEPT_DEBUG,                // Vector 1\r
+    EFI_VECTOR_HANDOFF_DO_NOT_HOOK,\r
+    EFI_DEBUG_AGENT_GUID\r
+  },\r
+  {\r
+    DEBUG_EXCEPT_NMI,                  // Vector 2\r
+    EFI_VECTOR_HANDOFF_HOOK_BEFORE,\r
+    EFI_DEBUG_AGENT_GUID\r
+  },\r
+  {\r
+    DEBUG_EXCEPT_BREAKPOINT,           // Vector 3\r
+    EFI_VECTOR_HANDOFF_DO_NOT_HOOK,\r
+    EFI_DEBUG_AGENT_GUID\r
+  },\r
+  {\r
+    DEBUG_EXCEPT_OVERFLOW,             // Vector 4\r
+    EFI_VECTOR_HANDOFF_HOOK_BEFORE,\r
+    EFI_DEBUG_AGENT_GUID\r
+  },\r
+  {\r
+    DEBUG_EXCEPT_BOUND,                // Vector 5\r
+    EFI_VECTOR_HANDOFF_HOOK_BEFORE,\r
+    EFI_DEBUG_AGENT_GUID\r
+  },\r
+  {\r
+    DEBUG_EXCEPT_INVALID_OPCODE,       // Vector 6\r
+    EFI_VECTOR_HANDOFF_HOOK_BEFORE,\r
+    EFI_DEBUG_AGENT_GUID\r
+  },\r
+  {\r
+    DEBUG_EXCEPT_DOUBLE_FAULT,         // Vector 8\r
+    EFI_VECTOR_HANDOFF_HOOK_BEFORE,\r
+    EFI_DEBUG_AGENT_GUID\r
+  },\r
+  {\r
+    DEBUG_EXCEPT_INVALID_TSS,          // Vector 10\r
+    EFI_VECTOR_HANDOFF_HOOK_BEFORE,\r
+    EFI_DEBUG_AGENT_GUID\r
+  },\r
+  {\r
+    DEBUG_EXCEPT_SEG_NOT_PRESENT,      // Vector 11\r
+    EFI_VECTOR_HANDOFF_HOOK_BEFORE,\r
+    EFI_DEBUG_AGENT_GUID\r
+  },\r
+  {\r
+    DEBUG_EXCEPT_STACK_FAULT,          // Vector 12\r
+    EFI_VECTOR_HANDOFF_HOOK_BEFORE,\r
+    EFI_DEBUG_AGENT_GUID\r
+  },\r
+  {\r
+    DEBUG_EXCEPT_GP_FAULT,             // Vector 13\r
+    EFI_VECTOR_HANDOFF_HOOK_BEFORE,\r
+    EFI_DEBUG_AGENT_GUID\r
+  },\r
+    {\r
+    DEBUG_EXCEPT_PAGE_FAULT,           // Vector 14\r
+    EFI_VECTOR_HANDOFF_HOOK_BEFORE,\r
+    EFI_DEBUG_AGENT_GUID\r
+  },\r
+  {\r
+    DEBUG_EXCEPT_FP_ERROR,             // Vector 16\r
+    EFI_VECTOR_HANDOFF_HOOK_BEFORE,\r
+    EFI_DEBUG_AGENT_GUID\r
+  },\r
+  {\r
+    DEBUG_EXCEPT_ALIGNMENT_CHECK,      // Vector 17\r
+    EFI_VECTOR_HANDOFF_HOOK_BEFORE,\r
+    EFI_DEBUG_AGENT_GUID\r
+  },\r
+  {\r
+    DEBUG_EXCEPT_MACHINE_CHECK,        // Vector 18\r
+    EFI_VECTOR_HANDOFF_HOOK_BEFORE,\r
+    EFI_DEBUG_AGENT_GUID\r
+  },\r
+  {\r
+    DEBUG_EXCEPT_SIMD,                 // Vector 19\r
+    EFI_VECTOR_HANDOFF_HOOK_BEFORE,\r
+    EFI_DEBUG_AGENT_GUID\r
+  },\r
+  {\r
+    DEBUG_TIMER_VECTOR,                // Vector 32\r
+    EFI_VECTOR_HANDOFF_DO_NOT_HOOK,\r
+    EFI_DEBUG_AGENT_GUID\r
+  },\r
+  {\r
+    DEBUG_MAILBOX_VECTOR,              // Vector 33\r
+    EFI_VECTOR_HANDOFF_DO_NOT_HOOK,\r
+    EFI_DEBUG_AGENT_GUID\r
+  },\r
+  {\r
+    0,\r
+    EFI_VECTOR_HANDOFF_LAST_ENTRY,\r
+    { 0 }\r
+  }\r
+};\r
+\r
+UINTN mVectorHandoffInfoCount = sizeof (mVectorHandoffInfoDebugAgent) / sizeof (EFI_VECTOR_HANDOFF_INFO);\r
+\r
 /**\r
   Calculate CRC16 for target data.\r
 \r
@@ -464,6 +572,7 @@ DebugAgentDataMsgPrint (
   @retval EFI_SUCCESS        Read the symbol in BreakSymbol.\r
   @retval EFI_CRC_ERROR      CRC check fail.\r
   @retval EFI_TIMEOUT        Timeout occurs when reading debug packet.\r
+  @retval EFI_DEVICE_ERROR   Receive the old or responsed packet.\r
 \r
 **/\r
 EFI_STATUS\r
@@ -473,10 +582,12 @@ ReadRemainingBreakPacket (
   )\r
 {\r
   UINT16                     Crc;\r
+  DEBUG_AGENT_MAILBOX        *Mailbox;\r
+\r
   //\r
   // Has received start symbol, try to read the rest part\r
   //\r
-  if (DebugPortReadBuffer (Handle, &DebugHeader->Command, sizeof (DEBUG_PACKET_HEADER) - 1, READ_PACKET_TIMEOUT) == 0) {\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
     //\r
     // Timeout occur, exit\r
     //\r
@@ -491,9 +602,20 @@ ReadRemainingBreakPacket (
     DebugAgentDataMsgPrint (DEBUG_AGENT_VERBOSE, FALSE, (UINT8 *)DebugHeader, DebugHeader->Length);\r
     return EFI_CRC_ERROR;\r
   }\r
-\r
-  UpdateMailboxContent (GetMailboxPointer(), DEBUG_MAILBOX_HOST_SEQUENCE_NO_INDEX, DebugHeader->SequenceNo);\r
-  return EFI_SUCCESS;\r
+  Mailbox = GetMailboxPointer();\r
+  if (((DebugHeader->Command & DEBUG_COMMAND_RESPONSE) == 0) &&\r
+       (DebugHeader->SequenceNo == (UINT8) (Mailbox->HostSequenceNo + 1))) {\r
+    //\r
+    // Only updagte HostSequenceNo for new command packet \r
+    //\r
+    UpdateMailboxContent (Mailbox, DEBUG_MAILBOX_HOST_SEQUENCE_NO_INDEX, DebugHeader->SequenceNo);\r
+    return EFI_SUCCESS;\r
+  } else {\r
+    //\r
+    // If one old command or response packet received, skip it\r
+    //\r
+    return EFI_DEVICE_ERROR;\r
+  }\r
 }\r
 \r
 /**\r
@@ -892,7 +1014,7 @@ ReceivePacket (
     //\r
     Received = DebugPortReadBuffer (\r
                  Handle,\r
-                 &DebugHeader->Command,\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
@@ -1110,55 +1232,127 @@ GetBreakCause (
 }\r
 \r
 /**\r
-  Send packet with response data to HOST.\r
+  Copy memory from source to destination with specified width.\r
+\r
+  @param[out] Dest        A pointer to the destination buffer of the memory copy.\r
+  @param[in]  Src         A pointer to the source buffer of the memory copy.\r
+  @param[in]  Count       The number of data with specified width to copy from source to destination.\r
+  @param[in]  Width       Data width in byte.\r
+\r
+**/\r
+VOID\r
+CopyMemByWidth (\r
+  OUT UINT8               *Dest,\r
+  IN  UINT8               *Src,\r
+  IN  UINT16              Count,\r
+  IN  UINT8               Width\r
+  )\r
+{\r
+  UINT8                   *Destination;\r
+  UINT8                   *Source;\r
+  INT8                    Step;\r
+\r
+  if (Src > Dest) {\r
+    Destination = Dest;\r
+    Source      = Src;\r
+    Step        = Width;\r
+  } else {\r
+    //\r
+    // Copy memory from tail to avoid memory overlap\r
+    //\r
+    Destination = Dest + (Count - 1) * Width;\r
+    Source      = Src  + (Count - 1) * Width;\r
+    Step        = -Width;\r
+  }\r
+\r
+  while (Count-- != 0) {\r
+    switch (Width) {\r
+    case 1:\r
+      *(UINT8 *) Destination = MmioRead8 ((UINTN) Source);\r
+      break;\r
+    case 2:\r
+      *(UINT16 *) Destination = MmioRead16 ((UINTN) Source);\r
+      break;\r
+    case 4:\r
+      *(UINT32 *) Destination = MmioRead32 ((UINTN) Source);\r
+      break;\r
+    case 8:\r
+      *(UINT64 *) Destination = MmioRead64 ((UINTN) Source);\r
+      break;\r
+    default:\r
+      ASSERT (FALSE);\r
+    }\r
+    Source      += Step;\r
+    Destination += Step;\r
+  }\r
+}\r
+\r
+/**\r
+  Read memory with speicifed width and send packet with response data to HOST.\r
 \r
   @param[in] Data        Pointer to response data buffer.\r
-  @param[in] DataSize    Size of response data in byte.\r
+  @param[in] Count       The number of data with specified Width.\r
+  @param[in] Width       Data width in byte.\r
 \r
   @retval RETURN_SUCCESS      Response data was sent successfully.\r
 \r
 **/\r
 RETURN_STATUS\r
-SendDataResponsePacket (\r
+ReadMemoryAndSendResponsePacket (\r
   IN UINT8                *Data,\r
-  IN UINT16               DataSize\r
+  IN UINT16               Count,\r
+  IN UINT8                Width\r
   )\r
 {\r
   RETURN_STATUS        Status;\r
   DEBUG_PACKET_HEADER  *DebugHeader;\r
   BOOLEAN              LastPacket;\r
   DEBUG_PACKET_HEADER  *AckDebugHeader;\r
-  UINT8                DebugPacket[DEBUG_DATA_UPPER_LIMIT];\r
+  UINT8                DebugPacket[DEBUG_DATA_UPPER_LIMIT + sizeof (UINT64) - 1];\r
   UINT8                InputPacketBuffer[DEBUG_DATA_UPPER_LIMIT];\r
   DEBUG_PORT_HANDLE    Handle;\r
   UINT8                SequenceNo;\r
+  UINTN                RemainingDataSize;\r
+  UINTN                CurrentDataSize;\r
 \r
   Handle = GetDebugPortHandle();\r
 \r
-  DebugHeader = (DEBUG_PACKET_HEADER *) &DebugPacket;\r
+  //\r
+  // Data is appended end of Debug Packet header,  make sure data address\r
+  // in Debug Packet 8-byte alignment always\r
+  //\r
+  DebugHeader = (DEBUG_PACKET_HEADER *) (ALIGN_VALUE ((UINTN)&DebugPacket + sizeof (DEBUG_PACKET_HEADER), sizeof (UINT64))\r
+                                         - sizeof (DEBUG_PACKET_HEADER));\r
   DebugHeader->StartSymbol = DEBUG_STARTING_SYMBOL_NORMAL;\r
 \r
+  RemainingDataSize = Count * Width;\r
   while (TRUE) {\r
     SequenceNo = GetMailboxPointer()->HostSequenceNo;\r
-    if (DataSize <= DEBUG_DATA_MAXIMUM_REAL_DATA) {\r
+    if (RemainingDataSize <= DEBUG_DATA_MAXIMUM_REAL_DATA) {\r
+      //\r
+      // If the remaining data is less one real packet size, this is the last data packet\r
+      //\r
+      CurrentDataSize = RemainingDataSize;\r
       LastPacket = TRUE;\r
-      DebugHeader->Command    = DEBUG_COMMAND_OK;\r
-      DebugHeader->Length     = (UINT8) (DataSize + sizeof (DEBUG_PACKET_HEADER));\r
-      DebugHeader->SequenceNo = SequenceNo;\r
-      DebugHeader->Crc        = 0;\r
-      CopyMem (DebugHeader + 1, Data, DataSize);\r
-\r
+      DebugHeader->Command = DEBUG_COMMAND_OK;\r
     } else {\r
+      //\r
+      // Data is too larger to be sent in one packet, calculate the actual data size could\r
+      // be sent in one Maximum data packet\r
+      //\r
+      CurrentDataSize = (DEBUG_DATA_MAXIMUM_REAL_DATA / Width) * Width;\r
       LastPacket = FALSE;\r
-      DebugHeader->Command    = DEBUG_COMMAND_IN_PROGRESS;\r
-      DebugHeader->Length     = DEBUG_DATA_MAXIMUM_REAL_DATA + sizeof (DEBUG_PACKET_HEADER);\r
-      DebugHeader->SequenceNo = SequenceNo;\r
-      DebugHeader->Crc        = 0;\r
-      CopyMem (DebugHeader + 1, Data, DEBUG_DATA_MAXIMUM_REAL_DATA);\r
+      DebugHeader->Command = DEBUG_COMMAND_IN_PROGRESS;\r
     }\r
-\r
     //\r
-    // Calculate and fill the checksum\r
+    // Construct the rest Debug header\r
+    //\r
+    DebugHeader->Length     = (UINT8)(CurrentDataSize + sizeof (DEBUG_PACKET_HEADER));\r
+    DebugHeader->SequenceNo = SequenceNo;\r
+    DebugHeader->Crc        = 0;\r
+    CopyMemByWidth ((UINT8 *)(DebugHeader + 1), Data, (UINT16) CurrentDataSize / Width, Width);\r
+    //\r
+    // Calculate and fill the checksum, DebugHeader->Crc should be 0 before invoking CalculateCrc16 ()\r
     //\r
     DebugHeader->Crc = CalculateCrc16 ((UINT8 *) DebugHeader, DebugHeader->Length, 0);\r
 \r
@@ -1184,10 +1378,10 @@ SendDataResponsePacket (
       }\r
       if ((SequenceNo == (UINT8) (DebugHeader->SequenceNo + 1)) && (AckDebugHeader->Command == DEBUG_COMMAND_CONTINUE)) {\r
         //\r
-        // Send the rest packet\r
+        // Calculate the rest data size\r
         //\r
-        Data     += DEBUG_DATA_MAXIMUM_REAL_DATA;\r
-        DataSize -= DEBUG_DATA_MAXIMUM_REAL_DATA;\r
+        Data              += CurrentDataSize;\r
+        RemainingDataSize -= CurrentDataSize;\r
         UpdateMailboxContent (GetMailboxPointer(), DEBUG_MAILBOX_HOST_SEQUENCE_NO_INDEX, (UINT8) SequenceNo);\r
         break;\r
       }\r
@@ -1199,6 +1393,24 @@ SendDataResponsePacket (
   }\r
 }\r
 \r
+/**\r
+  Send packet with response data to HOST.\r
+\r
+  @param[in] Data        Pointer to response data buffer.\r
+  @param[in] DataSize    Size of response data in byte.\r
+\r
+  @retval RETURN_SUCCESS      Response data was sent successfully.\r
+\r
+**/\r
+RETURN_STATUS\r
+SendDataResponsePacket (\r
+  IN UINT8                *Data,\r
+  IN UINT16               DataSize\r
+  )\r
+{\r
+  return ReadMemoryAndSendResponsePacket (Data, DataSize, 1);\r
+}\r
+\r
 /**\r
   Send break cause packet to HOST.\r
 \r
@@ -1349,7 +1561,7 @@ CommandCommunication (
   )\r
 {\r
   RETURN_STATUS                     Status;\r
-  UINT8                             InputPacketBuffer[DEBUG_DATA_UPPER_LIMIT];\r
+  UINT8                             InputPacketBuffer[DEBUG_DATA_UPPER_LIMIT + sizeof (UINT64) - 1];\r
   DEBUG_PACKET_HEADER               *DebugHeader;\r
   UINT8                             Width;\r
   UINT8                             Data8;\r
@@ -1376,6 +1588,7 @@ CommandCommunication (
   DEBUG_AGENT_EXCEPTION_BUFFER      AgentExceptionBuffer;\r
   UINT32                            IssuedViewPoint;\r
   DEBUG_AGENT_MAILBOX               *Mailbox;\r
+  UINT8                             *AlignedDataPtr;\r
 \r
   ProcessorIndex  = 0;\r
   IssuedViewPoint = 0;\r
@@ -1644,12 +1857,19 @@ CommandCommunication (
 \r
     case DEBUG_COMMAND_READ_MEMORY:\r
       MemoryRead = (DEBUG_DATA_READ_MEMORY *) (DebugHeader + 1);\r
-      Status = SendDataResponsePacket ((UINT8 *) (UINTN) MemoryRead->Address, (UINT16) (MemoryRead->Count * MemoryRead->Width));\r
+      Status = ReadMemoryAndSendResponsePacket ((UINT8 *) (UINTN) MemoryRead->Address, MemoryRead->Count, MemoryRead->Width);\r
       break;\r
 \r
     case DEBUG_COMMAND_WRITE_MEMORY:\r
       MemoryWrite = (DEBUG_DATA_WRITE_MEMORY *) (DebugHeader + 1);\r
-      CopyMem ((VOID *) (UINTN) MemoryWrite->Address, &MemoryWrite->Data, MemoryWrite->Count * MemoryWrite->Width);\r
+      //\r
+      // Copy data into one memory with 8-byte alignment address\r
+      //\r
+      AlignedDataPtr = ALIGN_POINTER ((UINT8 *) &MemoryWrite->Data, sizeof (UINT64));\r
+      if (AlignedDataPtr != (UINT8 *) &MemoryWrite->Data) {\r
+        CopyMem (AlignedDataPtr, (UINT8 *) &MemoryWrite->Data, MemoryWrite->Count * MemoryWrite->Width);\r
+      }\r
+      CopyMemByWidth ((UINT8 *) (UINTN) MemoryWrite->Address, AlignedDataPtr, MemoryWrite->Count, MemoryWrite->Width);\r
       SendAckPacket (DEBUG_COMMAND_OK);\r
       break;\r
 \r
@@ -1884,6 +2104,7 @@ InterruptProcess (
   UINT32                           IssuedViewPoint;\r
   DEBUG_AGENT_EXCEPTION_BUFFER     *ExceptionBuffer;\r
 \r
+  InputCharacter  = 0;\r
   ProcessorIndex  = 0;\r
   IssuedViewPoint = 0;\r
   BreakReceived   = FALSE;\r
@@ -1915,7 +2136,7 @@ InterruptProcess (
     // the saved CPU content in CommandCommunication()\r
     //\r
     if (GetDebugFlag (DEBUG_AGENT_FLAG_AGENT_IN_PROGRESS) == 1) {\r
-      DebugAgentMsgPrint (DEBUG_AGENT_ERROR, "Debug agent meet one Exception, ExceptionNum is %d.\n", Vector);\r
+      DebugAgentMsgPrint (DEBUG_AGENT_ERROR, "Debug agent meet one Exception, ExceptionNum is %d, EIP = 0x%x.\n", Vector, (UINTN)CpuContext->Eip);\r
       ExceptionBuffer = (DEBUG_AGENT_EXCEPTION_BUFFER *) (UINTN) GetMailboxPointer()->ExceptionBufferPointer;\r
       ExceptionBuffer->ExceptionContent.ExceptionNum  = (UINT8) Vector;\r
       ExceptionBuffer->ExceptionContent.ExceptionData = (UINT32) CpuContext->ExceptionData;\r