]> git.proxmox.com Git - mirror_edk2.git/blobdiff - SourceLevelDebugPkg/Library/DebugAgent/DebugAgentCommon/DebugAgent.c
SourceLevelDebugPkg/DebugAgent: Fix various typos
[mirror_edk2.git] / SourceLevelDebugPkg / Library / DebugAgent / DebugAgentCommon / DebugAgent.c
index 7834f885cc12badec2c3d3a3b00fbcec57429abd..8021437ca903a52ac25d1b85cc928381a56270d1 100644 (file)
 /** @file\r
-  Commond Debug Agent library implementition. It mainly includes\r
+  Commond Debug Agent library implementation. It mainly includes\r
   the first C function called by exception/interrupt handlers,\r
   read/write debug packet to communication with HOST based on transfer\r
   protocol.\r
 \r
-  Copyright (c) 2010, 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) 2010 - 2018, Intel Corporation. All rights reserved.<BR>\r
+  SPDX-License-Identifier: BSD-2-Clause-Patent\r
 \r
 **/\r
 \r
 #include "DebugAgent.h"\r
 #include "Ia32/DebugException.h"\r
 \r
+GLOBAL_REMOVE_IF_UNREFERENCED CHAR8 mErrorMsgVersionAlert[]       = "\rThe SourceLevelDebugPkg you are using requires a newer version of the Intel(R) UDK Debugger Tool.\r\n";\r
+GLOBAL_REMOVE_IF_UNREFERENCED CHAR8 mErrorMsgSendInitPacket[]     = "\rSend INIT break packet and try to connect the HOST (Intel(R) UDK Debugger Tool v1.5) ...\r\n";\r
+GLOBAL_REMOVE_IF_UNREFERENCED CHAR8 mErrorMsgConnectOK[]          = "HOST connection is successful!\r\n";\r
+GLOBAL_REMOVE_IF_UNREFERENCED CHAR8 mErrorMsgConnectFail[]        = "HOST connection is failed!\r\n";\r
+GLOBAL_REMOVE_IF_UNREFERENCED 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
+GLOBAL_REMOVE_IF_UNREFERENCED 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
+GLOBAL_REMOVE_IF_UNREFERENCED UINTN mVectorHandoffInfoCount = sizeof (mVectorHandoffInfoDebugAgent) / sizeof (EFI_VECTOR_HANDOFF_INFO);\r
+\r
+/**\r
+  Calculate CRC16 for target data.\r
+\r
+  @param[in]  Data              The target data.\r
+  @param[in]  DataSize          The target data size.\r
+  @param[in]  Crc               Initial CRC.\r
+\r
+  @return UINT16     The CRC16 value.\r
+\r
+**/\r
+UINT16\r
+CalculateCrc16 (\r
+  IN UINT8   *Data,\r
+  IN UINTN   DataSize,\r
+  IN UINT16  Crc\r
+  )\r
+{\r
+  UINTN  Index;\r
+  UINTN  BitIndex;\r
+\r
+  for (Index = 0; Index < DataSize; Index++) {\r
+    Crc ^= (UINT16)Data[Index];\r
+    for (BitIndex = 0; BitIndex < 8; BitIndex++) {\r
+      if ((Crc & 0x8000) != 0) {\r
+        Crc <<= 1;\r
+        Crc ^= 0x1021;\r
+      } else {\r
+        Crc <<= 1;\r
+      }\r
+    }\r
+  }\r
+  return Crc;\r
+}\r
+\r
+\r
 /**\r
-  Check if HOST is connected based on Mailbox.\r
+  Read IDT entry to check if IDT entries are setup by Debug Agent.\r
 \r
-  @retval TRUE        HOST is connected.\r
-  @retval FALSE       HOST is not connected.\r
+  @retval  TRUE     IDT entries were setup by Debug Agent.\r
+  @retval  FALSE    IDT entries were not setup by Debug Agent.\r
 \r
 **/\r
 BOOLEAN\r
