2010-09-12 08:43:36 +02:00
/** @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 .
2013-01-25 03:36:18 +01:00
Copyright ( c ) 2010 - 2013 , Intel Corporation . All rights reserved . < BR >
2010-09-12 08:43:36 +02:00
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"
2013-01-25 03:36:18 +01:00
CHAR8 mErrorMsgVersionAlert [ ] = " \r The SourceLevelDebugPkg you are using requires a newer version of the Intel(R) UDK Debugger Tool. \r \n " ;
CHAR8 mErrorMsgSendInitPacket [ ] = " \r Send 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 " ;
2012-06-11 04:15:11 +02:00
2013-01-25 03:36:18 +01:00
/**
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 ;
}
2012-06-11 04:15:11 +02:00
2010-09-12 08:43:36 +02:00
/**
2012-06-11 04:15:11 +02:00
Send a debug message packet to the debug port .
2010-09-12 08:43:36 +02:00
2012-06-11 04:15:11 +02:00
@ param [ in ] Buffer The debug message .
@ param [ in ] Length The length of debug message .
2010-09-12 08:43:36 +02:00
* */
2012-06-11 04:15:11 +02:00
VOID
SendDebugMsgPacket (
IN CHAR8 * Buffer ,
IN UINTN Length
2010-09-12 08:43:36 +02:00
)
{
2012-06-11 04:15:11 +02:00
DEBUG_PACKET_HEADER DebugHeader ;
DEBUG_PORT_HANDLE Handle ;
Handle = GetDebugPortHandle ( ) ;
2010-09-12 08:43:36 +02:00
2012-06-11 04:15:11 +02:00
DebugHeader . StartSymbol = DEBUG_STARTING_SYMBOL_NORMAL ;
DebugHeader . Command = DEBUG_COMMAND_PRINT_MESSAGE ;
DebugHeader . Length = sizeof ( DEBUG_PACKET_HEADER ) + ( UINT8 ) Length ;
2013-01-25 03:36:18 +01:00
DebugHeader . SequenceNo = 0xEE ;
DebugHeader . Crc = 0 ;
DebugHeader . Crc = CalculateCrc16 (
( UINT8 * ) Buffer , Length ,
CalculateCrc16 ( ( UINT8 * ) & DebugHeader , sizeof ( DEBUG_PACKET_HEADER ) , 0 )
) ;
2010-09-12 08:43:36 +02:00
2012-06-11 04:15:11 +02:00
DebugPortWriteBuffer ( Handle , ( UINT8 * ) & DebugHeader , sizeof ( DEBUG_PACKET_HEADER ) ) ;
DebugPortWriteBuffer ( Handle , ( UINT8 * ) Buffer , Length ) ;
}
/**
Prints a debug message to the debug port if the specified error level is enabled .
If any bit in ErrorLevel is also set in Mainbox , then print the message specified
by Format and the associated variable argument list to the debug port .
@ param [ in ] ErrorLevel The error level of the debug message .
@ param [ in ] Format Format string for the debug message to print .
@ param [ in ] . . . Variable argument list whose contents are accessed
based on the format string specified by Format .
* */
VOID
EFIAPI
DebugAgentMsgPrint (
IN UINT8 ErrorLevel ,
IN CHAR8 * Format ,
. . .
)
{
CHAR8 Buffer [ DEBUG_DATA_MAXIMUM_REAL_DATA ] ;
VA_LIST Marker ;
//
// Check driver debug mask value and global mask
//
2013-01-25 03:36:18 +01:00
if ( ( ErrorLevel & GetDebugFlag ( DEBUG_AGENT_FLAG_PRINT_ERROR_LEVEL ) ) = = 0 ) {
2012-06-11 04:15:11 +02:00
return ;
2010-09-12 08:43:36 +02:00
}
2012-06-11 04:15:11 +02:00
//
// Convert the DEBUG() message to an ASCII String
//
VA_START ( Marker , Format ) ;
AsciiVSPrint ( Buffer , sizeof ( Buffer ) , Format , Marker ) ;
VA_END ( Marker ) ;
SendDebugMsgPacket ( Buffer , AsciiStrLen ( Buffer ) ) ;
2010-09-12 08:43:36 +02:00
}
/**
2012-06-11 04:15:11 +02:00
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 .
2010-09-12 08:43:36 +02:00
* */
VOID
2012-06-11 04:15:11 +02:00
EFIAPI
DebugAgentDataMsgPrint (
IN UINT8 ErrorLevel ,
IN BOOLEAN IsSend ,
IN UINT8 * Data ,
IN UINT8 Length
2010-09-12 08:43:36 +02:00
)
{
2012-06-11 04:15:11 +02:00
CHAR8 Buffer [ DEBUG_DATA_MAXIMUM_REAL_DATA ] ;
CHAR8 * DestBuffer ;
UINTN Index ;
2010-09-12 08:43:36 +02:00
2012-06-11 04:15:11 +02:00
//
// Check driver debug mask value and global mask
//
2013-01-25 03:36:18 +01:00
if ( ( ErrorLevel & GetDebugFlag ( DEBUG_AGENT_FLAG_PRINT_ERROR_LEVEL ) ) = = 0 ) {
2012-06-11 04:15:11 +02:00
return ;
}
DestBuffer = Buffer ;
if ( IsSend ) {
DestBuffer + = AsciiSPrint ( DestBuffer , DEBUG_DATA_MAXIMUM_REAL_DATA , " Sent data [ " ) ;
} else {
DestBuffer + = AsciiSPrint ( DestBuffer , DEBUG_DATA_MAXIMUM_REAL_DATA , " Received data [ " ) ;
}
2010-09-12 08:43:36 +02:00
2012-06-11 04:15:11 +02:00
Index = 0 ;
while ( TRUE ) {
if ( DestBuffer - Buffer > DEBUG_DATA_MAXIMUM_REAL_DATA - 6 ) {
//
// If there was no enough space in buffer, send out the debug message,
// reserving 6 bytes is for the last data and end characters "]\n".
//
SendDebugMsgPacket ( Buffer , DestBuffer - Buffer ) ;
DestBuffer = Buffer ;
}
DestBuffer + = AsciiSPrint ( DestBuffer , DEBUG_DATA_MAXIMUM_REAL_DATA - ( DestBuffer - Buffer ) , " %02x " , Data [ Index ] ) ;
Index + + ;
if ( Index > = Length ) {
2013-01-25 03:36:18 +01:00
//
2012-06-11 04:15:11 +02:00
// The last character of debug message has been foramtted in buffer
//
DestBuffer + = AsciiSPrint ( DestBuffer , DEBUG_DATA_MAXIMUM_REAL_DATA - ( DestBuffer - Buffer ) , " ] \n " ) ;
SendDebugMsgPacket ( Buffer , DestBuffer - Buffer ) ;
break ;
}
}
2010-09-12 08:43:36 +02:00
}
2013-01-25 03:36:18 +01:00
/**
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 ;
}
2012-06-11 04:15:11 +02:00
2010-09-12 08:43:36 +02:00
/**
2012-06-11 04:15:11 +02:00
Check if HOST is attached based on Mailbox .
2010-09-12 08:43:36 +02:00
2012-06-11 04:15:11 +02:00
@ retval TRUE HOST is attached .
@ retval FALSE HOST is not attached .
2010-09-12 08:43:36 +02:00
2012-06-11 04:15:11 +02:00
* */
BOOLEAN
IsHostAttached (
VOID
)
{
2013-01-25 03:36:18 +01:00
return ( BOOLEAN ) ( GetDebugFlag ( DEBUG_AGENT_FLAG_HOST_ATTACHED ) = = 1 ) ;
2012-06-11 04:15:11 +02:00
}
/**
Set HOST connect flag in Mailbox .
@ param [ in ] Attached Attach status .
2010-09-12 08:43:36 +02:00
* */
VOID
2012-06-11 04:15:11 +02:00
SetHostAttached (
IN BOOLEAN Attached
2010-09-12 08:43:36 +02:00
)
{
2012-06-11 04:15:11 +02:00
DebugAgentMsgPrint ( DEBUG_AGENT_INFO , " Attach status is %d \n " , Attached ) ;
2013-01-25 03:36:18 +01:00
SetDebugFlag ( DEBUG_AGENT_FLAG_HOST_ATTACHED , ( UINT32 ) Attached ) ;
2012-06-11 04:15:11 +02:00
}
/**
Set debug setting of Debug Agent in Mailbox .
@ param DebugSetting Pointer to Debug Setting defined by transfer protocol .
@ retval RETURN_SUCCESS The setting is set successfully .
@ retval RETURN_UNSUPPORTED The Key value is not supported .
* */
RETURN_STATUS
SetDebugSetting (
IN DEBUG_DATA_SET_DEBUG_SETTING * DebugSetting
)
{
RETURN_STATUS Status ;
2010-09-12 08:43:36 +02:00
2012-06-11 04:15:11 +02:00
Status = RETURN_SUCCESS ;
switch ( DebugSetting - > Key ) {
case DEBUG_AGENT_SETTING_SMM_ENTRY_BREAK :
2013-01-25 03:36:18 +01:00
SetDebugFlag ( DEBUG_AGENT_FLAG_BREAK_ON_NEXT_SMI , DebugSetting - > Value ) ;
2012-06-11 04:15:11 +02:00
break ;
case DEBUG_AGENT_SETTING_PRINT_ERROR_LEVEL :
2013-01-25 03:36:18 +01:00
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 ) ;
2012-06-11 04:15:11 +02:00
break ;
default :
Status = RETURN_UNSUPPORTED ;
2010-09-12 08:43:36 +02:00
}
2012-06-11 04:15:11 +02:00
return Status ;
2010-09-12 08:43:36 +02:00
}
/**
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
//
2012-06-11 04:15:11 +02:00
Dr7Value & = ~ ( 0xf < < ( 16 + RegisterIndex * 4 ) ) ;
Dr7Value | = ( UINTN ) ( ( SetHwBreakpoint - > Type . Length < < 2 ) | SetHwBreakpoint - > Type . Access ) < < ( 16 + RegisterIndex * 4 ) ;
2010-09-12 08:43:36 +02:00
//
// 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 ) ;
}
}
2012-06-11 04:15:11 +02:00
2010-09-12 08:43:36 +02:00
/**
2012-06-11 04:15:11 +02:00
Return the offset of FP / MMX / XMM registers in the FPU saved state by register index .
2010-09-12 08:43:36 +02:00
2012-06-11 04:15:11 +02:00
@ param [ in ] Index Register index .
@ param [ out ] Width Register width returned .
@ return Offset in the FPU Save State .
* */
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_FX_SAVE_STATE , Fcw ) ;
case SOFT_DEBUGGER_REGISTER_FP_FSW :
* Width = ( UINT8 ) sizeof ( UINT16 ) ;
return OFFSET_OF ( DEBUG_DATA_FX_SAVE_STATE , Fsw ) ;
case SOFT_DEBUGGER_REGISTER_FP_FTW :
* Width = ( UINT8 ) sizeof ( UINT16 ) ;
return OFFSET_OF ( DEBUG_DATA_FX_SAVE_STATE , Ftw ) ;
case SOFT_DEBUGGER_REGISTER_FP_OPCODE :
* Width = ( UINT8 ) sizeof ( UINT16 ) ;
return OFFSET_OF ( DEBUG_DATA_FX_SAVE_STATE , Opcode ) ;
case SOFT_DEBUGGER_REGISTER_FP_EIP :
* Width = ( UINT8 ) sizeof ( UINT32 ) ;
return OFFSET_OF ( DEBUG_DATA_FX_SAVE_STATE , Eip ) ;
case SOFT_DEBUGGER_REGISTER_FP_CS :
* Width = ( UINT8 ) sizeof ( UINT16 ) ;
return OFFSET_OF ( DEBUG_DATA_FX_SAVE_STATE , Cs ) ;
case SOFT_DEBUGGER_REGISTER_FP_DATAOFFSET :
* Width = ( UINT8 ) sizeof ( UINT32 ) ;
return OFFSET_OF ( DEBUG_DATA_FX_SAVE_STATE , DataOffset ) ;
case SOFT_DEBUGGER_REGISTER_FP_DS :
* Width = ( UINT8 ) sizeof ( UINT16 ) ;
return OFFSET_OF ( DEBUG_DATA_FX_SAVE_STATE , Ds ) ;
case SOFT_DEBUGGER_REGISTER_FP_MXCSR :
* Width = ( UINT8 ) sizeof ( UINT32 ) ;
return OFFSET_OF ( DEBUG_DATA_FX_SAVE_STATE , Mxcsr ) ;
case SOFT_DEBUGGER_REGISTER_FP_MXCSR_MASK :
* Width = ( UINT8 ) sizeof ( UINT32 ) ;
return OFFSET_OF ( DEBUG_DATA_FX_SAVE_STATE , Mxcsr_Mask ) ;
}
}
if ( Index < = SOFT_DEBUGGER_REGISTER_ST7 ) {
* Width = 10 ;
} else if ( Index < = SOFT_DEBUGGER_REGISTER_XMM15 ) {
* Width = 16 ;
} else {
//
// MMX register
//
* Width = 8 ;
Index - = SOFT_DEBUGGER_REGISTER_MM0 - SOFT_DEBUGGER_REGISTER_ST0 ;
}
return OFFSET_OF ( DEBUG_DATA_FX_SAVE_STATE , St0Mm0 ) + ( Index - SOFT_DEBUGGER_REGISTER_ST0 ) * 16 ;
}
/**
Return the pointer of the register value in the CPU saved context .
@ param [ in ] CpuContext Pointer to saved CPU context .
@ param [ in ] Index Register index value .
@ param [ out ] Width Data width to read .
@ return The pointer in the CPU saved context .
* */
UINT8 *
ArchReadRegisterBuffer (
IN DEBUG_CPU_CONTEXT * CpuContext ,
IN UINT8 Index ,
OUT UINT8 * Width
)
{
UINT8 * Buffer ;
if ( Index < SOFT_DEBUGGER_REGISTER_FP_BASE ) {
Buffer = ( UINT8 * ) CpuContext + OFFSET_OF ( DEBUG_CPU_CONTEXT , Dr0 ) + Index * sizeof ( UINTN ) ;
* Width = ( UINT8 ) sizeof ( UINTN ) ;
} else {
//
// FPU/MMX/XMM registers
//
Buffer = ( UINT8 * ) CpuContext + OFFSET_OF ( DEBUG_CPU_CONTEXT , FxSaveState ) + ArchReadFxStatOffset ( Index , Width ) ;
}
return Buffer ;
}
/**
Send the packet without data to HOST .
@ param [ in ] CommandType Type of Command .
2013-01-25 03:36:18 +01:00
@ param [ in ] SequenceNo Sequence number .
2010-09-12 08:43:36 +02:00
* */
VOID
2012-06-11 04:15:11 +02:00
SendPacketWithoutData (
2013-01-25 03:36:18 +01:00
IN UINT8 CommandType ,
IN UINT8 SequenceNo
2010-09-12 08:43:36 +02:00
)
{
2012-06-11 04:15:11 +02:00
DEBUG_PACKET_HEADER DebugHeader ;
2010-09-12 08:43:36 +02:00
DEBUG_PORT_HANDLE Handle ;
Handle = GetDebugPortHandle ( ) ;
2012-06-11 04:15:11 +02:00
DebugHeader . StartSymbol = DEBUG_STARTING_SYMBOL_NORMAL ;
DebugHeader . Command = CommandType ;
DebugHeader . Length = sizeof ( DEBUG_PACKET_HEADER ) ;
2013-01-25 03:36:18 +01:00
DebugHeader . SequenceNo = SequenceNo ;
DebugHeader . Crc = 0 ;
DebugHeader . Crc = CalculateCrc16 ( ( UINT8 * ) & DebugHeader , sizeof ( DEBUG_PACKET_HEADER ) , 0 ) ;
2010-09-12 08:43:36 +02:00
2012-06-11 04:15:11 +02:00
DebugAgentDataMsgPrint ( DEBUG_AGENT_VERBOSE , TRUE , ( UINT8 * ) & DebugHeader , DebugHeader . Length ) ;
DebugPortWriteBuffer ( Handle , ( UINT8 * ) & DebugHeader , DebugHeader . Length ) ;
}
/**
Send acknowledge packet to HOST .
@ param [ in ] AckCommand Type of Acknowledge packet .
* */
VOID
SendAckPacket (
IN UINT8 AckCommand
)
{
2013-01-25 03:36:18 +01:00
UINT8 SequenceNo ;
DEBUG_AGENT_MAILBOX * Mailbox ;
2012-06-11 04:15:11 +02:00
if ( AckCommand ! = DEBUG_COMMAND_OK ) {
2013-01-25 03:36:18 +01:00
//
// This is not ACK OK packet
//
2012-06-11 04:15:11 +02:00
DebugAgentMsgPrint ( DEBUG_AGENT_ERROR , " Send ACK(%d) \n " , AckCommand ) ;
}
2013-01-25 03:36:18 +01:00
Mailbox = GetMailboxPointer ( ) ;
SequenceNo = Mailbox - > HostSequenceNo ;
DebugAgentMsgPrint ( DEBUG_AGENT_INFO , " SendAckPacket: SequenceNo = %x \n " , SequenceNo ) ;
SendPacketWithoutData ( AckCommand , SequenceNo ) ;
UpdateMailboxContent ( Mailbox , DEBUG_MAILBOX_LAST_ACK , AckCommand ) ;
2010-09-12 08:43:36 +02:00
}
/**
2013-01-25 03:36:18 +01:00
Receive valid packet from HOST .
2010-09-12 08:43:36 +02:00
2013-01-25 03:36:18 +01:00
@ 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 .
2010-09-12 08:43:36 +02:00
2013-01-25 03:36:18 +01:00
@ retval RETURN_SUCCESS A valid package was reveived in InputPacket .
@ retval RETURN_TIMEOUT Timeout occurs .
2010-09-12 08:43:36 +02:00
* */
RETURN_STATUS
2013-01-25 03:36:18 +01:00
ReceivePacket (
OUT UINT8 * InputPacket ,
OUT BOOLEAN * BreakReceived ,
OUT BOOLEAN * IncompatibilityFlag , OPTIONAL
IN UINTN Timeout ,
IN BOOLEAN SkipStartSymbol
2010-09-12 08:43:36 +02:00
)
{
2013-01-25 03:36:18 +01:00
DEBUG_PACKET_HEADER * DebugHeader ;
UINTN Received ;
DEBUG_PORT_HANDLE Handle ;
UINT16 Crc ;
UINTN TimeoutForStartSymbol ;
2010-09-12 08:43:36 +02:00
Handle = GetDebugPortHandle ( ) ;
2013-01-25 03:36:18 +01:00
if ( SkipStartSymbol ) {
TimeoutForStartSymbol = 0 ;
} else {
TimeoutForStartSymbol = Timeout ;
}
DebugHeader = ( DEBUG_PACKET_HEADER * ) InputPacket ;
2010-09-12 08:43:36 +02:00
while ( TRUE ) {
2013-01-25 03:36:18 +01:00
//
// 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 " ) ;
2010-09-12 08:43:36 +02:00
return RETURN_TIMEOUT ;
}
2013-01-25 03:36:18 +01:00
if ( DebugHeader - > StartSymbol ! = DEBUG_STARTING_SYMBOL_NORMAL ) {
DebugAgentMsgPrint ( DEBUG_AGENT_WARNING , " Invalid start symbol received [%02x] \n " , DebugHeader - > StartSymbol ) ;
continue ;
2010-09-12 08:43:36 +02:00
}
2012-06-11 04:15:11 +02:00
//
2013-01-25 03:36:18 +01:00
// Read Package header till field Length
2012-06-11 04:15:11 +02:00
//
2013-01-25 03:36:18 +01:00
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 " ) ;
2012-06-11 04:15:11 +02:00
return RETURN_TIMEOUT ;
}
2013-01-25 03:36:18 +01:00
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 ) ;
}
2012-06-11 04:15:11 +02:00
}
2013-01-25 03:36:18 +01:00
DebugAgentDataMsgPrint ( DEBUG_AGENT_VERBOSE , FALSE , ( UINT8 * ) DebugHeader , DebugHeader - > Length ) ;
2010-09-12 08:43:36 +02:00
return RETURN_SUCCESS ;
}
/**
Receive acknowledge packet OK from HOST in specified time .
2013-01-25 03:36:18 +01:00
@ 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 .
2010-09-12 08:43:36 +02:00
@ 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
2012-06-11 04:15:11 +02:00
SendCommandAndWaitForAckOK (
IN UINT8 Command ,
IN UINTN Timeout ,
OUT BOOLEAN * BreakReceived , OPTIONAL
2013-01-25 03:36:18 +01:00
OUT BOOLEAN * IncompatibilityFlag OPTIONAL
2010-09-12 08:43:36 +02:00
)
{
2012-06-11 04:15:11 +02:00
RETURN_STATUS Status ;
2013-01-25 03:36:18 +01:00
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 " ) ;
}
2012-06-11 04:15:11 +02:00
continue ;
}
2013-01-25 03:36:18 +01:00
ASSERT_EFI_ERROR ( Status ) ;
2012-06-11 04:15:11 +02:00
//
2013-01-25 03:36:18 +01:00
// Status == RETURN_SUCCESS
2012-06-11 04:15:11 +02:00
//
2013-01-25 03:36:18 +01:00
if ( DebugHeader - > Command = = DEBUG_COMMAND_OK & & DebugHeader - > SequenceNo = = SequenceNo ) {
//
// Received Ack OK
//
UpdateMailboxContent ( GetMailboxPointer ( ) , DEBUG_MAILBOX_SEQUENCE_NO_INDEX , + + SequenceNo ) ;
return Status ;
2010-09-12 08:43:36 +02:00
}
2013-01-25 03:36:18 +01:00
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 ) ;
2012-06-11 04:15:11 +02:00
}
2010-09-12 08:43:36 +02:00
}
2013-01-25 03:36:18 +01:00
ASSERT ( Command = = DEBUG_COMMAND_INIT_BREAK ) ;
return Status ;
2010-09-12 08:43:36 +02:00
}
/**
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 ;
2010-09-13 04:42:14 +02:00
//
// If it's single step, no need to check DR0, to ensure single step work in PeCoffExtraActionLib
// (right after triggering a breakpoint to report image load/unload).
//
return Cause ;
2010-09-12 08:43:36 +02:00
} 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 ) {
2013-01-25 03:36:18 +01:00
if ( GetDebugFlag ( DEBUG_AGENT_FLAG_STEPPING ) = = 1 ) {
2012-06-11 04:15:11 +02:00
//
// If stepping command is executing
//
Cause = DEBUG_DATA_BREAK_CAUSE_STEPPING ;
} else {
Cause = DEBUG_DATA_BREAK_CAUSE_EXCEPTION ;
}
2010-09-12 08:43:36 +02:00
}
break ;
}
return Cause ;
}
/**
2013-01-25 03:36:18 +01:00
Send packet with response data to HOST .
2010-09-12 08:43:36 +02:00
@ 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 .
* */
RETURN_STATUS
2013-01-25 03:36:18 +01:00
SendDataResponsePacket (
2010-09-12 08:43:36 +02:00
IN UINT8 * Data ,
IN UINT16 DataSize
)
{
2013-01-25 03:36:18 +01:00
RETURN_STATUS Status ;
2012-06-11 04:15:11 +02:00
DEBUG_PACKET_HEADER * DebugHeader ;
2010-09-12 08:43:36 +02:00
BOOLEAN LastPacket ;
2013-01-25 03:36:18 +01:00
DEBUG_PACKET_HEADER * AckDebugHeader ;
2012-06-11 04:15:11 +02:00
UINT8 DebugPacket [ DEBUG_DATA_UPPER_LIMIT ] ;
2013-01-25 03:36:18 +01:00
UINT8 InputPacketBuffer [ DEBUG_DATA_UPPER_LIMIT ] ;
2010-09-12 08:43:36 +02:00
DEBUG_PORT_HANDLE Handle ;
2013-01-25 03:36:18 +01:00
UINT8 SequenceNo ;
2010-09-12 08:43:36 +02:00
Handle = GetDebugPortHandle ( ) ;
2012-06-11 04:15:11 +02:00
DebugHeader = ( DEBUG_PACKET_HEADER * ) & DebugPacket ;
DebugHeader - > StartSymbol = DEBUG_STARTING_SYMBOL_NORMAL ;
2010-09-12 08:43:36 +02:00
while ( TRUE ) {
2013-01-25 03:36:18 +01:00
SequenceNo = GetMailboxPointer ( ) - > HostSequenceNo ;
2010-09-12 08:43:36 +02:00
if ( DataSize < = DEBUG_DATA_MAXIMUM_REAL_DATA ) {
LastPacket = TRUE ;
2013-01-25 03:36:18 +01:00
DebugHeader - > Command = DEBUG_COMMAND_OK ;
DebugHeader - > Length = ( UINT8 ) ( DataSize + sizeof ( DEBUG_PACKET_HEADER ) ) ;
DebugHeader - > SequenceNo = SequenceNo ;
DebugHeader - > Crc = 0 ;
2012-06-11 04:15:11 +02:00
CopyMem ( DebugHeader + 1 , Data , DataSize ) ;
2010-09-12 08:43:36 +02:00
} else {
LastPacket = FALSE ;
2013-01-25 03:36:18 +01:00
DebugHeader - > Command = DEBUG_COMMAND_IN_PROGRESS ;
DebugHeader - > Length = DEBUG_DATA_MAXIMUM_REAL_DATA + sizeof ( DEBUG_PACKET_HEADER ) ;
DebugHeader - > SequenceNo = SequenceNo ;
DebugHeader - > Crc = 0 ;
2012-06-11 04:15:11 +02:00
CopyMem ( DebugHeader + 1 , Data , DEBUG_DATA_MAXIMUM_REAL_DATA ) ;
2010-09-12 08:43:36 +02:00
}
2012-06-11 04:15:11 +02:00
//
// Calculate and fill the checksum
//
2013-01-25 03:36:18 +01:00
DebugHeader - > Crc = CalculateCrc16 ( ( UINT8 * ) DebugHeader , DebugHeader - > Length , 0 ) ;
2012-06-11 04:15:11 +02:00
DebugAgentDataMsgPrint ( DEBUG_AGENT_VERBOSE , TRUE , ( UINT8 * ) DebugHeader , DebugHeader - > Length ) ;
DebugPortWriteBuffer ( Handle , ( UINT8 * ) DebugHeader , DebugHeader - > Length ) ;
2010-09-12 08:43:36 +02:00
2013-01-25 03:36:18 +01:00
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 ) {
2010-09-12 08:43:36 +02:00
//
// If this is the last packet, return RETURN_SUCCESS.
//
return RETURN_SUCCESS ;
}
2013-01-25 03:36:18 +01:00
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 ;
}
2010-09-12 08:43:36 +02:00
}
}
}
/**
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 ) ;
2012-06-11 04:15:11 +02:00
return SendDataResponsePacket ( ( UINT8 * ) & DebugDataBreakCause , ( UINT16 ) sizeof ( DEBUG_DATA_RESPONSE_BREAK_CAUSE ) ) ;
2010-09-12 08:43:36 +02:00
}
2012-06-11 04:15:11 +02:00
/**
Try to attach the HOST .
Send init break packet to HOST :
If no acknowlege received in specified Timeout , return RETURN_TIMEOUT .
If received acknowlege , check the revision of HOST .
Set Attach Flag if attach successfully .
2013-01-25 03:36:18 +01:00
@ param [ in ] BreakCause Break cause of this break event .
2012-06-11 04:15:11 +02:00
@ 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 .
* */
RETURN_STATUS
AttachHost (
2013-01-25 03:36:18 +01:00
IN UINT8 BreakCause ,
2012-06-11 04:15:11 +02:00
IN UINTN Timeout ,
OUT BOOLEAN * BreakReceived
)
{
RETURN_STATUS Status ;
DEBUG_PORT_HANDLE Handle ;
2013-01-25 03:36:18 +01:00
BOOLEAN IncompatibilityFlag ;
2012-06-11 04:15:11 +02:00
2013-01-25 03:36:18 +01:00
IncompatibilityFlag = FALSE ;
2012-06-11 04:15:11 +02:00
Handle = GetDebugPortHandle ( ) ;
//
// Send init break and wait ack in Timeout
//
DebugPortWriteBuffer ( Handle , ( UINT8 * ) mErrorMsgSendInitPacket , AsciiStrLen ( mErrorMsgSendInitPacket ) ) ;
2013-01-25 03:36:18 +01:00
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 ) ;
2012-06-11 04:15:11 +02:00
}
2013-01-25 03:36:18 +01:00
if ( IncompatibilityFlag ) {
2012-06-11 04:15:11 +02:00
//
2013-01-25 03:36:18 +01:00
// 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.
2012-06-11 04:15:11 +02:00
//
DebugPortWriteBuffer ( Handle , ( UINT8 * ) mErrorMsgVersionAlert , AsciiStrLen ( mErrorMsgVersionAlert ) ) ;
CpuDeadLoop ( ) ;
}
2013-01-25 03:36:18 +01:00
if ( RETURN_ERROR ( Status ) ) {
DebugPortWriteBuffer ( Handle , ( UINT8 * ) mErrorMsgConnectFail , AsciiStrLen ( mErrorMsgConnectFail ) ) ;
} else {
DebugPortWriteBuffer ( Handle , ( UINT8 * ) mErrorMsgConnectOK , AsciiStrLen ( mErrorMsgConnectOK ) ) ;
//
// Set Attach flag
//
SetHostAttached ( TRUE ) ;
}
2012-06-11 04:15:11 +02:00
return Status ;
}
/**
Send Break point packet to HOST .
Only the first breaking processor could sent BREAK_POINT packet .
2013-01-25 03:36:18 +01:00
@ param [ in ] BreakCause Break cause of this break event .
2012-06-11 04:15:11 +02:00
@ param [ in ] ProcessorIndex Processor index value .
@ 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 .
* */
VOID
SendBreakPacketToHost (
2013-01-25 03:36:18 +01:00
IN UINT8 BreakCause ,
2012-06-11 04:15:11 +02:00
IN UINT32 ProcessorIndex ,
OUT BOOLEAN * BreakReceived
)
{
UINT8 InputCharacter ;
DEBUG_PORT_HANDLE Handle ;
Handle = GetDebugPortHandle ( ) ;
if ( IsHostAttached ( ) ) {
DebugAgentMsgPrint ( DEBUG_AGENT_INFO , " processor[%x]:Send Break Packet to HOST. \n " , ProcessorIndex ) ;
2013-01-25 03:36:18 +01:00
SendCommandAndWaitForAckOK ( DEBUG_COMMAND_BREAK_POINT , READ_PACKET_TIMEOUT , BreakReceived , NULL ) ;
2012-06-11 04:15:11 +02:00
} else {
DebugAgentMsgPrint ( DEBUG_AGENT_INFO , " processor[%x]:Try to attach HOST. \n " , ProcessorIndex ) ;
//
// If HOST is not attached, try to attach it firstly.
//
//
// Poll Attach symbols from HOST and ack OK
//
do {
DebugPortReadBuffer ( Handle , & InputCharacter , 1 , 0 ) ;
} while ( InputCharacter ! = DEBUG_STARTING_SYMBOL_ATTACH ) ;
SendAckPacket ( DEBUG_COMMAND_OK ) ;
//
// Try to attach HOST
//
2013-01-25 03:36:18 +01:00
while ( AttachHost ( BreakCause , 0 , NULL ) ! = RETURN_SUCCESS ) ;
2012-06-11 04:15:11 +02:00
}
}
2010-09-12 08:43:36 +02:00
/**
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
)
{
2012-06-11 04:15:11 +02:00
RETURN_STATUS Status ;
UINT8 InputPacketBuffer [ DEBUG_DATA_UPPER_LIMIT ] ;
DEBUG_PACKET_HEADER * DebugHeader ;
UINT8 Width ;
UINT8 Data8 ;
UINT32 Data32 ;
UINT64 Data64 ;
DEBUG_DATA_READ_MEMORY * MemoryRead ;
DEBUG_DATA_WRITE_MEMORY * 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_CPUID * Cpuid ;
DEBUG_DATA_RESPONSE_CPUID CpuidResponse ;
DEBUG_DATA_SEARCH_SIGNATURE * SearchSignature ;
DEBUG_DATA_RESPONSE_GET_EXCEPTION Exception ;
DEBUG_DATA_RESPONSE_GET_REVISION DebugAgentRevision ;
DEBUG_DATA_SET_VIEWPOINT * SetViewPoint ;
BOOLEAN HaltDeferred ;
UINT32 ProcessorIndex ;
DEBUG_PORT_HANDLE Handle ;
DEBUG_AGENT_EXCEPTION_BUFFER AgentExceptionBuffer ;
UINT32 IssuedViewPoint ;
2013-01-25 03:36:18 +01:00
DEBUG_AGENT_MAILBOX * Mailbox ;
2010-09-12 08:43:36 +02:00
ProcessorIndex = 0 ;
2012-06-11 04:15:11 +02:00
IssuedViewPoint = 0 ;
HaltDeferred = BreakReceived ;
2010-09-12 08:43:36 +02:00
2013-01-25 03:36:18 +01:00
if ( MultiProcessorDebugSupport ( ) ) {
2010-09-12 08:43:36 +02:00
ProcessorIndex = GetProcessorIndex ( ) ;
SetCpuStopFlagByIndex ( ProcessorIndex , TRUE ) ;
2012-06-11 04:15:11 +02:00
if ( mDebugMpContext . ViewPointIndex = = ProcessorIndex ) {
//
// Only the current view processor could set AgentInProgress Flag.
//
IssuedViewPoint = ProcessorIndex ;
}
2010-09-12 08:43:36 +02:00
}
2012-06-11 04:15:11 +02:00
if ( IssuedViewPoint = = ProcessorIndex ) {
//
// Set AgentInProgress Flag.
//
2013-01-25 03:36:18 +01:00
SetDebugFlag ( DEBUG_AGENT_FLAG_AGENT_IN_PROGRESS , 1 ) ;
2012-06-11 04:15:11 +02:00
}
Handle = GetDebugPortHandle ( ) ;
2010-09-12 08:43:36 +02:00
while ( TRUE ) {
2013-01-25 03:36:18 +01:00
if ( MultiProcessorDebugSupport ( ) ) {
2012-06-11 04:15:11 +02:00
//
// Check if the current processor is HOST view point
//
2010-09-12 08:43:36 +02:00
if ( mDebugMpContext . ViewPointIndex ! = ProcessorIndex ) {
if ( mDebugMpContext . RunCommandSet ) {
2012-06-11 04:15:11 +02:00
//
// If HOST view point sets RUN flag, run GO command to leave
//
2010-09-12 08:43:36 +02:00
SetCpuStopFlagByIndex ( ProcessorIndex , FALSE ) ;
CommandGo ( CpuContext ) ;
break ;
} else {
2012-06-11 04:15:11 +02:00
//
// Run into loop again
//
CpuPause ( ) ;
2010-09-12 08:43:36 +02:00
continue ;
}
}
}
2013-01-25 03:36:18 +01:00
AcquireMpSpinLock ( & mDebugMpContext . DebugPortSpinLock ) ;
2010-09-12 08:43:36 +02:00
2013-01-25 03:36:18 +01:00
DebugHeader = ( DEBUG_PACKET_HEADER * ) InputPacketBuffer ;
2010-09-12 08:43:36 +02:00
2013-01-25 03:36:18 +01:00
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 ;
2010-09-12 08:43:36 +02:00
}
2013-01-25 03:36:18 +01:00
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 ) ;
2010-09-12 08:43:36 +02:00
continue ;
}
2013-01-25 03:36:18 +01:00
2012-06-11 04:15:11 +02:00
//
// Save CPU content before executing HOST commond
//
2013-01-25 03:36:18 +01:00
UpdateMailboxContent ( Mailbox , DEBUG_MAILBOX_EXCEPTION_BUFFER_POINTER_INDEX , ( UINT64 ) ( UINTN ) & AgentExceptionBuffer . JumpBuffer ) ;
2012-06-11 04:15:11 +02:00
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 ) ;
2013-01-25 03:36:18 +01:00
ReleaseMpSpinLock ( & mDebugMpContext . DebugPortSpinLock ) ;
2012-06-11 04:15:11 +02:00
continue ;
}
DebugAgentMsgPrint ( DEBUG_AGENT_INFO , " Processor[%x]:Received one command(%x) \n " , mDebugMpContext . ViewPointIndex , DebugHeader - > Command ) ;
2010-09-12 08:43:36 +02:00
switch ( DebugHeader - > Command ) {
2013-01-25 03:36:18 +01:00
case DEBUG_COMMAND_HALT :
SendAckPacket ( DEBUG_COMMAND_HALT_DEFERRED ) ;
HaltDeferred = TRUE ;
BreakReceived = FALSE ;
Status = RETURN_SUCCESS ;
break ;
2010-09-12 08:43:36 +02:00
case DEBUG_COMMAND_RESET :
SendAckPacket ( DEBUG_COMMAND_OK ) ;
2013-01-25 03:36:18 +01:00
SendAckPacket ( DEBUG_COMMAND_OK ) ;
SendAckPacket ( DEBUG_COMMAND_OK ) ;
ReleaseMpSpinLock ( & mDebugMpContext . DebugPortSpinLock ) ;
2010-09-12 08:43:36 +02:00
ResetCold ( ) ;
//
2012-02-07 02:58:30 +01:00
// Assume system resets in 2 seconds, otherwise send TIMEOUT packet.
// PCD can be used if 2 seconds isn't long enough for some platforms.
2010-09-12 08:43:36 +02:00
//
2012-02-07 02:58:30 +01:00
MicroSecondDelay ( 2000000 ) ;
2013-01-25 03:36:18 +01:00
UpdateMailboxContent ( Mailbox , DEBUG_MAILBOX_HOST_SEQUENCE_NO_INDEX , Mailbox - > HostSequenceNo + 1 ) ;
SendAckPacket ( DEBUG_COMMAND_TIMEOUT ) ;
SendAckPacket ( DEBUG_COMMAND_TIMEOUT ) ;
2012-02-07 02:58:30 +01:00
SendAckPacket ( DEBUG_COMMAND_TIMEOUT ) ;
2010-09-12 08:43:36 +02:00
break ;
case DEBUG_COMMAND_GO :
CommandGo ( CpuContext ) ;
2012-06-11 04:15:11 +02:00
//
// Clear Dr0 to avoid to be recognized as IMAGE_LOAD/_UNLOAD again when hitting a breakpoint after GO
// If HOST changed Dr0 before GO, we will not change Dr0 here
//
Data8 = GetBreakCause ( Vector , CpuContext ) ;
if ( Data8 = = DEBUG_DATA_BREAK_CAUSE_IMAGE_LOAD | | Data8 = = DEBUG_DATA_BREAK_CAUSE_IMAGE_UNLOAD ) {
CpuContext - > Dr0 = 0 ;
}
//
// Clear Stepping Flag
//
2013-01-25 03:36:18 +01:00
SetDebugFlag ( DEBUG_AGENT_FLAG_STEPPING , 0 ) ;
2012-06-11 04:15:11 +02:00
2010-09-12 08:43:36 +02:00
if ( ! HaltDeferred ) {
//
// If no HALT command received when being in-active mode
//
2013-01-25 03:36:18 +01:00
if ( MultiProcessorDebugSupport ( ) ) {
2012-06-11 04:15:11 +02:00
Data32 = FindNextPendingBreakCpu ( ) ;
2010-09-12 08:43:36 +02:00
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 ) ;
//
2012-06-11 04:15:11 +02:00
// Send break packet to HOST to let HOST break again
//
2013-01-25 03:36:18 +01:00
SendBreakPacketToHost ( DEBUG_DATA_BREAK_CAUSE_UNKNOWN , mDebugMpContext . BreakAtCpuIndex , & BreakReceived ) ;
2012-06-11 04:15:11 +02:00
//
// Continue to run into loop to read command packet from HOST
2010-09-12 08:43:36 +02:00
//
2013-01-25 03:36:18 +01:00
ReleaseMpSpinLock ( & mDebugMpContext . DebugPortSpinLock ) ;
2010-09-12 08:43:36 +02:00
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 ) ;
2013-01-25 03:36:18 +01:00
ReleaseMpSpinLock ( & mDebugMpContext . DebugPortSpinLock ) ;
2010-09-12 08:43:36 +02:00
2013-01-25 03:36:18 +01:00
if ( ! IsHostAttached ( ) ) {
UpdateMailboxContent ( Mailbox , DEBUG_MAILBOX_SEQUENCE_NO_INDEX , 0 ) ;
UpdateMailboxContent ( Mailbox , DEBUG_MAILBOX_HOST_SEQUENCE_NO_INDEX , 0 ) ;
}
2010-09-12 08:43:36 +02:00
return ;
} else {
//
// If reveived HALT command, need to defer the GO command
//
SendAckPacket ( DEBUG_COMMAND_HALT_PROCESSED ) ;
HaltDeferred = FALSE ;
Vector = DEBUG_TIMER_VECTOR ;
}
break ;
case DEBUG_COMMAND_BREAK_CAUSE :
2013-01-25 03:36:18 +01:00
if ( MultiProcessorDebugSupport ( ) & & ProcessorIndex ! = mDebugMpContext . BreakAtCpuIndex ) {
2010-09-12 08:43:36 +02:00
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 ) ;
2012-06-11 04:15:11 +02:00
//
// Clear Dr0 to avoid to be recognized as IMAGE_LOAD/_UNLOAD again when hitting a breakpoint after GO
// If HOST changed Dr0 before GO, we will not change Dr0 here
//
Data8 = GetBreakCause ( Vector , CpuContext ) ;
if ( Data8 = = DEBUG_DATA_BREAK_CAUSE_IMAGE_LOAD | | Data8 = = DEBUG_DATA_BREAK_CAUSE_IMAGE_UNLOAD ) {
CpuContext - > Dr0 = 0 ;
}
2010-09-12 08:43:36 +02:00
mDebugMpContext . BreakAtCpuIndex = ( UINT32 ) ( - 1 ) ;
2012-06-11 04:15:11 +02:00
//
// Set Stepping Flag
//
2013-01-25 03:36:18 +01:00
SetDebugFlag ( DEBUG_AGENT_FLAG_STEPPING , 1 ) ;
ReleaseMpSpinLock ( & mDebugMpContext . DebugPortSpinLock ) ;
2010-09-12 08:43:36 +02:00
//
2012-06-11 04:15:11 +02:00
// Executing stepping command directly without sending ACK packet,
// ACK packet will be sent after stepping done.
2010-09-12 08:43:36 +02:00
//
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 ;
2012-06-11 04:15:11 +02:00
Status = SendDataResponsePacket ( ( UINT8 * ) & Data8 , ( UINT16 ) sizeof ( UINT8 ) ) ;
2010-09-12 08:43:36 +02:00
break ;
2012-06-11 04:15:11 +02:00
case DEBUG_COMMAND_READ_MEMORY :
MemoryRead = ( DEBUG_DATA_READ_MEMORY * ) ( DebugHeader + 1 ) ;
Status = SendDataResponsePacket ( ( UINT8 * ) ( UINTN ) MemoryRead - > Address , ( UINT16 ) ( MemoryRead - > Count * MemoryRead - > Width ) ) ;
2010-09-12 08:43:36 +02:00
break ;
2012-06-11 04:15:11 +02:00
case DEBUG_COMMAND_WRITE_MEMORY :
MemoryWrite = ( DEBUG_DATA_WRITE_MEMORY * ) ( DebugHeader + 1 ) ;
CopyMem ( ( VOID * ) ( UINTN ) MemoryWrite - > Address , & MemoryWrite - > Data , MemoryWrite - > Count * MemoryWrite - > Width ) ;
2010-09-12 08:43:36 +02:00
SendAckPacket ( DEBUG_COMMAND_OK ) ;
break ;
case DEBUG_COMMAND_READ_IO :
IoRead = ( DEBUG_DATA_READ_IO * ) ( DebugHeader + 1 ) ;
switch ( IoRead - > Width ) {
case 1 :
2012-06-11 04:15:11 +02:00
Data64 = IoRead8 ( ( UINTN ) IoRead - > Port ) ;
2010-09-12 08:43:36 +02:00
break ;
case 2 :
2012-06-11 04:15:11 +02:00
Data64 = IoRead16 ( ( UINTN ) IoRead - > Port ) ;
2010-09-12 08:43:36 +02:00
break ;
case 4 :
2012-06-11 04:15:11 +02:00
Data64 = IoRead32 ( ( UINTN ) IoRead - > Port ) ;
2010-09-12 08:43:36 +02:00
break ;
case 8 :
2012-06-11 04:15:11 +02:00
Data64 = IoRead64 ( ( UINTN ) IoRead - > Port ) ;
2010-09-12 08:43:36 +02:00
break ;
default :
Data64 = ( UINT64 ) - 1 ;
}
2012-06-11 04:15:11 +02:00
Status = SendDataResponsePacket ( ( UINT8 * ) & Data64 , IoRead - > Width ) ;
2010-09-12 08:43:36 +02:00
break ;
case DEBUG_COMMAND_WRITE_IO :
IoWrite = ( DEBUG_DATA_WRITE_IO * ) ( DebugHeader + 1 ) ;
switch ( IoWrite - > Width ) {
case 1 :
2012-06-11 04:15:11 +02:00
Data64 = IoWrite8 ( ( UINTN ) IoWrite - > Port , * ( UINT8 * ) & IoWrite - > Data ) ;
2010-09-12 08:43:36 +02:00
break ;
case 2 :
2012-06-11 04:15:11 +02:00
Data64 = IoWrite16 ( ( UINTN ) IoWrite - > Port , * ( UINT16 * ) & IoWrite - > Data ) ;
2010-09-12 08:43:36 +02:00
break ;
case 4 :
2012-06-11 04:15:11 +02:00
Data64 = IoWrite32 ( ( UINTN ) IoWrite - > Port , * ( UINT32 * ) & IoWrite - > Data ) ;
2010-09-12 08:43:36 +02:00
break ;
case 8 :
2012-06-11 04:15:11 +02:00
Data64 = IoWrite64 ( ( UINTN ) IoWrite - > Port , * ( UINT64 * ) & IoWrite - > Data ) ;
2010-09-12 08:43:36 +02:00
break ;
default :
Data64 = ( UINT64 ) - 1 ;
}
SendAckPacket ( DEBUG_COMMAND_OK ) ;
break ;
2012-06-11 04:15:11 +02:00
case DEBUG_COMMAND_READ_ALL_REGISTERS :
Status = SendDataResponsePacket ( ( UINT8 * ) CpuContext , sizeof ( * CpuContext ) ) ;
break ;
2010-09-12 08:43:36 +02:00
case DEBUG_COMMAND_READ_REGISTER :
RegisterRead = ( DEBUG_DATA_READ_REGISTER * ) ( DebugHeader + 1 ) ;
2012-06-11 04:15:11 +02:00
if ( RegisterRead - > Index < = SOFT_DEBUGGER_REGISTER_MAX ) {
RegisterBuffer = ArchReadRegisterBuffer ( CpuContext , RegisterRead - > Index , & Width ) ;
Status = SendDataResponsePacket ( RegisterBuffer , Width ) ;
2010-09-12 08:43:36 +02:00
} else {
2012-06-11 04:15:11 +02:00
Status = RETURN_UNSUPPORTED ;
2010-09-12 08:43:36 +02:00
}
break ;
case DEBUG_COMMAND_WRITE_REGISTER :
RegisterWrite = ( DEBUG_DATA_WRITE_REGISTER * ) ( DebugHeader + 1 ) ;
2012-06-11 04:15:11 +02:00
if ( RegisterWrite - > Index < = SOFT_DEBUGGER_REGISTER_MAX ) {
RegisterBuffer = ArchReadRegisterBuffer ( CpuContext , RegisterWrite - > Index , & Width ) ;
ASSERT ( Width = = RegisterWrite - > Length ) ;
CopyMem ( RegisterBuffer , RegisterWrite - > Data , Width ) ;
SendAckPacket ( DEBUG_COMMAND_OK ) ;
} else {
Status = RETURN_UNSUPPORTED ;
}
2010-09-12 08:43:36 +02:00
break ;
case DEBUG_COMMAND_ARCH_MODE :
Data8 = DEBUG_ARCH_SYMBOL ;
2012-06-11 04:15:11 +02:00
Status = SendDataResponsePacket ( ( UINT8 * ) & Data8 , ( UINT16 ) sizeof ( UINT8 ) ) ;
2010-09-12 08:43:36 +02:00
break ;
case DEBUG_COMMAND_READ_MSR :
MsrRegisterRead = ( DEBUG_DATA_READ_MSR * ) ( DebugHeader + 1 ) ;
Data64 = AsmReadMsr64 ( MsrRegisterRead - > Index ) ;
2012-06-11 04:15:11 +02:00
Status = SendDataResponsePacket ( ( UINT8 * ) & Data64 , ( UINT16 ) sizeof ( UINT64 ) ) ;
2010-09-12 08:43:36 +02:00
break ;
case DEBUG_COMMAND_WRITE_MSR :
MsrRegisterWrite = ( DEBUG_DATA_WRITE_MSR * ) ( DebugHeader + 1 ) ;
AsmWriteMsr64 ( MsrRegisterWrite - > Index , MsrRegisterWrite - > Value ) ;
SendAckPacket ( DEBUG_COMMAND_OK ) ;
break ;
2012-06-11 04:15:11 +02:00
case DEBUG_COMMAND_SET_DEBUG_SETTING :
Status = SetDebugSetting ( ( DEBUG_DATA_SET_DEBUG_SETTING * ) ( DebugHeader + 1 ) ) ;
if ( Status = = RETURN_SUCCESS ) {
SendAckPacket ( DEBUG_COMMAND_OK ) ;
}
2010-09-12 08:43:36 +02:00
break ;
case DEBUG_COMMAND_GET_REVISION :
DebugAgentRevision . Revision = DEBUG_AGENT_REVISION ;
DebugAgentRevision . Capabilities = DEBUG_AGENT_CAPABILITIES ;
2012-06-11 04:15:11 +02:00
Status = SendDataResponsePacket ( ( UINT8 * ) & DebugAgentRevision , ( UINT16 ) sizeof ( DEBUG_DATA_RESPONSE_GET_REVISION ) ) ;
2010-09-12 08:43:36 +02:00
break ;
case DEBUG_COMMAND_GET_EXCEPTION :
Exception . ExceptionNum = ( UINT8 ) Vector ;
2012-06-11 04:15:11 +02:00
Exception . ExceptionData = ( UINT32 ) CpuContext - > ExceptionData ;
Status = SendDataResponsePacket ( ( UINT8 * ) & Exception , ( UINT16 ) sizeof ( DEBUG_DATA_RESPONSE_GET_EXCEPTION ) ) ;
2010-09-12 08:43:36 +02:00
break ;
case DEBUG_COMMAND_SET_VIEWPOINT :
2012-06-11 04:15:11 +02:00
SetViewPoint = ( DEBUG_DATA_SET_VIEWPOINT * ) ( DebugHeader + 1 ) ;
2013-01-25 03:36:18 +01:00
if ( MultiProcessorDebugSupport ( ) ) {
2012-06-11 04:15:11 +02:00
if ( IsCpuStopped ( SetViewPoint - > ViewPoint ) ) {
SetDebugViewPoint ( SetViewPoint - > ViewPoint ) ;
2010-09-12 08:43:36 +02:00
SendAckPacket ( DEBUG_COMMAND_OK ) ;
} else {
//
// If CPU is not halted
//
SendAckPacket ( DEBUG_COMMAND_NOT_SUPPORTED ) ;
}
2012-06-11 04:15:11 +02:00
} else if ( SetViewPoint - > ViewPoint = = 0 ) {
2010-09-12 08:43:36 +02:00
SendAckPacket ( DEBUG_COMMAND_OK ) ;
} else {
SendAckPacket ( DEBUG_COMMAND_NOT_SUPPORTED ) ;
}
break ;
case DEBUG_COMMAND_GET_VIEWPOINT :
Data32 = mDebugMpContext . ViewPointIndex ;
2012-06-11 04:15:11 +02:00
SendDataResponsePacket ( ( UINT8 * ) & Data32 , ( UINT16 ) sizeof ( UINT32 ) ) ;
break ;
case DEBUG_COMMAND_MEMORY_READY :
2013-01-25 03:36:18 +01:00
Data8 = ( UINT8 ) GetDebugFlag ( DEBUG_AGENT_FLAG_MEMORY_READY ) ;
2012-06-11 04:15:11 +02:00
SendDataResponsePacket ( & Data8 , ( UINT16 ) sizeof ( UINT8 ) ) ;
break ;
case DEBUG_COMMAND_DETACH :
SetHostAttached ( FALSE ) ;
SendAckPacket ( DEBUG_COMMAND_OK ) ;
break ;
case DEBUG_COMMAND_CPUID :
Cpuid = ( DEBUG_DATA_CPUID * ) ( DebugHeader + 1 ) ;
AsmCpuidEx (
Cpuid - > Eax , Cpuid - > Ecx ,
& CpuidResponse . Eax , & CpuidResponse . Ebx ,
& CpuidResponse . Ecx , & CpuidResponse . Edx
) ;
SendDataResponsePacket ( ( UINT8 * ) & CpuidResponse , ( UINT16 ) sizeof ( CpuidResponse ) ) ;
break ;
case DEBUG_COMMAND_SEARCH_SIGNATURE :
SearchSignature = ( DEBUG_DATA_SEARCH_SIGNATURE * ) ( DebugHeader + 1 ) ;
if ( ( SearchSignature - > Alignment ! = 0 ) & &
( SearchSignature - > Alignment = = GetPowerOfTwo32 ( SearchSignature - > Alignment ) )
) {
if ( SearchSignature - > Positive ) {
for (
Data64 = ALIGN_VALUE ( ( UINTN ) SearchSignature - > Start , SearchSignature - > Alignment ) ;
Data64 < = SearchSignature - > Start + SearchSignature - > Count - SearchSignature - > DataLength ;
Data64 + = SearchSignature - > Alignment
) {
if ( CompareMem ( ( VOID * ) ( UINTN ) Data64 , & SearchSignature - > Data , SearchSignature - > DataLength ) = = 0 ) {
break ;
}
}
if ( Data64 > SearchSignature - > Start + SearchSignature - > Count - SearchSignature - > DataLength ) {
Data64 = ( UINT64 ) - 1 ;
}
} else {
for (
Data64 = ALIGN_VALUE ( ( UINTN ) SearchSignature - > Start - SearchSignature - > Alignment , SearchSignature - > Alignment ) ;
Data64 > = SearchSignature - > Start - SearchSignature - > Count ;
Data64 - = SearchSignature - > Alignment
) {
if ( CompareMem ( ( VOID * ) ( UINTN ) Data64 , & SearchSignature - > Data , SearchSignature - > DataLength ) = = 0 ) {
break ;
}
}
if ( Data64 < SearchSignature - > Start - SearchSignature - > Count ) {
Data64 = ( UINT64 ) - 1 ;
}
}
SendDataResponsePacket ( ( UINT8 * ) & Data64 , ( UINT16 ) sizeof ( Data64 ) ) ;
} else {
Status = RETURN_UNSUPPORTED ;
}
2010-09-12 08:43:36 +02:00
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 ) ;
}
2013-01-25 03:36:18 +01:00
ReleaseMpSpinLock ( & mDebugMpContext . DebugPortSpinLock ) ;
2010-09-12 08:43:36 +02:00
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
)
{
2012-06-11 04:15:11 +02:00
UINT8 InputCharacter ;
UINT8 BreakCause ;
UINTN SavedEip ;
BOOLEAN BreakReceived ;
UINT32 ProcessorIndex ;
UINT32 CurrentDebugTimerInitCount ;
DEBUG_PORT_HANDLE Handle ;
UINT8 Data8 ;
UINT8 * Al ;
UINT32 IssuedViewPoint ;
DEBUG_AGENT_EXCEPTION_BUFFER * ExceptionBuffer ;
2010-09-12 08:43:36 +02:00
2012-06-11 04:15:11 +02:00
ProcessorIndex = 0 ;
IssuedViewPoint = 0 ;
BreakReceived = FALSE ;
2010-09-12 08:43:36 +02:00
2013-01-25 03:36:18 +01:00
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 ( ) ) {
2010-09-12 08:43:36 +02:00
ProcessorIndex = GetProcessorIndex ( ) ;
2012-06-11 04:15:11 +02:00
//
// If this processor has alreay halted before, need to check it later
//
if ( IsCpuStopped ( ProcessorIndex ) ) {
IssuedViewPoint = ProcessorIndex ;
}
2010-09-12 08:43:36 +02:00
}
2013-01-25 03:36:18 +01:00
if ( IssuedViewPoint = = ProcessorIndex & & GetDebugFlag ( DEBUG_AGENT_FLAG_STEPPING ) ! = 1 ) {
2012-06-11 04:15:11 +02:00
//
// 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()
//
2013-01-25 03:36:18 +01:00
if ( GetDebugFlag ( DEBUG_AGENT_FLAG_AGENT_IN_PROGRESS ) = = 1 ) {
2012-06-11 04:15:11 +02:00
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 ;
2013-01-25 03:36:18 +01:00
LongJump ( ( BASE_LIBRARY_JUMP_BUFFER * ) ( UINTN ) ( ExceptionBuffer ) , 1 ) ;
2012-06-11 04:15:11 +02:00
}
}
2013-01-25 03:36:18 +01:00
if ( MultiProcessorDebugSupport ( ) ) {
2012-06-11 04:15:11 +02:00
//
// If RUN commmand is executing, wait for it done.
//
while ( mDebugMpContext . RunCommandSet ) {
CpuPause ( ) ;
}
}
2013-01-25 03:36:18 +01:00
Handle = GetDebugPortHandle ( ) ;
BreakCause = GetBreakCause ( Vector , CpuContext ) ;
2010-09-12 08:43:36 +02:00
switch ( Vector ) {
case DEBUG_INT1_VECTOR :
case DEBUG_INT3_VECTOR :
2012-06-11 04:15:11 +02:00
switch ( BreakCause ) {
case DEBUG_DATA_BREAK_CAUSE_SYSTEM_RESET :
2013-01-25 03:36:18 +01:00
if ( AttachHost ( BreakCause , READ_PACKET_TIMEOUT , & BreakReceived ) ! = RETURN_SUCCESS ) {
2012-06-11 04:15:11 +02:00
//
// Try to connect HOST, return if fails
//
2010-09-12 08:43:36 +02:00
break ;
}
CommandCommunication ( Vector , CpuContext , BreakReceived ) ;
2012-06-11 04:15:11 +02:00
break ;
2010-09-12 08:43:36 +02:00
2012-06-11 04:15:11 +02:00
case DEBUG_DATA_BREAK_CAUSE_STEPPING :
2010-09-12 08:43:36 +02:00
//
// Stepping is finished, send Ack package.
//
2013-01-25 03:36:18 +01:00
if ( MultiProcessorDebugSupport ( ) ) {
2010-09-12 08:43:36 +02:00
mDebugMpContext . BreakAtCpuIndex = ProcessorIndex ;
}
SendAckPacket ( DEBUG_COMMAND_OK ) ;
CommandCommunication ( Vector , CpuContext , BreakReceived ) ;
2012-06-11 04:15:11 +02:00
break ;
2010-09-12 08:43:36 +02:00
2012-06-11 04:15:11 +02:00
case DEBUG_DATA_BREAK_CAUSE_MEMORY_READY :
2010-09-12 08:43:36 +02:00
//
// Memory is ready
//
2013-01-25 03:36:18 +01:00
SendCommandAndWaitForAckOK ( DEBUG_COMMAND_MEMORY_READY , READ_PACKET_TIMEOUT , & BreakReceived , NULL ) ;
2010-09-12 08:43:36 +02:00
CommandCommunication ( Vector , CpuContext , BreakReceived ) ;
2012-06-11 04:15:11 +02:00
break ;
2010-09-12 08:43:36 +02:00
2012-06-11 04:15:11 +02:00
case DEBUG_DATA_BREAK_CAUSE_IMAGE_LOAD :
case DEBUG_DATA_BREAK_CAUSE_IMAGE_UNLOAD :
//
// Set AL to DEBUG_AGENT_IMAGE_CONTINUE
//
Al = ArchReadRegisterBuffer ( CpuContext , SOFT_DEBUGGER_REGISTER_AX , & Data8 ) ;
* Al = DEBUG_AGENT_IMAGE_CONTINUE ;
2010-09-12 08:43:36 +02:00
2012-06-11 04:15:11 +02:00
if ( ! IsHostAttached ( ) ) {
2010-09-12 08:43:36 +02:00
//
2012-06-11 04:15:11 +02:00
// If HOST is not connected for image load/unload, return
2010-09-12 08:43:36 +02:00
//
2012-06-11 04:15:11 +02:00
break ;
2010-09-12 08:43:36 +02:00
}
2012-06-11 04:15:11 +02:00
//
// Continue to run the following common code
//
case DEBUG_DATA_BREAK_CAUSE_HW_BREAKPOINT :
case DEBUG_DATA_BREAK_CAUSE_SW_BREAKPOINT :
default :
//
// Send Break packet to HOST
//
2013-01-25 03:36:18 +01:00
AcquireMpSpinLock ( & mDebugMpContext . DebugPortSpinLock ) ;
2012-06-11 04:15:11 +02:00
//
// Only the first breaking processor could send BREAK_POINT to HOST
//
if ( IsFirstBreakProcessor ( ProcessorIndex ) ) {
2013-01-25 03:36:18 +01:00
SendBreakPacketToHost ( BreakCause , ProcessorIndex , & BreakReceived ) ;
2010-09-12 08:43:36 +02:00
}
2013-01-25 03:36:18 +01:00
ReleaseMpSpinLock ( & mDebugMpContext . DebugPortSpinLock ) ;
2012-06-11 04:15:11 +02:00
2010-09-12 08:43:36 +02:00
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 ) ;
}
2012-06-11 04:15:11 +02:00
break ;
2010-09-12 08:43:36 +02:00
}
break ;
case DEBUG_TIMER_VECTOR :
2013-01-25 03:36:18 +01:00
AcquireMpSpinLock ( & mDebugMpContext . DebugPortSpinLock ) ;
2012-06-11 04:15:11 +02:00
2013-01-25 03:36:18 +01:00
if ( MultiProcessorDebugSupport ( ) ) {
2010-09-12 08:43:36 +02:00
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 ) {
2013-01-25 03:36:18 +01:00
ReleaseMpSpinLock ( & mDebugMpContext . DebugPortSpinLock ) ;
2010-09-12 08:43:36 +02:00
//
// 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
//
2012-06-11 04:15:11 +02:00
while ( TRUE ) {
2010-09-12 08:43:36 +02:00
//
2012-06-11 04:15:11 +02:00
// If there is data in debug port, will check whether it is break(attach/break-in) symbol,
2010-09-12 08:43:36 +02:00
// If yes, go into communication mode with HOST.
// If no, exit interrupt process.
//
2012-06-11 04:15:11 +02:00
if ( DebugReadBreakSymbol ( Handle , & InputCharacter ) = = EFI_NOT_FOUND ) {
break ;
}
2013-01-25 03:36:18 +01:00
2012-06-11 04:15:11 +02:00
if ( ( ! IsHostAttached ( ) & & ( InputCharacter = = DEBUG_STARTING_SYMBOL_ATTACH ) ) | |
2013-01-25 03:36:18 +01:00
( IsHostAttached ( ) & & ( InputCharacter = = DEBUG_COMMAND_HALT ) ) | |
( IsHostAttached ( ) & & ( InputCharacter = = DEBUG_COMMAND_GO ) )
2012-06-11 04:15:11 +02:00
) {
DebugAgentMsgPrint ( DEBUG_AGENT_VERBOSE , " Received data [%02x] \n " , InputCharacter ) ;
//
// Ack OK for break-in symbol
//
2010-09-12 08:43:36 +02:00
SendAckPacket ( DEBUG_COMMAND_OK ) ;
2012-06-11 04:15:11 +02:00
2013-01-25 03:36:18 +01:00
//
// If receive GO command in Debug Timer, means HOST may lost ACK packet before.
//
if ( InputCharacter = = DEBUG_COMMAND_GO ) {
break ;
}
2012-06-11 04:15:11 +02:00
if ( ! IsHostAttached ( ) ) {
//
// Try to attach HOST, if no ack received after 200ms, return
//
2013-01-25 03:36:18 +01:00
if ( AttachHost ( BreakCause , READ_PACKET_TIMEOUT , & BreakReceived ) ! = RETURN_SUCCESS ) {
2012-06-11 04:15:11 +02:00
break ;
}
}
2013-01-25 03:36:18 +01:00
if ( MultiProcessorDebugSupport ( ) ) {
2012-06-11 04:15:11 +02:00
if ( FindNextPendingBreakCpu ( ) ! = - 1 ) {
2010-09-12 08:43:36 +02:00
SetCpuBreakFlagByIndex ( ProcessorIndex , TRUE ) ;
} else {
HaltOtherProcessors ( ProcessorIndex ) ;
}
}
2013-01-25 03:36:18 +01:00
ReleaseMpSpinLock ( & mDebugMpContext . DebugPortSpinLock ) ;
2010-09-12 08:43:36 +02:00
CommandCommunication ( Vector , CpuContext , BreakReceived ) ;
2013-01-25 03:36:18 +01:00
AcquireMpSpinLock ( & mDebugMpContext . DebugPortSpinLock ) ;
2010-09-12 08:43:36 +02:00
break ;
}
}
//
// Clear EOI before exiting interrupt process routine.
//
SendApicEoi ( ) ;
2013-01-25 03:36:18 +01:00
ReleaseMpSpinLock ( & mDebugMpContext . DebugPortSpinLock ) ;
2010-09-12 08:43:36 +02:00
break ;
default :
if ( Vector < = DEBUG_EXCEPT_SIMD ) {
2012-06-11 04:15:11 +02:00
if ( BreakCause = = DEBUG_DATA_BREAK_CAUSE_STEPPING ) {
//
// Stepping is finished, send Ack package.
//
2013-01-25 03:36:18 +01:00
if ( MultiProcessorDebugSupport ( ) ) {
2012-06-11 04:15:11 +02:00
mDebugMpContext . BreakAtCpuIndex = ProcessorIndex ;
2010-09-12 08:43:36 +02:00
}
2012-06-11 04:15:11 +02:00
SendAckPacket ( DEBUG_COMMAND_OK ) ;
} else {
//
// Exception occurs, send Break packet to HOST
//
2013-01-25 03:36:18 +01:00
AcquireMpSpinLock ( & mDebugMpContext . DebugPortSpinLock ) ;
2012-06-11 04:15:11 +02:00
//
// Only the first breaking processor could send BREAK_POINT to HOST
//
if ( IsFirstBreakProcessor ( ProcessorIndex ) ) {
2013-01-25 03:36:18 +01:00
SendBreakPacketToHost ( BreakCause , ProcessorIndex , & BreakReceived ) ;
2012-06-11 04:15:11 +02:00
}
2013-01-25 03:36:18 +01:00
ReleaseMpSpinLock ( & mDebugMpContext . DebugPortSpinLock ) ;
2010-09-12 08:43:36 +02:00
}
2012-06-11 04:15:11 +02:00
2010-09-12 08:43:36 +02:00
CommandCommunication ( Vector , CpuContext , BreakReceived ) ;
}
break ;
}
2013-01-25 03:36:18 +01:00
if ( MultiProcessorDebugSupport ( ) ) {
2010-09-12 08:43:36 +02:00
//
// Clear flag and wait for all processors run here
//
SetIpiSentByApFlag ( FALSE ) ;
2012-06-11 04:15:11 +02:00
while ( mDebugMpContext . RunCommandSet ) {
CpuPause ( ) ;
}
//
// Only current (view) processor could clean up AgentInProgress flag.
//
if ( mDebugMpContext . ViewPointIndex = = ProcessorIndex ) {
IssuedViewPoint = mDebugMpContext . ViewPointIndex ;
}
}
2013-01-25 03:36:18 +01:00
if ( IssuedViewPoint = = ProcessorIndex & & GetDebugFlag ( DEBUG_AGENT_FLAG_STEPPING ) ! = 1 ) {
2012-06-11 04:15:11 +02:00
//
2013-01-25 03:36:18 +01:00
// If the command is not stepping, clean up AgentInProgress flag
2012-06-11 04:15:11 +02:00
//
2013-01-25 03:36:18 +01:00
SetDebugFlag ( DEBUG_AGENT_FLAG_AGENT_IN_PROGRESS , 0 ) ;
2010-09-12 08:43:36 +02:00
}
return ;
}