]> git.proxmox.com Git - mirror_edk2.git/commitdiff
This revision can only work with Intel(c) UDK Debugger Tool version 1.3 or greater...
authorvanjeff <vanjeff@6f19259b-4bc3-4df7-8a09-765794883524>
Fri, 25 Jan 2013 02:36:18 +0000 (02:36 +0000)
committervanjeff <vanjeff@6f19259b-4bc3-4df7-8a09-765794883524>
Fri, 25 Jan 2013 02:36:18 +0000 (02:36 +0000)
1. Add DebugAgentPei driver to initialize Debug Agent in PEI phase.
   Add DebugAgentDxe driver to initialize Debug Agent in DXE phase.
   DebugAgentDxe driver could be loaded and unloaded in shell.
2. Update the SourceLevelDebugPkg so that the debug agent can be initialized in any phase: SEC, PEI or DXE.
3. Add an enhanced retry algorithm that provides a robust connection when data loss happens in the debug channel.
4. Clear DR7 register in exception handler.
5. Set the default serial port parameter to 0 instead of PCDs.
6. Build pointer of Mailbox in HOB instead of Mailbox itself, since HOB may be moved at DXE entry point function.
7. Raise TPL to prevent recursion from EFI timer interrupts in SerialIo.c.
8. Add one spin lock for accessing Mailbox when MP debugging supported.
9. Use more non-NULL library instances in SourceLevelDebugPkg DSC file, thus DebugAgentDxe.efi built from SourceLevelDebugPkg could work in shell.
10.Separate all operations about IDT table entry from SecDebugAgentLib.c into DebugAgent\DebugAgentCommon's arch sub-directory.
11.Enhance Debug Agent to avoid breaking by hardware SMI during DXE debugging phase.
12.Add supporting on mode switch code debugging.
13.Remove reset Host Controller operation in DebugCommunicationLibUsb.c to avoid impacting EDKII usb stack.
14.Fix debug timer interrupt missing issue after back from legacy code.

Signed-off-by: Jeff Fan <jeff.fan@intel.com>
Signed-off-by: Ruiyu Ni <ruiyu.ni@intel.com>
Signed-off-by: Feng Tian <feng.tian@intel.com>
Reviewed-by: Jeff Fan <jeff.fan@intel.com>
Reviewed-by: Ruiyu Ni <ruiyu.ni@intel.com>
Reviewed-by: Feng Tian <feng.tian@intel.com>
git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@14083 6f19259b-4bc3-4df7-8a09-765794883524

41 files changed:
SourceLevelDebugPkg/DebugAgentDxe/DebugAgentDxe.c [new file with mode: 0644]
SourceLevelDebugPkg/DebugAgentDxe/DebugAgentDxe.inf [new file with mode: 0644]
SourceLevelDebugPkg/DebugAgentPei/DebugAgentPei.c [new file with mode: 0644]
SourceLevelDebugPkg/DebugAgentPei/DebugAgentPei.inf [new file with mode: 0644]
SourceLevelDebugPkg/Include/ImageDebugSupport.h
SourceLevelDebugPkg/Include/TransferProtocol.h
SourceLevelDebugPkg/Library/DebugAgent/DebugAgentCommon/DebugAgent.c
SourceLevelDebugPkg/Library/DebugAgent/DebugAgentCommon/DebugAgent.h
SourceLevelDebugPkg/Library/DebugAgent/DebugAgentCommon/DebugMp.c
SourceLevelDebugPkg/Library/DebugAgent/DebugAgentCommon/DebugMp.h
SourceLevelDebugPkg/Library/DebugAgent/DebugAgentCommon/DebugTimer.c
SourceLevelDebugPkg/Library/DebugAgent/DebugAgentCommon/Ia32/ArchDebugSupport.c
SourceLevelDebugPkg/Library/DebugAgent/DebugAgentCommon/Ia32/AsmFuncs.S
SourceLevelDebugPkg/Library/DebugAgent/DebugAgentCommon/Ia32/AsmFuncs.asm
SourceLevelDebugPkg/Library/DebugAgent/DebugAgentCommon/X64/ArchDebugSupport.c
SourceLevelDebugPkg/Library/DebugAgent/DebugAgentCommon/X64/AsmFuncs.S
SourceLevelDebugPkg/Library/DebugAgent/DebugAgentCommon/X64/AsmFuncs.asm
SourceLevelDebugPkg/Library/DebugAgent/DxeDebugAgent/DxeDebugAgentLib.c
SourceLevelDebugPkg/Library/DebugAgent/DxeDebugAgent/DxeDebugAgentLib.h
SourceLevelDebugPkg/Library/DebugAgent/DxeDebugAgent/SerialIo.c
SourceLevelDebugPkg/Library/DebugAgent/DxeDebugAgentLib.inf
SourceLevelDebugPkg/Library/DebugAgent/SecPeiDebugAgent/SecPeiDebugAgentLib.c
SourceLevelDebugPkg/Library/DebugAgent/SecPeiDebugAgent/SecPeiDebugAgentLib.h
SourceLevelDebugPkg/Library/DebugAgent/SecPeiDebugAgentLib.inf
SourceLevelDebugPkg/Library/DebugAgent/SmmDebugAgent/SmmDebugAgentLib.c
SourceLevelDebugPkg/Library/DebugAgent/SmmDebugAgentLib.inf
SourceLevelDebugPkg/Library/DebugCommunicationLibSerialPort/DebugCommunicationLibSerialPort.c
SourceLevelDebugPkg/Library/DebugCommunicationLibSerialPort/DebugCommunicationLibSerialPort.inf
SourceLevelDebugPkg/Library/DebugCommunicationLibUsb/DebugCommunicationLibUsb.c
SourceLevelDebugPkg/Library/DebugCommunicationLibUsb/DebugCommunicationLibUsb.inf
SourceLevelDebugPkg/Library/PeCoffExtraActionLibDebug/Ia32/IntHandler.S [new file with mode: 0644]
SourceLevelDebugPkg/Library/PeCoffExtraActionLibDebug/Ia32/IntHandler.asm [new file with mode: 0644]
SourceLevelDebugPkg/Library/PeCoffExtraActionLibDebug/Ia32/IntHandlerFuncs.c [new file with mode: 0644]
SourceLevelDebugPkg/Library/PeCoffExtraActionLibDebug/PeCoffExtraActionLib.c
SourceLevelDebugPkg/Library/PeCoffExtraActionLibDebug/PeCoffExtraActionLib.h [new file with mode: 0644]
SourceLevelDebugPkg/Library/PeCoffExtraActionLibDebug/PeCoffExtraActionLibDebug.inf
SourceLevelDebugPkg/Library/PeCoffExtraActionLibDebug/X64/IntHandler.S [new file with mode: 0644]
SourceLevelDebugPkg/Library/PeCoffExtraActionLibDebug/X64/IntHandler.asm [new file with mode: 0644]
SourceLevelDebugPkg/Library/PeCoffExtraActionLibDebug/X64/IntHandlerFuncs.c [new file with mode: 0644]
SourceLevelDebugPkg/SourceLevelDebugPkg.dec
SourceLevelDebugPkg/SourceLevelDebugPkg.dsc

