summaryrefslogtreecommitdiff
path: root/SourceLevelDebugPkg/Library
diff options
context:
space:
mode:
authorvanjeff <vanjeff@6f19259b-4bc3-4df7-8a09-765794883524>2010-09-12 06:43:36 +0000
committervanjeff <vanjeff@6f19259b-4bc3-4df7-8a09-765794883524>2010-09-12 06:43:36 +0000
commit18b144ea424e476f14839e9d9d3b81fb4820a613 (patch)
tree99df88301cc7c317753b0f6ea04e664b9a51856b /SourceLevelDebugPkg/Library
parentbf45bbe53d8759a5f02e036dd40d1772a10af14f (diff)
Import SourceLevelDebugPkg.
git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@10867 6f19259b-4bc3-4df7-8a09-765794883524
Diffstat (limited to 'SourceLevelDebugPkg/Library')
-rw-r--r--SourceLevelDebugPkg/Library/DebugAgent/DebugAgentCommon/DebugAgent.c1195
-rw-r--r--SourceLevelDebugPkg/Library/DebugAgent/DebugAgentCommon/DebugAgent.h308
-rw-r--r--SourceLevelDebugPkg/Library/DebugAgent/DebugAgentCommon/DebugMp.c365
-rw-r--r--SourceLevelDebugPkg/Library/DebugAgent/DebugAgentCommon/DebugMp.h221
-rw-r--r--SourceLevelDebugPkg/Library/DebugAgent/DebugAgentCommon/DebugTimer.c83
-rw-r--r--SourceLevelDebugPkg/Library/DebugAgent/DebugAgentCommon/DebugTimer.h28
-rw-r--r--SourceLevelDebugPkg/Library/DebugAgent/DebugAgentCommon/Ia32/ArchDebugSupport.c242
-rw-r--r--SourceLevelDebugPkg/Library/DebugAgent/DebugAgentCommon/Ia32/ArchDebugSupport.h31
-rw-r--r--SourceLevelDebugPkg/Library/DebugAgent/DebugAgentCommon/Ia32/ArchReadGroupRegister.c210
-rw-r--r--SourceLevelDebugPkg/Library/DebugAgent/DebugAgentCommon/Ia32/ArchRegisters.h156
-rw-r--r--SourceLevelDebugPkg/Library/DebugAgent/DebugAgentCommon/Ia32/AsmFuncs.S360
-rw-r--r--SourceLevelDebugPkg/Library/DebugAgent/DebugAgentCommon/Ia32/AsmFuncs.asm365
-rw-r--r--SourceLevelDebugPkg/Library/DebugAgent/DebugAgentCommon/Ia32/DebugException.h36
-rw-r--r--SourceLevelDebugPkg/Library/DebugAgent/DebugAgentCommon/X64/ArchDebugSupport.c255
-rw-r--r--SourceLevelDebugPkg/Library/DebugAgent/DebugAgentCommon/X64/ArchDebugSupport.h31
-rw-r--r--SourceLevelDebugPkg/Library/DebugAgent/DebugAgentCommon/X64/ArchReadGroupRegister.c259
-rw-r--r--SourceLevelDebugPkg/Library/DebugAgent/DebugAgentCommon/X64/ArchRegisters.h329
-rw-r--r--SourceLevelDebugPkg/Library/DebugAgent/DebugAgentCommon/X64/AsmFuncs.S401
-rw-r--r--SourceLevelDebugPkg/Library/DebugAgent/DebugAgentCommon/X64/AsmFuncs.asm364
-rw-r--r--SourceLevelDebugPkg/Library/DebugAgent/DebugAgentCommon/X64/DebugException.h36
-rw-r--r--SourceLevelDebugPkg/Library/DebugAgent/DxeDebugAgent/DxeDebugAgentLib.c247
-rw-r--r--SourceLevelDebugPkg/Library/DebugAgent/DxeDebugAgent/DxeDebugAgentLib.h25
-rw-r--r--SourceLevelDebugPkg/Library/DebugAgent/DxeDebugAgentLib.inf87
-rw-r--r--SourceLevelDebugPkg/Library/DebugAgent/SecPeiDebugAgent/SecPeiDebugAgentLib.c307
-rw-r--r--SourceLevelDebugPkg/Library/DebugAgent/SecPeiDebugAgent/SecPeiDebugAgentLib.h28
-rw-r--r--SourceLevelDebugPkg/Library/DebugAgent/SecPeiDebugAgentLib.inf81
-rw-r--r--SourceLevelDebugPkg/Library/DebugAgent/SmmDebugAgent/SmmDebugAgentLib.c157
-rw-r--r--SourceLevelDebugPkg/Library/DebugAgent/SmmDebugAgent/SmmDebugAgentLib.h24
-rw-r--r--SourceLevelDebugPkg/Library/DebugAgent/SmmDebugAgentLib.inf81
-rw-r--r--SourceLevelDebugPkg/Library/DebugCommunicationLibSerialPort/DebugCommunicationLibSerialPort.c169
-rw-r--r--SourceLevelDebugPkg/Library/DebugCommunicationLibSerialPort/DebugCommunicationLibSerialPort.inf38
-rw-r--r--SourceLevelDebugPkg/Library/DebugCommunicationLibUsb/DebugCommunicationLibUsb.c1076
-rw-r--r--SourceLevelDebugPkg/Library/DebugCommunicationLibUsb/DebugCommunicationLibUsb.inf53
-rw-r--r--SourceLevelDebugPkg/Library/PeCoffExtraActionLibDebug/PeCoffExtraActionLib.c269
-rw-r--r--SourceLevelDebugPkg/Library/PeCoffExtraActionLibDebug/PeCoffExtraActionLibDebug.inf45
35 files changed, 7962 insertions, 0 deletions
diff --git a/SourceLevelDebugPkg/Library/DebugAgent/DebugAgentCommon/DebugAgent.c b/SourceLevelDebugPkg/Library/DebugAgent/DebugAgentCommon/DebugAgent.c
new file mode 100644
index 000000000..39b24c39c
--- /dev/null
+++ b/SourceLevelDebugPkg/Library/DebugAgent/DebugAgentCommon/DebugAgent.c
@@ -0,0 +1,1195 @@
+/** @file
+ Commond Debug Agent library implementition. It mainly includes
+ the first C function called by exception/interrupt handlers,
+ read/write debug packet to communication with HOST based on transfer
+ protocol.
+
+ Copyright (c) 2010, Intel Corporation. All rights reserved.<BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php.
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "DebugAgent.h"
+#include "Ia32/DebugException.h"
+
+/**
+ Check if HOST is connected based on Mailbox.
+
+ @retval TRUE HOST is connected.
+ @retval FALSE HOST is not connected.
+
+**/
+BOOLEAN
+IsHostConnected (
+ VOID
+ )
+{
+ DEBUG_AGENT_MAILBOX *Mailbox;
+
+ Mailbox = GetMailboxPointer ();
+
+ if (Mailbox->DebugFlag.Bits.HostPresent == 1) {
+ return TRUE;
+ } else {
+ return FALSE;
+ }
+}
+
+/**
+ Set HOST connect flag in Mailbox.
+
+**/
+VOID
+SetHostConnectedFlag (
+ VOID
+ )
+{
+ DEBUG_AGENT_MAILBOX *Mailbox;
+
+ Mailbox = GetMailboxPointer ();
+
+ Mailbox->DebugFlag.Bits.HostPresent = 1;
+}
+
+/**
+ Set debug flag of Debug Agent in Mailbox.
+
+ @param DebugFlag Debug Flag defined by transfer protocol.
+
+**/
+VOID
+SetDebugFlag (
+ IN UINT32 DebugFlag
+ )
+{
+ DEBUG_AGENT_MAILBOX *Mailbox;
+
+ Mailbox = GetMailboxPointer ();
+
+ if ((DebugFlag & SOFT_DEBUGGER_SETTING_SMM_ENTRY_BREAK) != 0) {
+ Mailbox->DebugFlag.Bits.BreakOnNextSmi = 1;
+ } else {
+ Mailbox->DebugFlag.Bits.BreakOnNextSmi = 0;
+ }
+}
+
+/**
+ Exectue GO command.
+
+ @param[in] CpuContext Pointer to saved CPU context.
+
+**/
+VOID
+CommandGo (
+ IN DEBUG_CPU_CONTEXT *CpuContext
+ )
+{
+ IA32_EFLAGS32 *Eflags;
+
+ Eflags = (IA32_EFLAGS32 *) &CpuContext->Eflags;
+ Eflags->Bits.TF = 0;
+ Eflags->Bits.RF = 1;
+}
+
+/**
+ Exectue Stepping command.
+
+ @param[in] CpuContext Pointer to saved CPU context.
+
+**/
+VOID
+CommandStepping (
+ IN DEBUG_CPU_CONTEXT *CpuContext
+ )
+{
+ IA32_EFLAGS32 *Eflags;
+
+ Eflags = (IA32_EFLAGS32 *) &CpuContext->Eflags;
+ Eflags->Bits.TF = 1;
+ Eflags->Bits.RF = 1;
+}
+
+/**
+ Set debug register for hardware breakpoint.
+
+ @param[in] CpuContext Pointer to saved CPU context.
+ @param[in] SetHwBreakpoint Hardware breakpoint to be set.
+
+**/
+VOID
+SetDebugRegister (
+ IN DEBUG_CPU_CONTEXT *CpuContext,
+ IN DEBUG_DATA_SET_HW_BREAKPOINT *SetHwBreakpoint
+ )
+{
+ UINT8 RegisterIndex;
+ UINTN Dr7Value;
+
+ RegisterIndex = SetHwBreakpoint->Type.Index;
+
+ //
+ // Set debug address
+ //
+ * ((UINTN *) &CpuContext->Dr0 + RegisterIndex) = (UINTN) SetHwBreakpoint->Address;
+
+ Dr7Value = CpuContext->Dr7;
+
+ //
+ // Enable Gx, Lx
+ //
+ Dr7Value |= 0x3 << (RegisterIndex * 2);
+ //
+ // Set RWx and Lenx
+ //
+ Dr7Value &= ~(0xf0000 << (RegisterIndex * 4));
+ Dr7Value |= (SetHwBreakpoint->Type.Length | SetHwBreakpoint->Type.Access) << (RegisterIndex * 4);
+ //
+ // Enable GE, LE
+ //
+ Dr7Value |= 0x300;
+
+ CpuContext->Dr7 = Dr7Value;
+}
+
+/**
+ Clear debug register for hardware breakpoint.
+
+ @param[in] CpuContext Pointer to saved CPU context.
+ @param[in] ClearHwBreakpoint Hardware breakpoint to be cleared.
+
+**/
+VOID
+ClearDebugRegister (
+ IN DEBUG_CPU_CONTEXT *CpuContext,
+ IN DEBUG_DATA_CLEAR_HW_BREAKPOINT *ClearHwBreakpoint
+ )
+{
+ if ((ClearHwBreakpoint->IndexMask & BIT0) != 0) {
+ CpuContext->Dr0 = 0;
+ CpuContext->Dr7 &= ~(0x3 << 0);
+ }
+ if ((ClearHwBreakpoint->IndexMask & BIT1) != 0) {
+ CpuContext->Dr1 = 0;
+ CpuContext->Dr7 &= ~(0x3 << 2);
+ }
+ if ((ClearHwBreakpoint->IndexMask & BIT2) != 0) {
+ CpuContext->Dr2 = 0;
+ CpuContext->Dr7 &= ~(0x3 << 4);
+ }
+ if ((ClearHwBreakpoint->IndexMask & BIT3) != 0) {
+ CpuContext->Dr3 = 0;
+ CpuContext->Dr7 &= ~(0x3 << 6);
+ }
+}
+
+/**
+ Send acknowledge packet to HOST.
+
+ @param[in] AckCommand Type of Acknowledge packet.
+
+**/
+VOID
+SendAckPacket (
+ IN UINT8 AckCommand
+ )
+{
+ DEBUG_COMMAND_HEADER DebugCommonHeader;
+ DEBUG_PORT_HANDLE Handle;
+
+ Handle = GetDebugPortHandle();
+
+ DebugCommonHeader.StartSymbol = DEBUG_STARTING_SYMBOL_NORMAL;
+ DebugCommonHeader.Command = AckCommand;
+ DebugCommonHeader.DataLength = 0;
+
+ DebugPortWriteBuffer (Handle, (UINT8 *) &DebugCommonHeader, sizeof (DEBUG_COMMAND_HEADER));
+}
+
+/**
+ Receive acknowledge packet from HOST in specified time.
+
+ @param[out] Ack Returned acknowlege type from HOST.
+ @param[in] Timeout Time out value to wait for acknowlege from HOST.
+ The unit is microsecond.
+ @param[out] BreakReceived If BreakReceived is not NULL,
+ TRUE is retured if break-in symbol received.
+ FALSE is retured if break-in symbol not received.
+
+ @retval RETRUEN_SUCCESS Succeed to receive acknowlege packet from HOST,
+ the type of acknowlege packet saved in Ack.
+ @retval RETURN_TIMEOUT Specified timeout value was up.
+
+**/
+RETURN_STATUS
+ReceiveAckPacket (
+ OUT UINT8 *Ack,
+ IN UINTN Timeout,
+ OUT BOOLEAN *BreakReceived OPTIONAL
+ )
+{
+ DEBUG_COMMAND_HEADER DebugCommonHeader;
+ DEBUG_PORT_HANDLE Handle;
+
+ Handle = GetDebugPortHandle();
+
+ while (TRUE) {
+ if (DebugPortReadBuffer (Handle, (UINT8 *) &DebugCommonHeader.StartSymbol, 1, Timeout) == 0) {
+ return RETURN_TIMEOUT;
+ }
+ if (DebugCommonHeader.StartSymbol == DEBUG_STARTING_SYMBOL_BREAK) {
+ if (BreakReceived != NULL) {
+ SendAckPacket (DEBUG_COMMAND_HALT_DEFERRED);
+ *BreakReceived = TRUE;
+ }
+ }
+ if (DebugCommonHeader.StartSymbol == DEBUG_STARTING_SYMBOL_NORMAL) {
+ break;
+ }
+ }
+ if (DebugPortReadBuffer (Handle, (UINT8 *)&DebugCommonHeader.Command, sizeof (DEBUG_COMMAND_HEADER) - 1, Timeout) == 0) {
+ return RETURN_TIMEOUT;
+ }
+
+ *Ack = DebugCommonHeader.Command;
+ return RETURN_SUCCESS;
+}
+
+/**
+ Receive acknowledge packet OK from HOST in specified time.
+
+ @param[in] Timeout Time out value to wait for acknowlege from HOST.
+ The unit is microsecond.
+ @param[out] BreakReceived If BreakReceived is not NULL,
+ TRUE is retured if break-in symbol received.
+ FALSE is retured if break-in symbol not received.
+
+ @retval RETRUEN_SUCCESS Succeed to receive acknowlege packet from HOST,
+ the type of acknowlege packet saved in Ack.
+ @retval RETURN_TIMEOUT Specified timeout value was up.
+
+**/
+RETURN_STATUS
+WaitForAckPacketOK (
+ IN UINTN Timeout,
+ OUT BOOLEAN *BreakReceived OPTIONAL
+ )
+{
+ RETURN_STATUS Status;
+ UINT8 Ack;
+
+ while (TRUE) {
+ Status = ReceiveAckPacket (&Ack, Timeout, BreakReceived);
+ if ((Status == RETURN_SUCCESS && Ack == DEBUG_COMMAND_OK) ||
+ Status == RETURN_TIMEOUT) {
+ break;
+ }
+ }
+
+ return Status;
+}
+
+/**
+ Receive valid packet from HOST.
+
+ @param[out] InputPacket Buffer to receive packet.
+ @param[out] BreakReceived TRUE means break-in symbol received.
+ FALSE means break-in symbol not received.
+
+ @retval RETURN_SUCCESS A valid package was reveived in InputPacket.
+ @retval RETURN_NOT_READY No valid start symbol received.
+ @retval RETURN_TIMEOUT Timeout occurs.
+
+**/
+RETURN_STATUS
+ReceivePacket (
+ OUT UINT8 *InputPacket,
+ OUT BOOLEAN *BreakReceived
+ )
+{
+ DEBUG_COMMAND_HEADER *DebugHeader;
+ UINTN Received;
+ DEBUG_PORT_HANDLE Handle;
+
+ Handle = GetDebugPortHandle();
+ //
+ // Find the valid start symbol
+ //
+ DebugPortReadBuffer (Handle, InputPacket, 1, 0);
+
+ if (*InputPacket == DEBUG_STARTING_SYMBOL_BREAK) {
+ *BreakReceived = TRUE;
+ SendAckPacket (DEBUG_COMMAND_HALT_DEFERRED);
+ }
+
+ if (*InputPacket != DEBUG_STARTING_SYMBOL_NORMAL) {
+ return RETURN_NOT_READY;
+ }
+
+ //
+ // Read Package header
+ //
+ Received = DebugPortReadBuffer (Handle, InputPacket + 1, sizeof(DEBUG_COMMAND_HEADER_NO_START_SYMBOL), 0);
+ if (Received == 0) {
+ return RETURN_TIMEOUT;
+ }
+
+ DebugHeader = (DEBUG_COMMAND_HEADER *) InputPacket;
+ //
+ // Read the payload if has
+ //
+ if (DebugHeader->DataLength > 0 && DebugHeader->DataLength < (DEBUG_DATA_MAXIMUM_REAL_DATA - sizeof(DEBUG_COMMAND_HEADER))) {
+ InputPacket = InputPacket + 1 + Received;
+ Received = DebugPortReadBuffer (Handle, InputPacket, DebugHeader->DataLength, 0);
+
+ if (Received == 0) {
+ return RETURN_TIMEOUT;
+ }
+ }
+
+ return RETURN_SUCCESS;
+}
+
+/**
+ Get current break cause.
+
+ @param[in] Vector Vector value of exception or interrupt.
+ @param[in] CpuContext Pointer to save CPU context.
+
+ @return The type of break cause defined by XXXX
+
+**/
+UINT8
+GetBreakCause (
+ IN UINTN Vector,
+ IN DEBUG_CPU_CONTEXT *CpuContext
+ )
+{
+ UINT8 Cause;
+
+ Cause = DEBUG_DATA_BREAK_CAUSE_UNKNOWN;
+
+ switch (Vector) {
+ case DEBUG_INT1_VECTOR:
+ case DEBUG_INT3_VECTOR:
+
+ if (Vector == DEBUG_INT1_VECTOR) {
+ //
+ // INT 1
+ //
+ if ((CpuContext->Dr6 & BIT14) != 0) {
+ Cause = DEBUG_DATA_BREAK_CAUSE_STEPPING;
+
+ } else {
+ Cause = DEBUG_DATA_BREAK_CAUSE_HW_BREAKPOINT;
+ }
+ } else {
+ //
+ // INT 3
+ //
+ Cause = DEBUG_DATA_BREAK_CAUSE_SW_BREAKPOINT;
+ }
+
+ switch (CpuContext->Dr0) {
+ case IMAGE_LOAD_SIGNATURE:
+ case IMAGE_UNLOAD_SIGNATURE:
+
+ if (CpuContext->Dr3 == IO_PORT_BREAKPOINT_ADDRESS) {
+
+ Cause = (UINT8) ((CpuContext->Dr0 == IMAGE_LOAD_SIGNATURE) ?
+ DEBUG_DATA_BREAK_CAUSE_IMAGE_LOAD : DEBUG_DATA_BREAK_CAUSE_IMAGE_UNLOAD);
+ }
+ break;
+
+ case SOFT_INTERRUPT_SIGNATURE:
+
+ if (CpuContext->Dr1 == MEMORY_READY_SIGNATURE) {
+ Cause = DEBUG_DATA_BREAK_CAUSE_MEMORY_READY;
+ CpuContext->Dr0 = 0;
+ } else if (CpuContext->Dr1 == SYSTEM_RESET_SIGNATURE) {
+ Cause = DEBUG_DATA_BREAK_CAUSE_SYSTEM_RESET;
+ CpuContext->Dr0 = 0;
+ }
+ break;
+
+ default:
+ break;
+
+ }
+
+ break;
+
+ case DEBUG_TIMER_VECTOR:
+ Cause = DEBUG_DATA_BREAK_CAUSE_USER_HALT;
+ break;
+
+ default:
+ if (Vector < 20) {
+ Cause = DEBUG_DATA_BREAK_CAUSE_EXCEPTION;
+ }
+ break;
+ }
+
+ return Cause;
+}
+
+/**
+ Send packet with response data to HOST.
+
+ @param[in] CpuContext Pointer to saved CPU context.
+ @param[in] Data Pointer to response data buffer.
+ @param[in] DataSize Size of response data in byte.
+
+ @retval RETURN_SUCCESS Response data was sent successfully.
+ @retval RETURN_DEVICE_ERROR Cannot receive DEBUG_COMMAND_OK from HOST.
+
+**/
+RETURN_STATUS
+SendDataResponsePacket (
+ IN DEBUG_CPU_CONTEXT *CpuContext,
+ IN UINT8 *Data,
+ IN UINT16 DataSize
+ )
+{
+ UINT8 PacketHeader[DEBUG_DATA_MAXIMUM_LENGTH_FOR_SMALL_COMMANDS];
+ BOOLEAN LastPacket;
+ UINT8 Ack;
+ UINT8 PacketData[DEBUG_DATA_MAXIMUM_REAL_DATA];
+ DEBUG_PORT_HANDLE Handle;
+
+ Handle = GetDebugPortHandle();
+
+ ((DEBUG_COMMAND_HEADER *)PacketHeader)->StartSymbol = DEBUG_STARTING_SYMBOL_NORMAL;
+
+ while (TRUE) {
+ if (DataSize <= DEBUG_DATA_MAXIMUM_REAL_DATA) {
+ LastPacket = TRUE;
+ ((DEBUG_COMMAND_HEADER *)PacketHeader)->Command = DEBUG_COMMAND_OK;
+ ((DEBUG_COMMAND_HEADER *)PacketHeader)->DataLength = (UINT8) DataSize;
+ CopyMem (PacketData, Data, DataSize);
+
+ } else {
+ LastPacket = FALSE;
+ ((DEBUG_COMMAND_HEADER *)PacketHeader)->Command = DEBUG_COMMAND_IN_PROGRESS;
+ ((DEBUG_COMMAND_HEADER *)PacketHeader)->DataLength = DEBUG_DATA_MAXIMUM_REAL_DATA;
+ CopyMem (PacketData, Data, DEBUG_DATA_MAXIMUM_REAL_DATA);
+ }
+
+ DebugPortWriteBuffer (Handle, PacketHeader, sizeof (DEBUG_COMMAND_HEADER));
+ DebugPortWriteBuffer (Handle, PacketData, ((DEBUG_COMMAND_HEADER *)PacketHeader)->DataLength);
+
+ ReceiveAckPacket(&Ack, 0, NULL);
+ switch (Ack) {
+ case DEBUG_COMMAND_RESEND:
+ //
+ // Send the packet again
+ //
+ break;
+
+ case DEBUG_COMMAND_CONTINUE:
+ //
+ // Send the rest packet
+ //
+ Data += DEBUG_DATA_MAXIMUM_REAL_DATA;
+ DataSize -= DEBUG_DATA_MAXIMUM_REAL_DATA;
+ break;
+
+ case DEBUG_COMMAND_OK:
+ if (LastPacket) {
+ //
+ // If this is the last packet, return RETURN_SUCCESS.
+ //
+ return RETURN_SUCCESS;
+ } else {
+ return RETURN_DEVICE_ERROR;
+ }
+
+ default:
+ return RETURN_DEVICE_ERROR;
+
+ }
+ }
+}
+
+/**
+ Send break cause packet to HOST.
+
+ @param[in] Vector Vector value of exception or interrutp.
+ @param[in] CpuContext Pointer to save CPU context.
+
+ @retval RETURN_SUCCESS Response data was sent successfully.
+ @retval RETURN_DEVICE_ERROR Cannot receive DEBUG_COMMAND_OK from HOST.
+
+**/
+RETURN_STATUS
+SendBreakCausePacket (
+ IN UINTN Vector,
+ IN DEBUG_CPU_CONTEXT *CpuContext
+ )
+{
+ DEBUG_DATA_RESPONSE_BREAK_CAUSE DebugDataBreakCause;
+
+ DebugDataBreakCause.StopAddress = CpuContext->Eip;
+ DebugDataBreakCause.Cause = GetBreakCause (Vector, CpuContext);
+
+ return SendDataResponsePacket (CpuContext, (UINT8 *) &DebugDataBreakCause, (UINT16) sizeof (DEBUG_DATA_RESPONSE_BREAK_CAUSE));
+}
+
+
+/**
+ The main function to process communication with HOST.
+
+ It received the command packet from HOST, and sent response data packet to HOST.
+
+ @param[in] Vector Vector value of exception or interrutp.
+ @param[in, out] CpuContext Pointer to saved CPU context.
+ @param[in] BreakReceived TRUE means break-in symbol received.
+ FALSE means break-in symbol not received.
+
+**/
+VOID
+CommandCommunication (
+ IN UINTN Vector,
+ IN OUT DEBUG_CPU_CONTEXT *CpuContext,
+ IN BOOLEAN BreakReceived
+ )
+{
+ RETURN_STATUS Status;
+ UINT8 InputPacketBuffer[DEBUG_DATA_MAXIMUM_LENGTH_FOR_SMALL_COMMANDS];
+ DEBUG_COMMAND_HEADER *DebugHeader;
+ UINT8 Data8;
+ UINT32 Data32;
+ UINT64 Data64;
+ UINTN DataN;
+ DEBUG_DATA_READ_MEMORY_8 *MemoryRead;
+ DEBUG_DATA_WRITE_MEMORY_8 *MemoryWrite;
+ DEBUG_DATA_READ_IO *IoRead;
+ DEBUG_DATA_WRITE_IO *IoWrite;
+ DEBUG_DATA_READ_REGISTER *RegisterRead;
+ DEBUG_DATA_WRITE_REGISTER *RegisterWrite;
+ UINT8 *RegisterBuffer;
+ DEBUG_DATA_READ_MSR *MsrRegisterRead;
+ DEBUG_DATA_WRITE_MSR *MsrRegisterWrite;
+ DEBUG_DATA_REPONSE_READ_REGISTER_GROUP_SEGLIM RegisterGroupSegLim;
+ DEBUG_DATA_REPONSE_READ_REGISTER_GROUP_SEGBASE RegisterGroupSegBase;
+ DEBUG_DATA_RESPONSE_GET_REVISION DebugAgentRevision;
+ BOOLEAN HaltDeferred;
+ DEBUG_DATA_RESPONSE_GET_EXCEPTION Exception;
+ UINT32 ProcessorIndex;
+ DEBUG_PORT_HANDLE Handle;
+
+ Handle = GetDebugPortHandle();
+
+ ProcessorIndex = 0;
+ HaltDeferred = BreakReceived;
+
+ if (MultiProcessorDebugSupport) {
+ ProcessorIndex = GetProcessorIndex ();
+ SetCpuStopFlagByIndex (ProcessorIndex, TRUE);
+ }
+
+ while (TRUE) {
+
+ if (MultiProcessorDebugSupport) {
+ if (mDebugMpContext.ViewPointIndex != ProcessorIndex) {
+ if (mDebugMpContext.RunCommandSet) {
+ SetCpuStopFlagByIndex (ProcessorIndex, FALSE);
+ CommandGo (CpuContext);
+ break;
+ } else {
+ continue;
+ }
+ }
+ }
+
+ AcquireDebugPortControl ();
+
+ Status = ReceivePacket (InputPacketBuffer, &BreakReceived);
+
+ if (BreakReceived) {
+ HaltDeferred = TRUE;
+ BreakReceived = FALSE;
+ }
+
+ if (Status != RETURN_SUCCESS) {
+ ReleaseDebugPortControl ();
+ continue;
+ }
+
+ Data8 = 1;
+
+ DebugHeader =(DEBUG_COMMAND_HEADER *) InputPacketBuffer;
+ switch (DebugHeader->Command) {
+
+ case DEBUG_COMMAND_RESET:
+ SendAckPacket (DEBUG_COMMAND_OK);
+ ReleaseDebugPortControl ();
+
+ ResetCold ();
+ //
+ // Wait for reset
+ //
+ CpuDeadLoop ();
+ break;
+
+ case DEBUG_COMMAND_GO:
+ CommandGo (CpuContext);
+ if (!HaltDeferred) {
+ //
+ // If no HALT command received when being in-active mode
+ //
+ if (MultiProcessorDebugSupport) {
+ Data32 = FindCpuNotRunning ();
+ if (Data32 != -1) {
+ //
+ // If there are still others processors being in break state,
+ // send OK packet to HOST to finish this go command
+ //
+ SendAckPacket (DEBUG_COMMAND_OK);
+ CpuPause ();
+ //
+ // Set current view to the next breaking processor
+ //
+ mDebugMpContext.ViewPointIndex = Data32;
+ mDebugMpContext.BreakAtCpuIndex = mDebugMpContext.ViewPointIndex;
+ SetCpuBreakFlagByIndex (mDebugMpContext.ViewPointIndex, FALSE);
+ //
+ // Send break packet to HOST and exit to wait for command packet from HOST.
+ //
+ SendAckPacket (DEBUG_COMMAND_BREAK_POINT);
+ WaitForAckPacketOK (0, &BreakReceived);
+ ReleaseDebugPortControl ();
+ break;
+ }
+
+ //
+ // If no else processor break, set stop bitmask,
+ // and set Running flag for all processors.
+ //
+ SetCpuStopFlagByIndex (ProcessorIndex, FALSE);
+ SetCpuRunningFlag (TRUE);
+ CpuPause ();
+ //
+ // Wait for all processors are in running state
+ //
+ while (TRUE) {
+ if (IsAllCpuRunning ()) {
+ break;
+ }
+ }
+ //
+ // Set BSP to be current view point.
+ //
+ SetDebugViewPoint (mDebugMpContext.BspIndex);
+ CpuPause ();
+ //
+ // Clear breaking processor index and running flag
+ //
+ mDebugMpContext.BreakAtCpuIndex = (UINT32) (-1);
+ SetCpuRunningFlag (FALSE);
+ }
+
+ //
+ // Send OK packet to HOST to finish this go command
+ //
+ SendAckPacket (DEBUG_COMMAND_OK);
+
+ ReleaseDebugPortControl ();
+
+ return;
+
+ } else {
+ //
+ // If reveived HALT command, need to defer the GO command
+ //
+ SendAckPacket (DEBUG_COMMAND_HALT_PROCESSED);
+ HaltDeferred = FALSE;
+ Data8 = GetBreakCause (Vector, CpuContext);
+ if (Data8 == DEBUG_DATA_BREAK_CAUSE_IMAGE_LOAD || Data8 == DEBUG_DATA_BREAK_CAUSE_IMAGE_UNLOAD) {
+ CpuContext->Dr0 = 0;
+ CpuContext->Dr3 = 0;
+ }
+
+ Vector = DEBUG_TIMER_VECTOR;
+ }
+ break;
+
+ case DEBUG_COMMAND_BREAK_CAUSE:
+
+ if (MultiProcessorDebugSupport && ProcessorIndex != mDebugMpContext.BreakAtCpuIndex) {
+ Status = SendBreakCausePacket (DEBUG_TIMER_VECTOR, CpuContext);
+
+ } else {
+ Status = SendBreakCausePacket (Vector, CpuContext);
+ }
+
+ break;
+
+ case DEBUG_COMMAND_SET_HW_BREAKPOINT:
+ SetDebugRegister (CpuContext, (DEBUG_DATA_SET_HW_BREAKPOINT *) (DebugHeader + 1));
+ SendAckPacket (DEBUG_COMMAND_OK);
+ break;
+
+ case DEBUG_COMMAND_CLEAR_HW_BREAKPOINT:
+ ClearDebugRegister (CpuContext, (DEBUG_DATA_CLEAR_HW_BREAKPOINT *) (DebugHeader + 1));
+ SendAckPacket (DEBUG_COMMAND_OK);
+ break;
+
+ case DEBUG_COMMAND_SINGLE_STEPPING:
+ CommandStepping (CpuContext);
+
+ mDebugMpContext.BreakAtCpuIndex = (UINT32) (-1);
+
+ ReleaseDebugPortControl ();
+ //
+ // Executing stepping command directly without sending ACK packet.
+ //
+ return;
+
+ case DEBUG_COMMAND_SET_SW_BREAKPOINT:
+ Data64 = (UINTN) (((DEBUG_DATA_SET_SW_BREAKPOINT *) (DebugHeader + 1))->Address);
+ Data8 = *(UINT8 *) (UINTN) Data64;
+ *(UINT8 *) (UINTN) Data64 = DEBUG_SW_BREAKPOINT_SYMBOL;
+ Status = SendDataResponsePacket (CpuContext, (UINT8 *) &Data8, (UINT16) sizeof (UINT8));
+ break;
+
+ case DEBUG_COMMAND_READ_MEMORY_64:
+ Data8 *= 2;
+ case DEBUG_COMMAND_READ_MEMORY_32:
+ Data8 *= 2;
+ case DEBUG_COMMAND_READ_MEMORY_16:
+ Data8 *= 2;
+ case DEBUG_COMMAND_READ_MEMORY_8:
+ MemoryRead = (DEBUG_DATA_READ_MEMORY_8 *) (DebugHeader + 1);
+ Status = SendDataResponsePacket (CpuContext, (UINT8 *) (UINTN) MemoryRead->Address, (UINT16) (MemoryRead->Count * Data8));
+ break;
+
+ case DEBUG_COMMAND_WRITE_MEMORY_64:
+ Data8 *= 2;
+ case DEBUG_COMMAND_WRITE_MEMORY_32:
+ Data8 *= 2;
+ case DEBUG_COMMAND_WRITE_MEMORY_16:
+ Data8 *= 2;
+ case DEBUG_COMMAND_WRITE_MEMORY_8:
+ MemoryWrite = (DEBUG_DATA_WRITE_MEMORY_8 *) (DebugHeader + 1);
+ CopyMem ((VOID *) (UINTN) MemoryWrite->Address, &MemoryWrite->Data, MemoryWrite->Count * Data8);
+ SendAckPacket (DEBUG_COMMAND_OK);
+ break;
+
+ case DEBUG_COMMAND_READ_IO:
+ IoRead = (DEBUG_DATA_READ_IO *) (DebugHeader + 1);
+ switch (IoRead->Width) {
+ case 1:
+ Data64 = IoRead8 (IoRead->Port);
+ break;
+ case 2:
+ Data64 = IoRead16 (IoRead->Port);
+ break;
+ case 4:
+ Data64 = IoRead32 (IoRead->Port);
+ break;
+ case 8:
+ Data64 = IoRead64 (IoRead->Port);
+ break;
+ default:
+ Data64 = (UINT64) -1;
+ }
+ Status = SendDataResponsePacket (CpuContext, (UINT8 *) &Data64, IoRead->Width);
+ break;
+
+ case DEBUG_COMMAND_WRITE_IO:
+ IoWrite = (DEBUG_DATA_WRITE_IO *) (DebugHeader + 1);
+ switch (IoWrite->Width) {
+ case 1:
+ Data64 = IoWrite8 (IoWrite->Port, *(UINT8 *) &IoWrite->Data);
+ break;
+ case 2:
+ Data64 = IoWrite16 (IoWrite->Port, *(UINT16 *) &IoWrite->Data);
+ break;
+ case 4:
+ Data64 = IoWrite32 (IoWrite->Port, *(UINT32 *) &IoWrite->Data);
+ break;
+ case 8:
+ Data64 = IoWrite64 (IoWrite->Port, *(UINT64 *) &IoWrite->Data);
+ break;
+ default:
+ Data64 = (UINT64) -1;
+ }
+ SendAckPacket (DEBUG_COMMAND_OK);
+ break;
+
+ case DEBUG_COMMAND_READ_REGISTER:
+ RegisterRead = (DEBUG_DATA_READ_REGISTER *) (DebugHeader + 1);
+
+ if (RegisterRead->Index < SOFT_DEBUGGER_REGISTER_OTHERS_BASE) {
+ Data8 = RegisterRead->Length;
+ RegisterBuffer = ArchReadRegisterBuffer (CpuContext, RegisterRead->Index, RegisterRead->Offset, &Data8);
+ Status = SendDataResponsePacket (CpuContext, RegisterBuffer, Data8);
+ break;
+ }
+
+ if (RegisterRead->Index <= SOFT_DEBUGGER_REGISTER_TSS_LIM) {
+ ReadRegisterGroupSegLim (CpuContext, &RegisterGroupSegLim);
+ DataN = * ((UINTN *) &RegisterGroupSegLim + (RegisterRead->Index - SOFT_DEBUGGER_REGISTER_CS_LIM));
+ Status = SendDataResponsePacket (CpuContext, (UINT8 *) &DataN, (UINT16) sizeof (UINTN));
+ } else if (RegisterRead->Index <= SOFT_DEBUGGER_REGISTER_TSS_BAS) {
+ ReadRegisterGroupSegBase (CpuContext, &RegisterGroupSegBase);
+ DataN = * ((UINTN *) &RegisterGroupSegBase + (RegisterRead->Index - SOFT_DEBUGGER_REGISTER_CS_BAS));
+ Status = SendDataResponsePacket (CpuContext, (UINT8 *) &DataN, (UINT16) sizeof (UINTN));
+ } else if (RegisterRead->Index < SOFT_DEBUGGER_REGISTER_IDT_LIM) {
+ Data64 = ReadRegisterSelectorByIndex (CpuContext, RegisterRead->Index);
+ Status = SendDataResponsePacket (CpuContext, (UINT8 *) &Data64, (UINT16) sizeof (UINT64));
+ } else {
+ switch (RegisterRead->Index) {
+ case SOFT_DEBUGGER_REGISTER_IDT_LIM:
+ DataN = (UINTN) (CpuContext->Idtr[0] & 0xffff);
+ SendDataResponsePacket (CpuContext, (UINT8 *) &DataN, (UINT16) sizeof (UINTN));
+ break;
+ case SOFT_DEBUGGER_REGISTER_GDT_LIM:
+ DataN = (UINTN) (CpuContext->Gdtr[0] & 0xffff);
+ SendDataResponsePacket (CpuContext, (UINT8 *) &DataN, (UINT16) sizeof (UINTN));
+ break;
+ case SOFT_DEBUGGER_REGISTER_IDT_BAS:
+ DataN = (UINTN) RShiftU64 (CpuContext->Idtr[0], 16);
+ DataN |= (UINTN) LShiftU64 (CpuContext->Idtr[1], (UINT16) (sizeof (UINTN) * 8 - 16));
+ SendDataResponsePacket (CpuContext, (UINT8 *) &DataN, (UINT16) sizeof (UINTN));
+ break;
+ case SOFT_DEBUGGER_REGISTER_GDT_BAS:
+ DataN = (UINTN) RShiftU64 (CpuContext->Gdtr[0], 16);
+ DataN |= (UINTN) LShiftU64 (CpuContext->Gdtr[1], (UINT16) (sizeof (UINTN) * 8 - 16));
+ SendDataResponsePacket (CpuContext, (UINT8 *) &DataN, (UINT16) sizeof (UINTN));
+ break;
+ }
+ }
+ break;
+
+ case DEBUG_COMMAND_WRITE_REGISTER:
+ RegisterWrite = (DEBUG_DATA_WRITE_REGISTER *) (DebugHeader + 1);
+ ArchWriteRegisterBuffer (CpuContext, RegisterWrite->Index, RegisterWrite->Offset, RegisterWrite->Length, (UINT8 *)&RegisterWrite->Value);
+ SendAckPacket (DEBUG_COMMAND_OK);
+ break;
+
+ case DEBUG_COMMAND_ARCH_MODE:
+ Data8 = DEBUG_ARCH_SYMBOL;
+ Status = SendDataResponsePacket (CpuContext, (UINT8 *) &Data8, (UINT16) sizeof (UINT8));
+ break;
+
+ case DEBUG_COMMAND_READ_MSR:
+ MsrRegisterRead = (DEBUG_DATA_READ_MSR *) (DebugHeader + 1);
+ Data64 = AsmReadMsr64 (MsrRegisterRead->Index);
+ Status = SendDataResponsePacket (CpuContext, (UINT8 *) &Data64, (UINT16) sizeof (UINT64));
+ break;
+
+ case DEBUG_COMMAND_WRITE_MSR:
+ MsrRegisterWrite = (DEBUG_DATA_WRITE_MSR *) (DebugHeader + 1);
+ AsmWriteMsr64 (MsrRegisterWrite->Index, MsrRegisterWrite->Value);
+ SendAckPacket (DEBUG_COMMAND_OK);
+ break;
+
+ case DEBUG_COMMAND_READ_REGISTER_GROUP:
+ Data8 = *(UINT8 *) (DebugHeader + 1);
+ Status = ArchReadRegisterGroup (CpuContext, Data8);
+ break;
+
+ case DEBUG_COMMAND_SET_DEBUG_FLAG:
+ Data32 = *(UINT32 *) (DebugHeader + 1);
+ SetDebugFlag (Data32);
+ SendAckPacket (DEBUG_COMMAND_OK);
+ break;
+
+ case DEBUG_COMMAND_GET_REVISION:
+ DebugAgentRevision.Revision = DEBUG_AGENT_REVISION;
+ DebugAgentRevision.Capabilities = DEBUG_AGENT_CAPABILITIES;
+ Status = SendDataResponsePacket (CpuContext, (UINT8 *) &DebugAgentRevision, (UINT16) sizeof (DEBUG_DATA_RESPONSE_GET_REVISION));
+ break;
+
+ case DEBUG_COMMAND_GET_EXCEPTION:
+ Exception.ExceptionNum = (UINT8) Vector;
+ Exception.ExceptionData = 0;
+ Status = SendDataResponsePacket (CpuContext, (UINT8 *) &Exception, (UINT16) sizeof (DEBUG_DATA_RESPONSE_GET_EXCEPTION));
+ break;
+
+ case DEBUG_COMMAND_SET_VIEWPOINT:
+ Data32 = *(UINT32 *) (DebugHeader + 1);
+
+ if (MultiProcessorDebugSupport) {
+ if (IsCpuStopped (Data32)) {
+ SetDebugViewPoint (Data32);
+ SendAckPacket (DEBUG_COMMAND_OK);
+ } else {
+ //
+ // If CPU is not halted
+ //
+ SendAckPacket (DEBUG_COMMAND_NOT_SUPPORTED);
+ }
+ } else if (Data32 == 0) {
+ SendAckPacket (DEBUG_COMMAND_OK);
+
+ } else {
+ SendAckPacket (DEBUG_COMMAND_NOT_SUPPORTED);
+ }
+
+ break;
+
+ case DEBUG_COMMAND_GET_VIEWPOINT:
+ Data32 = mDebugMpContext.ViewPointIndex;
+ SendDataResponsePacket(CpuContext, (UINT8 *) &Data32, (UINT16) sizeof (UINT32));
+ break;
+
+ default:
+ SendAckPacket (DEBUG_COMMAND_NOT_SUPPORTED);
+ break;
+ }
+
+ if (Status == RETURN_UNSUPPORTED) {
+ SendAckPacket (DEBUG_COMMAND_NOT_SUPPORTED);
+ } else if (Status != RETURN_SUCCESS) {
+ SendAckPacket (DEBUG_COMMAND_ABORT);
+ }
+
+ ReleaseDebugPortControl ();
+ CpuPause ();
+ }
+}
+
+/**
+ C function called in interrupt handler.
+
+ @param[in] Vector Vector value of exception or interrutp.
+ @param[in] CpuContext Pointer to save CPU context.
+
+**/
+VOID
+EFIAPI
+InterruptProcess (
+ IN UINT32 Vector,
+ IN DEBUG_CPU_CONTEXT *CpuContext
+ )
+{
+ UINT8 InputCharacter;
+ UINT8 BreakCause;
+ UINTN SavedEip;
+ BOOLEAN BreakReceived;
+ UINT32 ProcessorIndex;
+ UINT32 CurrentDebugTimerInitCount;
+ DEBUG_PORT_HANDLE Handle;
+ UINT8 Data8;
+
+ Handle = GetDebugPortHandle();
+
+ ProcessorIndex = 0;
+ BreakReceived = FALSE;
+
+ if (MultiProcessorDebugSupport) {
+ ProcessorIndex = GetProcessorIndex ();
+ while (mDebugMpContext.RunCommandSet);
+ }
+
+ switch (Vector) {
+ case DEBUG_INT1_VECTOR:
+ case DEBUG_INT3_VECTOR:
+
+ BreakCause = GetBreakCause (Vector, CpuContext);
+
+ if (BreakCause == DEBUG_DATA_BREAK_CAUSE_SYSTEM_RESET) {
+
+ //
+ // Init break, if no ack received after 200ms, return
+ //
+ SendAckPacket (DEBUG_COMMAND_INIT_BREAK);
+ if (WaitForAckPacketOK (200 * 1000, &BreakReceived) != RETURN_SUCCESS) {
+ break;
+ }
+
+ SetHostConnectedFlag ();
+ CommandCommunication (Vector, CpuContext, BreakReceived);
+
+ } else if (BreakCause == DEBUG_DATA_BREAK_CAUSE_STEPPING) {
+
+ //
+ // Stepping is finished, send Ack package.
+ //
+ if (MultiProcessorDebugSupport) {
+ mDebugMpContext.BreakAtCpuIndex = ProcessorIndex;
+ }
+ SendAckPacket (DEBUG_COMMAND_OK);
+ CommandCommunication (Vector, CpuContext, BreakReceived);
+
+ } else if (BreakCause == DEBUG_DATA_BREAK_CAUSE_MEMORY_READY) {
+
+ //
+ // Memory is ready
+ //
+ SendAckPacket (DEBUG_COMMAND_MEMORY_READY);
+ WaitForAckPacketOK (0, &BreakReceived);
+ CommandCommunication (Vector, CpuContext, BreakReceived);
+
+ } else {
+
+ if (BreakCause == DEBUG_DATA_BREAK_CAUSE_IMAGE_LOAD || BreakCause == DEBUG_DATA_BREAK_CAUSE_IMAGE_UNLOAD) {
+
+ //
+ // Set AL to DEBUG_AGENT_IMAGE_CONTINUE
+ //
+ Data8 = DEBUG_AGENT_IMAGE_CONTINUE;
+ ArchWriteRegisterBuffer (CpuContext, SOFT_DEBUGGER_REGISTER_AX, 0, 1, &Data8);
+
+ if (!IsHostConnected ()) {
+ //
+ // If HOST is not connected, return
+ //
+ break;
+ }
+ }
+
+ AcquireDebugPortControl ();
+
+ if (MultiProcessorDebugSupport) {
+ if(!IsAllCpuRunning ()) {
+ //
+ // If other processors have been stopped
+ //
+ SetCpuBreakFlagByIndex (ProcessorIndex, TRUE);
+ } else {
+ //
+ // If no any processor was stopped, try to halt other processors
+ //
+ HaltOtherProcessors (ProcessorIndex);
+ SendAckPacket (DEBUG_COMMAND_BREAK_POINT);
+ WaitForAckPacketOK (0, &BreakReceived);
+ }
+ } else {
+ SendAckPacket (DEBUG_COMMAND_BREAK_POINT);
+ WaitForAckPacketOK (0, &BreakReceived);
+ }
+
+ ReleaseDebugPortControl ();
+
+ if (Vector == DEBUG_INT3_VECTOR) {
+ //
+ // go back address located "0xCC"
+ //
+ CpuContext->Eip--;
+ SavedEip = CpuContext->Eip;
+ CommandCommunication (Vector, CpuContext, BreakReceived);
+ if ((SavedEip == CpuContext->Eip) &&
+ (*(UINT8 *) (UINTN) CpuContext->Eip == DEBUG_SW_BREAKPOINT_SYMBOL)) {
+ //
+ // If this is not a software breakpoint set by HOST,
+ // restore EIP
+ //
+ CpuContext->Eip++;
+ }
+ } else {
+ CommandCommunication (Vector, CpuContext, BreakReceived);
+ }
+ }
+
+ break;
+
+ case DEBUG_TIMER_VECTOR:
+
+ if (MultiProcessorDebugSupport) {
+ if (IsBsp (ProcessorIndex)) {
+ //
+ // If current processor is BSP, check Apic timer's init count if changed,
+ // it may be re-written when switching BSP.
+ // If it changed, re-initialize debug timer
+ //
+ CurrentDebugTimerInitCount = GetApicTimerInitCount ();
+ if (mDebugMpContext.DebugTimerInitCount != CurrentDebugTimerInitCount) {
+ InitializeDebugTimer ();
+ }
+ }
+
+ if (!IsBsp (ProcessorIndex) || mDebugMpContext.IpiSentByAp) {
+ //
+ // If current processor is not BSP or this is one IPI sent by AP
+ //
+ if (mDebugMpContext.BreakAtCpuIndex != (UINT32) (-1)) {
+ CommandCommunication (Vector, CpuContext, FALSE);
+ }
+
+ //
+ // Clear EOI before exiting interrupt process routine.
+ //
+ SendApicEoi ();
+ break;
+ }
+ }
+
+ //
+ // Only BSP could run here
+ //
+
+ AcquireDebugPortControl ();
+
+ while (DebugPortPollBuffer (Handle)) {
+ //
+ // If there is data in debug port, will check whether it is break-in symbol,
+ // If yes, go into communication mode with HOST.
+ // If no, exit interrupt process.
+ //
+ DebugPortReadBuffer (Handle, &InputCharacter, 1, 0);
+ if (InputCharacter == DEBUG_STARTING_SYMBOL_BREAK) {
+ SendAckPacket (DEBUG_COMMAND_OK);
+ if (MultiProcessorDebugSupport) {
+ if(FindCpuNotRunning () != -1) {
+ SetCpuBreakFlagByIndex (ProcessorIndex, TRUE);
+ } else {
+ HaltOtherProcessors (ProcessorIndex);
+ }
+ }
+ ReleaseDebugPortControl ();
+ CommandCommunication (Vector, CpuContext, BreakReceived);
+ AcquireDebugPortControl ();
+ break;
+ }
+ }
+
+ //
+ // Clear EOI before exiting interrupt process routine.
+ //
+ SendApicEoi ();
+
+ ReleaseDebugPortControl ();
+
+ break;
+
+ default:
+
+ if (Vector <= DEBUG_EXCEPT_SIMD) {
+
+ AcquireDebugPortControl ();
+
+ if (MultiProcessorDebugSupport) {
+ if(FindCpuNotRunning () != -1) {
+ SetCpuBreakFlagByIndex (ProcessorIndex, TRUE);
+ } else {
+ HaltOtherProcessors (ProcessorIndex);
+ }
+ }
+ SendAckPacket (DEBUG_COMMAND_BREAK_POINT);
+ WaitForAckPacketOK (0, &BreakReceived);
+ ReleaseDebugPortControl ();
+ CommandCommunication (Vector, CpuContext, BreakReceived);
+ }
+ break;
+ }
+
+ if (MultiProcessorDebugSupport) {
+ //
+ // Clear flag and wait for all processors run here
+ //
+ SetIpiSentByApFlag (FALSE);
+ while (mDebugMpContext.RunCommandSet);
+ }
+
+ return;
+}
+
diff --git a/SourceLevelDebugPkg/Library/DebugAgent/DebugAgentCommon/DebugAgent.h b/SourceLevelDebugPkg/Library/DebugAgent/DebugAgentCommon/DebugAgent.h
new file mode 100644
index 000000000..9671ca4ef
--- /dev/null
+++ b/SourceLevelDebugPkg/Library/DebugAgent/DebugAgentCommon/DebugAgent.h
@@ -0,0 +1,308 @@
+/** @file
+ Command header of for Debug Agent library instance.
+
+ Copyright (c) 2010, Intel Corporation. All rights reserved.<BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php.
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef _DEBUG_AGENT_H_
+#define _DEBUG_AGENT_H_
+
+#include <Register/LocalApic.h>
+
+#include <Guid/DebugAgentGuid.h>
+
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/ResetSystemLib.h>
+#include <Library/IoLib.h>
+#include <Library/HobLib.h>
+#include <Library/DebugCommunicationLib.h>
+#include <Library/DebugAgentLib.h>
+#include <Library/PcdLib.h>
+#include <Library/SynchronizationLib.h>
+#include <Library/LocalApicLib.h>
+
+#include <TransferProtocol.h>
+#include <ImageDebugSupport.h>
+
+#include "DebugMp.h"
+#include "DebugTimer.h"
+#include "ArchDebugSupport.h"
+
+#define DEBUG_AGENT_REVISION ((0 << 16) | 01)
+#define DEBUG_AGENT_CAPABILITIES 0
+
+#define DEBUG_INT1_VECTOR 1
+#define DEBUG_INT3_VECTOR 3
+#define DEBUG_TIMER_VECTOR 32
+#define DEBUG_MAILBOX_VECTOR 33
+
+#define SOFT_INTERRUPT_SIGNATURE SIGNATURE_32('S','O','F','T')
+#define SYSTEM_RESET_SIGNATURE SIGNATURE_32('S','Y','S','R')
+#define MEMORY_READY_SIGNATURE SIGNATURE_32('M','E','M','R')
+
+extern UINTN Exception0Handle;
+extern UINTN TimerInterruptHandle;
+extern UINT16 ExceptionStubHeaderSize;
+
+typedef union {
+ struct {
+ UINT32 HostPresent : 1;
+ UINT32 BreakOnNextSmi : 1;
+ UINT32 Reserved : 30;
+ } Bits;
+ UINT32 Uint32;
+} DEBUG_AGENT_FLAG;
+
+#pragma pack(1)
+typedef struct {
+ DEBUG_AGENT_FLAG DebugFlag;
+ UINT64 DebugPortHandle;
+} DEBUG_AGENT_MAILBOX;
+#pragma pack()
+
+typedef union {
+ struct {
+ UINT32 LimitLow : 16;
+ UINT32 BaseLow : 16;
+ UINT32 BaseMid : 8;
+ UINT32 Type : 4;
+ UINT32 System : 1;
+ UINT32 Dpl : 2;
+ UINT32 Present : 1;
+ UINT32 LimitHigh : 4;
+ UINT32 Software : 1;
+ UINT32 Reserved : 1;
+ UINT32 DefaultSize : 1;
+ UINT32 Granularity : 1;
+ UINT32 BaseHigh : 8;
+ } Bits;
+ UINT64 Uint64;
+} IA32_GDT;
+
+/**
+ Caller provided function to be invoked at the end of DebugPortInitialize().
+
+ Refer to the descrption for DebugPortInitialize() for more details.
+
+ @param[in] Context The first input argument of DebugPortInitialize().
+ @param[in] DebugPortHandle Debug port handle created by Debug Communication Libary.
+
+**/
+VOID
+EFIAPI
+InitializeDebugAgentPhase2 (
+ IN VOID *Context,
+ IN DEBUG_PORT_HANDLE DebugPortHandle
+ );
+
+/**
+ Initialize IDT entries to support source level debug.
+
+**/
+VOID
+InitializeDebugIdt (
+ VOID
+ );
+
+/**
+ Write specified register into save CPU context.
+
+ @param[in] CpuContext Pointer to saved CPU context.
+ @param[in] Index Register index value.
+ @param[in] Offset Offset in register address range
+ @param[in] Width Data width to read.
+ @param[in] RegisterBuffer Pointer to input buffer with data.
+
+**/
+VOID
+ArchWriteRegisterBuffer (
+ IN DEBUG_CPU_CONTEXT *CpuContext,
+ IN UINT8 Index,
+ IN UINT8 Offset,
+ IN UINT8 Width,
+ IN UINT8 *RegisterBuffer
+ );
+
+/**
+ Read register value from saved CPU context.
+
+ @param[in] CpuContext Pointer to saved CPU context.
+ @param[in] Index Register index value.
+ @param[in] Offset Offset in register address range
+ @param[in] Width Data width to read.
+
+ @return The address of register value.
+
+**/
+UINT8 *
+ArchReadRegisterBuffer (
+ IN DEBUG_CPU_CONTEXT *CpuContext,
+ IN UINT8 Index,
+ IN UINT8 Offset,
+ IN UINT8 *Width
+ );
+
+/**
+ Send packet with response data to HOST.
+
+ @param[in] CpuContext Pointer to saved CPU context.
+ @param[in] Data Pointer to response data buffer.
+ @param[in] DataSize Size of response data in byte.
+
+ @retval RETURN_SUCCESS Response data was sent successfully.
+ @retval RETURN_DEVICE_ERROR Cannot receive DEBUG_COMMAND_OK from HOST.
+
+**/
+RETURN_STATUS
+SendDataResponsePacket (
+ IN DEBUG_CPU_CONTEXT *CpuContext,
+ IN UINT8 *Data,
+ IN UINT16 DataSize
+ );
+
+/**
+ Read segment selector by register index.
+
+ @param[in] CpuContext Pointer to saved CPU context.
+ @param[in] RegisterIndex Register Index.
+
+ @return Value of segment selector.
+
+**/
+UINT64
+ReadRegisterSelectorByIndex (
+ IN DEBUG_CPU_CONTEXT *CpuContext,
+ IN UINT8 RegisterIndex
+ );
+
+/**
+ Read group register of common registers.
+
+ @param[in] CpuContext Pointer to saved CPU context.
+ @param[in] RegisterGroup Pointer to Group registers.
+
+**/
+VOID
+ReadRegisterGroup (
+ IN DEBUG_CPU_CONTEXT *CpuContext,
+ IN DEBUG_DATA_REPONSE_READ_REGISTER_GROUP *RegisterGroup
+ );
+
+/**
+ Read group register of Segment Base.
+
+ @param[in] CpuContext Pointer to saved CPU context.
+ @param[in] RegisterGroupSegBase Pointer to Group registers.
+
+**/
+VOID
+ReadRegisterGroupSegBase (
+ IN DEBUG_CPU_CONTEXT *CpuContext,
+ IN DEBUG_DATA_REPONSE_READ_REGISTER_GROUP_SEGBASE *RegisterGroupSegBase
+ );
+
+/**
+ Read gourp register of Segment Limit.
+
+ @param[in] CpuContext Pointer to saved CPU context.
+ @param[in] RegisterGroupSegLim Pointer to Group registers.
+
+**/
+VOID
+ReadRegisterGroupSegLim (
+ IN DEBUG_CPU_CONTEXT *CpuContext,
+ IN DEBUG_DATA_REPONSE_READ_REGISTER_GROUP_SEGLIM *RegisterGroupSegLim
+ );
+
+/**
+ Read group register by group index.
+
+ @param[in] CpuContext Pointer to saved CPU context.
+ @param[in] GroupIndex Group Index.
+
+ @retval RETURN_SUCCESS Read successfully.
+ @retval RETURN_NOT_SUPPORTED Group index cannot be supported.
+
+**/
+RETURN_STATUS
+ArchReadRegisterGroup (
+ IN DEBUG_CPU_CONTEXT *CpuContext,
+ IN UINT8 GroupIndex
+ );
+
+/**
+ Send acknowledge packet to HOST.
+
+ @param AckCommand Type of Acknowledge packet.
+
+**/
+VOID
+SendAckPacket (
+ IN UINT8 AckCommand
+ );
+
+/**
+ Receive acknowledge packet OK from HOST in specified time.
+
+ @param[in] Timeout Time out value to wait for acknowlege from HOST.
+ The unit is microsecond.
+ @param[out] BreakReceived If BreakReceived is not NULL,
+ TRUE is retured if break-in symbol received.
+ FALSE is retured if break-in symbol not received.
+
+ @retval RETRUEN_SUCCESS Succeed to receive acknowlege packet from HOST,
+ the type of acknowlege packet saved in Ack.
+ @retval RETURN_TIMEOUT Specified timeout value was up.
+
+**/
+RETURN_STATUS
+WaitForAckPacketOK (
+ IN UINTN Timeout,
+ OUT BOOLEAN *BreakReceived OPTIONAL
+ );
+
+/**
+ Check if HOST is connected based on Mailbox.
+
+ @retval TRUE HOST is connected.
+ @retval FALSE HOST is not connected.
+
+**/
+BOOLEAN
+IsHostConnected (
+ VOID
+ );
+
+/**
+ Get Debug Agent Mailbox pointer.
+
+ @return Mailbox pointer.
+
+**/
+DEBUG_AGENT_MAILBOX *
+GetMailboxPointer (
+ VOID
+ );
+
+/**
+ Get debug port handle.
+
+ @return Debug port handle.
+
+**/
+DEBUG_PORT_HANDLE
+GetDebugPortHandle (
+ VOID
+ );
+
+#endif
+
diff --git a/SourceLevelDebugPkg/Library/DebugAgent/DebugAgentCommon/DebugMp.c b/SourceLevelDebugPkg/Library/DebugAgent/DebugAgentCommon/DebugMp.c
new file mode 100644
index 000000000..7d053fadc
--- /dev/null
+++ b/SourceLevelDebugPkg/Library/DebugAgent/DebugAgentCommon/DebugMp.c
@@ -0,0 +1,365 @@
+/** @file
+ Multi-Processor support functions implementation.
+
+ Copyright (c) 2010, Intel Corporation. All rights reserved.<BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php.
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "DebugAgent.h"
+
+DEBUG_MP_CONTEXT volatile mDebugMpContext = {0,0,0,0,0,0,0,0,FALSE,FALSE};
+
+DEBUG_CPU_DATA volatile mDebugCpuData = {0};
+
+/**
+ Acquire access control on debug port.
+
+ It will block in the function if cannot get the access control.
+
+**/
+VOID
+AcquireDebugPortControl (
+ VOID
+ )
+{
+ if (!MultiProcessorDebugSupport) {
+ return;
+ }
+
+ while (TRUE) {
+ if (AcquireSpinLockOrFail (&mDebugMpContext.DebugPortSpinLock)) {
+ break;
+ }
+ CpuPause ();
+ continue;
+ }
+}
+
+/**
+ Release access control on debug port.
+
+**/
+VOID
+ReleaseDebugPortControl (
+ VOID
+ )
+{
+ if (!MultiProcessorDebugSupport) {
+ return;
+ }
+
+ ReleaseSpinLock (&mDebugMpContext.DebugPortSpinLock);
+}
+
+/**
+ Acquire access control on MP context.
+
+ It will block in the function if cannot get the access control.
+
+**/
+VOID
+AcquireMpContextControl (
+ VOID
+ )
+{
+ while (TRUE) {
+ if (AcquireSpinLockOrFail (&mDebugMpContext.MpContextSpinLock)) {
+ break;
+ }
+ CpuPause ();
+ continue;
+ }
+}
+
+/**
+ Release access control on MP context.
+
+**/
+VOID
+ReleaseMpContextControl (
+ VOID
+ )
+{
+ ReleaseSpinLock (&mDebugMpContext.MpContextSpinLock);
+}
+
+/**
+ Break the other processor by send IPI.
+
+ @param[in] CurrentProcessorIndex Current processor index value.
+
+**/
+VOID
+HaltOtherProcessors (
+ IN UINT32 CurrentProcessorIndex
+ )
+{
+
+ if (!IsBsp (CurrentProcessorIndex)) {
+ SetIpiSentByApFlag (TRUE);;
+ }
+
+ mDebugMpContext.BreakAtCpuIndex = CurrentProcessorIndex;
+
+ //
+ // Send fixed IPI to other processors.
+ //
+ SendFixedIpiAllExcludingSelf (DEBUG_TIMER_VECTOR);
+
+}
+
+/**
+ Get the current processor's index.
+
+ @return Processor index value.
+
+**/
+UINT32
+GetProcessorIndex (
+ VOID
+ )
+{
+ UINT32 Index;
+ UINT16 LocalApicID;
+
+ LocalApicID = (UINT16) GetApicId ();
+
+ AcquireMpContextControl ();
+
+ for (Index = 0; Index < mDebugCpuData.CpuCount; Index ++) {
+ if (mDebugCpuData.ApicID[Index] == LocalApicID) {
+ break;
+ }
+ }
+
+ if (Index == mDebugCpuData.CpuCount) {
+ mDebugCpuData.ApicID[Index] = LocalApicID;
+ mDebugCpuData.CpuCount ++ ;
+ }
+
+ ReleaseMpContextControl ();
+
+ return Index;
+}
+
+/**
+ Check if the specified processor is BSP or not.
+
+ @param[in] ProcessorIndex Processor index value.
+
+ @retval TRUE It is BSP.
+ @retval FALSE It isn't BSP.
+
+**/
+BOOLEAN
+IsBsp (
+ IN UINT32 ProcessorIndex
+ )
+{
+ if (AsmMsrBitFieldRead64 (MSR_IA32_APIC_BASE_ADDRESS, 8, 8) == 1) {
+ if (mDebugMpContext.BspIndex != ProcessorIndex) {
+ AcquireMpContextControl ();
+ mDebugMpContext.BspIndex = ProcessorIndex;
+ ReleaseMpContextControl ();
+ }
+ return TRUE;
+ } else {
+ return FALSE;
+ }
+}
+
+/**
+ Set processor stop flag bitmask in MP context.
+
+ @param[in] ProcessorIndex Processor index value.
+ @param[in] StopFlag TRUE means set stop flag.
+ FALSE means clean break flag.
+
+**/
+VOID
+SetCpuStopFlagByIndex (
+ IN UINT32 ProcessorIndex,
+ IN BOOLEAN StopFlag
+ )
+{
+ UINT8 Value;
+ UINTN Index;
+
+ AcquireMpContextControl ();
+
+ Value = mDebugMpContext.CpuStopStatusMask[ProcessorIndex / 8];
+ Index = ProcessorIndex % 8;
+ if (StopFlag) {
+ Value = BitFieldWrite8 (Value, Index, Index, 1);
+ } else {
+ Value = BitFieldWrite8 (Value, Index, Index, 0);
+ }
+ mDebugMpContext.CpuStopStatusMask[ProcessorIndex / 8] = Value;
+
+ ReleaseMpContextControl ();
+}
+
+/**
+ Set processor break flag bitmask in MP context.
+
+ @param[in] ProcessorIndex Processor index value.
+ @param[in] BreakFlag TRUE means set break flag.
+ FALSE means clean break flag.
+
+**/
+VOID
+SetCpuBreakFlagByIndex (
+ IN UINT32 ProcessorIndex,
+ IN BOOLEAN BreakFlag
+ )
+{
+ UINT8 Value;
+ UINTN Index;
+
+ AcquireMpContextControl ();
+
+ Value = mDebugMpContext.CpuBreakMask[ProcessorIndex / 8];
+ Index = ProcessorIndex % 8;
+ if (BreakFlag) {
+ Value = BitFieldWrite8 (Value, Index, Index, 1);
+ } else {
+ Value = BitFieldWrite8 (Value, Index, Index, 0);
+ }
+ mDebugMpContext.CpuBreakMask[ProcessorIndex / 8] = Value;
+
+ ReleaseMpContextControl ();
+}
+
+/**
+ Check if processor is stopped already.
+
+ @param[in] ProcessorIndex Processor index value.
+
+ @retval TRUE Processor is stopped already.
+ @retval TRUE Processor isn't stopped.
+
+**/
+BOOLEAN
+IsCpuStopped (
+ IN UINT32 ProcessorIndex
+ )
+{
+ UINT8 CpuMask;
+
+ CpuMask = (UINT8) (1 << (ProcessorIndex % 8));
+
+ if ((mDebugMpContext.CpuStopStatusMask[ProcessorIndex / 8] & CpuMask) != 0) {
+ return TRUE;
+ } else {
+ return FALSE;
+ }
+}
+
+/**
+ Set the run command flag.
+
+ @param[in] RunningFlag TRUE means run command flag is set.
+ FALSE means run command flag is cleared.
+
+**/
+VOID
+SetCpuRunningFlag (
+ IN BOOLEAN RunningFlag
+ )
+{
+ AcquireMpContextControl ();
+
+ mDebugMpContext.RunCommandSet = RunningFlag;
+
+ ReleaseMpContextControl ();
+}
+
+/**
+ Set the current view point to be debugged.
+
+ @param[in] ProcessorIndex Processor index value.
+
+**/
+VOID
+SetDebugViewPoint (
+ IN UINT32 ProcessorIndex
+ )
+{
+ AcquireMpContextControl ();
+
+ mDebugMpContext.ViewPointIndex = ProcessorIndex;
+
+ ReleaseMpContextControl ();
+}
+
+/**
+ Initialize debug timer.
+
+ @param[in] IpiSentByApFlag TRUE means this IPI is sent by AP.
+ FALSE means this IPI is sent by BSP.
+
+**/
+VOID
+SetIpiSentByApFlag (
+ IN BOOLEAN IpiSentByApFlag
+ )
+{
+ AcquireMpContextControl ();
+
+ mDebugMpContext.IpiSentByAp = IpiSentByApFlag;
+
+ ReleaseMpContextControl ();
+}
+
+/**
+ Check if any processor breaks.
+
+ @retval others There is at least one processor broken, the minimum
+ index number of Processor returned.
+ @retval -1 No any processor broken.
+
+**/
+UINT32
+FindCpuNotRunning (
+ VOID
+ )
+{
+ UINT32 Index;
+
+ for (Index = 0; Index < DEBUG_CPU_MAX_COUNT / 8; Index ++) {
+ if (mDebugMpContext.CpuBreakMask[Index] != 0) {
+ return (UINT32) LowBitSet32 (mDebugMpContext.CpuBreakMask[Index]) + Index * 8;
+ }
+ }
+ return (UINT32)-1;
+}
+
+/**
+ Check if all processors are in running status.
+
+ @retval TRUE All processors run.
+ @retval FALSE At least one processor does not run.
+
+**/
+BOOLEAN
+IsAllCpuRunning (
+ VOID
+ )
+{
+ UINTN Index;
+
+ for (Index = 0; Index < DEBUG_CPU_MAX_COUNT / 8; Index ++) {
+ if (mDebugMpContext.CpuStopStatusMask[Index] != 0) {
+ return FALSE;
+ }
+ }
+ return TRUE;
+}
+
diff --git a/SourceLevelDebugPkg/Library/DebugAgent/DebugAgentCommon/DebugMp.h b/SourceLevelDebugPkg/Library/DebugAgent/DebugAgentCommon/DebugMp.h
new file mode 100644
index 000000000..db124599a
--- /dev/null
+++ b/SourceLevelDebugPkg/Library/DebugAgent/DebugAgentCommon/DebugMp.h
@@ -0,0 +1,221 @@
+/** @file
+ Header file for Multi-Processor support.
+
+ Copyright (c) 2010, Intel Corporation. All rights reserved.<BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php.
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef _DEBUG_MP_H_
+#define _DEBUG_MP_H_
+
+#define DEBUG_CPU_MAX_COUNT 256
+
+typedef struct {
+ UINT32 CpuCount; ///< Processor count
+ UINT16 ApicID[DEBUG_CPU_MAX_COUNT]; ///< Record the local apic id for each processor
+} DEBUG_CPU_DATA;
+
+typedef struct {
+ SPIN_LOCK MpContextSpinLock; ///< Lock for writting MP context
+ SPIN_LOCK DebugPortSpinLock; ///< Lock for access debug port
+ UINT8 CpuBreakMask[DEBUG_CPU_MAX_COUNT/8]; ///< Bitmask of all breaking CPUs
+ UINT8 CpuStopStatusMask[DEBUG_CPU_MAX_COUNT/8]; ///< Bitmask of CPU stop status
+ UINT32 ViewPointIndex; ///< Current view point to be debugged
+ UINT32 BspIndex; ///< Processor index value of BSP
+ UINT32 BreakAtCpuIndex; ///< Processor index value of the current breaking CPU
+ UINT32 DebugTimerInitCount; ///< Record BSP's init timer count
+ BOOLEAN IpiSentByAp; ///< TRUR: IPI is sent by AP. TALSE: IPI is sent by BSP
+ BOOLEAN RunCommandSet; ///< TRUE: RUN commmand is not executed. FALSE : RUN command is executed.
+} DEBUG_MP_CONTEXT;
+
+extern CONST BOOLEAN MultiProcessorDebugSupport;
+extern DEBUG_MP_CONTEXT volatile mDebugMpContext;
+extern DEBUG_CPU_DATA volatile mDebugCpuData;
+
+/**
+ Break the other processor by send IPI.
+
+ @param[in] CurrentProcessorIndex Current processor index value.
+
+**/
+VOID
+HaltOtherProcessors (
+ IN UINT32 CurrentProcessorIndex
+ );
+
+/**
+ Get the current processor's index.
+
+ @return Processor index value.
+
+**/
+UINT32
+GetProcessorIndex (
+ VOID
+ );
+
+/**
+ Acquire access control on MP context.
+
+ It will block in the function if cannot get the access control.
+
+**/
+VOID
+AcquireMpContextControl (
+ VOID
+ );
+
+/**
+ Release access control on MP context.
+
+**/
+VOID
+ReleaseMpContextControl (
+ VOID
+ );
+
+/**
+ Acquire access control on debug port.
+
+ It will block in the function if cannot get the access control.
+
+**/
+VOID
+AcquireDebugPortControl (
+ VOID
+ );
+
+/**
+ Release access control on debug port.
+
+**/
+VOID
+ReleaseDebugPortControl (
+ VOID
+ );
+
+/**
+ Check if the specified processor is BSP or not.
+
+ @param[in] ProcessorIndex Processor index value.
+
+ @retval TRUE It is BSP.
+ @retval FALSE It isn't BSP.
+
+**/
+BOOLEAN
+IsBsp (
+ IN UINT32 ProcessorIndex
+ );
+
+/**
+ Set processor stop flag bitmask in MP context.
+
+ @param[in] ProcessorIndex Processor index value.
+ @param[in] StopFlag TRUE means set stop flag.
+ FALSE means clean break flag.
+
+**/
+VOID
+SetCpuStopFlagByIndex (
+ IN UINT32 ProcessorIndex,
+ IN BOOLEAN StopFlag
+ );
+
+/**
+ Set processor break flag bitmask in MP context.
+
+ @param[in] ProcessorIndex Processor index value.
+ @param[in] BreakFlag TRUE means set break flag.
+ FALSE means clean break flag.
+
+**/
+VOID
+SetCpuBreakFlagByIndex (
+ IN UINT32 ProcessorIndex,
+ IN BOOLEAN BreakFlag
+ );
+
+/**
+ Check if processor is stopped already.
+
+ @param[in] ProcessorIndex Processor index value.
+
+ @retval TRUE Processor is stopped already.
+ @retval FALSE Processor isn't stopped.
+
+**/
+BOOLEAN
+IsCpuStopped (
+ IN UINT32 ProcessorIndex
+ );
+
+/**
+ Set the run command flag.
+
+ @param[in] RunningFlag TRUE means run command flag is set.
+ FALSE means run command flag is cleared.
+
+**/
+VOID
+SetCpuRunningFlag (
+ IN BOOLEAN RunningFlag
+ );
+
+/**
+ Set the current view point to be debugged.
+
+ @param[in] ProcessorIndex Processor index value.
+
+**/
+VOID
+SetDebugViewPoint (
+ IN UINT32 ProcessorIndex
+ );
+
+/**
+ Initialize debug timer.
+
+ @param[in] IpiSentByApFlag TRUE means this IPI is sent by AP.
+ FALSE means this IPI is sent by BSP.
+
+**/
+VOID
+SetIpiSentByApFlag (
+ IN BOOLEAN IpiSentByApFlag
+ );
+
+/**
+ Check if any processor breaks.
+
+ @retval others There is at least one processor broken, the minimum
+ index number of Processor returned.
+ @retval -1 No any processor broken.
+
+**/
+UINT32
+FindCpuNotRunning (
+ VOID
+ );
+
+/**
+ Check if all processors are in running status.
+
+ @retval TRUE All processors run.
+ @retval FALSE At least one processor does not run.
+
+**/
+BOOLEAN
+IsAllCpuRunning (
+ VOID
+ );
+
+#endif
+
diff --git a/SourceLevelDebugPkg/Library/DebugAgent/DebugAgentCommon/DebugTimer.c b/SourceLevelDebugPkg/Library/DebugAgent/DebugAgentCommon/DebugTimer.c
new file mode 100644
index 000000000..d473df867
--- /dev/null
+++ b/SourceLevelDebugPkg/Library/DebugAgent/DebugAgentCommon/DebugTimer.c
@@ -0,0 +1,83 @@
+/** @file
+ Code for debug timer to support debug agent library implementation.
+
+ Copyright (c) 2010, Intel Corporation. All rights reserved.<BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php.
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "DebugAgent.h"
+
+/**
+ Initialize CPU local APIC timer.
+
+**/
+VOID
+InitializeDebugTimer (
+ VOID
+ )
+{
+ UINTN ApicTimerDivisor;
+ UINT32 InitialCount;
+
+ GetApicTimerState (&ApicTimerDivisor, NULL, NULL);
+
+ //
+ // Cpu Local Apic timer interrupt frequency, it is set to 0.1s
+ //
+ InitialCount = (UINT32)DivU64x32 (
+ MultU64x64 (
+ PcdGet32(PcdFSBClock) / (UINT32)ApicTimerDivisor,
+ 100
+ ),
+ 1000
+ );
+
+ InitializeApicTimer (ApicTimerDivisor, InitialCount, TRUE, DEBUG_TIMER_VECTOR);
+
+ if (MultiProcessorDebugSupport) {
+ mDebugMpContext.DebugTimerInitCount = InitialCount;
+ }
+}
+
+/**
+ Enable/Disable the interrupt of debug timer and return the interrupt state
+ prior to the operation.
+
+ If EnableStatus is TRUE, enable the interrupt of debug timer.
+ If EnableStatus is FALSE, disable the interrupt of debug timer.
+
+ @param[in] EnableStatus Enable/Disable.
+
+ @retval TRUE Debug timer interrupt were enabled on entry to this call.
+ @retval FALSE Debug timer interrupt were disabled on entry to this call.
+
+**/
+BOOLEAN
+EFIAPI
+SaveAndSetDebugTimerInterrupt (
+ IN BOOLEAN EnableStatus
+ )
+{
+ BOOLEAN OldInterruptState;
+ BOOLEAN OldDebugTimerInterruptState;
+
+ OldInterruptState = SaveAndDisableInterrupts ();
+ OldDebugTimerInterruptState = GetApicTimerInterruptState ();
+
+ if (EnableStatus) {
+ EnableApicTimerInterrupt ();
+ } else {
+ DisableApicTimerInterrupt ();
+ }
+
+ SetInterruptState (OldInterruptState);
+ return OldDebugTimerInterruptState;
+}
+
diff --git a/SourceLevelDebugPkg/Library/DebugAgent/DebugAgentCommon/DebugTimer.h b/SourceLevelDebugPkg/Library/DebugAgent/DebugAgentCommon/DebugTimer.h
new file mode 100644
index 000000000..4970f93da
--- /dev/null
+++ b/SourceLevelDebugPkg/Library/DebugAgent/DebugAgentCommon/DebugTimer.h
@@ -0,0 +1,28 @@
+/** @file
+ Header file for debug timer to support debug agent library implementation.
+
+ Copyright (c) 2010, Intel Corporation. All rights reserved.<BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php.
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef _DEBUG_TIMER_H_
+#define _DEBUG_TIMER_H_
+
+/**
+ Initialize debug timer.
+
+**/
+VOID
+InitializeDebugTimer (
+ VOID
+ );
+
+#endif
+
diff --git a/SourceLevelDebugPkg/Library/DebugAgent/DebugAgentCommon/Ia32/ArchDebugSupport.c b/SourceLevelDebugPkg/Library/DebugAgent/DebugAgentCommon/Ia32/ArchDebugSupport.c
new file mode 100644
index 000000000..ab724ff3d
--- /dev/null
+++ b/SourceLevelDebugPkg/Library/DebugAgent/DebugAgentCommon/Ia32/ArchDebugSupport.c
@@ -0,0 +1,242 @@
+/** @file
+ Public include file for Debug Port Library.
+
+ Copyright (c) 2010, Intel Corporation. All rights reserved.<BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php.
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "DebugAgent.h"
+
+/**
+ Read the offset of FP / MMX / XMM registers by register index.
+
+ @param[in] Index Register index.
+ @param[out] Width Register width returned.
+
+ @return Offset in register address range.
+
+**/
+UINT16
+ArchReadFxStatOffset (
+ IN UINT8 Index,
+ OUT UINT8 *Width
+ )
+{
+ if (Index < SOFT_DEBUGGER_REGISTER_ST0) {
+ switch (Index) {
+ case SOFT_DEBUGGER_REGISTER_FP_FCW:
+ *Width = (UINT8) sizeof (UINT16);
+ return (UINT16)OFFSET_OF(DEBUG_DATA_IA32_FX_SAVE_STATE, Fcw);
+
+ case SOFT_DEBUGGER_REGISTER_FP_FSW:
+ *Width = (UINT8) sizeof (UINT16);
+ return (UINT16)OFFSET_OF(DEBUG_DATA_IA32_FX_SAVE_STATE, Fsw);
+
+ case SOFT_DEBUGGER_REGISTER_FP_FTW:
+ *Width = (UINT8) sizeof (UINT16);
+ return (UINT16)OFFSET_OF(DEBUG_DATA_IA32_FX_SAVE_STATE, Ftw);
+
+ case SOFT_DEBUGGER_REGISTER_FP_OPCODE:
+ *Width = (UINT8) sizeof (UINT16);
+ return (UINT16)OFFSET_OF(DEBUG_DATA_IA32_FX_SAVE_STATE, Opcode);
+
+ case SOFT_DEBUGGER_REGISTER_FP_EIP:
+ *Width = (UINT8) sizeof (UINTN);
+ return (UINT16)OFFSET_OF(DEBUG_DATA_IA32_FX_SAVE_STATE, Eip);
+
+ case SOFT_DEBUGGER_REGISTER_FP_CS:
+ *Width = (UINT8) sizeof (UINT16);
+ return (UINT16)OFFSET_OF(DEBUG_DATA_IA32_FX_SAVE_STATE, Cs);
+
+ case SOFT_DEBUGGER_REGISTER_FP_DATAOFFSET:
+ *Width = (UINT8) sizeof (UINTN);
+ return (UINT16)OFFSET_OF(DEBUG_DATA_IA32_FX_SAVE_STATE, DataOffset);
+
+ case SOFT_DEBUGGER_REGISTER_FP_DS:
+ *Width = (UINT8) sizeof (UINT16);
+ return (UINT16)OFFSET_OF(DEBUG_DATA_IA32_FX_SAVE_STATE, Ds);
+
+ case SOFT_DEBUGGER_REGISTER_FP_MXCSR:
+ *Width = (UINT8) sizeof (UINTN);
+ return (UINT16)OFFSET_OF(DEBUG_DATA_IA32_FX_SAVE_STATE, Mxcsr);
+
+ case SOFT_DEBUGGER_REGISTER_FP_MXCSR_MASK:
+ *Width = (UINT8) sizeof (UINTN);
+ return (UINT16)OFFSET_OF(DEBUG_DATA_IA32_FX_SAVE_STATE, Mxcsr_Mask);
+ }
+ }
+
+ if (Index < SOFT_DEBUGGER_REGISTER_XMM0) {
+ *Width = 10;
+ } else if (Index < SOFT_DEBUGGER_REGISTER_MM0 ) {
+ *Width = 16;
+ } else {
+ *Width = 8;
+ Index -= SOFT_DEBUGGER_REGISTER_MM0 - SOFT_DEBUGGER_REGISTER_ST0;
+ }
+
+ return (UINT16)(OFFSET_OF(DEBUG_DATA_IA32_FX_SAVE_STATE, St0Mm0) + (Index - SOFT_DEBUGGER_REGISTER_ST0) * 16);
+}
+
+/**
+ Write specified register into save CPU context.
+
+ @param[in] CpuContext Pointer to saved CPU context.
+ @param[in] Index Register index value.
+ @param[in] Offset Offset in register address range.
+ @param[in] Width Data width to read.
+ @param[in] RegisterBuffer Pointer to input buffer with data.
+
+**/
+VOID
+ArchWriteRegisterBuffer (
+ IN DEBUG_CPU_CONTEXT *CpuContext,
+ IN UINT8 Index,
+ IN UINT8 Offset,
+ IN UINT8 Width,
+ IN UINT8 *RegisterBuffer
+ )
+{
+ UINT8 *Buffer;
+ if (Index < SOFT_DEBUGGER_REGISTER_FP_BASE) {
+ Buffer = (UINT8 *) CpuContext + sizeof (DEBUG_DATA_IA32_FX_SAVE_STATE) + Index * 4;
+ } else {
+ //
+ // If it is MMX register, adjust its index position
+ //
+ if (Index >= SOFT_DEBUGGER_REGISTER_MM0) {
+ Index -= SOFT_DEBUGGER_REGISTER_MM0 - SOFT_DEBUGGER_REGISTER_ST0;
+ }
+ //
+ // FPU/MMX/XMM registers
+ //
+ Buffer = (UINT8 *) CpuContext + ArchReadFxStatOffset (Index, &Width);
+ }
+
+ CopyMem (Buffer + Offset, RegisterBuffer, Width);
+}
+
+/**
+ Read register value from saved CPU context.
+
+ @param[in] CpuContext Pointer to saved CPU context.
+ @param[in] Index Register index value.
+ @param[in] Offset Offset in register address range
+ @param[in] Width Data width to read.
+
+ @return The address of register value.
+
+**/
+UINT8 *
+ArchReadRegisterBuffer (
+ IN DEBUG_CPU_CONTEXT *CpuContext,
+ IN UINT8 Index,
+ IN UINT8 Offset,
+ IN UINT8 *Width
+ )
+{
+ UINT8 *Buffer;
+
+ if (Index < SOFT_DEBUGGER_REGISTER_FP_BASE) {
+ Buffer = (UINT8 *) CpuContext + sizeof (DEBUG_DATA_IA32_FX_SAVE_STATE) + Index * 4;
+ if (*Width == 0) {
+ *Width = (UINT8) sizeof (UINTN);
+ }
+ } else {
+ //
+ // FPU/MMX/XMM registers
+ //
+ Buffer = (UINT8 *) CpuContext + ArchReadFxStatOffset (Index, Width);
+ }
+
+ return Buffer;
+}
+
+/**
+ Read group register of common registers.
+
+ @param[in] CpuContext Pointer to saved CPU context.
+ @param[in] RegisterGroup Pointer to Group registers.
+
+**/
+VOID
+ReadRegisterGroup (
+ IN DEBUG_CPU_CONTEXT *CpuContext,
+ IN DEBUG_DATA_REPONSE_READ_REGISTER_GROUP *RegisterGroup
+ )
+{
+ RegisterGroup->Cs = (UINT16) CpuContext->Cs;
+ RegisterGroup->Ds = (UINT16) CpuContext->Ds;
+ RegisterGroup->Es = (UINT16) CpuContext->Es;
+ RegisterGroup->Fs = (UINT16) CpuContext->Fs;
+ RegisterGroup->Gs = (UINT16) CpuContext->Gs;
+ RegisterGroup->Ss = (UINT16) CpuContext->Ss;
+ RegisterGroup->Eflags = CpuContext->Eflags;
+ RegisterGroup->Ebp = CpuContext->Ebp;
+ RegisterGroup->Eip = CpuContext->Eip;
+ RegisterGroup->Esp = CpuContext->Esp;
+ RegisterGroup->Eax = CpuContext->Eax;
+ RegisterGroup->Ebx = CpuContext->Ebx;
+ RegisterGroup->Ecx = CpuContext->Ecx;
+ RegisterGroup->Edx = CpuContext->Edx;
+ RegisterGroup->Esi = CpuContext->Esi;
+ RegisterGroup->Edi = CpuContext->Edi;
+ RegisterGroup->Dr0 = CpuContext->Dr0;
+ RegisterGroup->Dr1 = CpuContext->Dr1;
+ RegisterGroup->Dr2 = CpuContext->Dr2;
+ RegisterGroup->Dr3 = CpuContext->Dr3;
+ RegisterGroup->Dr6 = CpuContext->Dr6;
+ RegisterGroup->Dr7 = CpuContext->Dr7;
+}
+
+/**
+ Initialize IDT entries to support source level debug.
+
+**/
+VOID
+InitializeDebugIdt (
+ VOID
+ )
+{
+ IA32_IDT_GATE_DESCRIPTOR *IdtEntry;
+ UINTN InterruptHandler;
+ IA32_DESCRIPTOR IdtDescriptor;
+ UINTN Index;
+ UINT16 CodeSegment;
+
+ AsmReadIdtr (&IdtDescriptor);
+
+ //
+ // Use current CS as the segment selector of interrupt gate in IDT
+ //
+ CodeSegment = AsmReadCs ();
+
+ IdtEntry = (IA32_IDT_GATE_DESCRIPTOR *) IdtDescriptor.Base;
+
+ for (Index = 0; Index < 20; Index ++) {
+ if ((PcdGet32 (PcdExceptionsIgnoredByDebugger) & (1 << Index)) != 0) {
+ //
+ // If the exception is masked to be reserved, skip it
+ //
+ continue;
+ }
+ InterruptHandler = (UINTN)&Exception0Handle + Index * ExceptionStubHeaderSize;
+ IdtEntry[Index].Bits.OffsetLow = (UINT16)(UINTN)InterruptHandler;
+ IdtEntry[Index].Bits.OffsetHigh = (UINT16)((UINTN)InterruptHandler >> 16);
+ IdtEntry[Index].Bits.Selector = CodeSegment;
+ IdtEntry[Index].Bits.GateType = IA32_IDT_GATE_TYPE_INTERRUPT_32;
+ }
+
+ InterruptHandler = (UINTN) &TimerInterruptHandle;
+ IdtEntry[DEBUG_TIMER_VECTOR].Bits.OffsetLow = (UINT16)(UINTN)InterruptHandler;
+ IdtEntry[DEBUG_TIMER_VECTOR].Bits.OffsetHigh = (UINT16)((UINTN)InterruptHandler >> 16);
+ IdtEntry[Index].Bits.Selector = CodeSegment;
+ IdtEntry[Index].Bits.GateType = IA32_IDT_GATE_TYPE_INTERRUPT_32;
+}
diff --git a/SourceLevelDebugPkg/Library/DebugAgent/DebugAgentCommon/Ia32/ArchDebugSupport.h b/SourceLevelDebugPkg/Library/DebugAgent/DebugAgentCommon/Ia32/ArchDebugSupport.h
new file mode 100644
index 000000000..7df3cb941
--- /dev/null
+++ b/SourceLevelDebugPkg/Library/DebugAgent/DebugAgentCommon/Ia32/ArchDebugSupport.h
@@ -0,0 +1,31 @@
+/** @file
+ IA32 specific defintions for debug agent library instance.
+
+ Copyright (c) 2010, Intel Corporation. All rights reserved.<BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php.
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef _ARCH_DEBUG_SUPPORT_H_
+#define _ARCH_DEBUG_SUPPORT_H_
+
+#include "ArchRegisters.h"
+#include "TransferProtocol.h"
+
+typedef DEBUG_DATA_REPONSE_READ_REGISTER_GROUP_IA32 DEBUG_DATA_REPONSE_READ_REGISTER_GROUP;
+typedef DEBUG_DATA_REPONSE_READ_REGISTER_GROUP_SEGLIM_IA32 DEBUG_DATA_REPONSE_READ_REGISTER_GROUP_SEGLIM;
+typedef DEBUG_DATA_REPONSE_READ_REGISTER_GROUP_SEGBASE_IA32 DEBUG_DATA_REPONSE_READ_REGISTER_GROUP_SEGBASE;
+
+#define DEBUG_SW_BREAKPOINT_SYMBOL 0xcc
+
+#define DEBUG_ARCH_SYMBOL DEBUG_DATA_BREAK_CPU_ARCH_IA32
+
+typedef DEBUG_DATA_IA32_SYSTEM_CONTEXT DEBUG_CPU_CONTEXT;
+
+#endif
diff --git a/SourceLevelDebugPkg/Library/DebugAgent/DebugAgentCommon/Ia32/ArchReadGroupRegister.c b/SourceLevelDebugPkg/Library/DebugAgent/DebugAgentCommon/Ia32/ArchReadGroupRegister.c
new file mode 100644
index 000000000..59ebd0025
--- /dev/null
+++ b/SourceLevelDebugPkg/Library/DebugAgent/DebugAgentCommon/Ia32/ArchReadGroupRegister.c
@@ -0,0 +1,210 @@
+/** @file
+ IA32 Group registers read support functions.
+
+ Copyright (c) 2010, Intel Corporation. All rights reserved.<BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php.
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "DebugAgent.h"
+
+/**
+ Read group register of Segment Base.
+
+ @param[in] CpuContext Pointer to saved CPU context.
+ @param[in] RegisterGroupSegBase Pointer to Group registers.
+
+**/
+VOID
+ReadRegisterGroupSegBase (
+ IN DEBUG_CPU_CONTEXT *CpuContext,
+ IN DEBUG_DATA_REPONSE_READ_REGISTER_GROUP_SEGBASE *RegisterGroupSegBase
+ )
+{
+ IA32_DESCRIPTOR *Ia32Descriptor;
+ IA32_GDT *Ia32Gdt;
+ UINTN Index;
+
+ Ia32Descriptor = (IA32_DESCRIPTOR *) CpuContext->Gdtr;
+ Ia32Gdt = (IA32_GDT *) (Ia32Descriptor->Base);
+
+ Index = CpuContext->Cs / 8;
+ RegisterGroupSegBase->CsBas = (Ia32Gdt[Index].Bits.BaseLow) + (Ia32Gdt[Index].Bits.BaseMid << 16) + (Ia32Gdt[Index].Bits.BaseMid << 24);
+ Index = CpuContext->Ss / 8;
+ RegisterGroupSegBase->SsBas = (Ia32Gdt[Index].Bits.BaseLow) + (Ia32Gdt[Index].Bits.BaseMid << 16) + (Ia32Gdt[Index].Bits.BaseMid << 24);
+ Index = CpuContext->Gs / 8;
+ RegisterGroupSegBase->GsBas = (Ia32Gdt[Index].Bits.BaseLow) + (Ia32Gdt[Index].Bits.BaseMid << 16) + (Ia32Gdt[Index].Bits.BaseMid << 24);
+ Index = CpuContext->Fs / 8;
+ RegisterGroupSegBase->FsBas = (Ia32Gdt[Index].Bits.BaseLow) + (Ia32Gdt[Index].Bits.BaseMid << 16) + (Ia32Gdt[Index].Bits.BaseMid << 24);
+ Index = CpuContext->Es / 8;
+ RegisterGroupSegBase->EsBas = (Ia32Gdt[Index].Bits.BaseLow) + (Ia32Gdt[Index].Bits.BaseMid << 16) + (Ia32Gdt[Index].Bits.BaseMid << 24);
+ Index = CpuContext->Ds / 8;
+ RegisterGroupSegBase->DsBas = (Ia32Gdt[Index].Bits.BaseLow) + (Ia32Gdt[Index].Bits.BaseMid << 16) + (Ia32Gdt[Index].Bits.BaseMid << 24);
+
+ RegisterGroupSegBase->LdtBas = 0;
+ RegisterGroupSegBase->TssBas = 0;
+}
+
+/**
+ Read gourp register of Segment Limit.
+
+ @param[in] CpuContext Pointer to saved CPU context.
+ @param[in] RegisterGroupSegLim Pointer to Group registers.
+
+**/
+VOID
+ReadRegisterGroupSegLim (
+ IN DEBUG_CPU_CONTEXT *CpuContext,
+ IN DEBUG_DATA_REPONSE_READ_REGISTER_GROUP_SEGLIM *RegisterGroupSegLim
+ )
+{
+ IA32_DESCRIPTOR *Ia32Descriptor;
+ IA32_GDT *Ia32Gdt;
+ UINTN Index;
+
+ Ia32Descriptor = (IA32_DESCRIPTOR *) CpuContext->Gdtr;
+ Ia32Gdt = (IA32_GDT *) (Ia32Descriptor->Base);
+
+ Index = CpuContext->Cs / 8;
+ RegisterGroupSegLim->CsLim = Ia32Gdt[Index].Bits.LimitLow + (Ia32Gdt[Index].Bits.LimitHigh << 16);
+ if (Ia32Gdt[Index].Bits.Granularity == 1) {
+ RegisterGroupSegLim->CsLim = (RegisterGroupSegLim->CsLim << 12) | 0xfff;
+ }
+
+ Index = CpuContext->Ss / 8;
+ RegisterGroupSegLim->SsLim = Ia32Gdt[Index].Bits.LimitLow + (Ia32Gdt[Index].Bits.LimitHigh << 16);
+ if (Ia32Gdt[Index].Bits.Granularity == 1) {
+ RegisterGroupSegLim->SsLim = (RegisterGroupSegLim->SsLim << 12) | 0xfff;
+ }
+
+ Index = CpuContext->Gs / 8;
+ RegisterGroupSegLim->GsLim = Ia32Gdt[Index].Bits.LimitLow + (Ia32Gdt[Index].Bits.LimitHigh << 16);
+ if (Ia32Gdt[Index].Bits.Granularity == 1) {
+ RegisterGroupSegLim->GsLim = (RegisterGroupSegLim->GsLim << 12) | 0xfff;
+ }
+
+ Index = CpuContext->Fs / 8;
+ RegisterGroupSegLim->FsLim = Ia32Gdt[Index].Bits.LimitLow + (Ia32Gdt[Index].Bits.LimitHigh << 16);
+ if (Ia32Gdt[Index].Bits.Granularity == 1) {
+ RegisterGroupSegLim->FsLim = (RegisterGroupSegLim->FsLim << 12) | 0xfff;
+ }
+
+ Index = CpuContext->Es / 8;
+ RegisterGroupSegLim->EsLim = Ia32Gdt[Index].Bits.LimitLow + (Ia32Gdt[Index].Bits.LimitHigh << 16);
+ if (Ia32Gdt[Index].Bits.Granularity == 1) {
+ RegisterGroupSegLim->EsLim = (RegisterGroupSegLim->EsLim << 12) | 0xfff;
+ }
+
+ Index = CpuContext->Ds / 8;
+ RegisterGroupSegLim->DsLim = Ia32Gdt[Index].Bits.LimitLow + (Ia32Gdt[Index].Bits.LimitHigh << 16);
+ if (Ia32Gdt[Index].Bits.Granularity == 1) {
+ RegisterGroupSegLim->DsLim = (RegisterGroupSegLim->DsLim << 12) | 0xfff;
+ }
+
+ RegisterGroupSegLim->LdtLim = 0xffff;
+ RegisterGroupSegLim->TssLim = 0xffff;
+}
+
+/**
+ Read group register by group index.
+
+ @param[in] CpuContext Pointer to saved CPU context.
+ @param[in] GroupIndex Group Index.
+
+ @retval RETURN_SUCCESS Read successfully.
+ @retval RETURN_NOT_SUPPORTED Group index cannot be supported.
+
+**/
+RETURN_STATUS
+ArchReadRegisterGroup (
+ IN DEBUG_CPU_CONTEXT *CpuContext,
+ IN UINT8 GroupIndex
+ )
+{
+ DEBUG_DATA_REPONSE_READ_REGISTER_GROUP RegisterGroup;
+ DEBUG_DATA_REPONSE_READ_REGISTER_GROUP_SEGLIM RegisterGroupSegLim;
+ DEBUG_DATA_REPONSE_READ_REGISTER_GROUP_SEGBASE RegisterGroupSegBase;
+
+ switch (GroupIndex) {
+ case SOFT_DEBUGGER_REGISTER_GROUP_GPDRS32:
+ ReadRegisterGroup (CpuContext, &RegisterGroup);
+ SendDataResponsePacket (CpuContext, (UINT8 *) &RegisterGroup, (UINT16) sizeof (DEBUG_DATA_REPONSE_READ_REGISTER_GROUP));
+ break;
+
+ case SOFT_DEBUGGER_REGISTER_GROUP_SEGMENT_LIMITS32:
+ ReadRegisterGroupSegLim (CpuContext, &RegisterGroupSegLim);
+ SendDataResponsePacket (CpuContext, (UINT8 *) &RegisterGroupSegLim, (UINT16) sizeof (DEBUG_DATA_REPONSE_READ_REGISTER_GROUP_SEGLIM));
+ break;
+
+ case SOFT_DEBUGGER_REGISTER_GROUP_SEGMENT_BASES32:
+ ReadRegisterGroupSegBase (CpuContext, &RegisterGroupSegBase);
+ SendDataResponsePacket (CpuContext, (UINT8 *) &RegisterGroupSegBase, (UINT16) sizeof (DEBUG_DATA_REPONSE_READ_REGISTER_GROUP_SEGBASE));
+ break;
+
+ default:
+ return RETURN_UNSUPPORTED;
+ }
+
+ return RETURN_SUCCESS;
+}
+
+/**
+ Read segment selector by register index.
+
+ @param[in] CpuContext Pointer to saved CPU context.
+ @param[in] RegisterIndex Register Index.
+
+ @return Value of segment selector.
+
+**/
+UINT64
+ReadRegisterSelectorByIndex (
+ IN DEBUG_CPU_CONTEXT *CpuContext,
+ IN UINT8 RegisterIndex
+ )
+{
+ IA32_DESCRIPTOR *Ia32Descriptor;
+ IA32_GDT *Ia32Gdt;
+ UINT16 Selector;
+ UINT32 Data32;
+
+ Ia32Descriptor = (IA32_DESCRIPTOR *) CpuContext->Gdtr;
+ Ia32Gdt = (IA32_GDT *) (Ia32Descriptor->Base);
+
+ Selector = 0;
+
+ switch (RegisterIndex) {
+ case SOFT_DEBUGGER_REGISTER_CSAS:
+ Selector = (UINT16) CpuContext->Cs;
+ break;
+ case SOFT_DEBUGGER_REGISTER_SSAS:
+ Selector = (UINT16) CpuContext->Ss;
+ break;
+ case SOFT_DEBUGGER_REGISTER_GSAS:
+ Selector = (UINT16) CpuContext->Gs;
+ break;
+ case SOFT_DEBUGGER_REGISTER_FSAS:
+ Selector = (UINT16) CpuContext->Fs;
+ break;
+ case SOFT_DEBUGGER_REGISTER_ESAS:
+ Selector = (UINT16) CpuContext->Es;
+ break;
+ case SOFT_DEBUGGER_REGISTER_DSAS:
+ Selector = (UINT16) CpuContext->Ds;
+ case SOFT_DEBUGGER_REGISTER_LDTAS:
+ case SOFT_DEBUGGER_REGISTER_TSSAS:
+ return 0x00820000;
+ break;
+ }
+
+ Data32 = (UINT32) RShiftU64 (Ia32Gdt[Selector / 8].Uint64, 24);
+ return (Data32 & (UINT32)(~0xff)) | Selector;
+
+}
+
diff --git a/SourceLevelDebugPkg/Library/DebugAgent/DebugAgentCommon/Ia32/ArchRegisters.h b/SourceLevelDebugPkg/Library/DebugAgent/DebugAgentCommon/Ia32/ArchRegisters.h
new file mode 100644
index 000000000..3c279589e
--- /dev/null
+++ b/SourceLevelDebugPkg/Library/DebugAgent/DebugAgentCommon/Ia32/ArchRegisters.h
@@ -0,0 +1,156 @@
+/** @file
+ IA32 register defintions needed by debug transfer protocol.
+
+ Copyright (c) 2010, Intel Corporation. All rights reserved.<BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php.
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef _ARCH_REGISTERS_H_
+#define _ARCH_REGISTERS_H_
+
+///
+/// FXSAVE_STATE
+/// FP / MMX / XMM registers (see fxrstor instruction definition)
+///
+typedef struct {
+ UINT16 Fcw;
+ UINT16 Fsw;
+ UINT16 Ftw;
+ UINT16 Opcode;
+ UINT32 Eip;
+ UINT16 Cs;
+ UINT16 Reserved1;
+ UINT32 DataOffset;
+ UINT16 Ds;
+ UINT8 Reserved2[2];
+ UINT32 Mxcsr;
+ UINT32 Mxcsr_Mask;
+ UINT8 St0Mm0[10];
+ UINT8 Reserved3[6];
+ UINT8 St1Mm1[10];
+ UINT8 Reserved4[6];
+ UINT8 St2Mm2[10];
+ UINT8 Reserved5[6];
+ UINT8 St3Mm3[10];
+ UINT8 Reserved6[6];
+ UINT8 St4Mm4[10];
+ UINT8 Reserved7[6];
+ UINT8 St5Mm5[10];
+ UINT8 Reserved8[6];
+ UINT8 St6Mm6[10];
+ UINT8 Reserved9[6];
+ UINT8 St7Mm7[10];
+ UINT8 Reserved10[6];
+ UINT8 Xmm0[16];
+ UINT8 Xmm1[16];
+ UINT8 Xmm2[16];
+ UINT8 Xmm3[16];
+ UINT8 Xmm4[16];
+ UINT8 Xmm5[16];
+ UINT8 Xmm6[16];
+ UINT8 Xmm7[16];
+ UINT8 Reserved11[14 * 16];
+} DEBUG_DATA_IA32_FX_SAVE_STATE;
+
+///
+/// IA-32 processor context definition
+///
+typedef struct {
+ DEBUG_DATA_IA32_FX_SAVE_STATE FxSaveState;
+ UINT32 Dr0;
+ UINT32 Dr1;
+ UINT32 Dr2;
+ UINT32 Dr3;
+ UINT32 Dr6;
+ UINT32 Dr7;
+ UINT32 Eflags;
+ UINT32 Ldtr;
+ UINT32 Tr;
+ UINT32 Gdtr[2];
+ UINT32 Idtr[2];
+ UINT32 Eip;
+ UINT32 Gs;
+ UINT32 Fs;
+ UINT32 Es;
+ UINT32 Ds;
+ UINT32 Cs;
+ UINT32 Ss;
+ UINT32 Cr0;
+ UINT32 Cr1; ///< Reserved
+ UINT32 Cr2;
+ UINT32 Cr3;
+ UINT32 Cr4;
+ UINT32 Edi;
+ UINT32 Esi;
+ UINT32 Ebp;
+ UINT32 Esp;
+ UINT32 Edx;
+ UINT32 Ecx;
+ UINT32 Ebx;
+ UINT32 Eax;
+} DEBUG_DATA_IA32_SYSTEM_CONTEXT;
+
+///
+/// IA32 GROUP register
+///
+typedef struct {
+ UINT16 Cs;
+ UINT16 Ds;
+ UINT16 Es;
+ UINT16 Fs;
+ UINT16 Gs;
+ UINT16 Ss;
+ UINT32 Eflags;
+ UINT32 Ebp;
+ UINT32 Eip;
+ UINT32 Esp;
+ UINT32 Eax;
+ UINT32 Ebx;
+ UINT32 Ecx;
+ UINT32 Edx;
+ UINT32 Esi;
+ UINT32 Edi;
+ UINT32 Dr0;
+ UINT32 Dr1;
+ UINT32 Dr2;
+ UINT32 Dr3;
+ UINT32 Dr6;
+ UINT32 Dr7;
+} DEBUG_DATA_REPONSE_READ_REGISTER_GROUP_IA32;
+
+///
+/// IA32 Segment Limit GROUP register
+///
+typedef struct {
+ UINT32 CsLim;
+ UINT32 SsLim;
+ UINT32 GsLim;
+ UINT32 FsLim;
+ UINT32 EsLim;
+ UINT32 DsLim;
+ UINT32 LdtLim;
+ UINT32 TssLim;
+} DEBUG_DATA_REPONSE_READ_REGISTER_GROUP_SEGLIM_IA32;
+
+///
+/// IA32 Segment Base GROUP register
+///
+typedef struct {
+ UINT32 CsBas;
+ UINT32 SsBas;
+ UINT32 GsBas;
+ UINT32 FsBas;
+ UINT32 EsBas;
+ UINT32 DsBas;
+ UINT32 LdtBas;
+ UINT32 TssBas;
+} DEBUG_DATA_REPONSE_READ_REGISTER_GROUP_SEGBASE_IA32;
+
+#endif
diff --git a/SourceLevelDebugPkg/Library/DebugAgent/DebugAgentCommon/Ia32/AsmFuncs.S b/SourceLevelDebugPkg/Library/DebugAgent/DebugAgentCommon/Ia32/AsmFuncs.S
new file mode 100644
index 000000000..365947f4d
--- /dev/null
+++ b/SourceLevelDebugPkg/Library/DebugAgent/DebugAgentCommon/Ia32/AsmFuncs.S
@@ -0,0 +1,360 @@
+#------------------------------------------------------------------------------
+#
+# Copyright (c) 2010, Intel Corporation. All rights reserved.<BR>
+# This program and the accompanying materials
+# are licensed and made available under the terms and conditions of the BSD License
+# which accompanies this distribution. The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php.
+#
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+# Module Name:
+#
+# AsmFuncs.S
+#
+# Abstract:
+#
+# Debug interrupt handle functions.
+#
+#------------------------------------------------------------------------------
+
+#include "DebugException.h"
+
+ASM_GLOBAL ASM_PFX(InterruptProcess)
+ASM_GLOBAL ASM_PFX(Exception0Handle)
+ASM_GLOBAL ASM_PFX(ExceptionStubHeaderSize)
+ASM_GLOBAL ASM_PFX(TimerInterruptHandle)
+ASM_GLOBAL ASM_PFX(CommonEntry)
+
+.data
+
+ASM_PFX(ExceptionStubHeaderSize): .word ASM_PFX(Exception1Handle) - ASM_PFX(Exception0Handle)
+
+.text
+
+ASM_PFX(Exception0Handle):
+ cli
+ pushl %eax
+ mov $0, %eax
+ jmp ASM_PFX(CommonEntry)
+ASM_PFX(Exception1Handle):
+ cli
+ pushl %eax
+ mov $1, %eax
+ jmp ASM_PFX(CommonEntry)
+ASM_PFX(Exception2Handle):
+ cli
+ pushl %eax
+ mov $2, %eax
+ jmp ASM_PFX(CommonEntry)
+ASM_PFX(Exception3Handle):
+ cli
+ pushl %eax
+ mov $3, %eax
+ jmp ASM_PFX(CommonEntry)
+ASM_PFX(Exception4Handle):
+ cli
+ pushl %eax
+ mov $4, %eax
+ jmp ASM_PFX(CommonEntry)
+ASM_PFX(Exception5Handle):
+ cli
+ pushl %eax
+ mov $5, %eax
+ jmp ASM_PFX(CommonEntry)
+ASM_PFX(Exception6Handle):
+ cli
+ pushl %eax
+ mov $6, %eax
+ jmp ASM_PFX(CommonEntry)
+ASM_PFX(Exception7Handle):
+ cli
+ pushl %eax
+ mov $7, %eax
+ jmp ASM_PFX(CommonEntry)
+ASM_PFX(Exception8Handle):
+ cli
+ pushl %eax
+ mov $8, %eax
+ jmp ASM_PFX(CommonEntry)
+ASM_PFX(Exception9Handle):
+ cli
+ pushl %eax
+ mov $9, %eax
+ jmp ASM_PFX(CommonEntry)
+ASM_PFX(Exception10Handle):
+ cli
+ pushl %eax
+ mov $10, %eax
+ jmp ASM_PFX(CommonEntry)
+ASM_PFX(Exception11Handle):
+ cli
+ pushl %eax
+ mov $11, %eax
+ jmp ASM_PFX(CommonEntry)
+ASM_PFX(Exception12Handle):
+ cli
+ pushl %eax
+ mov $12, %eax
+ jmp ASM_PFX(CommonEntry)
+ASM_PFX(Exception13Handle):
+ cli
+ pushl %eax
+ mov $13, %eax
+ jmp ASM_PFX(CommonEntry)
+ASM_PFX(Exception14Handle):
+ cli
+ pushl %eax
+ mov $14, %eax
+ jmp ASM_PFX(CommonEntry)
+ASM_PFX(Exception15Handle):
+ cli
+ pushl %eax
+ mov $15, %eax
+ jmp ASM_PFX(CommonEntry)
+ASM_PFX(Exception16Handle):
+ cli
+ pushl %eax
+ mov $16, %eax
+ jmp ASM_PFX(CommonEntry)
+ASM_PFX(Exception17Handle):
+ cli
+ pushl %eax
+ mov $17, %eax
+ jmp ASM_PFX(CommonEntry)
+ASM_PFX(Exception18Handle):
+ cli
+ pushl %eax
+ mov $18, %eax
+ jmp ASM_PFX(CommonEntry)
+ASM_PFX(Exception19Handle):
+ cli
+ pushl %eax
+ mov $19, %eax
+ jmp ASM_PFX(CommonEntry)
+
+ASM_PFX(TimerInterruptHandle):
+ cli
+ pushl %eax
+ mov $32, %eax
+ jmp ASM_PFX(CommonEntry)
+
+
+ASM_PFX(CommonEntry):
+
+#---------------------------------------;
+# _CommonEntry ;
+#----------------------------------------------------------------------------;
+# The follow algorithm is used for the common interrupt routine.
+# Entry from each interrupt with a push eax and eax=interrupt number
+#
+# +---------------------+
+# + EFlags +
+# +---------------------+
+# + CS +
+# +---------------------+
+# + EIP +
+# +---------------------+
+# + Error Code +
+# +---------------------+
+# + EAX / Vector Number +
+# +---------------------+
+# + EBP +
+# +---------------------+ <-- EBP
+#
+
+# We need to determine if any extra data was pushed by the exception
+ cmpl $DEBUG_EXCEPT_DOUBLE_FAULT, %eax
+ je NoExtrPush
+ cmpl $DEBUG_EXCEPT_INVALID_TSS, %eax
+ je NoExtrPush
+ cmpl $DEBUG_EXCEPT_SEG_NOT_PRESENT, %eax
+ je NoExtrPush
+ cmpl $DEBUG_EXCEPT_STACK_FAULT, %eax
+ je NoExtrPush
+ cmpl $DEBUG_EXCEPT_GP_FAULT, %eax
+ je NoExtrPush
+ cmpl $DEBUG_EXCEPT_PAGE_FAULT, %eax
+ je NoExtrPush
+ cmpl $DEBUG_EXCEPT_ALIGNMENT_CHECK, %eax
+ je NoExtrPush
+
+ pushl (%esp)
+ movl $0, 4(%esp)
+
+NoExtrPush:
+
+ pushl %ebp
+ movl %esp,%ebp
+
+ #
+ # Align stack to make sure that EFI_FX_SAVE_STATE_IA32 of EFI_SYSTEM_CONTEXT_IA32
+ # is 16-byte aligned
+ #
+ andl $0xfffffff0,%esp
+ subl $12,%esp
+
+## UINT32 Edi, Esi, Ebp, Esp, Ebx, Edx, Ecx, Eax;
+ pushl 0x4(%ebp)
+ pushl %ebx
+ pushl %ecx
+ pushl %edx
+ mov %eax, %ebx # save vector in ebx
+ leal 24(%ebp),%ecx
+ pushl %ecx # save original ESP
+ pushl (%ebp)
+ pushl %esi
+ pushl %edi
+
+## UINT32 Cr0, Cr1, Cr2, Cr3, Cr4;
+ movl %cr4, %eax
+ orl $0x208,%eax
+ movl %eax, %cr4
+ pushl %eax
+ movl %cr3, %eax
+ pushl %eax
+ movl %cr2, %eax
+ pushl %eax
+ xorl %eax,%eax
+ pushl %eax
+ movl %cr0, %eax
+ pushl %eax
+
+## UINT32 Gs, Fs, Es, Ds, Cs, Ss;
+ movl %ss,%eax
+ pushl %eax
+ movzwl 16(%ebp), %eax
+ pushl %eax
+ movl %ds,%eax
+ pushl %eax
+ movl %es,%eax
+ pushl %eax
+ movl %fs,%eax
+ pushl %eax
+ movl %gs,%eax
+ pushl %eax
+
+## UINT32 Eip;
+ pushl 12(%ebp)
+
+## UINT32 Gdtr[2], Idtr[2];
+ subl $8,%esp
+ sidt (%esp)
+ subl $8,%esp
+ sgdt (%esp)
+
+## UINT32 Ldtr, Tr;
+ xorl %eax,%eax
+ strl %eax
+ pushl %eax
+ sldtl %eax
+ pushl %eax
+
+## UINT32 EFlags;
+ pushl 20(%ebp)
+
+## UINT32 Dr0, Dr1, Dr2, Dr3, Dr6, Dr7;
+ movl %dr7, %eax
+ pushl %eax
+## clear Dr7 while executing debugger itself
+ xorl %eax,%eax
+# movl %eax, %dr7
+
+ movl %dr6, %eax
+ pushl %eax
+## insure all status bits in dr6 are clear...
+ xorl %eax,%eax
+ movl %eax, %dr6
+
+ movl %dr3, %eax
+ pushl %eax
+ movl %dr2, %eax
+ pushl %eax
+ movl %dr1, %eax
+ pushl %eax
+ movl %dr0, %eax
+ pushl %eax
+
+## FX_SAVE_STATE_IA32 FxSaveState;
+ subl $512,%esp
+ movl %esp,%edi
+ .byte 0x0f, 0xae, 0x07 # fxsave [edi]
+
+## Clear Direction Flag
+ cld
+
+## Prepare parameter and call C function
+ pushl %esp
+ pushl %ebx
+ call ASM_PFX(InterruptProcess)
+ addl $8,%esp
+
+## FX_SAVE_STATE_IA32 FxSaveState;
+ movl %esp,%esi
+ .byte 0x0f, 0xae, 0x0e # fxrstor [esi]
+ addl $512,%esp
+
+## UINT32 Dr0, Dr1, Dr2, Dr3, Dr6, Dr7;
+ popl %eax
+ movl %eax, %dr0
+ popl %eax
+ movl %eax, %dr1
+ popl %eax
+ movl %eax, %dr2
+ popl %eax
+ movl %eax, %dr3
+## skip restore of dr6. We cleared dr6 during the context save.
+ addl $4,%esp
+ popl %eax
+ movl %eax, %dr7
+
+## UINT32 EFlags;
+ popl 20(%ebp)
+
+## UINT32 Ldtr, Tr;
+## UINT32 Gdtr[2], Idtr[2];
+## Best not let anyone mess with these particular registers...
+ addl $24,%esp
+
+## UINT32 Eip;
+ pop 12(%ebp)
+
+## UINT32 Gs, Fs, Es, Ds, Cs, Ss;
+## NOTE - modified segment registers could hang the debugger... We
+## could attempt to insulate ourselves against this possibility,
+## but that poses risks as well.
+##
+ popl %gs
+ popl %fs
+ popl %es
+ popl %ds
+ popl 16(%ebp)
+ popl %ss
+
+## UINT32 Cr0, Cr1, Cr2, Cr3, Cr4;
+ popl %eax
+ movl %eax, %cr0
+ addl $4,%esp # not for Cr1
+ popl %eax
+ movl %eax, %cr2
+ popl %eax
+ movl %eax, %cr3
+ popl %eax
+ movl %eax, %cr4
+
+## UINT32 Edi, Esi, Ebp, Esp, Ebx, Edx, Ecx, Eax;
+ popl %edi
+ popl %esi
+ addl $4,%esp # not for ebp
+ addl $4,%esp # not for esp
+ popl %edx
+ popl %ecx
+ popl %ebx
+ popl %eax
+
+ movl %ebp,%esp
+ popl %ebp
+ addl $8,%esp # skip eax
+ iretl
+
diff --git a/SourceLevelDebugPkg/Library/DebugAgent/DebugAgentCommon/Ia32/AsmFuncs.asm b/SourceLevelDebugPkg/Library/DebugAgent/DebugAgentCommon/Ia32/AsmFuncs.asm
new file mode 100644
index 000000000..2d2fa5fc7
--- /dev/null
+++ b/SourceLevelDebugPkg/Library/DebugAgent/DebugAgentCommon/Ia32/AsmFuncs.asm
@@ -0,0 +1,365 @@
+;------------------------------------------------------------------------------
+;
+; Copyright (c) 2010, Intel Corporation. All rights reserved.<BR>
+; This program and the accompanying materials
+; are licensed and made available under the terms and conditions of the BSD License
+; which accompanies this distribution. The full text of the license may be found at
+; http://opensource.org/licenses/bsd-license.php.
+;
+; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+;
+; Module Name:
+;
+; AsmFuncs.asm
+;
+; Abstract:
+;
+; Debug interrupt handle functions.
+;
+;------------------------------------------------------------------------------
+
+#include "DebugException.h"
+
+.686p
+.xmm
+.model flat,c
+
+;
+; InterruptProcess()
+;
+InterruptProcess PROTO C
+
+public Exception0Handle, TimerInterruptHandle, ExceptionStubHeaderSize
+
+.data
+
+ExceptionStubHeaderSize DW Exception1Handle - Exception0Handle
+CommonEntryAddr DD CommonEntry
+
+.code
+
+Exception0Handle:
+ cli
+ push eax
+ mov eax, 0
+ jmp dword ptr [CommonEntryAddr]
+Exception1Handle:
+ cli
+ push eax
+ mov eax, 1
+ jmp dword ptr [CommonEntryAddr]
+Exception2Handle:
+ cli
+ push eax
+ mov eax, 2
+ jmp dword ptr [CommonEntryAddr]
+Exception3Handle:
+ cli
+ push eax
+ mov eax, 3
+ jmp dword ptr [CommonEntryAddr]
+Exception4Handle:
+ cli
+ push eax
+ mov eax, 4
+ jmp dword ptr [CommonEntryAddr]
+Exception5Handle:
+ cli
+ push eax
+ mov eax, 5
+ jmp dword ptr [CommonEntryAddr]
+Exception6Handle:
+ cli
+ push eax
+ mov eax, 6
+ jmp dword ptr [CommonEntryAddr]
+Exception7Handle:
+ cli
+ push eax
+ mov eax, 7
+ jmp dword ptr [CommonEntryAddr]
+Exception8Handle:
+ cli
+ push eax
+ mov eax, 8
+ jmp dword ptr [CommonEntryAddr]
+Exception9Handle:
+ cli
+ push eax
+ mov eax, 9
+ jmp dword ptr [CommonEntryAddr]
+Exception10Handle:
+ cli
+ push eax
+ mov eax, 10
+ jmp dword ptr [CommonEntryAddr]
+Exception11Handle:
+ cli
+ push eax
+ mov eax, 11
+ jmp dword ptr [CommonEntryAddr]
+Exception12Handle:
+ cli
+ push eax
+ mov eax, 12
+ jmp dword ptr [CommonEntryAddr]
+Exception13Handle:
+ cli
+ push eax
+ mov eax, 13
+ jmp dword ptr [CommonEntryAddr]
+Exception14Handle:
+ cli
+ push eax
+ mov eax, 14
+ jmp dword ptr [CommonEntryAddr]
+Exception15Handle:
+ cli
+ push eax
+ mov eax, 15
+ jmp dword ptr [CommonEntryAddr]
+Exception16Handle:
+ cli
+ push eax
+ mov eax, 16
+ jmp dword ptr [CommonEntryAddr]
+Exception17Handle:
+ cli
+ push eax
+ mov eax, 17
+ jmp dword ptr [CommonEntryAddr]
+Exception18Handle:
+ cli
+ push eax
+ mov eax, 18
+ jmp dword ptr [CommonEntryAddr]
+Exception19Handle:
+ cli
+ push eax
+ mov eax, 19
+ jmp dword ptr [CommonEntryAddr]
+
+TimerInterruptHandle:
+ cli
+ push eax
+ mov eax, 32
+ jmp dword ptr [CommonEntryAddr]
+
+CommonEntry:
+;
+; +---------------------+
+; + EFlags +
+; +---------------------+
+; + CS +
+; +---------------------+
+; + EIP +
+; +---------------------+
+; + Error Code +
+; +---------------------+
+; + EAX / Vector Number +
+; +---------------------+
+; + EBP +
+; +---------------------+ <-- EBP
+;
+ cmp eax, DEBUG_EXCEPT_DOUBLE_FAULT
+ je NoExtrPush
+ cmp eax, DEBUG_EXCEPT_INVALID_TSS
+ je NoExtrPush
+ cmp eax, DEBUG_EXCEPT_SEG_NOT_PRESENT
+ je NoExtrPush
+ cmp eax, DEBUG_EXCEPT_STACK_FAULT
+ je NoExtrPush
+ cmp eax, DEBUG_EXCEPT_GP_FAULT
+ je NoExtrPush
+ cmp eax, DEBUG_EXCEPT_PAGE_FAULT
+ je NoExtrPush
+ cmp eax, DEBUG_EXCEPT_ALIGNMENT_CHECK
+ je NoExtrPush
+
+ push [esp]
+ mov dword ptr [esp + 4], 0
+
+NoExtrPush:
+
+ push ebp
+ mov ebp, esp ; save esp in ebp
+ ;
+ ; Make stack 16-byte alignment to make sure save fxrstor later
+ ;
+ and esp, 0fffffff0h
+ sub esp, 12
+
+ ; store UINT32 Edi, Esi, Ebp, Ebx, Edx, Ecx, Eax;
+ push dword ptr [ebp + 4] ; original eax
+ push ebx
+ push ecx
+ push edx
+ mov ebx, eax ; save vector in ebx
+ mov eax, ebp
+ add eax, 4 * 6
+ push eax ; original ESP
+ push dword ptr [ebp] ; EBP
+ push esi
+ push edi
+
+ ;; UINT32 Cr0, Cr1, Cr2, Cr3, Cr4;
+ ;; insure FXSAVE/FXRSTOR is enabled in CR4...
+ ;; ... while we're at it, make sure DE is also enabled...
+ mov eax, cr4
+ push eax ; push cr4 firstly
+ or eax, 208h
+ mov cr4, eax
+ mov eax, cr3
+ push eax
+ mov eax, cr2
+ push eax
+ push 0 ; cr0 will not saved???
+ mov eax, cr0
+ push eax
+
+ xor ecx, ecx
+ mov ecx, Ss
+ push ecx
+ mov ecx, Cs
+ push ecx
+ mov ecx, Ds
+ push ecx
+ mov ecx, Es
+ push ecx
+ mov ecx, Fs
+ push ecx
+ mov ecx, Gs
+ push ecx
+
+ ;; EIP
+ mov ecx, [ebp + 4 * 3] ; EIP
+ push ecx
+
+ ;; UINT32 Gdtr[2], Idtr[2];
+ sub esp, 8
+ sidt fword ptr [esp]
+ sub esp, 8
+ sgdt fword ptr [esp]
+
+ ;; UINT32 Ldtr, Tr;
+ xor eax, eax
+ str ax
+ push eax
+ sldt ax
+ push eax
+
+ ;; EFlags
+ mov ecx, [ebp + 4 * 5]
+ push ecx
+
+ ;; UINT32 Dr0, Dr1, Dr2, Dr3, Dr6, Dr7;
+ mov eax, dr7
+ push eax
+
+ ;; clear Dr7 while executing debugger itself
+ xor eax, eax
+ ;; mov dr7, eax
+
+ ;; Dr6
+ mov eax, dr6
+ push eax
+
+ ;; insure all status bits in dr6 are clear...
+ xor eax, eax
+ mov dr6, eax
+
+ mov eax, dr3
+ push eax
+ mov eax, dr2
+ push eax
+ mov eax, dr1
+ push eax
+ mov eax, dr0
+ push eax
+
+ ;; FX_SAVE_STATE_IA32 FxSaveState;
+ sub esp, 512
+ mov edi, esp
+ db 0fh, 0aeh, 00000111y ;fxsave [edi]
+
+ ;; Clear Direction Flag
+ cld
+
+ ; call the C interrupt process function
+ push esp ; Structure
+ push ebx ; vector
+ call InterruptProcess
+ add esp, 8
+
+ ;; FX_SAVE_STATE_IA32 FxSaveState;
+ mov esi, esp
+ db 0fh, 0aeh, 00001110y ; fxrstor [esi]
+ add esp, 512
+
+ ;; UINT32 Dr0, Dr1, Dr2, Dr3, Dr6, Dr7;
+ pop eax
+ mov dr0, eax
+ pop eax
+ mov dr1, eax
+ pop eax
+ mov dr2, eax
+ pop eax
+ mov dr3, eax
+ ;; skip restore of dr6. We cleared dr6 during the context save.
+ add esp, 4
+ pop eax
+ mov dr7, eax
+
+ ;; set EFlags
+ pop dword ptr [ebp + 4 * 5] ; set EFLAGS in stack
+
+ ;; UINT32 Ldtr, Tr;
+ ;; UINT32 Gdtr[2], Idtr[2];
+ ;; Best not let anyone mess with these particular registers...
+ add esp, 24
+
+ ;; UINT32 Eip;
+ pop dword ptr [ebp + 4 * 3] ; set EIP in stack
+
+ ;; UINT32 Gs, Fs, Es, Ds, Cs, Ss;
+ ;; NOTE - modified segment registers could hang the debugger... We
+ ;; could attempt to insulate ourselves against this possibility,
+ ;; but that poses risks as well.
+ ;;
+ pop gs
+ pop fs
+ pop es
+ pop ds
+ pop dword ptr [ebp + 4 * 4] ; set CS in stack
+ pop ss
+
+ ;; UINT32 Cr0, Cr1, Cr2, Cr3, Cr4;
+ pop eax
+ mov cr0, eax
+ add esp, 4 ; skip for Cr1
+ pop eax
+ mov cr2, eax
+ pop eax
+ mov cr3, eax
+ pop eax
+ mov cr4, eax
+
+ ;; restore general register
+ pop edi
+ pop esi
+ pop dword ptr [ebp] ; save updated ebp
+ pop dword ptr [ebp + 4] ; save updated esp
+ pop edx
+ pop ecx
+ pop ebx
+ pop eax
+
+ mov esp, ebp
+ pop ebp ; restore ebp maybe updated
+ pop esp ; restore esp maybe updated
+ sub esp, 4 * 3 ; restore interupt pushced stack
+
+ iretd
+
+END
diff --git a/SourceLevelDebugPkg/Library/DebugAgent/DebugAgentCommon/Ia32/DebugException.h b/SourceLevelDebugPkg/Library/DebugAgent/DebugAgentCommon/Ia32/DebugException.h
new file mode 100644
index 000000000..13a7d23a0
--- /dev/null
+++ b/SourceLevelDebugPkg/Library/DebugAgent/DebugAgentCommon/Ia32/DebugException.h
@@ -0,0 +1,36 @@
+/** @file
+ Exception defintions.
+
+ Copyright (c) 2010, Intel Corporation. All rights reserved.<BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php.
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef _DEBUG_EXCEPTION_H_
+#define _DEBUG_EXCEPTION_H_
+
+#define DEBUG_EXCEPT_DIVIDE_ERROR 0
+#define DEBUG_EXCEPT_DEBUG 1
+#define DEBUG_EXCEPT_NMI 2
+#define DEBUG_EXCEPT_BREAKPOINT 3
+#define DEBUG_EXCEPT_OVERFLOW 4
+#define DEBUG_EXCEPT_BOUND 5
+#define DEBUG_EXCEPT_INVALID_OPCODE 6
+#define DEBUG_EXCEPT_DOUBLE_FAULT 8
+#define DEBUG_EXCEPT_INVALID_TSS 10
+#define DEBUG_EXCEPT_SEG_NOT_PRESENT 11
+#define DEBUG_EXCEPT_STACK_FAULT 12
+#define DEBUG_EXCEPT_GP_FAULT 13
+#define DEBUG_EXCEPT_PAGE_FAULT 14
+#define DEBUG_EXCEPT_FP_ERROR 16
+#define DEBUG_EXCEPT_ALIGNMENT_CHECK 17
+#define DEBUG_EXCEPT_MACHINE_CHECK 18
+#define DEBUG_EXCEPT_SIMD 19
+
+#endif
diff --git a/SourceLevelDebugPkg/Library/DebugAgent/DebugAgentCommon/X64/ArchDebugSupport.c b/SourceLevelDebugPkg/Library/DebugAgent/DebugAgentCommon/X64/ArchDebugSupport.c
new file mode 100644
index 000000000..3c18b8676
--- /dev/null
+++ b/SourceLevelDebugPkg/Library/DebugAgent/DebugAgentCommon/X64/ArchDebugSupport.c
@@ -0,0 +1,255 @@
+/** @file
+ Supporting functions for x64 architecture.
+
+ Copyright (c) 2010, Intel Corporation. All rights reserved.<BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php.
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "DebugAgent.h"
+
+/**
+ Read the offset of FP / MMX / XMM registers by register index.
+
+ @param[in] Index Register index.
+ @param[out] Width Register width returned.
+
+ @return Offset in register address range.
+
+**/
+UINT16
+ArchReadFxStatOffset (
+ IN UINT8 Index,
+ OUT UINT8 *Width
+ )
+{
+ if (Index < SOFT_DEBUGGER_REGISTER_ST0) {
+ switch (Index) {
+ case SOFT_DEBUGGER_REGISTER_FP_FCW:
+ *Width = (UINT8) sizeof (UINT16);
+ return OFFSET_OF(DEBUG_DATA_X64_FX_SAVE_STATE, Fcw);
+
+ case SOFT_DEBUGGER_REGISTER_FP_FSW:
+ *Width = (UINT8) sizeof (UINT16);
+ return OFFSET_OF(DEBUG_DATA_X64_FX_SAVE_STATE, Fsw);
+
+ case SOFT_DEBUGGER_REGISTER_FP_FTW:
+ *Width = (UINT8) sizeof (UINT16);
+ return OFFSET_OF(DEBUG_DATA_X64_FX_SAVE_STATE, Ftw);
+
+ case SOFT_DEBUGGER_REGISTER_FP_OPCODE:
+ *Width = (UINT8) sizeof (UINT16);
+ return OFFSET_OF(DEBUG_DATA_X64_FX_SAVE_STATE, Opcode);
+
+ case SOFT_DEBUGGER_REGISTER_FP_EIP:
+ *Width = (UINT8) sizeof (UINTN);
+ return OFFSET_OF(DEBUG_DATA_X64_FX_SAVE_STATE, Rip);
+
+ case SOFT_DEBUGGER_REGISTER_FP_DATAOFFSET:
+ *Width = (UINT8) sizeof (UINTN);
+ return OFFSET_OF(DEBUG_DATA_X64_FX_SAVE_STATE, DataOffset);
+
+ case SOFT_DEBUGGER_REGISTER_FP_MXCSR:
+ *Width = (UINT8) sizeof (UINT32);
+ return OFFSET_OF(DEBUG_DATA_X64_FX_SAVE_STATE, Mxcsr);
+
+ case SOFT_DEBUGGER_REGISTER_FP_MXCSR_MASK:
+ *Width = (UINT8) sizeof (UINT32);
+ return OFFSET_OF(DEBUG_DATA_X64_FX_SAVE_STATE, Mxcsr_Mask);
+
+ default:
+ return (UINT16) (-1);
+ }
+ }
+
+ if (Index < SOFT_DEBUGGER_REGISTER_XMM0) {
+ *Width = 10;
+ } else if (Index < SOFT_DEBUGGER_REGISTER_MM0 ) {
+ *Width = 16;
+ } else {
+ *Width = 8;
+ Index -= SOFT_DEBUGGER_REGISTER_MM0 - SOFT_DEBUGGER_REGISTER_ST0;
+ }
+
+ return OFFSET_OF(DEBUG_DATA_X64_FX_SAVE_STATE, St0Mm0) + (Index - SOFT_DEBUGGER_REGISTER_ST0) * 16;
+}
+
+/**
+ Write specified register into save CPU context.
+
+ @param[in] CpuContext Pointer to saved CPU context.
+ @param[in] Index Register index value.
+ @param[in] Offset Offset in register address range
+ @param[in] Width Data width to read.
+ @param[in] RegisterBuffer Pointer to input buffer with data.
+
+**/
+VOID
+ArchWriteRegisterBuffer (
+ IN DEBUG_CPU_CONTEXT *CpuContext,
+ IN UINT8 Index,
+ IN UINT8 Offset,
+ IN UINT8 Width,
+ IN UINT8 *RegisterBuffer
+ )
+{
+ UINT8 *Buffer;
+ if (Index < SOFT_DEBUGGER_REGISTER_FP_BASE) {
+ Buffer = (UINT8 *) CpuContext + sizeof (DEBUG_DATA_X64_FX_SAVE_STATE) + Index * 8;
+ } else {
+ //
+ // If it is MMX register, adjust its index position
+ //
+ if (Index >= SOFT_DEBUGGER_REGISTER_MM0) {
+ Index -= SOFT_DEBUGGER_REGISTER_MM0 - SOFT_DEBUGGER_REGISTER_ST0;
+ }
+
+ //
+ // FPU/MMX/XMM registers
+ //
+ Buffer = (UINT8 *) CpuContext + ArchReadFxStatOffset (Index, &Width);
+ }
+
+ CopyMem (Buffer + Offset, RegisterBuffer, Width);
+}
+
+/**
+ Read register value from saved CPU context.
+
+ @param[in] CpuContext Pointer to saved CPU context.
+ @param[in] Index Register index value.
+ @param[in] Offset Offset in register address range
+ @param[in] Width Data width to read.
+
+ @return The address of register value.
+
+**/
+UINT8 *
+ArchReadRegisterBuffer (
+ IN DEBUG_CPU_CONTEXT *CpuContext,
+ IN UINT8 Index,
+ IN UINT8 Offset,
+ IN UINT8 *Width
+ )
+{
+ UINT8 *Buffer;
+
+ if (Index < SOFT_DEBUGGER_REGISTER_FP_BASE) {
+ Buffer = (UINT8 *) CpuContext + sizeof (DEBUG_DATA_X64_FX_SAVE_STATE) + Index * 8;
+ if (*Width == 0) {
+ *Width = (UINT8) sizeof (UINTN);
+ }
+ } else {
+ //
+ // FPU/MMX/XMM registers
+ //
+ Buffer = (UINT8 *) CpuContext + ArchReadFxStatOffset (Index, Width);
+ }
+
+ return Buffer;
+}
+
+/**
+ Read group register of common registers.
+
+ @param[in] CpuContext Pointer to saved CPU context.
+ @param[in] RegisterGroup Pointer to Group registers.
+
+**/
+VOID
+ReadRegisterGroup (
+ IN DEBUG_CPU_CONTEXT *CpuContext,
+ IN DEBUG_DATA_REPONSE_READ_REGISTER_GROUP *RegisterGroup
+ )
+{
+ RegisterGroup->Cs = (UINT16) CpuContext->Cs;
+ RegisterGroup->Ds = (UINT16) CpuContext->Ds;
+ RegisterGroup->Es = (UINT16) CpuContext->Es;
+ RegisterGroup->Fs = (UINT16) CpuContext->Fs;
+ RegisterGroup->Gs = (UINT16) CpuContext->Gs;
+ RegisterGroup->Ss = (UINT16) CpuContext->Ss;
+ RegisterGroup->Eflags = (UINT32) CpuContext->Eflags;
+ RegisterGroup->Rbp = CpuContext->Rbp;
+ RegisterGroup->Eip = CpuContext->Eip;
+ RegisterGroup->Rsp = CpuContext->Rsp;
+ RegisterGroup->Eax = CpuContext->Rax;
+ RegisterGroup->Rbx = CpuContext->Rbx;
+ RegisterGroup->Rcx = CpuContext->Rcx;
+ RegisterGroup->Rdx = CpuContext->Rdx;
+ RegisterGroup->Rsi = CpuContext->Rsi;
+ RegisterGroup->Rdi = CpuContext->Rdi;
+ RegisterGroup->R8 = CpuContext->R8;
+ RegisterGroup->R9 = CpuContext->R9;
+ RegisterGroup->R10 = CpuContext->R10;
+ RegisterGroup->R11 = CpuContext->R11;
+ RegisterGroup->R12 = CpuContext->R12;
+ RegisterGroup->R13 = CpuContext->R13;
+ RegisterGroup->R14 = CpuContext->R14;
+ RegisterGroup->R15 = CpuContext->R15;
+ RegisterGroup->Dr0 = CpuContext->Dr0;
+ RegisterGroup->Dr1 = CpuContext->Dr1;
+ RegisterGroup->Dr2 = CpuContext->Dr2;
+ RegisterGroup->Dr3 = CpuContext->Dr3;
+ RegisterGroup->Dr6 = CpuContext->Dr6;
+ RegisterGroup->Dr7 = CpuContext->Dr7;
+ RegisterGroup->Cr0 = CpuContext->Cr0;
+ RegisterGroup->Cr2 = CpuContext->Cr2;
+ RegisterGroup->Cr3 = CpuContext->Cr3;
+ RegisterGroup->Cr4 = CpuContext->Cr4;
+ RegisterGroup->Cr8 = CpuContext->Cr8;
+
+ CopyMem ((UINT8 *) &RegisterGroup->Xmm0[0], (UINT8 *) &CpuContext->FxSaveState.Xmm0[0], 16 * 10);
+}
+
+/**
+ Initialize IDT entries to support source level debug.
+
+**/
+VOID
+InitializeDebugIdt (
+ VOID
+ )
+{
+ IA32_IDT_GATE_DESCRIPTOR *IdtEntry;
+ UINTN InterruptHandler;
+ IA32_DESCRIPTOR IdtDescriptor;
+ UINTN Index;
+ UINT16 CodeSegment;
+
+ AsmReadIdtr (&IdtDescriptor);
+
+ //
+ // Use current CS as the segment selector of interrupt gate in IDT
+ //
+ CodeSegment = AsmReadCs ();
+
+ IdtEntry = (IA32_IDT_GATE_DESCRIPTOR *) IdtDescriptor.Base;
+
+ for (Index = 0; Index < 20; Index ++) {
+ if ((PcdGet32 (PcdExceptionsIgnoredByDebugger) & (1 << Index)) != 0) {
+ //
+ // If the exception is masked to be reserved, skip it
+ //
+ continue;
+ }
+ InterruptHandler = (UINTN)&Exception0Handle + Index * ExceptionStubHeaderSize;
+ IdtEntry[Index].Bits.OffsetLow = (UINT16)(UINTN)InterruptHandler;
+ IdtEntry[Index].Bits.OffsetHigh = (UINT16)((UINTN)InterruptHandler >> 16);
+ IdtEntry[Index].Bits.OffsetUpper = (UINT32)((UINTN)InterruptHandler >> 32);
+ IdtEntry[Index].Bits.Selector = CodeSegment;
+ IdtEntry[Index].Bits.GateType = IA32_IDT_GATE_TYPE_INTERRUPT_32;
+ }
+
+ InterruptHandler = (UINTN) &TimerInterruptHandle;
+ IdtEntry[DEBUG_TIMER_VECTOR].Bits.OffsetLow = (UINT16)(UINTN)InterruptHandler;
+ IdtEntry[DEBUG_TIMER_VECTOR].Bits.OffsetHigh = (UINT16)((UINTN)InterruptHandler >> 16);
+ IdtEntry[DEBUG_TIMER_VECTOR].Bits.OffsetUpper = (UINT32)((UINTN)InterruptHandler >> 32);
+ IdtEntry[DEBUG_TIMER_VECTOR].Bits.Selector = CodeSegment;
+ IdtEntry[DEBUG_TIMER_VECTOR].Bits.GateType = IA32_IDT_GATE_TYPE_INTERRUPT_32;
+}
diff --git a/SourceLevelDebugPkg/Library/DebugAgent/DebugAgentCommon/X64/ArchDebugSupport.h b/SourceLevelDebugPkg/Library/DebugAgent/DebugAgentCommon/X64/ArchDebugSupport.h
new file mode 100644
index 000000000..0b25a78d1
--- /dev/null
+++ b/SourceLevelDebugPkg/Library/DebugAgent/DebugAgentCommon/X64/ArchDebugSupport.h
@@ -0,0 +1,31 @@
+/** @file
+ X64 specific defintions for debug agent library instance.
+
+ Copyright (c) 2010, Intel Corporation. All rights reserved.<BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php.
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef _ARCH_DEBUG_SUPPORT_H_
+#define _ARCH_DEBUG_SUPPORT_H_
+
+#include "ArchRegisters.h"
+#include "TransferProtocol.h"
+
+typedef DEBUG_DATA_REPONSE_READ_REGISTER_GROUP_X64 DEBUG_DATA_REPONSE_READ_REGISTER_GROUP;
+typedef DEBUG_DATA_REPONSE_READ_REGISTER_GROUP_SEGLIM_X64 DEBUG_DATA_REPONSE_READ_REGISTER_GROUP_SEGLIM;
+typedef DEBUG_DATA_REPONSE_READ_REGISTER_GROUP_SEGBASE_X64 DEBUG_DATA_REPONSE_READ_REGISTER_GROUP_SEGBASE;
+
+#define DEBUG_SW_BREAKPOINT_SYMBOL 0xcc
+
+#define DEBUG_ARCH_SYMBOL DEBUG_DATA_BREAK_CPU_ARCH_X64
+
+typedef DEBUG_DATA_X64_SYSTEM_CONTEXT DEBUG_CPU_CONTEXT;
+
+#endif
diff --git a/SourceLevelDebugPkg/Library/DebugAgent/DebugAgentCommon/X64/ArchReadGroupRegister.c b/SourceLevelDebugPkg/Library/DebugAgent/DebugAgentCommon/X64/ArchReadGroupRegister.c
new file mode 100644
index 000000000..72d30fcf5
--- /dev/null
+++ b/SourceLevelDebugPkg/Library/DebugAgent/DebugAgentCommon/X64/ArchReadGroupRegister.c
@@ -0,0 +1,259 @@
+/** @file
+ x64 Group registers read support functions.
+
+ Copyright (c) 2010, Intel Corporation. All rights reserved.<BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php.
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "DebugAgent.h"
+
+/**
+ Read segment selector by register index.
+
+ @param[in] CpuContext Pointer to saved CPU context.
+ @param[in] RegisterIndex Register Index.
+
+ @return Value of segment selector.
+
+**/
+UINT64
+ReadRegisterSelectorByIndex (
+ IN DEBUG_CPU_CONTEXT *CpuContext,
+ IN UINT8 RegisterIndex
+ )
+{
+ IA32_DESCRIPTOR *Ia32Descriptor;
+ IA32_GDT *Ia32Gdt;
+ UINT16 Selector;
+ UINT32 Data32;
+
+ Ia32Descriptor = (IA32_DESCRIPTOR *) CpuContext->Gdtr;
+ Ia32Gdt = (IA32_GDT *) (Ia32Descriptor->Base);
+
+ Selector = 0;
+
+ switch (RegisterIndex) {
+ case SOFT_DEBUGGER_REGISTER_CSAS:
+ Selector = (UINT16) CpuContext->Cs;
+ break;
+ case SOFT_DEBUGGER_REGISTER_SSAS:
+ Selector = (UINT16) CpuContext->Ss;
+ break;
+ case SOFT_DEBUGGER_REGISTER_GSAS:
+ Selector = (UINT16) CpuContext->Gs;
+ break;
+ case SOFT_DEBUGGER_REGISTER_FSAS:
+ Selector = (UINT16) CpuContext->Fs;
+ break;
+ case SOFT_DEBUGGER_REGISTER_ESAS:
+ Selector = (UINT16) CpuContext->Es;
+ break;
+ case SOFT_DEBUGGER_REGISTER_DSAS:
+ Selector = (UINT16) CpuContext->Ds;
+ case SOFT_DEBUGGER_REGISTER_LDTAS:
+ case SOFT_DEBUGGER_REGISTER_TSSAS:
+ return 0x00820000;
+ break;
+ }
+
+ Data32 = (UINT32) RShiftU64 (Ia32Gdt[Selector / 8].Uint64, 24);
+ return (Data32 & (UINT32)(~0xff)) | Selector;
+
+}
+
+/**
+ Read group register of Segment Base.
+
+ @param[in] CpuContext Pointer to saved CPU context.
+ @param[in] RegisterGroupSegBase Pointer to Group registers.
+
+**/
+VOID
+ReadRegisterGroupSegBase (
+ IN DEBUG_CPU_CONTEXT *CpuContext,
+ IN DEBUG_DATA_REPONSE_READ_REGISTER_GROUP_SEGBASE *RegisterGroupSegBase
+ )
+{
+ IA32_DESCRIPTOR *Ia32Descriptor;
+ IA32_GDT *Ia32Gdt;
+ UINTN Index;
+
+ Ia32Descriptor = (IA32_DESCRIPTOR *) CpuContext->Gdtr;
+ Ia32Gdt = (IA32_GDT *) (Ia32Descriptor->Base);
+
+ Index = CpuContext->Cs / 8;
+ RegisterGroupSegBase->CsBas = (Ia32Gdt[Index].Bits.BaseLow) + (Ia32Gdt[Index].Bits.BaseMid << 16) + (Ia32Gdt[Index].Bits.BaseMid << 24);
+ Index = CpuContext->Ss / 8;
+ RegisterGroupSegBase->SsBas = (Ia32Gdt[Index].Bits.BaseLow) + (Ia32Gdt[Index].Bits.BaseMid << 16) + (Ia32Gdt[Index].Bits.BaseMid << 24);
+ Index = CpuContext->Gs / 8;
+ RegisterGroupSegBase->GsBas = (Ia32Gdt[Index].Bits.BaseLow) + (Ia32Gdt[Index].Bits.BaseMid << 16) + (Ia32Gdt[Index].Bits.BaseMid << 24);
+ Index = CpuContext->Fs / 8;
+ RegisterGroupSegBase->FsBas = (Ia32Gdt[Index].Bits.BaseLow) + (Ia32Gdt[Index].Bits.BaseMid << 16) + (Ia32Gdt[Index].Bits.BaseMid << 24);
+ Index = CpuContext->Es / 8;
+ RegisterGroupSegBase->EsBas = (Ia32Gdt[Index].Bits.BaseLow) + (Ia32Gdt[Index].Bits.BaseMid << 16) + (Ia32Gdt[Index].Bits.BaseMid << 24);
+ Index = CpuContext->Ds / 8;
+ RegisterGroupSegBase->DsBas = (Ia32Gdt[Index].Bits.BaseLow) + (Ia32Gdt[Index].Bits.BaseMid << 16) + (Ia32Gdt[Index].Bits.BaseMid << 24);
+
+ RegisterGroupSegBase->LdtBas = 0;
+ RegisterGroupSegBase->TssBas = 0;
+}
+
+/**
+ Read group register of Segment Limit.
+
+ @param[in] CpuContext Pointer to saved CPU context.
+ @param[in] RegisterGroupSegLim Pointer to Group registers.
+
+**/
+VOID
+ReadRegisterGroupSegLim (
+ IN DEBUG_CPU_CONTEXT *CpuContext,
+ IN DEBUG_DATA_REPONSE_READ_REGISTER_GROUP_SEGLIM *RegisterGroupSegLim
+ )
+{
+ IA32_DESCRIPTOR *Ia32Descriptor;
+ IA32_GDT *Ia32Gdt;
+ UINTN Index;
+
+ Ia32Descriptor = (IA32_DESCRIPTOR *) CpuContext->Gdtr;
+ Ia32Gdt = (IA32_GDT *) (Ia32Descriptor->Base);
+
+ Index = CpuContext->Cs / 8;
+ RegisterGroupSegLim->CsLim = Ia32Gdt[Index].Bits.LimitLow + (Ia32Gdt[Index].Bits.LimitHigh << 16);
+ if (Ia32Gdt[Index].Bits.Granularity == 1) {
+ RegisterGroupSegLim->CsLim = (RegisterGroupSegLim->CsLim << 12) | 0xfff;
+ }
+
+ Index = CpuContext->Ss / 8;
+ RegisterGroupSegLim->SsLim = Ia32Gdt[Index].Bits.LimitLow + (Ia32Gdt[Index].Bits.LimitHigh << 16);
+ if (Ia32Gdt[Index].Bits.Granularity == 1) {
+ RegisterGroupSegLim->SsLim = (RegisterGroupSegLim->SsLim << 12) | 0xfff;
+ }
+
+ Index = CpuContext->Gs / 8;
+ RegisterGroupSegLim->GsLim = Ia32Gdt[Index].Bits.LimitLow + (Ia32Gdt[Index].Bits.LimitHigh << 16);
+ if (Ia32Gdt[Index].Bits.Granularity == 1) {
+ RegisterGroupSegLim->GsLim = (RegisterGroupSegLim->GsLim << 12) | 0xfff;
+ }
+
+ Index = CpuContext->Fs / 8;
+ RegisterGroupSegLim->FsLim = Ia32Gdt[Index].Bits.LimitLow + (Ia32Gdt[Index].Bits.LimitHigh << 16);
+ if (Ia32Gdt[Index].Bits.Granularity == 1) {
+ RegisterGroupSegLim->FsLim = (RegisterGroupSegLim->FsLim << 12) | 0xfff;
+ }
+
+ Index = CpuContext->Es / 8;
+ RegisterGroupSegLim->EsLim = Ia32Gdt[Index].Bits.LimitLow + (Ia32Gdt[Index].Bits.LimitHigh << 16);
+ if (Ia32Gdt[Index].Bits.Granularity == 1) {
+ RegisterGroupSegLim->EsLim = (RegisterGroupSegLim->EsLim << 12) | 0xfff;
+ }
+
+ Index = CpuContext->Ds / 8;
+ RegisterGroupSegLim->DsLim = Ia32Gdt[Index].Bits.LimitLow + (Ia32Gdt[Index].Bits.LimitHigh << 16);
+ if (Ia32Gdt[Index].Bits.Granularity == 1) {
+ RegisterGroupSegLim->DsLim = (RegisterGroupSegLim->DsLim << 12) | 0xfff;
+ }
+
+ RegisterGroupSegLim->LdtLim = 0xffff;
+ RegisterGroupSegLim->TssLim = 0xffff;
+}
+
+/**
+ Read group register by group index.
+
+ @param[in] CpuContext Pointer to saved CPU context.
+ @param[in] GroupIndex Group Index.
+
+ @retval RETURN_SUCCESS Read successfully.
+ @retval RETURN_NOT_SUPPORTED Group index cannot be supported.
+
+**/
+RETURN_STATUS
+ArchReadRegisterGroup (
+ IN DEBUG_CPU_CONTEXT *CpuContext,
+ IN UINT8 GroupIndex
+ )
+{
+ UINTN DataN;
+ DEBUG_DATA_REPONSE_READ_REGISTER_GROUP RegisterGroup;
+ DEBUG_DATA_REPONSE_READ_REGISTER_GROUP_SEGMENT_BAS_LIM RegisterGroupBasLim;
+ DEBUG_DATA_REPONSE_READ_REGISTER_GROUP_SEGMENT_BASES_X64 RegisterGroupBases64;
+
+ switch (GroupIndex) {
+ case SOFT_DEBUGGER_REGISTER_GROUP_SEGMENT64:
+ ReadRegisterGroup (CpuContext, &RegisterGroup);
+ SendDataResponsePacket (CpuContext, (UINT8 *) &RegisterGroup, (UINT16) sizeof (DEBUG_DATA_REPONSE_READ_REGISTER_GROUP_SEGMENT));
+ break;
+
+ case SOFT_DEBUGGER_REGISTER_GROUP_SEGMENT_BAS_LIM64:
+ DataN = (UINTN) (CpuContext->Idtr[0] & 0xffff);
+ RegisterGroupBasLim.IdtLim = DataN;
+ DataN = (UINTN) (CpuContext->Gdtr[0] & 0xffff);
+ RegisterGroupBasLim.GdtLim = DataN;
+ DataN = (UINTN) RShiftU64 (CpuContext->Idtr[0], 16);
+ DataN |= (UINTN) LShiftU64 (CpuContext->Idtr[1], sizeof (UINTN) * 8 - 16);
+ RegisterGroupBasLim.IdtBas = DataN;
+ DataN = (UINTN) RShiftU64 (CpuContext->Gdtr[0], 16);
+ DataN |= (UINTN) LShiftU64 (CpuContext->Gdtr[1], sizeof (UINTN) * 8 - 16);
+ RegisterGroupBasLim.GdtBas = DataN;
+
+ ReadRegisterGroupSegLim (CpuContext, (DEBUG_DATA_REPONSE_READ_REGISTER_GROUP_SEGLIM *) &RegisterGroupBasLim.CsLim);
+ ReadRegisterGroupSegBase (CpuContext, (DEBUG_DATA_REPONSE_READ_REGISTER_GROUP_SEGBASE *) &RegisterGroupBasLim.CsBas);
+
+ SendDataResponsePacket (CpuContext, (UINT8 *) &RegisterGroupBasLim, (UINT16) sizeof (DEBUG_DATA_REPONSE_READ_REGISTER_GROUP_SEGMENT_BAS_LIM));
+ break;
+
+ case SOFT_DEBUGGER_REGISTER_GROUP_GP2_64:
+ ReadRegisterGroup (CpuContext, &RegisterGroup);
+ SendDataResponsePacket (CpuContext, (UINT8 *) &RegisterGroup.Eflags, (UINT16) sizeof (DEBUG_DATA_REPONSE_READ_REGISTER_GROUP_GP2));
+ break;
+
+ case SOFT_DEBUGGER_REGISTER_GROUP_GP64:
+ ReadRegisterGroup (CpuContext, &RegisterGroup);
+ SendDataResponsePacket (CpuContext, (UINT8 *) &RegisterGroup.Eax, (UINT16) sizeof (DEBUG_DATA_REPONSE_READ_REGISTER_GROUP_GP));
+ break;
+
+ case SOFT_DEBUGGER_REGISTER_GROUP_DR64:
+ ReadRegisterGroup (CpuContext, &RegisterGroup);
+ SendDataResponsePacket (CpuContext, (UINT8 *) &RegisterGroup.Dr0, (UINT16) sizeof (DEBUG_DATA_REPONSE_READ_REGISTER_GROUP_DR));
+ break;
+
+ case SOFT_DEBUGGER_REGISTER_GROUP_SEGMENT_BASES64:
+ RegisterGroupBases64.Ldtr = (UINT16) CpuContext->Ldtr;
+ RegisterGroupBases64.Tr = (UINT16) CpuContext->Tr;
+
+ RegisterGroupBases64.Csas = ReadRegisterSelectorByIndex (CpuContext, SOFT_DEBUGGER_REGISTER_CSAS);
+ RegisterGroupBases64.Ssas = ReadRegisterSelectorByIndex (CpuContext, SOFT_DEBUGGER_REGISTER_SSAS);
+ RegisterGroupBases64.Gsas = ReadRegisterSelectorByIndex (CpuContext, SOFT_DEBUGGER_REGISTER_GSAS);
+ RegisterGroupBases64.Fsas = ReadRegisterSelectorByIndex (CpuContext, SOFT_DEBUGGER_REGISTER_FSAS);
+ RegisterGroupBases64.Esas = ReadRegisterSelectorByIndex (CpuContext, SOFT_DEBUGGER_REGISTER_ESAS);
+ RegisterGroupBases64.Dsas = ReadRegisterSelectorByIndex (CpuContext, SOFT_DEBUGGER_REGISTER_DSAS);
+ RegisterGroupBases64.Ldtas = ReadRegisterSelectorByIndex (CpuContext, SOFT_DEBUGGER_REGISTER_LDTAS);
+ RegisterGroupBases64.Tssas = ReadRegisterSelectorByIndex (CpuContext, SOFT_DEBUGGER_REGISTER_TSSAS);
+
+ SendDataResponsePacket (CpuContext, (UINT8 *) &RegisterGroupBases64, (UINT16) sizeof (DEBUG_DATA_REPONSE_READ_REGISTER_GROUP_SEGMENT_BASES_X64));
+ break;
+
+ case SOFT_DEBUGGER_REGISTER_GROUP_CR64:
+ ReadRegisterGroup (CpuContext, &RegisterGroup);
+ SendDataResponsePacket (CpuContext, (UINT8 *) &RegisterGroup.Dr7 + 8, (UINT16) sizeof (DEBUG_DATA_REPONSE_READ_REGISTER_GROUP_CR));
+ break;
+
+ case SOFT_DEBUGGER_REGISTER_GROUP_XMM64:
+ ReadRegisterGroup (CpuContext, &RegisterGroup);
+ SendDataResponsePacket (CpuContext, (UINT8 *) &RegisterGroup.Dr7 + 8 * 6, (UINT16) sizeof (DEBUG_DATA_REPONSE_READ_REGISTER_GROUP_XMM));
+ break;
+
+ default:
+ return RETURN_UNSUPPORTED;
+ }
+
+ return RETURN_SUCCESS;
+}
diff --git a/SourceLevelDebugPkg/Library/DebugAgent/DebugAgentCommon/X64/ArchRegisters.h b/SourceLevelDebugPkg/Library/DebugAgent/DebugAgentCommon/X64/ArchRegisters.h
new file mode 100644
index 000000000..e7a5a3308
--- /dev/null
+++ b/SourceLevelDebugPkg/Library/DebugAgent/DebugAgentCommon/X64/ArchRegisters.h
@@ -0,0 +1,329 @@
+/** @file
+ X64 register defintions needed by debug transfer protocol.
+
+ Copyright (c) 2010, Intel Corporation. All rights reserved.<BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php.
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef _ARCH_REGISTERS_H_
+#define _ARCH_REGISTERS_H_
+
+///
+/// FXSAVE_STATE (promoted operation)
+/// FP / MMX / XMM registers (see fxrstor instruction definition)
+///
+typedef struct {
+ UINT16 Fcw;
+ UINT16 Fsw;
+ UINT16 Ftw;
+ UINT16 Opcode;
+ UINT64 Rip;
+ UINT64 DataOffset;
+ UINT32 Mxcsr;
+ UINT32 Mxcsr_Mask;
+ UINT8 St0Mm0[10];
+ UINT8 Reserved2[6];
+ UINT8 St1Mm1[10];
+ UINT8 Reserved3[6];
+ UINT8 St2Mm2[10];
+ UINT8 Reserved4[6];
+ UINT8 St3Mm3[10];
+ UINT8 Reserved5[6];
+ UINT8 St4Mm4[10];
+ UINT8 Reserved6[6];
+ UINT8 St5Mm5[10];
+ UINT8 Reserved7[6];
+ UINT8 St6Mm6[10];
+ UINT8 Reserved8[6];
+ UINT8 St7Mm7[10];
+ UINT8 Reserved9[6];
+ UINT8 Xmm0[16];
+ UINT8 Xmm1[16];
+ UINT8 Xmm2[16];
+ UINT8 Xmm3[16];
+ UINT8 Xmm4[16];
+ UINT8 Xmm5[16];
+ UINT8 Xmm6[16];
+ UINT8 Xmm7[16];
+ UINT8 Xmm8[16];
+ UINT8 Xmm9[16];
+ UINT8 Xmm10[16];
+ UINT8 Xmm11[16];
+ UINT8 Xmm12[16];
+ UINT8 Xmm13[16];
+ UINT8 Xmm14[16];
+ UINT8 Xmm15[16];
+ UINT8 Reserved11[6 * 16];
+} DEBUG_DATA_X64_FX_SAVE_STATE;
+
+///
+/// x64 processor context definition
+///
+typedef struct {
+ DEBUG_DATA_X64_FX_SAVE_STATE FxSaveState;
+ UINT64 Dr0;
+ UINT64 Dr1;
+ UINT64 Dr2;
+ UINT64 Dr3;
+ UINT64 Dr6;
+ UINT64 Dr7;
+ UINT64 Eflags;
+ UINT64 Ldtr;
+ UINT64 Tr;
+ UINT64 Gdtr[2];
+ UINT64 Idtr[2];
+ UINT64 Eip;
+ UINT64 Gs;
+ UINT64 Fs;
+ UINT64 Es;
+ UINT64 Ds;
+ UINT64 Cs;
+ UINT64 Ss;
+ UINT64 Cr0;
+ UINT64 Cr1; /* Reserved */
+ UINT64 Cr2;
+ UINT64 Cr3;
+ UINT64 Cr4;
+ UINT64 Rdi;
+ UINT64 Rsi;
+ UINT64 Rbp;
+ UINT64 Rsp;
+ UINT64 Rdx;
+ UINT64 Rcx;
+ UINT64 Rbx;
+ UINT64 Rax;
+ UINT64 Cr8;
+ UINT64 R8;
+ UINT64 R9;
+ UINT64 R10;
+ UINT64 R11;
+ UINT64 R12;
+ UINT64 R13;
+ UINT64 R14;
+ UINT64 R15;
+} DEBUG_DATA_X64_SYSTEM_CONTEXT;
+
+
+///
+/// x64 GROUP register
+///
+typedef struct {
+ UINT16 Cs;
+ UINT16 Ds;
+ UINT16 Es;
+ UINT16 Fs;
+ UINT16 Gs;
+ UINT16 Ss;
+ UINT32 Eflags;
+ UINT64 Rbp;
+ UINT64 Eip;
+ UINT64 Rsp;
+ UINT64 Eax;
+ UINT64 Rbx;
+ UINT64 Rcx;
+ UINT64 Rdx;
+ UINT64 Rsi;
+ UINT64 Rdi;
+ UINT64 R8;
+ UINT64 R9;
+ UINT64 R10;
+ UINT64 R11;
+ UINT64 R12;
+ UINT64 R13;
+ UINT64 R14;
+ UINT64 R15;
+ UINT64 Dr0;
+ UINT64 Dr1;
+ UINT64 Dr2;
+ UINT64 Dr3;
+ UINT64 Dr6;
+ UINT64 Dr7;
+ UINT64 Cr0;
+ UINT64 Cr2;
+ UINT64 Cr3;
+ UINT64 Cr4;
+ UINT64 Cr8;
+ UINT8 Xmm0[16];
+ UINT8 Xmm1[16];
+ UINT8 Xmm2[16];
+ UINT8 Xmm3[16];
+ UINT8 Xmm4[16];
+ UINT8 Xmm5[16];
+ UINT8 Xmm6[16];
+ UINT8 Xmm7[16];
+ UINT8 Xmm8[16];
+ UINT8 Xmm9[16];
+ UINT8 Xmm10[16];
+ UINT8 Xmm11[16];
+ UINT8 Xmm12[16];
+ UINT8 Xmm13[16];
+ UINT8 Xmm14[16];
+ UINT8 Xmm15[16];
+} DEBUG_DATA_REPONSE_READ_REGISTER_GROUP_X64;
+
+///
+/// x64 Segment Limit GROUP register
+///
+typedef struct {
+ UINT64 CsLim;
+ UINT64 SsLim;
+ UINT64 GsLim;
+ UINT64 FsLim;
+ UINT64 EsLim;
+ UINT64 DsLim;
+ UINT64 LdtLim;
+ UINT64 TssLim;
+} DEBUG_DATA_REPONSE_READ_REGISTER_GROUP_SEGLIM_X64;
+
+///
+/// x64 Segment Base GROUP register
+///
+typedef struct {
+ UINT64 CsBas;
+ UINT64 SsBas;
+ UINT64 GsBas;
+ UINT64 FsBas;
+ UINT64 EsBas;
+ UINT64 DsBas;
+ UINT64 LdtBas;
+ UINT64 TssBas;
+} DEBUG_DATA_REPONSE_READ_REGISTER_GROUP_SEGBASE_X64;
+
+///
+/// x64 Segment Base/Limit GROUP register
+///
+typedef struct {
+ UINT64 IdtBas;
+ UINT64 IdtLim;
+ UINT64 GdtBas;
+ UINT64 GdtLim;
+ UINT64 CsLim;
+ UINT64 SsLim;
+ UINT64 GsLim;
+ UINT64 FsLim;
+ UINT64 EsLim;
+ UINT64 DsLim;
+ UINT64 LdtLim;
+ UINT64 TssLim;
+ UINT64 CsBas;
+ UINT64 SsBas;
+ UINT64 GsBas;
+ UINT64 FsBas;
+ UINT64 EsBas;
+ UINT64 DsBas;
+ UINT64 LdtBas;
+ UINT64 TssBas;
+} DEBUG_DATA_REPONSE_READ_REGISTER_GROUP_SEGMENT_BAS_LIM;
+
+///
+/// x64 register GROUP register
+///
+typedef struct {
+ UINT32 Eflags;
+ UINT64 Rbp;
+ UINT64 Eip;
+ UINT64 Rsp;
+} DEBUG_DATA_REPONSE_READ_REGISTER_GROUP_GP2;
+
+///
+/// x64 general register GROUP register
+///
+typedef struct {
+ UINT64 Eax;
+ UINT64 Rbx;
+ UINT64 Rcx;
+ UINT64 Rdx;
+ UINT64 Rsi;
+ UINT64 Rdi;
+ UINT64 R8;
+ UINT64 R9;
+ UINT64 R10;
+ UINT64 R11;
+ UINT64 R12;
+ UINT64 R13;
+ UINT64 R14;
+ UINT64 R15;
+} DEBUG_DATA_REPONSE_READ_REGISTER_GROUP_GP;
+
+///
+/// x64 Segment GROUP register
+///
+typedef struct {
+ UINT16 Cs;
+ UINT16 Ds;
+ UINT16 Es;
+ UINT16 Fs;
+ UINT16 Gs;
+ UINT16 Ss;
+} DEBUG_DATA_REPONSE_READ_REGISTER_GROUP_SEGMENT;
+
+///
+/// x64 Debug Register GROUP register
+///
+typedef struct {
+ UINT64 Dr0;
+ UINT64 Dr1;
+ UINT64 Dr2;
+ UINT64 Dr3;
+ UINT64 Dr6;
+ UINT64 Dr7;
+} DEBUG_DATA_REPONSE_READ_REGISTER_GROUP_DR;
+
+///
+/// x64 Control Register GROUP register
+///
+typedef struct {
+ UINT64 Cr0;
+ UINT64 Cr2;
+ UINT64 Cr3;
+ UINT64 Cr4;
+ UINT64 Cr8;
+} DEBUG_DATA_REPONSE_READ_REGISTER_GROUP_CR;
+
+///
+/// x64 XMM Register GROUP register
+///
+typedef struct {
+ UINT8 Xmm0[16];
+ UINT8 Xmm1[16];
+ UINT8 Xmm2[16];
+ UINT8 Xmm3[16];
+ UINT8 Xmm4[16];
+ UINT8 Xmm5[16];
+ UINT8 Xmm6[16];
+ UINT8 Xmm7[16];
+ UINT8 Xmm8[16];
+ UINT8 Xmm9[16];
+ UINT8 Xmm10[16];
+ UINT8 Xmm11[16];
+ UINT8 Xmm12[16];
+ UINT8 Xmm13[16];
+ UINT8 Xmm14[16];
+ UINT8 Xmm15[16];
+} DEBUG_DATA_REPONSE_READ_REGISTER_GROUP_XMM;
+
+///
+/// x64 Segment Base GROUP register
+///
+typedef struct {
+ UINT16 Ldtr;
+ UINT16 Tr;
+ UINT64 Csas;
+ UINT64 Ssas;
+ UINT64 Gsas;
+ UINT64 Fsas;
+ UINT64 Esas;
+ UINT64 Dsas;
+ UINT64 Ldtas;
+ UINT64 Tssas;
+} DEBUG_DATA_REPONSE_READ_REGISTER_GROUP_SEGMENT_BASES_X64;
+
+
+#endif
diff --git a/SourceLevelDebugPkg/Library/DebugAgent/DebugAgentCommon/X64/AsmFuncs.S b/SourceLevelDebugPkg/Library/DebugAgent/DebugAgentCommon/X64/AsmFuncs.S
new file mode 100644
index 000000000..0d78e7d77
--- /dev/null
+++ b/SourceLevelDebugPkg/Library/DebugAgent/DebugAgentCommon/X64/AsmFuncs.S
@@ -0,0 +1,401 @@
+#------------------------------------------------------------------------------
+#
+# Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.<BR>
+# This program and the accompanying materials
+# are licensed and made available under the terms and conditions of the BSD License
+# which accompanies this distribution. The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php.
+#
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+# Module Name:
+#
+# AsmFuncs.S
+#
+# Abstract:
+#
+# Debug interrupt handle functions.
+#
+#------------------------------------------------------------------------------
+
+#include "DebugException.h"
+
+ASM_GLOBAL ASM_PFX(InterruptProcess)
+
+ASM_GLOBAL ASM_PFX(Exception0Handle)
+ASM_GLOBAL ASM_PFX(ExceptionStubHeaderSize)
+ASM_GLOBAL ASM_PFX(TimerInterruptHandle)
+ASM_GLOBAL ASM_PFX(CommonEntry)
+
+.data
+
+ASM_PFX(ExceptionStubHeaderSize): .word ASM_PFX(Exception1Handle) - ASM_PFX(Exception0Handle)
+
+
+.text
+
+ASM_PFX(Exception0Handle):
+ cli
+ pushq %rcx
+ mov $0, %rcx
+ jmp ASM_PFX(CommonEntry)
+ASM_PFX(Exception1Handle):
+ cli
+ pushq %rcx
+ mov $1, %rcx
+ jmp ASM_PFX(CommonEntry)
+ASM_PFX(Exception2Handle):
+ cli
+ pushq %rcx
+ mov $2, %rcx
+ jmp ASM_PFX(CommonEntry)
+ASM_PFX(Exception3Handle):
+ cli
+ pushq %rcx
+ mov $3, %rcx
+ jmp ASM_PFX(CommonEntry)
+ASM_PFX(Exception4Handle):
+ cli
+ pushq %rcx
+ mov $4, %rcx
+ jmp ASM_PFX(CommonEntry)
+ASM_PFX(Exception5Handle):
+ cli
+ pushq %rcx
+ mov $5, %rcx
+ jmp ASM_PFX(CommonEntry)
+ASM_PFX(Exception6Handle):
+ cli
+ pushq %rcx
+ mov $6, %rcx
+ jmp ASM_PFX(CommonEntry)
+ASM_PFX(Exception7Handle):
+ cli
+ pushq %rcx
+ mov $7, %rcx
+ jmp ASM_PFX(CommonEntry)
+ASM_PFX(Exception8Handle):
+ cli
+ pushq %rcx
+ mov $8, %rcx
+ jmp ASM_PFX(CommonEntry)
+ASM_PFX(Exception9Handle):
+ cli
+ pushq %rcx
+ mov $9, %rcx
+ jmp ASM_PFX(CommonEntry)
+ASM_PFX(Exception10Handle):
+ cli
+ pushq %rcx
+ mov $10, %rcx
+ jmp ASM_PFX(CommonEntry)
+ASM_PFX(Exception11Handle):
+ cli
+ pushq %rcx
+ mov $11, %rcx
+ jmp ASM_PFX(CommonEntry)
+ASM_PFX(Exception12Handle):
+ cli
+ pushq %rcx
+ mov $12, %rcx
+ jmp ASM_PFX(CommonEntry)
+ASM_PFX(Exception13Handle):
+ cli
+ pushq %rcx
+ mov $13, %rcx
+ jmp ASM_PFX(CommonEntry)
+ASM_PFX(Exception14Handle):
+ cli
+ pushq %rcx
+ mov $14, %rcx
+ jmp ASM_PFX(CommonEntry)
+ASM_PFX(Exception15Handle):
+ cli
+ pushq %rcx
+ mov $15, %rcx
+ jmp ASM_PFX(CommonEntry)
+ASM_PFX(Exception16Handle):
+ cli
+ pushq %rcx
+ mov $16, %rcx
+ jmp ASM_PFX(CommonEntry)
+ASM_PFX(Exception17Handle):
+ cli
+ pushq %rcx
+ mov $17, %rcx
+ jmp ASM_PFX(CommonEntry)
+ASM_PFX(Exception18Handle):
+ cli
+ pushq %rcx
+ mov $18, %rcx
+ jmp ASM_PFX(CommonEntry)
+ASM_PFX(Exception19Handle):
+ cli
+ pushq %rcx
+ mov $19, %rcx
+ jmp ASM_PFX(CommonEntry)
+
+ASM_PFX(TimerInterruptHandle):
+ cli
+ pushq %rcx
+ mov $32, %rcx
+ jmp ASM_PFX(CommonEntry)
+
+
+ASM_PFX(CommonEntry):
+
+#---------------------------------------;
+# CommonInterruptEntry ;
+#---------------------------------------;
+# The follow algorithm is used for the common interrupt routine.
+
+#
+# +---------------------+ <-- 16-byte aligned ensured by processor
+# + Old SS +
+# +---------------------+
+# + Old RSP +
+# +---------------------+
+# + RFlags +
+# +---------------------+
+# + CS +
+# +---------------------+
+# + RIP +
+# +---------------------+
+# + Error Code +
+# +---------------------+
+# + RCX / Vector Number +
+# +---------------------+
+# + RBP +
+# +---------------------+ <-- RBP, 16-byte aligned
+#
+
+# We need to determine if any extra data was pushed by the exception
+ cmpq $DEBUG_EXCEPT_DOUBLE_FAULT, %rcx
+ je NoExtrPush
+ cmpq $DEBUG_EXCEPT_INVALID_TSS, %rcx
+ je NoExtrPush
+ cmpq $DEBUG_EXCEPT_SEG_NOT_PRESENT, %rcx
+ je NoExtrPush
+ cmpq $DEBUG_EXCEPT_STACK_FAULT, %rcx
+ je NoExtrPush
+ cmpq $DEBUG_EXCEPT_GP_FAULT, %rcx
+ je NoExtrPush
+ cmpq $DEBUG_EXCEPT_PAGE_FAULT, %rcx
+ je NoExtrPush
+ cmpq $DEBUG_EXCEPT_ALIGNMENT_CHECK, %rcx
+ je NoExtrPush
+
+ pushq (%rsp)
+ movq $0, 8(%rsp)
+
+NoExtrPush:
+ #
+ # All interrupt handlers are invoked through interrupt gates, so
+ # IF flag automatically cleared at the entry point
+ pushq %rbp
+ movq %rsp, %rbp
+
+ #
+ # Since here the stack pointer is 16-byte aligned, so
+ # EFI_FX_SAVE_STATE_X64 of EFI_SYSTEM_CONTEXT_x64
+ # is 16-byte aligned
+ #
+
+## UINT64 R8, R9, R10, R11, R12, R13, R14, R15;
+ pushq %r15
+ pushq %r14
+ pushq %r13
+ pushq %r12
+ pushq %r11
+ pushq %r10
+ pushq %r9
+ pushq %r8
+
+ movq %cr8, %r8
+ pushq %r8
+
+## UINT64 Rdi, Rsi, Rbp, Rsp, Rbx, Rdx, Rcx, Rax;
+ pushq %rax
+ pushq %rbx
+ pushq 8(%rbp) # original rcx
+ pushq %rdx
+ pushq 48(%rbp) # original rsp
+ pushq (%rbp) # original rbp
+ pushq %rsi
+ pushq %rdi
+
+## UINT64 Cr0, Cr1, Cr2, Cr3, Cr4;
+ movq %cr4, %rax
+ orq $0x208, %rax
+ movq %rax, %cr4
+ pushq %rax
+ movq %cr3, %rax
+ pushq %rax
+ movq %cr2, %rax
+ pushq %rax
+ xorq %rax, %rax
+ pushq %rax
+ movq %cr0, %rax
+ pushq %rax
+
+## UINT64 Gs, Fs, Es, Ds, Cs, Ss; insure high 16 bits of each is zero
+ xorq %rax, %rax # set rax to 0
+ movzwq 56(%rbp), %rax
+# movq %ss, %rax
+ pushq %rax
+ movzwq 32(%rbp), %rax
+# movq %cs, %rax
+ pushq %rax
+ movq %ds, %rax
+ pushq %rax
+ movq %es, %rax
+ pushq %rax
+ movq %fs, %rax
+ pushq %rax
+ movq %gs, %rax
+ pushq %rax
+
+## UINT64 Rip;
+ pushq 24(%rbp)
+
+## UINT64 Gdtr[2], Idtr[2];
+ subq $16, %rsp
+ sidt (%rsp)
+ subq $16, %rsp
+ sgdt (%rsp)
+
+## UINT64 Ldtr, Tr;
+ xorq %rax, %rax
+ strw %ax
+ pushq %rax
+ sldtw %ax
+ pushq %rax
+
+## UINT64 RFlags;
+ pushq 40(%rbp)
+
+## UINT64 Dr0, Dr1, Dr2, Dr3, Dr6, Dr7;
+ movq %dr7, %rax
+ pushq %rax
+## clear Dr7 while executing debugger itself
+ xorq %rax, %rax
+#debug movq %rax, %dr7
+
+ movq %dr6, %rax
+ pushq %rax
+## insure all status bits in dr6 are clear...
+ xorq %rax, %rax
+ movq %rax, %dr6
+
+ movq %dr3, %rax
+ pushq %rax
+ movq %dr2, %rax
+ pushq %rax
+ movq %dr1, %rax
+ pushq %rax
+ movq %dr0, %rax
+ pushq %rax
+
+## FX_SAVE_STATE_X64 FxSaveState;
+ subq $512, %rsp
+ movq %rsp, %rdi
+ .byte 0x0f, 0xae, 0b00000111
+
+## Clear Direction Flag
+ cld
+
+## Prepare parameter and call
+# movq 8(%rbp), %rcx
+ movq %rsp, %rdx
+ movq %rcx, %r15 # save vector in r15
+ #
+ # Per X64 calling convention, allocate maximum parameter stack space
+ # and make sure RSP is 16-byte aligned
+ #
+ subq $(4 * 8), %rsp
+ call ASM_PFX(InterruptProcess)
+ addq $(4 * 8), %rsp
+
+## FX_SAVE_STATE_X64 FxSaveState;
+
+ movq %rsp, %rsi
+ .byte 0x0f, 0xae, 0b00001110
+ addq $512, %rsp
+
+## UINT64 Dr0, Dr1, Dr2, Dr3, Dr6, Dr7;
+ popq %rax
+ movq %rax, %dr0
+ popq %rax
+ movq %rax, %dr1
+ popq %rax
+ movq %rax, %dr2
+ popq %rax
+ movq %rax, %dr3
+## skip restore of dr6. We cleared dr6 during the context save.
+ addq $8, %rsp
+ popq %rax
+ movq %rax, %dr7
+
+## UINT64 RFlags;
+ popq 40(%rbp)
+
+## UINT64 Ldtr, Tr;
+## UINT64 Gdtr[2], Idtr[2];
+## Best not let anyone mess with these particular registers...
+ addq $48, %rsp
+
+## UINT64 Rip;
+ popq 24(%rbp)
+
+## UINT64 Gs, Fs, Es, Ds, Cs, Ss;
+ popq %rax
+ # mov gs, rax ; not for gs
+ popq %rax
+ # mov fs, rax ; not for fs
+ # (X64 will not use fs and gs, so we do not restore it)
+ popq %rax
+ movw %rax, %es
+ popq %rax
+ movw %rax, %ds
+ popq 32(%rbp)
+ popq 56(%rbp)
+
+## UINT64 Cr0, Cr1, Cr2, Cr3, Cr4, Cr8;
+ popq %rax
+ movq %rax, %cr0
+ addq $8, %rsp
+ popq %rax
+ movq %rax, %cr2
+ popq %rax
+ movq %rax, %cr3
+ popq %rax
+ movq %rax, %cr4
+
+## UINT64 Rdi, Rsi, Rbp, Rsp, Rbx, Rdx, Rcx, Rax;
+## UINT64 R8, R9, R10, R11, R12, R13, R14, R15;
+ popq %rdi
+ popq %rsi
+ addq $8, %rsp
+ addq $8, %rsp
+ popq %rdx
+ popq %rcx
+ popq %rbx
+ popq %rax
+
+ popq %r8
+ movq %r8, %cr8
+
+ popq %r8
+ popq %r9
+ popq %r10
+ popq %r11
+ popq %r12
+ popq %r13
+ popq %r14
+ popq %r15
+
+ movq %rbp, %rsp
+ popq %rbp
+ addq $16, %rsp
+ iretq
diff --git a/SourceLevelDebugPkg/Library/DebugAgent/DebugAgentCommon/X64/AsmFuncs.asm b/SourceLevelDebugPkg/Library/DebugAgent/DebugAgentCommon/X64/AsmFuncs.asm
new file mode 100644
index 000000000..b712c428c
--- /dev/null
+++ b/SourceLevelDebugPkg/Library/DebugAgent/DebugAgentCommon/X64/AsmFuncs.asm
@@ -0,0 +1,364 @@
+;------------------------------------------------------------------------------
+;
+; Copyright (c) 2010, Intel Corporation. All rights reserved.<BR>
+; This program and the accompanying materials
+; are licensed and made available under the terms and conditions of the BSD License
+; which accompanies this distribution. The full text of the license may be found at
+; http://opensource.org/licenses/bsd-license.php.
+;
+; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+;
+; Module Name:
+;
+; AsmFuncs.asm
+;
+; Abstract:
+;
+; Debug interrupt handle functions.
+;
+;------------------------------------------------------------------------------
+
+#include "DebugException.h"
+
+
+externdef InterruptProcess:near
+
+data SEGMENT
+
+public Exception0Handle, TimerInterruptHandle, ExceptionStubHeaderSize
+
+ExceptionStubHeaderSize dw Exception1Handle - Exception0Handle ;
+CommonEntryAddr dq CommonEntry ;
+
+.code
+
+Exception0Handle:
+ cli
+ push rcx
+ mov rcx, 0
+ jmp qword ptr [CommonEntryAddr]
+Exception1Handle:
+ cli
+ push rcx
+ mov rcx, 1
+ jmp qword ptr [CommonEntryAddr]
+Exception2Handle:
+ cli
+ push rcx
+ mov rcx, 2
+ jmp qword ptr [CommonEntryAddr]
+Exception3Handle:
+ cli
+ push rcx
+ mov rcx, 3
+ jmp qword ptr [CommonEntryAddr]
+Exception4Handle:
+ cli
+ push rcx
+ mov rcx, 4
+ jmp qword ptr [CommonEntryAddr]
+Exception5Handle:
+ cli
+ push rcx
+ mov rcx, 5
+ jmp qword ptr [CommonEntryAddr]
+Exception6Handle:
+ cli
+ push rcx
+ mov rcx, 6
+ jmp qword ptr [CommonEntryAddr]
+Exception7Handle:
+ cli
+ push rcx
+ mov rcx, 7
+ jmp qword ptr [CommonEntryAddr]
+Exception8Handle:
+ cli
+ push rcx
+ mov rcx, 8
+ jmp qword ptr [CommonEntryAddr]
+Exception9Handle:
+ cli
+ push rcx
+ mov rcx, 9
+ jmp qword ptr [CommonEntryAddr]
+Exception10Handle:
+ cli
+ push rcx
+ mov rcx, 10
+ jmp qword ptr [CommonEntryAddr]
+Exception11Handle:
+ cli
+ push rcx
+ mov rcx, 11
+ jmp qword ptr [CommonEntryAddr]
+Exception12Handle:
+ cli
+ push rcx
+ mov rcx, 12
+ jmp qword ptr [CommonEntryAddr]
+Exception13Handle:
+ cli
+ push rcx
+ mov rcx, 13
+ jmp qword ptr [CommonEntryAddr]
+Exception14Handle:
+ cli
+ push rcx
+ mov rcx, 14
+ jmp qword ptr [CommonEntryAddr]
+Exception15Handle:
+ cli
+ push rcx
+ mov rcx, 15
+ jmp qword ptr [CommonEntryAddr]
+Exception16Handle:
+ cli
+ push rcx
+ mov rcx, 16
+ jmp qword ptr [CommonEntryAddr]
+Exception17Handle:
+ cli
+ push rcx
+ mov rcx, 17
+ jmp qword ptr [CommonEntryAddr]
+Exception18Handle:
+ cli
+ push rcx
+ mov rcx, 18
+ jmp qword ptr [CommonEntryAddr]
+Exception19Handle:
+ cli
+ push rcx
+ mov rcx, 19
+ jmp qword ptr [CommonEntryAddr]
+
+TimerInterruptHandle:
+ cli
+ push rcx
+ mov rcx, 32
+ jmp qword ptr [CommonEntryAddr]
+
+CommonEntry:
+ ; We need to determine if any extra data was pushed by the exception
+ cmp rcx, DEBUG_EXCEPT_DOUBLE_FAULT
+ je NoExtrPush
+ cmp rcx, DEBUG_EXCEPT_INVALID_TSS
+ je NoExtrPush
+ cmp rcx, DEBUG_EXCEPT_SEG_NOT_PRESENT
+ je NoExtrPush
+ cmp rcx, DEBUG_EXCEPT_STACK_FAULT
+ je NoExtrPush
+ cmp rcx, DEBUG_EXCEPT_GP_FAULT
+ je NoExtrPush
+ cmp rcx, DEBUG_EXCEPT_PAGE_FAULT
+ je NoExtrPush
+ cmp rcx, DEBUG_EXCEPT_ALIGNMENT_CHECK
+ je NoExtrPush
+
+ push [rsp]
+ mov qword ptr [rsp + 8], 0
+
+NoExtrPush:
+ push rbp
+ mov rbp, rsp
+
+ ; store UINT64 r8, r9, r10, r11, r12, r13, r14, r15;
+ push r15
+ push r14
+ push r13
+ push r12
+ push r11
+ push r10
+ push r9
+ push r8
+
+ mov r8, cr8
+ push r8
+
+ ; store UINT64 Rdi, Rsi, Rbp, Rsp, Rdx, Rcx, Rbx, Rax;
+ push rax
+ push rbx
+ push qword ptr [rbp + 8] ; original rcx
+ push rdx
+ push qword ptr [rbp + 6 * 8] ; original rsp
+ push qword ptr [rbp] ; original rbp
+ push rsi
+ push rdi
+
+ ;; UINT32 Cr0, Cr1, Cr2, Cr3, Cr4;
+ ;; insure FXSAVE/FXRSTOR is enabled in CR4...
+ ;; ... while we're at it, make sure DE is also enabled...
+ mov rax, cr4
+ or rax, 208h
+ mov cr4, rax
+ push rax
+ mov rax, cr3
+ push rax
+ mov rax, cr2
+ push rax
+ push 0 ; cr0 will not saved???
+ mov rax, cr0
+ push rax
+
+ xor rax, rax
+ mov rax, Ss
+ push rax
+ mov rax, Cs
+ push rax
+ mov rax, Ds
+ push rax
+ mov rax, Es
+ push rax
+ mov rax, Fs
+ push rax
+ mov rax, Gs
+ push rax
+
+ ;; EIP
+ mov rax, [rbp + 8 * 3] ; EIP
+ push rax
+
+ ;; UINT64 Gdtr[2], Idtr[2];
+ sub rsp, 16
+ sidt fword ptr [rsp]
+ sub rsp, 16
+ sgdt fword ptr [rsp]
+
+ ;; UINT64 Ldtr, Tr;
+ xor rax, rax
+ str ax
+ push rax
+ sldt ax
+ push rax
+
+ ;; EFlags
+ mov rax, [rbp + 8 * 5]
+ push rax
+
+ ;; UINT64 Dr0, Dr1, Dr2, Dr3, Dr6, Dr7;
+ mov rax, dr7
+ push rax
+
+ ;; clear Dr7 while executing debugger itself
+ xor rax, rax
+ mov dr7, rax
+
+ ;; Dr6
+ mov rax, dr6
+ push rax
+
+ ;; insure all status bits in dr6 are clear...
+ xor rax, rax
+ mov dr6, rax
+
+ mov rax, dr3
+ push rax
+ mov rax, dr2
+ push rax
+ mov rax, dr1
+ push rax
+ mov rax, dr0
+ push rax
+
+ sub rsp, 512
+ mov rdi, rsp
+ db 0fh, 0aeh, 00000111y ;fxsave [rdi]
+
+ ;; Clear Direction Flag
+ cld
+
+ ; call the C interrupt process function
+ mov rdx, rsp ; Structure
+ mov r15, rcx ; save vector in r15
+
+ sub rsp, 32
+ call InterruptProcess
+ add rsp, 32
+
+ mov rsi, rsp
+ db 0fh, 0aeh, 00001110y ; fxrstor [rsi]
+ add rsp, 512
+
+ ;; UINT64 Dr0, Dr1, Dr2, Dr3, Dr6, Dr7;
+ pop rax
+ mov dr0, rax
+ pop rax
+ mov dr1, rax
+ pop rax
+ mov dr2, rax
+ pop rax
+ mov dr3, rax
+ ;; skip restore of dr6. We cleared dr6 during the context save.
+ add rsp, 8
+ pop rax
+ mov dr7, rax
+
+ ;; set EFlags
+ pop qword ptr [rbp + 8 * 5]
+
+ ;; UINT64 Ldtr, Tr;
+ ;; UINT64 Gdtr[2], Idtr[2];
+ ;; Best not let anyone mess with these particular registers...
+ add rsp, 24 * 2
+
+ ;; UINT64 Eip;
+ pop qword ptr [rbp + 8 * 3] ; set EIP in stack
+
+ ;; UINT64 Gs, Fs, Es, Ds, Cs, Ss;
+ ;; NOTE - modified segment registers could hang the debugger... We
+ ;; could attempt to insulate ourselves against this possibility,
+ ;; but that poses risks as well.
+ ;;
+ pop rax
+ pop rax
+ pop rax
+ mov es, rax
+ pop rax
+ mov ds, rax
+ pop qword ptr [rbp + 8 * 4] ; Set CS in stack
+ pop rax
+ mov ss, rax
+
+ ;; UINT64 Cr0, Cr1, Cr2, Cr3, Cr4;
+ pop rax
+ mov cr0, rax
+ add rsp, 8 ; skip for Cr1
+ pop rax
+ mov cr2, rax
+ pop rax
+ mov cr3, rax
+ pop rax
+ mov cr4, rax
+
+ ;; restore general register
+ pop rdi
+ pop rsi
+ add rsp, 8 ; skip rbp
+ add rsp, 8 ; skip rsp
+ pop rdx
+ pop rcx
+ pop rbx
+ pop rax
+
+ pop r8
+ mov cr8, r8
+
+ ; store UINT64 r8, r9, r10, r11, r12, r13, r14, r15;
+ pop r8
+ pop r9
+ pop r10
+ pop r11
+ pop r12
+ pop r13
+ pop r14
+ pop r15
+
+ mov rsp, rbp
+ pop rbp
+ add rsp, 16 ; skip rcx and error code
+
+ iretq
+
+END
diff --git a/SourceLevelDebugPkg/Library/DebugAgent/DebugAgentCommon/X64/DebugException.h b/SourceLevelDebugPkg/Library/DebugAgent/DebugAgentCommon/X64/DebugException.h
new file mode 100644
index 000000000..13a7d23a0
--- /dev/null
+++ b/SourceLevelDebugPkg/Library/DebugAgent/DebugAgentCommon/X64/DebugException.h
@@ -0,0 +1,36 @@
+/** @file
+ Exception defintions.
+
+ Copyright (c) 2010, Intel Corporation. All rights reserved.<BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php.
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef _DEBUG_EXCEPTION_H_
+#define _DEBUG_EXCEPTION_H_
+
+#define DEBUG_EXCEPT_DIVIDE_ERROR 0
+#define DEBUG_EXCEPT_DEBUG 1
+#define DEBUG_EXCEPT_NMI 2
+#define DEBUG_EXCEPT_BREAKPOINT 3
+#define DEBUG_EXCEPT_OVERFLOW 4
+#define DEBUG_EXCEPT_BOUND 5
+#define DEBUG_EXCEPT_INVALID_OPCODE 6
+#define DEBUG_EXCEPT_DOUBLE_FAULT 8
+#define DEBUG_EXCEPT_INVALID_TSS 10
+#define DEBUG_EXCEPT_SEG_NOT_PRESENT 11
+#define DEBUG_EXCEPT_STACK_FAULT 12
+#define DEBUG_EXCEPT_GP_FAULT 13
+#define DEBUG_EXCEPT_PAGE_FAULT 14
+#define DEBUG_EXCEPT_FP_ERROR 16
+#define DEBUG_EXCEPT_ALIGNMENT_CHECK 17
+#define DEBUG_EXCEPT_MACHINE_CHECK 18
+#define DEBUG_EXCEPT_SIMD 19
+
+#endif
diff --git a/SourceLevelDebugPkg/Library/DebugAgent/DxeDebugAgent/DxeDebugAgentLib.c b/SourceLevelDebugPkg/Library/DebugAgent/DxeDebugAgent/DxeDebugAgentLib.c
new file mode 100644
index 000000000..cc49dc0a5
--- /dev/null
+++ b/SourceLevelDebugPkg/Library/DebugAgent/DxeDebugAgent/DxeDebugAgentLib.c
@@ -0,0 +1,247 @@
+/** @file
+ Debug Agent library implementition for Dxe Core and Dxr modules.
+
+ Copyright (c) 2010, Intel Corporation. All rights reserved.<BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php.
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "DxeDebugAgentLib.h"
+
+DEBUG_AGENT_MAILBOX mMailbox;
+
+DEBUG_AGENT_MAILBOX *mMailboxPointer;
+
+IA32_IDT_GATE_DESCRIPTOR mIdtEntryTable[33];
+
+BOOLEAN mConfigurationTableNeeded = FALSE;
+
+CONST BOOLEAN MultiProcessorDebugSupport = TRUE;
+
+/**
+ Constructor allocates the NVS memory to store Mailbox and install configuration table
+ in system table to store its pointer.
+
+ @param[in] ImageHandle The firmware allocated handle for the EFI image.
+ @param[in] SystemTable A pointer to the EFI System Table.
+
+ @retval RETURN_SUCCESS Allocate the global memory space to store guid and function tables.
+ @retval RETURN_OUT_OF_RESOURCES No enough memory to allocated.
+
+**/
+RETURN_STATUS
+EFIAPI
+DxeDebugAgentLibConstructor (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+ EFI_PHYSICAL_ADDRESS Address;
+
+ if (!mConfigurationTableNeeded) {
+ return RETURN_SUCCESS;
+ }
+
+ Address = 0;
+ Status = gBS->AllocatePages (
+ AllocateAnyPages,
+ EfiACPIMemoryNVS,
+ EFI_SIZE_TO_PAGES (sizeof (DEBUG_AGENT_MAILBOX)),
+ &Address
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ CopyMem (
+ (UINT8 *) (UINTN) Address,
+ (UINT8 *) (UINTN) mMailboxPointer,
+ sizeof (DEBUG_AGENT_MAILBOX)
+ );
+
+ mMailboxPointer = (DEBUG_AGENT_MAILBOX *) (UINTN) Address;
+
+ return gBS->InstallConfigurationTable (&gEfiDebugAgentGuid, (VOID *) mMailboxPointer);
+}
+
+/**
+ Get the pointer to Mailbox from the GUIDed HOB.
+
+ @param[in] HobStart The starting HOB pointer to search from.
+
+ @return Pointer to Mailbox.
+
+**/
+DEBUG_AGENT_MAILBOX *
+GetMailboxFromHob (
+ IN VOID *HobStart
+ )
+{
+ EFI_HOB_GUID_TYPE *GuidHob;
+
+ GuidHob = GetNextGuidHob (&gEfiDebugAgentGuid, HobStart);
+ if (GuidHob == NULL) {
+ return NULL;
+ }
+
+ return (DEBUG_AGENT_MAILBOX *) (GET_GUID_HOB_DATA(GuidHob));
+}
+
+/**
+ Get Debug Agent Mailbox pointer.
+
+ @return Mailbox pointer.
+
+**/
+DEBUG_AGENT_MAILBOX *
+GetMailboxPointer (
+ VOID
+ )
+{
+ return mMailboxPointer;
+}
+
+/**
+ Get debug port handle.
+
+ @return Debug port handle.
+
+**/
+DEBUG_PORT_HANDLE
+GetDebugPortHandle (
+ VOID
+ )
+{
+ return (DEBUG_PORT_HANDLE) (UINTN)(mMailboxPointer->DebugPortHandle);
+}
+
+
+/**
+ Initialize debug agent.
+
+ This function is used to set up debug enviroment for DXE phase.
+
+ If this function is called by DXE Core, Context must be the pointer
+ to HOB list which will be used to get GUIDed HOB. It will enable
+ interrupt to support break-in feature.
+ If this function is called by DXE module, Context must be NULL. It
+ will enable interrupt to support break-in feature.
+
+ @param[in] InitFlag Init flag is used to decide initialize process.
+ @param[in] Context Context needed according to InitFlag.
+ @param[in] Function Continue function called by debug agent library; it was
+ optional.
+
+**/
+VOID
+EFIAPI
+InitializeDebugAgent (
+ IN UINT32 InitFlag,
+ IN VOID *Context, OPTIONAL
+ IN DEBUG_AGENT_CONTINUE Function OPTIONAL
+ )
+{
+ DEBUG_AGENT_MAILBOX *Mailbox;
+ IA32_DESCRIPTOR Idtr;
+ UINT16 IdtEntryCount;
+ BOOLEAN InterruptStatus;
+
+ if (InitFlag != DEBUG_AGENT_INIT_DXE_CORE &&
+ InitFlag != DEBUG_AGENT_INIT_S3 &&
+ InitFlag != DEBUG_AGENT_INIT_DXE_AP) {
+ return;
+ }
+
+ //
+ // Save and disable original interrupt status
+ //
+ InterruptStatus = SaveAndDisableInterrupts ();
+
+ if (InitFlag == DEBUG_AGENT_INIT_DXE_CORE) {
+ //
+ // Try to get Mailbox from GUIDed HOB.
+ //
+ mConfigurationTableNeeded = TRUE;
+ Mailbox = GetMailboxFromHob (Context);
+
+ } else if (InitFlag == DEBUG_AGENT_INIT_DXE_AP) {
+
+ EnableInterrupts ();
+
+ return;
+
+ } else {
+ //
+ // If it is in S3 path, needn't to install configuration table.
+ //
+ Mailbox = NULL;
+ }
+
+ if (Mailbox != NULL) {
+ //
+ // If Mailbox exists, copy it into one global variable.
+ //
+ CopyMem (&mMailbox, Mailbox, sizeof (DEBUG_AGENT_MAILBOX));
+ mMailbox.DebugPortHandle = 0;
+ } else {
+ //
+ // If Mailbox not exists, used the local Mailbox.
+ //
+ ZeroMem (&mMailbox, sizeof (DEBUG_AGENT_MAILBOX));
+ }
+
+ mMailboxPointer = &mMailbox;
+
+ //
+ // Get original IDT address and size.
+ //
+ AsmReadIdtr ((IA32_DESCRIPTOR *) &Idtr);
+ IdtEntryCount = (UINT16) ((Idtr.Limit + 1) / sizeof (IA32_IDT_GATE_DESCRIPTOR));
+ if (IdtEntryCount < 33) {
+ Idtr.Limit = (UINT16) (sizeof (IA32_IDT_GATE_DESCRIPTOR) * 33 - 1);
+ Idtr.Base = (UINTN) &mIdtEntryTable;
+ AsmWriteIdtr ((IA32_DESCRIPTOR *) &Idtr);
+ }
+
+ //
+ // Initialize the IDT table entries to support source level debug.
+ //
+ InitializeDebugIdt ();
+
+ //
+ // Initialize debug communication port
+ //
+ mMailboxPointer->DebugPortHandle = (UINT64) (UINTN)DebugPortInitialize (NULL, NULL);
+
+ InitializeSpinLock (&mDebugMpContext.MpContextSpinLock);
+ InitializeSpinLock (&mDebugMpContext.DebugPortSpinLock);
+
+ if (InitFlag == DEBUG_AGENT_INIT_DXE_CORE) {
+ //
+ // Initialize Debug Timer hardware and enable interrupt.
+ //
+ InitializeDebugTimer ();
+ EnableInterrupts ();
+
+ return;
+ } else {
+ //
+ // Disable Debug Timer interrupt in S3 path.
+ //
+ SaveAndSetDebugTimerInterrupt (FALSE);
+
+ //
+ // Restore interrupt state.
+ //
+ SetInterruptState (InterruptStatus);
+ }
+
+}
+
diff --git a/SourceLevelDebugPkg/Library/DebugAgent/DxeDebugAgent/DxeDebugAgentLib.h b/SourceLevelDebugPkg/Library/DebugAgent/DxeDebugAgent/DxeDebugAgentLib.h
new file mode 100644
index 000000000..7d78c5183
--- /dev/null
+++ b/SourceLevelDebugPkg/Library/DebugAgent/DxeDebugAgent/DxeDebugAgentLib.h
@@ -0,0 +1,25 @@
+/** @file
+ Header file for Dxe Core Debug Agent Library instance.
+
+ Copyright (c) 2010, Intel Corporation. All rights reserved.<BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php.
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef _DXE_CORE_DEBUG_AGENT_LIB_H_
+#define _DXE_CORE_DEBUG_AGENT_LIB_H_
+
+#include <PiDxe.h>
+
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/UefiLib.h>
+
+#include "DebugAgent.h"
+
+#endif
diff --git a/SourceLevelDebugPkg/Library/DebugAgent/DxeDebugAgentLib.inf b/SourceLevelDebugPkg/Library/DebugAgent/DxeDebugAgentLib.inf
new file mode 100644
index 000000000..b93243725
--- /dev/null
+++ b/SourceLevelDebugPkg/Library/DebugAgent/DxeDebugAgentLib.inf
@@ -0,0 +1,87 @@
+## @file
+# Debug Agent library instance for Dxe Core and Dxe modules.
+#
+# Copyright (c) 2010, Intel Corporation. All rights reserved.<BR>
+#
+# This program and the accompanying materials
+# are licensed and made available under the terms and conditions of the BSD License
+# which accompanies this distribution. The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php.
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = DxeDebugAgentLib
+ FILE_GUID = BA6BAD25-B814-4747-B0B0-0FBB61D40B90
+ MODULE_TYPE = DXE_DRIVER
+ VERSION_STRING = 0.7
+ LIBRARY_CLASS = DebugAgentLib|DXE_CORE DXE_DRIVER
+
+ CONSTRUCTOR = DxeDebugAgentLibConstructor
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64
+#
+
+[Sources.common]
+ DxeDebugAgent/DxeDebugAgentLib.c
+ DxeDebugAgent/DxeDebugAgentLib.h
+ DebugAgentCommon/DebugAgent.c
+ DebugAgentCommon/DebugAgent.h
+ DebugAgentCommon/DebugTimer.c
+ DebugAgentCommon/DebugTimer.h
+ DebugAgentCommon/DebugMp.c
+ DebugAgentCommon/DebugMp.h
+
+[Sources.Ia32]
+ DebugAgentCommon/Ia32/AsmFuncs.S | GCC
+ DebugAgentCommon/Ia32/AsmFuncs.asm | MSFT
+ DebugAgentCommon/Ia32/ArchDebugSupport.h
+ DebugAgentCommon/Ia32/ArchDebugSupport.c
+ DebugAgentCommon/Ia32/ArchReadGroupRegister.c
+ DebugAgentCommon/Ia32/ArchRegisters.h
+ DebugAgentCommon/Ia32/DebugException.h
+
+[Sources.X64]
+ DebugAgentCommon/X64/AsmFuncs.S | GCC
+ DebugAgentCommon/X64/AsmFuncs.asm | MSFT
+ DebugAgentCommon/X64/ArchDebugSupport.h
+ DebugAgentCommon/X64/ArchDebugSupport.c
+ DebugAgentCommon/X64/ArchReadGroupRegister.c
+ DebugAgentCommon/X64/ArchRegisters.h
+ DebugAgentCommon/X64/DebugException.h
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ UefiCpuPkg/UefiCpuPkg.dec
+ SourceLevelDebugPkg/SourceLevelDebugPkg.dec
+
+[LibraryClasses]
+ BaseLib
+ BaseMemoryLib
+ ResetSystemLib
+ IoLib
+ HobLib
+ DebugCommunicationLib
+ UefiBootServicesTableLib
+ UefiLib
+ PcdLib
+ SynchronizationLib
+ MemoryAllocationLib
+ LocalApicLib
+
+[Guids]
+ gEfiDebugAgentGuid ## PRODUCES ## Configuration Table
+ gEfiDebugAgentGuid ## CONSUMES ## HOB
+
+[Pcd]
+ gEfiMdePkgTokenSpaceGuid.PcdFSBClock ## CONSUMES
+ gEfiSourceLevelDebugPkgTokenSpaceGuid.PcdExceptionsIgnoredByDebugger ## CONSUMES
+
diff --git a/SourceLevelDebugPkg/Library/DebugAgent/SecPeiDebugAgent/SecPeiDebugAgentLib.c b/SourceLevelDebugPkg/Library/DebugAgent/SecPeiDebugAgent/SecPeiDebugAgentLib.c
new file mode 100644
index 000000000..0d4169ccc
--- /dev/null
+++ b/SourceLevelDebugPkg/Library/DebugAgent/SecPeiDebugAgent/SecPeiDebugAgentLib.c
@@ -0,0 +1,307 @@
+/** @file
+ SEC Core Debug Agent Library instance implementition.
+
+ Copyright (c) 2010, Intel Corporation. All rights reserved.<BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php.
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "SecPeiDebugAgentLib.h"
+
+CONST BOOLEAN MultiProcessorDebugSupport = FALSE;
+
+/**
+ Get pointer to Mailbox from IDT entry before memory is ready.
+
+**/
+VOID *
+GetMailboxPointerInIdtEntry (
+ VOID
+ )
+{
+ IA32_IDT_GATE_DESCRIPTOR *IdtEntry;
+ IA32_DESCRIPTOR IdtDescriptor;
+ UINTN Mailbox;
+
+ AsmReadIdtr (&IdtDescriptor);
+ IdtEntry = (IA32_IDT_GATE_DESCRIPTOR *) IdtDescriptor.Base;
+
+ Mailbox = IdtEntry[DEBUG_MAILBOX_VECTOR].Bits.OffsetLow + (IdtEntry[DEBUG_MAILBOX_VECTOR].Bits.OffsetHigh << 16);
+ return (VOID *) Mailbox;
+}
+
+/**
+ Set the pointer of Mailbox into IDT entry before memory is ready.
+
+ @param[in] Mailbox The pointer of Mailbox.
+
+**/
+VOID
+SetMailboxPointerInIdtEntry (
+ IN VOID *Mailbox
+ )
+{
+ IA32_IDT_GATE_DESCRIPTOR *IdtEntry;
+ IA32_DESCRIPTOR IdtDescriptor;
+
+ AsmReadIdtr (&IdtDescriptor);
+ IdtEntry = (IA32_IDT_GATE_DESCRIPTOR *) IdtDescriptor.Base;
+
+ IdtEntry[DEBUG_MAILBOX_VECTOR].Bits.OffsetLow = (UINT16)(UINTN)Mailbox;
+ IdtEntry[DEBUG_MAILBOX_VECTOR].Bits.OffsetHigh = (UINT16)((UINTN)Mailbox >> 16);
+}
+
+/**
+ Get the pointer to Mailbox from IDT entry and build the Mailbox into GUIDed Hob
+ after memory is ready.
+
+ @return Pointer to Mailbox.
+
+**/
+DEBUG_AGENT_MAILBOX *
+BuildMailboxHob (
+ VOID
+ )
+{
+ DEBUG_AGENT_MAILBOX *Mailbox;
+
+ Mailbox = (DEBUG_AGENT_MAILBOX *) GetMailboxPointerInIdtEntry ();
+
+ return BuildGuidDataHob (
+ &gEfiDebugAgentGuid,
+ Mailbox,
+ sizeof (DEBUG_AGENT_MAILBOX)
+ );
+}
+
+/**
+ Get Debug Agent Mailbox pointer.
+
+ @return Mailbox pointer.
+
+**/
+DEBUG_AGENT_MAILBOX *
+GetMailboxPointer (
+ VOID
+ )
+{
+ return (DEBUG_AGENT_MAILBOX *) GetMailboxPointerInIdtEntry ();
+}
+
+/**
+ Get debug port handle.
+
+ @return Debug port handle.
+
+**/
+DEBUG_PORT_HANDLE
+GetDebugPortHandle (
+ VOID
+ )
+{
+ DEBUG_AGENT_MAILBOX *DebugAgentMailbox;
+
+ DebugAgentMailbox = (DEBUG_AGENT_MAILBOX *)GetMailboxPointerInIdtEntry ();
+
+ return (DEBUG_PORT_HANDLE) (UINTN)(DebugAgentMailbox->DebugPortHandle);
+}
+
+/**
+ Trigger one software interrupt to debug agent to handle it.
+
+ @param Signature Software interrupt signature.
+
+**/
+VOID
+TriggerSoftInterrupt (
+ UINT32 Signature
+ )
+{
+ UINTN Dr0;
+ UINTN Dr1;
+
+ //
+ // Save Debug Register State
+ //
+ Dr0 = AsmReadDr0 ();
+ Dr1 = AsmReadDr1 ();
+
+ //
+ // DR0 = Signature
+ //
+ AsmWriteDr0 (SOFT_INTERRUPT_SIGNATURE);
+ AsmWriteDr1 (Signature);
+
+ //
+ // Do INT3 to communicate with HOST side
+ //
+ CpuBreakpoint ();
+
+ //
+ // Restore Debug Register State only when Host didn't change it inside exception handler.
+ // Dr registers can only be changed by setting the HW breakpoint.
+ //
+ AsmWriteDr0 (Dr0);
+ AsmWriteDr1 (Dr1);
+
+}
+
+/**
+ Initialize debug agent.
+
+ This function is used to set up debug environment for SEC and PEI phase.
+
+ If InitFlag is DEBUG_AGENT_INIT_PREMEM_SEC, it will overirde IDT table entries
+ and initialize debug port. It will enable interrupt to support break-in feature.
+ It will set up debug agent Mailbox in cache-as-ramfrom. It will be called before
+ physical memory is ready.
+ If InitFlag is DEBUG_AGENT_INIT_POSTMEM_SEC, debug agent will build one GUIDed
+ HOB to copy debug agent Mailbox. It will be called after physical memory is ready.
+
+ This function is used to set up debug environment to support source level debugging.
+ If certain Debug Agent Library instance has to save some private data in the stack,
+ this function must work on the mode that doesn't return to the caller, then
+ the caller needs to wrap up all rest of logic after InitializeDebugAgent() into one
+ function and pass it into InitializeDebugAgent(). InitializeDebugAgent() is
+ responsible to invoke the passing-in function at the end of InitializeDebugAgent().
+
+ If the parameter Function is not NULL, Debug Agent Libary instance will invoke it by
+ passing in the Context to be its parameter.
+
+ If Function() is NULL, Debug Agent Library instance will return after setup debug
+ environment.
+
+ @param[in] InitFlag Init flag is used to decide the initialize process.
+ @param[in] Context Context needed according to InitFlag; it was optional.
+ @param[in] Function Continue function called by debug agent library; it was
+ optional.
+
+**/
+VOID
+EFIAPI
+InitializeDebugAgent (
+ IN UINT32 InitFlag,
+ IN VOID *Context, OPTIONAL
+ IN DEBUG_AGENT_CONTINUE Function OPTIONAL
+ )
+{
+ DEBUG_AGENT_MAILBOX *Mailbox;
+ DEBUG_AGENT_MAILBOX MailboxInStack;
+ DEBUG_AGENT_PHASE2_CONTEXT Phase2Context;
+ DEBUG_AGENT_CONTEXT_POSTMEM_SEC *DebugAgentContext;
+
+ if (InitFlag != DEBUG_AGENT_INIT_PREMEM_SEC &&
+ InitFlag != DEBUG_AGENT_INIT_POSTMEM_SEC) {
+ return;
+ }
+
+ DisableInterrupts ();
+
+ if (InitFlag == DEBUG_AGENT_INIT_POSTMEM_SEC) {
+
+ //
+ // Memory has been ready
+ //
+ if (IsHostConnected()) {
+ //
+ // Trigger one software interrupt to inform HOST
+ //
+ TriggerSoftInterrupt (MEMORY_READY_SIGNATURE);
+ }
+
+ DebugAgentContext = (DEBUG_AGENT_CONTEXT_POSTMEM_SEC *) Context;
+
+ Mailbox = (DEBUG_AGENT_MAILBOX *) GetMailboxPointerInIdtEntry ();
+ Mailbox->DebugPortHandle = Mailbox->DebugPortHandle + DebugAgentContext->StackMigrateOffset;
+
+ Mailbox = BuildMailboxHob ();
+ Mailbox = (DEBUG_AGENT_MAILBOX *) ((UINTN) Mailbox + DebugAgentContext->HeapMigrateOffset);
+
+ SetMailboxPointerInIdtEntry ((VOID *) Mailbox);
+
+ EnableInterrupts ();
+
+ if (Function != NULL) {
+ Function (Context);
+ }
+
+ return;
+
+ } else {
+
+ InitializeDebugIdt ();
+
+ Mailbox = &MailboxInStack;
+ ZeroMem ((VOID *) Mailbox, sizeof (DEBUG_AGENT_MAILBOX));
+
+ //
+ // Get and save debug port handle and set the length of memory block.
+ //
+ SetMailboxPointerInIdtEntry ((VOID *) Mailbox);
+
+ InitializeDebugTimer ();
+
+ Phase2Context.Context = Context;
+ Phase2Context.Function = Function;
+ DebugPortInitialize ((VOID *) &Phase2Context, InitializeDebugAgentPhase2);
+
+ return;
+ }
+}
+
+/**
+ Caller provided function to be invoked at the end of DebugPortInitialize().
+
+ Refer to the descrption for DebugPortInitialize() for more details.
+
+ @param[in] Context The first input argument of DebugPortInitialize().
+ @param[in] DebugPortHandle Debug port handle created by Debug Communication Libary.
+
+**/
+VOID
+EFIAPI
+InitializeDebugAgentPhase2 (
+ IN VOID *Context,
+ IN DEBUG_PORT_HANDLE DebugPortHandle
+ )
+{
+ DEBUG_AGENT_PHASE2_CONTEXT *Phase2Context;
+ DEBUG_AGENT_MAILBOX *Mailbox;
+ EFI_SEC_PEI_HAND_OFF *SecCoreData;
+
+ Mailbox = GetMailboxPointerInIdtEntry ();
+ Mailbox->DebugPortHandle = (UINT64) (UINTN)DebugPortHandle;
+
+ //
+ // Trigger one software interrupt to inform HOST
+ //
+ TriggerSoftInterrupt (SYSTEM_RESET_SIGNATURE);
+
+ //
+ // If Temporary RAM region is below 128 MB, then send message to
+ // host to disable low memory filtering.
+ //
+ Phase2Context = (DEBUG_AGENT_PHASE2_CONTEXT *) Context;
+ SecCoreData = (EFI_SEC_PEI_HAND_OFF *)Phase2Context->Context;
+ if ((UINTN)SecCoreData->TemporaryRamBase < BASE_128MB) {
+ TriggerSoftInterrupt (MEMORY_READY_SIGNATURE);
+ }
+
+ //
+ // Enable CPU interrupts so debug timer interrupts can be delivered
+ //
+ EnableInterrupts ();
+
+ //
+ // Call continuation function is it is not NULL.
+ //
+ if (Phase2Context->Function != NULL) {
+ Phase2Context->Function (Phase2Context->Context);
+ }
+}
diff --git a/SourceLevelDebugPkg/Library/DebugAgent/SecPeiDebugAgent/SecPeiDebugAgentLib.h b/SourceLevelDebugPkg/Library/DebugAgent/SecPeiDebugAgent/SecPeiDebugAgentLib.h
new file mode 100644
index 000000000..9ca5e87fb
--- /dev/null
+++ b/SourceLevelDebugPkg/Library/DebugAgent/SecPeiDebugAgent/SecPeiDebugAgentLib.h
@@ -0,0 +1,28 @@
+/** @file
+ Header file for Sec Core Debug Agent Library instance.
+
+ Copyright (c) 2010, Intel Corporation. All rights reserved.<BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php.
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef _SEC_CORE_DEBUG_AGENT_LIB_H_
+#define _SEC_CORE_DEBUG_AGENT_LIB_H_
+
+#include <PiPei.h>
+
+#include "DebugAgent.h"
+
+typedef struct {
+ VOID *Context;
+ DEBUG_AGENT_CONTINUE Function;
+} DEBUG_AGENT_PHASE2_CONTEXT;
+
+#endif
+
diff --git a/SourceLevelDebugPkg/Library/DebugAgent/SecPeiDebugAgentLib.inf b/SourceLevelDebugPkg/Library/DebugAgent/SecPeiDebugAgentLib.inf
new file mode 100644
index 000000000..e2b8ad60a
--- /dev/null
+++ b/SourceLevelDebugPkg/Library/DebugAgent/SecPeiDebugAgentLib.inf
@@ -0,0 +1,81 @@
+## @file
+# Debug Agent library instance for SEC Core and PEI modules.
+#
+# Copyright (c) 2010, Intel Corporation. All rights reserved.<BR>
+#
+# This program and the accompanying materials
+# are licensed and made available under the terms and conditions of the BSD License
+# which accompanies this distribution. The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php.
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = SecPeiDebugAgentLib
+ FILE_GUID = 508B7D59-CD4E-4a6b-A45B-6D3B2D90111E
+ MODULE_TYPE = PEIM
+ VERSION_STRING = 0.7
+ LIBRARY_CLASS = DebugAgentLib|SEC PEIM
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64
+#
+
+[Sources.common]
+ SecPeiDebugAgent/SecPeiDebugAgentLib.c
+ SecPeiDebugAgent/SecPeiDebugAgentLib.h
+ DebugAgentCommon/DebugAgent.c
+ DebugAgentCommon/DebugAgent.h
+ DebugAgentCommon/DebugTimer.c
+ DebugAgentCommon/DebugTimer.h
+ DebugAgentCommon/DebugMp.c
+ DebugAgentCommon/DebugMp.h
+
+[Sources.Ia32]
+ DebugAgentCommon/Ia32/AsmFuncs.S | GCC
+ DebugAgentCommon/Ia32/AsmFuncs.asm | MSFT
+ DebugAgentCommon/Ia32/ArchDebugSupport.h
+ DebugAgentCommon/Ia32/ArchDebugSupport.c
+ DebugAgentCommon/Ia32/ArchReadGroupRegister.c
+ DebugAgentCommon/Ia32/ArchRegisters.h
+ DebugAgentCommon/Ia32/DebugException.h
+
+[Sources.X64]
+ DebugAgentCommon/X64/AsmFuncs.S | GCC
+ DebugAgentCommon/X64/AsmFuncs.asm | MSFT
+ DebugAgentCommon/X64/ArchDebugSupport.h
+ DebugAgentCommon/X64/ArchDebugSupport.c
+ DebugAgentCommon/X64/ArchReadGroupRegister.c
+ DebugAgentCommon/X64/ArchRegisters.h
+ DebugAgentCommon/X64/DebugException.h
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ UefiCpuPkg/UefiCpuPkg.dec
+ SourceLevelDebugPkg/SourceLevelDebugPkg.dec
+
+[LibraryClasses]
+ BaseLib
+ BaseMemoryLib
+ ResetSystemLib
+ IoLib
+ HobLib
+ PcdLib
+ DebugCommunicationLib
+ SynchronizationLib
+ LocalApicLib
+
+[Guids]
+ gEfiDebugAgentGuid ## PRODUCES ## HOB
+
+[Pcd]
+ gEfiMdePkgTokenSpaceGuid.PcdFSBClock ## CONSUMES
+ gEfiSourceLevelDebugPkgTokenSpaceGuid.PcdExceptionsIgnoredByDebugger ## CONSUMES
+
diff --git a/SourceLevelDebugPkg/Library/DebugAgent/SmmDebugAgent/SmmDebugAgentLib.c b/SourceLevelDebugPkg/Library/DebugAgent/SmmDebugAgent/SmmDebugAgentLib.c
new file mode 100644
index 000000000..fa4231165
--- /dev/null
+++ b/SourceLevelDebugPkg/Library/DebugAgent/SmmDebugAgent/SmmDebugAgentLib.c
@@ -0,0 +1,157 @@
+/** @file
+ Debug Agent library implementition.
+
+ Copyright (c) 2010, Intel Corporation. All rights reserved.<BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php.
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "SmmDebugAgentLib.h"
+
+DEBUG_AGENT_MAILBOX *mMailboxPointer = NULL;
+
+GLOBAL_REMOVE_IF_UNREFERENCED DEBUG_AGENT_MAILBOX mLocalMailbox;
+
+GLOBAL_REMOVE_IF_UNREFERENCED UINTN mSavedDebugRegisters[6];
+
+CONST BOOLEAN MultiProcessorDebugSupport = FALSE;
+
+
+/**
+ Get Debug Agent Mailbox pointer.
+
+ @return Mailbox pointer.
+
+**/
+DEBUG_AGENT_MAILBOX *
+GetMailboxPointer (
+ VOID
+ )
+{
+ return mMailboxPointer;
+}
+
+/**
+ Get debug port handle.
+
+ @return Debug port handle.
+
+**/
+DEBUG_PORT_HANDLE
+GetDebugPortHandle (
+ VOID
+ )
+{
+ return (DEBUG_PORT_HANDLE) (UINTN)(mMailboxPointer->DebugPortHandle);
+}
+
+/**
+ Store debug register when SMI exit.
+
+**/
+VOID
+SaveDebugRegister (
+ VOID
+ )
+{
+ mSavedDebugRegisters[0] = AsmReadDr0 ();
+ mSavedDebugRegisters[1] = AsmReadDr1 ();
+ mSavedDebugRegisters[2] = AsmReadDr2 ();
+ mSavedDebugRegisters[3] = AsmReadDr3 ();
+ mSavedDebugRegisters[4] = AsmReadDr6 ();
+ mSavedDebugRegisters[5] = AsmReadDr7 ();
+}
+
+/**
+ Restore debug register when SMI exit.
+
+**/
+VOID
+RestoreDebugRegister (
+ VOID
+ )
+{
+ AsmWriteDr7 (0);
+ AsmWriteDr0 (mSavedDebugRegisters[0]);
+ AsmWriteDr1 (mSavedDebugRegisters[1]);
+ AsmWriteDr2 (mSavedDebugRegisters[2]);
+ AsmWriteDr3 (mSavedDebugRegisters[3]);
+ AsmWriteDr6 (mSavedDebugRegisters[4]);
+ AsmWriteDr7 (mSavedDebugRegisters[5]);
+}
+
+/**
+ Initialize debug agent.
+
+ This function is used to set up debug enviroment for source level debug
+ in SMM code.
+
+ If InitFlag is DEBUG_AGENT_INIT_SMM, it will overirde IDT table entries
+ and initialize debug port. It will get debug agent Mailbox from GUIDed HOB,
+ it it exists, debug agent wiil copied it into the local Mailbox in SMM space.
+ it will overirde IDT table entries and initialize debug port. Context will be
+ NULL.
+ If InitFlag is DEBUG_AGENT_INIT_ENTER_SMI, debug agent will save Debug
+ Registers and get local Mailbox in SMM space. Context will be NULL.
+ If InitFlag is DEBUG_AGENT_INIT_EXIT_SMI, debug agent will restore Debug
+ Registers. Context will be NULL.
+
+ @param[in] InitFlag Init flag is used to decide initialize process.
+ @param[in] Context Context needed according to InitFlag.
+ @param[in] Function Continue function called by debug agent library; it was
+ optional.
+
+**/
+VOID
+EFIAPI
+InitializeDebugAgent (
+ IN UINT32 InitFlag,
+ IN VOID *Context, OPTIONAL
+ IN DEBUG_AGENT_CONTINUE Function OPTIONAL
+ )
+{
+ EFI_STATUS Status;
+ UINT64 DebugPortHandle;
+
+ switch (InitFlag) {
+ case DEBUG_AGENT_INIT_SMM:
+ Status = EfiGetSystemConfigurationTable (&gEfiDebugAgentGuid, (VOID **) &mMailboxPointer);
+ if (EFI_ERROR (Status) || mMailboxPointer == NULL) {
+ ZeroMem (&mLocalMailbox, sizeof (DEBUG_AGENT_MAILBOX));
+ mMailboxPointer = &mLocalMailbox;
+ }
+
+ break;
+
+ case DEBUG_AGENT_INIT_ENTER_SMI:
+ SaveDebugRegister ();
+ InitializeDebugIdt ();
+
+ if (mMailboxPointer != NULL) {
+ //
+ // Initialize debug communication port
+ //
+ DebugPortHandle = (UINT64) (UINTN)DebugPortInitialize ((DEBUG_PORT_HANDLE) (UINTN)mMailboxPointer->DebugPortHandle, NULL);
+ mMailboxPointer->DebugPortHandle = DebugPortHandle;
+
+ if (mMailboxPointer->DebugFlag.Bits.BreakOnNextSmi == 1) {
+ //
+ // If SMM entry break is set, SMM code will be break at here.
+ //
+ CpuBreakpoint ();
+ }
+ }
+ break;
+
+ case DEBUG_AGENT_INIT_EXIT_SMI:
+ RestoreDebugRegister ();
+ break;
+ }
+}
+
diff --git a/SourceLevelDebugPkg/Library/DebugAgent/SmmDebugAgent/SmmDebugAgentLib.h b/SourceLevelDebugPkg/Library/DebugAgent/SmmDebugAgent/SmmDebugAgentLib.h
new file mode 100644
index 000000000..ccb55f830
--- /dev/null
+++ b/SourceLevelDebugPkg/Library/DebugAgent/SmmDebugAgent/SmmDebugAgentLib.h
@@ -0,0 +1,24 @@
+/** @file
+ Header file for Smm Debug Agent Library instance.
+
+ Copyright (c) 2010, Intel Corporation. All rights reserved.<BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php.
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef _SMM_DEBUG_AGENT_LIB_H_
+#define _SMM_DEBUG_AGENT_LIB_H_
+
+#include <PiDxe.h>
+
+#include <Library/UefiLib.h>
+
+#include "DebugAgent.h"
+
+#endif
diff --git a/SourceLevelDebugPkg/Library/DebugAgent/SmmDebugAgentLib.inf b/SourceLevelDebugPkg/Library/DebugAgent/SmmDebugAgentLib.inf
new file mode 100644
index 000000000..9dfdec1d3
--- /dev/null
+++ b/SourceLevelDebugPkg/Library/DebugAgent/SmmDebugAgentLib.inf
@@ -0,0 +1,81 @@
+## @file
+# Debug Agent library instance for SMM modules.
+#
+# Copyright (c) 2010, Intel Corporation. All rights reserved.<BR>
+#
+# This program and the accompanying materials
+# are licensed and made available under the terms and conditions of the BSD License
+# which accompanies this distribution. The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php.
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = SecDebugAgentLib
+ FILE_GUID = CB07D74C-598F-4268-A5D1-644FB4A481E8
+ MODULE_TYPE = DXE_SMM_DRIVER
+ VERSION_STRING = 0.7
+ LIBRARY_CLASS = DebugAgentLib|DXE_SMM_DRIVER
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64
+#
+
+[Sources.common]
+ SmmDebugAgent/SmmDebugAgentLib.c
+ SmmDebugAgent/SmmDebugAgentLib.h
+ DebugAgentCommon/DebugAgent.c
+ DebugAgentCommon/DebugAgent.h
+ DebugAgentCommon/DebugTimer.c
+ DebugAgentCommon/DebugTimer.h
+ DebugAgentCommon/DebugMp.c
+ DebugAgentCommon/DebugMp.h
+
+[Sources.Ia32]
+ DebugAgentCommon/Ia32/AsmFuncs.S | GCC
+ DebugAgentCommon/Ia32/AsmFuncs.asm | MSFT
+ DebugAgentCommon/Ia32/ArchDebugSupport.h
+ DebugAgentCommon/Ia32/ArchDebugSupport.c
+ DebugAgentCommon/Ia32/ArchReadGroupRegister.c
+ DebugAgentCommon/Ia32/ArchRegisters.h
+ DebugAgentCommon/Ia32/DebugException.h
+
+[Sources.X64]
+ DebugAgentCommon/X64/AsmFuncs.S | GCC
+ DebugAgentCommon/X64/AsmFuncs.asm | MSFT
+ DebugAgentCommon/X64/ArchDebugSupport.h
+ DebugAgentCommon/X64/ArchDebugSupport.c
+ DebugAgentCommon/X64/ArchReadGroupRegister.c
+ DebugAgentCommon/X64/ArchRegisters.h
+ DebugAgentCommon/X64/DebugException.h
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ UefiCpuPkg/UefiCpuPkg.dec
+ SourceLevelDebugPkg/SourceLevelDebugPkg.dec
+
+[LibraryClasses]
+ BaseLib
+ BaseMemoryLib
+ ResetSystemLib
+ IoLib
+ DebugCommunicationLib
+ UefiLib
+ PcdLib
+ SynchronizationLib
+ LocalApicLib
+
+[Guids]
+ gEfiDebugAgentGuid ## CONSUMES ## Configuration Table
+
+[Pcd]
+ gEfiMdePkgTokenSpaceGuid.PcdFSBClock ## CONSUMES
+ gEfiSourceLevelDebugPkgTokenSpaceGuid.PcdExceptionsIgnoredByDebugger ## CONSUMES
+
diff --git a/SourceLevelDebugPkg/Library/DebugCommunicationLibSerialPort/DebugCommunicationLibSerialPort.c b/SourceLevelDebugPkg/Library/DebugCommunicationLibSerialPort/DebugCommunicationLibSerialPort.c
new file mode 100644
index 000000000..ed1a35bd9
--- /dev/null
+++ b/SourceLevelDebugPkg/Library/DebugCommunicationLibSerialPort/DebugCommunicationLibSerialPort.c
@@ -0,0 +1,169 @@
+/** @file
+ Debug Port Library implementation based on serial port.
+
+ Copyright (c) 2010, Intel Corporation. All rights reserved.<BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php.
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include <Base.h>
+
+#include <Library/DebugCommunicationLib.h>
+#include <Library/SerialPortLib.h>
+#include <Library/TimerLib.h>
+
+/**
+ Initialize the debug port.
+
+ This function will initialize debug port to get it ready for data transmition. If
+ certain Debug Communication Library instance has to save some private data in the
+ stack, this function must work on the mode that doesn't return to the caller, then
+ the caller needs to wrap up all rest of logic after DebugPortInitialize() into one
+ function and pass it into DebugPortInitialize(). DebugPortInitialize() is
+ responsible to invoke the passing-in funciton at the end of DebugPortInitialize().
+
+ If the paramter Function is not NULL, Debug Communication Libary instance will
+ invoke it by passing in the Context to be the first parameter. Debug Communication
+ Library instance could create one debug port handle to be the second parameter
+ passing into the Function. Debug Communication Library instance also could pass
+ NULL to be the second parameter if it doesn't create the debug port handle.
+
+ If the parameter Function is NULL, and Context is not NULL. At this time, Context
+ is the debug port handle created by the previous Debug Communication Library
+ instance.
+ a) If the instance can understand and continue use the private data of the previous
+ instance, it could return the same handle as passed in (as Context parameter).
+ b) If the instance does not understand, or does not want to continue use the
+ private data of the previous instance, it could ignore the input Context parameter
+ and create the new hanlde to be returned.
+
+ If Function() is NULL and Context is NULL, Debug Communication Library could create a
+ new handle and return it. NULL is also a valid handle to be returned.
+
+ @param[in] Context Context needed by callback function; it was optional.
+ @param[in] Function Continue function called by Debug Communication library;
+ it was optional.
+
+ @return The debug port handle created by Debug Communication Library if Function
+ is not NULL.
+
+**/
+DEBUG_PORT_HANDLE
+EFIAPI
+DebugPortInitialize (
+ IN VOID *Context,
+ IN DEBUG_PORT_CONTINUE Function
+ )
+{
+ SerialPortInitialize ();
+
+ if (Function != NULL) {
+ Function (Context, NULL);
+ }
+
+ return NULL;
+}
+
+/**
+ Read data from debug device and save the datas in buffer.
+
+ Reads NumberOfBytes data bytes from a debug device into the buffer
+ specified by Buffer. The number of bytes actually read is returned.
+ If the return value is less than NumberOfBytes, then the rest operation failed.
+ If NumberOfBytes is zero, then return 0.
+
+ @param Handle Debug port handle.
+ @param Buffer Pointer to the data buffer to store the data read from the debug device.
+ @param NumberOfBytes Number of bytes which will be read.
+ @param Timeout Timeout value for reading from debug device. It unit is Microsecond.
+
+ @retval 0 Read data failed, no data is to be read.
+ @retval >0 Actual number of bytes read from debug device.
+
+**/
+UINTN
+EFIAPI
+DebugPortReadBuffer (
+ IN DEBUG_PORT_HANDLE Handle,
+ IN UINT8 *Buffer,
+ IN UINTN NumberOfBytes,
+ IN UINTN Timeout
+ )
+{
+ UINTN Index;
+ INTN Elapsed;
+
+ for (Index = 0; Index < NumberOfBytes; Index ++) {
+ Elapsed = (INTN) Timeout;
+ while (TRUE) {
+ if (SerialPortPoll () || Timeout == 0) {
+ SerialPortRead (Buffer + Index, 1);
+ break;
+ }
+ MicroSecondDelay (1000);
+ Elapsed -= 1000;
+ if (Elapsed < 0) {
+ return 0;
+ }
+ }
+ }
+
+ return NumberOfBytes;
+}
+
+/**
+ Write data from buffer to debug device.
+
+ Writes NumberOfBytes data bytes from Buffer to the debug device.
+ The number of bytes actually written to the debug device is returned.
+ If the return value is less than NumberOfBytes, then the write operation failed.
+ If NumberOfBytes is zero, then return 0.
+
+ @param Handle Debug port handle.
+ @param Buffer Pointer to the data buffer to be written.
+ @param NumberOfBytes Number of bytes to written to the debug device.
+
+ @retval 0 NumberOfBytes is 0.
+ @retval >0 The number of bytes written to the debug device.
+ If this value is less than NumberOfBytes, then the read operation failed.
+
+**/
+UINTN
+EFIAPI
+DebugPortWriteBuffer (
+ IN DEBUG_PORT_HANDLE Handle,
+ IN UINT8 *Buffer,
+ IN UINTN NumberOfBytes
+ )
+{
+ return SerialPortWrite (Buffer, NumberOfBytes);
+}
+
+/**
+ Polls a debug device to see if there is any data waiting to be read.
+
+ Polls a debug device to see if there is any data waiting to be read.
+ If there is data waiting to be read from the debug device, then TRUE is returned.
+ If there is no data waiting to be read from the debug device, then FALSE is returned.
+
+ @param Handle Debug port handle.
+
+ @retval TRUE Data is waiting to be read from the debug device.
+ @retval FALSE There is no data waiting to be read from the serial device.
+
+**/
+BOOLEAN
+EFIAPI
+DebugPortPollBuffer (
+ IN DEBUG_PORT_HANDLE Handle
+ )
+{
+ return SerialPortPoll ();
+}
+
diff --git a/SourceLevelDebugPkg/Library/DebugCommunicationLibSerialPort/DebugCommunicationLibSerialPort.inf b/SourceLevelDebugPkg/Library/DebugCommunicationLibSerialPort/DebugCommunicationLibSerialPort.inf
new file mode 100644
index 000000000..dff0fc92b
--- /dev/null
+++ b/SourceLevelDebugPkg/Library/DebugCommunicationLibSerialPort/DebugCommunicationLibSerialPort.inf
@@ -0,0 +1,38 @@
+## @file
+# Debug Communication Library instance based on serila port.
+#
+# Copyright (c) 2010, Intel Corporation. All rights reserved.<BR>
+#
+# This program and the accompanying materials
+# are licensed and made available under the terms and conditions of the BSD License
+# which accompanies this distribution. The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php.
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = DebugCommunicationLibSerialPort
+ FILE_GUID = 8CC435C5-6330-4269-B0C3-E3BD05C86FB8
+ MODULE_TYPE = BASE
+ VERSION_STRING = 0.7
+ LIBRARY_CLASS = DebugCommunicationLib
+
+#
+# VALID_ARCHITECTURES = IA32 X64
+#
+
+[Sources.common]
+ DebugCommunicationLibSerialPort.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ SourceLevelDebugPkg/SourceLevelDebugPkg.dec
+
+[LibraryClasses]
+ SerialPortLib
+ TimerLib
+
diff --git a/SourceLevelDebugPkg/Library/DebugCommunicationLibUsb/DebugCommunicationLibUsb.c b/SourceLevelDebugPkg/Library/DebugCommunicationLibUsb/DebugCommunicationLibUsb.c
new file mode 100644
index 000000000..588e45853
--- /dev/null
+++ b/SourceLevelDebugPkg/Library/DebugCommunicationLibUsb/DebugCommunicationLibUsb.c
@@ -0,0 +1,1076 @@
+/** @file
+ Debug Port Library implementation based on usb debug port.
+
+ Copyright (c) 2010, Intel Corporation. All rights reserved.<BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php.
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include <Base.h>
+#include <IndustryStandard/Pci.h>
+#include <IndustryStandard/Usb.h>
+#include <Library/IoLib.h>
+#include <Library/PciLib.h>
+#include <Library/PcdLib.h>
+#include <Library/TimerLib.h>
+#include <Library/DebugCommunicationLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/BaseLib.h>
+
+#define SETUP_PID 0x2D
+#define INPUT_PID 0x69
+#define OUTPUT_PID 0xE1
+#define ERROR_PID 0x55
+#define DATA0_PID 0xC3
+#define DATA1_PID 0x4B
+#define DATA2_PID 0x87
+#define MDATA_PID 0x0F
+#define ACK_PID 0xD2
+#define NAK_PID 0x5A
+#define STALL_PID 0x1E
+#define NYET_PID 0x96
+
+#define PCI_CAPABILITY_ID_DEBUG_PORT 0x0A
+#define USB_DEBUG_PORT_MAX_PACKET_SIZE 0x08
+
+#define USB_DEBUG_PORT_IN_USE BIT10
+#define USB_DEBUG_PORT_ENABLE BIT28
+#define USB_DEBUG_PORT_OWNER BIT30
+
+#define USB_PORT_LINE_STATUS_LS 0x400
+#define USB_PORT_LINE_STATUS_MASK 0xC00
+
+//
+// Usb debug device descriptor, which is defined at
+// USB2 Debug Device Specification.
+//
+typedef struct _USB_DEBUG_PORT_DESCRIPTOR {
+ UINT8 Length;
+ UINT8 DescriptorType;
+ UINT8 DebugInEndpoint;
+ UINT8 DebugOutEndpoint;
+}USB_DEBUG_PORT_DESCRIPTOR;
+
+USB_DEVICE_REQUEST mGetDebugDescriptor = {
+ 0x80,
+ USB_REQ_GET_DESCRIPTOR,
+ (UINT16)(0x0A << 8),
+ 0x0000,
+ sizeof(USB_DEBUG_PORT_DESCRIPTOR)
+ };
+
+USB_DEVICE_REQUEST mSetDebugFeature = {
+ 0x0,
+ USB_REQ_SET_FEATURE,
+ (UINT16)(0x06),
+ 0x0000,
+ 0x0
+ };
+
+USB_DEVICE_REQUEST mSetDebugAddress = {
+ 0x0,
+ USB_REQ_SET_ADDRESS,
+ (UINT16)(0x7F),
+ 0x0000,
+ 0x0
+ };
+
+//
+// Usb debug port register file, which is defined at
+// EHCI Specification.
+//
+typedef struct _USB_DEBUG_PORT_REGISTER {
+ UINT32 ControlStatus;
+ UINT8 TokenPid;
+ UINT8 SendPid;
+ UINT8 ReceivedPid;
+ UINT8 Reserved1;
+ UINT8 DataBuffer[8];
+ UINT8 UsbEndPoint;
+ UINT8 UsbAddress;
+ UINT8 Reserved2;
+ UINT8 Reserved3;
+}USB_DEBUG_PORT_REGISTER;
+
+#pragma pack(1)
+//
+// The internal data structure of DEBUG_PORT_HANDLE, which stores some
+// important datum which are used across various phases.
+//
+typedef struct _USB_DEBUG_PORT_HANDLE{
+ //
+ // The usb debug port memory BAR number in EHCI configuration space.
+ //
+ UINT8 DebugPortBarNumber;
+ UINT8 Reserved;
+ //
+ // The offset of usb debug port registers in EHCI memory range.
+ //
+ UINT16 DebugPortOffset;
+ //
+ // The usb debug port memory BAR address.
+ //
+ UINTN UsbDebugPortMemoryBase;
+ //
+ // The EHCI memory BAR address.
+ //
+ UINTN EhciMemoryBase;
+ //
+ // The Bulk In endpoint toggle bit.
+ //
+ UINT8 BulkInToggle;
+ //
+ // The Bulk Out endpoint toggle bit.
+ //
+ UINT8 BulkOutToggle;
+ //
+ // The available data length in the following data buffer.
+ //
+ UINT8 DataCount;
+ //
+ // The data buffer. Maximum length is 8 bytes.
+ //
+ UINT8 Data[8];
+} USB_DEBUG_PORT_HANDLE;
+#pragma pack()
+
+//
+// The global variable which can be used after memory is ready.
+//
+USB_DEBUG_PORT_HANDLE mUsbDebugPortHandle;
+
+/**
+ Calculate the usb debug port bar address.
+
+ @param DebugPortOffset Get usb debug port offset in the usb debug port memory space.
+ @param DebugPortBarNumbar Get the bar number at which usb debug port is located.
+
+ @retval RETURN_UNSUPPORTED The usb host controller does not supported usb debug port capability.
+ @retval RETURN_SUCCESS Get bar and offset successfully.
+
+**/
+RETURN_STATUS
+EFIAPI
+CalculateUsbDebugPortBar (
+ OUT UINT16 *DebugPortOffset,
+ OUT UINT8 *DebugPortBarNumbar
+ )
+{
+ UINT16 PciStatus;
+ UINT8 CapabilityPtr;
+ UINT8 CapabilityId;
+
+ //
+ // Enable Ehci Host Controller MMIO Space.
+ //
+ PciStatus = PciRead16 (PcdGet32(PcdUsbEhciPciAddress) + PCI_PRIMARY_STATUS_OFFSET);
+
+ if ((PciStatus & EFI_PCI_STATUS_CAPABILITY) == 0) {
+ //
+ // The Pci Device Doesn't Support Capability Pointer.
+ //
+ return RETURN_UNSUPPORTED;
+ }
+
+ //
+ // Get Pointer To Capability List
+ //
+ CapabilityPtr = PciRead8(PcdGet32(PcdUsbEhciPciAddress) + PCI_CAPBILITY_POINTER_OFFSET);
+
+ //
+ // Find Capability ID 0xA, Which Is For Debug Port
+ //
+ while (CapabilityPtr != 0) {
+ CapabilityId = PciRead8(PcdGet32(PcdUsbEhciPciAddress) + CapabilityPtr);
+ if (CapabilityId == PCI_CAPABILITY_ID_DEBUG_PORT) {
+ break;
+ }
+ CapabilityPtr = PciRead8(PcdGet32(PcdUsbEhciPciAddress) + CapabilityPtr + 1);
+ }
+
+ //
+ // No Debug Port Capability Found
+ //
+ if (CapabilityPtr == 0) {
+ return RETURN_UNSUPPORTED;
+ }
+
+ //
+ // Get The Base Address Of Debug Port Register In Debug Port Capability Register
+ //
+ *DebugPortOffset = (UINT16)(PciRead16(PcdGet32(PcdUsbEhciPciAddress) + CapabilityPtr + 2) & 0x1FFF);
+ *DebugPortBarNumbar = (UINT8)((PciRead16(PcdGet32(PcdUsbEhciPciAddress) + CapabilityPtr + 2) >> 13) - 1);
+
+ return RETURN_SUCCESS;
+}
+
+/**
+ Do a usb IN transaction by usb debug port.
+
+ @param DebugPortRegister Pointer to the base address of usb debug port register interface.
+ @param Buffer Pointer to the buffer receiving data.
+ @param Length Number of bytes of the received data.
+ @param Token The token PID for each USB transaction.
+ @param Addr The usb device address for usb transaction.
+ @param Ep The endpoint for usb transaction.
+ @param DataToggle The toggle bit used at usb transaction.
+
+ @retval RETURN_SUCCESS The IN transaction is executed successfully.
+ @retval RETURN_INVALID_PARAMETER The parameters passed in are invalid.
+ @retval RETURN_DEVICE_ERROR The IN transaction comes across error.
+
+**/
+RETURN_STATUS
+EFIAPI
+UsbDebugPortIn (
+ IN USB_DEBUG_PORT_REGISTER *DebugPortRegister,
+ IN OUT UINT8 *Buffer,
+ OUT UINT8 *Length,
+ IN UINT8 Token,
+ IN UINT8 Addr,
+ IN UINT8 Ep,
+ IN UINT8 DataToggle
+ )
+{
+ UINTN Index;
+
+ if (Length == NULL) {
+ return RETURN_INVALID_PARAMETER;
+ }
+ *Length = 0;
+
+ DebugPortRegister->TokenPid = Token;
+ if (DataToggle != 0) {
+ DebugPortRegister->SendPid = DATA1_PID;
+ } else {
+ DebugPortRegister->SendPid = DATA0_PID;
+ }
+
+ DebugPortRegister->UsbAddress = (UINT8)(Addr & 0x7F);
+ DebugPortRegister->UsbEndPoint = (UINT8)(Ep & 0xF);
+
+ //
+ // Clearing W/R bit to indicate it's a READ operation
+ //
+ MmioAnd32((UINTN)&DebugPortRegister->ControlStatus, (UINT32)~BIT4);
+
+ //
+ // Setting GO bit as well as clearing DONE bit
+ //
+ MmioOr32((UINTN)&DebugPortRegister->ControlStatus, (UINT32)BIT5);
+
+ //
+ // Wait for completing the request
+ //
+ while ((MmioRead32((UINTN)&DebugPortRegister->ControlStatus) & (UINT32)BIT16) == 0);
+
+ //
+ // Check if the request is executed successfully or not.
+ //
+ if ((MmioRead32((UINTN)&DebugPortRegister->ControlStatus)) & BIT6) {
+ return RETURN_DEVICE_ERROR;
+ }
+
+ //
+ // Make sure the received data are not beyond the allowable maximum length - 8 byte
+ //
+ if (((MmioRead32((UINTN)&DebugPortRegister->ControlStatus)) & 0xF) > USB_DEBUG_PORT_MAX_PACKET_SIZE) {
+ return RETURN_DEVICE_ERROR;
+ }
+
+ *Length = (UINT8)(MmioRead32((UINTN)&DebugPortRegister->ControlStatus) & 0xF);
+ for (Index = 0; Index < *Length; Index++) {
+ Buffer[Index] = DebugPortRegister->DataBuffer[Index];
+ }
+ return RETURN_SUCCESS;
+}
+
+/**
+ Do a usb SETUP/OUT transaction by usb debug port.
+
+ @param DebugPortRegister Pointer to the base address of usb debug port register interface.
+ @param Buffer Pointer to the buffer receiving data.
+ @param Length Number of bytes of the received data.
+ @param Token The token PID for each USB transaction.
+ @param Addr The usb device address for usb transaction.
+ @param Ep The endpoint for usb transaction.
+ @param DataToggle The toggle bit used at usb transaction.
+
+ @retval RETURN_SUCCESS The IN transaction is executed successfully.
+ @retval RETURN_INVALID_PARAMETER The parameters passed in are invalid.
+ @retval RETURN_DEVICE_ERROR The IN transaction comes across error.
+
+**/
+RETURN_STATUS
+EFIAPI
+UsbDebugPortOut (
+ IN USB_DEBUG_PORT_REGISTER *DebugPortRegister,
+ IN UINT8 *Buffer,
+ IN UINT8 Length,
+ IN UINT8 Token,
+ IN UINT8 Addr,
+ IN UINT8 Ep,
+ IN UINT8 DataToggle
+ )
+{
+ UINT8 Index;
+
+ if (Length > 8) {
+ return RETURN_INVALID_PARAMETER;
+ }
+
+ DebugPortRegister->TokenPid = Token;
+ if (DataToggle != 0) {
+ DebugPortRegister->SendPid = DATA1_PID;
+ } else {
+ DebugPortRegister->SendPid = DATA0_PID;
+ }
+ DebugPortRegister->UsbAddress = (UINT8)(Addr & 0x7F);
+ DebugPortRegister->UsbEndPoint = (UINT8)(Ep & 0xF);
+
+ //
+ // Fill in the data length and corresponding data.
+ //
+ MmioAnd32((UINTN)&DebugPortRegister->ControlStatus, (UINT32)~0xF);
+ MmioOr32((UINTN)&DebugPortRegister->ControlStatus, Length & 0xF);
+ for (Index = 0; Index < Length; Index++) {
+ DebugPortRegister->DataBuffer[Index] = Buffer[Index];
+ }
+
+ //
+ // Setting W/R bit to indicate it's a WRITE operation
+ //
+ MmioOr32((UINTN)&DebugPortRegister->ControlStatus, BIT4);
+ //
+ // Setting GO bit as well as clearing DONE bit
+ //
+ MmioOr32((UINTN)&DebugPortRegister->ControlStatus, BIT5);
+
+ //
+ // Wait for completing the request
+ //
+ while ((MmioRead32((UINTN)&DebugPortRegister->ControlStatus) & BIT16) == 0);
+
+ //
+ // Check if the request is executed successfully or not.
+ //
+ if ((MmioRead32((UINTN)&DebugPortRegister->ControlStatus)) & BIT6) {
+ return RETURN_DEVICE_ERROR;
+ }
+
+ //
+ // Make sure the sent data are not beyond the allowable maximum length - 8 byte
+ //
+ if (((MmioRead32((UINTN)&DebugPortRegister->ControlStatus)) & 0xF) > USB_DEBUG_PORT_MAX_PACKET_SIZE) {
+ return RETURN_DEVICE_ERROR;
+ }
+
+ return RETURN_SUCCESS;
+}
+
+/**
+ Do a usb control transfer by usb debug port.
+
+ @param DebugPortRegister Pointer to the base address of usb debug port register interface.
+ @param SetupPacket The token PID for each USB transaction.
+ @param Addr The usb device address for usb transaction.
+ @param Ep The endpoint for usb transaction.
+ @param Data Pointer to the buffer receiving data.
+ @param DataLength Number of bytes of the received data.
+
+ @retval RETURN_SUCCESS The IN transaction is executed successfully.
+ @retval RETURN_INVALID_PARAMETER The parameters passed in are invalid.
+ @retval RETURN_DEVICE_ERROR The IN transaction comes across error.
+
+**/
+RETURN_STATUS
+EFIAPI
+UsbDebugPortControlTransfer (
+ IN USB_DEBUG_PORT_REGISTER *DebugPortRegister,
+ IN USB_DEVICE_REQUEST *SetupPacket,
+ IN UINT8 Addr,
+ IN UINT8 Ep,
+ OUT UINT8 *Data,
+ IN OUT UINT8 *DataLength
+ )
+{
+ RETURN_STATUS Status;
+ UINT8 Temp;
+
+ //
+ // Setup Phase
+ //
+ Status = UsbDebugPortOut(DebugPortRegister, (UINT8 *)SetupPacket, (UINT8)sizeof(USB_DEVICE_REQUEST), SETUP_PID, Addr, Ep, 0);
+ if (RETURN_ERROR(Status)) {
+ return Status;
+ }
+
+ //
+ // Data Phase
+ //
+ if (SetupPacket->Length != 0) {
+ if ((SetupPacket->RequestType & BIT7) != 0) {
+ //
+ // Get Data From Device
+ //
+ Status = UsbDebugPortIn(DebugPortRegister, Data, DataLength, INPUT_PID, Addr, Ep, 1);
+ if (RETURN_ERROR(Status)) {
+ return Status;
+ }
+ } else {
+ //
+ // Send Data To Device
+ //
+ Status = UsbDebugPortOut(DebugPortRegister, Data, *DataLength, OUTPUT_PID, Addr, Ep, 1);
+ if (RETURN_ERROR(Status)) {
+ return Status;
+ }
+ }
+ }
+
+ //
+ // Status Phase
+ //
+ if ((SetupPacket->RequestType & BIT7) != 0) {
+ //
+ // For READ operation, Data Toggle in Status Phase Should be 1.
+ //
+ Status = UsbDebugPortOut(DebugPortRegister, NULL, 0, OUTPUT_PID, Addr, Ep, 1);
+ } else {
+ //
+ // For WRITE operation, Data Toggle in Status Phase Should be 1.
+ //
+ Status = UsbDebugPortIn(DebugPortRegister, NULL, &Temp, INPUT_PID, Addr, Ep, 1);
+ }
+
+ return Status;
+}
+
+/**
+ Check if it needs to re-initialize usb debug port hardware.
+
+ During different phases switch, such as SEC to PEI or PEI to DXE or DXE to SMM, we should check
+ whether the usb debug port hardware configuration is changed. Such case can be triggerred by
+ Pci bus resource allocation and so on.
+
+ @param Handle Debug port handle.
+
+ @retval TRUE The usb debug port hardware configuration is changed.
+ @retval FALSE The usb debug port hardware configuration is not changed.
+
+**/
+BOOLEAN
+EFIAPI
+NeedReinitializeHardware(
+ IN USB_DEBUG_PORT_HANDLE *Handle
+ )
+{
+ UINT16 PciCmd;
+ UINTN UsbDebugPortMemoryBase;
+ UINTN EhciMemoryBase;
+ BOOLEAN Status;
+ USB_DEBUG_PORT_REGISTER *UsbDebugPortRegister;
+
+ Status = FALSE;
+
+ EhciMemoryBase = 0xFFFFFC00 & PciRead32(PcdGet32(PcdUsbEhciPciAddress) + PCI_BASE_ADDRESSREG_OFFSET);
+ if (EhciMemoryBase != Handle->EhciMemoryBase) {
+ Handle->EhciMemoryBase = EhciMemoryBase;
+ Status = TRUE;
+ }
+
+ UsbDebugPortMemoryBase = 0xFFFFFC00 & PciRead32(PcdGet32(PcdUsbEhciPciAddress) + PCI_BASE_ADDRESSREG_OFFSET + Handle->DebugPortBarNumber * 4);
+ if (UsbDebugPortMemoryBase != Handle->UsbDebugPortMemoryBase) {
+ Handle->UsbDebugPortMemoryBase = UsbDebugPortMemoryBase;
+ Status = TRUE;
+ }
+
+ //
+ // Enable Ehci Memory Space Access
+ //
+ PciCmd = PciRead16 (PcdGet32(PcdUsbEhciPciAddress) + PCI_COMMAND_OFFSET);
+ if (((PciCmd & EFI_PCI_COMMAND_MEMORY_SPACE) == 0) || ((PciCmd & EFI_PCI_COMMAND_BUS_MASTER) == 0)) {
+ Status = TRUE;
+ }
+
+ //
+ // Check if the debug port is enabled and owned by myself.
+ //
+ UsbDebugPortRegister = (USB_DEBUG_PORT_REGISTER *)(Handle->UsbDebugPortMemoryBase + Handle->DebugPortOffset);
+ if ((MmioRead32((UINTN)&UsbDebugPortRegister->ControlStatus) &
+ (USB_DEBUG_PORT_OWNER | USB_DEBUG_PORT_ENABLE | USB_DEBUG_PORT_IN_USE)) == 0) {
+ Status = TRUE;
+ }
+ return Status;
+}
+
+/**
+ Initialize usb debug port hardware.
+
+ 1. reset ehci host controller.
+ 2. set right port to debug port.
+ 3. find a usb debug device is attached by getting debug device descriptor.
+ 4. set address for the usb debug device.
+ 5. configure the usb debug device to debug mode.
+
+ @param Handle Debug port handle.
+
+ @retval TRUE The usb debug port hardware configuration is changed.
+ @retval FALSE The usb debug port hardware configuration is not changed.
+
+**/
+RETURN_STATUS
+EFIAPI
+InitializeUsbDebugHardware (
+ IN USB_DEBUG_PORT_HANDLE *Handle
+)
+{
+ RETURN_STATUS Status;
+ USB_DEBUG_PORT_REGISTER *UsbDebugPortRegister;
+ USB_DEBUG_PORT_DESCRIPTOR UsbDebugPortDescriptor;
+ UINT16 PciCmd;
+ UINT32 *PortStatus;
+ UINT32 *UsbCmd;
+ UINT32 *UsbStatus;
+ UINT32 *UsbHCSParam;
+ UINT8 DebugPortNumber;
+ UINT8 Length;
+
+ UsbDebugPortRegister = (USB_DEBUG_PORT_REGISTER *)(Handle->UsbDebugPortMemoryBase + Handle->DebugPortOffset);
+ PciCmd = PciRead16 (PcdGet32(PcdUsbEhciPciAddress) + PCI_COMMAND_OFFSET);
+ UsbHCSParam = (UINT32 *)(Handle->EhciMemoryBase + 0x04);
+ UsbCmd = (UINT32 *)(Handle->EhciMemoryBase + 0x20);
+ UsbStatus = (UINT32 *)(Handle->EhciMemoryBase + 0x24);
+
+ //
+ // initialize the data toggle used by bulk in/out endpoint.
+ //
+ Handle->BulkInToggle = 0;
+ Handle->BulkOutToggle = 0;
+
+ //
+ // Enable Ehci Memory Space Access
+ //
+ if (((PciCmd & EFI_PCI_COMMAND_MEMORY_SPACE) == 0) || ((PciCmd & EFI_PCI_COMMAND_BUS_MASTER) == 0)) {
+ PciCmd |= EFI_PCI_COMMAND_MEMORY_SPACE | EFI_PCI_COMMAND_BUS_MASTER;
+ PciWrite16(PcdGet32(PcdUsbEhciPciAddress) + PCI_COMMAND_OFFSET, PciCmd);
+ }
+
+ //
+ // If the host controller is not halted, then halt it.
+ //
+ if ((MmioRead32((UINTN)UsbStatus) & BIT12) == 0) {
+ MmioAnd32((UINTN)UsbCmd, (UINT32)~BIT0);
+ while ((MmioRead32((UINTN)UsbStatus) & BIT12) == 0);
+ }
+ //
+ // reset the host controller.
+ //
+ MmioOr32((UINTN)UsbCmd, BIT1);
+ //
+ // ensure that the host controller is reset.
+ //
+ while (MmioRead32((UINTN)UsbCmd) & BIT1);
+
+ //
+ // Start the host controller if it's not running
+ //
+ if (MmioRead32((UINTN)UsbStatus) & BIT12) {
+ MmioOr32((UINTN)UsbCmd, BIT0);
+ // ensure that the host controller is started (HALTED bit must be cleared)
+ while (MmioRead32((UINTN)UsbStatus) & BIT12);
+ }
+
+ //
+ // First get the ownership of port 0.
+ //
+ MmioOr32((UINTN)&UsbDebugPortRegister->ControlStatus, USB_DEBUG_PORT_OWNER);
+
+ MicroSecondDelay (200000);
+
+ //
+ // Find out which port is used as debug port.
+ //
+ DebugPortNumber = (UINT8)((MmioRead32((UINTN)UsbHCSParam) & 0x00F00000) >> 20);
+ //
+ // Should find a non low-speed device is connected
+ //
+ PortStatus = (UINT32 *)(Handle->EhciMemoryBase + 0x64 + (DebugPortNumber - 1) * 4);
+ if (!(MmioRead32((UINTN)PortStatus) & BIT0) || ((MmioRead32((UINTN)PortStatus) & USB_PORT_LINE_STATUS_MASK) == USB_PORT_LINE_STATUS_LS)) {
+ return RETURN_NOT_FOUND;
+ }
+
+ //
+ // Reset the debug port
+ //
+ MmioOr32((UINTN)PortStatus, BIT8);
+ MicroSecondDelay (200000);
+ MmioAnd32((UINTN)PortStatus, (UINT32)~BIT8);
+ while (MmioRead32((UINTN)PortStatus) & BIT8);
+
+ //
+ // The port enabled bit should be set by HW.
+ //
+ if ((MmioRead32((UINTN)PortStatus) & BIT2) == 0) {
+ return RETURN_DEVICE_ERROR;
+ }
+
+ //
+ // Enable Usb Debug Port Capability
+ //
+ MmioOr32((UINTN)&UsbDebugPortRegister->ControlStatus, USB_DEBUG_PORT_ENABLE | USB_DEBUG_PORT_IN_USE);
+
+ //
+ // Start to communicate with Usb Debug Device to see if the attached device is usb debug device or not.
+ //
+ Length = (UINT8)sizeof (USB_DEBUG_PORT_DESCRIPTOR);
+
+ //
+ // It's not a dedicated usb debug device, should use address 0 to get debug descriptor.
+ //
+ Status = UsbDebugPortControlTransfer (UsbDebugPortRegister, &mGetDebugDescriptor, 0x0, 0x0, (UINT8*)&UsbDebugPortDescriptor, &Length);
+ if (RETURN_ERROR(Status)) {
+ //
+ // The device is not a usb debug device.
+ //
+ return Status;
+ }
+
+ //
+ // set usb debug device address as 0x7F.
+ //
+ Status = UsbDebugPortControlTransfer (UsbDebugPortRegister, &mSetDebugAddress, 0x0, 0x0, (UINT8*)&UsbDebugPortDescriptor, &Length);
+ if (RETURN_ERROR(Status)) {
+ //
+ // The device can not work well.
+ //
+ return Status;
+ }
+
+ //
+ // enable the usb debug feature.
+ //
+ Status = UsbDebugPortControlTransfer (UsbDebugPortRegister, &mSetDebugFeature, 0x7F, 0x0, NULL, NULL);
+
+ return Status;
+}
+
+/**
+ Read data from debug device and save the datas in buffer.
+
+ Reads NumberOfBytes data bytes from a debug device into the buffer
+ specified by Buffer. The number of bytes actually read is returned.
+ If the return value is less than NumberOfBytes, then the rest operation failed.
+ If NumberOfBytes is zero, then return 0.
+
+ @param Handle Debug port handle.
+ @param Buffer Pointer to the data buffer to store the data read from the debug device.
+ @param NumberOfBytes Number of bytes which will be read.
+ @param Timeout Timeout value for reading from debug device. It unit is Microsecond.
+
+ @retval 0 Read data failed, no data is to be read.
+ @retval >0 Actual number of bytes read from debug device.
+
+**/
+UINTN
+EFIAPI
+DebugPortReadBuffer (
+ IN DEBUG_PORT_HANDLE Handle,
+ IN UINT8 *Buffer,
+ IN UINTN NumberOfBytes,
+ IN UINTN Timeout
+ )
+{
+ USB_DEBUG_PORT_HANDLE *UsbDebugPortHandle;
+ USB_DEBUG_PORT_REGISTER *UsbDebugPortRegister;
+ RETURN_STATUS Status;
+ UINT8 Received;
+ UINTN Total;
+ UINTN Remaining;
+ UINT8 Index;
+ UINT8 Length;
+
+ if (NumberOfBytes == 0 || Buffer == NULL) {
+ return 0;
+ }
+
+ Received = 0;
+ Total = 0;
+ Remaining = 0;
+
+ //
+ // If Handle is NULL, it means memory is ready for use.
+ // Use global variable to store handle value.
+ //
+ if (Handle == NULL) {
+ UsbDebugPortHandle = &mUsbDebugPortHandle;
+ } else {
+ UsbDebugPortHandle = (USB_DEBUG_PORT_HANDLE *)Handle;
+ }
+
+ if (NeedReinitializeHardware(UsbDebugPortHandle)) {
+ Status = InitializeUsbDebugHardware (UsbDebugPortHandle);
+ if (RETURN_ERROR(Status)) {
+ return 0;
+ }
+ }
+
+ UsbDebugPortRegister = (USB_DEBUG_PORT_REGISTER *)(UsbDebugPortHandle->UsbDebugPortMemoryBase + UsbDebugPortHandle->DebugPortOffset);
+
+ //
+ // First read data from buffer, then read debug port hw to get received data.
+ //
+ if (UsbDebugPortHandle->DataCount > 0) {
+ if (NumberOfBytes <= UsbDebugPortHandle->DataCount) {
+ Total = NumberOfBytes;
+ } else {
+ Total = UsbDebugPortHandle->DataCount;
+ }
+
+ for (Index = 0; Index < Total; Index++) {
+ Buffer[Index] = UsbDebugPortHandle->Data[Index];
+ }
+
+ for (Index = 0; Index < UsbDebugPortHandle->DataCount - Total; Index++) {
+ if (Total + Index >= 8) {
+ return 0;
+ }
+ UsbDebugPortHandle->Data[Index] = UsbDebugPortHandle->Data[Total + Index];
+ }
+ UsbDebugPortHandle->DataCount = (UINT8)(UsbDebugPortHandle->DataCount - (UINT8)Total);
+ }
+
+ //
+ // If Timeout is equal to 0, then it means it should always wait until all datum required are received.
+ //
+ if (Timeout == 0) {
+ Timeout = 0xFFFFFFFF;
+ }
+
+ //
+ // Read remaining data by executing one or more usb debug transfer transactions at usb debug port hw.
+ //
+ while ((Total < NumberOfBytes) && (Timeout != 0)) {
+ Remaining = NumberOfBytes - Total;
+ if (Remaining >= USB_DEBUG_PORT_MAX_PACKET_SIZE) {
+ Status = UsbDebugPortIn(UsbDebugPortRegister, Buffer + Total, &Received, INPUT_PID, 0x7f, 0x82, UsbDebugPortHandle->BulkInToggle);
+
+ if (RETURN_ERROR(Status)) {
+ return Total;
+ }
+ } else {
+ Status = UsbDebugPortIn(UsbDebugPortRegister, &UsbDebugPortHandle->Data[0], &Received, INPUT_PID, 0x7f, 0x82, UsbDebugPortHandle->BulkInToggle);
+
+ if (RETURN_ERROR(Status)) {
+ return Total;
+ }
+
+ UsbDebugPortHandle->DataCount = Received;
+
+ if (Remaining <= Received) {
+ Length = (UINT8)Remaining;
+ } else {
+ Length = (UINT8)Received;
+ }
+
+ //
+ // Copy required data from the data buffer to user buffer.
+ //
+ for (Index = 0; Index < Length; Index++) {
+ (Buffer + Total)[Index] = UsbDebugPortHandle->Data[Index];
+ UsbDebugPortHandle->DataCount--;
+ }
+
+ //
+ // reorder the data buffer to make available data arranged from the beginning of the data buffer.
+ //
+ for (Index = 0; Index < Received - Length; Index++) {
+ if (Length + Index >= 8) {
+ return 0;
+ }
+ UsbDebugPortHandle->Data[Index] = UsbDebugPortHandle->Data[Length + Index];
+ }
+ //
+ // fixup the real received length in Buffer.
+ //
+ Received = Length;
+ }
+ UsbDebugPortHandle->BulkInToggle ^= 1;
+
+ Total += Received;
+ Timeout -= 100;
+ }
+
+ return Total;
+}
+
+/**
+ Write data from buffer to debug device.
+
+ Writes NumberOfBytes data bytes from Buffer to the debug device.
+ The number of bytes actually written to the debug device is returned.
+ If the return value is less than NumberOfBytes, then the write operation failed.
+ If NumberOfBytes is zero, then return 0.
+
+ @param Handle Debug port handle.
+ @param Buffer Pointer to the data buffer to be written.
+ @param NumberOfBytes Number of bytes to written to the debug device.
+
+ @retval 0 NumberOfBytes is 0.
+ @retval >0 The number of bytes written to the debug device.
+ If this value is less than NumberOfBytes, then the read operation failed.
+
+**/
+UINTN
+EFIAPI
+DebugPortWriteBuffer (
+ IN DEBUG_PORT_HANDLE Handle,
+ IN UINT8 *Buffer,
+ IN UINTN NumberOfBytes
+ )
+{
+ USB_DEBUG_PORT_HANDLE *UsbDebugPortHandle;
+ USB_DEBUG_PORT_REGISTER *UsbDebugPortRegister;
+ RETURN_STATUS Status;
+ UINT8 Sent;
+ UINTN Total;
+ UINT8 ReceivedPid;
+
+ if (NumberOfBytes == 0 || Buffer == NULL) {
+ return 0;
+ }
+
+ Sent = 0;
+ Total = 0;
+
+ //
+ // If Handle is NULL, it means memory is ready for use.
+ // Use global variable to store handle value.
+ //
+ if (Handle == NULL) {
+ UsbDebugPortHandle = &mUsbDebugPortHandle;
+ } else {
+ UsbDebugPortHandle = (USB_DEBUG_PORT_HANDLE *)Handle;
+ }
+
+ if (NeedReinitializeHardware(UsbDebugPortHandle)) {
+ Status = InitializeUsbDebugHardware (UsbDebugPortHandle);
+ if (RETURN_ERROR(Status)) {
+ return 0;
+ }
+ }
+
+ UsbDebugPortRegister = (USB_DEBUG_PORT_REGISTER *)(UsbDebugPortHandle->UsbDebugPortMemoryBase + UsbDebugPortHandle->DebugPortOffset);
+
+ while ((Total < NumberOfBytes)) {
+ if (NumberOfBytes - Total > USB_DEBUG_PORT_MAX_PACKET_SIZE) {
+ Sent = USB_DEBUG_PORT_MAX_PACKET_SIZE;
+ } else {
+ Sent = (UINT8)(NumberOfBytes - Total);
+ }
+
+ Status = UsbDebugPortOut(UsbDebugPortRegister, Buffer + Total, Sent, OUTPUT_PID, 0x7F, 0x01, UsbDebugPortHandle->BulkOutToggle);
+
+ if (RETURN_ERROR(Status)) {
+ return Total;
+ }
+
+ ReceivedPid = (MmioRead8((UINTN)&UsbDebugPortRegister->ReceivedPid));
+ //
+ // If received a NAK_PID on write transaction, it means the usb debug device is busy and can not handle this transaction.
+ // should send the packet again.
+ //
+ if (ReceivedPid == NAK_PID) {
+ Sent = 0;
+ } else {
+ UsbDebugPortHandle->BulkOutToggle ^= 1;
+ }
+ Total += Sent;
+ }
+ return Total;
+}
+
+/**
+ Polls a debug device to see if there is any data waiting to be read.
+
+ Polls a debug device to see if there is any data waiting to be read.
+ If there is data waiting to be read from the debug device, then TRUE is returned.
+ If there is no data waiting to be read from the debug device, then FALSE is returned.
+
+ @param Handle Debug port handle.
+
+ @retval TRUE Data is waiting to be read from the debug device.
+ @retval FALSE There is no data waiting to be read from the serial device.
+
+**/
+BOOLEAN
+EFIAPI
+DebugPortPollBuffer (
+ IN DEBUG_PORT_HANDLE Handle
+ )
+{
+ USB_DEBUG_PORT_HANDLE *UsbDebugPortHandle;
+ USB_DEBUG_PORT_REGISTER *UsbDebugPortRegister;
+ UINT8 Length;
+ UINT8 Index;
+ RETURN_STATUS Status;
+
+ //
+ // If Handle is NULL, it means memory is ready for use.
+ // Use global variable to store handle value.
+ //
+ if (Handle == NULL) {
+ UsbDebugPortHandle = &mUsbDebugPortHandle;
+ } else {
+ UsbDebugPortHandle = (USB_DEBUG_PORT_HANDLE *)Handle;
+ }
+
+ if (NeedReinitializeHardware(UsbDebugPortHandle)) {
+ Status = InitializeUsbDebugHardware(UsbDebugPortHandle);
+ if (RETURN_ERROR(Status)) {
+ return FALSE;
+ }
+ }
+
+ //
+ // If the data buffer is not empty, then return TRUE directly.
+ // else initialize a usb read transaction and read data to the data buffer.
+ //
+ if (UsbDebugPortHandle->DataCount != 0) {
+ return TRUE;
+ }
+
+ UsbDebugPortRegister = (USB_DEBUG_PORT_REGISTER *)(UsbDebugPortHandle->UsbDebugPortMemoryBase + UsbDebugPortHandle->DebugPortOffset);
+
+ UsbDebugPortRegister->TokenPid = INPUT_PID;
+ if (UsbDebugPortHandle->BulkInToggle == 0) {
+ UsbDebugPortRegister->SendPid = DATA0_PID;
+ } else {
+ UsbDebugPortRegister->SendPid = DATA1_PID;
+ }
+ UsbDebugPortRegister->UsbAddress = 0x7F;
+ UsbDebugPortRegister->UsbEndPoint = 0x82 & 0x0F;
+
+ //
+ // Clearing W/R bit to indicate it's a READ operation
+ //
+ MmioAnd32((UINTN)&UsbDebugPortRegister->ControlStatus, (UINT32)~BIT4);
+ //
+ // Setting GO bit as well as clearing DONE bit
+ //
+ MmioOr32((UINTN)&UsbDebugPortRegister->ControlStatus, (UINT32)BIT5);
+
+ //
+ // Wait for completing the request
+ //
+ while ((MmioRead32((UINTN)&UsbDebugPortRegister->ControlStatus) & (UINT32)BIT16) == 0);
+
+ if ((MmioRead32((UINTN)&UsbDebugPortRegister->ControlStatus)) & BIT6) {
+ return FALSE;
+ }
+
+ Length = (UINT8)(MmioRead32((UINTN)&UsbDebugPortRegister->ControlStatus) & 0xF);
+
+ if (Length > 8) {
+ return FALSE;
+ }
+
+ UsbDebugPortHandle->BulkInToggle ^= 1;
+
+ if (Length == 0) {
+ return FALSE;
+ }
+
+ for (Index = 0; Index < Length; Index++) {
+ UsbDebugPortHandle->Data[Index] = UsbDebugPortRegister->DataBuffer[Index];
+ }
+ UsbDebugPortHandle->DataCount = Length;
+
+ return TRUE;
+}
+
+/**
+ Initialize the debug port.
+
+ If Function is not NULL, Debug Communication Libary will call this function
+ by passing in the Context to be the first parameter. If needed, Debug Communication
+ Library will create one debug port handle to be the second argument passing in
+ calling the Function, otherwise it will pass NULL to be the second argument of
+ Function.
+
+ If Function is NULL, and Context is not NULL, the Debug Communication Library could
+ a) Return the same handle as passed in (as Context parameter).
+ b) Ignore the input Context parameter and create new hanlde to be returned.
+
+ If parameter Function is NULL and Context is NULL, Debug Communication Library could
+ created a new handle if needed and return it, otherwise it will return NULL.
+
+ @param[in] Context Context needed by callback function; it was optional.
+ @param[in] Function Continue function called by Debug Communication library;
+ it was optional.
+
+ @return The debug port handle created by Debug Communication Library if Function
+ is not NULL.
+
+**/
+DEBUG_PORT_HANDLE
+EFIAPI
+DebugPortInitialize (
+ IN VOID *Context,
+ IN DEBUG_PORT_CONTINUE Function
+ )
+{
+ RETURN_STATUS Status;
+ USB_DEBUG_PORT_HANDLE Handle;
+
+ if (Function == NULL && Context != NULL) {
+ return (DEBUG_PORT_HANDLE *) Context;
+ }
+
+ ZeroMem(&Handle, sizeof (USB_DEBUG_PORT_HANDLE));
+
+ Status = CalculateUsbDebugPortBar(&Handle.DebugPortOffset, &Handle.DebugPortBarNumber);
+ if (RETURN_ERROR (Status)) {
+ return NULL;
+ }
+
+ Handle.EhciMemoryBase = 0xFFFFFC00 & PciRead32(PcdGet32(PcdUsbEhciPciAddress) + PCI_BASE_ADDRESSREG_OFFSET);
+
+ if (Handle.EhciMemoryBase == 0) {
+ //
+ // Usb Debug Port MMIO Space Is Not Enabled. Assumption here that DebugPortBase is zero
+ //
+ PciWrite32(PcdGet32(PcdUsbEhciPciAddress) + PCI_BASE_ADDRESSREG_OFFSET, PcdGet32(PcdUsbEhciMemorySpaceBase));
+ Handle.EhciMemoryBase = 0xFFFFFC00 & PciRead32(PcdGet32(PcdUsbEhciPciAddress) + PCI_BASE_ADDRESSREG_OFFSET);
+ }
+
+ Handle.UsbDebugPortMemoryBase = 0xFFFFFC00 & PciRead32(PcdGet32(PcdUsbEhciPciAddress) + PCI_BASE_ADDRESSREG_OFFSET + Handle.DebugPortBarNumber * 4);
+
+ if (Handle.UsbDebugPortMemoryBase == 0) {
+ //
+ // Usb Debug Port MMIO Space Is Not Enabled. Assumption here that DebugPortBase is zero
+ //
+ PciWrite32(PcdGet32(PcdUsbEhciPciAddress) + PCI_BASE_ADDRESSREG_OFFSET + Handle.DebugPortBarNumber * 4, PcdGet32(PcdUsbDebugPortMemorySpaceBase));
+ Handle.UsbDebugPortMemoryBase = 0xFFFFFC00 & PciRead32(PcdGet32(PcdUsbEhciPciAddress) + PCI_BASE_ADDRESSREG_OFFSET + Handle.DebugPortBarNumber * 4);
+ }
+
+ Status = InitializeUsbDebugHardware (&Handle);
+ if (RETURN_ERROR(Status)) {
+ return NULL;
+ }
+
+ if (Function != NULL) {
+ Function (Context, &Handle);
+ } else {
+ CopyMem(&mUsbDebugPortHandle, &Handle, sizeof (USB_DEBUG_PORT_HANDLE));
+ }
+
+ return (DEBUG_PORT_HANDLE)(UINTN)&mUsbDebugPortHandle;
+}
+
diff --git a/SourceLevelDebugPkg/Library/DebugCommunicationLibUsb/DebugCommunicationLibUsb.inf b/SourceLevelDebugPkg/Library/DebugCommunicationLibUsb/DebugCommunicationLibUsb.inf
new file mode 100644
index 000000000..bce5659fe
--- /dev/null
+++ b/SourceLevelDebugPkg/Library/DebugCommunicationLibUsb/DebugCommunicationLibUsb.inf
@@ -0,0 +1,53 @@
+## @file
+# Debug Communication Library instance based on usb debug port.
+#
+# Copyright (c) 2010, Intel Corporation. All rights reserved.<BR>
+#
+# This program and the accompanying materials
+# are licensed and made available under the terms and conditions of the BSD License
+# which accompanies this distribution. The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php.
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = DebugCommunicationLibUsb
+ FILE_GUID = 87438836-AD8D-4e3e-9249-895120A67240
+ MODULE_TYPE = BASE
+ VERSION_STRING = 0.7
+ LIBRARY_CLASS = DebugCommunicationLib
+
+#
+# VALID_ARCHITECTURES = IA32 X64
+#
+
+[Sources.common]
+ DebugCommunicationLibUsb.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ SourceLevelDebugPkg/SourceLevelDebugPkg.dec
+
+[Pcd]
+ ## The memory BAR of usb debug port, it may be different with the memory bar of ehci host controller.
+ ## Note that the memory BAR address is only used before Pci bus resource allocation.
+ gEfiSourceLevelDebugPkgTokenSpaceGuid.PcdUsbDebugPortMemorySpaceBase
+
+ ## The memory BAR of ehci host controller, in which usb debug feature is enabled.
+ ## Note that the memory BAR address is only used before Pci bus resource allocation.
+ gEfiSourceLevelDebugPkgTokenSpaceGuid.PcdUsbEhciMemorySpaceBase
+
+ ## The pci address of ehci host controller, in which usb debug feature is enabled.
+ ## The format of pci address please refer to SourceLevelDebugPkg.dec
+ gEfiSourceLevelDebugPkgTokenSpaceGuid.PcdUsbEhciPciAddress
+
+[LibraryClasses]
+ TimerLib
+ IoLib
+ PciLib
+ PcdLib
+
diff --git a/SourceLevelDebugPkg/Library/PeCoffExtraActionLibDebug/PeCoffExtraActionLib.c b/SourceLevelDebugPkg/Library/PeCoffExtraActionLibDebug/PeCoffExtraActionLib.c
new file mode 100644
index 000000000..0fbc2b81d
--- /dev/null
+++ b/SourceLevelDebugPkg/Library/PeCoffExtraActionLibDebug/PeCoffExtraActionLib.c
@@ -0,0 +1,269 @@
+/** @file
+ PE/Coff Extra Action library instances.
+
+ Copyright (c) 2010, Intel Corporation. All rights reserved.<BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php.
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include <Base.h>
+#include <Library/PeCoffExtraActionLib.h>
+#include <Library/DebugLib.h>
+#include <Library/BaseLib.h>
+#include <Library/IoLib.h>
+#include <Library/PcdLib.h>
+
+#include <ImageDebugSupport.h>
+
+#define DEBUG_LOAD_IMAGE_METHOD_IO_HW_BREAKPOINT 1
+#define DEBUG_LOAD_IMAGE_METHOD_SOFT_INT3 2
+
+/**
+ Check if the hardware breakpoint in Drx is enabled by checking the Lx and Gx bit in Dr7.
+
+ It assumes that DebugAgent will set both Lx and Gx bit when setting up the hardware breakpoint.
+
+
+ @param RegisterIndex Index of Dr register. The value range is from 0 to 3.
+ @param Dr7 Value of Dr7 register.
+
+ @return TRUE The hardware breakpoint specified in the Drx is enabled.
+ @return FALSE The hardware breakpoint specified in the Drx is disabled.
+
+**/
+BOOLEAN
+IsDrxEnabled (
+ IN UINT8 RegisterIndex,
+ IN UINTN Dr7
+ )
+{
+ return (BOOLEAN) (((Dr7 >> (RegisterIndex * 2)) & (BIT0 | BIT1)) == (BIT0 | BIT1));
+}
+
+/**
+ Performs additional actions after a PE/COFF image has been loaded and relocated.
+
+ If ImageContext is NULL, then ASSERT().
+
+ @param ImageContext Pointer to the image context structure that describes the
+ PE/COFF image that has already been loaded and relocated.
+
+**/
+VOID
+EFIAPI
+PeCoffLoaderRelocateImageExtraAction (
+ IN OUT PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext
+ )
+{
+ BOOLEAN InterruptState;
+ UINTN Dr0;
+ UINTN Dr1;
+ UINTN Dr2;
+ UINTN Dr3;
+ UINTN Dr7;
+ UINTN Cr4;
+ UINTN NewDr7;
+ UINT8 LoadImageMethod;
+ UINT8 DebugAgentStatus;
+
+ ASSERT (ImageContext != NULL);
+
+ if (ImageContext->PdbPointer != NULL) {
+ DEBUG((EFI_D_ERROR, " PDB = %a\n", ImageContext->PdbPointer));
+ }
+
+ //
+ // Disable interrupts and save the current interrupt state
+ //
+ InterruptState = SaveAndDisableInterrupts ();
+
+ //
+ // Save Debug Register State
+ //
+ Dr0 = AsmReadDr0 ();
+ Dr1 = AsmReadDr1 ();
+ Dr2 = AsmReadDr2 ();
+ Dr3 = AsmReadDr3 ();
+ Dr7 = AsmReadDr7 ();
+ Cr4 = AsmReadCr4 ();
+
+ //
+ // DR0 = IMAGE_LOAD_SIGNATURE
+ // DR1 = The address of the Null-terminated ASCII string for the PE/COFF image's PDB file name
+ // DR2 = The pointer to the ImageContext structure
+ // DR3 = IO_PORT_BREAKPOINT_ADDRESS
+ // DR7 = Disables all HW breakpoints except for DR3 I/O port access of length 1 byte
+ // CR4 = Make sure DE(BIT3) is set
+ //
+ AsmWriteDr7 (0);
+ AsmWriteDr0 (IMAGE_LOAD_SIGNATURE);
+ AsmWriteDr1 ((UINTN)ImageContext->PdbPointer);
+ AsmWriteDr2 ((UINTN)ImageContext);
+ AsmWriteDr3 (IO_PORT_BREAKPOINT_ADDRESS);
+
+ LoadImageMethod = PcdGet8 (PcdDebugLoadImageMethod);
+ if (LoadImageMethod == DEBUG_LOAD_IMAGE_METHOD_IO_HW_BREAKPOINT) {
+ AsmWriteDr7 (0x20000480);
+ AsmWriteCr4 (Cr4 | BIT3);
+ //
+ // Do an IN from IO_PORT_BREAKPOINT_ADDRESS to generate a HW breakpoint until the port
+ // returns a read value other than DEBUG_AGENT_IMAGE_WAIT
+ //
+ do {
+ DebugAgentStatus = IoRead8 (IO_PORT_BREAKPOINT_ADDRESS);
+ } while (DebugAgentStatus == DEBUG_AGENT_IMAGE_WAIT);
+
+ } else if (LoadImageMethod == DEBUG_LOAD_IMAGE_METHOD_SOFT_INT3) {
+ //
+ // Generate a software break point.
+ //
+ CpuBreakpoint ();
+ }
+
+ //
+ // Restore Debug Register State only when Host didn't change it inside exception handler.
+ // E.g.: User halts the target and sets the HW breakpoint while target is
+ // in the above exception handler
+ //
+ NewDr7 = AsmReadDr7 ();
+ if (!IsDrxEnabled (0, NewDr7)) {
+ AsmWriteDr0 (Dr0);
+ }
+ if (!IsDrxEnabled (1, NewDr7)) {
+ AsmWriteDr1 (Dr1);
+ }
+ if (!IsDrxEnabled (2, NewDr7)) {
+ AsmWriteDr2 (Dr2);
+ }
+ if (!IsDrxEnabled (3, NewDr7)) {
+ AsmWriteDr3 (Dr3);
+ }
+ if (AsmReadCr4 () == (Cr4 | BIT3)) {
+ AsmWriteCr4 (Cr4);
+ }
+ if (NewDr7 == 0x20000480) {
+ AsmWriteDr7 (Dr7);
+ }
+ //
+ // Restore the interrupt state
+ //
+ SetInterruptState (InterruptState);
+}
+
+/**
+ Performs additional actions just before a PE/COFF image is unloaded. Any resources
+ that were allocated by PeCoffLoaderRelocateImageExtraAction() must be freed.
+
+ If ImageContext is NULL, then ASSERT().
+
+ @param ImageContext Pointer to the image context structure that describes the
+ PE/COFF image that is being unloaded.
+
+**/
+VOID
+EFIAPI
+PeCoffLoaderUnloadImageExtraAction (
+ IN OUT PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext
+ )
+{
+ BOOLEAN InterruptState;
+ UINTN Dr0;
+ UINTN Dr1;
+ UINTN Dr2;
+ UINTN Dr3;
+ UINTN Dr7;
+ UINTN Cr4;
+ UINTN NewDr7;
+ UINT8 LoadImageMethod;
+ UINT8 DebugAgentStatus;
+
+ ASSERT (ImageContext != NULL);
+
+ if (ImageContext->PdbPointer != NULL) {
+ DEBUG((EFI_D_ERROR, " PDB = %a\n", ImageContext->PdbPointer));
+ }
+
+ //
+ // Disable interrupts and save the current interrupt state
+ //
+ InterruptState = SaveAndDisableInterrupts ();
+
+ //
+ // Save Debug Register State
+ //
+ Dr0 = AsmReadDr0 ();
+ Dr1 = AsmReadDr1 ();
+ Dr2 = AsmReadDr2 ();
+ Dr3 = AsmReadDr3 ();
+ Dr7 = AsmReadDr7 ();
+ Cr4 = AsmReadCr4 ();
+
+ //
+ // DR0 = IMAGE_UNLOAD_SIGNATURE
+ // DR1 = The address of the Null-terminated ASCII string for the PE/COFF image's PDB file name
+ // DR2 = The pointer to the ImageContext structure
+ // DR3 = IO_PORT_BREAKPOINT_ADDRESS
+ // DR7 = Disables all HW breakpoints except for DR3 I/O port access of length 1 byte
+ // CR4 = Make sure DE(BIT3) is set
+ //
+ AsmWriteDr7 (0);
+ AsmWriteDr0 (IMAGE_UNLOAD_SIGNATURE);
+ AsmWriteDr1 ((UINTN)ImageContext->PdbPointer);
+ AsmWriteDr2 ((UINTN)ImageContext);
+ AsmWriteDr3 (IO_PORT_BREAKPOINT_ADDRESS);
+
+ LoadImageMethod = PcdGet8 (PcdDebugLoadImageMethod);
+ if (LoadImageMethod == DEBUG_LOAD_IMAGE_METHOD_IO_HW_BREAKPOINT) {
+ AsmWriteDr7 (0x20000480);
+ AsmWriteCr4 (Cr4 | BIT3);
+ //
+ // Do an IN from IO_PORT_BREAKPOINT_ADDRESS to generate a HW breakpoint until the port
+ // returns a read value other than DEBUG_AGENT_IMAGE_WAIT
+ //
+ do {
+ DebugAgentStatus = IoRead8 (IO_PORT_BREAKPOINT_ADDRESS);
+ } while (DebugAgentStatus == DEBUG_AGENT_IMAGE_WAIT);
+
+ } else if (LoadImageMethod == DEBUG_LOAD_IMAGE_METHOD_SOFT_INT3) {
+ //
+ // Generate a software break point.
+ //
+ CpuBreakpoint ();
+ }
+
+ //
+ // Restore Debug Register State only when Host didn't change it inside exception handler.
+ // E.g.: User halts the target and sets the HW breakpoint while target is
+ // in the above exception handler
+ //
+ NewDr7 = AsmReadDr7 ();
+ if (!IsDrxEnabled (0, NewDr7)) {
+ AsmWriteDr0 (Dr0);
+ }
+ if (!IsDrxEnabled (1, NewDr7)) {
+ AsmWriteDr1 (Dr1);
+ }
+ if (!IsDrxEnabled (2, NewDr7)) {
+ AsmWriteDr2 (Dr2);
+ }
+ if (!IsDrxEnabled (3, NewDr7)) {
+ AsmWriteDr3 (Dr3);
+ }
+ if (AsmReadCr4 () == (Cr4 | BIT3)) {
+ AsmWriteCr4 (Cr4);
+ }
+ if (NewDr7 == 0x20000480) {
+ AsmWriteDr7 (Dr7);
+ }
+
+ //
+ // Restore the interrupt state
+ //
+ SetInterruptState (InterruptState);
+}
diff --git a/SourceLevelDebugPkg/Library/PeCoffExtraActionLibDebug/PeCoffExtraActionLibDebug.inf b/SourceLevelDebugPkg/Library/PeCoffExtraActionLibDebug/PeCoffExtraActionLibDebug.inf
new file mode 100644
index 000000000..e3712afac
--- /dev/null
+++ b/SourceLevelDebugPkg/Library/PeCoffExtraActionLibDebug/PeCoffExtraActionLibDebug.inf
@@ -0,0 +1,45 @@
+## @file
+# PeCoffExtraAction Library to support source level debug.
+#
+# Copyright (c) 2010, Intel Corporation. All rights reserved.<BR>
+#
+# This program and the accompanying materials
+# are licensed and made available under the terms and conditions of the BSD License
+# which accompanies this distribution. The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php.
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = PeCoffExtraActionLib
+ FILE_GUID = 8F01CBD5-E069-44d7-90C9-35F0318603AD
+ MODULE_TYPE = BASE
+ VERSION_STRING = 0.7
+ LIBRARY_CLASS = PeCoffExtraActionLib
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64
+#
+
+[Sources.common]
+ PeCoffExtraActionLib.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ SourceLevelDebugPkg/SourceLevelDebugPkg.dec
+
+[LibraryClasses]
+ BaseLib
+ DebugLib
+ IoLib
+ PcdLib
+
+[Pcd]
+ gEfiSourceLevelDebugPkgTokenSpaceGuid.PcdDebugLoadImageMethod
+