summaryrefslogtreecommitdiffstats
path: root/SourceLevelDebugPkg/Library/DebugAgent/DebugAgentCommon
diff options
context:
space:
mode:
authorvanjeff <vanjeff@6f19259b-4bc3-4df7-8a09-765794883524>2013-01-25 02:36:18 +0000
committervanjeff <vanjeff@6f19259b-4bc3-4df7-8a09-765794883524>2013-01-25 02:36:18 +0000
commitb422b62c01a490e7892864c04280d430a2566e3f (patch)
tree1256106c1730868c3040ba879e430cb2550e04be /SourceLevelDebugPkg/Library/DebugAgent/DebugAgentCommon
parentb7d269eae175a25d9d6df8e09feb55a3d23eeab0 (diff)
downloadedk2-b422b62c01a490e7892864c04280d430a2566e3f.tar.gz
edk2-b422b62c01a490e7892864c04280d430a2566e3f.tar.bz2
edk2-b422b62c01a490e7892864c04280d430a2566e3f.zip
This revision can only work with Intel(c) UDK Debugger Tool version 1.3 or greater. Detailed change log is as below:
1. Add DebugAgentPei driver to initialize Debug Agent in PEI phase. Add DebugAgentDxe driver to initialize Debug Agent in DXE phase. DebugAgentDxe driver could be loaded and unloaded in shell. 2. Update the SourceLevelDebugPkg so that the debug agent can be initialized in any phase: SEC, PEI or DXE. 3. Add an enhanced retry algorithm that provides a robust connection when data loss happens in the debug channel. 4. Clear DR7 register in exception handler. 5. Set the default serial port parameter to 0 instead of PCDs. 6. Build pointer of Mailbox in HOB instead of Mailbox itself, since HOB may be moved at DXE entry point function. 7. Raise TPL to prevent recursion from EFI timer interrupts in SerialIo.c. 8. Add one spin lock for accessing Mailbox when MP debugging supported. 9. Use more non-NULL library instances in SourceLevelDebugPkg DSC file, thus DebugAgentDxe.efi built from SourceLevelDebugPkg could work in shell. 10.Separate all operations about IDT table entry from SecDebugAgentLib.c into DebugAgent\DebugAgentCommon's arch sub-directory. 11.Enhance Debug Agent to avoid breaking by hardware SMI during DXE debugging phase. 12.Add supporting on mode switch code debugging. 13.Remove reset Host Controller operation in DebugCommunicationLibUsb.c to avoid impacting EDKII usb stack. 14.Fix debug timer interrupt missing issue after back from legacy code. Signed-off-by: Jeff Fan <jeff.fan@intel.com> Signed-off-by: Ruiyu Ni <ruiyu.ni@intel.com> Signed-off-by: Feng Tian <feng.tian@intel.com> Reviewed-by: Jeff Fan <jeff.fan@intel.com> Reviewed-by: Ruiyu Ni <ruiyu.ni@intel.com> Reviewed-by: Feng Tian <feng.tian@intel.com> git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@14083 6f19259b-4bc3-4df7-8a09-765794883524
Diffstat (limited to 'SourceLevelDebugPkg/Library/DebugAgent/DebugAgentCommon')
-rw-r--r--SourceLevelDebugPkg/Library/DebugAgent/DebugAgentCommon/DebugAgent.c999
-rw-r--r--SourceLevelDebugPkg/Library/DebugAgent/DebugAgentCommon/DebugAgent.h287
-rw-r--r--SourceLevelDebugPkg/Library/DebugAgent/DebugAgentCommon/DebugMp.c97
-rw-r--r--SourceLevelDebugPkg/Library/DebugAgent/DebugAgentCommon/DebugMp.h37
-rw-r--r--SourceLevelDebugPkg/Library/DebugAgent/DebugAgentCommon/DebugTimer.c27
-rw-r--r--SourceLevelDebugPkg/Library/DebugAgent/DebugAgentCommon/Ia32/ArchDebugSupport.c56
-rw-r--r--SourceLevelDebugPkg/Library/DebugAgent/DebugAgentCommon/Ia32/AsmFuncs.S5
-rw-r--r--SourceLevelDebugPkg/Library/DebugAgent/DebugAgentCommon/Ia32/AsmFuncs.asm5
-rw-r--r--SourceLevelDebugPkg/Library/DebugAgent/DebugAgentCommon/X64/ArchDebugSupport.c54
-rw-r--r--SourceLevelDebugPkg/Library/DebugAgent/DebugAgentCommon/X64/AsmFuncs.S5
-rw-r--r--SourceLevelDebugPkg/Library/DebugAgent/DebugAgentCommon/X64/AsmFuncs.asm5
11 files changed, 1103 insertions, 474 deletions
diff --git a/SourceLevelDebugPkg/Library/DebugAgent/DebugAgentCommon/DebugAgent.c b/SourceLevelDebugPkg/Library/DebugAgent/DebugAgentCommon/DebugAgent.c
index 04dae34194..f4039f4995 100644
--- a/SourceLevelDebugPkg/Library/DebugAgent/DebugAgentCommon/DebugAgent.c
+++ b/SourceLevelDebugPkg/Library/DebugAgent/DebugAgentCommon/DebugAgent.c
@@ -4,7 +4,7 @@
read/write debug packet to communication with HOST based on transfer
protocol.
- Copyright (c) 2010 - 2012, Intel Corporation. All rights reserved.<BR>
+ Copyright (c) 2010 - 2013, 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
@@ -18,12 +18,305 @@
#include "DebugAgent.h"
#include "Ia32/DebugException.h"
-#define INIT_BREAK_ACK_TIMEOUT (200 * 1000)
+CHAR8 mErrorMsgVersionAlert[] = "\rThe SourceLevelDebugPkg you are using requires a newer version of the Intel(R) UDK Debugger Tool.\r\n";
+CHAR8 mErrorMsgSendInitPacket[] = "\rSend INIT break packet and try to connect the HOST (Intel(R) UDK Debugger Tool v1.3) ...\r\n";
+CHAR8 mErrorMsgConnectOK[] = "HOST connection is successful!\r\n";
+CHAR8 mErrorMsgConnectFail[] = "HOST connection is failed!\r\n";
+CHAR8 mWarningMsgIngoreBreakpoint[] = "Ignore break point in SMM for SMI issued during DXE debugging!\r\n";
-CHAR8 mErrorMsgVersionAlert[] = "\rThe SourceLevelDebugPkg you are using requires a newer version of the Intel(R) UDK Debugger Tool.\r\n";
-CHAR8 mErrorMsgSendInitPacket[] = "\rSend INIT break packet to HOST ...\r\n";
-CHAR8 mErrorMsgConnectOK[] = "HOST connection is successful!\r\n";
-CHAR8 mErrorMsgConnectFail[] = "HOST connection is failed!\r\n";
+/**
+ Calculate CRC16 for target data.
+
+ @param[in] Data The target data.
+ @param[in] DataSize The target data size.
+ @param[in] Crc Initial CRC.
+
+ @return UINT16 The CRC16 value.
+
+**/
+UINT16
+CalculateCrc16 (
+ IN UINT8 *Data,
+ IN UINTN DataSize,
+ IN UINT16 Crc
+ )
+{
+ UINTN Index;
+ UINTN BitIndex;
+
+ for (Index = 0; Index < DataSize; Index++) {
+ Crc ^= Data[Index];
+ for (BitIndex = 0; BitIndex < 8; BitIndex++) {
+ if ((Crc & 0x8000) != 0) {
+ Crc <<= 1;
+ Crc ^= 0x1021;
+ } else {
+ Crc <<= 1;
+ }
+ }
+ }
+ return Crc;
+}
+
+
+/**
+ Read IDT entry to check if IDT entries are setup by Debug Agent.
+
+ @retval TRUE IDT entries were setup by Debug Agent.
+ @retval FALSE IDT entries were not setup by Debug Agent.
+
+**/
+BOOLEAN
+IsDebugAgentInitialzed (
+ VOID
+ )
+{
+ UINTN InterruptHandler;
+
+ InterruptHandler = (UINTN) GetExceptionHandlerInIdtEntry (0);
+ if (InterruptHandler >= 4 && *(UINT32 *)(InterruptHandler - 4) == AGENT_HANDLER_SIGNATURE) {
+ return TRUE;
+ } else {
+ return FALSE;
+ }
+}
+
+/**
+ Find and report module image info to HOST.
+
+ @param[in] AlignSize Image aligned size.
+
+**/
+VOID
+FindAndReportModuleImageInfo (
+ IN UINTN AlignSize
+ )
+{
+ UINTN Pe32Data;
+ EFI_IMAGE_DOS_HEADER *DosHdr;
+ EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION Hdr;
+ PE_COFF_LOADER_IMAGE_CONTEXT ImageContext;
+
+ //
+ // Find Image Base
+ //
+ Pe32Data = ((UINTN)mErrorMsgVersionAlert) & ~(AlignSize - 1);
+ while (Pe32Data != 0) {
+ DosHdr = (EFI_IMAGE_DOS_HEADER *) Pe32Data;
+ if (DosHdr->e_magic == EFI_IMAGE_DOS_SIGNATURE) {
+ //
+ // DOS image header is present, so read the PE header after the DOS image header.
+ // Check if address overflow firstly.
+ //
+ if ((MAX_ADDRESS - (UINTN)DosHdr->e_lfanew) > Pe32Data) {
+ Hdr.Pe32 = (EFI_IMAGE_NT_HEADERS32 *)(Pe32Data + (UINTN)(DosHdr->e_lfanew));
+ if (Hdr.Pe32->Signature == EFI_IMAGE_NT_SIGNATURE) {
+ //
+ // It's PE image.
+ //
+ break;
+ }
+ }
+ } else {
+ //
+ // DOS image header is not present, TE header is at the image base.
+ //
+ Hdr.Pe32 = (EFI_IMAGE_NT_HEADERS32 *)Pe32Data;
+ if ((Hdr.Te->Signature == EFI_TE_IMAGE_HEADER_SIGNATURE) &&
+ ((Hdr.Te->Machine == IMAGE_FILE_MACHINE_I386) || Hdr.Te->Machine == IMAGE_FILE_MACHINE_X64)) {
+ //
+ // It's TE image, it TE header and Machine type match
+ //
+ break;
+ }
+ }
+
+ //
+ // Not found the image base, check the previous aligned address
+ //
+ Pe32Data -= AlignSize;
+ }
+
+ ImageContext.ImageAddress = Pe32Data;
+ ImageContext.PdbPointer = PeCoffLoaderGetPdbPointer ((VOID*) (UINTN) ImageContext.ImageAddress);
+ PeCoffLoaderRelocateImageExtraAction (&ImageContext);
+}
+
+/**
+ Trigger one software interrupt to debug agent to handle it.
+
+ @param[in] Signature Software interrupt signature.
+
+**/
+VOID
+TriggerSoftInterrupt (
+ IN 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);
+
+}
+
+/**
+ Caculate Mailbox checksum and update the checksum field.
+
+ @param[in] Mailbox Debug Agent Mailbox pointer.
+
+**/
+VOID
+UpdateMailboxChecksum (
+ IN DEBUG_AGENT_MAILBOX *Mailbox
+ )
+{
+ Mailbox->CheckSum = CalculateCheckSum8 ((UINT8 *)Mailbox, sizeof (DEBUG_AGENT_MAILBOX) - 2);
+}
+
+/**
+ Verify Mailbox checksum.
+
+ If checksum error, print debug message and run init dead loop.
+
+ @param[in] Mailbox Debug Agent Mailbox pointer.
+
+**/
+VOID
+VerifyMailboxChecksum (
+ IN DEBUG_AGENT_MAILBOX *Mailbox
+ )
+{
+ UINT8 CheckSum;
+
+ CheckSum = CalculateCheckSum8 ((UINT8 *) Mailbox, sizeof (DEBUG_AGENT_MAILBOX) - 2);
+ //
+ // The checksum updating process may be disturbed by hardware SMI, we need to check CheckSum field
+ // and ToBeCheckSum field to validate the mail box.
+ //
+ if (CheckSum != Mailbox->CheckSum && CheckSum != Mailbox->ToBeCheckSum) {
+ DEBUG ((EFI_D_ERROR, "DebugAgent: Mailbox checksum error, stack or heap crashed!\n"));
+ DEBUG ((EFI_D_ERROR, "DebugAgent: CheckSum = %x, Mailbox->CheckSum = %x, Mailbox->ToBeCheckSum = %x\n", CheckSum, Mailbox->CheckSum, Mailbox->ToBeCheckSum));
+ CpuDeadLoop ();
+ }
+}
+
+/**
+ Update Mailbox content by index.
+
+ @param[in] Mailbox Debug Agent Mailbox pointer.
+ @param[in] Index Mailbox content index.
+ @param[in] Value Value to be set into Mailbox.
+
+**/
+VOID
+UpdateMailboxContent (
+ IN DEBUG_AGENT_MAILBOX *Mailbox,
+ IN UINTN Index,
+ IN UINT64 Value
+ )
+{
+ AcquireMpSpinLock (&mDebugMpContext.MailboxSpinLock);
+ switch (Index) {
+ case DEBUG_MAILBOX_DEBUG_FLAG_INDEX:
+ Mailbox->ToBeCheckSum = Mailbox->CheckSum + CalculateSum8 ((UINT8 *)&Mailbox->DebugFlag.Uint64, sizeof(UINT64))
+ - CalculateSum8 ((UINT8 *)&Value, sizeof(UINT64));
+ Mailbox->DebugFlag.Uint64 = Value;
+ break;
+ case DEBUG_MAILBOX_DEBUG_PORT_HANDLE_INDEX:
+ Mailbox->ToBeCheckSum = Mailbox->CheckSum + CalculateSum8 ((UINT8 *)&Mailbox->DebugPortHandle, sizeof(UINTN))
+ - CalculateSum8 ((UINT8 *)&Value, sizeof(UINTN));
+ Mailbox->DebugPortHandle = (UINTN) Value;
+ break;
+ case DEBUG_MAILBOX_EXCEPTION_BUFFER_POINTER_INDEX:
+ Mailbox->ToBeCheckSum = Mailbox->CheckSum + CalculateSum8 ((UINT8 *)&Mailbox->ExceptionBufferPointer, sizeof(UINTN))
+ - CalculateSum8 ((UINT8 *)&Value, sizeof(UINTN));
+ Mailbox->ExceptionBufferPointer = (UINTN) Value;
+ break;
+ case DEBUG_MAILBOX_LAST_ACK:
+ Mailbox->ToBeCheckSum = Mailbox->CheckSum + CalculateSum8 ((UINT8 *)&Mailbox->LastAck, sizeof(UINT8))
+ - CalculateSum8 ((UINT8 *)&Value, sizeof(UINT8));
+ Mailbox->LastAck = (UINT8) Value;
+ break;
+ case DEBUG_MAILBOX_SEQUENCE_NO_INDEX:
+ Mailbox->ToBeCheckSum = Mailbox->CheckSum + CalculateSum8 ((UINT8 *)&Mailbox->SequenceNo, sizeof(UINT8))
+ - CalculateSum8 ((UINT8 *)&Value, sizeof(UINT8));
+ Mailbox->SequenceNo = (UINT8) Value;
+ break;
+ case DEBUG_MAILBOX_HOST_SEQUENCE_NO_INDEX:
+ Mailbox->ToBeCheckSum = Mailbox->CheckSum + CalculateSum8 ((UINT8 *)&Mailbox->HostSequenceNo, sizeof(UINT8))
+ - CalculateSum8 ((UINT8 *)&Value, sizeof(UINT8));
+ Mailbox->HostSequenceNo = (UINT8) Value;
+ break;
+ }
+ UpdateMailboxChecksum (Mailbox);
+ ReleaseMpSpinLock (&mDebugMpContext.MailboxSpinLock);
+}
+/**
+ Set debug flag in mailbox.
+
+ @param[in] FlagMask Debug flag mask value.
+ @param[in] FlagValue Debug flag value.
+
+**/
+VOID
+SetDebugFlag (
+ IN UINT64 FlagMask,
+ IN UINT32 FlagValue
+ )
+{
+ DEBUG_AGENT_MAILBOX *Mailbox;
+ UINT64 Data64;
+
+ Mailbox = GetMailboxPointer ();
+ Data64 = (Mailbox->DebugFlag.Uint64 & ~FlagMask) |
+ (LShiftU64 ((UINT64)FlagValue, LowBitSet64 (FlagMask)) & FlagMask);
+ UpdateMailboxContent (Mailbox, DEBUG_MAILBOX_DEBUG_FLAG_INDEX, Data64);
+}
+
+/**
+ Get debug flag in mailbox.
+
+ @param[in] FlagMask Debug flag mask value.
+
+ @return Debug flag value.
+
+**/
+UINT32
+GetDebugFlag (
+ IN UINT64 FlagMask
+ )
+{
+ DEBUG_AGENT_MAILBOX *Mailbox;
+ UINT32 DebugFlag;
+
+ Mailbox = GetMailboxPointer ();
+ DebugFlag = (UINT32) RShiftU64 (Mailbox->DebugFlag.Uint64 & FlagMask, LowBitSet64 (FlagMask));
+
+ return DebugFlag;
+}
/**
Send a debug message packet to the debug port.
@@ -46,8 +339,12 @@ SendDebugMsgPacket (
DebugHeader.StartSymbol = DEBUG_STARTING_SYMBOL_NORMAL;
DebugHeader.Command = DEBUG_COMMAND_PRINT_MESSAGE;
DebugHeader.Length = sizeof (DEBUG_PACKET_HEADER) + (UINT8) Length;
- DebugHeader.CheckSum = 0;
- DebugHeader.CheckSum = CalculateCheckSum8 ((UINT8 *)&DebugHeader, sizeof (DEBUG_PACKET_HEADER));
+ DebugHeader.SequenceNo = 0xEE;
+ DebugHeader.Crc = 0;
+ DebugHeader.Crc = CalculateCrc16 (
+ (UINT8 *)Buffer, Length,
+ CalculateCrc16 ((UINT8 *)&DebugHeader, sizeof (DEBUG_PACKET_HEADER), 0)
+ );
DebugPortWriteBuffer (Handle, (UINT8 *)&DebugHeader, sizeof (DEBUG_PACKET_HEADER));
DebugPortWriteBuffer (Handle, (UINT8 *)Buffer, Length);
@@ -73,15 +370,13 @@ DebugAgentMsgPrint (
...
)
{
- DEBUG_AGENT_MAILBOX *Mailbox;
CHAR8 Buffer[DEBUG_DATA_MAXIMUM_REAL_DATA];
VA_LIST Marker;
- Mailbox = GetMailboxPointer ();
//
// Check driver debug mask value and global mask
//
- if ((ErrorLevel & Mailbox->DebugFlag.PrintErrorLevel) == 0) {
+ if ((ErrorLevel & GetDebugFlag (DEBUG_AGENT_FLAG_PRINT_ERROR_LEVEL)) == 0) {
return;
}
@@ -119,16 +414,14 @@ DebugAgentDataMsgPrint (
IN UINT8 Length
)
{
- DEBUG_AGENT_MAILBOX *Mailbox;
CHAR8 Buffer[DEBUG_DATA_MAXIMUM_REAL_DATA];
CHAR8 *DestBuffer;
UINTN Index;
- Mailbox = GetMailboxPointer ();
//
// Check driver debug mask value and global mask
//
- if ((ErrorLevel & Mailbox->DebugFlag.PrintErrorLevel) == 0) {
+ if ((ErrorLevel & GetDebugFlag (DEBUG_AGENT_FLAG_PRINT_ERROR_LEVEL)) == 0) {
return;
}
@@ -152,7 +445,7 @@ DebugAgentDataMsgPrint (
DestBuffer += AsciiSPrint (DestBuffer, DEBUG_DATA_MAXIMUM_REAL_DATA - (DestBuffer - Buffer), "%02x ", Data[Index]);
Index ++;
if (Index >= Length) {
- //s
+ //
// The last character of debug message has been foramtted in buffer
//
DestBuffer += AsciiSPrint(DestBuffer, DEBUG_DATA_MAXIMUM_REAL_DATA - (DestBuffer - Buffer), "]\n");
@@ -162,6 +455,46 @@ DebugAgentDataMsgPrint (
}
}
+/**
+ Read remaing debug packet except for the start symbol
+
+ @param[in] Handle Pointer to Debug Port handle.
+ @param[in, out] DebugHeader Debug header buffer including start symbol.
+
+ @retval EFI_SUCCESS Read the symbol in BreakSymbol.
+ @retval EFI_CRC_ERROR CRC check fail.
+ @retval EFI_TIMEOUT Timeout occurs when reading debug packet.
+
+**/
+EFI_STATUS
+ReadRemainingBreakPacket (
+ IN DEBUG_PORT_HANDLE Handle,
+ IN OUT DEBUG_PACKET_HEADER *DebugHeader
+ )
+{
+ UINT16 Crc;
+ //
+ // Has received start symbol, try to read the rest part
+ //
+ if (DebugPortReadBuffer (Handle, &DebugHeader->Command, sizeof (DEBUG_PACKET_HEADER) - 1, READ_PACKET_TIMEOUT) == 0) {
+ //
+ // Timeout occur, exit
+ //
+ DebugAgentMsgPrint (DEBUG_AGENT_WARNING, "Timeout in Debug Timer interrupt\n");
+ return EFI_TIMEOUT;
+ }
+
+ Crc = DebugHeader->Crc;
+ DebugHeader->Crc = 0;
+ if (CalculateCrc16 ((UINT8 *)DebugHeader, DebugHeader->Length, 0) != Crc) {
+ DebugAgentMsgPrint (DEBUG_AGENT_WARNING, "Debug Timer CRC (%x) against (%x)\n", Crc, CalculateCrc16 ((UINT8 *) &DebugHeader, DebugHeader->Length, 0));
+ DebugAgentDataMsgPrint (DEBUG_AGENT_VERBOSE, FALSE, (UINT8 *)DebugHeader, DebugHeader->Length);
+ return EFI_CRC_ERROR;
+ }
+
+ UpdateMailboxContent (GetMailboxPointer(), DEBUG_MAILBOX_HOST_SEQUENCE_NO_INDEX, DebugHeader->SequenceNo);
+ return EFI_SUCCESS;
+}
/**
Check if HOST is attached based on Mailbox.
@@ -175,7 +508,7 @@ IsHostAttached (
VOID
)
{
- return (BOOLEAN) (GetMailboxPointer ()->DebugFlag.HostAttached == 1);
+ return (BOOLEAN) (GetDebugFlag (DEBUG_AGENT_FLAG_HOST_ATTACHED) == 1);
}
/**
@@ -190,7 +523,7 @@ SetHostAttached (
)
{
DebugAgentMsgPrint (DEBUG_AGENT_INFO, "Attach status is %d\n", Attached);
- GetMailboxPointer ()->DebugFlag.HostAttached = Attached;
+ SetDebugFlag (DEBUG_AGENT_FLAG_HOST_ATTACHED, (UINT32)Attached);
}
/**
@@ -208,17 +541,17 @@ SetDebugSetting (
)
{
RETURN_STATUS Status;
- DEBUG_AGENT_MAILBOX *Mailbox;
-
- Mailbox = GetMailboxPointer ();
Status = RETURN_SUCCESS;
switch (DebugSetting->Key) {
case DEBUG_AGENT_SETTING_SMM_ENTRY_BREAK:
- Mailbox->DebugFlag.BreakOnNextSmi = DebugSetting->Value;
+ SetDebugFlag (DEBUG_AGENT_FLAG_BREAK_ON_NEXT_SMI, DebugSetting->Value);
break;
case DEBUG_AGENT_SETTING_PRINT_ERROR_LEVEL:
- Mailbox->DebugFlag.PrintErrorLevel = DebugSetting->Value;
+ SetDebugFlag (DEBUG_AGENT_FLAG_PRINT_ERROR_LEVEL, DebugSetting->Value);
+ break;
+ case DEBUG_AGENT_SETTING_BOOT_SCRIPT_ENTRY_BREAK:
+ SetDebugFlag (DEBUG_AGENT_FLAG_BREAK_BOOT_SCRIPT, DebugSetting->Value);
break;
default:
Status = RETURN_UNSUPPORTED;
@@ -446,11 +779,13 @@ ArchReadRegisterBuffer (
Send the packet without data to HOST.
@param[in] CommandType Type of Command.
+ @param[in] SequenceNo Sequence number.
**/
VOID
SendPacketWithoutData (
- IN UINT8 CommandType
+ IN UINT8 CommandType,
+ IN UINT8 SequenceNo
)
{
DEBUG_PACKET_HEADER DebugHeader;
@@ -461,8 +796,9 @@ SendPacketWithoutData (
DebugHeader.StartSymbol = DEBUG_STARTING_SYMBOL_NORMAL;
DebugHeader.Command = CommandType;
DebugHeader.Length = sizeof (DEBUG_PACKET_HEADER);
- DebugHeader.CheckSum = 0;
- DebugHeader.CheckSum = CalculateCheckSum8 ((UINT8 *)&DebugHeader, sizeof (DEBUG_PACKET_HEADER));
+ DebugHeader.SequenceNo = SequenceNo;
+ DebugHeader.Crc = 0;
+ DebugHeader.Crc = CalculateCrc16 ((UINT8 *)&DebugHeader, sizeof (DEBUG_PACKET_HEADER), 0);
DebugAgentDataMsgPrint (DEBUG_AGENT_VERBOSE, TRUE, (UINT8 *) &DebugHeader, DebugHeader.Length);
DebugPortWriteBuffer (Handle, (UINT8 *) &DebugHeader, DebugHeader.Length);
@@ -479,104 +815,142 @@ SendAckPacket (
IN UINT8 AckCommand
)
{
+ UINT8 SequenceNo;
+ DEBUG_AGENT_MAILBOX *Mailbox;
+
if (AckCommand != DEBUG_COMMAND_OK) {
+ //
+ // This is not ACK OK packet
+ //
DebugAgentMsgPrint (DEBUG_AGENT_ERROR, "Send ACK(%d)\n", AckCommand);
}
- SendPacketWithoutData (AckCommand);
+ Mailbox = GetMailboxPointer();
+ SequenceNo = Mailbox->HostSequenceNo;
+ DebugAgentMsgPrint (DEBUG_AGENT_INFO, "SendAckPacket: SequenceNo = %x\n", SequenceNo);
+ SendPacketWithoutData (AckCommand, SequenceNo);
+ UpdateMailboxContent (Mailbox, DEBUG_MAILBOX_LAST_ACK, AckCommand);
}
/**
- Receive acknowledge packet from HOST in specified time.
+ Receive valid packet from HOST.
- @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.
- @param[out] CheckSumStatus If CheckSumStatus is not NULL,
- RETURN_SUCCESS CheckSum is OK.
- RETURN_NOT_FOUND Not find the CheckSum field.
+ @param[out] InputPacket Buffer to receive packet.
+ @param[out] BreakReceived TRUE means break-in symbol received.
+ FALSE means break-in symbol not received.
+ @param[out] IncompatibilityFlag If IncompatibilityFlag is not NULL, return
+ TRUE: Compatible packet received.
+ FALSE: Incompatible packet received.
+ @param[in] Timeout Time out value to wait for acknowlege from HOST.
+ The unit is microsecond.
+ @param[in] SkipStartSymbol TRUE: Skip time out when reading start symbol.
+ FALSE: Does not Skip time out when reading start symbol.
- @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.
+ @retval RETURN_SUCCESS A valid package was reveived in InputPacket.
+ @retval RETURN_TIMEOUT Timeout occurs.
**/
RETURN_STATUS
-ReceiveAckPacket (
- OUT UINT8 *Ack,
- IN UINTN Timeout,
- OUT BOOLEAN *BreakReceived, OPTIONAL
- OUT RETURN_STATUS *CheckSumStatus OPTIONAL
+ReceivePacket (
+ OUT UINT8 *InputPacket,
+ OUT BOOLEAN *BreakReceived,
+ OUT BOOLEAN *IncompatibilityFlag, OPTIONAL
+ IN UINTN Timeout,
+ IN BOOLEAN SkipStartSymbol
)
{
- DEBUG_PACKET_HEADER DebugHeader;
- DEBUG_PORT_HANDLE Handle;
+ DEBUG_PACKET_HEADER *DebugHeader;
+ UINTN Received;
+ DEBUG_PORT_HANDLE Handle;
+ UINT16 Crc;
+ UINTN TimeoutForStartSymbol;
Handle = GetDebugPortHandle();
-
+ if (SkipStartSymbol) {
+ TimeoutForStartSymbol = 0;
+ } else {
+ TimeoutForStartSymbol = Timeout;
+ }
+
+ DebugHeader = (DEBUG_PACKET_HEADER *) InputPacket;
while (TRUE) {
- if (DebugPortReadBuffer (Handle, (UINT8 *) &DebugHeader.StartSymbol, sizeof (DebugHeader.StartSymbol), Timeout) == 0) {
+ //
+ // Find the valid start symbol
+ //
+ Received = DebugPortReadBuffer (Handle, &DebugHeader->StartSymbol, sizeof (DebugHeader->StartSymbol), TimeoutForStartSymbol);
+ if (Received < sizeof (DebugHeader->StartSymbol)) {
+ DebugAgentMsgPrint (DEBUG_AGENT_WARNING, "DebugPortReadBuffer(StartSymbol) timeout\n");
return RETURN_TIMEOUT;
}
- if (DebugHeader.StartSymbol == DEBUG_STARTING_SYMBOL_BREAK) {
- if (BreakReceived != NULL) {
- SendAckPacket (DEBUG_COMMAND_HALT_DEFERRED);
- *BreakReceived = TRUE;
- }
- }
- if (DebugHeader.StartSymbol == DEBUG_STARTING_SYMBOL_NORMAL) {
- break;
+
+ if (DebugHeader->StartSymbol != DEBUG_STARTING_SYMBOL_NORMAL) {
+ DebugAgentMsgPrint (DEBUG_AGENT_WARNING, "Invalid start symbol received [%02x]\n", DebugHeader->StartSymbol);
+ continue;
}
- DebugAgentMsgPrint (DEBUG_AGENT_ERROR, "Invalid start symbol received [%02x]\n", DebugHeader.StartSymbol);
- }
- //
- // Read ACK packet header till field Length (not including StartSymbol and CheckSum)
- //
- DebugHeader.Length = 0;
- if (DebugPortReadBuffer (
- Handle,
- (UINT8 *)&DebugHeader.Command,
- OFFSET_OF (DEBUG_PACKET_HEADER, Length) + sizeof (DebugHeader.Length) - sizeof (DebugHeader.StartSymbol),
- Timeout
- ) == 0) {
- return RETURN_TIMEOUT;
- }
- if (DebugHeader.Length == 0) {
//
- // The CheckSum field does not exist
+ // Read Package header till field Length
//
- if (CheckSumStatus != NULL) {
- *CheckSumStatus = RETURN_NOT_FOUND;
- }
- } else {
- if (CheckSumStatus != NULL) {
- *CheckSumStatus = RETURN_SUCCESS;
- }
- if (DebugPortReadBuffer (Handle, &DebugHeader.CheckSum, sizeof (DebugHeader.CheckSum), Timeout) == 0) {
+ Received = DebugPortReadBuffer (
+ Handle,
+ &DebugHeader->Command,
+ OFFSET_OF (DEBUG_PACKET_HEADER, Length) + sizeof (DebugHeader->Length) - sizeof (DebugHeader->StartSymbol),
+ Timeout
+ );
+ if (Received == 0) {
+ DebugAgentMsgPrint (DEBUG_AGENT_ERROR, "DebugPortReadBuffer(Command) timeout\n");
return RETURN_TIMEOUT;
}
+ if (DebugHeader->Length < sizeof (DEBUG_PACKET_HEADER)) {
+ if (IncompatibilityFlag != NULL) {
+ //
+ // This is one old version debug packet format, set Incompatibility flag
+ //
+ *IncompatibilityFlag = TRUE;
+ } else {
+ //
+ // Skip the bad small packet
+ //
+ continue;
+ }
+ } else {
+ //
+ // Read the payload data include the CRC field
+ //
+ Received = DebugPortReadBuffer (Handle, &DebugHeader->SequenceNo, (UINT8) (DebugHeader->Length - OFFSET_OF (DEBUG_PACKET_HEADER, SequenceNo)), Timeout);
+ if (Received == 0) {
+ DebugAgentMsgPrint (DEBUG_AGENT_ERROR, "DebugPortReadBuffer(SequenceNo) timeout\n");
+ return RETURN_TIMEOUT;
+ }
+ //
+ // Calculate the CRC of Debug Packet
+ //
+ Crc = DebugHeader->Crc;
+ DebugHeader->Crc = 0;
+ if (Crc == CalculateCrc16 ((UINT8 *) DebugHeader, DebugHeader->Length, 0)) {
+ break;
+ }
+ DebugAgentMsgPrint (DEBUG_AGENT_WARNING, "CRC Error (received CRC is %x)\n", Crc);
+ DebugAgentDataMsgPrint (DEBUG_AGENT_VERBOSE, FALSE, (UINT8 *) DebugHeader, DebugHeader->Length);
+ }
}
- DebugAgentDataMsgPrint (DEBUG_AGENT_VERBOSE, FALSE, (UINT8 *)&DebugHeader, DebugHeader.Length);
- *Ack = DebugHeader.Command;
+ DebugAgentDataMsgPrint (DEBUG_AGENT_VERBOSE, FALSE, (UINT8 *) DebugHeader, DebugHeader->Length);
+
return RETURN_SUCCESS;
}
/**
Receive acknowledge packet OK from HOST in specified time.
- @param[in] Command The command type issued by TARGET.
- @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.
- @param[out] CheckSumStatus If CheckSumStatus is not NULL,
- RETURN_SUCCESS CheckSum is OK.
- RETURN_NOT_FOUND Not find the CheckSum field.
+ @param[in] Command The command type issued by TARGET.
+ @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.
+ @param[out] IncompatibilityFlag If IncompatibilityFlag is not NULL, return
+ TRUE: Compatible packet received.
+ FALSE: Incompatible packet received.
@retval RETRUEN_SUCCESS Succeed to receive acknowlege packet from HOST,
the type of acknowlege packet saved in Ack.
@@ -588,109 +962,56 @@ SendCommandAndWaitForAckOK (
IN UINT8 Command,
IN UINTN Timeout,
OUT BOOLEAN *BreakReceived, OPTIONAL
- OUT RETURN_STATUS *CheckSumStatus OPTIONAL
+ OUT BOOLEAN *IncompatibilityFlag OPTIONAL
)
{
RETURN_STATUS Status;
- UINT8 Ack;
-
- while (TRUE) {
- SendPacketWithoutData (Command);
- while (TRUE) {
- Status = ReceiveAckPacket (&Ack, Timeout, BreakReceived, CheckSumStatus);
- if (Status == RETURN_SUCCESS && Ack == DEBUG_COMMAND_RESEND) {
- //
- // Resend the last command
- //
- break;
- }
- if ((Status == RETURN_SUCCESS && Ack == DEBUG_COMMAND_OK) ||
- Status == RETURN_TIMEOUT) {
- //
- // Received Ack OK or timeout
- //
- 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_TIMEOUT Timeout occurs.
-
-**/
-RETURN_STATUS
-ReceivePacket (
- OUT UINT8 *InputPacket,
- OUT BOOLEAN *BreakReceived
- )
-{
- DEBUG_PACKET_HEADER *DebugHeader;
- UINTN Received;
- DEBUG_PORT_HANDLE Handle;
- UINT8 CheckSum;
-
- Handle = GetDebugPortHandle();
-
- DebugHeader = (DEBUG_PACKET_HEADER *) InputPacket;
- while (TRUE) {
- //
- // Find the valid start symbol
- //
- DebugPortReadBuffer (Handle, &DebugHeader->StartSymbol, sizeof (DebugHeader->StartSymbol), 0);
-
- if (DebugHeader->StartSymbol == DEBUG_STARTING_SYMBOL_BREAK) {
- *BreakReceived = TRUE;
- SendAckPacket (DEBUG_COMMAND_HALT_DEFERRED);
- }
-
- if (DebugHeader->StartSymbol != DEBUG_STARTING_SYMBOL_NORMAL) {
- DebugAgentMsgPrint (DEBUG_AGENT_ERROR, "Invalid start symbol received [%02x]\n", DebugHeader->StartSymbol);
+ UINT8 InputPacketBuffer[DEBUG_DATA_UPPER_LIMIT];
+ DEBUG_PACKET_HEADER *DebugHeader;
+ UINT8 SequenceNo;
+ UINT8 HostSequenceNo;
+ UINT8 RetryCount;
+
+ RetryCount = 3;
+ DebugHeader = (DEBUG_PACKET_HEADER *) InputPacketBuffer;
+ Status = RETURN_TIMEOUT;
+ while (RetryCount > 0) {
+ SequenceNo = GetMailboxPointer()->SequenceNo;
+ HostSequenceNo = GetMailboxPointer()->HostSequenceNo;
+ SendPacketWithoutData (Command, SequenceNo);
+ Status = ReceivePacket ((UINT8 *) DebugHeader, BreakReceived, IncompatibilityFlag, Timeout, FALSE);
+ if (Status == RETURN_TIMEOUT) {
+ if (Command == DEBUG_COMMAND_INIT_BREAK) {
+ RetryCount--;
+ } else {
+ DebugAgentMsgPrint (DEBUG_AGENT_WARNING, "TARGET: Timeout when waiting for ACK packet.\n");
+ }
continue;
}
-
- //
- // Read Package header except for checksum
- //
- Received = DebugPortReadBuffer (
- Handle,
- &DebugHeader->Command,
- OFFSET_OF (DEBUG_PACKET_HEADER, Length) + sizeof (DebugHeader->Length) - sizeof (DebugHeader->StartSymbol),
- 0
- );
- if (Received == 0) {
- return RETURN_TIMEOUT;
- }
-
+ ASSERT_EFI_ERROR (Status);
//
- // Read the payload data include the checksum
+ // Status == RETURN_SUCCESS
//
- Received = DebugPortReadBuffer (Handle, &DebugHeader->CheckSum, DebugHeader->Length - OFFSET_OF (DEBUG_PACKET_HEADER, CheckSum), 0);
- if (Received == 0) {
- return RETURN_TIMEOUT;
+ if (DebugHeader->Command == DEBUG_COMMAND_OK && DebugHeader->SequenceNo == SequenceNo) {
+ //
+ // Received Ack OK
+ //
+ UpdateMailboxContent (GetMailboxPointer(), DEBUG_MAILBOX_SEQUENCE_NO_INDEX, ++SequenceNo);
+ return Status;
}
- //
- // Calculate the checksum of Debug Packet
- //
- CheckSum = CalculateCheckSum8 ((UINT8 *) DebugHeader, DebugHeader->Length);
- if (CheckSum == 0) {
- break;
+ if (DebugHeader->Command == DEBUG_COMMAND_GO && (DebugHeader->SequenceNo == HostSequenceNo || Command == DEBUG_COMMAND_INIT_BREAK)) {
+ //
+ // Received Old GO
+ //
+ if (Command == DEBUG_COMMAND_INIT_BREAK) {
+ DebugAgentMsgPrint (DEBUG_AGENT_WARNING, "TARGET: Receive GO() in last boot\n");
+ }
+ SendPacketWithoutData (DEBUG_COMMAND_OK, DebugHeader->SequenceNo);
}
- DebugAgentMsgPrint (DEBUG_AGENT_WARNING, "CheckSum Error (Caculated checksum is %x, received checksum is %x\n", CheckSum, DebugHeader->CheckSum);
- DebugAgentMsgPrint (DEBUG_AGENT_WARNING, "Send DEBUG_COMMAND_RESEND command.\n");
- SendAckPacket (DEBUG_COMMAND_RESEND);
}
- DebugAgentDataMsgPrint (DEBUG_AGENT_VERBOSE, FALSE, (UINT8 *) DebugHeader, DebugHeader->Length);
-
- return RETURN_SUCCESS;
+ ASSERT (Command == DEBUG_COMMAND_INIT_BREAK);
+ return Status;
}
/**
@@ -773,7 +1094,7 @@ GetBreakCause (
default:
if (Vector < 20) {
- if (GetMailboxPointer()->DebugFlag.SteppingFlag == 1) {
+ if (GetDebugFlag (DEBUG_AGENT_FLAG_STEPPING) == 1) {
//
// If stepping command is executing
//
@@ -789,28 +1110,28 @@ GetBreakCause (
}
/**
- Send command packet with data to HOST.
+ Send packet with response data to HOST.
- @param[in] Command Command type.
@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
-SendCommandWithDataPacket (
- IN UINT8 Command,
+SendDataResponsePacket (
IN UINT8 *Data,
IN UINT16 DataSize
)
{
+ RETURN_STATUS Status;
DEBUG_PACKET_HEADER *DebugHeader;
BOOLEAN LastPacket;
- UINT8 Ack;
+ DEBUG_PACKET_HEADER *AckDebugHeader;
UINT8 DebugPacket[DEBUG_DATA_UPPER_LIMIT];
+ UINT8 InputPacketBuffer[DEBUG_DATA_UPPER_LIMIT];
DEBUG_PORT_HANDLE Handle;
+ UINT8 SequenceNo;
Handle = GetDebugPortHandle();
@@ -818,84 +1139,67 @@ SendCommandWithDataPacket (
DebugHeader->StartSymbol = DEBUG_STARTING_SYMBOL_NORMAL;
while (TRUE) {
+ SequenceNo = GetMailboxPointer()->HostSequenceNo;
if (DataSize <= DEBUG_DATA_MAXIMUM_REAL_DATA) {
LastPacket = TRUE;
- DebugHeader->Command = Command;
- DebugHeader->Length = (UINT8) (DataSize + sizeof (DEBUG_PACKET_HEADER));
- DebugHeader->CheckSum = 0;
+ DebugHeader->Command = DEBUG_COMMAND_OK;
+ DebugHeader->Length = (UINT8) (DataSize + sizeof (DEBUG_PACKET_HEADER));
+ DebugHeader->SequenceNo = SequenceNo;
+ DebugHeader->Crc = 0;
CopyMem (DebugHeader + 1, Data, DataSize);
} else {
LastPacket = FALSE;
- DebugHeader->Command = DEBUG_COMMAND_IN_PROGRESS;
- DebugHeader->Length = DEBUG_DATA_MAXIMUM_REAL_DATA + sizeof (DEBUG_PACKET_HEADER);
- DebugHeader->CheckSum = 0;
+ DebugHeader->Command = DEBUG_COMMAND_IN_PROGRESS;
+ DebugHeader->Length = DEBUG_DATA_MAXIMUM_REAL_DATA + sizeof (DEBUG_PACKET_HEADER);
+ DebugHeader->SequenceNo = SequenceNo;
+ DebugHeader->Crc = 0;
CopyMem (DebugHeader + 1, Data, DEBUG_DATA_MAXIMUM_REAL_DATA);
}
//
// Calculate and fill the checksum
//
- DebugHeader->CheckSum = CalculateCheckSum8 ((UINT8 *) DebugHeader, DebugHeader->Length);
+ DebugHeader->Crc = CalculateCrc16 ((UINT8 *) DebugHeader, DebugHeader->Length, 0);
DebugAgentDataMsgPrint (DEBUG_AGENT_VERBOSE, TRUE, (UINT8 *) DebugHeader, DebugHeader->Length);
DebugPortWriteBuffer (Handle, (UINT8 *) DebugHeader, DebugHeader->Length);
- ReceiveAckPacket(&Ack, 0, NULL, NULL);
- switch (Ack) {
- case DEBUG_COMMAND_RESEND:
- //
- // Send the packet again
- //
- DebugAgentMsgPrint (DEBUG_AGENT_WARNING, "Received DEBUG_COMMAND_RESEND.\n");
- 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) {
+ while (TRUE) {
+ Status = ReceivePacket (InputPacketBuffer, NULL, NULL, READ_PACKET_TIMEOUT, FALSE);
+ if (Status == RETURN_TIMEOUT) {
+ DebugAgentMsgPrint (DEBUG_AGENT_WARNING, "TARGET: Timeout in SendDataResponsePacket()\n");
+ break;
+ }
+ AckDebugHeader = (DEBUG_PACKET_HEADER *) InputPacketBuffer;
+ SequenceNo = AckDebugHeader->SequenceNo;
+ if (AckDebugHeader->Command == DEBUG_COMMAND_OK &&
+ SequenceNo == DebugHeader->SequenceNo &&
+ LastPacket) {
//
// If this is the last packet, return RETURN_SUCCESS.
//
return RETURN_SUCCESS;
- } else {
- return RETURN_DEVICE_ERROR;
}
-
- default:
- return RETURN_DEVICE_ERROR;
-
+ if ((SequenceNo == (UINT8) (DebugHeader->SequenceNo + 1)) && (AckDebugHeader->Command == DEBUG_COMMAND_CONTINUE)) {
+ //
+ // Send the rest packet
+ //
+ Data += DEBUG_DATA_MAXIMUM_REAL_DATA;
+ DataSize -= DEBUG_DATA_MAXIMUM_REAL_DATA;
+ UpdateMailboxContent (GetMailboxPointer(), DEBUG_MAILBOX_HOST_SEQUENCE_NO_INDEX, (UINT8) SequenceNo);
+ break;
+ }
+ if (SequenceNo >= DebugHeader->SequenceNo) {
+ DebugAgentMsgPrint (DEBUG_AGENT_WARNING, "TARGET: Received one old or new command(SequenceNo is %x, last SequenceNo is %x)\n", SequenceNo, DebugHeader->SequenceNo);
+ break;
+ }
}
}
}
/**
- Send packet with response data to HOST.
-
- @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 UINT8 *Data,
- IN UINT16 DataSize
- )
-{
- return SendCommandWithDataPacket (DEBUG_COMMAND_OK, Data, DataSize);
-}
-
-/**
Send break cause packet to HOST.
@param[in] Vector Vector value of exception or interrutp.
@@ -927,6 +1231,7 @@ SendBreakCausePacket (
If received acknowlege, check the revision of HOST.
Set Attach Flag if attach successfully.
+ @param[in] BreakCause Break cause of this break event.
@param[in] Timeout Time out value to wait for acknowlege from HOST.
The unit is microsecond.
@param[out] BreakReceived If BreakReceived is not NULL,
@@ -935,42 +1240,45 @@ SendBreakCausePacket (
**/
RETURN_STATUS
AttachHost (
+ IN UINT8 BreakCause,
IN UINTN Timeout,
OUT BOOLEAN *BreakReceived
)
{
RETURN_STATUS Status;
DEBUG_PORT_HANDLE Handle;
- RETURN_STATUS CheckSumStatus;
+ BOOLEAN IncompatibilityFlag;
+ IncompatibilityFlag = FALSE;
Handle = GetDebugPortHandle();
//
// Send init break and wait ack in Timeout
//
DebugPortWriteBuffer (Handle, (UINT8 *) mErrorMsgSendInitPacket, AsciiStrLen (mErrorMsgSendInitPacket));
- Status = SendCommandAndWaitForAckOK (DEBUG_COMMAND_INIT_BREAK, Timeout, BreakReceived, &CheckSumStatus);
- if (RETURN_ERROR (Status)) {
- DebugPortWriteBuffer (Handle, (UINT8 *) mErrorMsgConnectFail, AsciiStrLen (mErrorMsgConnectFail));
- return Status;
+ if (BreakCause == DEBUG_DATA_BREAK_CAUSE_SYSTEM_RESET) {
+ Status = SendCommandAndWaitForAckOK (DEBUG_COMMAND_INIT_BREAK, Timeout, BreakReceived, &IncompatibilityFlag);
+ } else {
+ Status = SendCommandAndWaitForAckOK (DEBUG_COMMAND_ATTACH_BREAK, Timeout, BreakReceived, &IncompatibilityFlag);
}
-
- if (CheckSumStatus == RETURN_NOT_FOUND) {
+ if (IncompatibilityFlag) {
//
- // If the CheckSum field does not exist in Debug Packet,
- // the HOST should be running with 0.1 transfer protocol.
- // It could be UDK Debugger for Windows v1.1 or for Linux v0.8.
+ // If the incompatible Debug Packet received, the HOST should be running transfer protocol before DEBUG_AGENT_REVISION.
+ // It could be UDK Debugger for Windows v1.1/v1.2 or for Linux v0.8/v1.2.
//
DebugPortWriteBuffer (Handle, (UINT8 *) mErrorMsgVersionAlert, AsciiStrLen (mErrorMsgVersionAlert));
CpuDeadLoop ();
}
-
- DebugPortWriteBuffer (Handle, (UINT8 *) mErrorMsgConnectOK, AsciiStrLen (mErrorMsgConnectOK));
- //
- // Set Attach flag
- //
- SetHostAttached (TRUE);
-
+
+ if (RETURN_ERROR (Status)) {
+ DebugPortWriteBuffer (Handle, (UINT8 *) mErrorMsgConnectFail, AsciiStrLen (mErrorMsgConnectFail));
+ } else {
+ DebugPortWriteBuffer (Handle, (UINT8 *) mErrorMsgConnectOK, AsciiStrLen (mErrorMsgConnectOK));
+ //
+ // Set Attach flag
+ //
+ SetHostAttached (TRUE);
+ }
return Status;
}
@@ -978,7 +1286,8 @@ AttachHost (
Send Break point packet to HOST.
Only the first breaking processor could sent BREAK_POINT packet.
-
+
+ @param[in] BreakCause Break cause of this break event.
@param[in] ProcessorIndex Processor index value.
@param[out] BreakReceived If BreakReceived is not NULL,
TRUE is retured if break-in symbol received.
@@ -987,6 +1296,7 @@ AttachHost (
**/
VOID
SendBreakPacketToHost (
+ IN UINT8 BreakCause,
IN UINT32 ProcessorIndex,
OUT BOOLEAN *BreakReceived
)
@@ -998,7 +1308,7 @@ SendBreakPacketToHost (
if (IsHostAttached ()) {
DebugAgentMsgPrint (DEBUG_AGENT_INFO, "processor[%x]:Send Break Packet to HOST.\n", ProcessorIndex);
- SendCommandAndWaitForAckOK (DEBUG_COMMAND_BREAK_POINT, 0, BreakReceived, NULL);
+ SendCommandAndWaitForAckOK (DEBUG_COMMAND_BREAK_POINT, READ_PACKET_TIMEOUT, BreakReceived, NULL);
} else {
DebugAgentMsgPrint (DEBUG_AGENT_INFO, "processor[%x]:Try to attach HOST.\n", ProcessorIndex);
//
@@ -1015,7 +1325,7 @@ SendBreakPacketToHost (
//
// Try to attach HOST
//
- while (AttachHost (0, NULL) != RETURN_SUCCESS);
+ while (AttachHost (BreakCause, 0, NULL) != RETURN_SUCCESS);
}
}
@@ -1065,12 +1375,13 @@ CommandCommunication (
DEBUG_PORT_HANDLE Handle;
DEBUG_AGENT_EXCEPTION_BUFFER AgentExceptionBuffer;
UINT32 IssuedViewPoint;
+ DEBUG_AGENT_MAILBOX *Mailbox;
ProcessorIndex = 0;
IssuedViewPoint = 0;
HaltDeferred = BreakReceived;
- if (MultiProcessorDebugSupport) {
+ if (MultiProcessorDebugSupport()) {
ProcessorIndex = GetProcessorIndex ();
SetCpuStopFlagByIndex (ProcessorIndex, TRUE);
if (mDebugMpContext.ViewPointIndex == ProcessorIndex) {
@@ -1085,14 +1396,14 @@ CommandCommunication (
//
// Set AgentInProgress Flag.
//
- GetMailboxPointer()->DebugFlag.AgentInProgress = 1;
+ SetDebugFlag (DEBUG_AGENT_FLAG_AGENT_IN_PROGRESS, 1);
}
Handle = GetDebugPortHandle();
while (TRUE) {
- if (MultiProcessorDebugSupport) {
+ if (MultiProcessorDebugSupport()) {
//
// Check if the current processor is HOST view point
//
@@ -1114,35 +1425,44 @@ CommandCommunication (
}
}
- AcquireDebugPortControl ();
+ AcquireMpSpinLock (&mDebugMpContext.DebugPortSpinLock);
- Status = ReceivePacket (InputPacketBuffer, &BreakReceived);
+ DebugHeader =(DEBUG_PACKET_HEADER *) InputPacketBuffer;
- if (BreakReceived) {
- HaltDeferred = TRUE;
- BreakReceived = FALSE;
+ DebugAgentMsgPrint (DEBUG_AGENT_INFO, "TARGET: Try to get command from HOST...\n");
+ Status = ReceivePacket ((UINT8 *)DebugHeader, &BreakReceived, NULL, READ_PACKET_TIMEOUT, TRUE);
+ if (Status != RETURN_SUCCESS || (DebugHeader->Command & DEBUG_COMMAND_RESPONSE) != 0) {
+ DebugAgentMsgPrint (DEBUG_AGENT_WARNING, "TARGET: Get command[%x] sequenceno[%x] returned status is [%x] \n", DebugHeader->Command, DebugHeader->SequenceNo, Status);
+ DebugAgentMsgPrint (DEBUG_AGENT_WARNING, "TARGET: Get command failed or it's response packet not expected! \n");
+ ReleaseMpSpinLock (&mDebugMpContext.DebugPortSpinLock);
+ continue;
}
- if (Status != RETURN_SUCCESS) {
- ReleaseDebugPortControl ();
+ Mailbox = GetMailboxPointer ();
+ if (DebugHeader->SequenceNo == Mailbox->HostSequenceNo) {
+ DebugAgentMsgPrint (DEBUG_AGENT_WARNING, "TARGET: Receive one old command[%x] agaist command[%x]\n", DebugHeader->SequenceNo, Mailbox->HostSequenceNo);
+ SendAckPacket (Mailbox->LastAck);
+ ReleaseMpSpinLock (&mDebugMpContext.DebugPortSpinLock);
+ continue;
+ } else if (DebugHeader->SequenceNo == (UINT8) (Mailbox->HostSequenceNo + 1)) {
+ UpdateMailboxContent (Mailbox, DEBUG_MAILBOX_HOST_SEQUENCE_NO_INDEX, (UINT8) DebugHeader->SequenceNo);
+ } else {
+ DebugAgentMsgPrint (DEBUG_AGENT_WARNING, "Receive one invalid comamnd[%x] agaist command[%x]\n", DebugHeader->SequenceNo, Mailbox->HostSequenceNo);
+ ReleaseMpSpinLock (&mDebugMpContext.DebugPortSpinLock);
continue;
}
-
- Data8 = 1;
-
- DebugHeader =(DEBUG_PACKET_HEADER *) InputPacketBuffer;
-
- GetMailboxPointer()->ExceptionBufferPointer = (UINT64)(UINTN) &AgentExceptionBuffer.JumpBuffer;
+
//
// Save CPU content before executing HOST commond
//
+ UpdateMailboxContent (Mailbox, DEBUG_MAILBOX_EXCEPTION_BUFFER_POINTER_INDEX, (UINT64)(UINTN) &AgentExceptionBuffer.JumpBuffer);
if (SetJump (&AgentExceptionBuffer.JumpBuffer) != 0) {
//
// If HOST command failed, continue to wait for HOST's next command
// If needed, agent could send exception info to HOST.
//
SendAckPacket (DEBUG_COMMAND_ABORT);
- ReleaseDebugPortControl ();
+ ReleaseMpSpinLock (&mDebugMpContext.DebugPortSpinLock);
continue;
}
@@ -1150,9 +1470,18 @@ CommandCommunication (
switch (DebugHeader->Command) {
+ case DEBUG_COMMAND_HALT:
+ SendAckPacket (DEBUG_COMMAND_HALT_DEFERRED);
+ HaltDeferred = TRUE;
+ BreakReceived = FALSE;
+ Status = RETURN_SUCCESS;
+ break;
+
case DEBUG_COMMAND_RESET:
SendAckPacket (DEBUG_COMMAND_OK);
- ReleaseDebugPortControl ();
+ SendAckPacket (DEBUG_COMMAND_OK);
+ SendAckPacket (DEBUG_COMMAND_OK);
+ ReleaseMpSpinLock (&mDebugMpContext.DebugPortSpinLock);
ResetCold ();
//
@@ -1160,6 +1489,9 @@ CommandCommunication (
// PCD can be used if 2 seconds isn't long enough for some platforms.
//
MicroSecondDelay (2000000);
+ UpdateMailboxContent (Mailbox, DEBUG_MAILBOX_HOST_SEQUENCE_NO_INDEX, Mailbox->HostSequenceNo + 1);
+ SendAckPacket (DEBUG_COMMAND_TIMEOUT);
+ SendAckPacket (DEBUG_COMMAND_TIMEOUT);
SendAckPacket (DEBUG_COMMAND_TIMEOUT);
break;
@@ -1176,13 +1508,13 @@ CommandCommunication (
//
// Clear Stepping Flag
//
- GetMailboxPointer()->DebugFlag.SteppingFlag = 0;
+ SetDebugFlag (DEBUG_AGENT_FLAG_STEPPING, 0);
if (!HaltDeferred) {
//
// If no HALT command received when being in-active mode
//
- if (MultiProcessorDebugSupport) {
+ if (MultiProcessorDebugSupport()) {
Data32 = FindNextPendingBreakCpu ();
if (Data32 != -1) {
//
@@ -1200,11 +1532,11 @@ CommandCommunication (
//
// Send break packet to HOST to let HOST break again
//
- SendBreakPacketToHost (0, &BreakReceived);
+ SendBreakPacketToHost (DEBUG_DATA_BREAK_CAUSE_UNKNOWN, mDebugMpContext.BreakAtCpuIndex, &BreakReceived);
//
// Continue to run into loop to read command packet from HOST
//
- ReleaseDebugPortControl ();
+ ReleaseMpSpinLock (&mDebugMpContext.DebugPortSpinLock);
break;
}
@@ -1240,8 +1572,12 @@ CommandCommunication (
//
SendAckPacket (DEBUG_COMMAND_OK);
- ReleaseDebugPortControl ();
+ ReleaseMpSpinLock (&mDebugMpContext.DebugPortSpinLock);
+ if (!IsHostAttached()) {
+ UpdateMailboxContent (Mailbox, DEBUG_MAILBOX_SEQUENCE_NO_INDEX, 0);
+ UpdateMailboxContent (Mailbox, DEBUG_MAILBOX_HOST_SEQUENCE_NO_INDEX, 0);
+ }
return;
} else {
@@ -1257,7 +1593,7 @@ CommandCommunication (
case DEBUG_COMMAND_BREAK_CAUSE:
- if (MultiProcessorDebugSupport && ProcessorIndex != mDebugMpContext.BreakAtCpuIndex) {
+ if (MultiProcessorDebugSupport() && ProcessorIndex != mDebugMpContext.BreakAtCpuIndex) {
Status = SendBreakCausePacket (DEBUG_TIMER_VECTOR, CpuContext);
} else {
@@ -1291,8 +1627,8 @@ CommandCommunication (
//
// Set Stepping Flag
//
- GetMailboxPointer()->DebugFlag.SteppingFlag = 1;
- ReleaseDebugPortControl ();
+ SetDebugFlag (DEBUG_AGENT_FLAG_STEPPING, 1);
+ ReleaseMpSpinLock (&mDebugMpContext.DebugPortSpinLock);
//
// Executing stepping command directly without sending ACK packet,
// ACK packet will be sent after stepping done.
@@ -1424,7 +1760,7 @@ CommandCommunication (
case DEBUG_COMMAND_SET_VIEWPOINT:
SetViewPoint = (DEBUG_DATA_SET_VIEWPOINT *) (DebugHeader + 1);
- if (MultiProcessorDebugSupport) {
+ if (MultiProcessorDebugSupport()) {
if (IsCpuStopped (SetViewPoint->ViewPoint)) {
SetDebugViewPoint (SetViewPoint->ViewPoint);
SendAckPacket (DEBUG_COMMAND_OK);
@@ -1449,7 +1785,7 @@ CommandCommunication (
break;
case DEBUG_COMMAND_MEMORY_READY:
- Data8 = (UINT8) GetMailboxPointer ()->DebugFlag.MemoryReady;
+ Data8 = (UINT8) GetDebugFlag (DEBUG_AGENT_FLAG_MEMORY_READY);
SendDataResponsePacket (&Data8, (UINT16) sizeof (UINT8));
break;
@@ -1517,7 +1853,7 @@ CommandCommunication (
SendAckPacket (DEBUG_COMMAND_ABORT);
}
- ReleaseDebugPortControl ();
+ ReleaseMpSpinLock (&mDebugMpContext.DebugPortSpinLock);
CpuPause ();
}
}
@@ -1552,7 +1888,17 @@ InterruptProcess (
IssuedViewPoint = 0;
BreakReceived = FALSE;
- if (MultiProcessorDebugSupport) {
+ if (mSkipBreakpoint) {
+ //
+ // If Skip Breakpoint flag is set, means communication is disturbed by hardware SMI, we need to ignore the break points in SMM
+ //
+ if ((Vector == DEBUG_INT1_VECTOR) || (Vector == DEBUG_INT3_VECTOR)) {
+ DebugPortWriteBuffer (GetDebugPortHandle(), (UINT8 *) mWarningMsgIngoreBreakpoint, AsciiStrLen (mWarningMsgIngoreBreakpoint));
+ return;
+ }
+ }
+
+ if (MultiProcessorDebugSupport()) {
ProcessorIndex = GetProcessorIndex ();
//
// If this processor has alreay halted before, need to check it later
@@ -1562,22 +1908,22 @@ InterruptProcess (
}
}
- if (IssuedViewPoint == ProcessorIndex) {
+ if (IssuedViewPoint == ProcessorIndex && GetDebugFlag (DEBUG_AGENT_FLAG_STEPPING) != 1) {
//
// Check if this exception is issued by Debug Agent itself
// If yes, fill the debug agent exception buffer and LongJump() back to
// the saved CPU content in CommandCommunication()
//
- if (GetMailboxPointer()->DebugFlag.AgentInProgress == 1) {
+ if (GetDebugFlag (DEBUG_AGENT_FLAG_AGENT_IN_PROGRESS) == 1) {
DebugAgentMsgPrint (DEBUG_AGENT_ERROR, "Debug agent meet one Exception, ExceptionNum is %d.\n", Vector);
ExceptionBuffer = (DEBUG_AGENT_EXCEPTION_BUFFER *) (UINTN) GetMailboxPointer()->ExceptionBufferPointer;
ExceptionBuffer->ExceptionContent.ExceptionNum = (UINT8) Vector;
ExceptionBuffer->ExceptionContent.ExceptionData = (UINT32) CpuContext->ExceptionData;
- LongJump ((BASE_LIBRARY_JUMP_BUFFER *)(UINTN)(GetMailboxPointer()->ExceptionBufferPointer), 1);
+ LongJump ((BASE_LIBRARY_JUMP_BUFFER *)(UINTN)(ExceptionBuffer), 1);
}
}
- if (MultiProcessorDebugSupport) {
+ if (MultiProcessorDebugSupport()) {
//
// If RUN commmand is executing, wait for it done.
//
@@ -1586,16 +1932,14 @@ InterruptProcess (
}
}
- Handle = GetDebugPortHandle();
-
+ Handle = GetDebugPortHandle();
+ BreakCause = GetBreakCause (Vector, CpuContext);
switch (Vector) {
case DEBUG_INT1_VECTOR:
case DEBUG_INT3_VECTOR:
- BreakCause = GetBreakCause (Vector, CpuContext);
-
switch (BreakCause) {
case DEBUG_DATA_BREAK_CAUSE_SYSTEM_RESET:
- if (AttachHost (INIT_BREAK_ACK_TIMEOUT, &BreakReceived) != RETURN_SUCCESS) {
+ if (AttachHost (BreakCause, READ_PACKET_TIMEOUT, &BreakReceived) != RETURN_SUCCESS) {
//
// Try to connect HOST, return if fails
//
@@ -1608,7 +1952,7 @@ InterruptProcess (
//
// Stepping is finished, send Ack package.
//
- if (MultiProcessorDebugSupport) {
+ if (MultiProcessorDebugSupport()) {
mDebugMpContext.BreakAtCpuIndex = ProcessorIndex;
}
SendAckPacket (DEBUG_COMMAND_OK);
@@ -1619,7 +1963,7 @@ InterruptProcess (
//
// Memory is ready
//
- SendCommandAndWaitForAckOK (DEBUG_COMMAND_MEMORY_READY, 0, &BreakReceived, NULL);
+ SendCommandAndWaitForAckOK (DEBUG_COMMAND_MEMORY_READY, READ_PACKET_TIMEOUT, &BreakReceived, NULL);
CommandCommunication (Vector, CpuContext, BreakReceived);
break;
@@ -1647,14 +1991,14 @@ InterruptProcess (
//
// Send Break packet to HOST
//
- AcquireDebugPortControl ();
+ AcquireMpSpinLock (&mDebugMpContext.DebugPortSpinLock);
//
// Only the first breaking processor could send BREAK_POINT to HOST
//
if (IsFirstBreakProcessor (ProcessorIndex)) {
- SendBreakPacketToHost (ProcessorIndex, &BreakReceived);
+ SendBreakPacketToHost (BreakCause, ProcessorIndex, &BreakReceived);
}
- ReleaseDebugPortControl ();
+ ReleaseMpSpinLock (&mDebugMpContext.DebugPortSpinLock);
if (Vector == DEBUG_INT3_VECTOR) {
//
@@ -1681,9 +2025,9 @@ InterruptProcess (
case DEBUG_TIMER_VECTOR:
- AcquireDebugPortControl ();
+ AcquireMpSpinLock (&mDebugMpContext.DebugPortSpinLock);
- if (MultiProcessorDebugSupport) {
+ if (MultiProcessorDebugSupport()) {
if (IsBsp (ProcessorIndex)) {
//
// If current processor is BSP, check Apic timer's init count if changed,
@@ -1697,7 +2041,7 @@ InterruptProcess (
}
if (!IsBsp (ProcessorIndex) || mDebugMpContext.IpiSentByAp) {
- ReleaseDebugPortControl ();
+ ReleaseMpSpinLock (&mDebugMpContext.DebugPortSpinLock);
//
// If current processor is not BSP or this is one IPI sent by AP
//
@@ -1725,8 +2069,10 @@ InterruptProcess (
if (DebugReadBreakSymbol (Handle, &InputCharacter) == EFI_NOT_FOUND) {
break;
}
+
if ((!IsHostAttached () && (InputCharacter == DEBUG_STARTING_SYMBOL_ATTACH)) ||
- (IsHostAttached () && (InputCharacter == DEBUG_STARTING_SYMBOL_BREAK))
+ (IsHostAttached () && (InputCharacter == DEBUG_COMMAND_HALT)) ||
+ (IsHostAttached () && (InputCharacter == DEBUG_COMMAND_GO))
) {
DebugAgentMsgPrint (DEBUG_AGENT_VERBOSE, "Received data [%02x]\n", InputCharacter);
//
@@ -1734,25 +2080,32 @@ InterruptProcess (
//
SendAckPacket (DEBUG_COMMAND_OK);
+ //
+ // If receive GO command in Debug Timer, means HOST may lost ACK packet before.
+ //
+ if (InputCharacter == DEBUG_COMMAND_GO) {
+ break;
+ }
+
if (!IsHostAttached ()) {
//
// Try to attach HOST, if no ack received after 200ms, return
//
- if (AttachHost (INIT_BREAK_ACK_TIMEOUT, &BreakReceived) != RETURN_SUCCESS) {
+ if (AttachHost (BreakCause, READ_PACKET_TIMEOUT, &BreakReceived) != RETURN_SUCCESS) {
break;
}
}
- if (MultiProcessorDebugSupport) {
+ if (MultiProcessorDebugSupport()) {
if(FindNextPendingBreakCpu () != -1) {
SetCpuBreakFlagByIndex (ProcessorIndex, TRUE);
} else {
HaltOtherProcessors (ProcessorIndex);
}
}
- ReleaseDebugPortControl ();
+ ReleaseMpSpinLock (&mDebugMpContext.DebugPortSpinLock);
CommandCommunication (Vector, CpuContext, BreakReceived);
- AcquireDebugPortControl ();
+ AcquireMpSpinLock (&mDebugMpContext.DebugPortSpinLock);
break;
}
}
@@ -1762,19 +2115,17 @@ InterruptProcess (
//
SendApicEoi ();
- ReleaseDebugPortControl ();
+ ReleaseMpSpinLock (&mDebugMpContext.DebugPortSpinLock);
break;
default:
-
if (Vector <= DEBUG_EXCEPT_SIMD) {
- BreakCause = GetBreakCause (Vector, CpuContext);
if (BreakCause == DEBUG_DATA_BREAK_CAUSE_STEPPING) {
//
// Stepping is finished, send Ack package.
//
- if (MultiProcessorDebugSupport) {
+ if (MultiProcessorDebugSupport()) {
mDebugMpContext.BreakAtCpuIndex = ProcessorIndex;
}
SendAckPacket (DEBUG_COMMAND_OK);
@@ -1782,14 +2133,14 @@ InterruptProcess (
//
// Exception occurs, send Break packet to HOST
//
- AcquireDebugPortControl ();
+ AcquireMpSpinLock (&mDebugMpContext.DebugPortSpinLock);
//
// Only the first breaking processor could send BREAK_POINT to HOST
//
if (IsFirstBreakProcessor (ProcessorIndex)) {
- SendBreakPacketToHost (ProcessorIndex, &BreakReceived);
+ SendBreakPacketToHost (BreakCause, ProcessorIndex, &BreakReceived);
}
- ReleaseDebugPortControl ();
+ ReleaseMpSpinLock (&mDebugMpContext.DebugPortSpinLock);
}
CommandCommunication (Vector, CpuContext, BreakReceived);
@@ -1797,7 +2148,7 @@ InterruptProcess (
break;
}
- if (MultiProcessorDebugSupport) {
+ if (MultiProcessorDebugSupport()) {
//
// Clear flag and wait for all processors run here
//
@@ -1814,11 +2165,11 @@ InterruptProcess (
}
}
- if (IssuedViewPoint == ProcessorIndex) {
+ if (IssuedViewPoint == ProcessorIndex && GetDebugFlag (DEBUG_AGENT_FLAG_STEPPING) != 1) {
//
- // Clean up AgentInProgress flag
+ // If the command is not stepping, clean up AgentInProgress flag
//
- GetMailboxPointer()->DebugFlag.AgentInProgress = 0;
+ SetDebugFlag (DEBUG_AGENT_FLAG_AGENT_IN_PROGRESS, 0);
}
return;
diff --git a/SourceLevelDebugPkg/Library/DebugAgent/DebugAgentCommon/DebugAgent.h b/SourceLevelDebugPkg/Library/DebugAgent/DebugAgentCommon/DebugAgent.h
index 61448448d4..5eb50d038c 100644
--- a/SourceLevelDebugPkg/Library/DebugAgent/DebugAgentCommon/DebugAgent.h
+++ b/SourceLevelDebugPkg/Library/DebugAgent/DebugAgentCommon/DebugAgent.h
@@ -1,7 +1,7 @@
/** @file
Command header of for Debug Agent library instance.
- Copyright (c) 2010 - 2012, Intel Corporation. All rights reserved.<BR>
+ Copyright (c) 2010 - 2013, 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
@@ -32,6 +32,8 @@
#include <Library/DebugLib.h>
#include <Library/TimerLib.h>
#include <Library/PrintLib.h>
+#include <Library/PeCoffGetEntryPointLib.h>
+#include <Library/PeCoffExtraActionLib.h>
#include <TransferProtocol.h>
#include <ImageDebugSupport.h>
@@ -40,11 +42,24 @@
#include "DebugTimer.h"
#include "ArchDebugSupport.h"
+//
+// These macros may be already defined in DebugAgentLib.h
+//
+#define DEBUG_AGENT_INIT_PEI 9
+#define DEBUG_AGENT_INIT_DXE_LOAD 10
+#define DEBUG_AGENT_INIT_DXE_UNLOAD 11
+#define DEBUG_AGENT_INIT_THUNK_PEI_IA32TOX64 12
+
#define DEBUG_INT1_VECTOR 1
#define DEBUG_INT3_VECTOR 3
#define DEBUG_TIMER_VECTOR 32
#define DEBUG_MAILBOX_VECTOR 33
+//
+// Timeout value for reading packet (unit is microsecond)
+//
+#define READ_PACKET_TIMEOUT (500 * 1000)
+
#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')
@@ -53,6 +68,8 @@ extern UINTN Exception0Handle;
extern UINTN TimerInterruptHandle;
extern UINT16 ExceptionStubHeaderSize;
+extern BOOLEAN mSkipBreakpoint;
+
//
// CPU exception information issued by debug agent
//
@@ -67,23 +84,44 @@ typedef struct {
DEBUG_DATA_RESPONSE_GET_EXCEPTION ExceptionContent;
} DEBUG_AGENT_EXCEPTION_BUFFER;
-#pragma pack(1)
-typedef struct {
- //
- // Lower 32 bits to store the status of DebugAgent
- //
- UINT32 HostAttached : 1; // 1: HOST is attached
- UINT32 AgentInProgress : 1; // 1: Debug Agent is communicating with HOST
- UINT32 MemoryReady : 1; // 1: Memory is ready
- UINT32 SteppingFlag : 1; // 1: Agent is running stepping command
- UINT32 Reserved1 : 28;
+#define DEBUG_AGENT_FLAG_HOST_ATTACHED BIT0
+#define DEBUG_AGENT_FLAG_AGENT_IN_PROGRESS BIT1
+#define DEBUG_AGENT_FLAG_MEMORY_READY BIT2
+#define DEBUG_AGENT_FLAG_STEPPING BIT3
+#define DEBUG_AGENT_FLAG_CHECK_MAILBOX_IN_HOB BIT4
+#define DEBUG_AGENT_FLAG_BREAK_ON_NEXT_SMI BIT32
+#define DEBUG_AGENT_FLAG_PRINT_ERROR_LEVEL (BIT33|BIT34|BIT35|BIT36)
+#define DEBUG_AGENT_FLAG_BREAK_BOOT_SCRIPT BIT37
+
+#define DEBUG_MAILBOX_DEBUG_FLAG_INDEX 1
+#define DEBUG_MAILBOX_DEBUG_PORT_HANDLE_INDEX 2
+#define DEBUG_MAILBOX_EXCEPTION_BUFFER_POINTER_INDEX 3
+#define DEBUG_MAILBOX_LAST_ACK 4
+#define DEBUG_MAILBOX_SEQUENCE_NO_INDEX 5
+#define DEBUG_MAILBOX_HOST_SEQUENCE_NO_INDEX 6
- //
- // Higher 32bits to control the behavior of DebugAgent
- //
- UINT32 BreakOnNextSmi : 1; // 1: Break on next SMI
- UINT32 PrintErrorLevel : 8; // Bitmask of print error level for debug message
- UINT32 Reserved2 : 23;
+#pragma pack(1)
+typedef union {
+ struct {
+ //
+ // Lower 32 bits to store the status of DebugAgent
+ //
+ UINT32 HostAttached : 1; // 1: HOST is attached
+ UINT32 AgentInProgress : 1; // 1: Debug Agent is communicating with HOST
+ UINT32 MemoryReady : 1; // 1: Memory is ready
+ UINT32 SteppingFlag : 1; // 1: Agent is running stepping command
+ UINT32 CheckMailboxInHob : 1; // 1: Need to check mailbox saved in HOB
+ UINT32 SendingPacket : 1; // 1: TARGET is sending debug packet to HOST
+ UINT32 Reserved1 : 26;
+ //
+ // Higher 32bits to control the behavior of DebugAgent
+ //
+ UINT32 BreakOnNextSmi : 1; // 1: Break on next SMI
+ UINT32 PrintErrorLevel : 4; // Bitmask of print error level for debug message
+ UINT32 BreakOnBootScript : 1; // 1: Break before executing boot script
+ UINT32 Reserved2 : 26;
+ } Bits;
+ UINT64 Uint64;
} DEBUG_AGENT_FLAG;
typedef struct {
@@ -93,9 +131,29 @@ typedef struct {
// Pointer to DEBUG_AGENT_EXCEPTION_BUFFER
//
UINT64 ExceptionBufferPointer;
+ UINT8 LastAck; // The last ack packet type
+ UINT8 SequenceNo;
+ UINT8 HostSequenceNo;
+ UINT8 CheckSum; // Mailbox checksum
+ UINT8 ToBeCheckSum; // To be Mailbox checksum at the next
} DEBUG_AGENT_MAILBOX;
#pragma pack()
+///
+/// Byte packed structure for an IA-32 Interrupt Gate Descriptor.
+///
+typedef union {
+ struct {
+ UINT32 OffsetLow:16; ///< Offset bits 15..0.
+ UINT32 Selector:16; ///< Selector.
+ UINT32 Reserved_0:8; ///< Reserved.
+ UINT32 GateType:8; ///< Gate Type. See #defines above.
+ UINT32 OffsetHigh:16; ///< Offset bits 31..16.
+ } Bits;
+ UINT64 Uint64;
+} IA32_IDT_ENTRY;
+
+
typedef union {
struct {
UINT32 LimitLow : 16;
@@ -116,22 +174,6 @@ typedef union {
} 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.
**/
@@ -242,5 +284,184 @@ DebugAgentMsgPrint (
IN CHAR8 *Format,
...
);
+
+/**
+ Trigger one software interrupt to debug agent to handle it.
+
+ @param[in] Signature Software interrupt signature.
+
+**/
+VOID
+TriggerSoftInterrupt (
+ IN UINT32 Signature
+ );
+
+/**
+ Check if debug agent support multi-processor.
+
+ @retval TRUE Multi-processor is supported.
+ @retval FALSE Multi-processor is not supported.
+
+**/
+BOOLEAN
+MultiProcessorDebugSupport (
+ VOID
+ );
+
+/**
+ Find and report module image info to HOST.
+
+ @param[in] AlignSize Image aligned size.
+
+**/
+VOID
+FindAndReportModuleImageInfo (
+ IN UINTN AlignSize
+ );
+
+/**
+ Read IDT entry to check if IDT entries are setup by Debug Agent.
+
+ @retval TRUE IDT entries were setup by Debug Agent.
+ @retval FALSE IDT entries were not setup by Debug Agent.
+
+**/
+BOOLEAN
+IsDebugAgentInitialzed (
+ VOID
+ );
+
+/**
+ Caculate Mailbox checksum and update the checksum field.
+
+ @param[in] Mailbox Debug Agent Mailbox pointer.
+
+**/
+VOID
+UpdateMailboxChecksum (
+ IN DEBUG_AGENT_MAILBOX *Mailbox
+ );
+
+/**
+ Verify Mailbox checksum.
+
+ If checksum error, print debug message and run init dead loop.
+
+ @param[in] Mailbox Debug Agent Mailbox pointer.
+
+**/
+VOID
+VerifyMailboxChecksum (
+ IN DEBUG_AGENT_MAILBOX *Mailbox
+ );
+
+/**
+ Set debug flag in mailbox.
+
+ @param[in] FlagMask Debug flag mask value.
+ @param[in] FlagValue Debug flag value.
+
+**/
+VOID
+SetDebugFlag (
+ IN UINT64 FlagMask,
+ IN UINT32 FlagValue
+ );
+
+/**
+ Get debug flag in mailbox.
+
+ @param[in] FlagMask Debug flag mask value.
+
+ @return Debug flag value.
+
+**/
+UINT32
+GetDebugFlag (
+ IN UINT64 FlagMask
+ );
+
+/**
+ Update Mailbox content by index.
+
+ @param[in] Mailbox Debug Agent Mailbox pointer.
+ @param[in] Index Mailbox content index.
+ @param[in] Value Value to be set into mail box.
+
+**/
+VOID
+UpdateMailboxContent (
+ IN DEBUG_AGENT_MAILBOX *Mailbox,
+ IN UINTN Index,
+ IN UINT64 Value
+ );
+
+/**
+ Retrieve exception handler from IDT table by ExceptionNum.
+
+ @param[in] ExceptionNum Exception number
+
+ @return Exception handler
+
+**/
+VOID *
+GetExceptionHandlerInIdtEntry (
+ IN UINTN ExceptionNum
+ );
+
+/**
+ Set exception handler in IDT table by ExceptionNum.
+
+ @param[in] ExceptionNum Exception number
+ @param[in] ExceptionHandler Exception Handler to be set
+
+**/
+VOID
+SetExceptionHandlerInIdtEntry (
+ IN UINTN ExceptionNum,
+ IN VOID *ExceptionHandler
+ );
+
+/**
+ Prints a debug message to the debug output device if the specified error level is enabled.
+
+ If any bit in ErrorLevel is also set in DebugPrintErrorLevelLib function
+ GetDebugPrintErrorLevel (), then print the message specified by Format and the
+ associated variable argument list to the debug output device.
+
+ If Format is NULL, then ASSERT().
+
+ @param[in] ErrorLevel The error level of the debug message.
+ @param[in] IsSend Flag of debug message to declare that the data is being sent or being received.
+ @param[in] Data Variable argument list whose contents are accessed
+ @param[in] Length based on the format string specified by Format.
+
+**/
+VOID
+EFIAPI
+DebugAgentDataMsgPrint (
+ IN UINT8 ErrorLevel,
+ IN BOOLEAN IsSend,
+ IN UINT8 *Data,
+ IN UINT8 Length
+ );
+
+/**
+ Read remaing debug packet except for the start symbol
+
+ @param[in] Handle Pointer to Debug Port handle.
+ @param[in, out] DebugHeader Debug header buffer including start symbol.
+
+ @retval EFI_SUCCESS Read the symbol in BreakSymbol.
+ @retval EFI_CRC_ERROR CRC check fail.
+ @retval EFI_TIMEOUT Timeout occurs when reading debug packet.
+
+**/
+EFI_STATUS
+ReadRemainingBreakPacket (
+ IN DEBUG_PORT_HANDLE Handle,
+ IN OUT DEBUG_PACKET_HEADER *DebugHeader
+ );
+
#endif
diff --git a/SourceLevelDebugPkg/Library/DebugAgent/DebugAgentCommon/DebugMp.c b/SourceLevelDebugPkg/Library/DebugAgent/DebugAgentCommon/DebugMp.c
index d7df6ad20d..6c729986cd 100644
--- a/SourceLevelDebugPkg/Library/DebugAgent/DebugAgentCommon/DebugMp.c
+++ b/SourceLevelDebugPkg/Library/DebugAgent/DebugAgentCommon/DebugMp.c
@@ -1,7 +1,7 @@
/** @file
Multi-Processor support functions implementation.
- Copyright (c) 2010 - 2012, Intel Corporation. All rights reserved.<BR>
+ Copyright (c) 2010 - 2013, 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
@@ -14,27 +14,30 @@
#include "DebugAgent.h"
-DEBUG_MP_CONTEXT volatile mDebugMpContext = {0,0,{0},{0},0,0,0,0,FALSE,FALSE};
+DEBUG_MP_CONTEXT volatile mDebugMpContext = {0,0,0,{0},{0},0,0,0,0,FALSE,FALSE};
DEBUG_CPU_DATA volatile mDebugCpuData = {0};
/**
- Acquire access control on debug port.
+ Acquire a spin lock when Multi-processor supported.
It will block in the function if cannot get the access control.
+ If Multi-processor is not supported, return directly.
+
+ @param[in, out] MpSpinLock A pointer to the spin lock.
**/
VOID
-AcquireDebugPortControl (
- VOID
+AcquireMpSpinLock (
+ IN OUT SPIN_LOCK *MpSpinLock
)
{
- if (!MultiProcessorDebugSupport) {
+ if (!MultiProcessorDebugSupport()) {
return;
}
while (TRUE) {
- if (AcquireSpinLockOrFail (&mDebugMpContext.DebugPortSpinLock)) {
+ if (AcquireSpinLockOrFail (MpSpinLock)) {
break;
}
CpuPause ();
@@ -43,51 +46,21 @@ AcquireDebugPortControl (
}
/**
- Release access control on debug port.
-
-**/
-VOID
-ReleaseDebugPortControl (
- VOID
- )
-{
- if (!MultiProcessorDebugSupport) {
- return;
- }
-
- ReleaseSpinLock (&mDebugMpContext.DebugPortSpinLock);
-}
-
-/**
- Acquire access control on MP context.
+ Release a spin lock when Multi-processor supported.
- It will block in the function if cannot get the access control.
+ @param[in, out] MpSpinLock A pointer to the spin lock.
**/
VOID
-AcquireMpContextControl (
- VOID
+ReleaseMpSpinLock (
+ IN OUT SPIN_LOCK *MpSpinLock
)
{
- while (TRUE) {
- if (AcquireSpinLockOrFail (&mDebugMpContext.MpContextSpinLock)) {
- break;
- }
- CpuPause ();
- continue;
+ if (!MultiProcessorDebugSupport()) {
+ return;
}
-}
-/**
- Release access control on MP context.
-
-**/
-VOID
-ReleaseMpContextControl (
- VOID
- )
-{
- ReleaseSpinLock (&mDebugMpContext.MpContextSpinLock);
+ ReleaseSpinLock (MpSpinLock);
}
/**
@@ -136,7 +109,7 @@ GetProcessorIndex (
LocalApicID = (UINT16) GetApicId ();
- AcquireMpContextControl ();
+ AcquireMpSpinLock (&mDebugMpContext.MpContextSpinLock);
for (Index = 0; Index < mDebugCpuData.CpuCount; Index ++) {
if (mDebugCpuData.ApicID[Index] == LocalApicID) {
@@ -149,7 +122,7 @@ GetProcessorIndex (
mDebugCpuData.CpuCount ++ ;
}
- ReleaseMpContextControl ();
+ ReleaseMpSpinLock (&mDebugMpContext.MpContextSpinLock);
return Index;
}
@@ -170,9 +143,9 @@ IsBsp (
{
if (AsmMsrBitFieldRead64 (MSR_IA32_APIC_BASE_ADDRESS, 8, 8) == 1) {
if (mDebugMpContext.BspIndex != ProcessorIndex) {
- AcquireMpContextControl ();
+ AcquireMpSpinLock (&mDebugMpContext.MpContextSpinLock);
mDebugMpContext.BspIndex = ProcessorIndex;
- ReleaseMpContextControl ();
+ ReleaseMpSpinLock (&mDebugMpContext.MpContextSpinLock);
}
return TRUE;
} else {
@@ -197,7 +170,7 @@ SetCpuStopFlagByIndex (
UINT8 Value;
UINTN Index;
- AcquireMpContextControl ();
+ AcquireMpSpinLock (&mDebugMpContext.MpContextSpinLock);
Value = mDebugMpContext.CpuStopStatusMask[ProcessorIndex / 8];
Index = ProcessorIndex % 8;
@@ -208,7 +181,7 @@ SetCpuStopFlagByIndex (
}
mDebugMpContext.CpuStopStatusMask[ProcessorIndex / 8] = Value;
- ReleaseMpContextControl ();
+ ReleaseMpSpinLock (&mDebugMpContext.MpContextSpinLock);
}
/**
@@ -228,7 +201,7 @@ SetCpuBreakFlagByIndex (
UINT8 Value;
UINTN Index;
- AcquireMpContextControl ();
+ AcquireMpSpinLock (&mDebugMpContext.MpContextSpinLock);
Value = mDebugMpContext.CpuBreakMask[ProcessorIndex / 8];
Index = ProcessorIndex % 8;
@@ -239,7 +212,7 @@ SetCpuBreakFlagByIndex (
}
mDebugMpContext.CpuBreakMask[ProcessorIndex / 8] = Value;
- ReleaseMpContextControl ();
+ ReleaseMpSpinLock (&mDebugMpContext.MpContextSpinLock);
}
/**
@@ -279,11 +252,9 @@ SetCpuRunningFlag (
IN BOOLEAN RunningFlag
)
{
- AcquireMpContextControl ();
-
+ AcquireMpSpinLock (&mDebugMpContext.MpContextSpinLock);
mDebugMpContext.RunCommandSet = RunningFlag;
-
- ReleaseMpContextControl ();
+ ReleaseMpSpinLock (&mDebugMpContext.MpContextSpinLock);
}
/**
@@ -297,11 +268,9 @@ SetDebugViewPoint (
IN UINT32 ProcessorIndex
)
{
- AcquireMpContextControl ();
-
+ AcquireMpSpinLock (&mDebugMpContext.MpContextSpinLock);
mDebugMpContext.ViewPointIndex = ProcessorIndex;
-
- ReleaseMpContextControl ();
+ ReleaseMpSpinLock (&mDebugMpContext.MpContextSpinLock);
}
/**
@@ -316,11 +285,9 @@ SetIpiSentByApFlag (
IN BOOLEAN IpiSentByApFlag
)
{
- AcquireMpContextControl ();
-
+ AcquireMpSpinLock (&mDebugMpContext.MpContextSpinLock);
mDebugMpContext.IpiSentByAp = IpiSentByApFlag;
-
- ReleaseMpContextControl ();
+ ReleaseMpSpinLock (&mDebugMpContext.MpContextSpinLock);
}
/**
@@ -384,7 +351,7 @@ IsFirstBreakProcessor (
IN UINT32 ProcessorIndex
)
{
- if (MultiProcessorDebugSupport) {
+ if (MultiProcessorDebugSupport()) {
if (mDebugMpContext.BreakAtCpuIndex != (UINT32) -1) {
//
// The current processor is not the first breaking one.
diff --git a/SourceLevelDebugPkg/Library/DebugAgent/DebugAgentCommon/DebugMp.h b/SourceLevelDebugPkg/Library/DebugAgent/DebugAgentCommon/DebugMp.h
index 183887cc9f..5bb50960ca 100644
--- a/SourceLevelDebugPkg/Library/DebugAgent/DebugAgentCommon/DebugMp.h
+++ b/SourceLevelDebugPkg/Library/DebugAgent/DebugAgentCommon/DebugMp.h
@@ -1,7 +1,7 @@
/** @file
Header file for Multi-Processor support.
- Copyright (c) 2010 - 2012, Intel Corporation. All rights reserved.<BR>
+ Copyright (c) 2010 - 2013, 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
@@ -25,6 +25,7 @@ typedef struct {
typedef struct {
SPIN_LOCK MpContextSpinLock; ///< Lock for writting MP context
SPIN_LOCK DebugPortSpinLock; ///< Lock for access debug port
+ SPIN_LOCK MailboxSpinLock; ///< Lock for accessing mail box
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
@@ -35,7 +36,6 @@ typedef struct {
BOOLEAN RunCommandSet; ///< TRUE: RUN commmand is executing. FALSE : RUN command has been executed.
} DEBUG_MP_CONTEXT;
-extern CONST BOOLEAN MultiProcessorDebugSupport;
extern DEBUG_MP_CONTEXT volatile mDebugMpContext;
extern DEBUG_CPU_DATA volatile mDebugCpuData;
@@ -62,43 +62,28 @@ GetProcessorIndex (
);
/**
- Acquire access control on MP context.
+ Acquire a spin lock when Multi-processor supported.
It will block in the function if cannot get the access control.
+ If Multi-processor is not supported, return directly.
-**/
-VOID
-AcquireMpContextControl (
- VOID
- );
-
-/**
- Release access control on MP context.
+ @param[in, out] MpSpinLock A pointer to the spin lock.
**/
VOID
-ReleaseMpContextControl (
- VOID
+AcquireMpSpinLock (
+ IN OUT SPIN_LOCK *MpSpinLock
);
/**
- Acquire access control on debug port.
-
- It will block in the function if cannot get the access control.
-
-**/
-VOID
-AcquireDebugPortControl (
- VOID
- );
+ Release a spin lock when Multi-processor supported.
-/**
- Release access control on debug port.
+ @param[in, out] MpSpinLock A pointer to the spin lock.
**/
VOID
-ReleaseDebugPortControl (
- VOID
+ReleaseMpSpinLock (
+ IN OUT SPIN_LOCK *MpSpinLock
);
/**
diff --git a/SourceLevelDebugPkg/Library/DebugAgent/DebugAgentCommon/DebugTimer.c b/SourceLevelDebugPkg/Library/DebugAgent/DebugAgentCommon/DebugTimer.c
index d473df8678..01fc4841f5 100644
--- a/SourceLevelDebugPkg/Library/DebugAgent/DebugAgentCommon/DebugTimer.c
+++ b/SourceLevelDebugPkg/Library/DebugAgent/DebugAgentCommon/DebugTimer.c
@@ -1,7 +1,7 @@
/** @file
Code for debug timer to support debug agent library implementation.
- Copyright (c) 2010, Intel Corporation. All rights reserved.<BR>
+ Copyright (c) 2010 - 2013, 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
@@ -41,7 +41,7 @@ InitializeDebugTimer (
InitializeApicTimer (ApicTimerDivisor, InitialCount, TRUE, DEBUG_TIMER_VECTOR);
- if (MultiProcessorDebugSupport) {
+ if (MultiProcessorDebugSupport()) {
mDebugMpContext.DebugTimerInitCount = InitialCount;
}
}
@@ -65,19 +65,26 @@ SaveAndSetDebugTimerInterrupt (
IN BOOLEAN EnableStatus
)
{
- BOOLEAN OldInterruptState;
BOOLEAN OldDebugTimerInterruptState;
- OldInterruptState = SaveAndDisableInterrupts ();
OldDebugTimerInterruptState = GetApicTimerInterruptState ();
- if (EnableStatus) {
- EnableApicTimerInterrupt ();
- } else {
- DisableApicTimerInterrupt ();
+ if (OldDebugTimerInterruptState != EnableStatus) {
+ if (EnableStatus) {
+ EnableApicTimerInterrupt ();
+ } else {
+ DisableApicTimerInterrupt ();
+ }
+ //
+ // Validate the Debug Timer interrupt state
+ // This will make additional delay after Local Apic Timer interrupt state is changed.
+ // Thus, CPU could handle the potential pending interrupt of Local Apic timer.
+ //
+ while (GetApicTimerInterruptState () != EnableStatus) {
+ CpuPause ();
+ }
}
-
- SetInterruptState (OldInterruptState);
+
return OldDebugTimerInterruptState;
}
diff --git a/SourceLevelDebugPkg/Library/DebugAgent/DebugAgentCommon/Ia32/ArchDebugSupport.c b/SourceLevelDebugPkg/Library/DebugAgent/DebugAgentCommon/Ia32/ArchDebugSupport.c
index 52ed647a27..9bd8fca6b6 100644
--- a/SourceLevelDebugPkg/Library/DebugAgent/DebugAgentCommon/Ia32/ArchDebugSupport.c
+++ b/SourceLevelDebugPkg/Library/DebugAgent/DebugAgentCommon/Ia32/ArchDebugSupport.c
@@ -1,7 +1,7 @@
/** @file
Supporting functions for IA32 architecture.
- Copyright (c) 2010 - 2012, Intel Corporation. All rights reserved.<BR>
+ Copyright (c) 2010 - 2013, 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
@@ -39,17 +39,17 @@ InitializeDebugIdt (
IdtEntry = (IA32_IDT_GATE_DESCRIPTOR *) IdtDescriptor.Base;
for (Index = 0; Index < 20; Index ++) {
- if ((PcdGet32 (PcdExceptionsIgnoredByDebugger) & (1 << Index)) != 0) {
+ if (((PcdGet32 (PcdExceptionsIgnoredByDebugger) & ~(BIT1 | BIT3)) & (1 << Index)) != 0) {
//
- // If the exception is masked to be reserved, skip it
+ // If the exception is masked to be reserved except for INT1 and INT3, 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;
+ IdtEntry[Index].Bits.Selector = CodeSegment;
+ IdtEntry[Index].Bits.GateType = IA32_IDT_GATE_TYPE_INTERRUPT_32;
}
InterruptHandler = (UINTN) &TimerInterruptHandle;
@@ -63,3 +63,49 @@ InitializeDebugIdt (
//
AsmWriteCr4 (AsmReadCr4 () | BIT3);
}
+
+/**
+ Retrieve exception handler from IDT table by ExceptionNum.
+
+ @param[in] ExceptionNum Exception number
+
+ @return Exception handler
+
+**/
+VOID *
+GetExceptionHandlerInIdtEntry (
+ IN UINTN ExceptionNum
+ )
+{
+ IA32_IDT_GATE_DESCRIPTOR *IdtEntry;
+ IA32_DESCRIPTOR IdtDescriptor;
+
+ AsmReadIdtr (&IdtDescriptor);
+ IdtEntry = (IA32_IDT_GATE_DESCRIPTOR *) IdtDescriptor.Base;
+
+ return (VOID *) (((UINTN)IdtEntry[ExceptionNum].Bits.OffsetLow) |
+ (((UINTN)IdtEntry[ExceptionNum].Bits.OffsetHigh) << 16));
+}
+
+/**
+ Set exception handler in IDT table by ExceptionNum.
+
+ @param[in] ExceptionNum Exception number
+ @param[in] ExceptionHandler Exception Handler to be set
+
+**/
+VOID
+SetExceptionHandlerInIdtEntry (
+ IN UINTN ExceptionNum,
+ IN VOID *ExceptionHandler
+ )
+{
+ IA32_IDT_GATE_DESCRIPTOR *IdtEntry;
+ IA32_DESCRIPTOR IdtDescriptor;
+
+ AsmReadIdtr (&IdtDescriptor);
+ IdtEntry = (IA32_IDT_GATE_DESCRIPTOR *) IdtDescriptor.Base;
+
+ IdtEntry[ExceptionNum].Bits.OffsetLow = (UINT16)(UINTN)ExceptionHandler;
+ IdtEntry[ExceptionNum].Bits.OffsetHigh = (UINT16)((UINTN)ExceptionHandler >> 16);
+}
diff --git a/SourceLevelDebugPkg/Library/DebugAgent/DebugAgentCommon/Ia32/AsmFuncs.S b/SourceLevelDebugPkg/Library/DebugAgent/DebugAgentCommon/Ia32/AsmFuncs.S
index cfeeea0472..e05317aaf8 100644
--- a/SourceLevelDebugPkg/Library/DebugAgent/DebugAgentCommon/Ia32/AsmFuncs.S
+++ b/SourceLevelDebugPkg/Library/DebugAgent/DebugAgentCommon/Ia32/AsmFuncs.S
@@ -1,6 +1,6 @@
#------------------------------------------------------------------------------
#
-# Copyright (c) 2010 - 2012, Intel Corporation. All rights reserved.<BR>
+# Copyright (c) 2010 - 2013, 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
@@ -33,6 +33,7 @@ ASM_PFX(ExceptionStubHeaderSize): .word ASM_PFX(Exception1Handle) - ASM_PFX
.text
+.byte 0x41, 0x47, 0x54, 0x48 # AGENT_HANDLER_SIGNATURE SIGNATURE_32('A','G','T','H')
ASM_PFX(Exception0Handle):
cli
pushl %eax
@@ -259,7 +260,7 @@ NoExtrPush:
pushl %eax
## clear Dr7 while executing debugger itself
xorl %eax,%eax
-# movl %eax, %dr7
+ movl %eax, %dr7
movl %dr6, %eax
pushl %eax
diff --git a/SourceLevelDebugPkg/Library/DebugAgent/DebugAgentCommon/Ia32/AsmFuncs.asm b/SourceLevelDebugPkg/Library/DebugAgent/DebugAgentCommon/Ia32/AsmFuncs.asm
index 6f3b3bc3d4..c80a33ba6c 100644
--- a/SourceLevelDebugPkg/Library/DebugAgent/DebugAgentCommon/Ia32/AsmFuncs.asm
+++ b/SourceLevelDebugPkg/Library/DebugAgent/DebugAgentCommon/Ia32/AsmFuncs.asm
@@ -1,6 +1,6 @@
;------------------------------------------------------------------------------
;
-; Copyright (c) 2010 - 2012, Intel Corporation. All rights reserved.<BR>
+; Copyright (c) 2010 - 2013, 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
@@ -39,6 +39,7 @@ CommonEntryAddr DD CommonEntry
.code
+db 41h, 47h, 54h, 48h ; AGENT_HANDLER_SIGNATURE SIGNATURE_32('A','G','T','H')
Exception0Handle:
cli
push eax
@@ -259,7 +260,7 @@ NoExtrPush:
;; clear Dr7 while executing debugger itself
xor eax, eax
- ;; mov dr7, eax
+ mov dr7, eax
;; Dr6
mov eax, dr6
diff --git a/SourceLevelDebugPkg/Library/DebugAgent/DebugAgentCommon/X64/ArchDebugSupport.c b/SourceLevelDebugPkg/Library/DebugAgent/DebugAgentCommon/X64/ArchDebugSupport.c
index 9803f0f76f..60d3eb8bb3 100644
--- a/SourceLevelDebugPkg/Library/DebugAgent/DebugAgentCommon/X64/ArchDebugSupport.c
+++ b/SourceLevelDebugPkg/Library/DebugAgent/DebugAgentCommon/X64/ArchDebugSupport.c
@@ -1,7 +1,7 @@
/** @file
Supporting functions for X64 architecture.
- Copyright (c) 2010 - 2012, Intel Corporation. All rights reserved.<BR>
+ Copyright (c) 2010 - 2013, 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
@@ -39,9 +39,9 @@ InitializeDebugIdt (
IdtEntry = (IA32_IDT_GATE_DESCRIPTOR *) IdtDescriptor.Base;
for (Index = 0; Index < 20; Index ++) {
- if ((PcdGet32 (PcdExceptionsIgnoredByDebugger) & (1 << Index)) != 0) {
+ if (((PcdGet32 (PcdExceptionsIgnoredByDebugger) & ~(BIT1 | BIT3)) & (1 << Index)) != 0) {
//
- // If the exception is masked to be reserved, skip it
+ // If the exception is masked to be reserved except for INT1 and INT3, skip it
//
continue;
}
@@ -65,3 +65,51 @@ InitializeDebugIdt (
//
AsmWriteCr4 (AsmReadCr4 () | BIT3);
}
+
+/**
+ Retrieve exception handler from IDT table by ExceptionNum.
+
+ @param[in] ExceptionNum Exception number
+
+ @return Exception handler
+
+**/
+VOID *
+GetExceptionHandlerInIdtEntry (
+ IN UINTN ExceptionNum
+ )
+{
+ IA32_IDT_GATE_DESCRIPTOR *IdtEntry;
+ IA32_DESCRIPTOR IdtDescriptor;
+
+ AsmReadIdtr (&IdtDescriptor);
+ IdtEntry = (IA32_IDT_GATE_DESCRIPTOR *) IdtDescriptor.Base;
+
+ return (VOID *) (IdtEntry[ExceptionNum].Bits.OffsetLow |
+ (((UINTN)IdtEntry[ExceptionNum].Bits.OffsetHigh) << 16) |
+ (((UINTN)IdtEntry[ExceptionNum].Bits.OffsetUpper) << 32));
+}
+
+/**
+ Set exception handler in IDT table by ExceptionNum.
+
+ @param[in] ExceptionNum Exception number
+ @param[in] ExceptionHandler Exception Handler to be set
+
+**/
+VOID
+SetExceptionHandlerInIdtEntry (
+ IN UINTN ExceptionNum,
+ IN VOID *ExceptionHandler
+ )
+{
+ IA32_IDT_GATE_DESCRIPTOR *IdtEntry;
+ IA32_DESCRIPTOR IdtDescriptor;
+
+ AsmReadIdtr (&IdtDescriptor);
+ IdtEntry = (IA32_IDT_GATE_DESCRIPTOR *) IdtDescriptor.Base;
+
+ IdtEntry[ExceptionNum].Bits.OffsetLow = (UINT16)(UINTN)ExceptionHandler;
+ IdtEntry[ExceptionNum].Bits.OffsetHigh = (UINT16)((UINTN)ExceptionHandler >> 16);
+ IdtEntry[ExceptionNum].Bits.OffsetUpper = (UINT32)((UINTN)ExceptionHandler >> 32);
+}
diff --git a/SourceLevelDebugPkg/Library/DebugAgent/DebugAgentCommon/X64/AsmFuncs.S b/SourceLevelDebugPkg/Library/DebugAgent/DebugAgentCommon/X64/AsmFuncs.S
index 3de9767dba..e7c3ed7464 100644
--- a/SourceLevelDebugPkg/Library/DebugAgent/DebugAgentCommon/X64/AsmFuncs.S
+++ b/SourceLevelDebugPkg/Library/DebugAgent/DebugAgentCommon/X64/AsmFuncs.S
@@ -1,6 +1,6 @@
#------------------------------------------------------------------------------
#
-# Copyright (c) 2006 - 2012, Intel Corporation. All rights reserved.<BR>
+# Copyright (c) 2006 - 2013, 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
@@ -35,6 +35,7 @@ ASM_PFX(ExceptionStubHeaderSize): .word ASM_PFX(Exception1Handle) - ASM_PFX
.text
+.byte 0x41, 0x47, 0x54, 0x48 # AGENT_HANDLER_SIGNATURE SIGNATURE_32('A','G','T','H')
ASM_PFX(Exception0Handle):
cli
pushq %rcx
@@ -280,7 +281,7 @@ NoExtrPush:
pushq %rax
## clear Dr7 while executing debugger itself
xorq %rax, %rax
-#debug movq %rax, %dr7
+ movq %rax, %dr7
movq %dr6, %rax
pushq %rax
diff --git a/SourceLevelDebugPkg/Library/DebugAgent/DebugAgentCommon/X64/AsmFuncs.asm b/SourceLevelDebugPkg/Library/DebugAgent/DebugAgentCommon/X64/AsmFuncs.asm
index 16d73a4121..23abcc7621 100644
--- a/SourceLevelDebugPkg/Library/DebugAgent/DebugAgentCommon/X64/AsmFuncs.asm
+++ b/SourceLevelDebugPkg/Library/DebugAgent/DebugAgentCommon/X64/AsmFuncs.asm
@@ -1,6 +1,6 @@
;------------------------------------------------------------------------------
;
-; Copyright (c) 2010 - 2012, Intel Corporation. All rights reserved.<BR>
+; Copyright (c) 2010 - 2013, 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
@@ -33,6 +33,7 @@ CommonEntryAddr dq CommonEntry ;
.code
+db 41h, 47h, 54h, 48h ; AGENT_HANDLER_SIGNATURE SIGNATURE_32('A','G','T','H')
Exception0Handle:
cli
push rcx
@@ -198,7 +199,7 @@ NoExtrPush:
push rax
mov rax, cr2
push rax
- push 0 ; cr0 will not saved???
+ push 0
mov rax, cr0
push rax