diff --git a/SourceLevelDebugPkg/DebugAgentDxe/DebugAgentDxe.c b/SourceLevelDebugPkg/DebugAgentDxe/DebugAgentDxe.c
new file mode 100644 (file)
index 0000000..99bb2fd
--- /dev/null
@@ -0,0 +1,101 @@
+/** @file\r
+  Initialize Debug Agent in DXE by invoking Debug Agent Library.\r
+\r
+Copyright (c) 2013, 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
+\r
+**/\r
+\r
+#include <PiDxe.h>\r
+#include <Guid/EventGroup.h>\r
+#include <Library/UefiBootServicesTableLib.h>\r
+#include <Library/DebugAgentLib.h>\r
+\r
+EFI_EVENT       mExitBootServiceEvent; \r
+\r
+/**\r
+  One notified function to disable Debug Timer interrupt when gBS->ExitBootServices() called.\r
+\r
+  @param[in]  Event              Pointer to this event\r
+  @param[in]  Context            Event hanlder private data\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+DisableDebugTimerExitBootService (\r
+  EFI_EVENT                      Event,\r
+  VOID                           *Context\r
+  )\r
+\r
+{\r
+  SaveAndSetDebugTimerInterrupt (FALSE);\r
+}\r
+\r
+/**\r
+  The Entry Point for Debug Agent Dxe driver.\r
+\r
+  It will invoke Debug Agent Library to enable source debugging feature in DXE phase.\r
+\r
+  @param[in] ImageHandle    The firmware allocated handle for the EFI image.\r
+  @param[in] SystemTable    A pointer to the EFI System Table.\r
+\r
+  @retval EFI_SUCCESS       The entry point is executed successfully.\r
+  @retval other             Some error occurs when initialzed Debug Agent.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+DebugAgentDxeInitialize(\r
+  IN EFI_HANDLE           ImageHandle,\r
+  IN EFI_SYSTEM_TABLE     *SystemTable\r
+  )\r
+{\r
+  EFI_STATUS      Status;\r
+\r
+  InitializeDebugAgent (DEBUG_AGENT_INIT_DXE_LOAD, &Status, NULL);\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+  //\r
+  // Create event to disable Debug Timer interrupt when exit boot service.\r
+  //\r
+  Status = gBS->CreateEventEx (\r
+                  EVT_NOTIFY_SIGNAL,\r
+                  TPL_NOTIFY,\r
+                  DisableDebugTimerExitBootService,\r
+                  NULL,\r
+                  &gEfiEventExitBootServicesGuid,\r
+                  &mExitBootServiceEvent\r
+                  );\r
+  return Status;\r
+}\r
+\r
+/**\r
+  This is the unload handle for Debug Agent Dxe driver.\r
+\r
+  It will invoke Debug Agent Library to disable source debugging feature.\r
+\r
+  @param[in]  ImageHandle       The drivers' driver image.\r
+\r
+  @retval EFI_SUCCESS           The image is unloaded.\r
+  @retval Others                Failed to unload the image.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+DebugAgentDxeUnload (\r
+  IN EFI_HANDLE           ImageHandle\r
+  )\r
+{\r
+  EFI_STATUS          Status;\r
+\r
+  InitializeDebugAgent (DEBUG_AGENT_INIT_DXE_UNLOAD, &Status, NULL);\r
+\r
+  return Status;\r
+}\r
diff --git a/SourceLevelDebugPkg/DebugAgentDxe/DebugAgentDxe.inf b/SourceLevelDebugPkg/DebugAgentDxe/DebugAgentDxe.inf
new file mode 100644 (file)
index 0000000..114b708
--- /dev/null
@@ -0,0 +1,48 @@
+## @file\r
+#  Initialized Debug Agent in one separated DXE driver.\r
+#\r
+#  This DXE driver will invoke Debug Agent Library to initialize the debug agent.\r
+#\r
+# Copyright (c) 2013, 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
+#\r
+##\r
+\r
+[Defines]\r
+  INF_VERSION                    = 0x00010005\r
+  BASE_NAME                      = DebugAgentDxe\r
+  FILE_GUID                      = 9727502C-034E-472b-8E1B-67BB28C6CFDB\r
+  MODULE_TYPE                    = DXE_DRIVER\r
+  VERSION_STRING                 = 1.0  \r
+  ENTRY_POINT                    = DebugAgentDxeInitialize\r
+  UNLOAD_IMAGE                   = DebugAgentDxeUnload\r
+\r
+#\r
+# The following information is for reference only and not required by the build tools.\r
+#\r
+#  VALID_ARCHITECTURES           = IA32 X64\r
+#\r
+\r
+[Sources]\r
+  DebugAgentDxe.c\r
+  \r
+[Packages]\r
+  MdePkg/MdePkg.dec\r
+  MdeModulePkg/MdeModulePkg.dec\r
+\r
+[LibraryClasses]\r
+  UefiDriverEntryPoint\r
+  UefiBootServicesTableLib\r
+  DebugAgentLib  \r
+\r
+[Guids]\r
+  gEfiEventExitBootServicesGuid                 ## SOMETIMES_CONSUMES ## Event\r
+\r
+[Depex]\r
+  TRUE\r
diff --git a/SourceLevelDebugPkg/DebugAgentPei/DebugAgentPei.c b/SourceLevelDebugPkg/DebugAgentPei/DebugAgentPei.c
new file mode 100644 (file)
index 0000000..df0ac87
--- /dev/null
@@ -0,0 +1,45 @@
+/** @file\r
+  Initialize Debug Agent in PEI by invoking Debug Agent Library.\r
+\r
+Copyright (c) 2013, 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
+\r
+**/\r
+\r
+#include <PiPei.h>\r
+\r
+#include <Library/DebugAgentLib.h>\r
+\r
+/**\r
+  The Entry Point for Debug Agent PEI driver.\r
+\r
+  It will invoke Debug Agent Library to enable source debugging feature in PEI phase.\r
+\r
+  This function is the Entry point of the CPU I/O PEIM which installs CpuIoPpi.\r
+\r
+  @param[in]  FileHandle   Pointer to image file handle.\r
+  @param[in]  PeiServices  Pointer to PEI Services Table   \r
+\r
+  @retval EFI_SUCCESS    Debug Agent successfully initialized.\r
+  @retval other          Some error occurs when initialzed Debug Agent.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+DebugAgentPeiInitialize (\r
+  IN EFI_PEI_FILE_HANDLE     FileHandle,\r
+  IN CONST EFI_PEI_SERVICES  **PeiServices\r
+  )\r
+{\r
+  EFI_STATUS                 Status;\r
+\r
+  InitializeDebugAgent (DEBUG_AGENT_INIT_PEI, &Status, NULL);\r
+\r
+  return Status;\r
+}\r
diff --git a/SourceLevelDebugPkg/DebugAgentPei/DebugAgentPei.inf b/SourceLevelDebugPkg/DebugAgentPei/DebugAgentPei.inf
new file mode 100644 (file)
index 0000000..d20a012
--- /dev/null
@@ -0,0 +1,44 @@
+## @file\r
+#  Initialized Debug Agent in PEI phase.\r
+#\r
+#  This PEIM will invoke Debug Agent Library to initialize the debug agent in \r
+#  whole PEI phase.\r
+#\r
+# Copyright (c) 2013, 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
+#\r
+##\r
+\r
+[Defines]\r
+  INF_VERSION                    = 0x00010005\r
+  BASE_NAME                      = DebugAgentPei\r
+  FILE_GUID                      = D9D114EF-F40B-4d48-AAA0-A3DC99C9F5BD\r
+  MODULE_TYPE                    = PEIM\r
+  VERSION_STRING                 = 1.0  \r
+  ENTRY_POINT                    = DebugAgentPeiInitialize\r
+\r
+#\r
+# The following information is for reference only and not required by the build tools.\r
+#\r
+#  VALID_ARCHITECTURES           = IA32 X64\r
+#\r
+\r
+[Sources]\r
+  DebugAgentPei.c\r
+  \r
+[Packages]\r
+  MdePkg/MdePkg.dec\r
+  MdeModulePkg/MdeModulePkg.dec\r
+\r
+[LibraryClasses]\r
+  PeimEntryPoint\r
+  DebugAgentLib\r
+\r
+[Depex]\r
+  TRUE\r
index 68299857a60c1a4124cf60b255734d4d17a16507..511a12ce27fa6b3247db9196933a3f0faa9aa649 100644 (file)
@@ -2,7 +2,7 @@
   Public include file for Debug Agent Library instance and PE/COFF Extra\r
   Action Library instance.\r
 \r
-  Copyright (c) 2010, Intel Corporation. All rights reserved.<BR>\r
+  Copyright (c) 2010 - 2013, 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
@@ -19,6 +19,7 @@
 #define IO_PORT_BREAKPOINT_ADDRESS  0x84\r
 #define IMAGE_LOAD_SIGNATURE        SIGNATURE_32('L','O','A','D')\r
 #define IMAGE_UNLOAD_SIGNATURE      SIGNATURE_32('U','N','L','O')\r
+#define AGENT_HANDLER_SIGNATURE     SIGNATURE_32('A','G','T','H')\r
 \r
 #define DEBUG_AGENT_IMAGE_WAIT      0x00\r
 #define DEBUG_AGENT_IMAGE_CONTINUE  0x01\r
index bb7b07b4e286407f30f59ce1c881698c735e77c8..53e9f7cf3689c26dd8b1e613eefaece6bb36d4a0 100644 (file)
@@ -2,7 +2,7 @@
   Transfer protocol defintions used by debug agent and host. It is only\r
   intended to be used by Debug related module implementation.\r
 \r
-  Copyright (c) 2010 - 2012, Intel Corporation. All rights reserved.<BR>\r
+  Copyright (c) 2010 - 2013, 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
 //\r
 // Current revision of transfer protocol\r
 //\r
-#define DEBUG_AGENT_REVISION            ((0 << 16) | 02)\r
+#define DEBUG_AGENT_REVISION            ((0 << 16) | 03)\r
 #define DEBUG_AGENT_CAPABILITIES        0\r
 \r
-//\r
-// Definitions for break command.\r
-//\r
-#define DEBUG_STARTING_SYMBOL_BREAK         (0xFC)\r
-\r
 //\r
 // Definitions for attach command\r
 //\r
-#define DEBUG_STARTING_SYMBOL_ATTACH        (0xFA)\r
+#define DEBUG_STARTING_SYMBOL_ATTACH    (0xFA)\r
 \r
 //\r
 // Definition for starting symbol of a normal debug packet. Choose a non-ASCII to avoid conflict with other serial output.\r
 //\r
 #define DEBUG_STARTING_SYMBOL_NORMAL    (0xFE)\r
 \r
-\r
 #pragma pack(1)\r
 \r
 //\r
@@ -49,7 +43,8 @@ typedef struct {
   UINT8                      StartSymbol;\r
   UINT8                      Command;\r
   UINT8                      Length;    // Length of Debug Packet including header and payload in byte\r
-  UINT8                      CheckSum;\r
+  UINT8                      SequenceNo;\r
+  UINT16                     Crc;\r
 } DEBUG_PACKET_HEADER;\r
 \r
 //\r
@@ -86,6 +81,7 @@ typedef struct {
 #define DEBUG_COMMAND_DETACH                      (DEBUG_COMMAND_REQUEST | 0x16)\r
 #define DEBUG_COMMAND_CPUID                       (DEBUG_COMMAND_REQUEST | 0x17)\r
 #define DEBUG_COMMAND_SEARCH_SIGNATURE            (DEBUG_COMMAND_REQUEST | 0x18)\r
+#define DEBUG_COMMAND_HALT                        (DEBUG_COMMAND_REQUEST | 0x19)\r
 \r
 //\r
 // TARGET initiated commands\r
@@ -94,6 +90,7 @@ typedef struct {
 #define DEBUG_COMMAND_BREAK_POINT                 (DEBUG_COMMAND_REQUEST | 0x3E)\r
 #define DEBUG_COMMAND_MEMORY_READY                (DEBUG_COMMAND_REQUEST | 0x3D)\r
 #define DEBUG_COMMAND_PRINT_MESSAGE               (DEBUG_COMMAND_REQUEST | 0x3C)\r
+#define DEBUG_COMMAND_ATTACH_BREAK                (DEBUG_COMMAND_REQUEST | 0x3B)\r
 \r
 //\r
 // Response commands\r
@@ -308,8 +305,9 @@ typedef struct {
 //\r
 // Supported keys\r
 //\r
-#define DEBUG_AGENT_SETTING_SMM_ENTRY_BREAK     1\r
-#define DEBUG_AGENT_SETTING_PRINT_ERROR_LEVEL   2\r
+#define DEBUG_AGENT_SETTING_SMM_ENTRY_BREAK          1\r
+#define DEBUG_AGENT_SETTING_PRINT_ERROR_LEVEL        2\r
+#define DEBUG_AGENT_SETTING_BOOT_SCRIPT_ENTRY_BREAK  3\r
 //\r
 // Bitmask of print error level for debug message\r
 //\r
index 04dae34194a99072eeceb1616bb165eb4e04ef19..f4039f49952cc051e27d06f6849db5259783a460 100644 (file)
@@ -4,7 +4,7 @@
   read/write debug packet to communication with HOST based on transfer\r
   protocol.\r
 \r
-  Copyright (c) 2010 - 2012, Intel Corporation. All rights reserved.<BR>\r
+  Copyright (c) 2010 - 2013, Intel Corporation. All rights reserved.<BR>\r
   This program and the accompanying materials\r
   are licensed and made available under the terms and conditions of the BSD License\r
   which accompanies this distribution.  The full text of the license may be found at\r
 #include "DebugAgent.h"\r
 #include "Ia32/DebugException.h"\r
 \r
-#define INIT_BREAK_ACK_TIMEOUT  (200 * 1000)\r
+CHAR8 mErrorMsgVersionAlert[]       = "\rThe SourceLevelDebugPkg you are using requires a newer version of the Intel(R) UDK Debugger Tool.\r\n";\r
+CHAR8 mErrorMsgSendInitPacket[]     = "\rSend INIT break packet and try to connect the HOST (Intel(R) UDK Debugger Tool v1.3) ...\r\n";\r
+CHAR8 mErrorMsgConnectOK[]          = "HOST connection is successful!\r\n";\r
+CHAR8 mErrorMsgConnectFail[]        = "HOST connection is failed!\r\n";\r
+CHAR8 mWarningMsgIngoreBreakpoint[] = "Ignore break point in SMM for SMI issued during DXE debugging!\r\n";\r
 \r
-CHAR8 mErrorMsgVersionAlert[]   = "\rThe SourceLevelDebugPkg you are using requires a newer version of the Intel(R) UDK Debugger Tool.\r\n";\r
-CHAR8 mErrorMsgSendInitPacket[] = "\rSend INIT break packet to HOST ...\r\n";\r
-CHAR8 mErrorMsgConnectOK[]      = "HOST connection is successful!\r\n";\r
-CHAR8 mErrorMsgConnectFail[]    = "HOST connection is failed!\r\n";\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 ^= 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
+  Read IDT entry to check if IDT entries are setup by Debug Agent.\r
+\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
+IsDebugAgentInitialzed (\r
+  VOID\r
+  )\r
+{\r
+  UINTN                      InterruptHandler;\r
+\r
+  InterruptHandler = (UINTN) GetExceptionHandlerInIdtEntry (0);\r
+  if (InterruptHandler >= 4 &&  *(UINT32 *)(InterruptHandler - 4) == AGENT_HANDLER_SIGNATURE) {\r
+    return TRUE;\r
+  } else {\r
+    return FALSE;\r
+  }\r
+}\r
+\r
+/**\r
+  Find and report module image info to HOST.\r
+  \r
+  @param[in] AlignSize      Image aligned size.\r
+  \r
+**/\r
+VOID \r
+FindAndReportModuleImageInfo (\r
+  IN UINTN          AlignSize                   \r
+  )\r
+{\r
+  UINTN                                Pe32Data;\r
+  EFI_IMAGE_DOS_HEADER                 *DosHdr;\r
+  EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION  Hdr;\r
+  PE_COFF_LOADER_IMAGE_CONTEXT         ImageContext;\r
+\r
+  //\r
+  // Find Image Base\r
+  //\r
+  Pe32Data = ((UINTN)mErrorMsgVersionAlert) & ~(AlignSize - 1);\r
+  while (Pe32Data != 0) {\r
+    DosHdr = (EFI_IMAGE_DOS_HEADER *) Pe32Data;\r
+    if (DosHdr->e_magic == EFI_IMAGE_DOS_SIGNATURE) {\r
+      //\r
+      // DOS image header is present, so read the PE header after the DOS image header.\r
+      // Check if address overflow firstly.\r
+      //\r
+      if ((MAX_ADDRESS - (UINTN)DosHdr->e_lfanew) > Pe32Data) {\r
+        Hdr.Pe32 = (EFI_IMAGE_NT_HEADERS32 *)(Pe32Data + (UINTN)(DosHdr->e_lfanew));\r
+        if (Hdr.Pe32->Signature == EFI_IMAGE_NT_SIGNATURE) {\r
+          //\r
+          // It's PE image.\r
+          //\r
+          break;\r
+        }\r
+      }\r
+    } else {\r
+      //\r
+      // DOS image header is not present, TE header is at the image base.\r
+      //\r
+      Hdr.Pe32 = (EFI_IMAGE_NT_HEADERS32 *)Pe32Data;\r
+      if ((Hdr.Te->Signature == EFI_TE_IMAGE_HEADER_SIGNATURE) &&\r
+          ((Hdr.Te->Machine == IMAGE_FILE_MACHINE_I386) || Hdr.Te->Machine == IMAGE_FILE_MACHINE_X64)) {\r
+        //\r
+        // It's TE image, it TE header and Machine type match\r
+        //\r
+        break;\r
+      }\r
+    }\r
+\r
+    //\r
+    // Not found the image base, check the previous aligned address\r
+    // \r
+    Pe32Data -= AlignSize;\r
+  }\r
+\r
+  ImageContext.ImageAddress = Pe32Data;\r
+  ImageContext.PdbPointer = PeCoffLoaderGetPdbPointer ((VOID*) (UINTN) ImageContext.ImageAddress);\r
+  PeCoffLoaderRelocateImageExtraAction (&ImageContext);\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
+  Caculate 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
+  }\r
+  UpdateMailboxChecksum (Mailbox);\r
+  ReleaseMpSpinLock (&mDebugMpContext.MailboxSpinLock);\r
+}\r
+/**\r
+  Set debug flag in mailbox.\r
+\r
+  @param[in]  FlagMask      Debug flag mask value.\r
+  @param[in]  FlagValue     Debug flag value.\r
+\r
+**/\r
+VOID \r
+SetDebugFlag (\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
+  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
@@ -46,8 +339,12 @@ SendDebugMsgPacket (
   DebugHeader.StartSymbol = DEBUG_STARTING_SYMBOL_NORMAL;\r
   DebugHeader.Command     = DEBUG_COMMAND_PRINT_MESSAGE;\r
   DebugHeader.Length      = sizeof (DEBUG_PACKET_HEADER) + (UINT8) Length;\r
-  DebugHeader.CheckSum    = 0;\r
-  DebugHeader.CheckSum    = CalculateCheckSum8 ((UINT8 *)&DebugHeader, sizeof (DEBUG_PACKET_HEADER));\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
@@ -73,15 +370,13 @@ DebugAgentMsgPrint (
   ...\r
   )\r
 {\r
-  DEBUG_AGENT_MAILBOX  *Mailbox;\r
   CHAR8                Buffer[DEBUG_DATA_MAXIMUM_REAL_DATA];\r
   VA_LIST              Marker;\r
 \r
-  Mailbox = GetMailboxPointer ();\r
   //\r
   // Check driver debug mask value and global mask\r
   //\r
-  if ((ErrorLevel & Mailbox->DebugFlag.PrintErrorLevel) == 0) {\r
+  if ((ErrorLevel & GetDebugFlag (DEBUG_AGENT_FLAG_PRINT_ERROR_LEVEL)) == 0) {\r
     return;\r
   }\r
 \r
@@ -119,16 +414,14 @@ DebugAgentDataMsgPrint (
   IN UINT8             Length  \r
   )\r
 {\r
-  DEBUG_AGENT_MAILBOX  *Mailbox;\r
   CHAR8                Buffer[DEBUG_DATA_MAXIMUM_REAL_DATA];\r
   CHAR8                *DestBuffer;\r
   UINTN                Index;\r
 \r
-  Mailbox = GetMailboxPointer ();\r
   //\r
   // Check driver debug mask value and global mask\r
   //\r
-  if ((ErrorLevel & Mailbox->DebugFlag.PrintErrorLevel) == 0) {\r
+  if ((ErrorLevel & GetDebugFlag (DEBUG_AGENT_FLAG_PRINT_ERROR_LEVEL)) == 0) {\r
     return;\r
   }\r
 \r
@@ -152,7 +445,7 @@ DebugAgentDataMsgPrint (
     DestBuffer += AsciiSPrint (DestBuffer, DEBUG_DATA_MAXIMUM_REAL_DATA - (DestBuffer - Buffer), "%02x ", Data[Index]);\r
     Index ++;\r
     if (Index >= Length) {\r
-      //s\r
+      //\r
       // The last character of debug message has been foramtted in buffer\r
       //\r
       DestBuffer += AsciiSPrint(DestBuffer, DEBUG_DATA_MAXIMUM_REAL_DATA - (DestBuffer - Buffer), "]\n");\r
@@ -162,6 +455,46 @@ DebugAgentDataMsgPrint (
   }\r
 }\r
 \r
+/**\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
+\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
+  //\r
+  // Has received start symbol, try to read the rest part\r
+  //\r
+  if (DebugPortReadBuffer (Handle, &DebugHeader->Command, sizeof (DEBUG_PACKET_HEADER) - 1, READ_PACKET_TIMEOUT) == 0) {\r
+    //\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
+\r
+  UpdateMailboxContent (GetMailboxPointer(), DEBUG_MAILBOX_HOST_SEQUENCE_NO_INDEX, DebugHeader->SequenceNo);\r
+  return EFI_SUCCESS;\r
+}\r
 \r
 /**\r
   Check if HOST is attached based on Mailbox.\r
@@ -175,7 +508,7 @@ IsHostAttached (
   VOID\r
   )\r
 {\r
-  return (BOOLEAN) (GetMailboxPointer ()->DebugFlag.HostAttached == 1);\r
+  return (BOOLEAN) (GetDebugFlag (DEBUG_AGENT_FLAG_HOST_ATTACHED) == 1);\r
 }\r
 \r
 /**\r
@@ -190,7 +523,7 @@ SetHostAttached (
   )\r
 {\r
   DebugAgentMsgPrint (DEBUG_AGENT_INFO, "Attach status is %d\n", Attached);\r
-  GetMailboxPointer ()->DebugFlag.HostAttached = Attached;\r
+  SetDebugFlag (DEBUG_AGENT_FLAG_HOST_ATTACHED, (UINT32)Attached);\r
 }\r
 \r
 /**\r
@@ -208,17 +541,17 @@ SetDebugSetting (
   )\r
 {\r
   RETURN_STATUS                Status;\r
-  DEBUG_AGENT_MAILBOX          *Mailbox;\r
-\r
-  Mailbox = GetMailboxPointer ();\r
 \r
   Status = RETURN_SUCCESS;\r
   switch (DebugSetting->Key) {\r
   case DEBUG_AGENT_SETTING_SMM_ENTRY_BREAK:\r
-    Mailbox->DebugFlag.BreakOnNextSmi = DebugSetting->Value;\r
+    SetDebugFlag (DEBUG_AGENT_FLAG_BREAK_ON_NEXT_SMI, DebugSetting->Value);\r
     break;\r
   case DEBUG_AGENT_SETTING_PRINT_ERROR_LEVEL:\r
-    Mailbox->DebugFlag.PrintErrorLevel = DebugSetting->Value;\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
@@ -446,11 +779,13 @@ ArchReadRegisterBuffer (
   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                  CommandType,\r
+  IN UINT8                  SequenceNo\r
   )\r
 {\r
   DEBUG_PACKET_HEADER       DebugHeader;\r
@@ -461,8 +796,9 @@ SendPacketWithoutData (
   DebugHeader.StartSymbol = DEBUG_STARTING_SYMBOL_NORMAL;\r
   DebugHeader.Command     = CommandType;\r
   DebugHeader.Length      = sizeof (DEBUG_PACKET_HEADER);\r
-  DebugHeader.CheckSum    = 0;\r
-  DebugHeader.CheckSum    = CalculateCheckSum8 ((UINT8 *)&DebugHeader, 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
   DebugAgentDataMsgPrint (DEBUG_AGENT_VERBOSE, TRUE, (UINT8 *) &DebugHeader, DebugHeader.Length);\r
   DebugPortWriteBuffer (Handle, (UINT8 *) &DebugHeader, DebugHeader.Length);\r
@@ -479,104 +815,142 @@ SendAckPacket (
   IN UINT8                AckCommand\r
   )\r
 {\r
+  UINT8                   SequenceNo;\r
+  DEBUG_AGENT_MAILBOX     *Mailbox;\r
+\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
-  SendPacketWithoutData (AckCommand);\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
-  Receive acknowledge packet from HOST in specified time.\r
+  Receive valid packet from HOST.\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[out] CheckSumStatus If CheckSumStatus is not NULL,\r
-                             RETURN_SUCCESS   CheckSum is OK.\r
-                             RETURN_NOT_FOUND Not find the CheckSum field.\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 acknowlege 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  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
+  @retval RETURN_SUCCESS   A valid package was reveived in InputPacket.\r
+  @retval RETURN_TIMEOUT   Timeout occurs.\r
 \r
 **/\r
 RETURN_STATUS\r
-ReceiveAckPacket (\r
-  OUT UINT8                     *Ack,\r
-  IN  UINTN                     Timeout,\r
-  OUT BOOLEAN                   *BreakReceived, OPTIONAL\r
-  OUT RETURN_STATUS             *CheckSumStatus OPTIONAL\r
+ReceivePacket (\r
+  OUT UINT8             *InputPacket,\r
+  OUT BOOLEAN           *BreakReceived,\r
+  OUT BOOLEAN           *IncompatibilityFlag, OPTIONAL\r
+  IN  UINTN             Timeout,\r
+  IN  BOOLEAN           SkipStartSymbol\r
   )\r
 {\r
-  DEBUG_PACKET_HEADER       DebugHeader;\r
-  DEBUG_PORT_HANDLE         Handle;\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
+  if (SkipStartSymbol) {\r
+    TimeoutForStartSymbol = 0;\r
+  } else {\r
+    TimeoutForStartSymbol = Timeout;\r
+  }\r
+  \r
+  DebugHeader = (DEBUG_PACKET_HEADER *) InputPacket;\r
   while (TRUE) {\r
-    if (DebugPortReadBuffer (Handle, (UINT8 *) &DebugHeader.StartSymbol, sizeof (DebugHeader.StartSymbol), Timeout) == 0) {\r
+    //\r
+    // Find the valid start symbol\r
+    //\r
+    Received = DebugPortReadBuffer (Handle, &DebugHeader->StartSymbol, sizeof (DebugHeader->StartSymbol), TimeoutForStartSymbol);\r
+    if (Received < sizeof (DebugHeader->StartSymbol)) {\r
+      DebugAgentMsgPrint (DEBUG_AGENT_WARNING, "DebugPortReadBuffer(StartSymbol) timeout\n");\r
       return RETURN_TIMEOUT;\r
     }\r
-    if (DebugHeader.StartSymbol == DEBUG_STARTING_SYMBOL_BREAK) {\r
-      if (BreakReceived != NULL) {\r
-        SendAckPacket (DEBUG_COMMAND_HALT_DEFERRED);\r
-        *BreakReceived = TRUE;\r
-      }\r
-    }\r
-    if (DebugHeader.StartSymbol == DEBUG_STARTING_SYMBOL_NORMAL) {\r
-      break;\r
+\r
+    if (DebugHeader->StartSymbol != DEBUG_STARTING_SYMBOL_NORMAL) {\r
+      DebugAgentMsgPrint (DEBUG_AGENT_WARNING, "Invalid start symbol received [%02x]\n", DebugHeader->StartSymbol);\r
+      continue;\r
     }\r
-    DebugAgentMsgPrint (DEBUG_AGENT_ERROR, "Invalid start symbol received [%02x]\n", DebugHeader.StartSymbol);\r
-  }\r
-  //\r
-  // Read ACK packet header till field Length (not including StartSymbol and CheckSum)\r
-  //\r
-  DebugHeader.Length = 0;\r
-  if (DebugPortReadBuffer (\r
-        Handle,\r
-        (UINT8 *)&DebugHeader.Command,\r
-        OFFSET_OF (DEBUG_PACKET_HEADER, Length) + sizeof (DebugHeader.Length) - sizeof (DebugHeader.StartSymbol),\r
-        Timeout\r
-        ) == 0) {\r
-    return RETURN_TIMEOUT;\r
-  }\r
 \r
-  if (DebugHeader.Length == 0) {\r
     //\r
-    // The CheckSum field does not exist\r
+    // Read Package header till field Length\r
     //\r
-    if (CheckSumStatus != NULL) {\r
-      *CheckSumStatus = RETURN_NOT_FOUND;\r
-    }\r
-  } else {\r
-    if (CheckSumStatus != NULL) {\r
-      *CheckSumStatus = RETURN_SUCCESS;\r
-    }\r
-    if (DebugPortReadBuffer (Handle, &DebugHeader.CheckSum, sizeof (DebugHeader.CheckSum), Timeout) == 0) {\r
+    Received = DebugPortReadBuffer (\r
+                 Handle,\r
+                 &DebugHeader->Command,\r
+                 OFFSET_OF (DEBUG_PACKET_HEADER, Length) + sizeof (DebugHeader->Length) - sizeof (DebugHeader->StartSymbol),\r
+                 Timeout\r
+                 );\r
+    if (Received == 0) {\r
+      DebugAgentMsgPrint (DEBUG_AGENT_ERROR, "DebugPortReadBuffer(Command) timeout\n");\r
       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 = DebugPortReadBuffer (Handle, &DebugHeader->SequenceNo, (UINT8) (DebugHeader->Length - OFFSET_OF (DEBUG_PACKET_HEADER, SequenceNo)), Timeout);\r
+      if (Received == 0) {\r
+        DebugAgentMsgPrint (DEBUG_AGENT_ERROR, "DebugPortReadBuffer(SequenceNo) timeout\n");\r
+        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
-  *Ack = DebugHeader.Command;\r
+  DebugAgentDataMsgPrint (DEBUG_AGENT_VERBOSE, FALSE, (UINT8 *) DebugHeader, DebugHeader->Length);\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 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[out] CheckSumStatus If CheckSumStatus is not NULL,\r
-                             RETURN_SUCCESS   CheckSum is OK.\r
-                             RETURN_NOT_FOUND Not find the CheckSum field.\r
+  @param[in]  Command             The command type issued by TARGET.\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[out] IncompatibilityFlag If IncompatibilityFlag is not NULL, return\r
+                                  TRUE:  Compatible packet received.\r
+                                  FALSE: Incompatible packet received.\r
 \r
   @retval  RETRUEN_SUCCESS  Succeed to receive acknowlege packet from HOST,\r
                             the type of acknowlege packet saved in Ack.\r
@@ -588,109 +962,56 @@ SendCommandAndWaitForAckOK (
   IN  UINT8               Command,\r
   IN  UINTN               Timeout,\r
   OUT BOOLEAN             *BreakReceived, OPTIONAL\r
-  OUT RETURN_STATUS       *CheckSumStatus OPTIONAL\r
+  OUT BOOLEAN             *IncompatibilityFlag OPTIONAL\r
   )\r
 {\r
   RETURN_STATUS           Status;\r
-  UINT8                   Ack;\r
-  \r
-  while (TRUE) {\r
-    SendPacketWithoutData (Command);\r
-    while (TRUE) {\r
-      Status = ReceiveAckPacket (&Ack, Timeout, BreakReceived, CheckSumStatus);\r
-      if (Status == RETURN_SUCCESS && Ack == DEBUG_COMMAND_RESEND) {\r
-        //\r
-        // Resend the last command\r
-        //\r
-        break;\r
-      } \r
-      if ((Status == RETURN_SUCCESS && Ack == DEBUG_COMMAND_OK) ||\r
-           Status == RETURN_TIMEOUT) {\r
-        //\r
-        // Received Ack OK or timeout\r
-        //\r
-        return Status;\r
-      }  \r
-    }\r
-  }\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_TIMEOUT   Timeout occurs.\r
-\r
-**/\r
-RETURN_STATUS\r
-ReceivePacket (\r
-  OUT UINT8             *InputPacket,\r
-  OUT BOOLEAN           *BreakReceived\r
-  )\r
-{\r
-  DEBUG_PACKET_HEADER   *DebugHeader;\r
-  UINTN                 Received;\r
-  DEBUG_PORT_HANDLE     Handle;\r
-  UINT8                 CheckSum;\r
-\r
-  Handle = GetDebugPortHandle();\r
-  \r
-  DebugHeader = (DEBUG_PACKET_HEADER *) InputPacket;\r
-  while (TRUE) {\r
-    //\r
-    // Find the valid start symbol\r
-    //\r
-    DebugPortReadBuffer (Handle, &DebugHeader->StartSymbol, sizeof (DebugHeader->StartSymbol), 0);\r
-\r
-    if (DebugHeader->StartSymbol == DEBUG_STARTING_SYMBOL_BREAK) {\r
-      *BreakReceived = TRUE;\r
-      SendAckPacket (DEBUG_COMMAND_HALT_DEFERRED);\r
-    }\r
-\r
-    if (DebugHeader->StartSymbol != DEBUG_STARTING_SYMBOL_NORMAL) {\r
-      DebugAgentMsgPrint (DEBUG_AGENT_ERROR, "Invalid start symbol received [%02x]\n", DebugHeader->StartSymbol);\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
-\r
-    //\r
-    // Read Package header except for checksum\r
-    //\r
-    Received = DebugPortReadBuffer (\r
-                 Handle,\r
-                 &DebugHeader->Command,\r
-                 OFFSET_OF (DEBUG_PACKET_HEADER, Length) + sizeof (DebugHeader->Length) - sizeof (DebugHeader->StartSymbol),\r
-                 0\r
-                 );\r
-    if (Received == 0) {\r
-      return RETURN_TIMEOUT;\r
-    }\r
-\r
+    ASSERT_EFI_ERROR (Status);\r
     //\r
-    // Read the payload data include the checksum\r
+    // Status == RETURN_SUCCESS\r
     //\r
-    Received = DebugPortReadBuffer (Handle, &DebugHeader->CheckSum, DebugHeader->Length - OFFSET_OF (DEBUG_PACKET_HEADER, CheckSum), 0);\r
-    if (Received == 0) {\r
-      return RETURN_TIMEOUT;\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
-    //\r
-    // Calculate the checksum of Debug Packet\r
-    //\r
-    CheckSum = CalculateCheckSum8 ((UINT8 *) DebugHeader, DebugHeader->Length);\r
-    if (CheckSum == 0) {\r
-      break;\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
-    DebugAgentMsgPrint (DEBUG_AGENT_WARNING, "CheckSum Error (Caculated checksum is %x, received checksum is %x\n", CheckSum, DebugHeader->CheckSum);\r
-    DebugAgentMsgPrint (DEBUG_AGENT_WARNING, "Send DEBUG_COMMAND_RESEND command.\n");\r
-    SendAckPacket (DEBUG_COMMAND_RESEND);\r
   }\r
 \r
-  DebugAgentDataMsgPrint (DEBUG_AGENT_VERBOSE, FALSE, (UINT8 *) DebugHeader, DebugHeader->Length);\r
-\r
-  return RETURN_SUCCESS;\r
+  ASSERT (Command == DEBUG_COMMAND_INIT_BREAK);\r
+  return Status;\r
 }\r
 \r
 /**\r
@@ -773,7 +1094,7 @@ GetBreakCause (
 \r
   default:\r
     if (Vector < 20) {\r
-      if (GetMailboxPointer()->DebugFlag.SteppingFlag == 1) {\r
+      if (GetDebugFlag (DEBUG_AGENT_FLAG_STEPPING) == 1) {\r
         //\r
         // If stepping command is executing\r
         //\r
@@ -789,28 +1110,28 @@ GetBreakCause (
 }\r
 \r
 /**\r
-  Send command packet with data to HOST.\r
+  Send packet with response data to HOST.\r
 \r
-  @param[in] Command     Command type.\r
   @param[in] Data        Pointer to response data buffer.\r
   @param[in] DataSize    Size of response data in byte.\r
 \r
   @retval RETURN_SUCCESS      Response data was sent successfully.\r
-  @retval RETURN_DEVICE_ERROR Cannot receive DEBUG_COMMAND_OK from HOST.\r
 \r
 **/\r
 RETURN_STATUS\r
-SendCommandWithDataPacket (\r
-  IN UINT8                Command,\r
+SendDataResponsePacket (\r
   IN UINT8                *Data,\r
   IN UINT16               DataSize\r
   )\r
 {\r
+  RETURN_STATUS        Status;\r
   DEBUG_PACKET_HEADER  *DebugHeader;\r
   BOOLEAN              LastPacket;\r
-  UINT8                Ack;\r
+  DEBUG_PACKET_HEADER  *AckDebugHeader;\r
   UINT8                DebugPacket[DEBUG_DATA_UPPER_LIMIT];\r
+  UINT8                InputPacketBuffer[DEBUG_DATA_UPPER_LIMIT];\r
   DEBUG_PORT_HANDLE    Handle;\r
+  UINT8                SequenceNo;\r
 \r
   Handle = GetDebugPortHandle();\r
 \r
@@ -818,83 +1139,66 @@ SendCommandWithDataPacket (
   DebugHeader->StartSymbol = DEBUG_STARTING_SYMBOL_NORMAL;\r
 \r
   while (TRUE) {\r
+    SequenceNo = GetMailboxPointer()->HostSequenceNo;\r
     if (DataSize <= DEBUG_DATA_MAXIMUM_REAL_DATA) {\r
       LastPacket = TRUE;\r
-      DebugHeader->Command  = Command;\r
-      DebugHeader->Length   = (UINT8) (DataSize + sizeof (DEBUG_PACKET_HEADER));\r
-      DebugHeader->CheckSum = 0;\r
+      DebugHeader->Command    = DEBUG_COMMAND_OK;\r
+      DebugHeader->Length     = (UINT8) (DataSize + sizeof (DEBUG_PACKET_HEADER));\r
+      DebugHeader->SequenceNo = SequenceNo;\r
+      DebugHeader->Crc        = 0;\r
       CopyMem (DebugHeader + 1, Data, DataSize);\r
 \r
     } else {\r
       LastPacket = FALSE;\r
-      DebugHeader->Command  = DEBUG_COMMAND_IN_PROGRESS;\r
-      DebugHeader->Length   = DEBUG_DATA_MAXIMUM_REAL_DATA + sizeof (DEBUG_PACKET_HEADER);\r
-      DebugHeader->CheckSum = 0;\r
+      DebugHeader->Command    = DEBUG_COMMAND_IN_PROGRESS;\r
+      DebugHeader->Length     = DEBUG_DATA_MAXIMUM_REAL_DATA + sizeof (DEBUG_PACKET_HEADER);\r
+      DebugHeader->SequenceNo = SequenceNo;\r
+      DebugHeader->Crc        = 0;\r
       CopyMem (DebugHeader + 1, Data, DEBUG_DATA_MAXIMUM_REAL_DATA);\r
     }\r
 \r
     //\r
     // Calculate and fill the checksum\r
     //\r
-    DebugHeader->CheckSum = CalculateCheckSum8 ((UINT8 *) DebugHeader, DebugHeader->Length);\r
+    DebugHeader->Crc = CalculateCrc16 ((UINT8 *) DebugHeader, DebugHeader->Length, 0);\r
 \r
     DebugAgentDataMsgPrint (DEBUG_AGENT_VERBOSE, TRUE, (UINT8 *) DebugHeader, DebugHeader->Length);\r
     \r
     DebugPortWriteBuffer (Handle, (UINT8 *) DebugHeader, DebugHeader->Length);\r
 \r
-    ReceiveAckPacket(&Ack, 0, NULL, NULL);\r
-    switch (Ack) {\r
-    case DEBUG_COMMAND_RESEND:\r
-      //\r
-      // Send the packet again\r
-      //\r
-      DebugAgentMsgPrint (DEBUG_AGENT_WARNING, "Received DEBUG_COMMAND_RESEND.\n");\r
-      break;\r
-\r
-    case DEBUG_COMMAND_CONTINUE:\r
-      //\r
-      // Send the rest packet\r
-      //\r
-      Data     += DEBUG_DATA_MAXIMUM_REAL_DATA;\r
-      DataSize -= DEBUG_DATA_MAXIMUM_REAL_DATA;\r
-      break;\r
-\r
-    case DEBUG_COMMAND_OK:\r
-      if (LastPacket) {\r
+    while (TRUE) {\r
+      Status = ReceivePacket (InputPacketBuffer, 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
+      AckDebugHeader = (DEBUG_PACKET_HEADER *) InputPacketBuffer;\r
+      SequenceNo = AckDebugHeader->SequenceNo;\r
+      if (AckDebugHeader->Command == DEBUG_COMMAND_OK &&\r
+          SequenceNo == DebugHeader->SequenceNo &&\r
+          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 ((SequenceNo == (UINT8) (DebugHeader->SequenceNo + 1)) && (AckDebugHeader->Command == DEBUG_COMMAND_CONTINUE)) {\r
+        //\r
+        // Send the rest packet\r
+        //\r
+        Data     += DEBUG_DATA_MAXIMUM_REAL_DATA;\r
+        DataSize -= DEBUG_DATA_MAXIMUM_REAL_DATA;\r
+        UpdateMailboxContent (GetMailboxPointer(), DEBUG_MAILBOX_HOST_SEQUENCE_NO_INDEX, (UINT8) SequenceNo);\r
+        break;\r
+      }\r
+      if (SequenceNo >= DebugHeader->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 packet with response data to HOST.\r
-\r
-  @param[in] Data        Pointer to response data buffer.\r
-  @param[in] DataSize    Size of response data in byte.\r
-\r
-  @retval RETURN_SUCCESS      Response data was sent successfully.\r
-  @retval RETURN_DEVICE_ERROR Cannot receive DEBUG_COMMAND_OK from HOST.\r
-\r
-**/\r
-RETURN_STATUS\r
-SendDataResponsePacket (\r
-  IN UINT8                *Data,\r
-  IN UINT16               DataSize\r
-  )\r
-{\r
-  return SendCommandWithDataPacket (DEBUG_COMMAND_OK, Data, DataSize);\r
-}\r
-\r
 /**\r
   Send break cause packet to HOST.\r
 \r
@@ -927,6 +1231,7 @@ SendBreakCausePacket (
   If received acknowlege, 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 acknowlege from HOST.\r
                              The unit is microsecond.\r
   @param[out] BreakReceived  If BreakReceived is not NULL,\r
@@ -935,42 +1240,45 @@ SendBreakCausePacket (
 **/\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
-  RETURN_STATUS                    CheckSumStatus;\r
+  BOOLEAN                          IncompatibilityFlag;\r
 \r
+  IncompatibilityFlag = FALSE;\r
   Handle = GetDebugPortHandle();\r
     \r
   //\r
   // Send init break and wait ack in Timeout\r
   //\r
   DebugPortWriteBuffer (Handle, (UINT8 *) mErrorMsgSendInitPacket, AsciiStrLen (mErrorMsgSendInitPacket));\r
-  Status = SendCommandAndWaitForAckOK (DEBUG_COMMAND_INIT_BREAK, Timeout, BreakReceived, &CheckSumStatus);\r
-  if (RETURN_ERROR (Status)) {\r
-    DebugPortWriteBuffer (Handle, (UINT8 *) mErrorMsgConnectFail, AsciiStrLen (mErrorMsgConnectFail));\r
-    return Status;\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
-  \r
-  if (CheckSumStatus == RETURN_NOT_FOUND) {\r
+  if (IncompatibilityFlag) {\r
     //\r
-    // If the CheckSum field does not exist in Debug Packet,\r
-    // the HOST should be running with 0.1 transfer protocol.\r
-    // It could be UDK Debugger for Windows v1.1 or for Linux v0.8.\r
+    // If the incompatible Debug Packet received, the HOST should be running transfer protocol before DEBUG_AGENT_REVISION.\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
-  DebugPortWriteBuffer (Handle, (UINT8 *) mErrorMsgConnectOK, AsciiStrLen (mErrorMsgConnectOK));\r
-  //\r
-  // Set Attach flag\r
-  //\r
-  SetHostAttached (TRUE);\r
-\r
+  \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
@@ -978,7 +1286,8 @@ AttachHost (
   Send Break point packet to HOST. \r
   \r
   Only the first breaking processor could sent BREAK_POINT packet.\r
\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 retured if break-in symbol received.\r
@@ -987,6 +1296,7 @@ AttachHost (
 **/\r
 VOID\r
 SendBreakPacketToHost (\r
+  IN  UINT8                BreakCause,\r
   IN  UINT32               ProcessorIndex,\r
   OUT BOOLEAN              *BreakReceived\r
   )\r
@@ -998,7 +1308,7 @@ SendBreakPacketToHost (
   \r
   if (IsHostAttached ()) {\r
     DebugAgentMsgPrint (DEBUG_AGENT_INFO, "processor[%x]:Send Break Packet to HOST.\n", ProcessorIndex);\r
-    SendCommandAndWaitForAckOK (DEBUG_COMMAND_BREAK_POINT, 0, BreakReceived, NULL);\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
@@ -1015,7 +1325,7 @@ SendBreakPacketToHost (
     //\r
     // Try to attach HOST\r
     //\r
-    while (AttachHost (0, NULL) != RETURN_SUCCESS);\r
+    while (AttachHost (BreakCause, 0, NULL) != RETURN_SUCCESS);\r
    \r
   }\r
 }\r
@@ -1065,12 +1375,13 @@ CommandCommunication (
   DEBUG_PORT_HANDLE                 Handle;\r
   DEBUG_AGENT_EXCEPTION_BUFFER      AgentExceptionBuffer;\r
   UINT32                            IssuedViewPoint;\r
+  DEBUG_AGENT_MAILBOX               *Mailbox;\r
 \r
   ProcessorIndex  = 0;\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
@@ -1085,14 +1396,14 @@ CommandCommunication (
     //\r
     // Set AgentInProgress Flag.\r
     //\r
-    GetMailboxPointer()->DebugFlag.AgentInProgress = 1;\r
+    SetDebugFlag (DEBUG_AGENT_FLAG_AGENT_IN_PROGRESS, 1);\r
   }  \r
 \r
   Handle = GetDebugPortHandle();\r
 \r
   while (TRUE) {\r
 \r
-    if (MultiProcessorDebugSupport) {\r
+    if (MultiProcessorDebugSupport()) {\r
       //\r
       // Check if the current processor is HOST view point\r
       //\r
@@ -1114,35 +1425,44 @@ CommandCommunication (
       }\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 || (DebugHeader->Command & DEBUG_COMMAND_RESPONSE) != 0) {\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
-    if (Status != RETURN_SUCCESS) {\r
-      ReleaseDebugPortControl ();\r
+    Mailbox = GetMailboxPointer ();\r
+    if (DebugHeader->SequenceNo == Mailbox->HostSequenceNo) {\r
+      DebugAgentMsgPrint (DEBUG_AGENT_WARNING, "TARGET: Receive one old command[%x] agaist 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 comamnd[%x] agaist command[%x]\n", DebugHeader->SequenceNo, Mailbox->HostSequenceNo);\r
+      ReleaseMpSpinLock (&mDebugMpContext.DebugPortSpinLock);\r
       continue;\r
     }\r
-\r
-    Data8 = 1;\r
-\r
-    DebugHeader =(DEBUG_PACKET_HEADER *) InputPacketBuffer;\r
-\r
-    GetMailboxPointer()->ExceptionBufferPointer = (UINT64)(UINTN) &AgentExceptionBuffer.JumpBuffer;\r
+    \r
     //\r
     // Save CPU content before executing HOST commond\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
-      ReleaseDebugPortControl ();\r
+      ReleaseMpSpinLock (&mDebugMpContext.DebugPortSpinLock);\r
       continue;\r
     }\r
 \r
@@ -1150,9 +1470,18 @@ CommandCommunication (
     \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
@@ -1160,6 +1489,9 @@ CommandCommunication (
       // PCD can be used if 2 seconds isn't long enough for some platforms.\r
       //\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
@@ -1176,13 +1508,13 @@ CommandCommunication (
       //\r
       // Clear Stepping Flag\r
       //\r
-      GetMailboxPointer()->DebugFlag.SteppingFlag = 0;\r
+      SetDebugFlag (DEBUG_AGENT_FLAG_STEPPING, 0);\r
       \r
       if (!HaltDeferred) {\r
         //\r
         // If no HALT command received when being in-active mode\r
         //\r
-        if (MultiProcessorDebugSupport) {\r
+        if (MultiProcessorDebugSupport()) {\r
           Data32 = FindNextPendingBreakCpu ();\r
           if (Data32 != -1) {\r
             //\r
@@ -1200,11 +1532,11 @@ CommandCommunication (
             //\r
             // Send break packet to HOST to let HOST break again\r
             //\r
-            SendBreakPacketToHost (0, &BreakReceived);\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
-            ReleaseDebugPortControl (); \r
+            ReleaseMpSpinLock (&mDebugMpContext.DebugPortSpinLock);\r
             break;\r
           }\r
 \r
@@ -1240,8 +1572,12 @@ 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
@@ -1257,7 +1593,7 @@ CommandCommunication (
 \r
     case DEBUG_COMMAND_BREAK_CAUSE:\r
 \r
-      if (MultiProcessorDebugSupport && ProcessorIndex != mDebugMpContext.BreakAtCpuIndex) {\r
+      if (MultiProcessorDebugSupport() && ProcessorIndex != mDebugMpContext.BreakAtCpuIndex) {\r
         Status = SendBreakCausePacket (DEBUG_TIMER_VECTOR, CpuContext);\r
 \r
       } else {\r
@@ -1291,8 +1627,8 @@ CommandCommunication (
       //\r
       // Set Stepping Flag\r
       //\r
-      GetMailboxPointer()->DebugFlag.SteppingFlag = 1;\r
-      ReleaseDebugPortControl ();\r
+      SetDebugFlag (DEBUG_AGENT_FLAG_STEPPING, 1);\r
+      ReleaseMpSpinLock (&mDebugMpContext.DebugPortSpinLock);\r
       //\r
       // Executing stepping command directly without sending ACK packet,\r
       // ACK packet will be sent after stepping done.\r
@@ -1424,7 +1760,7 @@ CommandCommunication (
 \r
     case DEBUG_COMMAND_SET_VIEWPOINT:\r
       SetViewPoint = (DEBUG_DATA_SET_VIEWPOINT *) (DebugHeader + 1);\r
-      if (MultiProcessorDebugSupport) {\r
+      if (MultiProcessorDebugSupport()) {\r
         if (IsCpuStopped (SetViewPoint->ViewPoint)) {\r
           SetDebugViewPoint (SetViewPoint->ViewPoint);\r
           SendAckPacket (DEBUG_COMMAND_OK);\r
@@ -1449,7 +1785,7 @@ CommandCommunication (
       break;\r
 \r
     case DEBUG_COMMAND_MEMORY_READY:\r
-      Data8 = (UINT8) GetMailboxPointer ()->DebugFlag.MemoryReady;\r
+      Data8 = (UINT8) GetDebugFlag (DEBUG_AGENT_FLAG_MEMORY_READY);\r
       SendDataResponsePacket (&Data8, (UINT16) sizeof (UINT8));\r
       break;\r
 \r
@@ -1517,7 +1853,7 @@ CommandCommunication (
       SendAckPacket (DEBUG_COMMAND_ABORT);\r
     }\r
 \r
-    ReleaseDebugPortControl ();\r
+    ReleaseMpSpinLock (&mDebugMpContext.DebugPortSpinLock);\r
     CpuPause ();\r
   }\r
 }\r
@@ -1552,7 +1888,17 @@ InterruptProcess (
   IssuedViewPoint = 0;\r
   BreakReceived   = FALSE;\r
 \r
-  if (MultiProcessorDebugSupport) {\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
     ProcessorIndex = GetProcessorIndex ();\r
     //\r
     // If this processor has alreay halted before, need to check it later\r
@@ -1562,22 +1908,22 @@ InterruptProcess (
     }\r
   }\r
 \r
-  if (IssuedViewPoint == ProcessorIndex) {\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
     //\r
-    if (GetMailboxPointer()->DebugFlag.AgentInProgress == 1) {\r
+    if (GetDebugFlag (DEBUG_AGENT_FLAG_AGENT_IN_PROGRESS) == 1) {\r
       DebugAgentMsgPrint (DEBUG_AGENT_ERROR, "Debug agent meet one Exception, ExceptionNum is %d.\n", Vector);\r
       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)(GetMailboxPointer()->ExceptionBufferPointer), 1);\r
+      LongJump ((BASE_LIBRARY_JUMP_BUFFER *)(UINTN)(ExceptionBuffer), 1);\r
     }\r
   }\r
 \r
-  if (MultiProcessorDebugSupport) {\r
+  if (MultiProcessorDebugSupport()) {\r
     //\r
     // If RUN commmand is executing, wait for it done.  \r
     //\r
@@ -1586,16 +1932,14 @@ InterruptProcess (
     }\r
   }\r
 \r
-  Handle = GetDebugPortHandle();\r
-\r
+  Handle     = GetDebugPortHandle();\r
+  BreakCause = GetBreakCause (Vector, CpuContext);\r
   switch (Vector) {\r
   case DEBUG_INT1_VECTOR:\r
   case DEBUG_INT3_VECTOR:\r
-    BreakCause = GetBreakCause (Vector, CpuContext);\r
-\r
     switch (BreakCause) {\r
     case DEBUG_DATA_BREAK_CAUSE_SYSTEM_RESET:\r
-      if (AttachHost (INIT_BREAK_ACK_TIMEOUT, &BreakReceived) != RETURN_SUCCESS) {\r
+      if (AttachHost (BreakCause, READ_PACKET_TIMEOUT, &BreakReceived) != RETURN_SUCCESS) {\r
         //\r
         // Try to connect HOST, return if fails\r
         //\r
@@ -1608,7 +1952,7 @@ InterruptProcess (
       //\r
       // Stepping is finished, send Ack package.\r
       //\r
-      if (MultiProcessorDebugSupport) {\r
+      if (MultiProcessorDebugSupport()) {\r
         mDebugMpContext.BreakAtCpuIndex = ProcessorIndex;\r
       }\r
       SendAckPacket (DEBUG_COMMAND_OK);\r
@@ -1619,7 +1963,7 @@ InterruptProcess (
       //\r
       // Memory is ready\r
       //\r
-      SendCommandAndWaitForAckOK (DEBUG_COMMAND_MEMORY_READY, 0, &BreakReceived, NULL);\r
+      SendCommandAndWaitForAckOK (DEBUG_COMMAND_MEMORY_READY, READ_PACKET_TIMEOUT, &BreakReceived, NULL);\r
       CommandCommunication (Vector, CpuContext, BreakReceived);\r
       break;\r
 \r
@@ -1647,14 +1991,14 @@ InterruptProcess (
       //\r
       // Send Break packet to HOST\r
       //\r
-      AcquireDebugPortControl ();\r
+      AcquireMpSpinLock (&mDebugMpContext.DebugPortSpinLock);\r
       //\r
       // Only the first breaking processor could send BREAK_POINT to HOST\r
       // \r
       if (IsFirstBreakProcessor (ProcessorIndex)) {\r
-        SendBreakPacketToHost (ProcessorIndex, &BreakReceived);\r
+        SendBreakPacketToHost (BreakCause, ProcessorIndex, &BreakReceived);\r
       }\r
-      ReleaseDebugPortControl ();\r
+      ReleaseMpSpinLock (&mDebugMpContext.DebugPortSpinLock);\r
       \r
       if (Vector == DEBUG_INT3_VECTOR) {\r
         //\r
@@ -1681,9 +2025,9 @@ InterruptProcess (
 \r
   case DEBUG_TIMER_VECTOR:\r
 \r
-    AcquireDebugPortControl ();\r
+    AcquireMpSpinLock (&mDebugMpContext.DebugPortSpinLock);\r
 \r
-    if (MultiProcessorDebugSupport) {\r
+    if (MultiProcessorDebugSupport()) {\r
       if (IsBsp (ProcessorIndex)) {\r
         //\r
         // If current processor is BSP, check Apic timer's init count if changed,\r
@@ -1697,7 +2041,7 @@ InterruptProcess (
       }\r
 \r
       if (!IsBsp (ProcessorIndex) || mDebugMpContext.IpiSentByAp) {\r
-        ReleaseDebugPortControl ();\r
+        ReleaseMpSpinLock (&mDebugMpContext.DebugPortSpinLock);\r
         //\r
         // If current processor is not BSP or this is one IPI sent by AP\r
         //\r
@@ -1725,8 +2069,10 @@ InterruptProcess (
       if (DebugReadBreakSymbol (Handle, &InputCharacter) == EFI_NOT_FOUND) {\r
         break;\r
       }\r
+\r
       if ((!IsHostAttached () && (InputCharacter == DEBUG_STARTING_SYMBOL_ATTACH)) ||\r
-          (IsHostAttached () && (InputCharacter == DEBUG_STARTING_SYMBOL_BREAK))\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
@@ -1734,25 +2080,32 @@ InterruptProcess (
         //\r
         SendAckPacket (DEBUG_COMMAND_OK);\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 (INIT_BREAK_ACK_TIMEOUT, &BreakReceived) != RETURN_SUCCESS) {\r
+          if (AttachHost (BreakCause, READ_PACKET_TIMEOUT, &BreakReceived) != RETURN_SUCCESS) {\r
             break;\r
           }\r
         }\r
 \r
-        if (MultiProcessorDebugSupport) {\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
@@ -1762,19 +2115,17 @@ InterruptProcess (
     //\r
     SendApicEoi ();\r
 \r
-    ReleaseDebugPortControl ();\r
+    ReleaseMpSpinLock (&mDebugMpContext.DebugPortSpinLock);\r
 \r
     break;\r
 \r
   default:\r
-\r
     if (Vector <= DEBUG_EXCEPT_SIMD) {\r
-      BreakCause = GetBreakCause (Vector, CpuContext);\r
       if (BreakCause == 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
         SendAckPacket (DEBUG_COMMAND_OK);\r
@@ -1782,14 +2133,14 @@ InterruptProcess (
         //\r
         // Exception occurs, send Break packet to HOST\r
         //\r
-        AcquireDebugPortControl ();\r
+        AcquireMpSpinLock (&mDebugMpContext.DebugPortSpinLock);\r
         //\r
         // Only the first breaking processor could send BREAK_POINT to HOST\r
         // \r
         if (IsFirstBreakProcessor (ProcessorIndex)) {\r
-          SendBreakPacketToHost (ProcessorIndex, &BreakReceived);\r
+          SendBreakPacketToHost (BreakCause, ProcessorIndex, &BreakReceived);\r
         }\r
-        ReleaseDebugPortControl ();\r
+        ReleaseMpSpinLock (&mDebugMpContext.DebugPortSpinLock);\r
       }\r
       \r
       CommandCommunication (Vector, CpuContext, BreakReceived);\r
@@ -1797,7 +2148,7 @@ InterruptProcess (
     break;\r
   }\r
 \r
-  if (MultiProcessorDebugSupport) {\r
+  if (MultiProcessorDebugSupport()) {\r
     //\r
     // Clear flag and wait for all processors run here\r
     //\r
@@ -1814,11 +2165,11 @@ InterruptProcess (
     }\r
   }\r
 \r
-  if (IssuedViewPoint == ProcessorIndex) {\r
+  if (IssuedViewPoint == ProcessorIndex && GetDebugFlag (DEBUG_AGENT_FLAG_STEPPING) != 1) {\r
     //\r
-    // Clean up AgentInProgress flag\r
+    // If the command is not stepping, clean up AgentInProgress flag\r
     //\r
-    GetMailboxPointer()->DebugFlag.AgentInProgress = 0;\r
+    SetDebugFlag (DEBUG_AGENT_FLAG_AGENT_IN_PROGRESS, 0);\r
   }\r
 \r
   return;\r
index 61448448d46e83c6872e7853cb8cc15b1b12aaca..5eb50d038c0433e5ff049f973d252f42d00c1411 100644 (file)
@@ -1,7 +1,7 @@
 /** @file\r
   Command header of for Debug Agent library instance.\r
 \r
-  Copyright (c) 2010 - 2012, Intel Corporation. All rights reserved.<BR>\r
+  Copyright (c) 2010 - 2013, 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
@@ -32,6 +32,8 @@
 #include <Library/DebugLib.h>\r
 #include <Library/TimerLib.h>\r
 #include <Library/PrintLib.h>\r
+#include <Library/PeCoffGetEntryPointLib.h>\r
+#include <Library/PeCoffExtraActionLib.h>\r
 \r
 #include <TransferProtocol.h>\r
 #include <ImageDebugSupport.h>\r
 #include "DebugTimer.h"\r
 #include "ArchDebugSupport.h"\r
 \r
+//\r
+// These macros may be already defined in DebugAgentLib.h\r
+//\r
+#define DEBUG_AGENT_INIT_PEI                     9\r
+#define DEBUG_AGENT_INIT_DXE_LOAD               10\r
+#define DEBUG_AGENT_INIT_DXE_UNLOAD             11\r
+#define DEBUG_AGENT_INIT_THUNK_PEI_IA32TOX64    12\r
+\r
 #define DEBUG_INT1_VECTOR               1\r
 #define DEBUG_INT3_VECTOR               3\r
 #define DEBUG_TIMER_VECTOR              32\r
 #define DEBUG_MAILBOX_VECTOR            33\r
 \r
+//\r
+//  Timeout value for reading packet (unit is microsecond)\r
+//\r
+#define READ_PACKET_TIMEOUT     (500 * 1000)\r
+\r
 #define SOFT_INTERRUPT_SIGNATURE    SIGNATURE_32('S','O','F','T')\r
 #define SYSTEM_RESET_SIGNATURE      SIGNATURE_32('S','Y','S','R')\r
 #define MEMORY_READY_SIGNATURE      SIGNATURE_32('M','E','M','R')\r
@@ -53,6 +68,8 @@ extern UINTN  Exception0Handle;
 extern UINTN  TimerInterruptHandle;\r
 extern UINT16 ExceptionStubHeaderSize;\r
 \r
+extern BOOLEAN mSkipBreakpoint;\r
+\r
 //\r
 // CPU exception information issued by debug agent\r
 //\r
@@ -67,23 +84,44 @@ typedef struct {
   DEBUG_DATA_RESPONSE_GET_EXCEPTION   ExceptionContent;\r
 } DEBUG_AGENT_EXCEPTION_BUFFER;\r
 \r
-#pragma pack(1)\r
-typedef struct {\r
-  //\r
-  // Lower 32 bits to store the status of DebugAgent\r
-  //\r
-  UINT32  HostAttached    : 1;   // 1: HOST is attached\r
-  UINT32  AgentInProgress : 1;   // 1: Debug Agent is communicating with HOST\r
-  UINT32  MemoryReady     : 1;   // 1: Memory is ready\r
-  UINT32  SteppingFlag    : 1;   // 1: Agent is running stepping command\r
-  UINT32  Reserved1       : 28;\r
+#define DEBUG_AGENT_FLAG_HOST_ATTACHED         BIT0\r
+#define DEBUG_AGENT_FLAG_AGENT_IN_PROGRESS     BIT1\r
+#define DEBUG_AGENT_FLAG_MEMORY_READY          BIT2\r
+#define DEBUG_AGENT_FLAG_STEPPING              BIT3\r
+#define DEBUG_AGENT_FLAG_CHECK_MAILBOX_IN_HOB  BIT4\r
+#define DEBUG_AGENT_FLAG_BREAK_ON_NEXT_SMI     BIT32\r
+#define DEBUG_AGENT_FLAG_PRINT_ERROR_LEVEL     (BIT33|BIT34|BIT35|BIT36)\r
+#define DEBUG_AGENT_FLAG_BREAK_BOOT_SCRIPT     BIT37\r
+\r
+#define DEBUG_MAILBOX_DEBUG_FLAG_INDEX                1\r
+#define DEBUG_MAILBOX_DEBUG_PORT_HANDLE_INDEX         2\r
+#define DEBUG_MAILBOX_EXCEPTION_BUFFER_POINTER_INDEX  3\r
+#define DEBUG_MAILBOX_LAST_ACK                        4\r
+#define DEBUG_MAILBOX_SEQUENCE_NO_INDEX               5\r
+#define DEBUG_MAILBOX_HOST_SEQUENCE_NO_INDEX          6\r
 \r
-  //\r
-  // Higher 32bits to control the behavior of DebugAgent\r
-  //\r
-  UINT32  BreakOnNextSmi  : 1;   // 1: Break on next SMI\r
-  UINT32  PrintErrorLevel : 8;   // Bitmask of print error level for debug message\r
-  UINT32  Reserved2       : 23;\r
+#pragma pack(1)\r
+typedef union {\r
+  struct {\r
+    //\r
+    // Lower 32 bits to store the status of DebugAgent\r
+    //\r
+    UINT32  HostAttached      : 1;   // 1: HOST is attached\r
+    UINT32  AgentInProgress   : 1;   // 1: Debug Agent is communicating with HOST\r
+    UINT32  MemoryReady       : 1;   // 1: Memory is ready\r
+    UINT32  SteppingFlag      : 1;   // 1: Agent is running stepping command\r
+    UINT32  CheckMailboxInHob : 1;   // 1: Need to check mailbox saved in HOB\r
+    UINT32  SendingPacket     : 1;   // 1: TARGET is sending debug packet to HOST\r
+    UINT32  Reserved1         : 26;\r
+    //\r
+    // Higher 32bits to control the behavior of DebugAgent\r
+    //\r
+    UINT32  BreakOnNextSmi    : 1;   // 1: Break on next SMI\r
+    UINT32  PrintErrorLevel   : 4;   // Bitmask of print error level for debug message\r
+    UINT32  BreakOnBootScript : 1;   // 1: Break before executing boot script \r
+    UINT32  Reserved2         : 26;\r
+  } Bits;\r
+  UINT64  Uint64;\r
 } DEBUG_AGENT_FLAG;\r
 \r
 typedef struct {\r
@@ -93,9 +131,29 @@ typedef struct {
   // Pointer to DEBUG_AGENT_EXCEPTION_BUFFER\r
   //\r
   UINT64                     ExceptionBufferPointer;\r
+  UINT8                      LastAck;      // The last ack packet type\r
+  UINT8                      SequenceNo;\r
+  UINT8                      HostSequenceNo;\r
+  UINT8                      CheckSum;     // Mailbox checksum\r
+  UINT8                      ToBeCheckSum; // To be Mailbox checksum at the next\r
 } DEBUG_AGENT_MAILBOX;\r
 #pragma pack()\r
 \r
+///\r
+/// Byte packed structure for an IA-32 Interrupt Gate Descriptor.\r
+///\r
+typedef union {\r
+  struct {\r
+    UINT32  OffsetLow:16;   ///< Offset bits 15..0.\r
+    UINT32  Selector:16;    ///< Selector.\r
+    UINT32  Reserved_0:8;   ///< Reserved.\r
+    UINT32  GateType:8;     ///< Gate Type.  See #defines above.\r
+    UINT32  OffsetHigh:16;  ///< Offset bits 31..16.\r
+  } Bits;\r
+  UINT64  Uint64;\r
+} IA32_IDT_ENTRY;\r
+\r
+\r
 typedef union {\r
   struct {\r
     UINT32  LimitLow    : 16;\r
@@ -115,22 +173,6 @@ typedef union {
   UINT64  Uint64;\r
 } IA32_GDT;\r
 \r
-/**\r
-  Caller provided function to be invoked at the end of DebugPortInitialize().\r
-\r
-  Refer to the descrption for DebugPortInitialize() for more details.\r
-\r
-  @param[in] Context           The first input argument of DebugPortInitialize().\r
-  @param[in] DebugPortHandle   Debug port handle created by Debug Communication Libary.\r
-\r
-**/\r
-VOID\r
-EFIAPI\r
-InitializeDebugAgentPhase2 (\r
-  IN VOID                  *Context,\r
-  IN DEBUG_PORT_HANDLE     DebugPortHandle\r
-  );\r
-\r
 /**\r
   Initialize IDT entries to support source level debug.\r
 \r
@@ -242,5 +284,184 @@ DebugAgentMsgPrint (
   IN CHAR8         *Format,\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
+/**\r
+  Check if debug agent support multi-processor.\r
+\r
+  @retval TRUE    Multi-processor is supported.\r
+  @retval FALSE   Multi-processor is not supported.\r
+\r
+**/\r
+BOOLEAN\r
+MultiProcessorDebugSupport (\r
+  VOID\r
+  );\r
+\r
+/**\r
+  Find and report module image info to HOST.\r
+  \r
+  @param[in] AlignSize      Image aligned size.\r
+  \r
+**/\r
+VOID \r
+FindAndReportModuleImageInfo (\r
+  IN UINTN          AlignSize                   \r
+  );\r
+\r
+/**\r
+  Read IDT entry to check if IDT entries are setup by Debug Agent.\r
+\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
+IsDebugAgentInitialzed (\r
+  VOID\r
+  );\r
+\r
+/**\r
+  Caculate 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
+/**\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
+/**\r
+  Set debug flag in mailbox.\r
+\r
+  @param[in]  FlagMask      Debug flag mask value.\r
+  @param[in]  FlagValue     Debug flag value.\r
+\r
+**/\r
+VOID \r
+SetDebugFlag (\r
+  IN UINT64                 FlagMask,\r
+  IN UINT32                 FlagValue                          \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
+/**\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 mail box.\r
+  \r
+**/\r
+VOID\r
+UpdateMailboxContent ( \r
+  IN DEBUG_AGENT_MAILBOX    *Mailbox,\r
+  IN UINTN                  Index,\r
+  IN UINT64                 Value\r
+  );\r
+\r
+/**\r
+  Retrieve exception handler from IDT table by ExceptionNum.\r
+\r
+  @param[in]  ExceptionNum    Exception number\r
\r
+  @return Exception handler\r
+\r
+**/\r
+VOID *\r
+GetExceptionHandlerInIdtEntry (\r
+  IN UINTN             ExceptionNum\r
+  );\r
+\r
+/**\r
+  Set exception handler in IDT table by ExceptionNum.\r
+\r
+  @param[in]  ExceptionNum      Exception number\r
+  @param[in]  ExceptionHandler  Exception Handler to be set \r
+\r
+**/\r
+VOID\r
+SetExceptionHandlerInIdtEntry (\r
+  IN UINTN             ExceptionNum,\r
+  IN VOID              *ExceptionHandler\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
+/**\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
+\r
+**/\r
+EFI_STATUS\r
+ReadRemainingBreakPacket (\r
+  IN     DEBUG_PORT_HANDLE      Handle,\r
+  IN OUT DEBUG_PACKET_HEADER    *DebugHeader\r
+  );\r
+\r
 #endif\r
 \r
index d7df6ad20ddd4271b7ad0120ee7f2762c6fd1392..6c729986cd47672f5e0ecffa2533a21e60016e7a 100644 (file)
@@ -1,7 +1,7 @@
 /** @file\r
   Multi-Processor support functions implementation.\r
 \r
-  Copyright (c) 2010 - 2012, Intel Corporation. All rights reserved.<BR>\r
+  Copyright (c) 2010 - 2013, 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
 \r
 #include "DebugAgent.h"\r
 \r
-DEBUG_MP_CONTEXT volatile  mDebugMpContext = {0,0,{0},{0},0,0,0,0,FALSE,FALSE};\r
+DEBUG_MP_CONTEXT volatile  mDebugMpContext = {0,0,0,{0},{0},0,0,0,0,FALSE,FALSE};\r
 \r
 DEBUG_CPU_DATA volatile  mDebugCpuData = {0};\r
 \r
 /**\r
-  Acquire access control on debug port.\r
+  Acquire a spin lock when Multi-processor supported.\r
 \r
   It will block in the function if cannot get the access control.\r
+  If Multi-processor is not supported, return directly.\r
+\r
+  @param[in, out] MpSpinLock      A pointer to the spin lock.\r
 \r
 **/\r
 VOID\r
-AcquireDebugPortControl (\r
-  VOID\r
+AcquireMpSpinLock (\r
+  IN OUT SPIN_LOCK           *MpSpinLock\r
   )\r
 {\r
-  if (!MultiProcessorDebugSupport) {\r
+  if (!MultiProcessorDebugSupport()) {\r
     return;\r
   }\r
 \r
   while (TRUE) {\r
-    if (AcquireSpinLockOrFail (&mDebugMpContext.DebugPortSpinLock)) {\r
+    if (AcquireSpinLockOrFail (MpSpinLock)) {\r
       break;\r
     }\r
     CpuPause ();\r
@@ -43,51 +46,21 @@ AcquireDebugPortControl (
 }\r
 \r
 /**\r
-  Release access control on debug port.\r
-\r
-**/\r
-VOID\r
-ReleaseDebugPortControl (\r
-  VOID\r
-  )\r
-{\r
-  if (!MultiProcessorDebugSupport) {\r
-    return;\r
-  }\r
-\r
-  ReleaseSpinLock (&mDebugMpContext.DebugPortSpinLock);\r
-}\r
-\r
-/**\r
-  Acquire access control on MP context.\r
+  Release a spin lock when Multi-processor supported.\r
 \r
-  It will block in the function if cannot get the access control.\r
+  @param[in, out] MpSpinLock      A pointer to the spin lock.\r
 \r
 **/\r
 VOID\r
-AcquireMpContextControl (\r
-  VOID\r
+ReleaseMpSpinLock (\r
+  IN OUT SPIN_LOCK           *MpSpinLock\r
   )\r
 {\r
-  while (TRUE) {\r
-    if (AcquireSpinLockOrFail (&mDebugMpContext.MpContextSpinLock)) {\r
-      break;\r
-    }\r
-    CpuPause ();\r
-    continue;\r
+  if (!MultiProcessorDebugSupport()) {\r
+    return;\r
   }\r
-}\r
 \r
-/**\r
-  Release access control on MP context.\r
-\r
-**/\r
-VOID\r
-ReleaseMpContextControl (\r
-  VOID\r
-  )\r
-{\r
-  ReleaseSpinLock (&mDebugMpContext.MpContextSpinLock);\r
+  ReleaseSpinLock (MpSpinLock);\r
 }\r
 \r
 /**\r
@@ -136,7 +109,7 @@ GetProcessorIndex (
 \r
   LocalApicID = (UINT16) GetApicId ();\r
 \r
-  AcquireMpContextControl ();\r
+  AcquireMpSpinLock (&mDebugMpContext.MpContextSpinLock);\r
 \r
   for (Index = 0; Index < mDebugCpuData.CpuCount; Index ++) {\r
     if (mDebugCpuData.ApicID[Index] == LocalApicID) {\r
@@ -149,7 +122,7 @@ GetProcessorIndex (
     mDebugCpuData.CpuCount ++ ;\r
   }\r
 \r
-  ReleaseMpContextControl ();\r
+  ReleaseMpSpinLock (&mDebugMpContext.MpContextSpinLock);\r
 \r
   return Index;\r
 }\r
@@ -170,9 +143,9 @@ IsBsp (
 {\r
   if (AsmMsrBitFieldRead64 (MSR_IA32_APIC_BASE_ADDRESS, 8, 8) == 1) {\r
     if (mDebugMpContext.BspIndex != ProcessorIndex) {\r
-      AcquireMpContextControl ();\r
+      AcquireMpSpinLock (&mDebugMpContext.MpContextSpinLock);\r
       mDebugMpContext.BspIndex = ProcessorIndex;\r
-      ReleaseMpContextControl ();\r
+      ReleaseMpSpinLock (&mDebugMpContext.MpContextSpinLock);\r
     }\r
     return TRUE;\r
   } else {\r
@@ -197,7 +170,7 @@ SetCpuStopFlagByIndex (
   UINT8                 Value;\r
   UINTN                 Index;\r
 \r
-  AcquireMpContextControl ();\r
+  AcquireMpSpinLock (&mDebugMpContext.MpContextSpinLock);\r
 \r
   Value = mDebugMpContext.CpuStopStatusMask[ProcessorIndex / 8];\r
   Index = ProcessorIndex % 8;\r
@@ -208,7 +181,7 @@ SetCpuStopFlagByIndex (
   }\r
   mDebugMpContext.CpuStopStatusMask[ProcessorIndex / 8] = Value;\r
 \r
-  ReleaseMpContextControl ();\r
+  ReleaseMpSpinLock (&mDebugMpContext.MpContextSpinLock);\r
 }\r
 \r
 /**\r
@@ -228,7 +201,7 @@ SetCpuBreakFlagByIndex (
   UINT8                 Value;\r
   UINTN                 Index;\r
 \r
-  AcquireMpContextControl ();\r
+  AcquireMpSpinLock (&mDebugMpContext.MpContextSpinLock);\r
 \r
   Value = mDebugMpContext.CpuBreakMask[ProcessorIndex / 8];\r
   Index = ProcessorIndex % 8;\r
@@ -239,7 +212,7 @@ SetCpuBreakFlagByIndex (
   }\r
   mDebugMpContext.CpuBreakMask[ProcessorIndex / 8] = Value;\r
 \r
-  ReleaseMpContextControl ();\r
+  ReleaseMpSpinLock (&mDebugMpContext.MpContextSpinLock);\r
 }\r
 \r
 /**\r
@@ -279,11 +252,9 @@ SetCpuRunningFlag (
   IN BOOLEAN            RunningFlag\r
   )\r
 {\r
-  AcquireMpContextControl ();\r
-\r
+  AcquireMpSpinLock (&mDebugMpContext.MpContextSpinLock);\r
   mDebugMpContext.RunCommandSet = RunningFlag;\r
-\r
-  ReleaseMpContextControl ();\r
+  ReleaseMpSpinLock (&mDebugMpContext.MpContextSpinLock);\r
 }\r
 \r
 /**\r
@@ -297,11 +268,9 @@ SetDebugViewPoint (
   IN UINT32             ProcessorIndex\r
   )\r
 {\r
-  AcquireMpContextControl ();\r
-\r
+  AcquireMpSpinLock (&mDebugMpContext.MpContextSpinLock);\r
   mDebugMpContext.ViewPointIndex = ProcessorIndex;\r
-\r
-  ReleaseMpContextControl ();\r
+  ReleaseMpSpinLock (&mDebugMpContext.MpContextSpinLock);\r
 }\r
 \r
 /**\r
@@ -316,11 +285,9 @@ SetIpiSentByApFlag (
   IN BOOLEAN            IpiSentByApFlag\r
   )\r
 {\r
-  AcquireMpContextControl ();\r
-\r
+  AcquireMpSpinLock (&mDebugMpContext.MpContextSpinLock);\r
   mDebugMpContext.IpiSentByAp = IpiSentByApFlag;\r
-\r
-  ReleaseMpContextControl ();\r
+  ReleaseMpSpinLock (&mDebugMpContext.MpContextSpinLock);\r
 }\r
 \r
 /**\r
@@ -384,7 +351,7 @@ IsFirstBreakProcessor (
   IN UINT32              ProcessorIndex\r
   )\r
 {\r
-  if (MultiProcessorDebugSupport) {\r
+  if (MultiProcessorDebugSupport()) {\r
     if (mDebugMpContext.BreakAtCpuIndex != (UINT32) -1) {\r
       //\r
       // The current processor is not the first breaking one.\r
index 183887cc9f212144d4cc2f174c29ccecd9ef0182..5bb50960ca72b57763e68d42d553de59d3b1a829 100644 (file)
@@ -1,7 +1,7 @@
 /** @file\r
   Header file for Multi-Processor support.\r
 \r
-  Copyright (c) 2010 - 2012, Intel Corporation. All rights reserved.<BR>\r
+  Copyright (c) 2010 - 2013, 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
@@ -25,6 +25,7 @@ typedef struct {
 typedef struct {\r
   SPIN_LOCK                 MpContextSpinLock;   ///< Lock for writting MP context\r
   SPIN_LOCK                 DebugPortSpinLock;   ///< Lock for access debug port\r
+  SPIN_LOCK                 MailboxSpinLock;     ///< Lock for accessing mail box\r
   UINT8                     CpuBreakMask[DEBUG_CPU_MAX_COUNT/8];        ///< Bitmask of all breaking CPUs\r
   UINT8                     CpuStopStatusMask[DEBUG_CPU_MAX_COUNT/8];   ///< Bitmask of CPU stop status\r
   UINT32                    ViewPointIndex;      ///< Current view point to be debugged\r
@@ -35,7 +36,6 @@ typedef struct {
   BOOLEAN                   RunCommandSet;       ///< TRUE: RUN commmand is executing. FALSE : RUN command has been executed.\r
 } DEBUG_MP_CONTEXT;\r
 \r
-extern CONST BOOLEAN               MultiProcessorDebugSupport;\r
 extern DEBUG_MP_CONTEXT volatile   mDebugMpContext;\r
 extern DEBUG_CPU_DATA   volatile   mDebugCpuData;\r
 \r
@@ -62,43 +62,28 @@ GetProcessorIndex (
   );\r
 \r
 /**\r
-  Acquire access control on MP context.\r
+  Acquire a spin lock when Multi-processor supported.\r
 \r
   It will block in the function if cannot get the access control.\r
+  If Multi-processor is not supported, return directly.\r
 \r
-**/\r
-VOID\r
-AcquireMpContextControl (\r
-  VOID\r
-  );\r
-\r
-/**\r
-  Release access control on MP context.\r
+  @param[in, out] MpSpinLock      A pointer to the spin lock.\r
 \r
 **/\r
 VOID\r
-ReleaseMpContextControl (\r
-  VOID\r
+AcquireMpSpinLock (\r
+  IN OUT SPIN_LOCK           *MpSpinLock\r
   );\r
 \r
 /**\r
-  Acquire access control on debug port.\r
-\r
-  It will block in the function if cannot get the access control.\r
-\r
-**/\r
-VOID\r
-AcquireDebugPortControl (\r
-  VOID\r
-  );\r
+  Release a spin lock when Multi-processor supported.\r
 \r
-/**\r
-  Release access control on debug port.\r
+  @param[in, out] MpSpinLock      A pointer to the spin lock.\r
 \r
 **/\r
 VOID\r
-ReleaseDebugPortControl (\r
-  VOID\r
+ReleaseMpSpinLock (\r
+  IN OUT SPIN_LOCK           *MpSpinLock\r
   );\r
 \r
 /**\r
index d473df867807b0cabaf363d355a321777ac1a036..01fc4841f52ea6d790e5e9121359dbf1590d21c1 100644 (file)
@@ -1,7 +1,7 @@
 /** @file\r
   Code for debug timer to support debug agent library implementation.\r
 \r
-  Copyright (c) 2010, Intel Corporation. All rights reserved.<BR>\r
+  Copyright (c) 2010 - 2013, Intel Corporation. All rights reserved.<BR>\r
   This program and the accompanying materials\r
   are licensed and made available under the terms and conditions of the BSD License\r
   which accompanies this distribution.  The full text of the license may be found at\r
@@ -41,7 +41,7 @@ InitializeDebugTimer (
 \r
   InitializeApicTimer (ApicTimerDivisor, InitialCount, TRUE, DEBUG_TIMER_VECTOR);\r
 \r
-  if (MultiProcessorDebugSupport) {\r
+  if (MultiProcessorDebugSupport()) {\r
     mDebugMpContext.DebugTimerInitCount = InitialCount;\r
   }\r
 }\r
@@ -65,19 +65,26 @@ SaveAndSetDebugTimerInterrupt (
   IN BOOLEAN                EnableStatus\r
   )\r
 {\r
-  BOOLEAN     OldInterruptState;\r
   BOOLEAN     OldDebugTimerInterruptState;\r
 \r
-  OldInterruptState = SaveAndDisableInterrupts ();\r
   OldDebugTimerInterruptState = GetApicTimerInterruptState ();\r
   \r
-  if (EnableStatus) {\r
-    EnableApicTimerInterrupt ();\r
-  } else {\r
-    DisableApicTimerInterrupt ();\r
+  if (OldDebugTimerInterruptState != EnableStatus) {\r
+    if (EnableStatus) {\r
+      EnableApicTimerInterrupt ();\r
+    } else {\r
+      DisableApicTimerInterrupt ();\r
+    }\r
+    //\r
+    // Validate the Debug Timer interrupt state\r
+    // This will make additional delay after Local Apic Timer interrupt state is changed.\r
+    // Thus, CPU could handle the potential pending interrupt of Local Apic timer.\r
+    //\r
+    while (GetApicTimerInterruptState () != EnableStatus) {\r
+      CpuPause ();\r
+    }\r
   }\r
-\r
-  SetInterruptState (OldInterruptState);\r
+  \r
   return OldDebugTimerInterruptState;\r
 }\r
 \r
index 52ed647a270f2608fda6713ab838e7155a64ea05..9bd8fca6b6e361b53e2d1d0e0e8967daf8588721 100644 (file)
@@ -1,7 +1,7 @@
 /** @file\r
   Supporting functions for IA32 architecture.\r
 \r
-  Copyright (c) 2010 - 2012, Intel Corporation. All rights reserved.<BR>\r
+  Copyright (c) 2010 - 2013, 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
@@ -39,17 +39,17 @@ InitializeDebugIdt (
   IdtEntry = (IA32_IDT_GATE_DESCRIPTOR *) IdtDescriptor.Base;\r
 \r
   for (Index = 0; Index < 20; Index ++) {\r
-    if ((PcdGet32 (PcdExceptionsIgnoredByDebugger) & (1 << Index)) != 0) {\r
+    if (((PcdGet32 (PcdExceptionsIgnoredByDebugger) & ~(BIT1 | BIT3)) & (1 << Index)) != 0) {\r
       //\r
-      // If the exception is masked to be reserved, skip it\r
+      // If the exception is masked to be reserved except for INT1 and INT3, skip it\r
       //\r
       continue;\r
     }\r
     InterruptHandler = (UINTN)&Exception0Handle + Index * ExceptionStubHeaderSize;\r
     IdtEntry[Index].Bits.OffsetLow  = (UINT16)(UINTN)InterruptHandler;\r
     IdtEntry[Index].Bits.OffsetHigh = (UINT16)((UINTN)InterruptHandler >> 16);\r
-    IdtEntry[Index].Bits.Selector        = CodeSegment;\r
-    IdtEntry[Index].Bits.GateType        = IA32_IDT_GATE_TYPE_INTERRUPT_32;\r
+    IdtEntry[Index].Bits.Selector   = CodeSegment;\r
+    IdtEntry[Index].Bits.GateType   = IA32_IDT_GATE_TYPE_INTERRUPT_32;\r
   }\r
 \r
   InterruptHandler = (UINTN) &TimerInterruptHandle;\r
@@ -63,3 +63,49 @@ InitializeDebugIdt (
   //\r
   AsmWriteCr4 (AsmReadCr4 () | BIT3);\r
 }\r
+\r
+/**\r
+  Retrieve exception handler from IDT table by ExceptionNum.\r
+\r
+  @param[in]  ExceptionNum    Exception number\r
\r
+  @return Exception handler\r
+\r
+**/\r
+VOID *\r
+GetExceptionHandlerInIdtEntry (\r
+  IN UINTN             ExceptionNum\r
+  )\r
+{\r
+  IA32_IDT_GATE_DESCRIPTOR   *IdtEntry;\r
+  IA32_DESCRIPTOR            IdtDescriptor;\r
+\r
+  AsmReadIdtr (&IdtDescriptor);\r
+  IdtEntry = (IA32_IDT_GATE_DESCRIPTOR *) IdtDescriptor.Base;\r
+\r
+  return (VOID *) (((UINTN)IdtEntry[ExceptionNum].Bits.OffsetLow) |\r
+                  (((UINTN)IdtEntry[ExceptionNum].Bits.OffsetHigh) << 16));\r
+} \r
+\r
+/**\r
+  Set exception handler in IDT table by ExceptionNum.\r
+\r
+  @param[in]  ExceptionNum      Exception number\r
+  @param[in]  ExceptionHandler  Exception Handler to be set \r
+\r
+**/\r
+VOID\r
+SetExceptionHandlerInIdtEntry (\r
+  IN UINTN             ExceptionNum,\r
+  IN VOID              *ExceptionHandler\r
+  )\r
+{\r
+  IA32_IDT_GATE_DESCRIPTOR   *IdtEntry;\r
+  IA32_DESCRIPTOR            IdtDescriptor;\r
+\r
+  AsmReadIdtr (&IdtDescriptor);\r
+  IdtEntry = (IA32_IDT_GATE_DESCRIPTOR *) IdtDescriptor.Base;\r
+\r
+  IdtEntry[ExceptionNum].Bits.OffsetLow   = (UINT16)(UINTN)ExceptionHandler;\r
+  IdtEntry[ExceptionNum].Bits.OffsetHigh  = (UINT16)((UINTN)ExceptionHandler >> 16);\r
+}\r
index cfeeea0472c60675c825f7815c0d77dad4df2fe6..e05317aaf84cd238793223a4ee97126382d3b783 100644 (file)
@@ -1,6 +1,6 @@
 #------------------------------------------------------------------------------\r
 #\r
-# Copyright (c) 2010 - 2012, Intel Corporation. All rights reserved.<BR>\r
+# Copyright (c) 2010 - 2013, 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
@@ -33,6 +33,7 @@ ASM_PFX(ExceptionStubHeaderSize):  .word     ASM_PFX(Exception1Handle) - ASM_PFX
 \r
 .text\r
 \r
+.byte 0x41, 0x47, 0x54, 0x48  # AGENT_HANDLER_SIGNATURE     SIGNATURE_32('A','G','T','H')\r
 ASM_PFX(Exception0Handle):\r
    cli\r
    pushl %eax\r
@@ -259,7 +260,7 @@ NoExtrPush:
   pushl   %eax\r
 ## clear Dr7 while executing debugger itself\r
   xorl    %eax,%eax\r
-#  movl    %eax, %dr7\r
+  movl    %eax, %dr7\r
 \r
   movl    %dr6, %eax\r
   pushl   %eax\r
index 6f3b3bc3d4803a8730d0a9306c08e1b0d85e54e4..c80a33ba6c877bd27cbe975f8e471b5ad32695c3 100644 (file)
@@ -1,6 +1,6 @@
 ;------------------------------------------------------------------------------\r
 ;\r
-; Copyright (c) 2010 - 2012, Intel Corporation. All rights reserved.<BR>\r
+; Copyright (c) 2010 - 2013, 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
@@ -39,6 +39,7 @@ CommonEntryAddr           DD    CommonEntry
 \r
 .code\r
 \r
+db   41h, 47h, 54h, 48h  ; AGENT_HANDLER_SIGNATURE     SIGNATURE_32('A','G','T','H')\r
 Exception0Handle:\r
     cli\r
     push    eax\r
@@ -259,7 +260,7 @@ NoExtrPush:
 \r
     ;; clear Dr7 while executing debugger itself\r
     xor     eax, eax\r
;; mov     dr7, eax\r
   mov     dr7, eax\r
 \r
     ;; Dr6\r
     mov     eax, dr6\r
index 9803f0f76fbb8d16326d39309b30c0447bad7e32..60d3eb8bb3de95e3d3978dc132f8ffd828a97501 100644 (file)
@@ -1,7 +1,7 @@
 /** @file\r
   Supporting functions for X64 architecture.\r
 \r
-  Copyright (c) 2010 - 2012, Intel Corporation. All rights reserved.<BR>\r
+  Copyright (c) 2010 - 2013, 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
@@ -39,9 +39,9 @@ InitializeDebugIdt (
   IdtEntry = (IA32_IDT_GATE_DESCRIPTOR *) IdtDescriptor.Base;\r
 \r
   for (Index = 0; Index < 20; Index ++) {\r
-    if ((PcdGet32 (PcdExceptionsIgnoredByDebugger) & (1 << Index)) != 0) {\r
+    if (((PcdGet32 (PcdExceptionsIgnoredByDebugger) & ~(BIT1 | BIT3)) & (1 << Index)) != 0) {\r
       //\r
-      // If the exception is masked to be reserved, skip it\r
+      // If the exception is masked to be reserved except for INT1 and INT3, skip it\r
       //\r
       continue;\r
     }\r
@@ -65,3 +65,51 @@ InitializeDebugIdt (
   //\r
   AsmWriteCr4 (AsmReadCr4 () | BIT3);\r
 }\r
+\r
+/**\r
+  Retrieve exception handler from IDT table by ExceptionNum.\r
+\r
+  @param[in]  ExceptionNum    Exception number\r
\r
+  @return Exception handler\r
+\r
+**/\r
+VOID *\r
+GetExceptionHandlerInIdtEntry (\r
+  IN UINTN             ExceptionNum\r
+  )\r
+{\r
+  IA32_IDT_GATE_DESCRIPTOR   *IdtEntry;\r
+  IA32_DESCRIPTOR            IdtDescriptor;\r
+\r
+  AsmReadIdtr (&IdtDescriptor);\r
+  IdtEntry = (IA32_IDT_GATE_DESCRIPTOR *) IdtDescriptor.Base;\r
+\r
+  return (VOID *) (IdtEntry[ExceptionNum].Bits.OffsetLow |\r
+                  (((UINTN)IdtEntry[ExceptionNum].Bits.OffsetHigh) << 16) |\r
+                  (((UINTN)IdtEntry[ExceptionNum].Bits.OffsetUpper) << 32));\r
+} \r
+\r
+/**\r
+  Set exception handler in IDT table by ExceptionNum.\r
+\r
+  @param[in]  ExceptionNum      Exception number\r
+  @param[in]  ExceptionHandler  Exception Handler to be set \r
+\r
+**/\r
+VOID\r
+SetExceptionHandlerInIdtEntry (\r
+  IN UINTN             ExceptionNum,\r
+  IN VOID              *ExceptionHandler\r
+  )\r
+{\r
+  IA32_IDT_GATE_DESCRIPTOR   *IdtEntry;\r
+  IA32_DESCRIPTOR            IdtDescriptor;\r
+\r
+  AsmReadIdtr (&IdtDescriptor);\r
+  IdtEntry = (IA32_IDT_GATE_DESCRIPTOR *) IdtDescriptor.Base;\r
+\r
+  IdtEntry[ExceptionNum].Bits.OffsetLow   = (UINT16)(UINTN)ExceptionHandler;\r
+  IdtEntry[ExceptionNum].Bits.OffsetHigh  = (UINT16)((UINTN)ExceptionHandler >> 16);\r
+  IdtEntry[ExceptionNum].Bits.OffsetUpper = (UINT32)((UINTN)ExceptionHandler >> 32);\r
+}\r
index 3de9767dba3a6c86bf556d99ff66d5fe7185054a..e7c3ed74640d8dd3b1de5c6328277169b6dc6799 100644 (file)
@@ -1,6 +1,6 @@
 #------------------------------------------------------------------------------\r
 #\r
-# Copyright (c) 2006 - 2012, Intel Corporation. All rights reserved.<BR>\r
+# Copyright (c) 2006 - 2013, 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
@@ -35,6 +35,7 @@ ASM_PFX(ExceptionStubHeaderSize):  .word     ASM_PFX(Exception1Handle) - ASM_PFX
 \r
 .text\r
 \r
+.byte 0x41, 0x47, 0x54, 0x48  # AGENT_HANDLER_SIGNATURE     SIGNATURE_32('A','G','T','H')\r
 ASM_PFX(Exception0Handle):\r
    cli\r
    pushq %rcx\r
@@ -280,7 +281,7 @@ NoExtrPush:
   pushq   %rax\r
 ## clear Dr7 while executing debugger itself\r
    xorq    %rax, %rax\r
-#debug   movq    %rax, %dr7\r
+   movq    %rax, %dr7\r
 \r
    movq    %dr6, %rax\r
   pushq    %rax\r
index 16d73a41211977022378207c113b98bdf0c26359..23abcc7621c7ddecfa61e7ebed49d8653f0a5409 100644 (file)
@@ -1,6 +1,6 @@
 ;------------------------------------------------------------------------------\r
 ;\r
-; Copyright (c) 2010 - 2012, Intel Corporation. All rights reserved.<BR>\r
+; Copyright (c) 2010 - 2013, 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
@@ -33,6 +33,7 @@ CommonEntryAddr                dq      CommonEntry ;
 \r
 .code\r
 \r
+db   41h, 47h, 54h, 48h  ; AGENT_HANDLER_SIGNATURE     SIGNATURE_32('A','G','T','H')\r
 Exception0Handle:\r
     cli\r
     push    rcx\r
@@ -198,7 +199,7 @@ NoExtrPush:
     push    rax\r
     mov     rax, cr2\r
     push    rax\r
-    push    0         ; cr0 will not saved???\r
+    push    0\r
     mov     rax, cr0\r
     push    rax\r
 \r
index f8e3f6c1abe888565ca5d88f927b1e4e83086c8e..35c6acfd9da5e3c359f07d79f972c5948d2bac9c 100644 (file)
@@ -1,7 +1,7 @@
 /** @file\r
   Debug Agent library implementition for Dxe Core and Dxr modules.\r
 \r
-  Copyright (c) 2010 - 2012, Intel Corporation. All rights reserved.<BR>\r
+  Copyright (c) 2010 - 2013, Intel Corporation. All rights reserved.<BR>\r
   This program and the accompanying materials\r
   are licensed and made available under the terms and conditions of the BSD License\r
   which accompanies this distribution.  The full text of the license may be found at\r
 #include "DxeDebugAgentLib.h"\r
 \r
 DEBUG_AGENT_MAILBOX          mMailbox;\r
-DEBUG_AGENT_MAILBOX          *mMailboxPointer;\r
+DEBUG_AGENT_MAILBOX          *mMailboxPointer = NULL;\r
 IA32_IDT_GATE_DESCRIPTOR     mIdtEntryTable[33];\r
-BOOLEAN                      mDxeCoreFlag               = FALSE;\r
-CONST BOOLEAN                MultiProcessorDebugSupport = TRUE;\r
+BOOLEAN                      mDxeCoreFlag                = FALSE;\r
+BOOLEAN                      mMultiProcessorDebugSupport = FALSE;\r
+VOID                         *mSavedIdtTable             = NULL;\r
+UINTN                        mSaveIdtTableSize           = 0;\r
+BOOLEAN                      mDebugAgentInitialized      = FALSE;\r
+BOOLEAN                      mSkipBreakpoint             = FALSE;\r
 \r
 /**\r
-  Constructor allocates the NVS memory to store Mailbox and install configuration table\r
-  in system table to store its pointer.\r
+  Check if debug agent support multi-processor.\r
 \r
-  @param[in]  ImageHandle   The firmware allocated handle for the EFI image.\r
-  @param[in]  SystemTable   A pointer to the EFI System Table.\r
+  @retval TRUE    Multi-processor is supported.\r
+  @retval FALSE   Multi-processor is not supported.\r
+\r
+**/\r
+BOOLEAN\r
+MultiProcessorDebugSupport (\r
+  VOID\r
+  )\r
+{\r
+  return mMultiProcessorDebugSupport;\r
+}\r
 \r
-  @retval  RETURN_SUCCESS   Allocate the global memory space to store guid and function tables.\r
+/**\r
+  Internal constructor worker function.\r
+\r
+  It will register one callback function on EFI PCD Protocol.\r
+  It will allocate the NVS memory to store Mailbox and install configuration table\r
+  in system table to store its pointer.\r
 \r
 **/\r
-RETURN_STATUS\r
-EFIAPI\r
-DxeDebugAgentLibConstructor (\r
-  IN EFI_HANDLE        ImageHandle,\r
-  IN EFI_SYSTEM_TABLE  *SystemTable\r
+VOID\r
+InternalConstructorWorker (\r
+  VOID\r
   )\r
 {\r
   EFI_STATUS                  Status;\r
   EFI_PHYSICAL_ADDRESS        Address;\r
-  EFI_EVENT                   Event;\r
-  VOID                        *EventRegistration;\r
-\r
-  if (!mDxeCoreFlag) {\r
-    return RETURN_SUCCESS;\r
-  }\r
-\r
-  Status = gBS->CreateEvent (\r
-                  EVT_NOTIFY_SIGNAL,\r
-                  TPL_CALLBACK,\r
-                  InstallSerialIoNotification,\r
-                  NULL,\r
-                  &Event\r
-                  );\r
-  ASSERT_EFI_ERROR (Status);\r
+  BOOLEAN                     DebugTimerInterruptState;\r
 \r
   //\r
-  // Register for protocol notifications on this event\r
+  // Install EFI Serial IO protocol on debug port\r
   //\r
-\r
-  Status = gBS->RegisterProtocolNotify (\r
-                  &gEfiPcdProtocolGuid,\r
-                  Event,\r
-                  &EventRegistration\r
-                  );\r
-\r
-  ASSERT_EFI_ERROR (Status);\r
+  InstallSerialIo ();\r
 \r
   Address = 0;\r
   Status = gBS->AllocatePages (\r
@@ -76,18 +70,67 @@ DxeDebugAgentLibConstructor (
                   );\r
   ASSERT_EFI_ERROR (Status);\r
 \r
+  DebugTimerInterruptState = SaveAndSetDebugTimerInterrupt (FALSE);\r
   CopyMem (\r
     (UINT8 *) (UINTN) Address,\r
-    (UINT8 *) (UINTN) mMailboxPointer,\r
+    (UINT8 *) (UINTN) GetMailboxPointer (),\r
     sizeof (DEBUG_AGENT_MAILBOX)\r
     );\r
+  DebugTimerInterruptState = SaveAndSetDebugTimerInterrupt (DebugTimerInterruptState);\r
 \r
   mMailboxPointer = (DEBUG_AGENT_MAILBOX *) (UINTN) Address;\r
 \r
   Status = gBS->InstallConfigurationTable (&gEfiDebugAgentGuid, (VOID *) mMailboxPointer);\r
   ASSERT_EFI_ERROR (Status);\r
+}\r
+\r
+/**\r
+  Debug Agent constructor function.\r
+\r
+  @param[in]  ImageHandle   The firmware allocated handle for the EFI image.\r
+  @param[in]  SystemTable   A pointer to the EFI System Table.\r
+\r
+  @retval  RETURN_SUCCESS  When this function completed.\r
+\r
+**/\r
+RETURN_STATUS\r
+EFIAPI\r
+DxeDebugAgentLibConstructor (\r
+  IN EFI_HANDLE        ImageHandle,\r
+  IN EFI_SYSTEM_TABLE  *SystemTable\r
+  )\r
+{\r
+  if (mDxeCoreFlag) {\r
+    //\r
+    // Invoke internal constructor function only when DXE core links this library instance\r
+    //\r
+    InternalConstructorWorker ();\r
+  }\r
+\r
+  return RETURN_SUCCESS;\r
+}\r
+\r
+/**\r
+  Get the pointer to Mailbox from the configuration table.\r
+\r
+  @return Pointer to Mailbox.\r
+\r
+**/\r
+DEBUG_AGENT_MAILBOX *\r
+GetMailboxFromConfigurationTable (\r
+  VOID\r
+  )\r
+{\r
+  EFI_STATUS               Status;\r
+  DEBUG_AGENT_MAILBOX      *Mailbox;\r
   \r
-  return Status;\r
+  Status = EfiGetSystemConfigurationTable (&gEfiDebugAgentGuid, (VOID **) &Mailbox);\r
+  if (Status == EFI_SUCCESS && Mailbox != NULL) {\r
+    VerifyMailboxChecksum (Mailbox);\r
+    return Mailbox;\r
+  } else {\r
+    return NULL;\r
+  }\r
 }\r
 \r
 /**\r
@@ -104,13 +147,18 @@ GetMailboxFromHob (
   )\r
 {\r
   EFI_HOB_GUID_TYPE        *GuidHob;\r
+  UINT64                   *MailboxLocation;\r
+  DEBUG_AGENT_MAILBOX      *Mailbox;\r
 \r
   GuidHob = GetNextGuidHob (&gEfiDebugAgentGuid, HobStart);\r
   if (GuidHob == NULL) {\r
     return NULL;\r
   }\r
+  MailboxLocation = (UINT64 *) (GET_GUID_HOB_DATA(GuidHob));\r
+  Mailbox = (DEBUG_AGENT_MAILBOX *)(UINTN)(*MailboxLocation);\r
+  VerifyMailboxChecksum (Mailbox);\r
 \r
-  return (DEBUG_AGENT_MAILBOX *) (GET_GUID_HOB_DATA(GuidHob));\r
+  return Mailbox;\r
 }\r
 \r
 /**\r
@@ -124,6 +172,9 @@ GetMailboxPointer (
   VOID\r
   )\r
 {\r
+  AcquireMpSpinLock (&mDebugMpContext.MailboxSpinLock);\r
+  VerifyMailboxChecksum (mMailboxPointer);\r
+  ReleaseMpSpinLock (&mDebugMpContext.MailboxSpinLock);\r
   return mMailboxPointer;\r
 }\r
 \r
@@ -138,10 +189,86 @@ GetDebugPortHandle (
   VOID\r
   )\r
 {\r
-  return (DEBUG_PORT_HANDLE) (UINTN)(mMailboxPointer->DebugPortHandle);\r
+  return (DEBUG_PORT_HANDLE) (UINTN)(GetMailboxPointer ()->DebugPortHandle);\r
+}\r
+\r
+/**\r
+  Worker function to setup IDT table and initialize the IDT entries.\r
+\r
+  @param[in] Mailbox        Pointer to Mailbox.\r
+\r
+**/\r
+VOID\r
+SetupDebugAgentEnviroment (\r
+  IN DEBUG_AGENT_MAILBOX       *Mailbox\r
+  )\r
+{\r
+  IA32_DESCRIPTOR              Idtr;\r
+  UINT16                       IdtEntryCount;\r
+  UINT64                       DebugPortHandle;\r
+\r
+  if (mMultiProcessorDebugSupport) {\r
+    InitializeSpinLock (&mDebugMpContext.MpContextSpinLock);\r
+    InitializeSpinLock (&mDebugMpContext.DebugPortSpinLock);\r
+    InitializeSpinLock (&mDebugMpContext.MailboxSpinLock);\r
+    //\r
+    // Clear Break CPU index value\r
+    //\r
+    mDebugMpContext.BreakAtCpuIndex = (UINT32) -1;\r
+  }\r
+\r
+  //\r
+  // Get original IDT address and size.\r
+  //\r
+  AsmReadIdtr ((IA32_DESCRIPTOR *) &Idtr);\r
+  IdtEntryCount = (UINT16) ((Idtr.Limit + 1) / sizeof (IA32_IDT_GATE_DESCRIPTOR));\r
+  if (IdtEntryCount < 33) {\r
+    Idtr.Limit = (UINT16) (sizeof (IA32_IDT_GATE_DESCRIPTOR) * 33 - 1);\r
+    Idtr.Base  = (UINTN) &mIdtEntryTable;\r
+    ZeroMem (&mIdtEntryTable, Idtr.Limit + 1);\r
+    AsmWriteIdtr ((IA32_DESCRIPTOR *) &Idtr);\r
+  }\r
+\r
+  //\r
+  // Initialize the IDT table entries to support source level debug.\r
+  //\r
+  InitializeDebugIdt ();\r
+\r
+  if (Mailbox != NULL) {\r
+    //\r
+    // If Mailbox exists, copy it into one global variable,\r
+    //\r
+    CopyMem (&mMailbox, Mailbox, sizeof (DEBUG_AGENT_MAILBOX));\r
+  } else {\r
+    ZeroMem (&mMailbox, sizeof (DEBUG_AGENT_MAILBOX));\r
+  }  \r
+\r
+  mMailboxPointer = &mMailbox;\r
+  //\r
+  // Initialize debug communication port\r
+  //\r
+  DebugPortHandle = (UINT64) (UINTN)DebugPortInitialize ((VOID *)(UINTN)mMailboxPointer->DebugPortHandle, NULL);\r
+  UpdateMailboxContent (mMailboxPointer, DEBUG_MAILBOX_DEBUG_PORT_HANDLE_INDEX, DebugPortHandle);\r
+\r
+  if (Mailbox == NULL) {\r
+    //\r
+    // Trigger one software interrupt to inform HOST\r
+    //\r
+    TriggerSoftInterrupt (SYSTEM_RESET_SIGNATURE);\r
+    SetDebugFlag (DEBUG_AGENT_FLAG_MEMORY_READY, 1);\r
+    //\r
+    // Memory has been ready\r
+    //\r
+    if (IsHostAttached ()) {\r
+      //\r
+      // Trigger one software interrupt to inform HOST\r
+      //\r
+      TriggerSoftInterrupt (MEMORY_READY_SIGNATURE);\r
+    }\r
+  }\r
 }\r
 \r
\r
+\r
 /**\r
   Initialize debug agent.\r
 \r
@@ -167,105 +294,207 @@ InitializeDebugAgent (
   IN DEBUG_AGENT_CONTINUE  Function  OPTIONAL\r
   )\r
 {\r
+  UINT64                       *MailboxLocation;\r
   DEBUG_AGENT_MAILBOX          *Mailbox;\r
-  IA32_DESCRIPTOR              Idtr;\r
-  UINT16                       IdtEntryCount;\r
   BOOLEAN                      InterruptStatus;\r
+  VOID                         *HobList;\r
+  IA32_DESCRIPTOR              IdtDescriptor;\r
+  IA32_DESCRIPTOR              *Ia32Idtr;\r
+  IA32_IDT_ENTRY               *Ia32IdtEntry;\r
 \r
-  if (InitFlag != DEBUG_AGENT_INIT_DXE_CORE &&\r
-      InitFlag != DEBUG_AGENT_INIT_S3 &&\r
-      InitFlag != DEBUG_AGENT_INIT_DXE_AP) {\r
-    return;\r
+  if (InitFlag == DEBUG_AGENT_INIT_DXE_AP) {\r
+    //\r
+    // Invoked by AP, enable interrupt to let AP could receive IPI from other processors\r
+    //\r
+    EnableInterrupts ();\r
+    return ;\r
   }\r
 \r
+  // \r
+  // Disable Debug Timer interrupt\r
+  //\r
+  SaveAndSetDebugTimerInterrupt (FALSE);\r
   //\r
   // Save and disable original interrupt status\r
   //\r
   InterruptStatus = SaveAndDisableInterrupts ();\r
 \r
-  if (InitFlag == DEBUG_AGENT_INIT_DXE_CORE) {\r
+  //\r
+  // Try to get mailbox firstly\r
+  //\r
+  HobList         = NULL;\r
+  Mailbox         = NULL;\r
+  MailboxLocation = NULL;\r
+\r
+  switch (InitFlag) {\r
+\r
+  case DEBUG_AGENT_INIT_DXE_LOAD:\r
     //\r
-    // Try to get Mailbox from GUIDed HOB.\r
+    // Check if Debug Agent has been initialized before\r
     //\r
-    mDxeCoreFlag = TRUE;\r
-    Mailbox = GetMailboxFromHob (Context);\r
-    \r
+    if (IsDebugAgentInitialzed ()) {\r
+      DEBUG ((EFI_D_INFO, "Debug Agent: The former agent will be overwritten by the new one!\n"));\r
+    }\r
+\r
+    mMultiProcessorDebugSupport = TRUE;\r
     //\r
-    // Clear Break CPU index value\r
+    // Save original IDT table\r
+    //\r
+    AsmReadIdtr (&IdtDescriptor);\r
+    mSaveIdtTableSize = IdtDescriptor.Limit + 1;\r
+    mSavedIdtTable    = AllocateCopyPool (mSaveIdtTableSize, (VOID *) IdtDescriptor.Base);\r
+    //\r
+    // Initialize Debug Timer hardware\r
+    //\r
+    InitializeDebugTimer ();\r
+    //\r
+    // Check if Debug Agent initialized in DXE phase\r
+    //\r
+    Mailbox = GetMailboxFromConfigurationTable ();\r
+    if (Mailbox == NULL) {\r
+      //\r
+      // Try to get mailbox from GUIDed HOB build in PEI \r
+      //\r
+      HobList = GetHobList ();\r
+      Mailbox = GetMailboxFromHob (HobList);\r
+    }\r
+    //\r
+    // Set up IDT table and prepare for IDT entries\r
+    //\r
+    SetupDebugAgentEnviroment (Mailbox);\r
+    //\r
+    // For DEBUG_AGENT_INIT_S3, needn't to install configuration table and EFI Serial IO protocol\r
+    // For DEBUG_AGENT_INIT_DXE_CORE, InternalConstructorWorker() will invoked in Constructor()\r
+    //\r
+    InternalConstructorWorker ();\r
+    //\r
+    // Enable interrupt to receive Debug Timer interrupt\r
     //\r
-    mDebugMpContext.BreakAtCpuIndex = (UINT32) -1;\r
-\r
-  } else if (InitFlag == DEBUG_AGENT_INIT_DXE_AP) {\r
-\r
     EnableInterrupts ();\r
 \r
-    return;\r
+    mDebugAgentInitialized = TRUE;\r
+    FindAndReportModuleImageInfo (SIZE_4KB);\r
+\r
+    *(EFI_STATUS *)Context = EFI_SUCCESS;\r
+\r
+    if (gST->ConOut != NULL) {\r
+      Print (L"Debug Agent: Initialized successfully!\r\n");\r
+      Print (L"If the Debug Port is serial port, please make sure this serial port isn't connected by ISA Serial driver\r\n");\r
+      Print (L"You could do the following steps to disconnect the serial port:\r\n");\r
+      Print (L"1: Shell> drivers\r\n");\r
+      Print (L"   ...\r\n");\r
+      Print (L"   V  VERSION  E G G #D #C DRIVER NAME                         IMAGE NAME\r\n");\r
+      Print (L"   == ======== = = = == == =================================== ===================\r\n");\r
+      Print (L"   8F 0000000A B - -  1 14 PCI Bus Driver                      PciBusDxe\r\n");\r
+      Print (L"   91 00000010 ? - -  -  - ATA Bus Driver                      AtaBusDxe\r\n");\r
+      Print (L"   ...\r\n");\r
+      Print (L"   A7 0000000A B - -  1  1 ISA Serial Driver                   IsaSerialDxe\r\n");\r
+      Print (L"   ...\r\n");\r
+      Print (L"2: Shell> dh -d A7\r\n");\r
+      Print (L"   A7: Image(IsaSerialDxe) ImageDevPath (..9FB3-11D4-9A3A-0090273FC14D))DriverBinding ComponentName ComponentName2\r\n");\r
+      Print (L"        Driver Name    : ISA Serial Driver\r\n");\r
+      Print (L"        Image Name     : FvFile(93B80003-9FB3-11D4-9A3A-0090273FC14D)\r\n");\r
+      Print (L"        Driver Version : 0000000A\r\n");\r
+      Print (L"        Driver Type    : BUS\r\n");\r
+      Print (L"        Configuration  : NO\r\n");\r
+      Print (L"        Diagnostics    : NO\r\n");\r
+      Print (L"        Managing       :\r\n");\r
+      Print (L"          Ctrl[EA] : PciRoot(0x0)/Pci(0x1F,0x0)/Serial(0x0)\r\n");\r
+      Print (L"            Child[EB] : PciRoot(0x0)/Pci(0x1F,0x0)/Serial(0x0)/Uart(115200,8,N,1)\r\n");\r
+      Print (L"3: Shell> disconnect EA\r\n");\r
+      Print (L"4: Shell> load -nc DebugAgentDxe.efi\r\n\r\n");\r
+    }\r
+    break;\r
+\r
+  case DEBUG_AGENT_INIT_DXE_UNLOAD:\r
+    if (mDebugAgentInitialized) {\r
+      if (IsHostAttached ()) {\r
+        Print (L"Debug Agent: Host is still connected, please de-attach TARGET firstly!\r\n");\r
+        *(EFI_STATUS *)Context = EFI_ACCESS_DENIED;\r
+        // \r
+        // Enable Debug Timer interrupt again\r
+        //\r
+        SaveAndSetDebugTimerInterrupt (TRUE);\r
+      } else {\r
+        //\r
+        // Restore original IDT table\r
+        //\r
+        AsmReadIdtr (&IdtDescriptor);\r
+        IdtDescriptor.Limit = (UINT16) (mSaveIdtTableSize - 1);\r
+        CopyMem ((VOID *) IdtDescriptor.Base, mSavedIdtTable, mSaveIdtTableSize);\r
+        AsmWriteIdtr (&IdtDescriptor);\r
+        FreePool (mSavedIdtTable);\r
+        mDebugAgentInitialized = FALSE;\r
+        *(EFI_STATUS *)Context = EFI_SUCCESS;\r
+      }\r
+    } else {\r
+      Print (L"Debug Agent: It hasn't been initialized, cannot unload it!\r\n");\r
+      *(EFI_STATUS *)Context = EFI_NOT_STARTED;\r
+    }\r
 \r
-  } else {\r
     //\r
-    // If it is in S3 path, needn't to install configuration table.\r
+    // Restore interrupt state.\r
     //\r
-    Mailbox = NULL;\r
-  }\r
+    SetInterruptState (InterruptStatus);\r
+    break;\r
 \r
-  if (Mailbox != NULL) {\r
+  case DEBUG_AGENT_INIT_DXE_CORE:\r
+    mDxeCoreFlag                = TRUE;\r
+    mMultiProcessorDebugSupport = TRUE;\r
     //\r
-    // If Mailbox exists, copy it into one global variable.\r
+    // Initialize Debug Timer hardware\r
     //\r
-    CopyMem (&mMailbox, Mailbox, sizeof (DEBUG_AGENT_MAILBOX));\r
-  } else {\r
+    InitializeDebugTimer ();\r
     //\r
-    // If Mailbox not exists, used the local Mailbox.\r
+    // Try to get mailbox from GUIDed HOB build in PEI \r
     //\r
-    ZeroMem (&mMailbox, sizeof (DEBUG_AGENT_MAILBOX));\r
-  }\r
-\r
-  mMailboxPointer = &mMailbox;\r
-\r
-  //\r
-  // Get original IDT address and size.\r
-  //\r
-  AsmReadIdtr ((IA32_DESCRIPTOR *) &Idtr);\r
-  IdtEntryCount = (UINT16) ((Idtr.Limit + 1) / sizeof (IA32_IDT_GATE_DESCRIPTOR));\r
-  if (IdtEntryCount < 33) {\r
-    Idtr.Limit = (UINT16) (sizeof (IA32_IDT_GATE_DESCRIPTOR) * 33 - 1);\r
-    Idtr.Base  = (UINTN) &mIdtEntryTable;\r
-    ZeroMem (&mIdtEntryTable, Idtr.Limit + 1);\r
-    AsmWriteIdtr ((IA32_DESCRIPTOR *) &Idtr);\r
-  }\r
+    HobList = Context;\r
+    Mailbox = GetMailboxFromHob (HobList);\r
+    //\r
+    // Set up IDT table and prepare for IDT entries\r
+    //\r
+    SetupDebugAgentEnviroment (Mailbox);\r
+    //\r
+    // Enable interrupt to receive Debug Timer interrupt\r
+    //\r
+    EnableInterrupts ();\r
 \r
-  //\r
-  // Initialize the IDT table entries to support source level debug.\r
-  //\r
-  InitializeDebugIdt ();\r
+    break;\r
 \r
-  //\r
-  // Initialize debug communication port\r
-  //\r
-  mMailboxPointer->DebugPortHandle = (UINT64) (UINTN)DebugPortInitialize ((VOID *)(UINTN)mMailbox.DebugPortHandle, NULL);\r
+  case DEBUG_AGENT_INIT_S3:\r
 \r
-  InitializeSpinLock (&mDebugMpContext.MpContextSpinLock);\r
-  InitializeSpinLock (&mDebugMpContext.DebugPortSpinLock);\r
\r
-  if (InitFlag == DEBUG_AGENT_INIT_DXE_CORE) {\r
+    if (Context != NULL) {\r
+      Ia32Idtr =  (IA32_DESCRIPTOR *) Context;\r
+      Ia32IdtEntry = (IA32_IDT_ENTRY *)(Ia32Idtr->Base);\r
+      MailboxLocation = (UINT64 *) (UINTN) (Ia32IdtEntry[DEBUG_MAILBOX_VECTOR].Bits.OffsetLow + \r
+                                           (Ia32IdtEntry[DEBUG_MAILBOX_VECTOR].Bits.OffsetHigh << 16));\r
+      Mailbox = (DEBUG_AGENT_MAILBOX *)(UINTN)(*MailboxLocation);\r
+      VerifyMailboxChecksum (Mailbox);\r
+    }\r
     //\r
-    // Initialize Debug Timer hardware and enable interrupt.\r
+    // Set up IDT table and prepare for IDT entries\r
     //\r
-    InitializeDebugTimer ();\r
-    EnableInterrupts ();\r
-\r
-    return;\r
-  } else {\r
+    SetupDebugAgentEnviroment (Mailbox);\r
     //\r
-    // Disable Debug Timer interrupt in S3 path.\r
+    // Disable interrupt\r
     //\r
-    SaveAndSetDebugTimerInterrupt (FALSE);\r
-\r
+    DisableInterrupts ();\r
+    FindAndReportModuleImageInfo (SIZE_4KB);\r
+    if (GetDebugFlag (DEBUG_AGENT_FLAG_BREAK_BOOT_SCRIPT) == 1) {\r
+      //\r
+      // If Boot Script entry break is set, code will be break at here.\r
+      //\r
+      CpuBreakpoint ();\r
+    }\r
+    break;\r
+\r
+  default:\r
     //\r
-    // Restore interrupt state.\r
+    // Only DEBUG_AGENT_INIT_PREMEM_SEC and DEBUG_AGENT_INIT_POSTMEM_SEC are allowed for this \r
+    // Debug Agent library instance.\r
     //\r
-    SetInterruptState (InterruptStatus);\r
+    DEBUG ((EFI_D_ERROR, "Debug Agent: The InitFlag value is not allowed!\n"));\r
+    CpuDeadLoop ();\r
+    break;\r
   }\r
-\r
 }\r
-\r
index ab561812cd0cb5b1da14d209869b917feb5fcf32..536fb71dc5b2e0d92da1a9e79caf5cc97815edd3 100644 (file)
@@ -1,7 +1,7 @@
 /** @file\r
   Header file for Dxe Core Debug Agent Library instance.\r
 \r
-  Copyright (c) 2010 - 2012, Intel Corporation. All rights reserved.<BR>\r
+  Copyright (c) 2010 - 2013, Intel Corporation. All rights reserved.<BR>\r
   This program and the accompanying materials\r
   are licensed and made available under the terms and conditions of the BSD License\r
   which accompanies this distribution.  The full text of the license may be found at\r
 #include <Library/UefiBootServicesTableLib.h>\r
 #include <Library/UefiLib.h>\r
 #include <Library/DevicePathLib.h>\r
+#include <Library/MemoryAllocationLib.h>\r
 \r
 #include "DebugAgent.h"\r
 \r
 /**\r
-  Notification function on EFI PCD protocol to install EFI Serial IO protocol based\r
-  on Debug Communication Library. \r
-\r
-  @param[in]  Event    The event of notify protocol.\r
-  @param[in]  Context  Notify event context.\r
+  Install EFI Serial IO protocol based on Debug Communication Library. \r
 \r
 **/\r
 VOID\r
-EFIAPI\r
-InstallSerialIoNotification (\r
-  IN EFI_EVENT     Event,\r
-  IN VOID          *Context\r
+InstallSerialIo (\r
+  VOID\r
   );\r
   \r
 #endif\r
index 0cb7c5255473ad78055186a91ed65832ac124786..9b181e3ac7fa82cc798c974b6393f8e0f42789be 100644 (file)
@@ -1,7 +1,7 @@
 /** @file\r
   Install Serial IO Protocol that layers on top of a Debug Communication Library instance.\r
 \r
-  Copyright (c) 2012, Intel Corporation. All rights reserved.<BR>\r
+  Copyright (c) 2012 - 2013, 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
@@ -149,11 +149,11 @@ SerialRead (
 EFI_SERIAL_IO_MODE  mSerialIoMode = {\r
   SERIAL_PORT_DEFAULT_CONTROL_MASK,\r
   SERIAL_PORT_DEFAULT_TIMEOUT,\r
-  0,  // BaudRate\r
+  0,  // default BaudRate\r
   SERIAL_PORT_DEFAULT_RECEIVE_FIFO_DEPTH,\r
-  0,  // DataBits\r
-  0,  // Parity\r
-  0   // StopBits\r
+  0,  // default DataBits\r
+  0,  // default Parity\r
+  0   // default StopBits\r
 };\r
 \r
 //\r
@@ -204,10 +204,10 @@ SERIAL_IO_DEVICE_PATH mSerialIoDevicePath = {
       }\r
     },\r
     0,\r
-    0,  // BaudRate\r
-    0,  // DataBits\r
-    0,  // Parity\r
-    0,  // StopBits\r
+    0,  // default BaudRate\r
+    0,  // default DataBits\r
+    0,  // default Parity\r
+    0,  // default StopBits\r
   },\r
   {\r
     END_DEVICE_PATH_TYPE,\r
@@ -357,34 +357,15 @@ DebugTerminalFifoRemove (
 }\r
 \r
 /**\r
-  Notification function on EFI PCD protocol to install EFI Serial IO protocol based\r
-  on Debug Communication Library. \r
-\r
-  @param[in]  Event    The event of notify protocol.\r
-  @param[in]  Context  Notify event context.\r
+  Install EFI Serial IO protocol based on Debug Communication Library. \r
 \r
 **/\r
 VOID\r
-EFIAPI\r
-InstallSerialIoNotification (\r
-  IN EFI_EVENT     Event,\r
-  IN VOID          *Context\r
+InstallSerialIo (\r
+  VOID\r
   )\r
 {\r
-  EFI_STATUS  Status;\r
-\r
-  //\r
-  // Get Debug Port parameters from PCDs\r
-  //\r
-  mSerialIoDevicePath.UartDevicePath.BaudRate = PcdGet64 (PcdUartDefaultBaudRate);\r
-  mSerialIoDevicePath.UartDevicePath.DataBits = PcdGet8 (PcdUartDefaultDataBits);\r
-  mSerialIoDevicePath.UartDevicePath.Parity   = PcdGet8 (PcdUartDefaultParity);\r
-  mSerialIoDevicePath.UartDevicePath.StopBits = PcdGet8 (PcdUartDefaultStopBits);\r
-\r
-  mSerialIoMode.BaudRate = mSerialIoDevicePath.UartDevicePath.BaudRate;\r
-  mSerialIoMode.DataBits = mSerialIoDevicePath.UartDevicePath.DataBits;\r
-  mSerialIoMode.Parity   = mSerialIoDevicePath.UartDevicePath.Parity;\r
-  mSerialIoMode.StopBits = mSerialIoDevicePath.UartDevicePath.StopBits;\r
+  EFI_STATUS       Status;\r
 \r
   Status = gBS->InstallMultipleProtocolInterfaces (\r
                   &mSerialIoHandle,\r
@@ -448,22 +429,10 @@ SerialSetAttributes (
   )\r
 {\r
   //\r
-  // The Debug Communication Library does not support changing communications parameters, so unless\r
-  // the request is to use the default value or the value the Debug Communication Library is already\r
-  // using, then return EFI_INVALID_PARAMETER.\r
+  // The Debug Communication Library CAN NOT change communications parameters (if it has)\r
+  // actually. Because it also has no any idea on what parameters are based on, we cannot\r
+  // check the input parameters (like BaudRate, Parity, DataBits and StopBits). \r
   //\r
-  if (BaudRate != 0 && BaudRate != PcdGet64 (PcdUartDefaultBaudRate)) {\r
-    return EFI_INVALID_PARAMETER;\r
-  }\r
-  if (Parity != DefaultParity && Parity != PcdGet8 (PcdUartDefaultParity)) {\r
-    return EFI_INVALID_PARAMETER;\r
-  }\r
-  if (DataBits != 0 && DataBits != PcdGet8 (PcdUartDefaultDataBits)) {\r
-    return EFI_INVALID_PARAMETER;\r
-  }\r
-  if (StopBits != DefaultStopBits && StopBits != PcdGet8 (PcdUartDefaultStopBits)) {\r
-    return EFI_INVALID_PARAMETER;\r
-  }\r
   \r
   //\r
   // Update the Timeout value in the mode structure based on the request.\r
@@ -536,7 +505,18 @@ SerialGetControl (
   )\r
 {\r
   DEBUG_PORT_HANDLE                Handle;\r
+  BOOLEAN                          DebugTimerInterruptState;\r
+  EFI_TPL                          Tpl;\r
 \r
+  //\r
+  // Raise TPL to prevent recursion from EFI timer interrupts\r
+  //\r
+  Tpl = gBS->RaiseTPL (TPL_NOTIFY);\r
+  \r
+  //\r
+  // Save and disable Debug Timer interrupt to avoid it to access Debug Port\r
+  //\r
+  DebugTimerInterruptState = SaveAndSetDebugTimerInterrupt (FALSE);\r
   Handle = GetDebugPortHandle ();\r
   \r
   //\r
@@ -552,6 +532,17 @@ SerialGetControl (
   if (!IsDebugTermianlFifoEmpty (&mSerialFifoForTerminal) || DebugPortPollBuffer (Handle)) {\r
     *Control &= ~EFI_SERIAL_INPUT_BUFFER_EMPTY;\r
   }\r
+\r
+  //\r
+  // Restore Debug Timer interrupt\r
+  //  \r
+  SaveAndSetDebugTimerInterrupt (DebugTimerInterruptState);\r
+  \r
+  //\r
+  // Restore to original TPL\r
+  //\r
+  gBS->RestoreTPL (Tpl);\r
+  \r
   return EFI_SUCCESS;\r
 }\r
 \r
@@ -577,7 +568,18 @@ SerialWrite (
   )\r
 {\r
   DEBUG_PORT_HANDLE                Handle;\r
+  BOOLEAN                          DebugTimerInterruptState;\r
+  EFI_TPL                          Tpl;\r
 \r
+  //\r
+  // Raise TPL to prevent recursion from EFI timer interrupts\r
+  //\r
+  Tpl = gBS->RaiseTPL (TPL_NOTIFY);\r
+  \r
+  //\r
+  // Save and disable Debug Timer interrupt to avoid it to access Debug Port\r
+  //\r
+  DebugTimerInterruptState = SaveAndSetDebugTimerInterrupt (FALSE);\r
   Handle = GetDebugPortHandle ();\r
   \r
   if ((mSerialIoMode.ControlMask & EFI_SERIAL_SOFTWARE_LOOPBACK_ENABLE) != 0)  {\r
@@ -593,6 +595,17 @@ SerialWrite (
   } else {\r
     *BufferSize = DebugPortWriteBuffer (Handle, Buffer, *BufferSize);\r
   }\r
+\r
+  //\r
+  // Restore Debug Timer interrupt\r
+  //  \r
+  SaveAndSetDebugTimerInterrupt (DebugTimerInterruptState);\r
+  \r
+  //\r
+  // Restore to original TPL\r
+  //\r
+  gBS->RestoreTPL (Tpl);\r
+  \r
   return EFI_SUCCESS;\r
 }\r
 \r
@@ -620,17 +633,24 @@ SerialRead (
   EFI_STATUS                  Status;\r
   UINTN                       Index;\r
   UINT8                       *Uint8Buffer;\r
-  BOOLEAN                     OldInterruptState;\r
+  BOOLEAN                     DebugTimerInterruptState;\r
+  EFI_TPL                     Tpl;\r
   DEBUG_PORT_HANDLE           Handle;\r
-  UINT8                       Data;\r
-\r
-  Handle = GetDebugPortHandle ();\r
+  DEBUG_PACKET_HEADER         DebugHeader;\r
+  UINT8                       *Data8;\r
 \r
   //\r
-  // Save and disable Debug Timer interrupt to avoid it to access Debug Port\r
+  // Raise TPL to prevent recursion from EFI timer interrupts\r
   //\r
-  OldInterruptState = SaveAndSetDebugTimerInterrupt (FALSE);\r
+  Tpl = gBS->RaiseTPL (TPL_NOTIFY);\r
   \r
+  //\r
+  // Save and disable Debug Timer interrupt to avoid it to access Debug Port\r
+  //\r
+  DebugTimerInterruptState = SaveAndSetDebugTimerInterrupt (FALSE);\r
+  Handle = GetDebugPortHandle ();\r
\r
+  Data8 = (UINT8 *) &DebugHeader;\r
   Uint8Buffer = (UINT8 *)Buffer;\r
   if ((mSerialIoMode.ControlMask & EFI_SERIAL_SOFTWARE_LOOPBACK_ENABLE) != 0)  {\r
     if ((mLoopbackBuffer & SERIAL_PORT_LOOPBACK_BUFFER_FULL) == 0) {\r
@@ -644,9 +664,9 @@ SerialRead (
       //\r
       // Read input character from terminal FIFO firstly\r
       //\r
-      Status = DebugTerminalFifoRemove (&mSerialFifoForTerminal, &Data);\r
+      Status = DebugTerminalFifoRemove (&mSerialFifoForTerminal, Data8);\r
       if (Status == EFI_SUCCESS) {\r
-        *Uint8Buffer = Data;\r
+        *Uint8Buffer = *Data8;\r
         Uint8Buffer ++;\r
         continue;\r
       }\r
@@ -656,16 +676,25 @@ SerialRead (
       if (!DebugPortPollBuffer (Handle)) {\r
         break;\r
       }\r
-      DebugPortReadBuffer (Handle, &Data, 1, 0);\r
+      DebugPortReadBuffer (Handle, Data8, 1, 0);\r
 \r
-      if (Data== DEBUG_STARTING_SYMBOL_ATTACH ||\r
-          Data == DEBUG_STARTING_SYMBOL_BREAK) {\r
+      if (*Data8 == DEBUG_STARTING_SYMBOL_ATTACH) {\r
         //\r
         // Add the debug symbol into Debug FIFO\r
         //\r
-        DebugTerminalFifoAdd (&mSerialFifoForDebug, Data);\r
+        DebugAgentMsgPrint (DEBUG_AGENT_INFO, "Terminal Timer attach symbol received %x", *Data8);\r
+        DebugTerminalFifoAdd (&mSerialFifoForDebug, *Data8);\r
+      } else if (*Data8 == DEBUG_STARTING_SYMBOL_NORMAL) {\r
+        Status = ReadRemainingBreakPacket (Handle, &DebugHeader);\r
+        if (Status == EFI_SUCCESS) {\r
+          DebugAgentMsgPrint (DEBUG_AGENT_INFO, "Terminal Timer break symbol received %x", DebugHeader.Command);\r
+          DebugTerminalFifoAdd (&mSerialFifoForDebug, DebugHeader.Command);\r
+        }\r
+        if (Status == EFI_TIMEOUT) {\r
+          continue;\r
+        }\r
       } else {\r
-        *Uint8Buffer = Data;\r
+        *Uint8Buffer = *Data8;\r
         Uint8Buffer ++;\r
       }\r
     }\r
@@ -675,7 +704,12 @@ SerialRead (
   //\r
   // Restore Debug Timer interrupt\r
   //  \r
-  SaveAndSetDebugTimerInterrupt (OldInterruptState);\r
+  SaveAndSetDebugTimerInterrupt (DebugTimerInterruptState);\r
+  \r
+  //\r
+  // Restore to original TPL\r
+  //\r
+  gBS->RestoreTPL (Tpl);\r
   \r
   return EFI_SUCCESS;\r
 }\r
@@ -691,36 +725,90 @@ SerialRead (
 \r
 **/\r
 EFI_STATUS\r
-DebugReadBreakSymbol (\r
+DebugReadBreakFromDebugPort (\r
   IN  DEBUG_PORT_HANDLE      Handle,\r
   OUT UINT8                  *BreakSymbol\r
   )\r
 {\r
-  EFI_STATUS               Status;\r
-  UINT8                    Data;\r
+  EFI_STATUS                 Status;\r
+  DEBUG_PACKET_HEADER        DebugHeader;\r
+  UINT8                      *Data8;\r
 \r
-  Status = DebugTerminalFifoRemove (&mSerialFifoForDebug, &Data);\r
-  if (Status != EFI_SUCCESS) {\r
+  *BreakSymbol = 0;\r
+  //\r
+  // If Debug Port buffer has data, read it till it was break symbol or Debug Port buffer empty.\r
+  //\r
+  Data8 = (UINT8 *) &DebugHeader;\r
+  while (TRUE) {\r
+    //\r
+    // If start symbol is not received\r
+    //\r
     if (!DebugPortPollBuffer (Handle)) {\r
       //\r
-      // No data in Debug Port buffer.\r
+      // If no data in Debug Port, exit\r
       //\r
-      return EFI_NOT_FOUND;\r
+      break;\r
+    }\r
+    //\r
+    // Try to read the start symbol\r
+    //\r
+    DebugPortReadBuffer (Handle, Data8, 1, 0);\r
+    if (*Data8 == DEBUG_STARTING_SYMBOL_ATTACH) {\r
+      DebugAgentMsgPrint (DEBUG_AGENT_INFO, "Debug Timer attach symbol received %x", *Data8);\r
+      *BreakSymbol = *Data8;\r
+      return EFI_SUCCESS;\r
+    } \r
+    if (*Data8 == DEBUG_STARTING_SYMBOL_NORMAL) {\r
+      Status = ReadRemainingBreakPacket (Handle, &DebugHeader);\r
+      if (Status == EFI_SUCCESS) {\r
+        DebugAgentMsgPrint (DEBUG_AGENT_INFO, "Debug Timer break symbol received %x", DebugHeader.Command);\r
+        *BreakSymbol = DebugHeader.Command;\r
+        return EFI_SUCCESS;\r
+      }\r
+      if (Status == EFI_TIMEOUT) {\r
+        break;\r
+      }\r
     } else {\r
       //\r
-      // Read one character from Debug Port.\r
+      // Add to Terminal FIFO\r
       //\r
-      DebugPortReadBuffer (Handle, &Data, 1, 0);\r
-      if ((Data != DEBUG_STARTING_SYMBOL_ATTACH) && (Data != DEBUG_STARTING_SYMBOL_BREAK)) {\r
-        //\r
-        // If the data is not Break symbol, add it into Terminal FIFO\r
-        //\r
-        DebugTerminalFifoAdd (&mSerialFifoForTerminal, Data);\r
-        return EFI_NOT_FOUND;\r
-      }\r
+      DebugTerminalFifoAdd (&mSerialFifoForTerminal, *Data8);\r
     }\r
   }\r
   \r
-  *BreakSymbol = Data;\r
-  return EFI_SUCCESS;\r
+  return EFI_NOT_FOUND;\r
+}\r
+\r
+/**\r
+  Read the Attach/Break-in symbols.\r
+\r
+  @param[in]  Handle         Pointer to Debug Port handle.\r
+  @param[out] BreakSymbol    Returned break symbol.\r
+\r
+  @retval EFI_SUCCESS        Read the symbol in BreakSymbol.\r
+  @retval EFI_NOT_FOUND      No read the break symbol.\r
+\r
+**/\r
+EFI_STATUS\r
+DebugReadBreakSymbol (\r
+  IN  DEBUG_PORT_HANDLE      Handle,\r
+  OUT UINT8                  *BreakSymbol\r
+  )\r
+{\r
+  EFI_STATUS               Status;\r
+  UINT8                    Data8;\r
+\r
+  //\r
+  // Read break symbol from debug FIFO firstly\r
+  //\r
+  Status = DebugTerminalFifoRemove (&mSerialFifoForDebug, &Data8);\r
+  if (Status == EFI_SUCCESS) {\r
+    *BreakSymbol = Data8;\r
+    return EFI_SUCCESS;\r
+  } else {\r
+    //\r
+    // Read Break symbol from debug port\r
+    //\r
+    return DebugReadBreakFromDebugPort (Handle, BreakSymbol);\r
+  }\r
 }\r
index 434d21a9fbca490fa35bb7b84b3a1902d227fadd..f73385ce714134863d2252d0a1bc85c4b1cb5c04 100644 (file)
@@ -1,7 +1,7 @@
 ## @file\r
 #  Debug Agent library instance for Dxe Core and Dxe modules.\r
 #\r
-#  Copyright (c) 2010 - 2012, Intel Corporation. All rights reserved.<BR>\r
+#  Copyright (c) 2010 - 2013, Intel Corporation. All rights reserved.<BR>\r
 #\r
 #  This program and the accompanying materials\r
 #  are licensed and made available under the terms and conditions of the BSD License\r
@@ -75,6 +75,9 @@
   LocalApicLib\r
   TimerLib\r
   PrintLib\r
+  PeCoffGetEntryPointLib\r
+  PeCoffExtraActionLib\r
+  MemoryAllocationLib\r
 \r
 [Guids]\r
   gEfiDebugAgentGuid                            ## PRODUCES ## Configuration Table\r
 [Protocols]\r
   gEfiSerialIoProtocolGuid                      ## PRODUCES\r
   gEfiDevicePathProtocolGuid                    ## PRODUCES \r
-  gEfiPcdProtocolGuid                           ## NOTIFY\r
 \r
 [Pcd]\r
   gEfiMdePkgTokenSpaceGuid.PcdFSBClock                                  ## CONSUMES\r
-  gEfiMdePkgTokenSpaceGuid.PcdUartDefaultBaudRate                       ## CONSUMES\r
-  gEfiMdePkgTokenSpaceGuid.PcdUartDefaultDataBits                       ## CONSUMES\r
-  gEfiMdePkgTokenSpaceGuid.PcdUartDefaultParity                         ## CONSUMES\r
-  gEfiMdePkgTokenSpaceGuid.PcdUartDefaultStopBits                       ## CONSUMES\r
   gEfiSourceLevelDebugPkgTokenSpaceGuid.PcdExceptionsIgnoredByDebugger  ## CONSUMES\r
 \r
index ea702e654834e48ad7b3bae69ac9a85a984cb610..49c8268e09439a8fee9a56ca5545c5d06f64d8c3 100644 (file)
@@ -1,7 +1,7 @@
 /** @file\r
   SEC Core Debug Agent Library instance implementition.\r
 \r
-  Copyright (c) 2010 - 2012, Intel Corporation. All rights reserved.<BR>\r
+  Copyright (c) 2010 - 2013, 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
 \r
 #include "SecPeiDebugAgentLib.h"\r
 \r
-CONST BOOLEAN                MultiProcessorDebugSupport = FALSE;\r
+BOOLEAN  mSkipBreakpoint = FALSE;\r
+\r
+EFI_PEI_NOTIFY_DESCRIPTOR mMemoryDiscoveredNotifyList[1] = {\r
+  {\r
+    (EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),\r
+    &gEfiPeiMemoryDiscoveredPpiGuid,\r
+    DebugAgentCallbackMemoryDiscoveredPpi\r
+  }\r
+};\r
+\r
+/**\r
+  Check if debug agent support multi-processor.\r
+\r
+  @retval TRUE    Multi-processor is supported.\r
+  @retval FALSE   Multi-processor is not supported.\r
+\r
+**/\r
+BOOLEAN\r
+MultiProcessorDebugSupport (\r
+  VOID\r
+  )\r
+{\r
+  return FALSE;\r
+}\r
 \r
 /**\r
   Read the Attach/Break-in symbols from the debug port.\r
@@ -32,14 +55,44 @@ DebugReadBreakSymbol (
   OUT UINT8                  *BreakSymbol\r
   )\r
 {\r
+  EFI_STATUS                 Status;\r
+  DEBUG_PACKET_HEADER        DebugHeader;\r
+  UINT8                      *Data8;\r
+\r
   *BreakSymbol = 0;\r
   //\r
-  // If Debug Port buffer has data, read it till it was break symbol or Debug Port buffer emty.\r
+  // If Debug Port buffer has data, read it till it was break symbol or Debug Port buffer empty.\r
   //\r
-  while (DebugPortPollBuffer (Handle)) {\r
-    DebugPortReadBuffer (Handle, BreakSymbol, 1, 0);\r
-    if (*BreakSymbol == DEBUG_STARTING_SYMBOL_ATTACH || *BreakSymbol == DEBUG_STARTING_SYMBOL_BREAK) {\r
+  Data8 = (UINT8 *) &DebugHeader;\r
+  while (TRUE) {\r
+    //\r
+    // If start symbol is not received\r
+    //\r
+    if (!DebugPortPollBuffer (Handle)) {\r
+      //\r
+      // If no data in Debug Port, exit\r
+      //\r
+      break;\r
+    }\r
+    //\r
+    // Try to read the start symbol\r
+    //\r
+    DebugPortReadBuffer (Handle, Data8, 1, 0);\r
+    if (*Data8 == DEBUG_STARTING_SYMBOL_ATTACH) {\r
+      *BreakSymbol = *Data8;\r
+      DebugAgentMsgPrint (DEBUG_AGENT_INFO, "Debug Timer attach symbol received %x", *BreakSymbol);\r
       return EFI_SUCCESS;\r
+    } \r
+    if (*Data8 == DEBUG_STARTING_SYMBOL_NORMAL) {\r
+      Status = ReadRemainingBreakPacket (Handle, &DebugHeader);\r
+      if (Status == EFI_SUCCESS) {\r
+        *BreakSymbol = DebugHeader.Command;\r
+        DebugAgentMsgPrint (DEBUG_AGENT_INFO, "Debug Timer break symbol received %x", *BreakSymbol);\r
+        return EFI_SUCCESS;\r
+      }\r
+      if (Status == EFI_TIMEOUT) {\r
+        break;\r
+      }\r
     }\r
   }\r
   \r
@@ -47,67 +100,56 @@ DebugReadBreakSymbol (
 }\r
 \r
 /**\r
-  Get pointer to Mailbox from IDT entry before memory is ready.\r
+  Get the pointer to location saved Mailbox pointer from IDT entry.\r
 \r
 **/\r
 VOID *\r
-GetMailboxPointerInIdtEntry (\r
+GetLocationSavedMailboxPointerInIdtEntry (\r
   VOID\r
   )\r
 {\r
-  IA32_IDT_GATE_DESCRIPTOR   *IdtEntry;\r
-  IA32_DESCRIPTOR            IdtDescriptor;\r
-  UINTN                      Mailbox;\r
-\r
-  AsmReadIdtr (&IdtDescriptor);\r
-  IdtEntry = (IA32_IDT_GATE_DESCRIPTOR *) IdtDescriptor.Base;\r
+  UINTN                     *MailboxLocation;\r
 \r
-  Mailbox = IdtEntry[DEBUG_MAILBOX_VECTOR].Bits.OffsetLow + (IdtEntry[DEBUG_MAILBOX_VECTOR].Bits.OffsetHigh << 16);\r
-  return (VOID *) Mailbox;\r
+  MailboxLocation = (UINTN *) GetExceptionHandlerInIdtEntry (DEBUG_MAILBOX_VECTOR);\r
+  //\r
+  // *MailboxLocation is the pointer to Mailbox\r
+  //\r
+  VerifyMailboxChecksum ((DEBUG_AGENT_MAILBOX *) (*MailboxLocation));\r
+  return MailboxLocation;\r
 }\r
 \r
 /**\r
   Set the pointer of Mailbox into IDT entry before memory is ready.\r
 \r
-  @param[in]  Mailbox       The pointer of Mailbox.\r
+  @param[in]  MailboxLocation    Pointer to location saved Mailbox pointer.\r
 \r
 **/\r
 VOID\r
-SetMailboxPointerInIdtEntry (\r
-  IN VOID                    *Mailbox\r
+SetLocationSavedMailboxPointerInIdtEntry (\r
+  IN VOID                  *MailboxLocation\r
   )\r
 {\r
-  IA32_IDT_GATE_DESCRIPTOR   *IdtEntry;\r
-  IA32_DESCRIPTOR            IdtDescriptor;\r
-\r
-  AsmReadIdtr (&IdtDescriptor);\r
-  IdtEntry = (IA32_IDT_GATE_DESCRIPTOR *) IdtDescriptor.Base;\r
-\r
-  IdtEntry[DEBUG_MAILBOX_VECTOR].Bits.OffsetLow  = (UINT16)(UINTN)Mailbox;\r
-  IdtEntry[DEBUG_MAILBOX_VECTOR].Bits.OffsetHigh = (UINT16)((UINTN)Mailbox >> 16);\r
+  SetExceptionHandlerInIdtEntry (DEBUG_MAILBOX_VECTOR, MailboxLocation);\r
 }\r
 \r
 /**\r
-  Get the pointer to Mailbox from IDT entry and build the Mailbox into GUIDed Hob\r
-  after memory is ready.\r
+  Get the location of Mailbox pointer from the GUIDed HOB.\r
 \r
-  @return Pointer to Mailbox.\r
+  @return Pointer to the location saved Mailbox pointer.\r
 \r
 **/\r
-DEBUG_AGENT_MAILBOX *\r
-BuildMailboxHob (\r
+UINT64 *\r
+GetMailboxLocationFromHob (\r
   VOID\r
   )\r
 {\r
-  DEBUG_AGENT_MAILBOX       *Mailbox;\r
-\r
-  Mailbox = (DEBUG_AGENT_MAILBOX *) GetMailboxPointerInIdtEntry ();\r
+  EFI_HOB_GUID_TYPE        *GuidHob;\r
 \r
-  return BuildGuidDataHob (\r
-           &gEfiDebugAgentGuid,\r
-           Mailbox,\r
-           sizeof (DEBUG_AGENT_MAILBOX)\r
-           );\r
+  GuidHob = GetFirstGuidHob (&gEfiDebugAgentGuid);\r
+  if (GuidHob == NULL) {\r
+    return NULL;\r
+  }\r
+  return (UINT64 *) (GET_GUID_HOB_DATA(GuidHob));\r
 }\r
 \r
 /**\r
@@ -121,7 +163,49 @@ GetMailboxPointer (
   VOID\r
   )\r
 {\r
-  return (DEBUG_AGENT_MAILBOX *) GetMailboxPointerInIdtEntry ();\r
+  UINT64               DebugPortHandle;\r
+  UINT64               *MailboxLocationInIdt;\r
+  UINT64               *MailboxLocationInHob;\r
+  DEBUG_AGENT_MAILBOX  *Mailbox;\r
+  \r
+  //\r
+  // Get mailbox from IDT entry firstly\r
+  //\r
+  MailboxLocationInIdt = GetLocationSavedMailboxPointerInIdtEntry ();\r
+  Mailbox = (DEBUG_AGENT_MAILBOX *)(UINTN)(*MailboxLocationInIdt);\r
+  //\r
+  // Check if mailbox was setup in PEI firstly, cannot used GetDebugFlag() to \r
+  // get CheckMailboxInHob flag to avoid GetMailboxPointer() nesting.\r
+  //\r
+  if (Mailbox->DebugFlag.Bits.CheckMailboxInHob != 1) {\r
+    //\r
+    // If mailbox in IDT entry has already been the final one\r
+    //\r
+    return Mailbox;\r
+  }\r
+\r
+  MailboxLocationInHob = GetMailboxLocationFromHob ();\r
+  //\r
+  // Compare mailbox in IDT enry with mailbox in HOB\r
+  //\r
+  if (MailboxLocationInHob != MailboxLocationInIdt && MailboxLocationInHob != NULL) {\r
+    Mailbox = (DEBUG_AGENT_MAILBOX *)(UINTN)(*MailboxLocationInHob);\r
+    //\r
+    // Fix up Debug Port handler and save new mailbox in IDT entry\r
+    //\r
+    Mailbox = (DEBUG_AGENT_MAILBOX *)((UINTN)Mailbox + ((UINTN)(MailboxLocationInHob) - (UINTN)MailboxLocationInIdt));\r
+    DebugPortHandle = (UINT64)((UINTN)Mailbox->DebugPortHandle + ((UINTN)(MailboxLocationInHob) - (UINTN)MailboxLocationInIdt));\r
+    UpdateMailboxContent (Mailbox, DEBUG_MAILBOX_DEBUG_PORT_HANDLE_INDEX, DebugPortHandle);\r
+    *MailboxLocationInHob = (UINT64)(UINTN)Mailbox;\r
+    SetLocationSavedMailboxPointerInIdtEntry (MailboxLocationInHob);\r
+    //\r
+    // Clean CheckMailboxInHob flag\r
+    //\r
+    Mailbox->DebugFlag.Bits.CheckMailboxInHob = 0;\r
+    UpdateMailboxChecksum (Mailbox);\r
+  }\r
+\r
+  return Mailbox;\r
 }\r
 \r
 /**\r
@@ -137,49 +221,59 @@ GetDebugPortHandle (
 {\r
   DEBUG_AGENT_MAILBOX    *DebugAgentMailbox;\r
   \r
-  DebugAgentMailbox = (DEBUG_AGENT_MAILBOX *)GetMailboxPointerInIdtEntry ();\r
+  DebugAgentMailbox = GetMailboxPointer ();\r
 \r
   return (DEBUG_PORT_HANDLE) (UINTN)(DebugAgentMailbox->DebugPortHandle);\r
 }\r
 \r
 /**\r
-  Trigger one software interrupt to debug agent to handle it.\r
+  Debug Agent provided notify callback function on Memory Discovered PPI.\r
+\r
+  @param[in] PeiServices      Indirect reference to the PEI Services Table.\r
+  @param[in] NotifyDescriptor Address of the notification descriptor data structure.\r
+  @param[in] Ppi              Address of the PPI that was installed.\r
 \r
-  @param Signature       Software interrupt signature.\r
+  @retval EFI_SUCCESS If the function completed successfully.\r
 \r
 **/\r
-VOID\r
-TriggerSoftInterrupt (\r
-  UINT32                 Signature\r
+EFI_STATUS\r
+EFIAPI\r
+DebugAgentCallbackMemoryDiscoveredPpi (\r
+  IN EFI_PEI_SERVICES                     **PeiServices,\r
+  IN EFI_PEI_NOTIFY_DESCRIPTOR            *NotifyDescriptor,\r
+  IN VOID                                 *Ppi\r
   )\r
 {\r
-  UINTN                  Dr0;\r
-  UINTN                  Dr1;\r
-\r
+  DEBUG_AGENT_MAILBOX            *Mailbox;\r
+  BOOLEAN                        InterruptStatus;\r
+  \r
   //\r
-  // Save Debug Register State\r
+  // Save and disable original interrupt status\r
   //\r
-  Dr0 = AsmReadDr0 ();\r
-  Dr1 = AsmReadDr1 ();\r
-\r
+  InterruptStatus = SaveAndDisableInterrupts ();\r
+  \r
   //\r
-  // DR0 = Signature\r
+  // Set physical memory ready flag\r
   //\r
-  AsmWriteDr0 (SOFT_INTERRUPT_SIGNATURE);\r
-  AsmWriteDr1 (Signature);\r
+  Mailbox = GetMailboxPointer ();\r
+  SetDebugFlag (DEBUG_AGENT_FLAG_MEMORY_READY, 1);\r
 \r
   //\r
-  // Do INT3 to communicate with HOST side\r
+  // Memory has been ready\r
   //\r
-  CpuBreakpoint ();\r
+  if (IsHostAttached ()) {\r
+    //\r
+    // Trigger one software interrupt to inform HOST\r
+    //\r
+    TriggerSoftInterrupt (MEMORY_READY_SIGNATURE);\r
+  }\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
+  // Restore interrupt state.\r
   //\r
-  AsmWriteDr0 (Dr0);\r
-  AsmWriteDr1 (Dr1);\r
-\r
+  SetInterruptState (InterruptStatus);\r
+  \r
+  return EFI_SUCCESS;\r
 }\r
 \r
 /**\r
@@ -225,7 +319,13 @@ InitializeDebugAgent (
   DEBUG_AGENT_MAILBOX              MailboxInStack;\r
   DEBUG_AGENT_PHASE2_CONTEXT       Phase2Context;\r
   DEBUG_AGENT_CONTEXT_POSTMEM_SEC  *DebugAgentContext;\r
-\r
+  EFI_STATUS                       Status;\r
+  IA32_DESCRIPTOR                  *Ia32Idtr;\r
+  IA32_IDT_ENTRY                   *Ia32IdtEntry;\r
+  UINT64                           DebugPortHandle;\r
+  UINT64                           MailboxLocation;\r
+  UINT64                           *MailboxLocationPointer;\r
+  \r
   DisableInterrupts ();\r
 \r
   switch (InitFlag) {\r
@@ -234,20 +334,20 @@ InitializeDebugAgent (
 \r
     InitializeDebugIdt ();\r
 \r
+    MailboxLocation = (UINT64)(UINTN)&MailboxInStack;\r
     Mailbox = &MailboxInStack;\r
     ZeroMem ((VOID *) Mailbox, sizeof (DEBUG_AGENT_MAILBOX));\r
-\r
     //\r
     // Get and save debug port handle and set the length of memory block.\r
     //\r
-    SetMailboxPointerInIdtEntry ((VOID *) Mailbox);\r
+    SetLocationSavedMailboxPointerInIdtEntry (&MailboxLocation);\r
+    SetDebugFlag (DEBUG_AGENT_FLAG_PRINT_ERROR_LEVEL, DEBUG_AGENT_ERROR);\r
 \r
     InitializeDebugTimer ();\r
 \r
     Phase2Context.Context  = Context;\r
     Phase2Context.Function = Function;\r
     DebugPortInitialize ((VOID *) &Phase2Context, InitializeDebugAgentPhase2);\r
-\r
     //\r
     // If reaches here, it means Debug Port initialization failed.\r
     //\r
@@ -256,34 +356,123 @@ InitializeDebugAgent (
     break;\r
 \r
   case DEBUG_AGENT_INIT_POSTMEM_SEC:\r
-\r
+    Mailbox = GetMailboxPointer ();\r
     //\r
     // Memory has been ready\r
     //\r
-    if (IsHostAttached()) {\r
+    SetDebugFlag (DEBUG_AGENT_FLAG_MEMORY_READY, 1);\r
+    if (IsHostAttached ()) {\r
       //\r
       // Trigger one software interrupt to inform HOST\r
       //\r
       TriggerSoftInterrupt (MEMORY_READY_SIGNATURE);\r
     }\r
 \r
+    //\r
+    // Fix up Debug Port handle address and mailbox address\r
+    //\r
     DebugAgentContext = (DEBUG_AGENT_CONTEXT_POSTMEM_SEC *) Context;\r
+    DebugPortHandle = (UINT64)(UINT32)(Mailbox->DebugPortHandle + DebugAgentContext->StackMigrateOffset);\r
+    UpdateMailboxContent (Mailbox, DEBUG_MAILBOX_DEBUG_PORT_HANDLE_INDEX, DebugPortHandle);\r
+    Mailbox = (DEBUG_AGENT_MAILBOX *) ((UINTN) Mailbox + DebugAgentContext->StackMigrateOffset);\r
+    MailboxLocation = (UINT64)(UINTN)Mailbox;\r
+    //\r
+    // Build mailbox location in HOB and fix-up its address\r
+    //\r
+    MailboxLocationPointer = BuildGuidDataHob (\r
+                               &gEfiDebugAgentGuid,\r
+                               &MailboxLocation,\r
+                               sizeof (UINT64)\r
+                               );\r
+    MailboxLocationPointer = (UINT64 *) ((UINTN) MailboxLocationPointer + DebugAgentContext->HeapMigrateOffset);\r
+    //\r
+    // Update IDT entry to save the location saved mailbox pointer\r
+    //\r
+    SetLocationSavedMailboxPointerInIdtEntry (MailboxLocationPointer);\r
+    //\r
+    // Enable CPU interrupts so debug timer interrupts can be delivered\r
+    //\r
+    EnableInterrupts ();\r
+\r
+    break;\r
+\r
+  case DEBUG_AGENT_INIT_PEI:\r
+    //\r
+    // Check if Debug Agent has initialized before\r
+    //\r
+    if (IsDebugAgentInitialzed()) {\r
+      DEBUG ((EFI_D_WARN, "Debug Agent: It has already initialized in SEC Core!\n"));\r
+      break;\r
+    }\r
+    //\r
+    // Set up IDT entries\r
+    //\r
+    InitializeDebugIdt ();\r
+    //\r
+    // Build mailbox in HOB and setup Mailbox Set In Pei flag\r
+    //\r
+    Mailbox = AllocateZeroPool (sizeof (DEBUG_AGENT_MAILBOX));\r
+    MailboxLocation = (UINT64)(UINTN)Mailbox;\r
+    MailboxLocationPointer = BuildGuidDataHob (\r
+                               &gEfiDebugAgentGuid,\r
+                               &MailboxLocation,\r
+                               sizeof (UINT64)\r
+                               );\r
 \r
-    Mailbox = (DEBUG_AGENT_MAILBOX *) GetMailboxPointerInIdtEntry ();\r
-    Mailbox->DebugPortHandle = (UINT64)(UINT32)(Mailbox->DebugPortHandle + DebugAgentContext->StackMigrateOffset);\r
-    Mailbox->DebugFlag.MemoryReady = 1;\r
+    InitializeDebugTimer ();\r
+    //\r
+    // Update IDT entry to save the location pointer saved mailbox pointer\r
+    //\r
+    SetLocationSavedMailboxPointerInIdtEntry (MailboxLocationPointer);\r
+    //\r
+    // Register for a callback once memory has been initialized.\r
+    // If memery has been ready, the callback funtion will be invoked immediately\r
+    //\r
+    Status = PeiServicesNotifyPpi (&mMemoryDiscoveredNotifyList[0]);\r
+    ASSERT_EFI_ERROR (Status);\r
+    //\r
+    // Set HOB check flag if memory has not been ready yet\r
+    //\r
+    if (GetDebugFlag (DEBUG_AGENT_FLAG_MEMORY_READY) == 0) {\r
+      SetDebugFlag (DEBUG_AGENT_FLAG_CHECK_MAILBOX_IN_HOB, 1);\r
+    }\r
 \r
-    Mailbox = BuildMailboxHob ();\r
-    Mailbox = (DEBUG_AGENT_MAILBOX *) ((UINTN) Mailbox + DebugAgentContext->HeapMigrateOffset);\r
+    Phase2Context.Context  = Context;\r
+    Phase2Context.Function = Function;\r
+    DebugPortInitialize ((VOID *) &Phase2Context, InitializeDebugAgentPhase2);\r
 \r
-    SetMailboxPointerInIdtEntry ((VOID *) Mailbox);\r
+    FindAndReportModuleImageInfo (4);\r
 \r
-    EnableInterrupts ();\r
+    break;\r
 \r
+  case DEBUG_AGENT_INIT_THUNK_PEI_IA32TOX64:\r
+    if (Context == NULL) {\r
+      DEBUG ((EFI_D_ERROR, "DebugAgent: Input parameter Context cannot be NULL!\n"));\r
+      CpuDeadLoop ();\r
+    } else {\r
+      Ia32Idtr =  (IA32_DESCRIPTOR *) Context;\r
+      Ia32IdtEntry = (IA32_IDT_ENTRY *)(Ia32Idtr->Base);\r
+      MailboxLocationPointer = (UINT64 *) (UINTN) (Ia32IdtEntry[DEBUG_MAILBOX_VECTOR].Bits.OffsetLow +\r
+                                                (Ia32IdtEntry[DEBUG_MAILBOX_VECTOR].Bits.OffsetHigh << 16));\r
+      Mailbox = (DEBUG_AGENT_MAILBOX *) (UINTN)(*MailboxLocationPointer);\r
+      VerifyMailboxChecksum (Mailbox);\r
+\r
+      DebugPortHandle = (UINT64) (UINTN)DebugPortInitialize ((VOID *)(UINTN)Mailbox->DebugPortHandle, NULL);\r
+      UpdateMailboxContent (Mailbox, DEBUG_MAILBOX_DEBUG_PORT_HANDLE_INDEX, DebugPortHandle);\r
+      //\r
+      // Set up IDT entries\r
+      //\r
+      InitializeDebugIdt ();\r
+      //\r
+      // Update IDT entry to save location pointer saved the mailbox pointer\r
+      //\r
+      SetLocationSavedMailboxPointerInIdtEntry (MailboxLocationPointer);\r
+\r
+      FindAndReportModuleImageInfo (4);\r
+    }\r
     break;\r
 \r
   default:\r
-\r
     //\r
     // Only DEBUG_AGENT_INIT_PREMEM_SEC and DEBUG_AGENT_INIT_POSTMEM_SEC are allowed for this \r
     // Debug Agent library instance.\r
@@ -294,6 +483,8 @@ InitializeDebugAgent (
 \r
   }\r
 \r
+  EnableInterrupts ();\r
+\r
   //\r
   // If Function is not NULL, invoke it always whatever debug agent was initialized sucesssfully or not.\r
   //\r
@@ -319,11 +510,22 @@ InitializeDebugAgentPhase2 (
   )\r
 {\r
   DEBUG_AGENT_PHASE2_CONTEXT *Phase2Context;\r
+  UINT64                     *MailboxLocation;\r
   DEBUG_AGENT_MAILBOX        *Mailbox;\r
   EFI_SEC_PEI_HAND_OFF       *SecCoreData;\r
+  UINT16                     BufferSize;\r
+  UINT64                     NewDebugPortHandle;\r
 \r
-  Mailbox = GetMailboxPointerInIdtEntry ();\r
-  Mailbox->DebugPortHandle = (UINT64) (UINTN)DebugPortHandle;\r
+  Phase2Context = (DEBUG_AGENT_PHASE2_CONTEXT *) Context;\r
+  MailboxLocation = GetLocationSavedMailboxPointerInIdtEntry ();\r
+  Mailbox = (DEBUG_AGENT_MAILBOX *)(UINTN)(*MailboxLocation);\r
+  BufferSize = PcdGet16(PcdDebugPortHandleBufferSize);\r
+  if (Phase2Context->Function == NULL && DebugPortHandle != NULL && BufferSize != 0) {\r
+    NewDebugPortHandle = (UINT64)(UINTN)AllocateCopyPool (BufferSize, DebugPortHandle);\r
+  } else {\r
+    NewDebugPortHandle = (UINT64)(UINTN)DebugPortHandle;\r
+  }\r
+  UpdateMailboxContent (Mailbox, DEBUG_MAILBOX_DEBUG_PORT_HANDLE_INDEX, NewDebugPortHandle);\r
 \r
   //\r
   // Trigger one software interrupt to inform HOST\r
@@ -334,9 +536,9 @@ InitializeDebugAgentPhase2 (
   // If Temporary RAM region is below 128 MB, then send message to \r
   // host to disable low memory filtering.\r
   //\r
-  Phase2Context = (DEBUG_AGENT_PHASE2_CONTEXT *) Context;\r
   SecCoreData = (EFI_SEC_PEI_HAND_OFF *)Phase2Context->Context;\r
   if ((UINTN)SecCoreData->TemporaryRamBase < BASE_128MB && IsHostAttached ()) {\r
+    SetDebugFlag (DEBUG_AGENT_FLAG_MEMORY_READY, 1);\r
     TriggerSoftInterrupt (MEMORY_READY_SIGNATURE);\r
   }\r
 \r
index 9ca5e87fb3f4d14edad3fa24040b854f0be2977f..68bfbf7cab12f4f38354acd3c7c1c061f7ef1a10 100644 (file)
@@ -1,7 +1,7 @@
 /** @file\r
   Header file for Sec Core Debug Agent Library instance.\r
 \r
-  Copyright (c) 2010, Intel Corporation. All rights reserved.<BR>\r
+  Copyright (c) 2010 - 2013, 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
@@ -16,7 +16,9 @@
 #define _SEC_CORE_DEBUG_AGENT_LIB_H_\r
 \r
 #include <PiPei.h>\r
-\r
+#include <Ppi/MemoryDiscovered.h>\r
+#include <Library/PeiServicesLib.h>\r
+#include <Library/MemoryAllocationLib.h>\r
 #include "DebugAgent.h"\r
 \r
 typedef struct {\r
@@ -24,5 +26,39 @@ typedef struct {
   DEBUG_AGENT_CONTINUE    Function;\r
 } DEBUG_AGENT_PHASE2_CONTEXT;\r
 \r
+/**\r
+  Caller provided function to be invoked at the end of DebugPortInitialize().\r
+\r
+  Refer to the descrption for DebugPortInitialize() for more details.\r
+\r
+  @param[in] Context           The first input argument of DebugPortInitialize().\r
+  @param[in] DebugPortHandle   Debug port handle created by Debug Communication Libary.\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+InitializeDebugAgentPhase2 (\r
+  IN VOID                  *Context,\r
+  IN DEBUG_PORT_HANDLE     DebugPortHandle\r
+  );\r
+\r
+/**\r
+  Debug Agent provided notify callback function on Memory Discovered PPI.\r
+\r
+  @param[in] PeiServices      Indirect reference to the PEI Services Table.\r
+  @param[in] NotifyDescriptor Address of the notification descriptor data structure.\r
+  @param[in] Ppi              Address of the PPI that was installed.\r
+\r
+  @retval EFI_SUCCESS If the function completed successfully.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+DebugAgentCallbackMemoryDiscoveredPpi (\r
+  IN EFI_PEI_SERVICES                     **PeiServices,\r
+  IN EFI_PEI_NOTIFY_DESCRIPTOR            *NotifyDescriptor,\r
+  IN VOID                                 *Ppi\r
+  );\r
+\r
 #endif\r
 \r
index 577a635a47d03fc08813f600d4685d54aff19753..b81fc16d17a62eda3758964ca0c22900f0f13d19 100644 (file)
@@ -1,7 +1,7 @@
 ## @file\r
 #  Debug Agent library instance for SEC Core and PEI modules.\r
 #\r
-#  Copyright (c) 2010 - 2012, Intel Corporation. All rights reserved.<BR>\r
+#  Copyright (c) 2010 - 2013, Intel Corporation. All rights reserved.<BR>\r
 #\r
 #  This program and the accompanying materials\r
 #  are licensed and made available under the terms and conditions of the BSD License\r
   DebugLib\r
   TimerLib\r
   PrintLib\r
+  PeiServicesLib\r
+  MemoryAllocationLib\r
+  PeCoffGetEntryPointLib\r
+  PeCoffExtraActionLib\r
+\r
+[Ppis]\r
+  gEfiPeiMemoryDiscoveredPpiGuid\r
 \r
 [Guids]\r
   gEfiDebugAgentGuid                            ## PRODUCES ## HOB\r
@@ -77,4 +84,5 @@
 [Pcd]\r
   gEfiMdePkgTokenSpaceGuid.PcdFSBClock                                  ## CONSUMES\r
   gEfiSourceLevelDebugPkgTokenSpaceGuid.PcdExceptionsIgnoredByDebugger  ## CONSUMES\r
+  gEfiSourceLevelDebugPkgTokenSpaceGuid.PcdDebugPortHandleBufferSize    ## CONSUMES\r
 \r
index 3326c0a05fb4c0bae0d9c359b96722c8065ce417..145fee0fa5d188bbbd89717a021fec9fefb1b3e9 100644 (file)
@@ -1,7 +1,7 @@
 /** @file\r
   Debug Agent library implementition.\r
 \r
-  Copyright (c) 2010 - 2012, Intel Corporation. All rights reserved.<BR>\r
+  Copyright (c) 2010 - 2013, 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
 DEBUG_AGENT_MAILBOX         *mMailboxPointer = NULL;\r
 DEBUG_AGENT_MAILBOX         mLocalMailbox;\r
 UINTN                       mSavedDebugRegisters[6];\r
-CONST BOOLEAN               MultiProcessorDebugSupport = FALSE;\r
+IA32_IDT_GATE_DESCRIPTOR    mIdtEntryTable[33];\r
+BOOLEAN                     mSkipBreakpoint = FALSE;\r
+\r
+CHAR8 mWarningMsgIgnoreSmmEntryBreak[] = "Ignore smmentrybreak setting for SMI issued during DXE debugging!\r\n";\r
+\r
+/**\r
+  Check if debug agent support multi-processor.\r
+\r
+  @retval TRUE    Multi-processor is supported.\r
+  @retval FALSE   Multi-processor is not supported.\r
+\r
+**/\r
+BOOLEAN\r
+MultiProcessorDebugSupport (\r
+  VOID\r
+  )\r
+{\r
+  return FALSE;\r
+}\r
 \r
 /**\r
   Read the Attach/Break-in symbols from the debug port.\r
@@ -41,6 +59,32 @@ DebugReadBreakSymbol (
   return EFI_NOT_FOUND;\r
 }\r
 \r
+/**\r
+  Get the pointer to Mailbox from the GUIDed HOB.\r
+\r
+  @return Pointer to Mailbox.\r
+\r
+**/\r
+DEBUG_AGENT_MAILBOX *\r
+GetMailboxFromHob (\r
+  VOID\r
+  )\r
+{\r
+  EFI_HOB_GUID_TYPE        *GuidHob;\r
+  UINT64                   *MailboxLocation;  \r
+  DEBUG_AGENT_MAILBOX      *Mailbox;\r
+\r
+  GuidHob = GetFirstGuidHob (&gEfiDebugAgentGuid);\r
+  if (GuidHob == NULL) {\r
+    return NULL;\r
+  }\r
+  MailboxLocation = (UINT64 *) (GET_GUID_HOB_DATA(GuidHob));\r
+  Mailbox = (DEBUG_AGENT_MAILBOX *)(UINTN)(*MailboxLocation);\r
+  VerifyMailboxChecksum (Mailbox);\r
+  \r
+  return Mailbox;\r
+}\r
+\r
 /**\r
   Get Debug Agent Mailbox pointer.\r
 \r
@@ -52,6 +96,7 @@ GetMailboxPointer (
   VOID\r
   )\r
 {\r
+  VerifyMailboxChecksum (mMailboxPointer);\r
   return mMailboxPointer;\r
 }\r
 \r
@@ -66,7 +111,7 @@ GetDebugPortHandle (
   VOID\r
   )\r
 {\r
-  return (DEBUG_PORT_HANDLE) (UINTN)(mMailboxPointer->DebugPortHandle);\r
+  return (DEBUG_PORT_HANDLE) (UINTN)(GetMailboxPointer()->DebugPortHandle);\r
 }\r
 \r
 /**\r
@@ -134,16 +179,76 @@ InitializeDebugAgent (
   IN DEBUG_AGENT_CONTINUE  Function  OPTIONAL\r
   )\r
 {\r
-  EFI_STATUS               Status;\r
-  UINT64                   DebugPortHandle;\r
+  EFI_STATUS                    Status;\r
+  UINT64                        DebugPortHandle;\r
+  IA32_IDT_GATE_DESCRIPTOR      IdtEntry[33];\r
+  IA32_DESCRIPTOR               IdtDescriptor;\r
+  IA32_DESCRIPTOR               *Ia32Idtr;\r
+  IA32_IDT_ENTRY                *Ia32IdtEntry;\r
+  IA32_DESCRIPTOR               Idtr;\r
+  UINT16                        IdtEntryCount;\r
+  DEBUG_AGENT_MAILBOX           *Mailbox;\r
+  UINT64                        *MailboxLocation;\r
 \r
   switch (InitFlag) {\r
   case DEBUG_AGENT_INIT_SMM:\r
-    Status = EfiGetSystemConfigurationTable (&gEfiDebugAgentGuid, (VOID **) &mMailboxPointer);\r
-    if (EFI_ERROR (Status) || mMailboxPointer == NULL) {\r
-      ZeroMem (&mLocalMailbox, sizeof (DEBUG_AGENT_MAILBOX));\r
-      mMailboxPointer = &mLocalMailbox;\r
+    //\r
+    // Check if Debug Agent initialized in DXE phase\r
+    //\r
+    Status = EfiGetSystemConfigurationTable (&gEfiDebugAgentGuid, (VOID **) &Mailbox);\r
+    if (Status == EFI_SUCCESS && Mailbox != NULL) {\r
+      VerifyMailboxChecksum (Mailbox);\r
+      mMailboxPointer = Mailbox;\r
+      break;\r
     }\r
+    //\r
+    // Check if Debug Agent initialized in SEC/PEI phase\r
+    //\r
+    Mailbox = GetMailboxFromHob (); \r
+    if (Mailbox != NULL) {\r
+      mMailboxPointer = Mailbox;\r
+      break;\r
+    }\r
+    //\r
+    // Debug Agent was not initialized before, uset the local mailbox.\r
+    //\r
+    ZeroMem (&mLocalMailbox, sizeof (DEBUG_AGENT_MAILBOX));\r
+    Mailbox = &mLocalMailbox;\r
+    //\r
+    // Save original IDT entries\r
+    //\r
+    AsmReadIdtr (&IdtDescriptor);      \r
+    CopyMem (&IdtEntry, (VOID *)IdtDescriptor.Base, 33 * sizeof(IA32_IDT_GATE_DESCRIPTOR));\r
+    //\r
+    // Initialized Debug Agent\r
+    //\r
+    InitializeDebugIdt ();\r
+    DebugPortHandle = (UINT64) (UINTN)DebugPortInitialize ((DEBUG_PORT_HANDLE) (UINTN)Mailbox->DebugPortHandle, NULL);\r
+    UpdateMailboxContent (Mailbox, DEBUG_MAILBOX_DEBUG_PORT_HANDLE_INDEX, DebugPortHandle);\r
+    mMailboxPointer = Mailbox;\r
+    //\r
+    // Trigger one software interrupt to inform HOST\r
+    //\r
+    TriggerSoftInterrupt (SYSTEM_RESET_SIGNATURE);\r
+\r
+    SetDebugFlag (DEBUG_AGENT_FLAG_MEMORY_READY, 1);\r
+    //\r
+    // Memory has been ready\r
+    //\r
+    if (IsHostAttached ()) {\r
+      //\r
+      // Trigger one software interrupt to inform HOST\r
+      //\r
+      TriggerSoftInterrupt (MEMORY_READY_SIGNATURE);\r
+    }\r
+    //\r
+    // Find and report PE/COFF image info to HOST\r
+    //  \r
+    FindAndReportModuleImageInfo (SIZE_4KB);\r
+    //\r
+    // Restore saved IDT entries\r
+    //     \r
+    CopyMem ((VOID *)IdtDescriptor.Base, &IdtEntry, 33 * sizeof(IA32_IDT_GATE_DESCRIPTOR));\r
 \r
     break;\r
 \r
@@ -151,14 +256,24 @@ InitializeDebugAgent (
     SaveDebugRegister ();\r
     InitializeDebugIdt ();\r
 \r
-    if (mMailboxPointer != NULL) {\r
+    Mailbox = GetMailboxPointer ();\r
+    if (GetDebugFlag (DEBUG_AGENT_FLAG_AGENT_IN_PROGRESS) == 1) {\r
       //\r
-      // Initialize debug communication port\r
+      // If Debug Agent has been communicaton state with HOST, we need skip\r
+      // any break points set in SMM, set Skip Breakpoint flag\r
       //\r
-      DebugPortHandle = (UINT64) (UINTN)DebugPortInitialize ((DEBUG_PORT_HANDLE) (UINTN)mMailboxPointer->DebugPortHandle, NULL);\r
-      mMailboxPointer->DebugPortHandle = DebugPortHandle;\r
-\r
-      if (mMailboxPointer->DebugFlag.BreakOnNextSmi == 1) {\r
+      mSkipBreakpoint = TRUE;\r
+    }\r
+    if (GetDebugFlag (DEBUG_AGENT_FLAG_BREAK_ON_NEXT_SMI) == 1) {\r
+      if (mSkipBreakpoint) {\r
+        //\r
+        // Print warning message if ignore smm entry break\r
+        //\r
+        DebugPortWriteBuffer ((DEBUG_PORT_HANDLE) (UINTN)Mailbox->DebugPortHandle,\r
+                               (UINT8 *)mWarningMsgIgnoreSmmEntryBreak,\r
+                               AsciiStrLen (mWarningMsgIgnoreSmmEntryBreak)\r
+                               );\r
+      } else {\r
         //\r
         // If SMM entry break is set, SMM code will be break at here.\r
         //\r
@@ -168,8 +283,56 @@ InitializeDebugAgent (
     break;\r
 \r
   case DEBUG_AGENT_INIT_EXIT_SMI:\r
+    Mailbox = GetMailboxPointer ();\r
+    //\r
+    // Clear Skip Breakpoint flag\r
+    //\r
+    mSkipBreakpoint = FALSE;\r
     RestoreDebugRegister ();\r
     break;\r
+\r
+  case DEBUG_AGENT_INIT_THUNK_PEI_IA32TOX64:\r
+    if (Context == NULL) {\r
+      DEBUG ((EFI_D_ERROR, "DebugAgent: Input parameter Context cannot be NULL!\n"));\r
+      CpuDeadLoop ();\r
+    } else {\r
+      Ia32Idtr =  (IA32_DESCRIPTOR *) Context;\r
+      Ia32IdtEntry = (IA32_IDT_ENTRY *)(Ia32Idtr->Base);\r
+      MailboxLocation = (UINT64 *) (UINTN) (Ia32IdtEntry[DEBUG_MAILBOX_VECTOR].Bits.OffsetLow + \r
+                                           (Ia32IdtEntry[DEBUG_MAILBOX_VECTOR].Bits.OffsetHigh << 16));\r
+      mMailboxPointer = (DEBUG_AGENT_MAILBOX *)(UINTN)(*MailboxLocation);\r
+      VerifyMailboxChecksum (mMailboxPointer);\r
+      //\r
+      // Get original IDT address and size.\r
+      //\r
+      AsmReadIdtr ((IA32_DESCRIPTOR *) &Idtr);\r
+      IdtEntryCount = (UINT16) ((Idtr.Limit + 1) / sizeof (IA32_IDT_GATE_DESCRIPTOR));\r
+      if (IdtEntryCount < 33) {\r
+        Idtr.Limit = (UINT16) (sizeof (IA32_IDT_GATE_DESCRIPTOR) * 33 - 1);\r
+        Idtr.Base  = (UINTN) &mIdtEntryTable;\r
+        ZeroMem (&mIdtEntryTable, Idtr.Limit + 1);\r
+        AsmWriteIdtr ((IA32_DESCRIPTOR *) &Idtr);\r
+      }\r
+\r
+      InitializeDebugIdt ();\r
+      //\r
+      // Initialize Debug Timer hardware and enable interrupt.\r
+      //\r
+      InitializeDebugTimer ();\r
+      EnableInterrupts ();\r
+\r
+      FindAndReportModuleImageInfo (SIZE_4KB);\r
+    }\r
+    break;\r
+\r
+  default:\r
+    //\r
+    // Only DEBUG_AGENT_INIT_PREMEM_SEC and DEBUG_AGENT_INIT_POSTMEM_SEC are allowed for this \r
+    // Debug Agent library instance.\r
+    //\r
+    DEBUG ((EFI_D_ERROR, "Debug Agent: The InitFlag value is not allowed!\n"));\r
+    CpuDeadLoop ();\r
+    break;    \r
   }\r
 }\r
 \r
index f62d9975cf55603d73088f006f981b9e32a31ff0..9ed314d407c47fbf1590d583cc92e4564ee06719 100644 (file)
@@ -1,7 +1,7 @@
 ## @file\r
 #  Debug Agent library instance for SMM modules.\r
 #\r
-#  Copyright (c) 2010 - 2012, Intel Corporation. All rights reserved.<BR>\r
+#  Copyright (c) 2010 - 2013, Intel Corporation. All rights reserved.<BR>\r
 #\r
 #  This program and the accompanying materials\r
 #  are licensed and made available under the terms and conditions of the BSD License\r
@@ -15,7 +15,7 @@
 \r
 [Defines]\r
   INF_VERSION                    = 0x00010005\r
-  BASE_NAME                      = SecDebugAgentLib\r
+  BASE_NAME                      = SmmDebugAgentLib\r
   FILE_GUID                      = CB07D74C-598F-4268-A5D1-644FB4A481E8\r
   MODULE_TYPE                    = DXE_SMM_DRIVER\r
   VERSION_STRING                 = 0.7\r
   LocalApicLib\r
   TimerLib\r
   PrintLib\r
+  PeCoffExtraActionLib\r
+  PeCoffGetEntryPointLib\r
 \r
 [Guids]\r
   gEfiDebugAgentGuid                            ## CONSUMES ## Configuration Table\r
 \r
 [Pcd]\r
-  gEfiMdePkgTokenSpaceGuid.PcdFSBClock                                  ## CONSUMES\r
-  gEfiSourceLevelDebugPkgTokenSpaceGuid.PcdExceptionsIgnoredByDebugger  ## CONSUMES\r
+  gEfiMdePkgTokenSpaceGuid.PcdFSBClock                                             ## CONSUMES\r
+  ## Skip Page Fault exception (14) by default in SMM\r
+  gEfiSourceLevelDebugPkgTokenSpaceGuid.PcdExceptionsIgnoredByDebugger|0x00004000  ## CONSUMES\r
 \r
index dd88e7d6938013cac1b65fd9045115f17b4d88b7..95232165919e0cf8fd99da03a1d30498d8cd81b0 100644 (file)
@@ -1,7 +1,7 @@
 /** @file\r
   Debug Port Library implementation based on serial port.\r
 \r
-  Copyright (c) 2010 - 2011, Intel Corporation. All rights reserved.<BR>\r
+  Copyright (c) 2010 - 2013, Intel Corporation. All rights reserved.<BR>\r
   This program and the accompanying materials\r
   are licensed and made available under the terms and conditions of the BSD License\r
   which accompanies this distribution.  The full text of the license may be found at\r
 #include <Library/SerialPortLib.h>\r
 #include <Library/TimerLib.h>\r
 #include <Library/DebugLib.h>\r
+#include <Library/BaseLib.h>\r
+#include <Library/BaseMemoryLib.h>\r
+\r
+#pragma pack(1)\r
+//\r
+// The internal data structure of DEBUG_PORT_HANDLE, which stores some\r
+// important datum which are used across various phases.\r
+//\r
+typedef struct _SERIAL_DEBUG_PORT_HANDLE{\r
+  //\r
+  // Timter settings\r
+  //\r
+  UINT64       TimerFrequency;\r
+  UINT64       TimerCycle;\r
+  BOOLEAN      TimerCountDown;\r
+} SERIAL_DEBUG_PORT_HANDLE;\r
+#pragma pack()\r
+\r
+//\r
+// The global variable which can be used after memory is ready.\r
+//\r
+SERIAL_DEBUG_PORT_HANDLE     mSerialDebugPortHandle;\r
+\r
+/**\r
+  Check if the timer is timeout.\r
+  \r
+  @param[in] SerialDebugPortHandle  Pointer to Serial Debug port handle\r
+  @param[in] Timer                  The start timer from the begin.\r
+  @param[in] TimeoutTicker          Ticker number need time out.\r
+\r
+  @return TRUE  Timer time out occurs.\r
+  @retval FALSE Timer does not time out.\r
+\r
+**/\r
+BOOLEAN\r
+IsTimerTimeout (\r
+  IN SERIAL_DEBUG_PORT_HANDLE   *SerialDebugPortHandle,\r
+  IN UINT64                     Timer,\r
+  IN UINT64                     TimeoutTicker\r
+  )\r
+{\r
+  UINT64  CurrentTimer;\r
+  UINT64  Delta;\r
+\r
+  CurrentTimer = GetPerformanceCounter ();\r
+\r
+  if (SerialDebugPortHandle->TimerCountDown) {\r
+    //\r
+    // The timer counter counts down.  Check for roll over condition.\r
+    //\r
+    if (CurrentTimer < Timer) {\r
+      Delta = Timer - CurrentTimer;\r
+    } else {\r
+      //\r
+      // Handle one roll-over. \r
+      //\r
+      Delta = SerialDebugPortHandle->TimerCycle - (CurrentTimer - Timer);\r
+    }\r
+  } else {\r
+    //\r
+    // The timer counter counts up.  Check for roll over condition.\r
+    //\r
+    if (CurrentTimer > Timer) {\r
+      Delta = CurrentTimer - Timer;\r
+    } else {\r
+      //\r
+      // Handle one roll-over. \r
+      //\r
+      Delta = SerialDebugPortHandle->TimerCycle - (Timer - CurrentTimer);\r
+    }\r
+  }\r
\r
+  return (BOOLEAN) (Delta >= TimeoutTicker);\r
+}\r
 \r
 /**\r
   Initialize the debug port.\r
@@ -62,7 +136,42 @@ DebugPortInitialize (
   IN DEBUG_PORT_CONTINUE  Function\r
   )\r
 {\r
-  RETURN_STATUS      Status;\r
+  RETURN_STATUS              Status;\r
+  SERIAL_DEBUG_PORT_HANDLE   Handle;\r
+  SERIAL_DEBUG_PORT_HANDLE   *SerialDebugPortHandle;\r
+  UINT64                     TimerStartValue;\r
+  UINT64                     TimerEndValue;\r
+\r
+  //\r
+  // Validate the PCD PcdDebugPortHandleBufferSize value \r
+  //\r
+  ASSERT (PcdGet16 (PcdDebugPortHandleBufferSize) == sizeof (SERIAL_DEBUG_PORT_HANDLE));\r
+\r
+  if (Context != NULL && Function == NULL) {\r
+    SerialDebugPortHandle = (SERIAL_DEBUG_PORT_HANDLE *)Context;\r
+  } else {\r
+    ZeroMem (&Handle, sizeof (SERIAL_DEBUG_PORT_HANDLE));\r
+    SerialDebugPortHandle = &Handle;\r
+  }\r
+  SerialDebugPortHandle->TimerFrequency = GetPerformanceCounterProperties (\r
+                                            &TimerStartValue,\r
+                                            &TimerEndValue\r
+                                            );\r
+  DEBUG ((EFI_D_INFO, "Serial Debug Port: TimerFrequency  = 0x%lx\n", SerialDebugPortHandle->TimerFrequency)); \r
+  DEBUG ((EFI_D_INFO, "Serial Debug Port: TimerStartValue = 0x%lx\n", TimerStartValue)); \r
+  DEBUG ((EFI_D_INFO, "Serial Debug Port: TimerEndValue   = 0x%lx\n", TimerEndValue)); \r
+\r
+  if (TimerEndValue < TimerStartValue) {\r
+    SerialDebugPortHandle->TimerCountDown = TRUE;\r
+    SerialDebugPortHandle->TimerCycle     = TimerStartValue - TimerEndValue;\r
+  } else {\r
+    SerialDebugPortHandle->TimerCountDown = FALSE;\r
+    SerialDebugPortHandle->TimerCycle     = TimerEndValue - TimerStartValue;\r
+  }  \r
+\r
+  if (Function == NULL && Context != NULL) {\r
+    return (DEBUG_PORT_HANDLE *) Context;\r
+  }\r
 \r
   Status = SerialPortInitialize ();\r
   if (RETURN_ERROR(Status)) {\r
@@ -70,10 +179,12 @@ DebugPortInitialize (
   }\r
 \r
   if (Function != NULL) {\r
-    Function (Context, NULL);\r
+    Function (Context, SerialDebugPortHandle);\r
+  } else {\r
+    CopyMem(&mSerialDebugPortHandle, SerialDebugPortHandle, sizeof (SERIAL_DEBUG_PORT_HANDLE));\r
   }\r
 \r
-  return NULL;\r
+  return (DEBUG_PORT_HANDLE)(UINTN)&mSerialDebugPortHandle;\r
 }\r
 \r
 /**\r
@@ -102,25 +213,62 @@ DebugPortReadBuffer (
   IN UINTN                 Timeout\r
   )\r
 {\r
-  UINTN                Index;\r
-  INTN                 Elapsed;\r
-\r
-  for (Index = 0; Index < NumberOfBytes; Index ++) {\r
-    Elapsed = (INTN) Timeout;\r
-    while (TRUE) {\r
-      if (SerialPortPoll () || Timeout == 0) {\r
-        SerialPortRead (Buffer + Index, 1);\r
-        break;\r
-      }\r
-      MicroSecondDelay (1000);\r
-      Elapsed -= 1000;\r
-      if (Elapsed < 0) {\r
+  SERIAL_DEBUG_PORT_HANDLE *SerialDebugPortHandle;\r
+  UINTN                    Index;\r
+  UINT64                   Begin;\r
+  UINT64                   TimeoutTicker;\r
+  UINT64                   TimerRound;\r
+  \r
+  //\r
+  // If Handle is NULL, it means memory is ready for use.\r
+  // Use global variable to store handle value.\r
+  //\r
+  if (Handle == NULL) {\r
+    SerialDebugPortHandle = &mSerialDebugPortHandle;\r
+  } else {\r
+    SerialDebugPortHandle = (SERIAL_DEBUG_PORT_HANDLE *)Handle;\r
+  }\r
+\r
+  Begin         = 0;\r
+  TimeoutTicker = 0;  \r
+  TimerRound    = 0;\r
+  if (Timeout != 0) {\r
+    Begin = GetPerformanceCounter ();\r
+    TimeoutTicker = DivU64x32 (\r
+                      MultU64x64 (\r
+                        SerialDebugPortHandle->TimerFrequency,\r
+                        Timeout\r
+                        ),\r
+                      1000000u\r
+                      );\r
+    TimerRound = DivU64x64Remainder (\r
+                   TimeoutTicker,\r
+                   DivU64x32 (SerialDebugPortHandle->TimerCycle, 2),\r
+                   &TimeoutTicker\r
+                   );\r
+  }\r
+  Index = 0;\r
+  while (Index < NumberOfBytes) {\r
+    if (SerialPortPoll () || Timeout == 0) {\r
+      SerialPortRead (Buffer + Index, 1);\r
+      Index ++; \r
+      continue;\r
+    }\r
+    if (TimerRound == 0) {\r
+      if (IsTimerTimeout (SerialDebugPortHandle, Begin, TimeoutTicker)) {\r
+        //\r
+        // If time out occurs.\r
+        //\r
         return 0;\r
       }\r
+    } else {\r
+      if (IsTimerTimeout (SerialDebugPortHandle, Begin, DivU64x32 (SerialDebugPortHandle->TimerCycle, 2))) {\r
+        TimerRound --;\r
+      }\r
     }\r
   }\r
 \r
-  return NumberOfBytes;\r
+  return Index;\r
 }\r
 \r
 /**\r
index 6d36cefd7476565db201c391d15a8385491bdcc1..6ee5ddccee4164ff8908fdf2729a6d2713323932 100644 (file)
@@ -1,7 +1,7 @@
 ## @file\r
 #  Debug Communication Library instance based on serila port.\r
 #\r
-#  Copyright (c) 2010 - 2011, Intel Corporation. All rights reserved.<BR>\r
+#  Copyright (c) 2010 - 2013, Intel Corporation. All rights reserved.<BR>\r
 #\r
 #  This program and the accompanying materials\r
 #  are licensed and made available under the terms and conditions of the BSD License\r
   SerialPortLib\r
   TimerLib\r
   DebugLib\r
-  \r
+  BaseMemoryLib\r
+  BaseLib\r
+\r
+[PCD]\r
+  ## The value of data buffer size used for Serial debug port handle.\r
+  ## It should be equal to sizeof (SERIAL_DEBUG_PORT_HANDLE).\r
+  gEfiSourceLevelDebugPkgTokenSpaceGuid.PcdDebugPortHandleBufferSize|17\r
index aafd52d3c3944975502f5f526f1a1a991c88f8ae..c08d45b7871fe4cecc6e8b6bc1d23d14911e8367 100644 (file)
@@ -1,7 +1,7 @@
 /** @file\r
   Debug Port Library implementation based on usb debug port.\r
 \r
-  Copyright (c) 2010 - 2011, Intel Corporation. All rights reserved.<BR>\r
+  Copyright (c) 2010 - 2013, 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
@@ -147,6 +147,12 @@ typedef struct _USB_DEBUG_PORT_HANDLE{
   // The data buffer. Maximum length is 8 bytes.\r
   //\r
   UINT8        Data[8];\r
+  //\r
+  // Timter settings\r
+  //\r
+  UINT64       TimerFrequency;\r
+  UINT64       TimerCycle;\r
+  BOOLEAN      TimerCountDown;\r
 } USB_DEBUG_PORT_HANDLE;\r
 #pragma pack()\r
 \r
@@ -155,6 +161,58 @@ typedef struct _USB_DEBUG_PORT_HANDLE{
 //\r
 USB_DEBUG_PORT_HANDLE     mUsbDebugPortHandle;\r
 \r
+/**\r
+  Check if the timer is timeout.\r
+  \r
+  @param[in] UsbDebugPortHandle  Pointer to USB Debug port handle\r
+  @param[in] Timer               The start timer from the begin.\r
+  @param[in] TimeoutTicker       Ticker number need time out.\r
+\r
+  @return TRUE  Timer time out occurs.\r
+  @retval FALSE Timer does not time out.\r
+\r
+**/\r
+BOOLEAN\r
+IsTimerTimeout (\r
+  IN USB_DEBUG_PORT_HANDLE   *UsbDebugPortHandle,\r
+  IN UINT64                  Timer,\r
+  IN UINT64                  TimeoutTicker\r
+  )\r
+{\r
+  UINT64  CurrentTimer;\r
+  UINT64  Delta;\r
+\r
+  CurrentTimer = GetPerformanceCounter ();\r
+\r
+  if (UsbDebugPortHandle->TimerCountDown) {\r
+    //\r
+    // The timer counter counts down.  Check for roll over condition.\r
+    //\r
+    if (CurrentTimer < Timer) {\r
+      Delta = Timer - CurrentTimer;\r
+    } else {\r
+      //\r
+      // Handle one roll-over. \r
+      //\r
+      Delta = UsbDebugPortHandle->TimerCycle - (CurrentTimer - Timer);\r
+    }\r
+  } else {\r
+    //\r
+    // The timer counter counts up.  Check for roll over condition.\r
+    //\r
+    if (CurrentTimer > Timer) {\r
+      Delta = CurrentTimer - Timer;\r
+    } else {\r
+      //\r
+      // Handle one roll-over. \r
+      //\r
+      Delta = UsbDebugPortHandle->TimerCycle - (Timer - CurrentTimer);\r
+    }\r
+  }\r
\r
+  return (BOOLEAN) (Delta >= TimeoutTicker);\r
+}\r
+\r
 /**\r
   Calculate the usb debug port bar address.\r
 \r
@@ -617,28 +675,21 @@ InitializeUsbDebugHardware (
   if (((MmioRead32((UINTN)&UsbDebugPortRegister->ControlStatus) & (USB_DEBUG_PORT_OWNER | USB_DEBUG_PORT_IN_USE))\r
        != (USB_DEBUG_PORT_OWNER | USB_DEBUG_PORT_IN_USE)) || (Handle->Initialized == USBDBG_RESET)) {\r
     //\r
-    // If the host controller is not halted, then halt it.\r
-    //\r
-    if ((MmioRead32((UINTN)UsbStatus) & BIT12) == 0) {\r
-      MmioAnd32((UINTN)UsbCmd, (UINT32)~BIT0);\r
-      while ((MmioRead32((UINTN)UsbStatus) & BIT12) == 0);\r
-    }\r
-    //\r
-    // reset the host controller.\r
-    //\r
-    MmioOr32((UINTN)UsbCmd, BIT1);\r
+    // If the host controller is halted, then reset and restart it.\r
     //\r
-    // ensure that the host controller is reset.\r
-    //\r
-    while (MmioRead32((UINTN)UsbCmd) & BIT1);\r
+    if ((MmioRead32((UINTN)UsbStatus) & BIT12) != 0) {\r
+      //\r
+      // reset the host controller.\r
+      //\r
+      MmioOr32((UINTN)UsbCmd, BIT1);\r
+      //\r
+      // ensure that the host controller is reset.\r
+      //\r
+      while ((MmioRead32((UINTN)UsbCmd) & BIT1) != 0);\r
 \r
-    //\r
-    // Start the host controller if it's not running\r
-    //\r
-    if (MmioRead32((UINTN)UsbStatus) & BIT12) {\r
       MmioOr32((UINTN)UsbCmd, BIT0);\r
       // ensure that the host controller is started (HALTED bit must be cleared)\r
-      while (MmioRead32((UINTN)UsbStatus) & BIT12);\r
+      while ((MmioRead32((UINTN)UsbStatus) & BIT12) != 0);\r
     }\r
 \r
     //\r
@@ -780,6 +831,9 @@ DebugPortReadBuffer (
   UINTN                     Remaining;\r
   UINT8                     Index;\r
   UINT8                     Length;\r
+  UINT64                    Begin;\r
+  UINT64                    TimeoutTicker;\r
+  UINT64                    TimerRound;\r
 \r
   if (NumberOfBytes == 0 || Buffer == NULL) {\r
     return 0;\r
@@ -834,14 +888,43 @@ DebugPortReadBuffer (
   //\r
   // If Timeout is equal to 0, then it means it should always wait until all datum required are received.\r
   //\r
-  if (Timeout == 0) {\r
-    Timeout = 0xFFFFFFFF;\r
+  Begin         = 0;\r
+  TimeoutTicker = 0;  \r
+  TimerRound    = 0;\r
+  if (Timeout != 0) {\r
+    Begin = GetPerformanceCounter ();\r
+    TimeoutTicker = DivU64x32 (\r
+                      MultU64x64 (\r
+                        UsbDebugPortHandle->TimerFrequency,\r
+                        Timeout\r
+                        ),\r
+                      1000000u\r
+                      );\r
+    TimerRound = DivU64x64Remainder (\r
+                   TimeoutTicker,\r
+                   DivU64x32 (UsbDebugPortHandle->TimerCycle, 2),\r
+                   &TimeoutTicker\r
+                   );\r
   }\r
 \r
   //\r
   // Read remaining data by executing one or more usb debug transfer transactions at usb debug port hw.\r
   //\r
-  while ((Total < NumberOfBytes) && (Timeout != 0)) {\r
+  while (Total < NumberOfBytes) {\r
+    if (Timeout != 0) {\r
+      if (TimerRound == 0) {\r
+        if (IsTimerTimeout (UsbDebugPortHandle, Begin, TimeoutTicker)) {\r
+          //\r
+          // If time out occurs.\r
+          //\r
+          return 0;\r
+        }\r
+      } else {\r
+        if (IsTimerTimeout (UsbDebugPortHandle, Begin, DivU64x32 (UsbDebugPortHandle->TimerCycle, 2))) {\r
+          TimerRound --;\r
+        }\r
+      }\r
+    }\r
     Remaining = NumberOfBytes - Total;\r
     if (Remaining >= USB_DEBUG_PORT_MAX_PACKET_SIZE) {\r
       Status = UsbDebugPortIn(UsbDebugPortRegister, Buffer + Total, &Received, INPUT_PID, 0x7f, 0x82, UsbDebugPortHandle->BulkInToggle);\r
@@ -850,46 +933,44 @@ DebugPortReadBuffer (
         return Total;\r
       }\r
     } else {\r
-        Status = UsbDebugPortIn(UsbDebugPortRegister, &UsbDebugPortHandle->Data[0], &Received, INPUT_PID, 0x7f, 0x82, UsbDebugPortHandle->BulkInToggle);\r
+      Status = UsbDebugPortIn(UsbDebugPortRegister, &UsbDebugPortHandle->Data[0], &Received, INPUT_PID, 0x7f, 0x82, UsbDebugPortHandle->BulkInToggle);\r
 \r
-        if (RETURN_ERROR(Status)) {\r
-          return Total;\r
-        }\r
+      if (RETURN_ERROR(Status)) {\r
+        return Total;\r
+      }\r
 \r
-        UsbDebugPortHandle->DataCount = Received;\r
+      UsbDebugPortHandle->DataCount = Received;\r
 \r
-        if (Remaining <= Received) {\r
-          Length = (UINT8)Remaining;\r
-        } else {\r
-          Length = (UINT8)Received;\r
-        }\r
+      if (Remaining <= Received) {\r
+        Length = (UINT8)Remaining;\r
+      } else {\r
+        Length = (UINT8)Received;\r
+      }\r
 \r
-        //\r
-        // Copy required data from the data buffer to user buffer.\r
-        //\r
-        for (Index = 0; Index < Length; Index++) {\r
-          (Buffer + Total)[Index] = UsbDebugPortHandle->Data[Index];\r
-          UsbDebugPortHandle->DataCount--;\r
-        }\r
+      //\r
+      // Copy required data from the data buffer to user buffer.\r
+      //\r
+      for (Index = 0; Index < Length; Index++) {\r
+        (Buffer + Total)[Index] = UsbDebugPortHandle->Data[Index];\r
+        UsbDebugPortHandle->DataCount--;\r
+      }\r
 \r
-        //\r
-        // reorder the data buffer to make available data arranged from the beginning of the data buffer.\r
-        //\r
-        for (Index = 0; Index < Received - Length; Index++) {\r
-          if (Length + Index >= 8) {\r
-            return 0;\r
-          }\r
-          UsbDebugPortHandle->Data[Index] = UsbDebugPortHandle->Data[Length + Index];\r
+      //\r
+      // reorder the data buffer to make available data arranged from the beginning of the data buffer.\r
+      //\r
+      for (Index = 0; Index < Received - Length; Index++) {\r
+        if (Length + Index >= 8) {\r
+          return 0;\r
         }\r
-        //\r
-        // fixup the real received length in Buffer.\r
-        //\r
-        Received = Length;\r
+        UsbDebugPortHandle->Data[Index] = UsbDebugPortHandle->Data[Length + Index];\r
       }\r
-      UsbDebugPortHandle->BulkInToggle ^= 1;\r
-\r
-      Total += Received;\r
-      Timeout -= 100;\r
+      //\r
+      // fixup the real received length in Buffer.\r
+      //\r
+      Received = Length;\r
+    }\r
+    UsbDebugPortHandle->BulkInToggle ^= 1;\r
+    Total += Received;\r
   }\r
 \r
   return Total;\r
@@ -1118,11 +1199,40 @@ DebugPortInitialize (
 {\r
   RETURN_STATUS             Status;\r
   USB_DEBUG_PORT_HANDLE     Handle;\r
-\r  if (Function == NULL && Context != NULL) {\r
-    return (DEBUG_PORT_HANDLE *) Context;\r
+  USB_DEBUG_PORT_HANDLE     *UsbDebugPortHandle;\r
+  UINT64                    TimerStartValue;\r
+  UINT64                    TimerEndValue;\r
+\r  //\r
+  // Validate the PCD PcdDebugPortHandleBufferSize value \r
+  //\r
+  ASSERT (PcdGet16 (PcdDebugPortHandleBufferSize) == sizeof (USB_DEBUG_PORT_HANDLE));\r
+\r
+  if (Function == NULL && Context != NULL) {\r
+    UsbDebugPortHandle = (USB_DEBUG_PORT_HANDLE *)Context;\r
+  } else {\r
+    ZeroMem(&Handle, sizeof (USB_DEBUG_PORT_HANDLE));\r
+    UsbDebugPortHandle = &Handle;\r
   }\r
 \r
-  ZeroMem(&Handle, sizeof (USB_DEBUG_PORT_HANDLE));\r
+  UsbDebugPortHandle->TimerFrequency = GetPerformanceCounterProperties (\r
+                                         &TimerStartValue,\r
+                                         &TimerEndValue\r
+                                         );\r
+  DEBUG ((EFI_D_INFO, "USB Debug Port: TimerFrequency  = 0x%lx\n", UsbDebugPortHandle->TimerFrequency)); \r
+  DEBUG ((EFI_D_INFO, "USB Debug Port: TimerStartValue = 0x%lx\n", TimerStartValue)); \r
+  DEBUG ((EFI_D_INFO, "USB Debug Port: TimerEndValue   = 0x%lx\n", TimerEndValue)); \r
+\r
+  if (TimerEndValue < TimerStartValue) {\r
+    UsbDebugPortHandle->TimerCountDown = TRUE;\r
+    UsbDebugPortHandle->TimerCycle     = TimerStartValue - TimerEndValue;\r
+  } else {\r
+    UsbDebugPortHandle->TimerCountDown = FALSE;\r
+    UsbDebugPortHandle->TimerCycle     = TimerEndValue - TimerStartValue;\r
+  }   \r
+\r
+  if (Function == NULL && Context != NULL) {\r
+    return (DEBUG_PORT_HANDLE *) Context;\r
+  }\r
 \r
   Status = CalculateUsbDebugPortBar(&Handle.DebugPortOffset, &Handle.DebugPortBarNumber);\r
   if (RETURN_ERROR (Status)) {\r
@@ -1156,7 +1266,7 @@ DebugPortInitialize (
     DEBUG ((EFI_D_ERROR, "UsbDbg: Start EHCI debug port initialization!\n"));\r
     Status = InitializeUsbDebugHardware (&Handle);\r
     if (RETURN_ERROR(Status)) {\r
-      DEBUG ((EFI_D_ERROR, "UsbDbg: Initialization failed, please check if USB debug cable is plugged into EHCI debug port correctly!\n"));\r
+      DEBUG ((EFI_D_ERROR, "UsbDbg: Failed, please check if USB debug cable is plugged into EHCI debug port correctly!\n"));\r
       goto Exit;\r
     }\r
   }\r
index 61e8a7f1dea4630025b92aecc5155801208cf0df..37e365a7a3ae1bcbda2c7f4fd9aed5173b953495 100644 (file)
@@ -1,7 +1,7 @@
 ## @file\r
 #  Debug Communication Library instance based on usb debug port.\r
 #\r
-#  Copyright (c) 2010, Intel Corporation. All rights reserved.<BR>\r
+#  Copyright (c) 2010 - 2013, Intel Corporation. All rights reserved.<BR>\r
 #\r
 #  This program and the accompanying materials\r
 #  are licensed and made available under the terms and conditions of the BSD License\r
@@ -44,6 +44,9 @@
   ## The pci address of ehci host controller, in which usb debug feature is enabled.\r
   ## The format of pci address please refer to SourceLevelDebugPkg.dec\r
   gEfiSourceLevelDebugPkgTokenSpaceGuid.PcdUsbEhciPciAddress\r
+  ## The value of data buffer size used for USB debug port handle.\r
+  ## It should be equal to sizeof (USB_DEBUG_PORT_HANDLE).\r
+  gEfiSourceLevelDebugPkgTokenSpaceGuid.PcdDebugPortHandleBufferSize|40\r
 \r
 [LibraryClasses]\r
   TimerLib\r
diff --git a/SourceLevelDebugPkg/Library/PeCoffExtraActionLibDebug/Ia32/IntHandler.S b/SourceLevelDebugPkg/Library/PeCoffExtraActionLibDebug/Ia32/IntHandler.S
new file mode 100644 (file)
index 0000000..69c9037
--- /dev/null
@@ -0,0 +1,28 @@
+#------------------------------------------------------------------------------\r
+#\r
+# Copyright (c) 2013, 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
+#\r
+# Module Name:\r
+#\r
+#   IntHandler.S\r
+#\r
+# Abstract:\r
+#\r
+#   Assembly interrupt handler function.\r
+#\r
+#------------------------------------------------------------------------------\r
+\r
+ASM_GLOBAL ASM_PFX(AsmInterruptHandle)\r
+\r
+.text\r
+ASM_PFX(AsmInterruptHandle):\r
+   cli\r
+   movb   $1, %al\r
+   iretl\r
diff --git a/SourceLevelDebugPkg/Library/PeCoffExtraActionLibDebug/Ia32/IntHandler.asm b/SourceLevelDebugPkg/Library/PeCoffExtraActionLibDebug/Ia32/IntHandler.asm
new file mode 100644 (file)
index 0000000..ce9c03b
--- /dev/null
@@ -0,0 +1,33 @@
+;------------------------------------------------------------------------------\r
+;\r
+; Copyright (c) 2013, 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
+;\r
+; Module Name:\r
+;\r
+;   IntHandler.asm\r
+;\r
+; Abstract:\r
+;\r
+;   Assembly interrupt handler function.\r
+;\r
+;------------------------------------------------------------------------------\r
+\r
+\r
+.686p\r
+.model  flat,c\r
+\r
+public AsmInterruptHandle\r
+\r
+.code\r
+AsmInterruptHandle:\r
+    cli\r
+    mov   al, 1\r
+    iretd\r
+END\r
diff --git a/SourceLevelDebugPkg/Library/PeCoffExtraActionLibDebug/Ia32/IntHandlerFuncs.c b/SourceLevelDebugPkg/Library/PeCoffExtraActionLibDebug/Ia32/IntHandlerFuncs.c
new file mode 100644 (file)
index 0000000..b2d4c37
--- /dev/null
@@ -0,0 +1,96 @@
+/** @file\r
+  Ia32 arch functions to access IDT vector.\r
+\r
+  Copyright (c) 2013, 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
+\r
+**/\r
+\r
+#include <PeCoffExtraActionLib.h>\r
+\r
+/**\r
+  Read IDT entry to check if IDT entries are setup by Debug Agent.\r
+\r
+  @param[in]  IdtDescriptor      Pointer to IDT Descriptor.\r
+\r
+  @retval  TRUE     IDT entries were setup by Debug Agent.\r
+  @retval  FALSE    IDT entries were not setuo by Debug Agent.\r
+\r
+**/\r
+BOOLEAN \r
+CheckDebugAgentHandler (\r
+  IN  IA32_DESCRIPTOR            *IdtDescriptor\r
+  )\r
+{\r
+  IA32_IDT_GATE_DESCRIPTOR   *IdtEntry;\r
+  UINTN                      InterruptHandler;\r
+\r
+  IdtEntry = (IA32_IDT_GATE_DESCRIPTOR *) IdtDescriptor->Base;\r
+  if (IdtEntry == NULL) {\r
+    return FALSE;\r
+  }\r
+\r
+  InterruptHandler = IdtEntry[0].Bits.OffsetLow + (IdtEntry[0].Bits.OffsetHigh << 16);\r
+  if (InterruptHandler >= 4 &&  *(UINT32 *)(InterruptHandler - 4) == AGENT_HANDLER_SIGNATURE) {\r
+    return TRUE;\r
+  } else {\r
+    return FALSE;\r
+  }\r
+}\r
+\r
+/**\r
+  Save IDT entry for INT1 and update it. \r
+\r
+  @param[in]  IdtDescriptor      Pointer to IDT Descriptor.\r
+  @param[out] SavedIdtEntry      Original IDT entry returned.\r
+\r
+**/\r
+VOID\r
+SaveAndUpdateIdtEntry1 (\r
+  IN  IA32_DESCRIPTOR            *IdtDescriptor,\r
+  OUT IA32_IDT_GATE_DESCRIPTOR   *SavedIdtEntry\r
+  )\r
+{\r
+  IA32_IDT_GATE_DESCRIPTOR   *IdtEntry;\r
+  UINT16                     CodeSegment;\r
+  UINTN                      InterruptHandler;\r
+  \r
+  IdtEntry = (IA32_IDT_GATE_DESCRIPTOR *) IdtDescriptor->Base;\r
+  CopyMem (SavedIdtEntry, &IdtEntry[1], sizeof (IA32_IDT_GATE_DESCRIPTOR));\r
+\r
+    //\r
+  // Use current CS as the segment selector of interrupt gate in IDT\r
+  //\r
+  CodeSegment = AsmReadCs ();\r
+\r
+  InterruptHandler = (UINTN) &AsmInterruptHandle;\r
+  IdtEntry[1].Bits.OffsetLow  = (UINT16)(UINTN)InterruptHandler;\r
+  IdtEntry[1].Bits.OffsetHigh = (UINT16)((UINTN)InterruptHandler >> 16);\r
+  IdtEntry[1].Bits.Selector   = CodeSegment;\r
+  IdtEntry[1].Bits.GateType   = IA32_IDT_GATE_TYPE_INTERRUPT_32;\r
+}\r
+\r
+/**\r
+  Restore IDT entry for INT1. \r
+\r
+  @param[in]  IdtDescriptor      Pointer to IDT Descriptor.\r
+  @param[in]  RestoredIdtEntry   IDT entry to be restored.\r
+\r
+**/\r
+VOID\r
+RestoreIdtEntry1 (\r
+  IN  IA32_DESCRIPTOR            *IdtDescriptor,\r
+  IN  IA32_IDT_GATE_DESCRIPTOR   *RestoredIdtEntry\r
+  )\r
+{\r
+  IA32_IDT_GATE_DESCRIPTOR   *IdtEntry;\r
+  \r
+  IdtEntry = (IA32_IDT_GATE_DESCRIPTOR *) IdtDescriptor->Base;\r
+  CopyMem (&IdtEntry[1], RestoredIdtEntry, sizeof (IA32_IDT_GATE_DESCRIPTOR));\r
+}\r
index 7b551f20ed42b1104b6903a7954ae577d0676bdc..c28d7930a30afd3aa662133222f17e8327c946a4 100644 (file)
@@ -1,7 +1,7 @@
 /** @file\r
   PE/Coff Extra Action library instances.\r
 \r
-  Copyright (c) 2010 - 2012, Intel Corporation. All rights reserved.<BR>\r
+  Copyright (c) 2010 - 2013, 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
 \r
 **/\r
 \r
-#include <Base.h>\r
-#include <Library/PeCoffExtraActionLib.h>\r
-#include <Library/DebugLib.h>\r
-#include <Library/BaseLib.h>\r
-#include <Library/IoLib.h>\r
-#include <Library/PcdLib.h>\r
-\r
-#include <ImageDebugSupport.h>\r
-\r
-#define DEBUG_LOAD_IMAGE_METHOD_IO_HW_BREAKPOINT    1\r
-#define DEBUG_LOAD_IMAGE_METHOD_SOFT_INT3           2\r
+#include <PeCoffExtraActionLib.h>\r
 \r
 /**\r
   Check if the hardware breakpoint in Drx is enabled by checking the Lx and Gx bit in Dr7.\r
@@ -62,16 +52,19 @@ PeCoffLoaderExtraActionCommon (
   IN     UINTN                         Signature\r
   )\r
 {\r
-  BOOLEAN  InterruptState;\r
-  UINTN    Dr0;\r
-  UINTN    Dr1;\r
-  UINTN    Dr2;\r
-  UINTN    Dr3;\r
-  UINTN    Dr7;\r
-  UINTN    Cr4;\r
-  UINTN    NewDr7;\r
-  UINT8    LoadImageMethod;\r
-  UINT8    DebugAgentStatus;\r
+  BOOLEAN                    InterruptState;\r
+  UINTN                      Dr0;\r
+  UINTN                      Dr1;\r
+  UINTN                      Dr2;\r
+  UINTN                      Dr3;\r
+  UINTN                      Dr7;\r
+  UINTN                      Cr4;\r
+  UINTN                      NewDr7;\r
+  UINT8                      LoadImageMethod;\r
+  UINT8                      DebugAgentStatus;\r
+  IA32_DESCRIPTOR            IdtDescriptor;\r
+  IA32_IDT_GATE_DESCRIPTOR   OriginalIdtEntry;\r
+  BOOLEAN                    IdtEntryHooked;\r
 \r
   ASSERT (ImageContext != NULL);\r
 \r
@@ -84,6 +77,23 @@ PeCoffLoaderExtraActionCommon (
   //\r
   InterruptState = SaveAndDisableInterrupts ();\r
 \r
+  IdtEntryHooked  = FALSE;\r
+  LoadImageMethod = PcdGet8 (PcdDebugLoadImageMethod);\r
+  AsmReadIdtr (&IdtDescriptor);\r
+  if (!CheckDebugAgentHandler (&IdtDescriptor)) {\r
+    if (LoadImageMethod == DEBUG_LOAD_IMAGE_METHOD_SOFT_INT3) {\r
+      //\r
+      // Do not trigger INT3 if Debug Agent did not setup IDT entries.\r
+      //\r
+      return;\r
+    }\r
+    //\r
+    // Save and update IDT entry for INT1\r
+    //\r
+    SaveAndUpdateIdtEntry1 (&IdtDescriptor, &OriginalIdtEntry);\r
+    IdtEntryHooked = TRUE;\r
+  }\r
+  \r
   //\r
   // Save Debug Register State\r
   //\r
@@ -108,7 +118,6 @@ PeCoffLoaderExtraActionCommon (
   AsmWriteDr2 ((UINTN) ImageContext);\r
   AsmWriteDr3 (IO_PORT_BREAKPOINT_ADDRESS);\r
 \r
-  LoadImageMethod = PcdGet8 (PcdDebugLoadImageMethod);\r
   if (LoadImageMethod == DEBUG_LOAD_IMAGE_METHOD_IO_HW_BREAKPOINT) {\r
     AsmWriteDr7 (0x20000480);\r
     AsmWriteCr4 (Cr4 | BIT3);\r
@@ -156,6 +165,12 @@ PeCoffLoaderExtraActionCommon (
     AsmWriteDr7 (Dr7);\r
   }\r
   //\r
+  // Restore original IDT entry for INT1 if it was hooked.\r
+  //\r
+  if (IdtEntryHooked) {\r
+    RestoreIdtEntry1 (&IdtDescriptor, &OriginalIdtEntry);\r
+  }\r
+  //\r
   // Restore the interrupt state\r
   //\r
   SetInterruptState (InterruptState);\r
diff --git a/SourceLevelDebugPkg/Library/PeCoffExtraActionLibDebug/PeCoffExtraActionLib.h b/SourceLevelDebugPkg/Library/PeCoffExtraActionLibDebug/PeCoffExtraActionLib.h
new file mode 100644 (file)
index 0000000..36aebf1
--- /dev/null
@@ -0,0 +1,74 @@
+/** @file\r
+  PE/Coff Extra Action library instances, it will report image debug info.\r
+\r
+  Copyright (c) 2013, 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
+\r
+**/\r
+\r
+#ifndef _PE_COFF_EXTRA_ACTION_LIB_H_\r
+#define _PE_COFF_EXTRA_ACTION_LIB_H_\r
+\r
+#include <Base.h>\r
+#include <Library/PeCoffExtraActionLib.h>\r
+#include <Library/DebugLib.h>\r
+#include <Library/BaseLib.h>\r
+#include <Library/IoLib.h>\r
+#include <Library/PcdLib.h>\r
+#include <Library/BaseMemoryLib.h>\r
+\r
+#include <ImageDebugSupport.h>\r
+\r
+#define DEBUG_LOAD_IMAGE_METHOD_IO_HW_BREAKPOINT    1\r
+#define DEBUG_LOAD_IMAGE_METHOD_SOFT_INT3           2\r
+\r
+extern UINTN  AsmInterruptHandle;\r
+\r
+/**\r
+  Read IDT entry to check if IDT entries are setup by Debug Agent.\r
+\r
+  @param[in]  IdtDescriptor      Pointer to IDT Descriptor.\r
+\r
+  @retval  TRUE     IDT entries were setup by Debug Agent.\r
+  @retval  FALSE    IDT entries were not setuo by Debug Agent.\r
+\r
+**/\r
+BOOLEAN \r
+CheckDebugAgentHandler (\r
+  IN  IA32_DESCRIPTOR            *IdtDescriptor\r
+  );\r
+\r
+/**\r
+  Save IDT entry for INT1 and update it. \r
+\r
+  @param[in]  IdtDescriptor      Pointer to IDT Descriptor.\r
+  @param[out] SavedIdtEntry      Original IDT entry returned.\r
+\r
+**/\r
+VOID\r
+SaveAndUpdateIdtEntry1 (\r
+  IN  IA32_DESCRIPTOR            *IdtDescriptor,\r
+  OUT IA32_IDT_GATE_DESCRIPTOR   *SavedIdtEntry\r
+  );\r
+\r
+/**\r
+  Restore IDT entry for INT1. \r
+\r
+  @param[in]  IdtDescriptor      Pointer to IDT Descriptor.\r
+  @param[in]  RestoredIdtEntry   IDT entry to be restored.\r
+\r
+**/\r
+VOID\r
+RestoreIdtEntry1 (\r
+  IN  IA32_DESCRIPTOR            *IdtDescriptor,\r
+  IN  IA32_IDT_GATE_DESCRIPTOR   *RestoredIdtEntry\r
+  );\r
+\r
+#endif\r
+\r
index e3712afacb9f37791abb899b8d33860f181ac897..fa485bcf182267750517d7a8ba6e278b5e81e8f8 100644 (file)
@@ -1,7 +1,7 @@
 ## @file\r
 #  PeCoffExtraAction Library to support source level debug.\r
 #\r
-#  Copyright (c) 2010, Intel Corporation. All rights reserved.<BR>\r
+#  Copyright (c) 2010 - 2013, Intel Corporation. All rights reserved.<BR>\r
 #\r
 #  This program and the accompanying materials\r
 #  are licensed and made available under the terms and conditions of the BSD License\r
 #\r
 \r
 [Sources.common]\r
+  PeCoffExtraActionLib.h\r
   PeCoffExtraActionLib.c\r
 \r
+[Sources.IA32]\r
+  Ia32/IntHandlerFuncs.c\r
+  Ia32/IntHandler.asm     | MSFT\r
+  Ia32/IntHandler.S       | GCC\r
+\r
+[Sources.X64]\r
+  X64/IntHandlerFuncs.c\r
+  X64/IntHandler.asm      | MSFT\r
+  X64/IntHandler.S        | GCC\r
+\r
 [Packages]\r
   MdePkg/MdePkg.dec\r
   SourceLevelDebugPkg/SourceLevelDebugPkg.dec\r
diff --git a/SourceLevelDebugPkg/Library/PeCoffExtraActionLibDebug/X64/IntHandler.S b/SourceLevelDebugPkg/Library/PeCoffExtraActionLibDebug/X64/IntHandler.S
new file mode 100644 (file)
index 0000000..108b40c
--- /dev/null
@@ -0,0 +1,28 @@
+#------------------------------------------------------------------------------\r
+#\r
+# Copyright (c) 2013, 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
+#\r
+# Module Name:\r
+#\r
+#   IntHandler.S\r
+#\r
+# Abstract:\r
+#\r
+#   Assembly interrupt handler function.\r
+#\r
+#------------------------------------------------------------------------------\r
+\r
+ASM_GLOBAL ASM_PFX(AsmInterruptHandle)\r
+\r
+.text\r
+ASM_PFX(AsmInterruptHandle):\r
+   cli\r
+   movb   $1, %al\r
+   iretq\r
diff --git a/SourceLevelDebugPkg/Library/PeCoffExtraActionLibDebug/X64/IntHandler.asm b/SourceLevelDebugPkg/Library/PeCoffExtraActionLibDebug/X64/IntHandler.asm
new file mode 100644 (file)
index 0000000..93f4d6f
--- /dev/null
@@ -0,0 +1,29 @@
+;------------------------------------------------------------------------------\r
+;\r
+; Copyright (c) 2013, 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
+;\r
+; Module Name:\r
+;\r
+;   IntHandler.asm\r
+;\r
+; Abstract:\r
+;\r
+;   Assembly interrupt handler function.\r
+;\r
+;------------------------------------------------------------------------------\r
+\r
+public AsmInterruptHandle\r
+\r
+.code\r
+AsmInterruptHandle:\r
+    cli\r
+    mov   al, 1\r
+    iretq\r
+END\r
diff --git a/SourceLevelDebugPkg/Library/PeCoffExtraActionLibDebug/X64/IntHandlerFuncs.c b/SourceLevelDebugPkg/Library/PeCoffExtraActionLibDebug/X64/IntHandlerFuncs.c
new file mode 100644 (file)
index 0000000..c9041de
--- /dev/null
@@ -0,0 +1,98 @@
+/** @file\r
+  X64 arch function to access IDT vector.\r
+\r
+  Copyright (c) 2013, 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
+\r
+**/\r
+\r
+#include <PeCoffExtraActionLib.h>\r
+\r
+/**\r
+  Read IDT entry to check if IDT entries are setup by Debug Agent.\r
+\r
+  @param[in]  IdtDescriptor      Pointer to IDT Descriptor.\r
+\r
+  @retval  TRUE     IDT entries were setup by Debug Agent.\r
+  @retval  FALSE    IDT entries were not setuo by Debug Agent.\r
+\r
+**/\r
+BOOLEAN \r
+CheckDebugAgentHandler (\r
+  IN  IA32_DESCRIPTOR            *IdtDescriptor\r
+  )\r
+{\r
+  IA32_IDT_GATE_DESCRIPTOR   *IdtEntry;\r
+  UINTN                      InterruptHandler;\r
+\r
+  IdtEntry = (IA32_IDT_GATE_DESCRIPTOR *) IdtDescriptor->Base;\r
+  if (IdtEntry == NULL) {\r
+    return FALSE;\r
+  }\r
+\r
+  InterruptHandler = IdtEntry[0].Bits.OffsetLow + (((UINTN)IdtEntry[0].Bits.OffsetHigh) << 16) + \r
+                     (((UINTN)IdtEntry[0].Bits.OffsetUpper) << 32);\r
+  if (InterruptHandler >= 4 &&  *(UINT32 *)(InterruptHandler - 4) == AGENT_HANDLER_SIGNATURE) {\r
+    return TRUE;\r
+  } else {\r
+    return FALSE;\r
+  }\r
+}\r
+\r
+/**\r
+  Save IDT entry for INT1 and update it. \r
+\r
+  @param[in]  IdtDescriptor      Pointer to IDT Descriptor.\r
+  @param[out] SavedIdtEntry      Original IDT entry returned.\r
+\r
+**/\r
+VOID\r
+SaveAndUpdateIdtEntry1 (\r
+  IN  IA32_DESCRIPTOR            *IdtDescriptor,\r
+  OUT IA32_IDT_GATE_DESCRIPTOR   *SavedIdtEntry\r
+  )\r
+{\r
+  IA32_IDT_GATE_DESCRIPTOR   *IdtEntry;\r
+  UINT16                     CodeSegment;\r
+  UINTN                      InterruptHandler;\r
+  \r
+  IdtEntry = (IA32_IDT_GATE_DESCRIPTOR *) IdtDescriptor->Base;\r
+  CopyMem (SavedIdtEntry, &IdtEntry[1], sizeof (IA32_IDT_GATE_DESCRIPTOR));\r
+\r
+    //\r
+  // Use current CS as the segment selector of interrupt gate in IDT\r
+  //\r
+  CodeSegment = AsmReadCs ();\r
+\r
+  InterruptHandler = (UINTN) &AsmInterruptHandle;\r
+  IdtEntry[1].Bits.OffsetLow       = (UINT16)(UINTN)InterruptHandler;\r
+  IdtEntry[1].Bits.OffsetHigh      = (UINT16)((UINTN)InterruptHandler >> 16);\r
+  IdtEntry[1].Bits.OffsetUpper     = (UINT32)((UINTN)InterruptHandler >> 32);\r
+  IdtEntry[1].Bits.Selector        = CodeSegment;\r
+  IdtEntry[1].Bits.GateType        = IA32_IDT_GATE_TYPE_INTERRUPT_32;\r
+}\r
+\r
+/**\r
+  Restore IDT entry for INT1. \r
+\r
+  @param[in]  IdtDescriptor      Pointer to IDT Descriptor.\r
+  @param[in]  RestoredIdtEntry   IDT entry to be restored.\r
+\r
+**/\r
+VOID\r
+RestoreIdtEntry1 (\r
+  IN  IA32_DESCRIPTOR            *IdtDescriptor,\r
+  IN  IA32_IDT_GATE_DESCRIPTOR   *RestoredIdtEntry\r
+  )\r
+{\r
+  IA32_IDT_GATE_DESCRIPTOR   *IdtEntry;\r
+  \r
+  IdtEntry = (IA32_IDT_GATE_DESCRIPTOR *) IdtDescriptor->Base;\r
+  CopyMem (&IdtEntry[1], RestoredIdtEntry, sizeof (IA32_IDT_GATE_DESCRIPTOR));\r
+}\r
index 34d7006522a83e51b6bfdafc1e6bcae866357df5..5146b9e222c7430421f2cc4e45b6d896c80d75f8 100644 (file)
@@ -7,7 +7,7 @@
 # and host, PeCoffExtraActionLib instance to report symbol path information,\r
 # etc.\r
 #\r
-# Copyright (c) 2010 - 2012, Intel Corporation. All rights reserved.<BR>\r
+# Copyright (c) 2010 - 2013, Intel Corporation. All rights reserved.<BR>\r
 # This program and the accompanying materials are licensed and made available under \r
 # the terms and conditions of the BSD License that accompanies this distribution.  \r
 # The full text of the license may be found at\r
@@ -22,7 +22,7 @@
   DEC_SPECIFICATION              = 0x00010005\r
   PACKAGE_NAME                   = SourceLevelDebugPkg\r
   PACKAGE_GUID                   = DBF00C27-D8D7-443d-918B-4E85CDA1373B\r
-  PACKAGE_VERSION                = 0.80\r
+  PACKAGE_VERSION                = 0.85\r
 \r
 [Includes]\r
   Include\r
@@ -72,3 +72,7 @@
   ## 1: Use I/O Port 84 to issue hardware break point\r
   ## 2: Use INT3 to issue software break point\r
   gEfiSourceLevelDebugPkgTokenSpaceGuid.PcdDebugLoadImageMethod|0x1|UINT8|0x00000005\r
+\r
+  ## The data buffer size used by debug port in debug communication library.\r
+  gEfiSourceLevelDebugPkgTokenSpaceGuid.PcdDebugPortHandleBufferSize|0x0|UINT16|0x00000006\r
+\r
index 461cbf8852a6b60ac8193a1d0280b2462d41d798..3d9c36428cbe3708e44b498738604667e86ac95a 100644 (file)
@@ -2,7 +2,7 @@
 #\r
 # Source Level Debug Package.\r
 #\r
-# Copyright (c) 2010 - 2012, Intel Corporation. All rights reserved.<BR>\r
+# Copyright (c) 2010 - 2013, Intel Corporation. All rights reserved.<BR>\r
 #\r
 #    This program and the accompanying materials\r
 #    are licensed and made available under the terms and conditions of the BSD License\r
@@ -22,7 +22,7 @@
 [Defines]\r
   PLATFORM_NAME                  = SourceLevelDebugPkg\r
   PLATFORM_GUID                  = 38C85805-883F-4ee8-A854-95B966ED73AA\r
-  PLATFORM_VERSION               = 0.80\r
+  PLATFORM_VERSION               = 0.85\r
   DSC_SPECIFICATION              = 0x00010005\r
   OUTPUT_DIRECTORY               = Build/SourceLevelDebugPkg\r
   SUPPORTED_ARCHITECTURES        = IA32|X64\r
   SKUID_IDENTIFIER               = DEFAULT\r
 \r
 [LibraryClasses.common]\r
-  DebugLib|MdePkg/Library/UefiDebugLibStdErr/UefiDebugLibStdErr.inf\r
+  DebugLib|MdePkg/Library/BaseDebugLibSerialPort/BaseDebugLibSerialPort.inf\r
   DebugPrintErrorLevelLib|MdePkg/Library/BaseDebugPrintErrorLevelLib/BaseDebugPrintErrorLevelLib.inf  \r
   BaseLib|MdePkg/Library/BaseLib/BaseLib.inf\r
   BaseMemoryLib|MdePkg/Library/BaseMemoryLib/BaseMemoryLib.inf\r
-  TimerLib|MdePkg/Library/BaseTimerLibNullTemplate/BaseTimerLibNullTemplate.inf\r
   PcdLib|MdePkg/Library/BasePcdLibNull/BasePcdLibNull.inf\r
+  PrintLib|MdePkg/Library/BasePrintLib/BasePrintLib.inf\r
+  IoLib|MdePkg/Library/BaseIoLibIntrinsic/BaseIoLibIntrinsic.inf\r
+  SynchronizationLib|MdePkg/Library/BaseSynchronizationLib/BaseSynchronizationLib.inf\r
+  LocalApicLib|UefiCpuPkg/Library/BaseXApicLib/BaseXApicLib.inf\r
+  PeCoffGetEntryPointLib|MdePkg/Library/BasePeCoffGetEntryPointLib/BasePeCoffGetEntryPointLib.inf\r
+  SerialPortLib|MdeModulePkg/Library/BaseSerialPortLib16550/BaseSerialPortLib16550.inf\r
+  PeCoffExtraActionLib|SourceLevelDebugPkg/Library/PeCoffExtraActionLibDebug/PeCoffExtraActionLibDebug.inf\r
+  TimerLib|UefiCpuPkg/Library/SecPeiDxeTimerLibUefiCpu/SecPeiDxeTimerLibUefiCpu.inf\r
+  ResetSystemLib|PcAtChipsetPkg/Library/ResetSystemLib/ResetSystemLib.inf\r
+\r
+  PlatformHookLib|MdeModulePkg/Library/BasePlatformHookLibNull/BasePlatformHookLibNull.inf\r
+\r
   DebugCommunicationLib|SourceLevelDebugPkg/Library/DebugCommunicationLibSerialPort/DebugCommunicationLibSerialPort.inf\r
+  #DebugCommunicationLib|SourceLevelDebugPkg/Library/DebugCommunicationLibUsb/DebugCommunicationLibUsb.inf\r
+\r
+[LibraryClasses.common.PEIM]\r
+  PeimEntryPoint|MdePkg/Library/PeimEntryPoint/PeimEntryPoint.inf\r
+  PeiServicesLib|MdePkg/Library/PeiServicesLib/PeiServicesLib.inf\r
+  PeiServicesTablePointerLib|MdePkg/Library/PeiServicesTablePointerLibIdt/PeiServicesTablePointerLibIdt.inf\r
+  HobLib|MdePkg/Library/PeiHobLib/PeiHobLib.inf\r
+  MemoryAllocationLib|MdePkg/Library/PeiMemoryAllocationLib/PeiMemoryAllocationLib.inf\r
+  DebugAgentLib|SourceLevelDebugPkg/Library/DebugAgent/SecPeiDebugAgentLib.inf\r
+\r
+[LibraryClasses.common.DXE_DRIVER]\r
+  UefiDriverEntryPoint|MdePkg/Library/UefiDriverEntryPoint/UefiDriverEntryPoint.inf\r
+  UefiBootServicesTableLib|MdePkg/Library/UefiBootServicesTableLib/UefiBootServicesTableLib.inf\r
+  UefiRuntimeServicesTableLib|MdePkg/Library/UefiRuntimeServicesTableLib/UefiRuntimeServicesTableLib.inf\r
+  UefiLib|MdePkg/Library/UefiLib/UefiLib.inf\r
+  DevicePathLib|MdePkg/Library/UefiDevicePathLib/UefiDevicePathLib.inf\r
+  HobLib|MdePkg/Library/DxeHobLib/DxeHobLib.inf\r
+  MemoryAllocationLib|MdePkg/Library/UefiMemoryAllocationLib/UefiMemoryAllocationLib.inf\r
+  DebugAgentLib|SourceLevelDebugPkg/Library/DebugAgent/DxeDebugAgentLib.inf\r
 \r
 ###################################################################################################\r
 #\r
@@ -64,4 +94,5 @@
   SourceLevelDebugPkg/Library/DebugAgent/SecPeiDebugAgentLib.inf\r
   SourceLevelDebugPkg/Library/DebugAgent/DxeDebugAgentLib.inf\r
   SourceLevelDebugPkg/Library/DebugAgent/SmmDebugAgentLib.inf\r
-\r
+  SourceLevelDebugPkg/DebugAgentPei/DebugAgentPei.inf\r
+  SourceLevelDebugPkg/DebugAgentDxe/DebugAgentDxe.inf\r