-IsHostConnected (\r
+IsDebugAgentInitialzed (\r
   VOID\r
   )\r
 {\r
-  DEBUG_AGENT_MAILBOX          *Mailbox;\r
-\r
-  Mailbox = GetMailboxPointer ();\r
+  UINTN                      InterruptHandler;\r
 \r
-  if (Mailbox->DebugFlag.Bits.HostPresent == 1) {\r
+  InterruptHandler = (UINTN) GetExceptionHandlerInIdtEntry (0);\r
+  if (InterruptHandler >= 4 &&  *(UINT32 *)(InterruptHandler - 4) == AGENT_HANDLER_SIGNATURE) {\r
     return TRUE;\r
   } else {\r
     return FALSE;\r
@@ -42,45 +184,546 @@ IsHostConnected (
 }\r
 \r
 /**\r
-  Set HOST connect flag in Mailbox.\r
+  Find and report module image info to HOST.\r
+\r
+  @param[in] AlignSize      Image aligned size.\r
 \r
 **/\r
 VOID\r
-SetHostConnectedFlag (\r
-  VOID\r
+FindAndReportModuleImageInfo (\r
+  IN UINTN          AlignSize\r
   )\r
 {\r
-  DEBUG_AGENT_MAILBOX          *Mailbox;\r
+  UINTN                                Pe32Data;\r
+  PE_COFF_LOADER_IMAGE_CONTEXT         ImageContext;\r
 \r
-  Mailbox = GetMailboxPointer ();\r
+  //\r
+  // Find Image Base\r
+  //\r
+  Pe32Data = PeCoffSearchImageBase ((UINTN) mErrorMsgVersionAlert);\r
+  if (Pe32Data != 0) {\r
+    ImageContext.ImageAddress = Pe32Data;\r
+    ImageContext.PdbPointer = PeCoffLoaderGetPdbPointer ((VOID*) (UINTN) ImageContext.ImageAddress);\r
+    PeCoffLoaderRelocateImageExtraAction (&ImageContext);\r
+  }\r
+}\r
+\r
+/**\r
+  Trigger one software interrupt to debug agent to handle it.\r
+\r
+  @param[in] Signature       Software interrupt signature.\r
+\r
+**/\r
+VOID\r
+TriggerSoftInterrupt (\r
+  IN UINT32                 Signature\r
+  )\r
+{\r
+  UINTN                  Dr0;\r
+  UINTN                  Dr1;\r
+\r
+  //\r
+  // Save Debug Register State\r
+  //\r
+  Dr0 = AsmReadDr0 ();\r
+  Dr1 = AsmReadDr1 ();\r
+\r
+  //\r
+  // DR0 = Signature\r
+  //\r
+  AsmWriteDr0 (SOFT_INTERRUPT_SIGNATURE);\r
+  AsmWriteDr1 (Signature);\r
+\r
+  //\r
+  // Do INT3 to communicate with HOST side\r
+  //\r
+  CpuBreakpoint ();\r
+\r
+  //\r
+  // Restore Debug Register State only when Host didn't change it inside exception handler.\r
+  //   Dr registers can only be changed by setting the HW breakpoint.\r
+  //\r
+  AsmWriteDr0 (Dr0);\r
+  AsmWriteDr1 (Dr1);\r
+\r
+}\r
+\r
+/**\r
+  Calculate Mailbox checksum and update the checksum field.\r
+\r
+  @param[in]  Mailbox  Debug Agent Mailbox pointer.\r
+\r
+**/\r
+VOID\r
+UpdateMailboxChecksum (\r
+  IN DEBUG_AGENT_MAILBOX    *Mailbox\r
+  )\r
+{\r
+  Mailbox->CheckSum = CalculateCheckSum8 ((UINT8 *)Mailbox, sizeof (DEBUG_AGENT_MAILBOX) - 2);\r
+}\r
+\r
+/**\r
+  Verify Mailbox checksum.\r
+\r
+  If checksum error, print debug message and run init dead loop.\r
+\r
+  @param[in]  Mailbox  Debug Agent Mailbox pointer.\r
+\r
+**/\r
+VOID\r
+VerifyMailboxChecksum (\r
+  IN DEBUG_AGENT_MAILBOX    *Mailbox\r
+  )\r
+{\r
+  UINT8                     CheckSum;\r
+\r
+  CheckSum = CalculateCheckSum8 ((UINT8 *) Mailbox, sizeof (DEBUG_AGENT_MAILBOX) - 2);\r
+  //\r
+  // The checksum updating process may be disturbed by hardware SMI, we need to check CheckSum field\r
+  // and ToBeCheckSum field to validate the mail box.\r
+  //\r
+  if (CheckSum != Mailbox->CheckSum && CheckSum != Mailbox->ToBeCheckSum) {\r
+    DEBUG ((EFI_D_ERROR, "DebugAgent: Mailbox checksum error, stack or heap crashed!\n"));\r
+    DEBUG ((EFI_D_ERROR, "DebugAgent: CheckSum = %x, Mailbox->CheckSum = %x, Mailbox->ToBeCheckSum = %x\n", CheckSum, Mailbox->CheckSum, Mailbox->ToBeCheckSum));\r
+    CpuDeadLoop ();\r
+  }\r
+}\r
+\r
+/**\r
+  Update Mailbox content by index.\r
+\r
+  @param[in]  Mailbox  Debug Agent Mailbox pointer.\r
+  @param[in]  Index    Mailbox content index.\r
+  @param[in]  Value    Value to be set into Mailbox.\r
+\r
+**/\r
+VOID\r
+UpdateMailboxContent (\r
+  IN DEBUG_AGENT_MAILBOX    *Mailbox,\r
+  IN UINTN                  Index,\r
+  IN UINT64                 Value\r
+  )\r
+{\r
+  AcquireMpSpinLock (&mDebugMpContext.MailboxSpinLock);\r
+  switch (Index) {\r
+  case DEBUG_MAILBOX_DEBUG_FLAG_INDEX:\r
+    Mailbox->ToBeCheckSum = Mailbox->CheckSum + CalculateSum8 ((UINT8 *)&Mailbox->DebugFlag.Uint64, sizeof(UINT64))\r
+                                              - CalculateSum8 ((UINT8 *)&Value, sizeof(UINT64));\r
+    Mailbox->DebugFlag.Uint64 = Value;\r
+    break;\r
+  case DEBUG_MAILBOX_DEBUG_PORT_HANDLE_INDEX:\r
+    Mailbox->ToBeCheckSum = Mailbox->CheckSum + CalculateSum8 ((UINT8 *)&Mailbox->DebugPortHandle, sizeof(UINTN))\r
+                                              - CalculateSum8 ((UINT8 *)&Value, sizeof(UINTN));\r
+    Mailbox->DebugPortHandle = (UINTN) Value;\r
+    break;\r
+  case DEBUG_MAILBOX_EXCEPTION_BUFFER_POINTER_INDEX:\r
+    Mailbox->ToBeCheckSum = Mailbox->CheckSum + CalculateSum8 ((UINT8 *)&Mailbox->ExceptionBufferPointer, sizeof(UINTN))\r
+                                              - CalculateSum8 ((UINT8 *)&Value, sizeof(UINTN));\r
+    Mailbox->ExceptionBufferPointer = (UINTN) Value;\r
+    break;\r
+  case DEBUG_MAILBOX_LAST_ACK:\r
+    Mailbox->ToBeCheckSum = Mailbox->CheckSum + CalculateSum8 ((UINT8 *)&Mailbox->LastAck, sizeof(UINT8))\r
+                                              - CalculateSum8 ((UINT8 *)&Value, sizeof(UINT8));\r
+    Mailbox->LastAck = (UINT8) Value;\r
+    break;\r
+  case DEBUG_MAILBOX_SEQUENCE_NO_INDEX:\r
+    Mailbox->ToBeCheckSum = Mailbox->CheckSum + CalculateSum8 ((UINT8 *)&Mailbox->SequenceNo, sizeof(UINT8))\r
+                                              - CalculateSum8 ((UINT8 *)&Value, sizeof(UINT8));\r
+    Mailbox->SequenceNo = (UINT8) Value;\r
+    break;\r
+  case DEBUG_MAILBOX_HOST_SEQUENCE_NO_INDEX:\r
+    Mailbox->ToBeCheckSum = Mailbox->CheckSum + CalculateSum8 ((UINT8 *)&Mailbox->HostSequenceNo, sizeof(UINT8))\r
+                                              - 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
-  Mailbox->DebugFlag.Bits.HostPresent = 1;\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 of Debug Agent in Mailbox.\r
+  Set debug flag in mailbox.\r
 \r
-  @param DebugFlag       Debug Flag defined by transfer protocol.\r
+  @param[in]  FlagMask      Debug flag mask value.\r
+  @param[in]  FlagValue     Debug flag value.\r
 \r
 **/\r
 VOID\r
 SetDebugFlag (\r
-  IN UINT32               DebugFlag\r
+  IN UINT64                 FlagMask,\r
+  IN UINT32                 FlagValue\r
+  )\r
+{\r
+  DEBUG_AGENT_MAILBOX    *Mailbox;\r
+  UINT64                 Data64;\r
+\r
+  Mailbox = GetMailboxPointer ();\r
+  Data64 = (Mailbox->DebugFlag.Uint64 & ~FlagMask) |\r
+           (LShiftU64 ((UINT64)FlagValue, LowBitSet64 (FlagMask)) & FlagMask);\r
+  UpdateMailboxContent (Mailbox, DEBUG_MAILBOX_DEBUG_FLAG_INDEX, Data64);\r
+}\r
+\r
+/**\r
+  Get debug flag in mailbox.\r
+\r
+  @param[in]  FlagMask      Debug flag mask value.\r
+\r
+  @return Debug flag value.\r
+\r
+**/\r
+UINT32\r
+GetDebugFlag (\r
+  IN UINT64                 FlagMask\r
   )\r
 {\r
-  DEBUG_AGENT_MAILBOX          *Mailbox;\r
+  DEBUG_AGENT_MAILBOX    *Mailbox;\r
+  UINT32                 DebugFlag;\r
 \r
   Mailbox = GetMailboxPointer ();\r
+  DebugFlag = (UINT32) RShiftU64 (Mailbox->DebugFlag.Uint64 & FlagMask, LowBitSet64 (FlagMask));\r
+\r
+  return DebugFlag;\r
+}\r
+\r
+/**\r
+  Send a debug message packet to the debug port.\r
+\r
+  @param[in] Buffer  The debug message.\r
+  @param[in] Length  The length of debug message.\r
+\r
+**/\r
+VOID\r
+SendDebugMsgPacket (\r
+  IN CHAR8         *Buffer,\r
+  IN UINTN         Length\r
+  )\r
+{\r
+  DEBUG_PACKET_HEADER  DebugHeader;\r
+  DEBUG_PORT_HANDLE    Handle;\r
+\r
+  Handle = GetDebugPortHandle();\r
+\r
+  DebugHeader.StartSymbol = DEBUG_STARTING_SYMBOL_NORMAL;\r
+  DebugHeader.Command     = DEBUG_COMMAND_PRINT_MESSAGE;\r
+  DebugHeader.Length      = sizeof (DEBUG_PACKET_HEADER) + (UINT8) Length;\r
+  DebugHeader.SequenceNo  = 0xEE;\r
+  DebugHeader.Crc         = 0;\r
+  DebugHeader.Crc         = CalculateCrc16 (\r
+                              (UINT8 *)Buffer, Length,\r
+                              CalculateCrc16 ((UINT8 *)&DebugHeader, sizeof (DEBUG_PACKET_HEADER), 0)\r
+                              );\r
+\r
+  DebugPortWriteBuffer (Handle, (UINT8 *)&DebugHeader, sizeof (DEBUG_PACKET_HEADER));\r
+  DebugPortWriteBuffer (Handle, (UINT8 *)Buffer, Length);\r
+}\r
+\r
+/**\r
+  Prints a debug message to the debug port if the specified error level is enabled.\r
+\r
+  If any bit in ErrorLevel is also set in Mainbox, then print the message specified\r
+  by Format and the associated variable argument list to the debug port.\r
+\r
+  @param[in] ErrorLevel  The error level of the debug message.\r
+  @param[in] Format      Format string for the debug message to print.\r
+  @param[in] ...         Variable argument list whose contents are accessed\r
+                         based on the format string specified by Format.\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+DebugAgentMsgPrint (\r
+  IN UINT8         ErrorLevel,\r
+  IN CHAR8         *Format,\r
+  ...\r
+  )\r
+{\r
+  CHAR8                Buffer[DEBUG_DATA_MAXIMUM_REAL_DATA];\r
+  VA_LIST              Marker;\r
+\r
+  //\r
+  // Check driver debug mask value and global mask\r
+  //\r
+  if ((ErrorLevel & GetDebugFlag (DEBUG_AGENT_FLAG_PRINT_ERROR_LEVEL)) == 0) {\r
+    return;\r
+  }\r
 \r
-  if ((DebugFlag & SOFT_DEBUGGER_SETTING_SMM_ENTRY_BREAK) != 0) {\r
-    Mailbox->DebugFlag.Bits.BreakOnNextSmi = 1;\r
+  //\r
+  // Convert the DEBUG() message to an ASCII String\r
+  //\r
+  VA_START (Marker, Format);\r
+  AsciiVSPrint (Buffer, sizeof (Buffer), Format, Marker);\r
+  VA_END (Marker);\r
+\r
+  SendDebugMsgPacket (Buffer, AsciiStrLen (Buffer));\r
+}\r
+\r
+/**\r
+  Prints a debug message to the debug output device if the specified error level is enabled.\r
+\r
+  If any bit in ErrorLevel is also set in DebugPrintErrorLevelLib function\r
+  GetDebugPrintErrorLevel (), then print the message specified by Format and the\r
+  associated variable argument list to the debug output device.\r
+\r
+  If Format is NULL, then ASSERT().\r
+\r
+  @param[in] ErrorLevel  The error level of the debug message.\r
+  @param[in] IsSend      Flag of debug message to declare that the data is being sent or being received.\r
+  @param[in] Data        Variable argument list whose contents are accessed\r
+  @param[in] Length      based on the format string specified by Format.\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+DebugAgentDataMsgPrint (\r
+  IN UINT8             ErrorLevel,\r
+  IN BOOLEAN           IsSend,\r
+  IN UINT8             *Data,\r
+  IN UINT8             Length\r
+  )\r
+{\r
+  CHAR8                Buffer[DEBUG_DATA_MAXIMUM_REAL_DATA];\r
+  CHAR8                *DestBuffer;\r
+  UINTN                Index;\r
+\r
+  //\r
+  // Check driver debug mask value and global mask\r
+  //\r
+  if ((ErrorLevel & GetDebugFlag (DEBUG_AGENT_FLAG_PRINT_ERROR_LEVEL)) == 0) {\r
+    return;\r
+  }\r
+\r
+  DestBuffer = Buffer;\r
+  if (IsSend) {\r
+    DestBuffer += AsciiSPrint (DestBuffer, DEBUG_DATA_MAXIMUM_REAL_DATA, "Sent data [ ");\r
   } else {\r
-    Mailbox->DebugFlag.Bits.BreakOnNextSmi = 0;\r
+    DestBuffer += AsciiSPrint (DestBuffer, DEBUG_DATA_MAXIMUM_REAL_DATA, "Received data [ ");\r
+  }\r
+\r
+  Index = 0;\r
+  while (TRUE) {\r
+    if (DestBuffer - Buffer > DEBUG_DATA_MAXIMUM_REAL_DATA - 6) {\r
+      //\r
+      // If there was no enough space in buffer, send out the debug message,\r
+      // reserving 6 bytes is for the last data and end characters "]\n".\r
+      //\r
+      SendDebugMsgPacket (Buffer, DestBuffer - Buffer);\r
+      DestBuffer = Buffer;\r
+    }\r
+    DestBuffer += AsciiSPrint (DestBuffer, DEBUG_DATA_MAXIMUM_REAL_DATA - (DestBuffer - Buffer), "%02x ", Data[Index]);\r
+    Index ++;\r
+    if (Index >= Length) {\r
+      //\r
+      // The last character of debug message has been formatted in buffer\r
+      //\r
+      DestBuffer += AsciiSPrint(DestBuffer, DEBUG_DATA_MAXIMUM_REAL_DATA - (DestBuffer - Buffer), "]\n");\r
+      SendDebugMsgPacket (Buffer, DestBuffer - Buffer);\r
+      break;\r
+    }\r
   }\r
 }\r
 \r
 /**\r
-  Exectue GO command.\r
+  Read remaing debug packet except for the start symbol\r
+\r
+  @param[in]      Handle        Pointer to Debug Port handle.\r
+  @param[in, out] DebugHeader   Debug header buffer including start symbol.\r
+\r
+  @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
+ReadRemainingBreakPacket (\r
+  IN     DEBUG_PORT_HANDLE      Handle,\r
+  IN OUT DEBUG_PACKET_HEADER    *DebugHeader\r
+  )\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 (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
+    DebugAgentMsgPrint (DEBUG_AGENT_WARNING, "Timeout in Debug Timer interrupt\n");\r
+    return EFI_TIMEOUT;\r
+  }\r
+\r
+  Crc = DebugHeader->Crc;\r
+  DebugHeader->Crc = 0;\r
+  if (CalculateCrc16 ((UINT8 *)DebugHeader, DebugHeader->Length, 0) != Crc) {\r
+    DebugAgentMsgPrint (DEBUG_AGENT_WARNING, "Debug Timer CRC (%x) against (%x)\n", Crc, CalculateCrc16 ((UINT8 *) &DebugHeader, DebugHeader->Length, 0));\r
+    DebugAgentDataMsgPrint (DEBUG_AGENT_VERBOSE, FALSE, (UINT8 *)DebugHeader, DebugHeader->Length);\r
+    return EFI_CRC_ERROR;\r
+  }\r
+  Mailbox = GetMailboxPointer();\r
+  if (IS_REQUEST (DebugHeader)) {\r
+    if (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
+    }\r
+    if (DebugHeader->SequenceNo == Mailbox->HostSequenceNo) {\r
+      return EFI_SUCCESS;\r
+    }\r
+  }\r
+\r
+  return EFI_DEVICE_ERROR;\r
+}\r
+\r
+/**\r
+  Check if HOST is attached based on Mailbox.\r
+\r
+  @retval TRUE        HOST is attached.\r
+  @retval FALSE       HOST is not attached.\r
+\r
+**/\r
+BOOLEAN\r
+IsHostAttached (\r
+  VOID\r
+  )\r
+{\r
+  return (BOOLEAN) (GetDebugFlag (DEBUG_AGENT_FLAG_HOST_ATTACHED) == 1);\r
+}\r
+\r
+/**\r
+  Set HOST connect flag in Mailbox.\r
+\r
+  @param[in] Attached        Attach status.\r
+\r
+**/\r
+VOID\r
+SetHostAttached (\r
+  IN BOOLEAN                      Attached\r
+  )\r
+{\r
+  DebugAgentMsgPrint (DEBUG_AGENT_INFO, "Attach status is %d\n", Attached);\r
+  SetDebugFlag (DEBUG_AGENT_FLAG_HOST_ATTACHED, (UINT32)Attached);\r
+}\r
+\r
+/**\r
+  Set debug setting of Debug Agent in Mailbox.\r
+\r
+  @param DebugSetting         Pointer to Debug Setting defined by transfer protocol.\r
+\r
+  @retval RETURN_SUCCESS      The setting is set successfully.\r
+  @retval RETURN_UNSUPPORTED  The Key value is not supported.\r
+\r
+**/\r
+RETURN_STATUS\r
+SetDebugSetting (\r
+  IN DEBUG_DATA_SET_DEBUG_SETTING  *DebugSetting\r
+  )\r
+{\r
+  RETURN_STATUS                Status;\r
+\r
+  Status = RETURN_SUCCESS;\r
+  switch (DebugSetting->Key) {\r
+  case DEBUG_AGENT_SETTING_SMM_ENTRY_BREAK:\r
+    SetDebugFlag (DEBUG_AGENT_FLAG_BREAK_ON_NEXT_SMI, DebugSetting->Value);\r
+    break;\r
+  case DEBUG_AGENT_SETTING_PRINT_ERROR_LEVEL:\r
+    SetDebugFlag (DEBUG_AGENT_FLAG_PRINT_ERROR_LEVEL, DebugSetting->Value);\r
+    break;\r
+  case DEBUG_AGENT_SETTING_BOOT_SCRIPT_ENTRY_BREAK:\r
+    SetDebugFlag (DEBUG_AGENT_FLAG_BREAK_BOOT_SCRIPT, DebugSetting->Value);\r
+    break;\r
+  default:\r
+    Status = RETURN_UNSUPPORTED;\r
+  }\r
+  return Status;\r
+}\r
+\r
+/**\r
+  Execute GO command.\r
 \r
   @param[in] CpuContext        Pointer to saved CPU context.\r
 \r
@@ -98,7 +741,7 @@ CommandGo (
 }\r
 \r
 /**\r
-  Exectue Stepping command.\r
+  Execute Stepping command.\r
 \r
   @param[in] CpuContext        Pointer to saved CPU context.\r
 \r
@@ -113,6 +756,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
@@ -143,12 +819,12 @@ SetDebugRegister (
   //\r
   // Enable Gx, Lx\r
   //\r
-  Dr7Value |= 0x3 << (RegisterIndex * 2);\r
+  Dr7Value |= (UINTN) (0x3 << (RegisterIndex * 2));\r
   //\r
   // Set RWx and Lenx\r
   //\r
-  Dr7Value &= ~(0xf0000 << (RegisterIndex * 4));\r
-  Dr7Value |= (SetHwBreakpoint->Type.Length | SetHwBreakpoint->Type.Access) << (RegisterIndex * 4);\r
+  Dr7Value &= (UINTN) (~(0xf << (16 + RegisterIndex * 4)));\r
+  Dr7Value |= (UINTN) ((SetHwBreakpoint->Type.Length << 2) | SetHwBreakpoint->Type.Access) << (16 + RegisterIndex * 4);\r
   //\r
   // Enable GE, LE\r
   //\r
@@ -172,189 +848,419 @@ ClearDebugRegister (
 {\r
   if ((ClearHwBreakpoint->IndexMask & BIT0) != 0) {\r
     CpuContext->Dr0 = 0;\r
-    CpuContext->Dr7 &= ~(0x3 << 0);\r
+    CpuContext->Dr7 &= (UINTN)(~(0x3 << 0));\r
   }\r
   if ((ClearHwBreakpoint->IndexMask & BIT1) != 0) {\r
     CpuContext->Dr1 = 0;\r
-    CpuContext->Dr7 &= ~(0x3 << 2);\r
+    CpuContext->Dr7 &= (UINTN)(~(0x3 << 2));\r
   }\r
   if ((ClearHwBreakpoint->IndexMask & BIT2) != 0) {\r
     CpuContext->Dr2 = 0;\r
-    CpuContext->Dr7 &= ~(0x3 << 4);\r
+    CpuContext->Dr7 &= (UINTN)(~(0x3 << 4));\r
   }\r
   if ((ClearHwBreakpoint->IndexMask & BIT3) != 0) {\r
     CpuContext->Dr3 = 0;\r
-    CpuContext->Dr7 &= ~(0x3 << 6);\r
+    CpuContext->Dr7 &= (UINTN)(~(0x3 << 6));\r
   }\r
 }\r
 \r
+\r
 /**\r
-  Send acknowledge packet to HOST.\r
+  Return the offset of FP / MMX / XMM registers in the FPU saved state by register index.\r
 \r
-  @param[in] AckCommand    Type of Acknowledge packet.\r
+  @param[in]  Index    Register index.\r
+  @param[out] Width    Register width returned.\r
+\r
+  @return Offset in the FPU Save State.\r
 \r
 **/\r
-VOID\r
-SendAckPacket (\r
-  IN UINT8                AckCommand\r
+UINT16\r
+ArchReadFxStatOffset (\r
+  IN  UINT8                     Index,\r
+  OUT UINT8                     *Width\r
   )\r
 {\r
-  DEBUG_COMMAND_HEADER      DebugCommonHeader;\r
-  DEBUG_PORT_HANDLE         Handle;\r
-\r
-  Handle = GetDebugPortHandle();\r
+  if (Index < SOFT_DEBUGGER_REGISTER_ST0) {\r
+    switch (Index) {\r
+    case SOFT_DEBUGGER_REGISTER_FP_FCW:\r
+      *Width = (UINT8) sizeof (UINT16);\r
+      return OFFSET_OF(DEBUG_DATA_FX_SAVE_STATE, Fcw);\r
+\r
+    case SOFT_DEBUGGER_REGISTER_FP_FSW:\r
+      *Width = (UINT8) sizeof (UINT16);\r
+      return OFFSET_OF(DEBUG_DATA_FX_SAVE_STATE, Fsw);\r
+\r
+    case SOFT_DEBUGGER_REGISTER_FP_FTW:\r
+      *Width = (UINT8) sizeof (UINT16);\r
+      return OFFSET_OF(DEBUG_DATA_FX_SAVE_STATE, Ftw);\r
+\r
+    case SOFT_DEBUGGER_REGISTER_FP_OPCODE:\r
+      *Width = (UINT8) sizeof (UINT16);\r
+      return OFFSET_OF(DEBUG_DATA_FX_SAVE_STATE, Opcode);\r
+\r
+    case SOFT_DEBUGGER_REGISTER_FP_EIP:\r
+      *Width = (UINT8) sizeof (UINT32);\r
+      return OFFSET_OF(DEBUG_DATA_FX_SAVE_STATE, Eip);\r
+\r
+    case SOFT_DEBUGGER_REGISTER_FP_CS:\r
+      *Width = (UINT8) sizeof (UINT16);\r
+      return OFFSET_OF(DEBUG_DATA_FX_SAVE_STATE, Cs);\r
+\r
+    case SOFT_DEBUGGER_REGISTER_FP_DATAOFFSET:\r
+      *Width = (UINT8) sizeof (UINT32);\r
+      return OFFSET_OF(DEBUG_DATA_FX_SAVE_STATE, DataOffset);\r
+\r
+    case SOFT_DEBUGGER_REGISTER_FP_DS:\r
+      *Width = (UINT8) sizeof (UINT16);\r
+      return OFFSET_OF(DEBUG_DATA_FX_SAVE_STATE, Ds);\r
+\r
+    case SOFT_DEBUGGER_REGISTER_FP_MXCSR:\r
+      *Width = (UINT8) sizeof (UINT32);\r
+      return OFFSET_OF(DEBUG_DATA_FX_SAVE_STATE, Mxcsr);\r
+\r
+    case SOFT_DEBUGGER_REGISTER_FP_MXCSR_MASK:\r
+      *Width = (UINT8) sizeof (UINT32);\r
+      return OFFSET_OF(DEBUG_DATA_FX_SAVE_STATE, Mxcsr_Mask);\r
+    }\r
+  }\r
 \r
-  DebugCommonHeader.StartSymbol = DEBUG_STARTING_SYMBOL_NORMAL;\r
-  DebugCommonHeader.Command     = AckCommand;\r
-  DebugCommonHeader.DataLength  = 0;\r
+  if (Index <= SOFT_DEBUGGER_REGISTER_ST7) {\r
+    *Width = 10;\r
+  } else if (Index <= SOFT_DEBUGGER_REGISTER_XMM15) {\r
+    *Width = 16;\r
+  } else {\r
+    //\r
+    // MMX register\r
+    //\r
+    *Width = 8;\r
+    Index -= SOFT_DEBUGGER_REGISTER_MM0 - SOFT_DEBUGGER_REGISTER_ST0;\r
+  }\r
 \r
-  DebugPortWriteBuffer (Handle, (UINT8 *) &DebugCommonHeader, sizeof (DEBUG_COMMAND_HEADER));\r
+  return OFFSET_OF (DEBUG_DATA_FX_SAVE_STATE, St0Mm0) + (Index - SOFT_DEBUGGER_REGISTER_ST0) * 16;\r
 }\r
 \r
 /**\r
-  Receive acknowledge packet from HOST in specified time.\r
+  Return the pointer of the register value in the CPU saved context.\r
 \r
-  @param[out] Ack           Returned acknowlege type from HOST.\r
-  @param[in]  Timeout       Time out value to wait for acknowlege from HOST.\r
-                            The unit is microsecond.\r
-  @param[out] BreakReceived If BreakReceived is not NULL,\r
-                            TRUE is retured if break-in symbol received.\r
-                            FALSE is retured if break-in symbol not received.\r
+  @param[in]  CpuContext         Pointer to saved CPU context.\r
+  @param[in]  Index              Register index value.\r
+  @param[out] Width              Data width to read.\r
 \r
-  @retval  RETRUEN_SUCCESS  Succeed to receive acknowlege packet from HOST,\r
-                            the type of acknowlege packet saved in Ack.\r
-  @retval  RETURN_TIMEOUT   Specified timeout value was up.\r
+  @return The pointer in the CPU saved context.\r
 \r
 **/\r
-RETURN_STATUS\r
-ReceiveAckPacket (\r
-  OUT UINT8                     *Ack,\r
-  IN  UINTN                     Timeout,\r
-  OUT BOOLEAN                   *BreakReceived OPTIONAL\r
+UINT8 *\r
+ArchReadRegisterBuffer (\r
+  IN DEBUG_CPU_CONTEXT               *CpuContext,\r
+  IN UINT8                           Index,\r
+  OUT UINT8                          *Width\r
+  )\r
+{\r
+  UINT8           *Buffer;\r
+\r
+  if (Index < SOFT_DEBUGGER_REGISTER_FP_BASE) {\r
+    Buffer = (UINT8 *) CpuContext + OFFSET_OF (DEBUG_CPU_CONTEXT, Dr0) + Index * sizeof (UINTN);\r
+    *Width = (UINT8) sizeof (UINTN);\r
+  } else {\r
+    //\r
+    // FPU/MMX/XMM registers\r
+    //\r
+    Buffer = (UINT8 *) CpuContext + OFFSET_OF (DEBUG_CPU_CONTEXT, FxSaveState) + ArchReadFxStatOffset (Index, Width);\r
+  }\r
+\r
+  return Buffer;\r
+}\r
+\r
+/**\r
+  Send the packet without data to HOST.\r
+\r
+  @param[in] CommandType    Type of Command.\r
+  @param[in] SequenceNo     Sequence number.\r
+\r
+**/\r
+VOID\r
+SendPacketWithoutData (\r
+  IN UINT8                  CommandType,\r
+  IN UINT8                  SequenceNo\r
   )\r
 {\r
-  DEBUG_COMMAND_HEADER      DebugCommonHeader;\r
+  DEBUG_PACKET_HEADER       DebugHeader;\r
   DEBUG_PORT_HANDLE         Handle;\r
 \r
   Handle = GetDebugPortHandle();\r
 \r
-  while (TRUE) {\r
-    if (DebugPortReadBuffer (Handle, (UINT8 *) &DebugCommonHeader.StartSymbol, 1, Timeout) == 0) {\r
-      return RETURN_TIMEOUT;\r
-    }\r
-    if (DebugCommonHeader.StartSymbol == DEBUG_STARTING_SYMBOL_BREAK) {\r
-      if (BreakReceived != NULL) {\r
-        SendAckPacket (DEBUG_COMMAND_HALT_DEFERRED);\r
-        *BreakReceived = TRUE;\r
-      }\r
-    }\r
-    if (DebugCommonHeader.StartSymbol == DEBUG_STARTING_SYMBOL_NORMAL) {\r
-      break;\r
-    }\r
-  }\r
-  if (DebugPortReadBuffer (Handle, (UINT8 *)&DebugCommonHeader.Command, sizeof (DEBUG_COMMAND_HEADER) - 1, Timeout) == 0) {\r
-    return RETURN_TIMEOUT;\r
-  }\r
+  DebugHeader.StartSymbol = DEBUG_STARTING_SYMBOL_NORMAL;\r
+  DebugHeader.Command     = CommandType;\r
+  DebugHeader.Length      = sizeof (DEBUG_PACKET_HEADER);\r
+  DebugHeader.SequenceNo  = SequenceNo;\r
+  DebugHeader.Crc         = 0;\r
+  DebugHeader.Crc         = CalculateCrc16 ((UINT8 *)&DebugHeader, sizeof (DEBUG_PACKET_HEADER), 0);\r
 \r
-  *Ack = DebugCommonHeader.Command;\r
-  return RETURN_SUCCESS;\r
+  DebugAgentDataMsgPrint (DEBUG_AGENT_VERBOSE, TRUE, (UINT8 *) &DebugHeader, DebugHeader.Length);\r
+  DebugPortWriteBuffer (Handle, (UINT8 *) &DebugHeader, DebugHeader.Length);\r
 }\r
 \r
 /**\r
-  Receive acknowledge packet OK from HOST in specified time.\r
-\r
-  @param[in]  Timeout       Time out value to wait for acknowlege from HOST.\r
-                            The unit is microsecond.\r
-  @param[out] BreakReceived If BreakReceived is not NULL,\r
-                            TRUE is retured if break-in symbol received.\r
-                            FALSE is retured if break-in symbol not received.\r
+  Send acknowledge packet to HOST.\r
 \r
-  @retval  RETRUEN_SUCCESS  Succeed to receive acknowlege packet from HOST,\r
-                            the type of acknowlege packet saved in Ack.\r
-  @retval  RETURN_TIMEOUT   Specified timeout value was up.\r
+  @param[in] AckCommand    Type of Acknowledge packet.\r
 \r
 **/\r
-RETURN_STATUS\r
-WaitForAckPacketOK (\r
-  IN  UINTN                     Timeout,\r
-  OUT BOOLEAN                   *BreakReceived OPTIONAL\r
+VOID\r
+SendAckPacket (\r
+  IN UINT8                AckCommand\r
   )\r
 {\r
-  RETURN_STATUS             Status;\r
-  UINT8                     Ack;\r
+  UINT8                   SequenceNo;\r
+  DEBUG_AGENT_MAILBOX     *Mailbox;\r
 \r
-  while (TRUE) {\r
-    Status = ReceiveAckPacket (&Ack, Timeout, BreakReceived);\r
-    if ((Status == RETURN_SUCCESS && Ack == DEBUG_COMMAND_OK) ||\r
-         Status == RETURN_TIMEOUT) {\r
-      break;\r
+  if (AckCommand != DEBUG_COMMAND_OK) {\r
+    //\r
+    // This is not ACK OK packet\r
+    //\r
+    DebugAgentMsgPrint (DEBUG_AGENT_ERROR, "Send ACK(%d)\n", AckCommand);\r
+  }\r
+  Mailbox = GetMailboxPointer();\r
+  SequenceNo = Mailbox->HostSequenceNo;\r
+  DebugAgentMsgPrint (DEBUG_AGENT_INFO, "SendAckPacket: SequenceNo = %x\n", SequenceNo);\r
+  SendPacketWithoutData (AckCommand, SequenceNo);\r
+  UpdateMailboxContent (Mailbox, DEBUG_MAILBOX_LAST_ACK, AckCommand);\r
+}\r
+\r
+/**\r
+  Decompress the Data in place.\r
+\r
+  @param[in, out] Data   The compressed data buffer.\r
+                         The buffer is assumed large enough to hold the uncompressed data.\r
+  @param[in]      Length The length of the compressed data buffer.\r
+\r
+  @return   The length of the uncompressed data buffer.\r
+**/\r
+UINT8\r
+DecompressDataInPlace (\r
+  IN OUT UINT8   *Data,\r
+  IN UINTN       Length\r
+  )\r
+{\r
+  UINTN  Index;\r
+  UINT16 LastChar;\r
+  UINTN  LastCharCount;\r
+  UINT8  CurrentChar;\r
+\r
+  LastChar = (UINT16) -1;\r
+  LastCharCount = 0;\r
+  for (Index = 0; Index < Length; Index++) {\r
+    CurrentChar = Data[Index];\r
+    if (LastCharCount == 2) {\r
+      LastCharCount = 0;\r
+      CopyMem (&Data[Index + CurrentChar], &Data[Index + 1], Length - Index - 1);\r
+      SetMem (&Data[Index], CurrentChar, (UINT8) LastChar);\r
+      LastChar = (UINT16) -1;\r
+      Index += CurrentChar - 1;\r
+      Length += CurrentChar - 1;\r
+    } else {\r
+      if (LastChar != CurrentChar) {\r
+        LastCharCount = 0;\r
+      }\r
+      LastCharCount++;\r
+      LastChar = CurrentChar;\r
     }\r
   }\r
 \r
-  return Status;\r
+  ASSERT (Length <= DEBUG_DATA_MAXIMUM_REAL_DATA);\r
+\r
+  return (UINT8) Length;\r
 }\r
 \r
 /**\r
   Receive valid packet from HOST.\r
 \r
-  @param[out] InputPacket    Buffer to receive packet.\r
-  @param[out] BreakReceived  TRUE means break-in symbol received.\r
-                             FALSE means break-in symbol not received.\r
-\r
-  @retval RETURN_SUCCESS   A valid package was reveived in InputPacket.\r
-  @retval RETURN_NOT_READY No valid start symbol received.\r
+  @param[out] InputPacket         Buffer to receive packet.\r
+  @param[out] BreakReceived       TRUE means break-in symbol received.\r
+                                  FALSE means break-in symbol not received.\r
+  @param[out] IncompatibilityFlag If IncompatibilityFlag is not NULL, return\r
+                                  TRUE:  Compatible packet received.\r
+                                  FALSE: Incompatible packet received.\r
+  @param[in]  Timeout             Time out value to wait for acknowledge from HOST.\r
+                                  The unit is microsecond.\r
+  @param[in]  SkipStartSymbol     TRUE:  Skip time out when reading start symbol.\r
+                                  FALSE: Does not Skip time out when reading start symbol.\r
+\r
+  @retval RETURN_SUCCESS   A valid package was received in InputPacket.\r
   @retval RETURN_TIMEOUT   Timeout occurs.\r
 \r
 **/\r
 RETURN_STATUS\r
 ReceivePacket (\r
   OUT UINT8             *InputPacket,\r
-  OUT BOOLEAN           *BreakReceived\r
+  OUT BOOLEAN           *BreakReceived,\r
+  OUT BOOLEAN           *IncompatibilityFlag, OPTIONAL\r
+  IN  UINTN             Timeout,\r
+  IN  BOOLEAN           SkipStartSymbol\r
   )\r
 {\r
-  DEBUG_COMMAND_HEADER  *DebugHeader;\r
+  DEBUG_PACKET_HEADER   *DebugHeader;\r
   UINTN                 Received;\r
   DEBUG_PORT_HANDLE     Handle;\r
+  UINT16                Crc;\r
+  UINTN                 TimeoutForStartSymbol;\r
 \r
   Handle = GetDebugPortHandle();\r
-  //\r
-  // Find the valid start symbol\r
-  //\r
-  DebugPortReadBuffer (Handle, InputPacket, 1, 0);\r
-\r
-  if (*InputPacket == DEBUG_STARTING_SYMBOL_BREAK) {\r
-    *BreakReceived = TRUE;\r
-    SendAckPacket (DEBUG_COMMAND_HALT_DEFERRED);\r
-  }\r
-\r
-  if (*InputPacket != DEBUG_STARTING_SYMBOL_NORMAL) {\r
-    return RETURN_NOT_READY;\r
+  if (SkipStartSymbol) {\r
+    TimeoutForStartSymbol = 0;\r
+  } else {\r
+    TimeoutForStartSymbol = Timeout;\r
   }\r
 \r
-  //\r
-  // Read Package header\r
-  //\r
-  Received = DebugPortReadBuffer (Handle, InputPacket + 1, sizeof(DEBUG_COMMAND_HEADER_NO_START_SYMBOL), 0);\r
-  if (Received == 0) {\r
-    return RETURN_TIMEOUT;\r
-  }\r
+  DebugHeader = (DEBUG_PACKET_HEADER *) InputPacket;\r
+  while (TRUE) {\r
+    //\r
+    // Find the valid start symbol\r
+    //\r
+    Received = DebugAgentReadBuffer (Handle, &DebugHeader->StartSymbol, sizeof (DebugHeader->StartSymbol), TimeoutForStartSymbol);\r
+    if (Received < sizeof (DebugHeader->StartSymbol)) {\r
+      DebugAgentMsgPrint (DEBUG_AGENT_WARNING, "DebugAgentReadBuffer(StartSymbol) timeout\n");\r
+      return RETURN_TIMEOUT;\r
+    }\r
 \r
-  DebugHeader = (DEBUG_COMMAND_HEADER *) InputPacket;\r
-  //\r
-  // Read the payload if has\r
-  //\r
-  if (DebugHeader->DataLength > 0 && DebugHeader->DataLength < (DEBUG_DATA_MAXIMUM_REAL_DATA - sizeof(DEBUG_COMMAND_HEADER))) {\r
-    InputPacket = InputPacket + 1 + Received;\r
-    Received = DebugPortReadBuffer (Handle, InputPacket, DebugHeader->DataLength, 0);\r
+    if ((DebugHeader->StartSymbol != DEBUG_STARTING_SYMBOL_NORMAL) && (DebugHeader->StartSymbol != DEBUG_STARTING_SYMBOL_COMPRESS)) {\r
+      DebugAgentMsgPrint (DEBUG_AGENT_WARNING, "Invalid start symbol received [%02x]\n", DebugHeader->StartSymbol);\r
+      continue;\r
+    }\r
 \r
+    //\r
+    // Read Package header till field Length\r
+    //\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, "DebugAgentReadBuffer(Command) timeout\n");\r
       return RETURN_TIMEOUT;\r
     }\r
+    if (DebugHeader->Length < sizeof (DEBUG_PACKET_HEADER)) {\r
+      if (IncompatibilityFlag != NULL) {\r
+        //\r
+        // This is one old version debug packet format, set Incompatibility flag\r
+        //\r
+        *IncompatibilityFlag = TRUE;\r
+      } else {\r
+        //\r
+        // Skip the bad small packet\r
+        //\r
+        continue;\r
+      }\r
+    } else {\r
+      //\r
+      // Read the payload data include the CRC field\r
+      //\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, "DebugAgentReadBuffer(SequenceNo) timeout\n");\r
+        return RETURN_TIMEOUT;\r
+      }\r
+      //\r
+      // Calculate the CRC of Debug Packet\r
+      //\r
+      Crc = DebugHeader->Crc;\r
+      DebugHeader->Crc = 0;\r
+      if (Crc == CalculateCrc16 ((UINT8 *) DebugHeader, DebugHeader->Length, 0)) {\r
+        break;\r
+      }\r
+      DebugAgentMsgPrint (DEBUG_AGENT_WARNING, "CRC Error (received CRC is %x)\n", Crc);\r
+      DebugAgentDataMsgPrint (DEBUG_AGENT_VERBOSE, FALSE, (UINT8 *) DebugHeader, DebugHeader->Length);\r
+    }\r
   }\r
 \r
+  DebugAgentDataMsgPrint (DEBUG_AGENT_VERBOSE, FALSE, (UINT8 *) DebugHeader, DebugHeader->Length);\r
+\r
+  if (DebugHeader->StartSymbol == DEBUG_STARTING_SYMBOL_COMPRESS) {\r
+    DebugHeader->StartSymbol = DEBUG_STARTING_SYMBOL_NORMAL;\r
+    DebugHeader->Length      = DecompressDataInPlace (\r
+                                 (UINT8 *) (DebugHeader + 1), DebugHeader->Length - sizeof (DEBUG_PACKET_HEADER)\r
+                                 ) + sizeof (DEBUG_PACKET_HEADER);\r
+  }\r
   return RETURN_SUCCESS;\r
 }\r
 \r
+/**\r
+  Receive acknowledge packet OK from HOST in specified time.\r
+\r
+  @param[in]  Command             The command type issued by TARGET.\r
+  @param[in]  Timeout             Time out value to wait for acknowledge from HOST.\r
+                                  The unit is microsecond.\r
+  @param[out] BreakReceived       If BreakReceived is not NULL,\r
+                                  TRUE is returned if break-in symbol received.\r
+                                  FALSE is returned if break-in symbol not received.\r
+  @param[out] IncompatibilityFlag If IncompatibilityFlag is not NULL, return\r
+                                  TRUE:  Compatible packet received.\r
+                                  FALSE: Incompatible packet received.\r
+\r
+  @retval  RETURN_SUCCESS   Succeed to receive acknowledge packet from HOST,\r
+                            the type of acknowledge packet saved in Ack.\r
+  @retval  RETURN_TIMEOUT   Specified timeout value was up.\r
+\r
+**/\r
+RETURN_STATUS\r
+SendCommandAndWaitForAckOK (\r
+  IN  UINT8               Command,\r
+  IN  UINTN               Timeout,\r
+  OUT BOOLEAN             *BreakReceived, OPTIONAL\r
+  OUT BOOLEAN             *IncompatibilityFlag OPTIONAL\r
+  )\r
+{\r
+  RETURN_STATUS           Status;\r
+  UINT8                   InputPacketBuffer[DEBUG_DATA_UPPER_LIMIT];\r
+  DEBUG_PACKET_HEADER     *DebugHeader;\r
+  UINT8                   SequenceNo;\r
+  UINT8                   HostSequenceNo;\r
+  UINT8                   RetryCount;\r
+\r
+  RetryCount  = 3;\r
+  DebugHeader = (DEBUG_PACKET_HEADER *) InputPacketBuffer;\r
+  Status      = RETURN_TIMEOUT;\r
+  while (RetryCount > 0) {\r
+    SequenceNo = GetMailboxPointer()->SequenceNo;\r
+    HostSequenceNo = GetMailboxPointer()->HostSequenceNo;\r
+    SendPacketWithoutData (Command, SequenceNo);\r
+    Status = ReceivePacket ((UINT8 *) DebugHeader, BreakReceived, IncompatibilityFlag, Timeout, FALSE);\r
+    if (Status == RETURN_TIMEOUT) {\r
+      if (Command == DEBUG_COMMAND_INIT_BREAK) {\r
+        RetryCount--;\r
+      } else {\r
+        DebugAgentMsgPrint (DEBUG_AGENT_WARNING, "TARGET: Timeout when waiting for ACK packet.\n");\r
+      }\r
+      continue;\r
+    }\r
+    ASSERT_EFI_ERROR (Status);\r
+    //\r
+    // Status == RETURN_SUCCESS\r
+    //\r
+    if (DebugHeader->Command == DEBUG_COMMAND_OK && DebugHeader->SequenceNo == SequenceNo) {\r
+      //\r
+      // Received Ack OK\r
+      //\r
+      UpdateMailboxContent (GetMailboxPointer(), DEBUG_MAILBOX_SEQUENCE_NO_INDEX, ++SequenceNo);\r
+      return Status;\r
+    }\r
+    if (DebugHeader->Command == DEBUG_COMMAND_GO && (DebugHeader->SequenceNo == HostSequenceNo || Command == DEBUG_COMMAND_INIT_BREAK)) {\r
+      //\r
+      // Received Old GO\r
+      //\r
+      if (Command == DEBUG_COMMAND_INIT_BREAK) {\r
+        DebugAgentMsgPrint (DEBUG_AGENT_WARNING, "TARGET: Receive GO() in last boot\n");\r
+      }\r
+      SendPacketWithoutData (DEBUG_COMMAND_OK, DebugHeader->SequenceNo);\r
+    }\r
+  }\r
+\r
+  ASSERT (Command == DEBUG_COMMAND_INIT_BREAK);\r
+  return Status;\r
+}\r
+\r
 /**\r
   Get current break cause.\r
 \r
@@ -385,8 +1291,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
@@ -406,13 +1316,13 @@ GetBreakCause (
 \r
       if (CpuContext->Dr3 == IO_PORT_BREAKPOINT_ADDRESS) {\r
 \r
-        Cause = (UINT8) ((CpuContext->Dr0 == IMAGE_LOAD_SIGNATURE) ? \r
+        Cause = (UINT8) ((CpuContext->Dr0 == IMAGE_LOAD_SIGNATURE) ?\r
           DEBUG_DATA_BREAK_CAUSE_IMAGE_LOAD : DEBUG_DATA_BREAK_CAUSE_IMAGE_UNLOAD);\r
       }\r
       break;\r
 \r
     case SOFT_INTERRUPT_SIGNATURE:\r
-   \r
+\r
       if (CpuContext->Dr1 == MEMORY_READY_SIGNATURE) {\r
         Cause = DEBUG_DATA_BREAK_CAUSE_MEMORY_READY;\r
         CpuContext->Dr0 = 0;\r
@@ -435,7 +1345,14 @@ GetBreakCause (
 \r
   default:\r
     if (Vector < 20) {\r
-      Cause = DEBUG_DATA_BREAK_CAUSE_EXCEPTION;\r
+      if (GetDebugFlag (DEBUG_AGENT_FLAG_STEPPING) == 1) {\r
+        //\r
+        // If stepping command is executing\r
+        //\r
+        Cause = DEBUG_DATA_BREAK_CAUSE_STEPPING;\r
+      } else {\r
+        Cause = DEBUG_DATA_BREAK_CAUSE_EXCEPTION;\r
+      }\r
     }\r
     break;\r
   }\r
@@ -444,114 +1361,423 @@ 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
+  Compress the data buffer but do not modify the original buffer.\r
+\r
+  The compressed data is directly send to the debug channel.\r
+  Compressing in place doesn't work because the data may become larger\r
+  during compressing phase. ("3 3 ..." --> "3 3 0 ...")\r
+  The routine is expected to be called three times:\r
+  1. Compute the length of the compressed data buffer;\r
+  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
+**/\r
+VOID\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
+  )\r
+{\r
+  UINTN                 Index;\r
+  UINT8                 LastChar;\r
+  UINT8                 LastCharCount;\r
+  UINT8                 CurrentChar;\r
+  UINTN                 CompressedIndex;\r
+\r
+  ASSERT (Length > 0);\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
+    if (Index < Length) {\r
+      CurrentChar = Data[Index];\r
+    } else {\r
+      CurrentChar = (UINT8) LastChar + 1; // just ensure it's different from LastChar\r
+    }\r
+    if (LastChar != CurrentChar) {\r
+      if (LastCharCount == 1) {\r
+        CompressedIndex++;\r
+        if (CompressedCrc != NULL) {\r
+          *CompressedCrc = CalculateCrc16 (&LastChar, 1, *CompressedCrc);\r
+        }\r
+        if (Send) {\r
+          DebugPortWriteBuffer (Handle, &LastChar, 1);\r
+        }\r
+\r
+      } else if (LastCharCount >= 2) {\r
+        CompressedIndex += 3;\r
+        LastCharCount -= 2;\r
+        if (CompressedCrc != NULL) {\r
+          *CompressedCrc = CalculateCrc16 (&LastChar, 1, *CompressedCrc);\r
+          *CompressedCrc = CalculateCrc16 (&LastChar, 1, *CompressedCrc);\r
+          *CompressedCrc = CalculateCrc16 (&LastCharCount, 1, *CompressedCrc);\r
+        }\r
+        if (Send) {\r
+          DebugPortWriteBuffer (Handle, &LastChar, 1);\r
+          DebugPortWriteBuffer (Handle, &LastChar, 1);\r
+          DebugPortWriteBuffer (Handle, &LastCharCount, 1);\r
+        }\r
+      }\r
+      LastCharCount = 0;\r
+    }\r
+    LastCharCount++;\r
+    LastChar = CurrentChar;\r
+  }\r
+\r
+  if (CompressedLength != NULL) {\r
+    *CompressedLength = CompressedIndex;\r
+  }\r
+}\r
+\r
+/**\r
+  Read memory with specified width and send packet with response data to HOST.\r
 \r
-  @param[in] CpuContext  Pointer to saved CPU context.\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
+  @param[in] DebugHeader Pointer to a buffer for creating response packet and receiving ACK packet,\r
+                         to minimize the stack usage.\r
 \r
   @retval RETURN_SUCCESS      Response data was sent successfully.\r
-  @retval RETURN_DEVICE_ERROR Cannot receive DEBUG_COMMAND_OK from HOST.\r
 \r
 **/\r
 RETURN_STATUS\r
-SendDataResponsePacket (\r
-  IN DEBUG_CPU_CONTEXT    *CpuContext,\r
-  IN UINT8                *Data,\r
-  IN UINT16               DataSize\r
+ReadMemoryAndSendResponsePacket (\r
+  IN UINT8                   *Data,\r
+  IN UINT16                  Count,\r
+  IN UINT8                   Width,\r
+  IN DEBUG_PACKET_HEADER     *DebugHeader\r
   )\r
 {\r
-  UINT8                PacketHeader[DEBUG_DATA_MAXIMUM_LENGTH_FOR_SMALL_COMMANDS];\r
+  RETURN_STATUS        Status;\r
   BOOLEAN              LastPacket;\r
-  UINT8                Ack;\r
-  UINT8                PacketData[DEBUG_DATA_MAXIMUM_REAL_DATA];\r
   DEBUG_PORT_HANDLE    Handle;\r
+  UINT8                SequenceNo;\r
+  UINTN                RemainingDataSize;\r
+  UINT8                CurrentDataSize;\r
+  UINTN                CompressedDataSize;\r
 \r
   Handle = GetDebugPortHandle();\r
 \r
-  ((DEBUG_COMMAND_HEADER *)PacketHeader)->StartSymbol = DEBUG_STARTING_SYMBOL_NORMAL;\r
-\r
+  RemainingDataSize = Count * Width;\r
   while (TRUE) {\r
-    if (DataSize <= DEBUG_DATA_MAXIMUM_REAL_DATA) {\r
+    SequenceNo = GetMailboxPointer()->HostSequenceNo;\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 = (UINT8) RemainingDataSize;\r
       LastPacket = TRUE;\r
-      ((DEBUG_COMMAND_HEADER *)PacketHeader)->Command     = DEBUG_COMMAND_OK;\r
-      ((DEBUG_COMMAND_HEADER *)PacketHeader)->DataLength  = (UINT8) DataSize;\r
-      CopyMem (PacketData, 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
-      ((DEBUG_COMMAND_HEADER *)PacketHeader)->Command     = DEBUG_COMMAND_IN_PROGRESS;\r
-      ((DEBUG_COMMAND_HEADER *)PacketHeader)->DataLength  = DEBUG_DATA_MAXIMUM_REAL_DATA;\r
-      CopyMem (PacketData, Data, DEBUG_DATA_MAXIMUM_REAL_DATA);\r
+      DebugHeader->Command = DEBUG_COMMAND_IN_PROGRESS;\r
     }\r
+    //\r
+    // Construct the rest Debug header\r
+    //\r
+    DebugHeader->StartSymbol = DEBUG_STARTING_SYMBOL_NORMAL;\r
+    DebugHeader->Length      = CurrentDataSize + sizeof (DEBUG_PACKET_HEADER);\r
+    DebugHeader->SequenceNo  = SequenceNo;\r
+    DebugHeader->Crc         = 0;\r
+    CopyMemByWidth ((UINT8 *) (DebugHeader + 1), Data, CurrentDataSize / Width, Width);\r
 \r
-    DebugPortWriteBuffer (Handle, PacketHeader, sizeof (DEBUG_COMMAND_HEADER));\r
-    DebugPortWriteBuffer (Handle, PacketData, ((DEBUG_COMMAND_HEADER *)PacketHeader)->DataLength);\r
-\r
-    ReceiveAckPacket(&Ack, 0, NULL);\r
-    switch (Ack) {\r
-    case DEBUG_COMMAND_RESEND:\r
+    //\r
+    // Compression/decompression support was added since revision 0.4.\r
+    // Revision 0.3 shouldn't compress the packet.\r
+    //\r
+    if (PcdGet32(PcdTransferProtocolRevision) >= DEBUG_AGENT_REVISION_04) {\r
       //\r
-      // Send the packet again\r
+      // Get the compressed data size without modifying the packet.\r
       //\r
-      break;\r
+      CompressData (\r
+        Handle,\r
+        (UINT8 *) (DebugHeader + 1),\r
+        CurrentDataSize,\r
+        FALSE,\r
+        &CompressedDataSize,\r
+        NULL\r
+        );\r
+    } else {\r
+      CompressedDataSize = CurrentDataSize;\r
+    }\r
+    if (CompressedDataSize < CurrentDataSize) {\r
+      DebugHeader->Length = (UINT8) CompressedDataSize + sizeof (DEBUG_PACKET_HEADER);\r
+      DebugHeader->StartSymbol = DEBUG_STARTING_SYMBOL_COMPRESS;\r
+      //\r
+      // Compute the CRC of the packet head without modifying the packet.\r
+      //\r
+      DebugHeader->Crc = CalculateCrc16 ((UINT8 *) DebugHeader, sizeof (DEBUG_PACKET_HEADER), 0);\r
+      CompressData (\r
+        Handle,\r
+        (UINT8 *) (DebugHeader + 1),\r
+        CurrentDataSize,\r
+        FALSE,\r
+        NULL,\r
+        &DebugHeader->Crc\r
+        );\r
+      //\r
+      // Send out the packet head.\r
+      //\r
+      DebugPortWriteBuffer (Handle, (UINT8 *) DebugHeader, sizeof (DEBUG_PACKET_HEADER));\r
+      //\r
+      // Compress and send out the packet data.\r
+      //\r
+      CompressData (\r
+        Handle,\r
+        (UINT8 *) (DebugHeader + 1),\r
+        CurrentDataSize,\r
+        TRUE,\r
+        NULL,\r
+        NULL\r
+        );\r
+    } else {\r
 \r
-    case DEBUG_COMMAND_CONTINUE:\r
       //\r
-      // Send the rest packet\r
+      // Calculate and fill the checksum, DebugHeader->Crc should be 0 before invoking CalculateCrc16 ()\r
       //\r
-      Data     += DEBUG_DATA_MAXIMUM_REAL_DATA;\r
-      DataSize -= DEBUG_DATA_MAXIMUM_REAL_DATA;\r
-      break;\r
+      DebugHeader->Crc = CalculateCrc16 ((UINT8 *) DebugHeader, DebugHeader->Length, 0);\r
 \r
-    case DEBUG_COMMAND_OK:\r
-      if (LastPacket) {\r
+      DebugAgentDataMsgPrint (DEBUG_AGENT_VERBOSE, TRUE, (UINT8 *) DebugHeader, DebugHeader->Length);\r
+\r
+      DebugPortWriteBuffer (Handle, (UINT8 *) DebugHeader, DebugHeader->Length);\r
+    }\r
+\r
+    while (TRUE) {\r
+      Status = ReceivePacket ((UINT8 *) DebugHeader, NULL, NULL, READ_PACKET_TIMEOUT, FALSE);\r
+      if (Status == RETURN_TIMEOUT) {\r
+        DebugAgentMsgPrint (DEBUG_AGENT_WARNING, "TARGET: Timeout in SendDataResponsePacket()\n");\r
+        break;\r
+      }\r
+      if ((DebugHeader->Command == DEBUG_COMMAND_OK) && (DebugHeader->SequenceNo == SequenceNo) && LastPacket) {\r
         //\r
         // If this is the last packet, return RETURN_SUCCESS.\r
         //\r
         return RETURN_SUCCESS;\r
-      } else {\r
-        return RETURN_DEVICE_ERROR;\r
       }\r
-\r
-    default:\r
-      return RETURN_DEVICE_ERROR;\r
-\r
+      if ((DebugHeader->Command == DEBUG_COMMAND_CONTINUE) && (DebugHeader->SequenceNo == (UINT8) (SequenceNo + 1))) {\r
+        //\r
+        // Calculate the rest data size\r
+        //\r
+        Data              += CurrentDataSize;\r
+        RemainingDataSize -= CurrentDataSize;\r
+        UpdateMailboxContent (GetMailboxPointer(), DEBUG_MAILBOX_HOST_SEQUENCE_NO_INDEX, DebugHeader->SequenceNo);\r
+        break;\r
+      }\r
+      if (DebugHeader->SequenceNo >= SequenceNo) {\r
+        DebugAgentMsgPrint (DEBUG_AGENT_WARNING, "TARGET: Received one old or new command(SequenceNo is %x, last SequenceNo is %x)\n", SequenceNo, DebugHeader->SequenceNo);\r
+        break;\r
+      }\r
     }\r
   }\r
 }\r
 \r
 /**\r
-  Send break cause packet to HOST.\r
+  Send packet with response data to HOST.\r
 \r
-  @param[in] Vector      Vector value of exception or interrutp.\r
-  @param[in] CpuContext  Pointer to save CPU context.\r
+  @param[in]      Data        Pointer to response data buffer.\r
+  @param[in]      DataSize    Size of response data in byte.\r
+  @param[in, out] DebugHeader Pointer to a buffer for creating response packet and receiving ACK packet,\r
+                              to minimize the stack usage.\r
 \r
   @retval RETURN_SUCCESS      Response data was sent successfully.\r
-  @retval RETURN_DEVICE_ERROR Cannot receive DEBUG_COMMAND_OK from HOST.\r
 \r
 **/\r
 RETURN_STATUS\r
-SendBreakCausePacket (\r
-  IN UINTN                    Vector,\r
-  IN DEBUG_CPU_CONTEXT        *CpuContext\r
+SendDataResponsePacket (\r
+  IN UINT8                   *Data,\r
+  IN UINT16                  DataSize,\r
+  IN OUT DEBUG_PACKET_HEADER *DebugHeader\r
   )\r
 {\r
-  DEBUG_DATA_RESPONSE_BREAK_CAUSE    DebugDataBreakCause;\r
+  return ReadMemoryAndSendResponsePacket (Data, DataSize, 1, DebugHeader);\r
+}\r
+\r
+/**\r
+  Try to attach the HOST.\r
+\r
+  Send init break packet to HOST:\r
+  If no acknowledge received in specified Timeout, return RETURN_TIMEOUT.\r
+  If received acknowledge, check the revision of HOST.\r
+  Set Attach Flag if attach successfully.\r
+\r
+  @param[in]  BreakCause     Break cause of this break event.\r
+  @param[in]  Timeout        Time out value to wait for acknowledge from HOST.\r
+                             The unit is microsecond.\r
+  @param[out] BreakReceived  If BreakReceived is not NULL,\r
+                             TRUE is returned if break-in symbol received.\r
+                             FALSE is returned if break-in symbol not received.\r
+**/\r
+RETURN_STATUS\r
+AttachHost (\r
+  IN  UINT8                BreakCause,\r
+  IN  UINTN                Timeout,\r
+  OUT BOOLEAN              *BreakReceived\r
+  )\r
+{\r
+  RETURN_STATUS                    Status;\r
+  DEBUG_PORT_HANDLE                Handle;\r
+  BOOLEAN                          IncompatibilityFlag;\r
+\r
+  IncompatibilityFlag = FALSE;\r
+  Handle = GetDebugPortHandle();\r
 \r
-  DebugDataBreakCause.StopAddress = CpuContext->Eip;\r
-  DebugDataBreakCause.Cause       = GetBreakCause (Vector, CpuContext);\r
+  //\r
+  // Send init break and wait ack in Timeout\r
+  //\r
+  DebugPortWriteBuffer (Handle, (UINT8 *) mErrorMsgSendInitPacket, AsciiStrLen (mErrorMsgSendInitPacket));\r
+  if (BreakCause == DEBUG_DATA_BREAK_CAUSE_SYSTEM_RESET) {\r
+    Status = SendCommandAndWaitForAckOK (DEBUG_COMMAND_INIT_BREAK, Timeout, BreakReceived, &IncompatibilityFlag);\r
+  } else {\r
+    Status = SendCommandAndWaitForAckOK (DEBUG_COMMAND_ATTACH_BREAK, Timeout, BreakReceived, &IncompatibilityFlag);\r
+  }\r
+  if (IncompatibilityFlag) {\r
+    //\r
+    // If the incompatible Debug Packet received, the HOST should be running transfer protocol before PcdTransferProtocolRevision.\r
+    // It could be UDK Debugger for Windows v1.1/v1.2 or for Linux v0.8/v1.2.\r
+    //\r
+    DebugPortWriteBuffer (Handle, (UINT8 *) mErrorMsgVersionAlert, AsciiStrLen (mErrorMsgVersionAlert));\r
+    CpuDeadLoop ();\r
+  }\r
 \r
-  return SendDataResponsePacket (CpuContext, (UINT8 *) &DebugDataBreakCause, (UINT16) sizeof (DEBUG_DATA_RESPONSE_BREAK_CAUSE));\r
+  if (RETURN_ERROR (Status)) {\r
+    DebugPortWriteBuffer (Handle, (UINT8 *) mErrorMsgConnectFail, AsciiStrLen (mErrorMsgConnectFail));\r
+  } else {\r
+    DebugPortWriteBuffer (Handle, (UINT8 *) mErrorMsgConnectOK, AsciiStrLen (mErrorMsgConnectOK));\r
+    //\r
+    // Set Attach flag\r
+    //\r
+    SetHostAttached (TRUE);\r
+  }\r
+  return Status;\r
 }\r
 \r
+/**\r
+  Send Break point packet to HOST.\r
+\r
+  Only the first breaking processor could sent BREAK_POINT packet.\r
+\r
+  @param[in]  BreakCause     Break cause of this break event.\r
+  @param[in]  ProcessorIndex Processor index value.\r
+  @param[out] BreakReceived  If BreakReceived is not NULL,\r
+                             TRUE is returned if break-in symbol received.\r
+                             FALSE is returned if break-in symbol not received.\r
+\r
+**/\r
+VOID\r
+SendBreakPacketToHost (\r
+  IN  UINT8                BreakCause,\r
+  IN  UINT32               ProcessorIndex,\r
+  OUT BOOLEAN              *BreakReceived\r
+  )\r
+{\r
+  UINT8                 InputCharacter;\r
+  DEBUG_PORT_HANDLE     Handle;\r
+\r
+  Handle = GetDebugPortHandle();\r
+\r
+  if (IsHostAttached ()) {\r
+    DebugAgentMsgPrint (DEBUG_AGENT_INFO, "processor[%x]:Send Break Packet to HOST.\n", ProcessorIndex);\r
+    SendCommandAndWaitForAckOK (DEBUG_COMMAND_BREAK_POINT, READ_PACKET_TIMEOUT, BreakReceived, NULL);\r
+  } else {\r
+    DebugAgentMsgPrint (DEBUG_AGENT_INFO, "processor[%x]:Try to attach HOST.\n", ProcessorIndex);\r
+    //\r
+    // If HOST is not attached, try to attach it firstly.\r
+    //\r
+    //\r
+    // Poll Attach symbols from HOST and ack OK\r
+    //\r
+    do {\r
+      DebugAgentReadBuffer (Handle, &InputCharacter, 1, 0);\r
+    } while (InputCharacter != DEBUG_STARTING_SYMBOL_ATTACH);\r
+    SendAckPacket (DEBUG_COMMAND_OK);\r
+\r
+    //\r
+    // Try to attach HOST\r
+    //\r
+    while (AttachHost (BreakCause, 0, NULL) != RETURN_SUCCESS);\r
+\r
+  }\r
+}\r
 \r
 /**\r
   The main function to process communication with HOST.\r
 \r
   It received the command packet from HOST, and sent response data packet to HOST.\r
 \r
-  @param[in]      Vector         Vector value of exception or interrutp.\r
+  @param[in]      Vector         Vector value of exception or interrupt.\r
   @param[in, out] CpuContext     Pointer to saved CPU context.\r
   @param[in]      BreakReceived  TRUE means break-in symbol received.\r
                                  FALSE means break-in symbol not received.\r
@@ -564,95 +1790,172 @@ CommandCommunication (
   IN     BOOLEAN                 BreakReceived\r
   )\r
 {\r
-  RETURN_STATUS                 Status;\r
-  UINT8                         InputPacketBuffer[DEBUG_DATA_MAXIMUM_LENGTH_FOR_SMALL_COMMANDS];\r
-  DEBUG_COMMAND_HEADER          *DebugHeader;\r
-  UINT8                         Data8;\r
-  UINT32                        Data32;\r
-  UINT64                        Data64;\r
-  UINTN                         DataN;\r
-  DEBUG_DATA_READ_MEMORY_8      *MemoryRead;\r
-  DEBUG_DATA_WRITE_MEMORY_8     *MemoryWrite;\r
-  DEBUG_DATA_READ_IO            *IoRead;\r
-  DEBUG_DATA_WRITE_IO           *IoWrite;\r
-  DEBUG_DATA_READ_REGISTER      *RegisterRead;\r
-  DEBUG_DATA_WRITE_REGISTER     *RegisterWrite;\r
-  UINT8                         *RegisterBuffer;\r
-  DEBUG_DATA_READ_MSR           *MsrRegisterRead;\r
-  DEBUG_DATA_WRITE_MSR          *MsrRegisterWrite;\r
-  DEBUG_DATA_REPONSE_READ_REGISTER_GROUP_SEGLIM   RegisterGroupSegLim;\r
-  DEBUG_DATA_REPONSE_READ_REGISTER_GROUP_SEGBASE  RegisterGroupSegBase;\r
-  DEBUG_DATA_RESPONSE_GET_REVISION DebugAgentRevision;\r
-  BOOLEAN                       HaltDeferred;\r
-  DEBUG_DATA_RESPONSE_GET_EXCEPTION  Exception;\r
-  UINT32                        ProcessorIndex;\r
-  DEBUG_PORT_HANDLE             Handle;\r
-\r
-  Handle = GetDebugPortHandle();\r
+  RETURN_STATUS                     Status;\r
+  UINT8                             InputPacketBuffer[DEBUG_DATA_UPPER_LIMIT + sizeof (UINT64) - 1];\r
+  DEBUG_PACKET_HEADER               *DebugHeader;\r
+  UINT8                             Width;\r
+  UINT8                             Data8;\r
+  UINT32                            Data32;\r
+  UINT64                            Data64;\r
+  DEBUG_DATA_READ_MEMORY            *MemoryRead;\r
+  DEBUG_DATA_WRITE_MEMORY           *MemoryWrite;\r
+  DEBUG_DATA_READ_IO                *IoRead;\r
+  DEBUG_DATA_WRITE_IO               *IoWrite;\r
+  DEBUG_DATA_READ_REGISTER          *RegisterRead;\r
+  DEBUG_DATA_WRITE_REGISTER         *RegisterWrite;\r
+  UINT8                             *RegisterBuffer;\r
+  DEBUG_DATA_READ_MSR               *MsrRegisterRead;\r
+  DEBUG_DATA_WRITE_MSR              *MsrRegisterWrite;\r
+  DEBUG_DATA_CPUID                  *Cpuid;\r
+  DEBUG_DATA_RESPONSE_BREAK_CAUSE   BreakCause;\r
+  DEBUG_DATA_RESPONSE_CPUID         CpuidResponse;\r
+  DEBUG_DATA_SEARCH_SIGNATURE       *SearchSignature;\r
+  DEBUG_DATA_RESPONSE_GET_EXCEPTION Exception;\r
+  DEBUG_DATA_RESPONSE_GET_REVISION  DebugAgentRevision;\r
+  DEBUG_DATA_SET_VIEWPOINT          *SetViewPoint;\r
+  BOOLEAN                           HaltDeferred;\r
+  UINT32                            ProcessorIndex;\r
+  DEBUG_AGENT_EXCEPTION_BUFFER      AgentExceptionBuffer;\r
+  UINT32                            IssuedViewPoint;\r
+  DEBUG_AGENT_MAILBOX               *Mailbox;\r
+  UINT8                             *AlignedDataPtr;\r
 \r
   ProcessorIndex  = 0;\r
-  HaltDeferred = BreakReceived;\r
+  IssuedViewPoint = 0;\r
+  HaltDeferred    = BreakReceived;\r
 \r
-  if (MultiProcessorDebugSupport) {\r
+  if (MultiProcessorDebugSupport()) {\r
     ProcessorIndex = GetProcessorIndex ();\r
     SetCpuStopFlagByIndex (ProcessorIndex, TRUE);\r
+    if (mDebugMpContext.ViewPointIndex == ProcessorIndex) {\r
+      //\r
+      // Only the current view processor could set AgentInProgress Flag.\r
+      //\r
+      IssuedViewPoint = ProcessorIndex;\r
+    }\r
+  }\r
+\r
+  if (IssuedViewPoint == ProcessorIndex) {\r
+    //\r
+    // Set AgentInProgress Flag.\r
+    //\r
+    SetDebugFlag (DEBUG_AGENT_FLAG_AGENT_IN_PROGRESS, 1);\r
   }\r
 \r
   while (TRUE) {\r
 \r
-    if (MultiProcessorDebugSupport) {\r
+    if (MultiProcessorDebugSupport()) {\r
+      //\r
+      // Check if the current processor is HOST view point\r
+      //\r
       if (mDebugMpContext.ViewPointIndex != ProcessorIndex) {\r
         if (mDebugMpContext.RunCommandSet) {\r
+          //\r
+          // If HOST view point sets RUN flag, run GO command to leave\r
+          //\r
           SetCpuStopFlagByIndex (ProcessorIndex, FALSE);\r
           CommandGo (CpuContext);\r
           break;\r
         } else {\r
+          //\r
+          // Run into loop again\r
+          //\r
+          CpuPause ();\r
           continue;\r
         }\r
       }\r
     }\r
 \r
-    AcquireDebugPortControl ();\r
+    AcquireMpSpinLock (&mDebugMpContext.DebugPortSpinLock);\r
 \r
-    Status = ReceivePacket (InputPacketBuffer, &BreakReceived);\r
+    DebugHeader =(DEBUG_PACKET_HEADER *) InputPacketBuffer;\r
 \r
-    if (BreakReceived) {\r
-      HaltDeferred = TRUE;\r
-      BreakReceived = FALSE;\r
+    DebugAgentMsgPrint (DEBUG_AGENT_INFO, "TARGET: Try to get command from HOST...\n");\r
+    Status = ReceivePacket ((UINT8 *) DebugHeader, &BreakReceived, NULL, READ_PACKET_TIMEOUT, TRUE);\r
+    if (Status != RETURN_SUCCESS || !IS_REQUEST (DebugHeader)) {\r
+      DebugAgentMsgPrint (DEBUG_AGENT_WARNING, "TARGET: Get command[%x] sequenceno[%x] returned status is [%x] \n", DebugHeader->Command, DebugHeader->SequenceNo, Status);\r
+      DebugAgentMsgPrint (DEBUG_AGENT_WARNING, "TARGET: Get command failed or it's response packet not expected! \n");\r
+      ReleaseMpSpinLock (&mDebugMpContext.DebugPortSpinLock);\r
+      continue;\r
+    }\r
+\r
+    Mailbox = GetMailboxPointer ();\r
+    if (DebugHeader->SequenceNo == Mailbox->HostSequenceNo) {\r
+      DebugAgentMsgPrint (DEBUG_AGENT_WARNING, "TARGET: Receive one old command[%x] against command[%x]\n", DebugHeader->SequenceNo, Mailbox->HostSequenceNo);\r
+      SendAckPacket (Mailbox->LastAck);\r
+      ReleaseMpSpinLock (&mDebugMpContext.DebugPortSpinLock);\r
+      continue;\r
+    } else if (DebugHeader->SequenceNo == (UINT8) (Mailbox->HostSequenceNo + 1)) {\r
+      UpdateMailboxContent (Mailbox, DEBUG_MAILBOX_HOST_SEQUENCE_NO_INDEX, (UINT8) DebugHeader->SequenceNo);\r
+    } else {\r
+      DebugAgentMsgPrint (DEBUG_AGENT_WARNING, "Receive one invalid command[%x] against command[%x]\n", DebugHeader->SequenceNo, Mailbox->HostSequenceNo);\r
+      ReleaseMpSpinLock (&mDebugMpContext.DebugPortSpinLock);\r
+      continue;\r
     }\r
 \r
-    if (Status != RETURN_SUCCESS) {\r
-      ReleaseDebugPortControl ();\r
+    //\r
+    // Save CPU content before executing HOST command\r
+    //\r
+    UpdateMailboxContent (Mailbox, DEBUG_MAILBOX_EXCEPTION_BUFFER_POINTER_INDEX, (UINT64)(UINTN) &AgentExceptionBuffer.JumpBuffer);\r
+    if (SetJump (&AgentExceptionBuffer.JumpBuffer) != 0) {\r
+      //\r
+      // If HOST command failed, continue to wait for HOST's next command\r
+      // If needed, agent could send exception info to HOST.\r
+      //\r
+      SendAckPacket (DEBUG_COMMAND_ABORT);\r
+      ReleaseMpSpinLock (&mDebugMpContext.DebugPortSpinLock);\r
       continue;\r
     }\r
 \r
-    Data8 = 1;\r
+    DebugAgentMsgPrint (DEBUG_AGENT_INFO, "Processor[%x]:Received one command(%x)\n", mDebugMpContext.ViewPointIndex, DebugHeader->Command);\r
 \r
-    DebugHeader =(DEBUG_COMMAND_HEADER *) InputPacketBuffer;\r
     switch (DebugHeader->Command) {\r
 \r
+    case DEBUG_COMMAND_HALT:\r
+      SendAckPacket (DEBUG_COMMAND_HALT_DEFERRED);\r
+      HaltDeferred = TRUE;\r
+      BreakReceived = FALSE;\r
+      Status = RETURN_SUCCESS;\r
+      break;\r
+\r
     case DEBUG_COMMAND_RESET:\r
       SendAckPacket (DEBUG_COMMAND_OK);\r
-      ReleaseDebugPortControl ();\r
+      SendAckPacket (DEBUG_COMMAND_OK);\r
+      SendAckPacket (DEBUG_COMMAND_OK);\r
+      ReleaseMpSpinLock (&mDebugMpContext.DebugPortSpinLock);\r
 \r
       ResetCold ();\r
       //\r
-      // Wait for reset\r
+      // Assume system resets in 2 seconds, otherwise send TIMEOUT packet.\r
+      // PCD can be used if 2 seconds isn't long enough for some platforms.\r
       //\r
-      CpuDeadLoop ();\r
+      MicroSecondDelay (2000000);\r
+      UpdateMailboxContent (Mailbox, DEBUG_MAILBOX_HOST_SEQUENCE_NO_INDEX, Mailbox->HostSequenceNo + 1);\r
+      SendAckPacket (DEBUG_COMMAND_TIMEOUT);\r
+      SendAckPacket (DEBUG_COMMAND_TIMEOUT);\r
+      SendAckPacket (DEBUG_COMMAND_TIMEOUT);\r
       break;\r
 \r
     case DEBUG_COMMAND_GO:\r
       CommandGo (CpuContext);\r
+      //\r
+      // Clear Dr0 to avoid to be recognized as IMAGE_LOAD/_UNLOAD again when hitting a breakpoint after GO\r
+      // If HOST changed Dr0 before GO, we will not change Dr0 here\r
+      //\r
+      Data8 = GetBreakCause (Vector, CpuContext);\r
+      if (Data8 == DEBUG_DATA_BREAK_CAUSE_IMAGE_LOAD || Data8 == DEBUG_DATA_BREAK_CAUSE_IMAGE_UNLOAD) {\r
+        CpuContext->Dr0 = 0;\r
+      }\r
+\r
       if (!HaltDeferred) {\r
         //\r
         // If no HALT command received when being in-active mode\r
         //\r
-        if (MultiProcessorDebugSupport) {\r
-          Data32 = FindCpuNotRunning ();\r
+        if (MultiProcessorDebugSupport()) {\r
+          Data32 = FindNextPendingBreakCpu ();\r
           if (Data32 != -1) {\r
             //\r
-            // If there are still others processors being in break state,          \r
+            // If there are still others processors being in break state,\r
             // send OK packet to HOST to finish this go command\r
             //\r
             SendAckPacket (DEBUG_COMMAND_OK);\r
@@ -664,11 +1967,13 @@ CommandCommunication (
             mDebugMpContext.BreakAtCpuIndex = mDebugMpContext.ViewPointIndex;\r
             SetCpuBreakFlagByIndex (mDebugMpContext.ViewPointIndex, FALSE);\r
             //\r
-            // Send break packet to HOST and exit to wait for command packet from HOST.\r
+            // Send break packet to HOST to let HOST break again\r
             //\r
-            SendAckPacket (DEBUG_COMMAND_BREAK_POINT);\r
-            WaitForAckPacketOK (0, &BreakReceived);\r
-            ReleaseDebugPortControl (); \r
+            SendBreakPacketToHost (DEBUG_DATA_BREAK_CAUSE_UNKNOWN, mDebugMpContext.BreakAtCpuIndex, &BreakReceived);\r
+            //\r
+            // Continue to run into loop to read command packet from HOST\r
+            //\r
+            ReleaseMpSpinLock (&mDebugMpContext.DebugPortSpinLock);\r
             break;\r
           }\r
 \r
@@ -680,7 +1985,7 @@ CommandCommunication (
           SetCpuRunningFlag (TRUE);\r
           CpuPause ();\r
           //\r
-          // Wait for all processors are in running state \r
+          // Wait for all processors are in running state\r
           //\r
           while (TRUE) {\r
             if (IsAllCpuRunning ()) {\r
@@ -704,35 +2009,33 @@ CommandCommunication (
         //\r
         SendAckPacket (DEBUG_COMMAND_OK);\r
 \r
-        ReleaseDebugPortControl ();\r
+        ReleaseMpSpinLock (&mDebugMpContext.DebugPortSpinLock);\r
 \r
+        if (!IsHostAttached()) {\r
+          UpdateMailboxContent (Mailbox, DEBUG_MAILBOX_SEQUENCE_NO_INDEX, 0);\r
+          UpdateMailboxContent (Mailbox, DEBUG_MAILBOX_HOST_SEQUENCE_NO_INDEX, 0);\r
+        }\r
         return;\r
 \r
       } else {\r
         //\r
-        // If reveived HALT command, need to defer the GO command\r
+        // If received HALT command, need to defer the GO command\r
         //\r
         SendAckPacket (DEBUG_COMMAND_HALT_PROCESSED);\r
         HaltDeferred = FALSE;\r
-        Data8 = GetBreakCause (Vector, CpuContext);\r
-        if (Data8 == DEBUG_DATA_BREAK_CAUSE_IMAGE_LOAD || Data8 == DEBUG_DATA_BREAK_CAUSE_IMAGE_UNLOAD) {\r
-          CpuContext->Dr0 = 0;\r
-          CpuContext->Dr3 = 0;\r
-        }\r
 \r
         Vector = DEBUG_TIMER_VECTOR;\r
       }\r
       break;\r
 \r
     case DEBUG_COMMAND_BREAK_CAUSE:\r
-\r
-      if (MultiProcessorDebugSupport && ProcessorIndex != mDebugMpContext.BreakAtCpuIndex) {\r
-        Status = SendBreakCausePacket (DEBUG_TIMER_VECTOR, CpuContext);\r
-\r
+      BreakCause.StopAddress = CpuContext->Eip;\r
+      if (MultiProcessorDebugSupport() && ProcessorIndex != mDebugMpContext.BreakAtCpuIndex) {\r
+        BreakCause.Cause       = GetBreakCause (DEBUG_TIMER_VECTOR, CpuContext);\r
       } else {\r
-        Status = SendBreakCausePacket (Vector, CpuContext);\r
+        BreakCause.Cause       = GetBreakCause (Vector, CpuContext);\r
       }\r
-\r
+      SendDataResponsePacket ((UINT8 *) &BreakCause, (UINT16) sizeof (DEBUG_DATA_RESPONSE_BREAK_CAUSE), DebugHeader);\r
       break;\r
 \r
     case DEBUG_COMMAND_SET_HW_BREAKPOINT:\r
@@ -747,12 +2050,20 @@ CommandCommunication (
 \r
     case DEBUG_COMMAND_SINGLE_STEPPING:\r
       CommandStepping (CpuContext);\r
+      //\r
+      // Clear Dr0 to avoid to be recognized as IMAGE_LOAD/_UNLOAD again when hitting a breakpoint after GO\r
+      // If HOST changed Dr0 before GO, we will not change Dr0 here\r
+      //\r
+      Data8 = GetBreakCause (Vector, CpuContext);\r
+      if (Data8 == DEBUG_DATA_BREAK_CAUSE_IMAGE_LOAD || Data8 == DEBUG_DATA_BREAK_CAUSE_IMAGE_UNLOAD) {\r
+        CpuContext->Dr0 = 0;\r
+      }\r
 \r
       mDebugMpContext.BreakAtCpuIndex = (UINT32) (-1);\r
-\r
-      ReleaseDebugPortControl ();\r
+      ReleaseMpSpinLock (&mDebugMpContext.DebugPortSpinLock);\r
       //\r
-      // Executing stepping command directly without sending ACK packet.\r
+      // Executing stepping command directly without sending ACK packet,\r
+      // ACK packet will be sent after stepping done.\r
       //\r
       return;\r
 \r
@@ -760,29 +2071,24 @@ CommandCommunication (
       Data64 = (UINTN) (((DEBUG_DATA_SET_SW_BREAKPOINT *) (DebugHeader + 1))->Address);\r
       Data8 = *(UINT8 *) (UINTN) Data64;\r
       *(UINT8 *) (UINTN) Data64 = DEBUG_SW_BREAKPOINT_SYMBOL;\r
-      Status = SendDataResponsePacket (CpuContext, (UINT8 *) &Data8, (UINT16) sizeof (UINT8));\r
+      Status = SendDataResponsePacket ((UINT8 *) &Data8, (UINT16) sizeof (UINT8), DebugHeader);\r
       break;\r
 \r
-    case DEBUG_COMMAND_READ_MEMORY_64:\r
-      Data8 *= 2;\r
-    case DEBUG_COMMAND_READ_MEMORY_32:\r
-      Data8 *= 2;\r
-    case DEBUG_COMMAND_READ_MEMORY_16:\r
-      Data8 *= 2;\r
-         case DEBUG_COMMAND_READ_MEMORY_8:\r
-      MemoryRead = (DEBUG_DATA_READ_MEMORY_8 *) (DebugHeader + 1);\r
-      Status = SendDataResponsePacket (CpuContext, (UINT8 *) (UINTN) MemoryRead->Address, (UINT16) (MemoryRead->Count * Data8));\r
+    case DEBUG_COMMAND_READ_MEMORY:\r
+      MemoryRead = (DEBUG_DATA_READ_MEMORY *) (DebugHeader + 1);\r
+      Status = ReadMemoryAndSendResponsePacket ((UINT8 *) (UINTN) MemoryRead->Address, MemoryRead->Count, MemoryRead->Width, DebugHeader);\r
       break;\r
 \r
-    case DEBUG_COMMAND_WRITE_MEMORY_64:\r
-      Data8 *= 2;\r
-    case DEBUG_COMMAND_WRITE_MEMORY_32:\r
-      Data8 *= 2;\r
-    case DEBUG_COMMAND_WRITE_MEMORY_16:\r
-      Data8 *= 2;\r
-    case DEBUG_COMMAND_WRITE_MEMORY_8:\r
-      MemoryWrite = (DEBUG_DATA_WRITE_MEMORY_8 *) (DebugHeader + 1);\r
-      CopyMem ((VOID *) (UINTN) MemoryWrite->Address, &MemoryWrite->Data, MemoryWrite->Count * Data8);\r
+    case DEBUG_COMMAND_WRITE_MEMORY:\r
+      MemoryWrite = (DEBUG_DATA_WRITE_MEMORY *) (DebugHeader + 1);\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
@@ -790,37 +2096,37 @@ CommandCommunication (
       IoRead = (DEBUG_DATA_READ_IO *) (DebugHeader + 1);\r
       switch (IoRead->Width) {\r
       case 1:\r
-        Data64  = IoRead8 (IoRead->Port);\r
+        Data64  = IoRead8 ((UINTN) IoRead->Port);\r
         break;\r
       case 2:\r
-        Data64  = IoRead16 (IoRead->Port);\r
+        Data64  = IoRead16 ((UINTN) IoRead->Port);\r
         break;\r
       case 4:\r
-        Data64  = IoRead32 (IoRead->Port);\r
+        Data64  = IoRead32 ((UINTN) IoRead->Port);\r
         break;\r
       case 8:\r
-        Data64  = IoRead64 (IoRead->Port);\r
+        Data64  = IoRead64 ((UINTN) IoRead->Port);\r
         break;\r
       default:\r
         Data64  = (UINT64) -1;\r
       }\r
-      Status = SendDataResponsePacket (CpuContext, (UINT8 *) &Data64, IoRead->Width);\r
+      Status = SendDataResponsePacket ((UINT8 *) &Data64, IoRead->Width, DebugHeader);\r
       break;\r
 \r
     case DEBUG_COMMAND_WRITE_IO:\r
       IoWrite = (DEBUG_DATA_WRITE_IO *) (DebugHeader + 1);\r
       switch (IoWrite->Width) {\r
       case 1:\r
-        Data64  = IoWrite8 (IoWrite->Port, *(UINT8 *) &IoWrite->Data);\r
+        Data64  = IoWrite8 ((UINTN) IoWrite->Port, *(UINT8 *) &IoWrite->Data);\r
         break;\r
       case 2:\r
-        Data64  = IoWrite16 (IoWrite->Port, *(UINT16 *) &IoWrite->Data);\r
+        Data64  = IoWrite16 ((UINTN) IoWrite->Port, *(UINT16 *) &IoWrite->Data);\r
         break;\r
       case 4:\r
-        Data64  = IoWrite32 (IoWrite->Port, *(UINT32 *) &IoWrite->Data);\r
+        Data64  = IoWrite32 ((UINTN) IoWrite->Port, *(UINT32 *) &IoWrite->Data);\r
         break;\r
       case 8:\r
-        Data64  = IoWrite64 (IoWrite->Port, *(UINT64 *) &IoWrite->Data);\r
+        Data64  = IoWrite64 ((UINTN) IoWrite->Port, *(UINT64 *) &IoWrite->Data);\r
         break;\r
       default:\r
         Data64  = (UINT64) -1;\r
@@ -828,66 +2134,42 @@ CommandCommunication (
       SendAckPacket (DEBUG_COMMAND_OK);\r
       break;\r
 \r
+    case DEBUG_COMMAND_READ_ALL_REGISTERS:\r
+      Status = SendDataResponsePacket ((UINT8 *) CpuContext, sizeof (*CpuContext), DebugHeader);\r
+      break;\r
+\r
     case DEBUG_COMMAND_READ_REGISTER:\r
       RegisterRead = (DEBUG_DATA_READ_REGISTER *) (DebugHeader + 1);\r
 \r
-      if (RegisterRead->Index < SOFT_DEBUGGER_REGISTER_OTHERS_BASE) {\r
-        Data8 = RegisterRead->Length;\r
-        RegisterBuffer = ArchReadRegisterBuffer (CpuContext, RegisterRead->Index, RegisterRead->Offset, &Data8);\r
-        Status = SendDataResponsePacket (CpuContext, RegisterBuffer, Data8);\r
-        break;\r
-      }\r
-\r
-      if (RegisterRead->Index <= SOFT_DEBUGGER_REGISTER_TSS_LIM) {\r
-        ReadRegisterGroupSegLim (CpuContext, &RegisterGroupSegLim);\r
-        DataN = * ((UINTN *) &RegisterGroupSegLim + (RegisterRead->Index - SOFT_DEBUGGER_REGISTER_CS_LIM));\r
-        Status = SendDataResponsePacket (CpuContext, (UINT8 *) &DataN, (UINT16) sizeof (UINTN));\r
-      } else if (RegisterRead->Index <= SOFT_DEBUGGER_REGISTER_TSS_BAS) {\r
-        ReadRegisterGroupSegBase (CpuContext, &RegisterGroupSegBase);\r
-        DataN = * ((UINTN *) &RegisterGroupSegBase + (RegisterRead->Index - SOFT_DEBUGGER_REGISTER_CS_BAS));\r
-        Status = SendDataResponsePacket (CpuContext, (UINT8 *) &DataN, (UINT16) sizeof (UINTN));\r
-      } else if (RegisterRead->Index < SOFT_DEBUGGER_REGISTER_IDT_LIM) {\r
-        Data64 = ReadRegisterSelectorByIndex (CpuContext, RegisterRead->Index);\r
-        Status = SendDataResponsePacket (CpuContext, (UINT8 *) &Data64, (UINT16) sizeof (UINT64));\r
+      if (RegisterRead->Index <= SOFT_DEBUGGER_REGISTER_MAX) {\r
+        RegisterBuffer = ArchReadRegisterBuffer (CpuContext, RegisterRead->Index, &Width);\r
+        Status = SendDataResponsePacket (RegisterBuffer, Width, DebugHeader);\r
       } else {\r
-        switch (RegisterRead->Index) {\r
-        case SOFT_DEBUGGER_REGISTER_IDT_LIM:\r
-          DataN = (UINTN) (CpuContext->Idtr[0] & 0xffff);\r
-          SendDataResponsePacket (CpuContext, (UINT8 *) &DataN, (UINT16) sizeof (UINTN));\r
-          break;\r
-        case SOFT_DEBUGGER_REGISTER_GDT_LIM:\r
-          DataN = (UINTN) (CpuContext->Gdtr[0] & 0xffff);\r
-          SendDataResponsePacket (CpuContext, (UINT8 *) &DataN, (UINT16) sizeof (UINTN));\r
-          break;\r
-        case SOFT_DEBUGGER_REGISTER_IDT_BAS:\r
-          DataN = (UINTN) RShiftU64 (CpuContext->Idtr[0], 16);\r
-          DataN |= (UINTN) LShiftU64 (CpuContext->Idtr[1], (UINT16) (sizeof (UINTN) * 8 - 16));\r
-          SendDataResponsePacket (CpuContext, (UINT8 *) &DataN, (UINT16) sizeof (UINTN));\r
-          break;\r
-        case SOFT_DEBUGGER_REGISTER_GDT_BAS:\r
-          DataN = (UINTN) RShiftU64 (CpuContext->Gdtr[0], 16);\r
-          DataN |= (UINTN) LShiftU64 (CpuContext->Gdtr[1], (UINT16) (sizeof (UINTN) * 8 - 16));\r
-          SendDataResponsePacket (CpuContext, (UINT8 *) &DataN, (UINT16) sizeof (UINTN));\r
-          break;\r
-        }\r
+        Status = RETURN_UNSUPPORTED;\r
       }\r
       break;\r
 \r
     case DEBUG_COMMAND_WRITE_REGISTER:\r
       RegisterWrite = (DEBUG_DATA_WRITE_REGISTER *) (DebugHeader + 1);\r
-      ArchWriteRegisterBuffer (CpuContext, RegisterWrite->Index, RegisterWrite->Offset, RegisterWrite->Length, (UINT8 *)&RegisterWrite->Value);\r
-      SendAckPacket (DEBUG_COMMAND_OK);\r
+      if (RegisterWrite->Index <= SOFT_DEBUGGER_REGISTER_MAX) {\r
+        RegisterBuffer = ArchReadRegisterBuffer (CpuContext, RegisterWrite->Index, &Width);\r
+        ASSERT (Width == RegisterWrite->Length);\r
+        CopyMem (RegisterBuffer, RegisterWrite->Data, Width);\r
+        SendAckPacket (DEBUG_COMMAND_OK);\r
+      } else {\r
+        Status = RETURN_UNSUPPORTED;\r
+      }\r
       break;\r
 \r
     case DEBUG_COMMAND_ARCH_MODE:\r
       Data8 = DEBUG_ARCH_SYMBOL;\r
-      Status = SendDataResponsePacket (CpuContext, (UINT8 *) &Data8, (UINT16) sizeof (UINT8));\r
+      Status = SendDataResponsePacket ((UINT8 *) &Data8, (UINT16) sizeof (UINT8), DebugHeader);\r
       break;\r
 \r
     case DEBUG_COMMAND_READ_MSR:\r
       MsrRegisterRead = (DEBUG_DATA_READ_MSR *) (DebugHeader + 1);\r
       Data64 = AsmReadMsr64 (MsrRegisterRead->Index);\r
-      Status = SendDataResponsePacket (CpuContext, (UINT8 *) &Data64, (UINT16) sizeof (UINT64));\r
+      Status = SendDataResponsePacket ((UINT8 *) &Data64, (UINT16) sizeof (UINT64), DebugHeader);\r
       break;\r
 \r
     case DEBUG_COMMAND_WRITE_MSR:\r
@@ -896,35 +2178,30 @@ CommandCommunication (
       SendAckPacket (DEBUG_COMMAND_OK);\r
       break;\r
 \r
-    case DEBUG_COMMAND_READ_REGISTER_GROUP:\r
-      Data8 = *(UINT8 *) (DebugHeader + 1);\r
-      Status = ArchReadRegisterGroup (CpuContext, Data8);\r
-      break;\r
-\r
-    case DEBUG_COMMAND_SET_DEBUG_FLAG:\r
-      Data32 = *(UINT32 *) (DebugHeader + 1);\r
-      SetDebugFlag (Data32);\r
-      SendAckPacket (DEBUG_COMMAND_OK);\r
+    case DEBUG_COMMAND_SET_DEBUG_SETTING:\r
+      Status = SetDebugSetting ((DEBUG_DATA_SET_DEBUG_SETTING *)(DebugHeader + 1));\r
+      if (Status == RETURN_SUCCESS) {\r
+        SendAckPacket (DEBUG_COMMAND_OK);\r
+      }\r
       break;\r
 \r
     case DEBUG_COMMAND_GET_REVISION:\r
-      DebugAgentRevision.Revision = DEBUG_AGENT_REVISION;\r
+      DebugAgentRevision.Revision = PcdGet32(PcdTransferProtocolRevision);\r
       DebugAgentRevision.Capabilities = DEBUG_AGENT_CAPABILITIES;\r
-      Status = SendDataResponsePacket (CpuContext, (UINT8 *) &DebugAgentRevision, (UINT16) sizeof (DEBUG_DATA_RESPONSE_GET_REVISION));\r
+      Status = SendDataResponsePacket ((UINT8 *) &DebugAgentRevision, (UINT16) sizeof (DEBUG_DATA_RESPONSE_GET_REVISION), DebugHeader);\r
       break;\r
 \r
     case DEBUG_COMMAND_GET_EXCEPTION:\r
       Exception.ExceptionNum  = (UINT8) Vector;\r
-      Exception.ExceptionData = 0;\r
-      Status = SendDataResponsePacket (CpuContext, (UINT8 *) &Exception, (UINT16) sizeof (DEBUG_DATA_RESPONSE_GET_EXCEPTION));\r
+      Exception.ExceptionData = (UINT32) CpuContext->ExceptionData;\r
+      Status = SendDataResponsePacket ((UINT8 *) &Exception, (UINT16) sizeof (DEBUG_DATA_RESPONSE_GET_EXCEPTION), DebugHeader);\r
       break;\r
 \r
     case DEBUG_COMMAND_SET_VIEWPOINT:\r
-      Data32 = *(UINT32 *) (DebugHeader + 1);\r
-\r
-      if (MultiProcessorDebugSupport) {\r
-        if (IsCpuStopped (Data32)) {\r
-          SetDebugViewPoint (Data32);\r
+      SetViewPoint = (DEBUG_DATA_SET_VIEWPOINT *) (DebugHeader + 1);\r
+      if (MultiProcessorDebugSupport()) {\r
+        if (IsCpuStopped (SetViewPoint->ViewPoint)) {\r
+          SetDebugViewPoint (SetViewPoint->ViewPoint);\r
           SendAckPacket (DEBUG_COMMAND_OK);\r
         } else {\r
           //\r
@@ -932,7 +2209,7 @@ CommandCommunication (
           //\r
           SendAckPacket (DEBUG_COMMAND_NOT_SUPPORTED);\r
         }\r
-      } else if (Data32 == 0) {\r
+      } else if (SetViewPoint->ViewPoint == 0) {\r
         SendAckPacket (DEBUG_COMMAND_OK);\r
 \r
       } else {\r
@@ -943,7 +2220,65 @@ CommandCommunication (
 \r
     case DEBUG_COMMAND_GET_VIEWPOINT:\r
       Data32 = mDebugMpContext.ViewPointIndex;\r
-      SendDataResponsePacket(CpuContext, (UINT8 *) &Data32, (UINT16) sizeof (UINT32));\r
+      SendDataResponsePacket((UINT8 *) &Data32, (UINT16) sizeof (UINT32), DebugHeader);\r
+      break;\r
+\r
+    case DEBUG_COMMAND_MEMORY_READY:\r
+      Data8 = (UINT8) GetDebugFlag (DEBUG_AGENT_FLAG_MEMORY_READY);\r
+      SendDataResponsePacket (&Data8, (UINT16) sizeof (UINT8), DebugHeader);\r
+      break;\r
+\r
+    case DEBUG_COMMAND_DETACH:\r
+      SetHostAttached (FALSE);\r
+      SendAckPacket (DEBUG_COMMAND_OK);\r
+      break;\r
+\r
+    case DEBUG_COMMAND_CPUID:\r
+      Cpuid = (DEBUG_DATA_CPUID *) (DebugHeader + 1);\r
+      AsmCpuidEx (\r
+        Cpuid->Eax, Cpuid->Ecx,\r
+        &CpuidResponse.Eax, &CpuidResponse.Ebx,\r
+        &CpuidResponse.Ecx, &CpuidResponse.Edx\r
+        );\r
+      SendDataResponsePacket ((UINT8 *) &CpuidResponse, (UINT16) sizeof (CpuidResponse), DebugHeader);\r
+      break;\r
+\r
+   case DEBUG_COMMAND_SEARCH_SIGNATURE:\r
+      SearchSignature = (DEBUG_DATA_SEARCH_SIGNATURE *) (DebugHeader + 1);\r
+      if ((SearchSignature->Alignment != 0) &&\r
+          (SearchSignature->Alignment == GetPowerOfTwo32 (SearchSignature->Alignment))\r
+         ) {\r
+        if (SearchSignature->Positive) {\r
+          for (\r
+            Data64 = ALIGN_VALUE ((UINTN) SearchSignature->Start, SearchSignature->Alignment);\r
+            Data64 <= SearchSignature->Start + SearchSignature->Count - SearchSignature->DataLength;\r
+            Data64 += SearchSignature->Alignment\r
+              ) {\r
+            if (CompareMem ((VOID *) (UINTN) Data64, &SearchSignature->Data, SearchSignature->DataLength) == 0) {\r
+              break;\r
+            }\r
+          }\r
+          if (Data64 > SearchSignature->Start + SearchSignature->Count - SearchSignature->DataLength) {\r
+            Data64 = (UINT64) -1;\r
+          }\r
+        } else {\r
+          for (\r
+            Data64 = ALIGN_VALUE ((UINTN) SearchSignature->Start - SearchSignature->Alignment, SearchSignature->Alignment);\r
+            Data64 >= SearchSignature->Start - SearchSignature->Count;\r
+            Data64 -= SearchSignature->Alignment\r
+              ) {\r
+            if (CompareMem ((VOID *) (UINTN) Data64, &SearchSignature->Data, SearchSignature->DataLength) == 0) {\r
+              break;\r
+            }\r
+          }\r
+          if (Data64 < SearchSignature->Start - SearchSignature->Count) {\r
+            Data64 = (UINT64) -1;\r
+          }\r
+        }\r
+        SendDataResponsePacket ((UINT8 *) &Data64, (UINT16) sizeof (Data64), DebugHeader);\r
+      } else {\r
+        Status = RETURN_UNSUPPORTED;\r
+      }\r
       break;\r
 \r
     default:\r
@@ -957,7 +2292,7 @@ CommandCommunication (
       SendAckPacket (DEBUG_COMMAND_ABORT);\r
     }\r
 \r
-    ReleaseDebugPortControl ();\r
+    ReleaseMpSpinLock (&mDebugMpContext.DebugPortSpinLock);\r
     CpuPause ();\r
   }\r
 }\r
@@ -965,7 +2300,7 @@ CommandCommunication (
 /**\r
   C function called in interrupt handler.\r
 \r
-  @param[in] Vector      Vector value of exception or interrutp.\r
+  @param[in] Vector      Vector value of exception or interrupt.\r
   @param[in] CpuContext  Pointer to save CPU context.\r
 \r
 **/\r
@@ -976,104 +2311,145 @@ InterruptProcess (
   IN DEBUG_CPU_CONTEXT               *CpuContext\r
   )\r
 {\r
-  UINT8                     InputCharacter;\r
-  UINT8                     BreakCause;\r
-  UINTN                     SavedEip;\r
-  BOOLEAN                   BreakReceived;\r
-  UINT32                    ProcessorIndex;\r
-  UINT32                    CurrentDebugTimerInitCount;\r
-  DEBUG_PORT_HANDLE         Handle;\r
-  UINT8                     Data8;\r
-\r
-  Handle = GetDebugPortHandle();\r
+  UINT8                            InputCharacter;\r
+  UINT8                            BreakCause;\r
+  UINTN                            SavedEip;\r
+  BOOLEAN                          BreakReceived;\r
+  UINT32                           ProcessorIndex;\r
+  UINT32                           CurrentDebugTimerInitCount;\r
+  DEBUG_PORT_HANDLE                Handle;\r
+  UINT8                            Data8;\r
+  UINT8                            *Al;\r
+  UINT32                           IssuedViewPoint;\r
+  DEBUG_AGENT_EXCEPTION_BUFFER     *ExceptionBuffer;\r
+\r
+  InputCharacter  = 0;\r
+  ProcessorIndex  = 0;\r
+  IssuedViewPoint = 0;\r
+  BreakReceived   = FALSE;\r
 \r
-  ProcessorIndex = 0;\r
-  BreakReceived  = FALSE;\r
+  if (mSkipBreakpoint) {\r
+    //\r
+    // If Skip Breakpoint flag is set, means communication is disturbed by hardware SMI, we need to ignore the break points in SMM\r
+    //\r
+    if ((Vector == DEBUG_INT1_VECTOR) || (Vector == DEBUG_INT3_VECTOR)) {\r
+      DebugPortWriteBuffer (GetDebugPortHandle(), (UINT8 *) mWarningMsgIngoreBreakpoint, AsciiStrLen (mWarningMsgIngoreBreakpoint));\r
+      return;\r
+    }\r
+  }\r
 \r
-  if (MultiProcessorDebugSupport) {\r
+  if (MultiProcessorDebugSupport()) {\r
     ProcessorIndex = GetProcessorIndex ();\r
-    while (mDebugMpContext.RunCommandSet);\r
+    //\r
+    // If this processor has already halted before, need to check it later\r
+    //\r
+    if (IsCpuStopped (ProcessorIndex)) {\r
+      IssuedViewPoint = ProcessorIndex;\r
+    }\r
+  }\r
+\r
+  if (IssuedViewPoint == ProcessorIndex && GetDebugFlag (DEBUG_AGENT_FLAG_STEPPING) != 1) {\r
+    //\r
+    // 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 (\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
+      LongJump ((BASE_LIBRARY_JUMP_BUFFER *)(UINTN)(ExceptionBuffer), 1);\r
+    }\r
+  }\r
+\r
+  if (MultiProcessorDebugSupport()) {\r
+    //\r
+    // If RUN command is executing, wait for it done.\r
+    //\r
+    while (mDebugMpContext.RunCommandSet) {\r
+      CpuPause ();\r
+    }\r
   }\r
 \r
+  Handle     = GetDebugPortHandle();\r
+  BreakCause = GetBreakCause (Vector, CpuContext);\r
   switch (Vector) {\r
   case DEBUG_INT1_VECTOR:\r
   case DEBUG_INT3_VECTOR:\r
-\r
-    BreakCause = GetBreakCause (Vector, CpuContext);\r
-\r
-    if (BreakCause == DEBUG_DATA_BREAK_CAUSE_SYSTEM_RESET) {\r
-\r
-      //\r
-      // Init break, if no ack received after 200ms, return\r
-      //\r
-      SendAckPacket (DEBUG_COMMAND_INIT_BREAK);\r
-      if (WaitForAckPacketOK (200 * 1000, &BreakReceived) != RETURN_SUCCESS) {\r
+    switch (BreakCause) {\r
+    case DEBUG_DATA_BREAK_CAUSE_SYSTEM_RESET:\r
+      if (AttachHost (BreakCause, READ_PACKET_TIMEOUT, &BreakReceived) != RETURN_SUCCESS) {\r
+        //\r
+        // Try to connect HOST, return if fails\r
+        //\r
         break;\r
       }\r
-\r
-      SetHostConnectedFlag ();\r
       CommandCommunication (Vector, CpuContext, BreakReceived);\r
+      break;\r
 \r
-    } else if (BreakCause == DEBUG_DATA_BREAK_CAUSE_STEPPING) {\r
-\r
+    case DEBUG_DATA_BREAK_CAUSE_STEPPING:\r
       //\r
       // Stepping is finished, send Ack package.\r
       //\r
-      if (MultiProcessorDebugSupport) {\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
       CommandCommunication (Vector, CpuContext, BreakReceived);\r
+      break;\r
 \r
-    } else if (BreakCause == DEBUG_DATA_BREAK_CAUSE_MEMORY_READY) {\r
-\r
+    case DEBUG_DATA_BREAK_CAUSE_MEMORY_READY:\r
       //\r
       // Memory is ready\r
       //\r
-      SendAckPacket (DEBUG_COMMAND_MEMORY_READY);\r
-      WaitForAckPacketOK (0, &BreakReceived);\r
+      SendCommandAndWaitForAckOK (DEBUG_COMMAND_MEMORY_READY, READ_PACKET_TIMEOUT, &BreakReceived, NULL);\r
       CommandCommunication (Vector, CpuContext, BreakReceived);\r
+      break;\r
 \r
-    } else {\r
+    case DEBUG_DATA_BREAK_CAUSE_IMAGE_LOAD:\r
+    case DEBUG_DATA_BREAK_CAUSE_IMAGE_UNLOAD:\r
+      //\r
+      // Set AL to DEBUG_AGENT_IMAGE_CONTINUE\r
+      //\r
+      Al = ArchReadRegisterBuffer (CpuContext, SOFT_DEBUGGER_REGISTER_AX, &Data8);\r
+      *Al = DEBUG_AGENT_IMAGE_CONTINUE;\r
 \r
-      if (BreakCause == DEBUG_DATA_BREAK_CAUSE_IMAGE_LOAD || BreakCause == DEBUG_DATA_BREAK_CAUSE_IMAGE_UNLOAD) {\r
-        \r
+      if (!IsHostAttached ()) {\r
         //\r
-        // Set AL to DEBUG_AGENT_IMAGE_CONTINUE\r
+        // If HOST is not connected for image load/unload, return\r
         //\r
-        Data8 = DEBUG_AGENT_IMAGE_CONTINUE;\r
-        ArchWriteRegisterBuffer (CpuContext, SOFT_DEBUGGER_REGISTER_AX, 0, 1, &Data8);\r
-\r
-        if (!IsHostConnected ()) {\r
-          //\r
-          // If HOST is not connected, return\r
-          //\r
-          break;\r
-        }\r
+        break;\r
       }\r
+      //\r
+      // Continue to run the following common code\r
+      //\r
 \r
-      AcquireDebugPortControl ();\r
-\r
-      if (MultiProcessorDebugSupport) {\r
-        if(!IsAllCpuRunning ()) {\r
-          //\r
-          // If other processors have been stopped\r
-          //\r
-          SetCpuBreakFlagByIndex (ProcessorIndex, TRUE);\r
-        } else {\r
-          //\r
-          // If no any processor was stopped, try to halt other processors\r
-          //\r
-          HaltOtherProcessors (ProcessorIndex);\r
-          SendAckPacket (DEBUG_COMMAND_BREAK_POINT);\r
-          WaitForAckPacketOK (0, &BreakReceived);\r
-        }\r
-      } else {\r
-        SendAckPacket (DEBUG_COMMAND_BREAK_POINT);\r
-        WaitForAckPacketOK (0, &BreakReceived);\r
+    case DEBUG_DATA_BREAK_CAUSE_HW_BREAKPOINT:\r
+    case DEBUG_DATA_BREAK_CAUSE_SW_BREAKPOINT:\r
+    default:\r
+      //\r
+      // Send Break packet to HOST\r
+      //\r
+      AcquireMpSpinLock (&mDebugMpContext.DebugPortSpinLock);\r
+      //\r
+      // Only the first breaking processor could send BREAK_POINT to HOST\r
+      //\r
+      if (IsFirstBreakProcessor (ProcessorIndex)) {\r
+        SendBreakPacketToHost (BreakCause, ProcessorIndex, &BreakReceived);\r
       }\r
-\r
-      ReleaseDebugPortControl ();\r
+      ReleaseMpSpinLock (&mDebugMpContext.DebugPortSpinLock);\r
 \r
       if (Vector == DEBUG_INT3_VECTOR) {\r
         //\r
@@ -1093,14 +2469,17 @@ InterruptProcess (
       } else {\r
         CommandCommunication (Vector, CpuContext, BreakReceived);\r
       }\r
+      break;\r
     }\r
 \r
     break;\r
 \r
   case DEBUG_TIMER_VECTOR:\r
 \r
-    if (MultiProcessorDebugSupport) {\r
-      if (IsBsp (ProcessorIndex)) {\r
+    AcquireMpSpinLock (&mDebugMpContext.DebugPortSpinLock);\r
+\r
+    if (MultiProcessorDebugSupport()) {\r
+      if (DebugAgentIsBsp (ProcessorIndex)) {\r
         //\r
         // If current processor is BSP, check Apic timer's init count if changed,\r
         // it may be re-written when switching BSP.\r
@@ -1108,11 +2487,13 @@ InterruptProcess (
         //\r
         CurrentDebugTimerInitCount = GetApicTimerInitCount ();\r
         if (mDebugMpContext.DebugTimerInitCount != CurrentDebugTimerInitCount) {\r
-          InitializeDebugTimer ();\r
+          InitializeDebugTimer (NULL, FALSE);\r
+          SaveAndSetDebugTimerInterrupt (TRUE);\r
         }\r
       }\r
 \r
-      if (!IsBsp (ProcessorIndex) || mDebugMpContext.IpiSentByAp) {\r
+      if (!DebugAgentIsBsp (ProcessorIndex) || mDebugMpContext.IpiSentByAp) {\r
+        ReleaseMpSpinLock (&mDebugMpContext.DebugPortSpinLock);\r
         //\r
         // If current processor is not BSP or this is one IPI sent by AP\r
         //\r
@@ -1131,28 +2512,52 @@ InterruptProcess (
     //\r
     // Only BSP could run here\r
     //\r
-\r
-    AcquireDebugPortControl ();\r
-    \r
-    while (DebugPortPollBuffer (Handle)) {\r
+    while (TRUE) {\r
       //\r
-      // If there is data in debug port, will check whether it is break-in symbol,\r
+      // If there is data in debug port, will check whether it is break(attach/break-in) symbol,\r
       // If yes, go into communication mode with HOST.\r
       // If no, exit interrupt process.\r
       //\r
-      DebugPortReadBuffer (Handle, &InputCharacter, 1, 0);\r
-      if (InputCharacter == DEBUG_STARTING_SYMBOL_BREAK) {\r
+      if (DebugReadBreakSymbol (Handle, &InputCharacter) == EFI_NOT_FOUND) {\r
+        break;\r
+      }\r
+\r
+      if ((!IsHostAttached () && (InputCharacter == DEBUG_STARTING_SYMBOL_ATTACH)) ||\r
+          (IsHostAttached () && (InputCharacter == DEBUG_COMMAND_HALT)) ||\r
+          (IsHostAttached () && (InputCharacter == DEBUG_COMMAND_GO))\r
+         ) {\r
+        DebugAgentMsgPrint (DEBUG_AGENT_VERBOSE, "Received data [%02x]\n", InputCharacter);\r
+        //\r
+        // Ack OK for break-in symbol\r
+        //\r
         SendAckPacket (DEBUG_COMMAND_OK);\r
-        if (MultiProcessorDebugSupport) {\r
-          if(FindCpuNotRunning () != -1) {\r
+\r
+        //\r
+        // If receive GO command in Debug Timer, means HOST may lost ACK packet before.\r
+        //\r
+        if (InputCharacter == DEBUG_COMMAND_GO) {\r
+          break;\r
+        }\r
+\r
+        if (!IsHostAttached ()) {\r
+          //\r
+          // Try to attach HOST, if no ack received after 200ms, return\r
+          //\r
+          if (AttachHost (BreakCause, READ_PACKET_TIMEOUT, &BreakReceived) != RETURN_SUCCESS) {\r
+            break;\r
+          }\r
+        }\r
+\r
+        if (MultiProcessorDebugSupport()) {\r
+          if(FindNextPendingBreakCpu  () != -1) {\r
             SetCpuBreakFlagByIndex (ProcessorIndex, TRUE);\r
           } else {\r
             HaltOtherProcessors (ProcessorIndex);\r
           }\r
         }\r
-        ReleaseDebugPortControl ();\r
+        ReleaseMpSpinLock (&mDebugMpContext.DebugPortSpinLock);\r
         CommandCommunication (Vector, CpuContext, BreakReceived);\r
-        AcquireDebugPortControl ();\r
+        AcquireMpSpinLock (&mDebugMpContext.DebugPortSpinLock);\r
         break;\r
       }\r
     }\r
@@ -1162,37 +2567,72 @@ InterruptProcess (
     //\r
     SendApicEoi ();\r
 \r
-    ReleaseDebugPortControl ();\r
+    ReleaseMpSpinLock (&mDebugMpContext.DebugPortSpinLock);\r
 \r
     break;\r
 \r
   default:\r
-\r
     if (Vector <= DEBUG_EXCEPT_SIMD) {\r
-\r
-      AcquireDebugPortControl ();\r
-\r
-      if (MultiProcessorDebugSupport) {\r
-        if(FindCpuNotRunning () != -1) {\r
-          SetCpuBreakFlagByIndex (ProcessorIndex, TRUE);\r
-        } else {\r
-          HaltOtherProcessors (ProcessorIndex);\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
+        // 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
+        // Exception occurs, send Break packet to HOST\r
+        //\r
+        AcquireMpSpinLock (&mDebugMpContext.DebugPortSpinLock);\r
+        //\r
+        // Only the first breaking processor could send BREAK_POINT to HOST\r
+        //\r
+        if (IsFirstBreakProcessor (ProcessorIndex)) {\r
+          SendBreakPacketToHost (BreakCause, ProcessorIndex, &BreakReceived);\r
         }\r
+        ReleaseMpSpinLock (&mDebugMpContext.DebugPortSpinLock);\r
       }\r
-      SendAckPacket (DEBUG_COMMAND_BREAK_POINT);\r
-      WaitForAckPacketOK (0, &BreakReceived);\r
-      ReleaseDebugPortControl ();\r
+\r
       CommandCommunication (Vector, CpuContext, BreakReceived);\r
     }\r
     break;\r
   }\r
 \r
-  if (MultiProcessorDebugSupport) {\r
+  if (MultiProcessorDebugSupport()) {\r
     //\r
     // Clear flag and wait for all processors run here\r
     //\r
     SetIpiSentByApFlag (FALSE);\r
-    while (mDebugMpContext.RunCommandSet);\r
+    while (mDebugMpContext.RunCommandSet) {\r
+      CpuPause ();\r
+    }\r
+\r
+    //\r
+    // Only current (view) processor could clean up AgentInProgress flag.\r
+    //\r
+    if (mDebugMpContext.ViewPointIndex == ProcessorIndex) {\r
+      IssuedViewPoint = mDebugMpContext.ViewPointIndex;\r
+    }\r
+  }\r
+\r
+  if (IssuedViewPoint == ProcessorIndex && GetDebugFlag (DEBUG_AGENT_FLAG_STEPPING) != 1) {\r
+    //\r
+    // If the command is not stepping, clean up AgentInProgress flag\r
+    //\r
+    SetDebugFlag (DEBUG_AGENT_FLAG_AGENT_IN_PROGRESS, 0);\r
   }\r
 \r
   return;\r