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 .
2017-04-01 14:27:16 +02:00
Copyright ( c ) 2010 - 2017 , 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"
2014-11-04 02:29:20 +01:00
GLOBAL_REMOVE_IF_UNREFERENCED CHAR8 mErrorMsgVersionAlert [ ] = " \r The SourceLevelDebugPkg you are using requires a newer version of the Intel(R) UDK Debugger Tool. \r \n " ;
2015-09-24 05:07:04 +02:00
GLOBAL_REMOVE_IF_UNREFERENCED CHAR8 mErrorMsgSendInitPacket [ ] = " \r Send INIT break packet and try to connect the HOST (Intel(R) UDK Debugger Tool v1.5) ... \r \n " ;
2014-11-04 02:29:20 +01:00
GLOBAL_REMOVE_IF_UNREFERENCED CHAR8 mErrorMsgConnectOK [ ] = " HOST connection is successful! \r \n " ;
GLOBAL_REMOVE_IF_UNREFERENCED CHAR8 mErrorMsgConnectFail [ ] = " HOST connection is failed! \r \n " ;
GLOBAL_REMOVE_IF_UNREFERENCED CHAR8 mWarningMsgIngoreBreakpoint [ ] = " Ignore break point in SMM for SMI issued during DXE debugging! \r \n " ;
2012-06-11 04:15:11 +02:00
2013-11-22 07:30:01 +01:00
//
// Vector Handoff Info list used by Debug Agent for persist
//
2014-11-04 02:29:20 +01:00
GLOBAL_REMOVE_IF_UNREFERENCED EFI_VECTOR_HANDOFF_INFO mVectorHandoffInfoDebugAgent [ ] = {
2013-11-22 07:30:01 +01:00
{
DEBUG_EXCEPT_DIVIDE_ERROR , // Vector 0
EFI_VECTOR_HANDOFF_HOOK_BEFORE ,
EFI_DEBUG_AGENT_GUID
} ,
{
DEBUG_EXCEPT_DEBUG , // Vector 1
EFI_VECTOR_HANDOFF_DO_NOT_HOOK ,
EFI_DEBUG_AGENT_GUID
} ,
{
DEBUG_EXCEPT_NMI , // Vector 2
EFI_VECTOR_HANDOFF_HOOK_BEFORE ,
EFI_DEBUG_AGENT_GUID
} ,
{
DEBUG_EXCEPT_BREAKPOINT , // Vector 3
EFI_VECTOR_HANDOFF_DO_NOT_HOOK ,
EFI_DEBUG_AGENT_GUID
} ,
{
DEBUG_EXCEPT_OVERFLOW , // Vector 4
EFI_VECTOR_HANDOFF_HOOK_BEFORE ,
EFI_DEBUG_AGENT_GUID
} ,
{
DEBUG_EXCEPT_BOUND , // Vector 5
EFI_VECTOR_HANDOFF_HOOK_BEFORE ,
EFI_DEBUG_AGENT_GUID
} ,
{
DEBUG_EXCEPT_INVALID_OPCODE , // Vector 6
EFI_VECTOR_HANDOFF_HOOK_BEFORE ,
EFI_DEBUG_AGENT_GUID
} ,
{
DEBUG_EXCEPT_DOUBLE_FAULT , // Vector 8
EFI_VECTOR_HANDOFF_HOOK_BEFORE ,
EFI_DEBUG_AGENT_GUID
} ,
{
DEBUG_EXCEPT_INVALID_TSS , // Vector 10
EFI_VECTOR_HANDOFF_HOOK_BEFORE ,
EFI_DEBUG_AGENT_GUID
} ,
{
DEBUG_EXCEPT_SEG_NOT_PRESENT , // Vector 11
EFI_VECTOR_HANDOFF_HOOK_BEFORE ,
EFI_DEBUG_AGENT_GUID
} ,
{
DEBUG_EXCEPT_STACK_FAULT , // Vector 12
EFI_VECTOR_HANDOFF_HOOK_BEFORE ,
EFI_DEBUG_AGENT_GUID
} ,
{
DEBUG_EXCEPT_GP_FAULT , // Vector 13
EFI_VECTOR_HANDOFF_HOOK_BEFORE ,
EFI_DEBUG_AGENT_GUID
} ,
{
DEBUG_EXCEPT_PAGE_FAULT , // Vector 14
EFI_VECTOR_HANDOFF_HOOK_BEFORE ,
EFI_DEBUG_AGENT_GUID
} ,
{
DEBUG_EXCEPT_FP_ERROR , // Vector 16
EFI_VECTOR_HANDOFF_HOOK_BEFORE ,
EFI_DEBUG_AGENT_GUID
} ,
{
DEBUG_EXCEPT_ALIGNMENT_CHECK , // Vector 17
EFI_VECTOR_HANDOFF_HOOK_BEFORE ,
EFI_DEBUG_AGENT_GUID
} ,
{
DEBUG_EXCEPT_MACHINE_CHECK , // Vector 18
EFI_VECTOR_HANDOFF_HOOK_BEFORE ,
EFI_DEBUG_AGENT_GUID
} ,
{
DEBUG_EXCEPT_SIMD , // Vector 19
EFI_VECTOR_HANDOFF_HOOK_BEFORE ,
EFI_DEBUG_AGENT_GUID
} ,
{
DEBUG_TIMER_VECTOR , // Vector 32
EFI_VECTOR_HANDOFF_DO_NOT_HOOK ,
EFI_DEBUG_AGENT_GUID
} ,
{
DEBUG_MAILBOX_VECTOR , // Vector 33
EFI_VECTOR_HANDOFF_DO_NOT_HOOK ,
EFI_DEBUG_AGENT_GUID
} ,
{
0 ,
EFI_VECTOR_HANDOFF_LAST_ENTRY ,
{ 0 }
}
} ;
2014-11-04 02:29:20 +01:00
GLOBAL_REMOVE_IF_UNREFERENCED UINTN mVectorHandoffInfoCount = sizeof ( mVectorHandoffInfoDebugAgent ) / sizeof ( EFI_VECTOR_HANDOFF_INFO ) ;
2013-11-22 07:30:01 +01: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 + + ) {
2014-08-08 07:51:21 +02:00
Crc ^ = ( UINT16 ) Data [ Index ] ;
2013-01-25 03:36:18 +01:00
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 .
* */
2014-11-04 02:29:20 +01:00
BOOLEAN
2013-01-25 03:36:18 +01:00
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 .
2014-11-04 02:29:20 +01:00
2013-01-25 03:36:18 +01:00
@ param [ in ] AlignSize Image aligned size .
2014-11-04 02:29:20 +01:00
2013-01-25 03:36:18 +01:00
* */
2014-11-04 02:29:20 +01:00
VOID
2013-01-25 03:36:18 +01:00
FindAndReportModuleImageInfo (
2014-11-04 02:29:20 +01:00
IN UINTN AlignSize
2013-01-25 03:36:18 +01:00
)
{
UINTN Pe32Data ;
PE_COFF_LOADER_IMAGE_CONTEXT ImageContext ;
//
// Find Image Base
//
2017-04-24 04:06:31 +02:00
Pe32Data = PeCoffSearchImageBase ( ( UINTN ) mErrorMsgVersionAlert ) ;
2017-04-01 14:27:16 +02:00
if ( Pe32Data ! = 0 ) {
ImageContext . ImageAddress = Pe32Data ;
ImageContext . PdbPointer = PeCoffLoaderGetPdbPointer ( ( VOID * ) ( UINTN ) ImageContext . ImageAddress ) ;
PeCoffLoaderRelocateImageExtraAction ( & ImageContext ) ;
2013-01-25 03:36:18 +01:00
}
}
/**
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 ) ;
}
/**
2015-03-13 09:18:19 +01:00
Calculate Mailbox checksum and update the checksum field .
2013-01-25 03:36:18 +01:00
@ param [ in ] Mailbox Debug Agent Mailbox pointer .
* */
VOID
UpdateMailboxChecksum (
IN DEBUG_AGENT_MAILBOX * Mailbox
)
{
2014-11-04 02:29:20 +01:00
Mailbox - > CheckSum = CalculateCheckSum8 ( ( UINT8 * ) Mailbox , sizeof ( DEBUG_AGENT_MAILBOX ) - 2 ) ;
2013-01-25 03:36:18 +01:00
}
/**
Verify Mailbox checksum .
If checksum error , print debug message and run init dead loop .
@ param [ in ] Mailbox Debug Agent Mailbox pointer .
* */
2014-11-04 02:29:20 +01:00
VOID
2013-01-25 03:36:18 +01:00
VerifyMailboxChecksum (
IN DEBUG_AGENT_MAILBOX * Mailbox
)
{
UINT8 CheckSum ;
2014-11-04 02:29:20 +01:00
2013-01-25 03:36:18 +01:00
CheckSum = CalculateCheckSum8 ( ( UINT8 * ) Mailbox , sizeof ( DEBUG_AGENT_MAILBOX ) - 2 ) ;
//
2014-11-04 02:29:20 +01:00
// The checksum updating process may be disturbed by hardware SMI, we need to check CheckSum field
2013-01-25 03:36:18 +01:00
// 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 .
2014-11-04 02:29:20 +01:00
2013-01-25 03:36:18 +01:00
* */
VOID
2014-11-04 02:29:20 +01:00
UpdateMailboxContent (
2013-01-25 03:36:18 +01:00
IN DEBUG_AGENT_MAILBOX * Mailbox ,
IN UINTN Index ,
IN UINT64 Value
)
{
AcquireMpSpinLock ( & mDebugMpContext . MailboxSpinLock ) ;
switch ( Index ) {
case DEBUG_MAILBOX_DEBUG_FLAG_INDEX :
2014-11-04 02:29:20 +01:00
Mailbox - > ToBeCheckSum = Mailbox - > CheckSum + CalculateSum8 ( ( UINT8 * ) & Mailbox - > DebugFlag . Uint64 , sizeof ( UINT64 ) )
2013-01-25 03:36:18 +01:00
- 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 ;
2015-04-01 09:51:15 +02:00
case DEBUG_MAILBOX_DEBUG_TIMER_FREQUENCY :
2015-04-10 10:52:48 +02:00
Mailbox - > ToBeCheckSum = Mailbox - > CheckSum + CalculateSum8 ( ( UINT8 * ) & Mailbox - > DebugTimerFrequency , sizeof ( UINT32 ) )
2015-04-01 09:51:15 +02:00
- CalculateSum8 ( ( UINT8 * ) & Value , sizeof ( UINT32 ) ) ;
Mailbox - > DebugTimerFrequency = ( UINT32 ) Value ;
break ;
2013-01-25 03:36:18 +01:00
}
UpdateMailboxChecksum ( Mailbox ) ;
ReleaseMpSpinLock ( & mDebugMpContext . MailboxSpinLock ) ;
}
2015-04-01 09:51:15 +02:00
/**
Read data from debug device and save the data in buffer .
Reads NumberOfBytes data bytes from a debug device into the buffer
specified by Buffer . The number of bytes actually read is returned .
If the return value is less than NumberOfBytes , then the rest operation failed .
If NumberOfBytes is zero , then return 0.
@ param Handle Debug port handle .
@ param Buffer Pointer to the data buffer to store the data read from the debug device .
@ param NumberOfBytes Number of bytes which will be read .
@ param Timeout Timeout value for reading from debug device . It unit is Microsecond .
@ retval 0 Read data failed , no data is to be read .
@ retval > 0 Actual number of bytes read from debug device .
* */
UINTN
DebugAgentReadBuffer (
IN DEBUG_PORT_HANDLE Handle ,
IN UINT8 * Buffer ,
IN UINTN NumberOfBytes ,
IN UINTN Timeout
)
{
UINTN Index ;
UINT32 Begin ;
UINT32 TimeoutTicker ;
UINT32 TimerRound ;
UINT32 TimerFrequency ;
UINT32 TimerCycle ;
Begin = 0 ;
TimeoutTicker = 0 ;
TimerRound = 0 ;
TimerFrequency = GetMailboxPointer ( ) - > DebugTimerFrequency ;
TimerCycle = GetApicTimerInitCount ( ) ;
if ( Timeout ! = 0 ) {
Begin = GetApicTimerCurrentCount ( ) ;
TimeoutTicker = ( UINT32 ) DivU64x32 (
MultU64x64 (
TimerFrequency ,
Timeout
) ,
1000000u
) ;
TimerRound = ( UINT32 ) DivU64x32Remainder ( TimeoutTicker , TimerCycle / 2 , & TimeoutTicker ) ;
}
Index = 0 ;
while ( Index < NumberOfBytes ) {
if ( DebugPortPollBuffer ( Handle ) ) {
DebugPortReadBuffer ( Handle , Buffer + Index , 1 , 0 ) ;
Index + + ;
continue ;
}
if ( Timeout ! = 0 ) {
if ( TimerRound = = 0 ) {
if ( IsDebugTimerTimeout ( TimerCycle , Begin , TimeoutTicker ) ) {
//
// If time out occurs.
//
return 0 ;
}
} else {
if ( IsDebugTimerTimeout ( TimerCycle , Begin , TimerCycle / 2 ) ) {
TimerRound - - ;
Begin = GetApicTimerCurrentCount ( ) ;
}
}
}
}
return Index ;
}
2013-01-25 03:36:18 +01:00
/**
Set debug flag in mailbox .
@ param [ in ] FlagMask Debug flag mask value .
@ param [ in ] FlagValue Debug flag value .
* */
2014-11-04 02:29:20 +01:00
VOID
2013-01-25 03:36:18 +01:00
SetDebugFlag (
IN UINT64 FlagMask ,
2014-11-04 02:29:20 +01:00
IN UINT32 FlagValue
2013-01-25 03:36:18 +01:00
)
{
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 .
2014-11-04 02:29:20 +01:00
2013-01-25 03:36:18 +01:00
@ 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 ,
2014-11-04 02:29:20 +01:00
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 ;
2014-11-04 02:29:20 +01:00
2012-06-11 04:15:11 +02:00
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 .
2014-11-04 02:29:20 +01:00
@ param [ in ] . . . Variable argument list whose contents are accessed
2012-06-11 04:15:11 +02:00
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 .
2014-11-04 02:29:20 +01:00
If any bit in ErrorLevel is also set in DebugPrintErrorLevelLib function
GetDebugPrintErrorLevel ( ) , then print the message specified by Format and the
2012-06-11 04:15:11 +02:00
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 .
2014-11-04 02:29:20 +01:00
@ param [ in ] Data Variable argument list whose contents are accessed
2012-06-11 04:15:11 +02:00
@ 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 ,
2014-11-04 02:29:20 +01:00
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 ) {
//
2014-11-04 02:29:20 +01:00
// If there was no enough space in buffer, send out the debug message,
2012-06-11 04:15:11 +02:00
// 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 .
2013-12-20 06:49:15 +01:00
@ retval EFI_DEVICE_ERROR Receive the old or responsed packet .
2013-01-25 03:36:18 +01:00
* */
EFI_STATUS
ReadRemainingBreakPacket (
IN DEBUG_PORT_HANDLE Handle ,
IN OUT DEBUG_PACKET_HEADER * DebugHeader
)
{
UINT16 Crc ;
2013-12-20 06:49:15 +01:00
DEBUG_AGENT_MAILBOX * Mailbox ;
2013-01-25 03:36:18 +01:00
//
// Has received start symbol, try to read the rest part
//
2015-04-01 09:51:15 +02:00
if ( DebugAgentReadBuffer ( Handle , ( UINT8 * ) DebugHeader + OFFSET_OF ( DEBUG_PACKET_HEADER , Command ) , sizeof ( DEBUG_PACKET_HEADER ) - OFFSET_OF ( DEBUG_PACKET_HEADER , Command ) , READ_PACKET_TIMEOUT ) = = 0 ) {
2013-01-25 03:36:18 +01:00
//
// 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 ;
}
2013-12-20 06:49:15 +01:00
Mailbox = GetMailboxPointer ( ) ;
2014-11-10 09:47:49 +01:00
if ( IS_REQUEST ( DebugHeader ) ) {
if ( DebugHeader - > SequenceNo = = ( UINT8 ) ( Mailbox - > HostSequenceNo + 1 ) ) {
//
// Only updagte HostSequenceNo for new command packet
//
UpdateMailboxContent ( Mailbox , DEBUG_MAILBOX_HOST_SEQUENCE_NO_INDEX , DebugHeader - > SequenceNo ) ;
return EFI_SUCCESS ;
}
if ( DebugHeader - > SequenceNo = = Mailbox - > HostSequenceNo ) {
return EFI_SUCCESS ;
}
2013-12-20 06:49:15 +01:00
}
2014-11-10 09:47:49 +01:00
return EFI_DEVICE_ERROR ;
2013-01-25 03:36:18 +01:00
}
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 .
2014-11-04 02:29:20 +01:00
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 .
2014-11-04 02:29:20 +01:00
2012-06-11 04:15:11 +02:00
@ retval RETURN_SUCCESS The setting is set successfully .
@ retval RETURN_UNSUPPORTED The Key value is not supported .
* */
RETURN_STATUS
SetDebugSetting (
2014-11-04 02:29:20 +01:00
IN DEBUG_DATA_SET_DEBUG_SETTING * DebugSetting
2012-06-11 04:15:11 +02:00
)
{
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 ;
}
/**
2015-04-27 07:23:43 +02:00
Execute Stepping command .
2010-09-12 08:43:36 +02:00
@ 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 ;
2015-04-27 07:23:43 +02:00
//
// Save and clear EFLAGS.IF to avoid interrupt happen when executing Stepping
//
SetDebugFlag ( DEBUG_AGENT_FLAG_INTERRUPT_FLAG , Eflags - > Bits . IF ) ;
Eflags - > Bits . IF = 0 ;
//
// Set Stepping Flag
//
SetDebugFlag ( DEBUG_AGENT_FLAG_STEPPING , 1 ) ;
}
/**
Do some cleanup after Stepping command done .
@ param [ in ] CpuContext Pointer to saved CPU context .
* */
VOID
CommandSteppingCleanup (
IN DEBUG_CPU_CONTEXT * CpuContext
)
{
IA32_EFLAGS32 * Eflags ;
Eflags = ( IA32_EFLAGS32 * ) & CpuContext - > Eflags ;
//
// Restore EFLAGS.IF
//
Eflags - > Bits . IF = GetDebugFlag ( DEBUG_AGENT_FLAG_INTERRUPT_FLAG ) ;
//
// Clear Stepping flag
//
SetDebugFlag ( DEBUG_AGENT_FLAG_STEPPING , 0 ) ;
2010-09-12 08:43:36 +02:00
}
/**
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
//
2014-08-08 07:51:21 +02:00
Dr7Value | = ( UINTN ) ( 0x3 < < ( RegisterIndex * 2 ) ) ;
2010-09-12 08:43:36 +02:00
//
// Set RWx and Lenx
//
2014-08-08 07:51:21 +02:00
Dr7Value & = ( UINTN ) ( ~ ( 0xf < < ( 16 + RegisterIndex * 4 ) ) ) ;
2012-06-11 04:15:11 +02:00
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 ;
2014-08-08 07:51:21 +02:00
CpuContext - > Dr7 & = ( UINTN ) ( ~ ( 0x3 < < 0 ) ) ;
2010-09-12 08:43:36 +02:00
}
if ( ( ClearHwBreakpoint - > IndexMask & BIT1 ) ! = 0 ) {
CpuContext - > Dr1 = 0 ;
2014-08-08 07:51:21 +02:00
CpuContext - > Dr7 & = ( UINTN ) ( ~ ( 0x3 < < 2 ) ) ;
2010-09-12 08:43:36 +02:00
}
if ( ( ClearHwBreakpoint - > IndexMask & BIT2 ) ! = 0 ) {
CpuContext - > Dr2 = 0 ;
2014-08-08 07:51:21 +02:00
CpuContext - > Dr7 & = ( UINTN ) ( ~ ( 0x3 < < 4 ) ) ;
2010-09-12 08:43:36 +02:00
}
if ( ( ClearHwBreakpoint - > IndexMask & BIT3 ) ! = 0 ) {
CpuContext - > Dr3 = 0 ;
2014-08-08 07:51:21 +02:00
CpuContext - > Dr7 & = ( UINTN ) ( ~ ( 0x3 < < 6 ) ) ;
2010-09-12 08:43:36 +02:00
}
}
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
}
2015-01-20 09:46:31 +01:00
/**
Decompress the Data in place .
@ param [ in , out ] Data The compressed data buffer .
The buffer is assumed large enough to hold the uncompressed data .
@ param [ in ] Length The length of the compressed data buffer .
@ return The length of the uncompressed data buffer .
* */
UINT8
DecompressDataInPlace (
IN OUT UINT8 * Data ,
IN UINTN Length
)
{
UINTN Index ;
UINT16 LastChar ;
UINTN LastCharCount ;
UINT8 CurrentChar ;
LastChar = ( UINT16 ) - 1 ;
LastCharCount = 0 ;
for ( Index = 0 ; Index < Length ; Index + + ) {
CurrentChar = Data [ Index ] ;
if ( LastCharCount = = 2 ) {
LastCharCount = 0 ;
CopyMem ( & Data [ Index + CurrentChar ] , & Data [ Index + 1 ] , Length - Index - 1 ) ;
SetMem ( & Data [ Index ] , CurrentChar , ( UINT8 ) LastChar ) ;
LastChar = ( UINT16 ) - 1 ;
Index + = CurrentChar - 1 ;
Length + = CurrentChar - 1 ;
} else {
if ( LastChar ! = CurrentChar ) {
LastCharCount = 0 ;
}
LastCharCount + + ;
LastChar = CurrentChar ;
}
}
ASSERT ( Length < = DEBUG_DATA_MAXIMUM_REAL_DATA ) ;
return ( UINT8 ) Length ;
}
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 ;
}
2014-11-04 02:29:20 +01:00
2013-01-25 03:36:18 +01:00
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
//
2015-04-01 09:51:15 +02:00
Received = DebugAgentReadBuffer ( Handle , & DebugHeader - > StartSymbol , sizeof ( DebugHeader - > StartSymbol ) , TimeoutForStartSymbol ) ;
2013-01-25 03:36:18 +01:00
if ( Received < sizeof ( DebugHeader - > StartSymbol ) ) {
2015-04-01 09:51:15 +02:00
DebugAgentMsgPrint ( DEBUG_AGENT_WARNING , " DebugAgentReadBuffer(StartSymbol) timeout \n " ) ;
2010-09-12 08:43:36 +02:00
return RETURN_TIMEOUT ;
}
2013-01-25 03:36:18 +01:00
2015-01-20 09:46:31 +01:00
if ( ( DebugHeader - > StartSymbol ! = DEBUG_STARTING_SYMBOL_NORMAL ) & & ( DebugHeader - > StartSymbol ! = DEBUG_STARTING_SYMBOL_COMPRESS ) ) {
2013-01-25 03:36:18 +01:00
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
//
2015-04-01 09:51:15 +02:00
Received = DebugAgentReadBuffer (
2013-01-25 03:36:18 +01:00
Handle ,
2015-01-20 09:46:31 +01:00
( UINT8 * ) DebugHeader + OFFSET_OF ( DEBUG_PACKET_HEADER , Command ) ,
2013-01-25 03:36:18 +01:00
OFFSET_OF ( DEBUG_PACKET_HEADER , Length ) + sizeof ( DebugHeader - > Length ) - sizeof ( DebugHeader - > StartSymbol ) ,
Timeout
) ;
if ( Received = = 0 ) {
2015-04-01 09:51:15 +02:00
DebugAgentMsgPrint ( DEBUG_AGENT_ERROR , " DebugAgentReadBuffer(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
//
2015-04-01 09:51:15 +02:00
Received = DebugAgentReadBuffer ( Handle , & DebugHeader - > SequenceNo , ( UINT8 ) ( DebugHeader - > Length - OFFSET_OF ( DEBUG_PACKET_HEADER , SequenceNo ) ) , Timeout ) ;
2013-01-25 03:36:18 +01:00
if ( Received = = 0 ) {
2015-04-01 09:51:15 +02:00
DebugAgentMsgPrint ( DEBUG_AGENT_ERROR , " DebugAgentReadBuffer(SequenceNo) timeout \n " ) ;
2013-01-25 03:36:18 +01:00
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 ) ;
2015-01-20 09:46:31 +01:00
if ( DebugHeader - > StartSymbol = = DEBUG_STARTING_SYMBOL_COMPRESS ) {
DebugHeader - > StartSymbol = DEBUG_STARTING_SYMBOL_NORMAL ;
DebugHeader - > Length = DecompressDataInPlace (
( UINT8 * ) ( DebugHeader + 1 ) , DebugHeader - > Length - sizeof ( DEBUG_PACKET_HEADER )
) + sizeof ( DEBUG_PACKET_HEADER ) ;
}
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
//
2015-04-27 07:26:03 +02:00
// DR6.BIT14 Indicates (when set) that the debug exception was
// triggered by the single step execution mode.
// The single-step mode is the highest priority debug exception.
// This is single step, no need to check DR0, to ensure single step
// work in PeCoffExtraActionLib (right after triggering a breakpoint
// to report image load/unload).
2010-09-13 04:42:14 +02:00
//
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 ) {
2014-11-04 02:29:20 +01:00
Cause = ( UINT8 ) ( ( CpuContext - > Dr0 = = IMAGE_LOAD_SIGNATURE ) ?
2010-09-12 08:43:36 +02:00
DEBUG_DATA_BREAK_CAUSE_IMAGE_LOAD : DEBUG_DATA_BREAK_CAUSE_IMAGE_UNLOAD ) ;
}
break ;
case SOFT_INTERRUPT_SIGNATURE :
2014-11-04 02:29:20 +01:00
2010-09-12 08:43:36 +02:00
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-05-06 09:36:32 +02:00
Copy memory from source to destination with specified width .
@ param [ out ] Dest A pointer to the destination buffer of the memory copy .
@ param [ in ] Src A pointer to the source buffer of the memory copy .
@ param [ in ] Count The number of data with specified width to copy from source to destination .
@ param [ in ] Width Data width in byte .
* */
VOID
CopyMemByWidth (
OUT UINT8 * Dest ,
IN UINT8 * Src ,
IN UINT16 Count ,
IN UINT8 Width
)
{
UINT8 * Destination ;
UINT8 * Source ;
INT8 Step ;
if ( Src > Dest ) {
Destination = Dest ;
Source = Src ;
Step = Width ;
} else {
//
// Copy memory from tail to avoid memory overlap
//
Destination = Dest + ( Count - 1 ) * Width ;
Source = Src + ( Count - 1 ) * Width ;
Step = - Width ;
}
while ( Count - - ! = 0 ) {
switch ( Width ) {
case 1 :
* ( UINT8 * ) Destination = MmioRead8 ( ( UINTN ) Source ) ;
break ;
case 2 :
* ( UINT16 * ) Destination = MmioRead16 ( ( UINTN ) Source ) ;
break ;
case 4 :
* ( UINT32 * ) Destination = MmioRead32 ( ( UINTN ) Source ) ;
break ;
case 8 :
* ( UINT64 * ) Destination = MmioRead64 ( ( UINTN ) Source ) ;
break ;
default :
ASSERT ( FALSE ) ;
}
Source + = Step ;
Destination + = Step ;
}
}
2015-01-20 09:46:31 +01:00
/**
Compress the data buffer but do not modify the original buffer .
The compressed data is directly send to the debug channel .
Compressing in place doesn ' t work because the data may become larger
during compressing phase . ( " 3 3 ... " - - > " 3 3 0 ... " )
The routine is expected to be called three times :
1. Compute the length of the compressed data buffer ;
2. Compute the CRC of the compressed data buffer ;
3. Compress the data and send to the debug channel .
2015-05-18 07:29:01 +02:00
@ param [ in ] Handle The debug channel handle to send the compressed data buffer .
2015-01-20 09:46:31 +01:00
@ param [ in ] Data The data buffer .
@ param [ in ] Length The length of the data buffer .
2015-05-18 07:29:01 +02:00
@ param [ in ] Send TRUE to send the compressed data buffer .
2015-01-20 09:46:31 +01:00
@ param [ out ] CompressedLength Return the length of the compressed data buffer .
It may be larger than the Length in some cases .
@ param [ out ] CompressedCrc Return the CRC of the compressed data buffer .
* */
VOID
2015-05-18 07:29:01 +02:00
CompressData (
IN DEBUG_PORT_HANDLE Handle ,
2015-01-20 09:46:31 +01:00
IN UINT8 * Data ,
IN UINT8 Length ,
2015-05-18 07:29:01 +02:00
IN BOOLEAN Send ,
2015-01-20 09:46:31 +01:00
OUT UINTN * CompressedLength , OPTIONAL
2015-05-18 07:29:01 +02:00
OUT UINT16 * CompressedCrc OPTIONAL
2015-01-20 09:46:31 +01:00
)
{
2015-05-18 07:29:01 +02:00
UINTN Index ;
UINT8 LastChar ;
UINT8 LastCharCount ;
UINT8 CurrentChar ;
UINTN CompressedIndex ;
2015-01-20 09:46:31 +01:00
ASSERT ( Length > 0 ) ;
2015-05-18 07:29:01 +02:00
LastChar = Data [ 0 ] + 1 ; // Just ensure it's different from the first byte.
2015-01-20 09:46:31 +01:00
LastCharCount = 0 ;
for ( Index = 0 , CompressedIndex = 0 ; Index < = Length ; Index + + ) {
if ( Index < Length ) {
CurrentChar = Data [ Index ] ;
} else {
CurrentChar = ( UINT8 ) LastChar + 1 ; // just ensure it's different from LastChar
}
if ( LastChar ! = CurrentChar ) {
if ( LastCharCount = = 1 ) {
CompressedIndex + + ;
if ( CompressedCrc ! = NULL ) {
* CompressedCrc = CalculateCrc16 ( & LastChar , 1 , * CompressedCrc ) ;
}
2015-05-18 07:29:01 +02:00
if ( Send ) {
2015-01-20 09:46:31 +01:00
DebugPortWriteBuffer ( Handle , & LastChar , 1 ) ;
}
} else if ( LastCharCount > = 2 ) {
CompressedIndex + = 3 ;
LastCharCount - = 2 ;
if ( CompressedCrc ! = NULL ) {
* CompressedCrc = CalculateCrc16 ( & LastChar , 1 , * CompressedCrc ) ;
* CompressedCrc = CalculateCrc16 ( & LastChar , 1 , * CompressedCrc ) ;
* CompressedCrc = CalculateCrc16 ( & LastCharCount , 1 , * CompressedCrc ) ;
}
2015-05-18 07:29:01 +02:00
if ( Send ) {
2015-01-20 09:46:31 +01:00
DebugPortWriteBuffer ( Handle , & LastChar , 1 ) ;
DebugPortWriteBuffer ( Handle , & LastChar , 1 ) ;
DebugPortWriteBuffer ( Handle , & LastCharCount , 1 ) ;
}
}
LastCharCount = 0 ;
}
LastCharCount + + ;
LastChar = CurrentChar ;
}
if ( CompressedLength ! = NULL ) {
* CompressedLength = CompressedIndex ;
}
}
2013-05-06 09:36:32 +02:00
/**
Read memory with speicifed width and send packet with response data to HOST .
2010-09-12 08:43:36 +02:00
@ param [ in ] Data Pointer to response data buffer .
2013-05-06 09:36:32 +02:00
@ param [ in ] Count The number of data with specified Width .
@ param [ in ] Width Data width in byte .
2015-01-20 09:46:31 +01:00
@ param [ in ] DebugHeader Pointer to a buffer for creating response packet and receiving ACK packet ,
to minimize the stack usage .
2010-09-12 08:43:36 +02:00
@ retval RETURN_SUCCESS Response data was sent successfully .
* */
RETURN_STATUS
2013-05-06 09:36:32 +02:00
ReadMemoryAndSendResponsePacket (
2015-01-20 09:46:31 +01:00
IN UINT8 * Data ,
IN UINT16 Count ,
IN UINT8 Width ,
IN DEBUG_PACKET_HEADER * DebugHeader
2010-09-12 08:43:36 +02:00
)
{
2013-01-25 03:36:18 +01:00
RETURN_STATUS Status ;
2010-09-12 08:43:36 +02:00
BOOLEAN LastPacket ;
DEBUG_PORT_HANDLE Handle ;
2013-01-25 03:36:18 +01:00
UINT8 SequenceNo ;
2013-05-06 09:36:32 +02:00
UINTN RemainingDataSize ;
2015-01-20 09:46:31 +01:00
UINT8 CurrentDataSize ;
UINTN CompressedDataSize ;
2010-09-12 08:43:36 +02:00
Handle = GetDebugPortHandle ( ) ;
2013-05-06 09:36:32 +02:00
RemainingDataSize = Count * Width ;
2010-09-12 08:43:36 +02:00
while ( TRUE ) {
2013-01-25 03:36:18 +01:00
SequenceNo = GetMailboxPointer ( ) - > HostSequenceNo ;
2013-05-06 09:36:32 +02:00
if ( RemainingDataSize < = DEBUG_DATA_MAXIMUM_REAL_DATA ) {
//
// If the remaining data is less one real packet size, this is the last data packet
//
2015-01-20 09:46:31 +01:00
CurrentDataSize = ( UINT8 ) RemainingDataSize ;
2010-09-12 08:43:36 +02:00
LastPacket = TRUE ;
2013-05-06 09:36:32 +02:00
DebugHeader - > Command = DEBUG_COMMAND_OK ;
2010-09-12 08:43:36 +02:00
} else {
2013-05-06 09:36:32 +02:00
//
// Data is too larger to be sent in one packet, calculate the actual data size could
// be sent in one Maximum data packet
//
CurrentDataSize = ( DEBUG_DATA_MAXIMUM_REAL_DATA / Width ) * Width ;
2010-09-12 08:43:36 +02:00
LastPacket = FALSE ;
2013-05-06 09:36:32 +02:00
DebugHeader - > Command = DEBUG_COMMAND_IN_PROGRESS ;
2010-09-12 08:43:36 +02:00
}
2012-06-11 04:15:11 +02:00
//
2013-05-06 09:36:32 +02:00
// Construct the rest Debug header
//
2015-01-20 09:46:31 +01:00
DebugHeader - > StartSymbol = DEBUG_STARTING_SYMBOL_NORMAL ;
DebugHeader - > Length = CurrentDataSize + sizeof ( DEBUG_PACKET_HEADER ) ;
DebugHeader - > SequenceNo = SequenceNo ;
DebugHeader - > Crc = 0 ;
CopyMemByWidth ( ( UINT8 * ) ( DebugHeader + 1 ) , Data , CurrentDataSize / Width , Width ) ;
2013-05-06 09:36:32 +02:00
//
2015-01-20 09:46:31 +01:00
// Compression/decompression support was added since revision 0.4.
// Revision 0.3 shouldn't compress the packet.
2012-06-11 04:15:11 +02:00
//
2017-09-01 03:32:10 +02:00
if ( PcdGet32 ( PcdTransferProtocolRevision ) > = DEBUG_AGENT_REVISION_04 ) {
2015-01-20 09:46:31 +01:00
//
// Get the compressed data size without modifying the packet.
//
2015-05-18 07:29:01 +02:00
CompressData (
Handle ,
2015-01-20 09:46:31 +01:00
( UINT8 * ) ( DebugHeader + 1 ) ,
CurrentDataSize ,
2015-05-18 07:29:01 +02:00
FALSE ,
2015-01-20 09:46:31 +01:00
& CompressedDataSize ,
NULL
) ;
} else {
CompressedDataSize = CurrentDataSize ;
}
if ( CompressedDataSize < CurrentDataSize ) {
DebugHeader - > Length = ( UINT8 ) CompressedDataSize + sizeof ( DEBUG_PACKET_HEADER ) ;
DebugHeader - > StartSymbol = DEBUG_STARTING_SYMBOL_COMPRESS ;
//
// Compute the CRC of the packet head without modifying the packet.
//
DebugHeader - > Crc = CalculateCrc16 ( ( UINT8 * ) DebugHeader , sizeof ( DEBUG_PACKET_HEADER ) , 0 ) ;
2015-05-18 07:29:01 +02:00
CompressData (
Handle ,
2015-01-20 09:46:31 +01:00
( UINT8 * ) ( DebugHeader + 1 ) ,
CurrentDataSize ,
2015-05-18 07:29:01 +02:00
FALSE ,
2015-01-20 09:46:31 +01:00
NULL ,
2015-05-18 07:29:01 +02:00
& DebugHeader - > Crc
2015-01-20 09:46:31 +01:00
) ;
//
// Send out the packet head.
//
DebugPortWriteBuffer ( Handle , ( UINT8 * ) DebugHeader , sizeof ( DEBUG_PACKET_HEADER ) ) ;
//
// Compress and send out the packet data.
//
2015-05-18 07:29:01 +02:00
CompressData (
Handle ,
2015-01-20 09:46:31 +01:00
( UINT8 * ) ( DebugHeader + 1 ) ,
CurrentDataSize ,
2015-05-18 07:29:01 +02:00
TRUE ,
2015-01-20 09:46:31 +01:00
NULL ,
2015-05-18 07:29:01 +02:00
NULL
2015-01-20 09:46:31 +01:00
) ;
} else {
2012-06-11 04:15:11 +02:00
2015-01-20 09:46:31 +01:00
//
// Calculate and fill the checksum, DebugHeader->Crc should be 0 before invoking CalculateCrc16 ()
//
DebugHeader - > Crc = CalculateCrc16 ( ( UINT8 * ) DebugHeader , DebugHeader - > Length , 0 ) ;
2014-11-04 02:29:20 +01:00
2015-01-20 09:46:31 +01: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 ) {
2015-01-20 09:46:31 +01:00
Status = ReceivePacket ( ( UINT8 * ) DebugHeader , NULL , NULL , READ_PACKET_TIMEOUT , FALSE ) ;
2013-01-25 03:36:18 +01:00
if ( Status = = RETURN_TIMEOUT ) {
DebugAgentMsgPrint ( DEBUG_AGENT_WARNING , " TARGET: Timeout in SendDataResponsePacket() \n " ) ;
break ;
}
2015-01-20 09:46:31 +01:00
if ( ( DebugHeader - > Command = = DEBUG_COMMAND_OK ) & & ( DebugHeader - > SequenceNo = = SequenceNo ) & & LastPacket ) {
2010-09-12 08:43:36 +02:00
//
// If this is the last packet, return RETURN_SUCCESS.
//
return RETURN_SUCCESS ;
}
2015-01-20 09:46:31 +01:00
if ( ( DebugHeader - > Command = = DEBUG_COMMAND_CONTINUE ) & & ( DebugHeader - > SequenceNo = = ( UINT8 ) ( SequenceNo + 1 ) ) ) {
2013-01-25 03:36:18 +01:00
//
2013-05-06 09:36:32 +02:00
// Calculate the rest data size
2013-01-25 03:36:18 +01:00
//
2013-05-06 09:36:32 +02:00
Data + = CurrentDataSize ;
RemainingDataSize - = CurrentDataSize ;
2015-01-20 09:46:31 +01:00
UpdateMailboxContent ( GetMailboxPointer ( ) , DEBUG_MAILBOX_HOST_SEQUENCE_NO_INDEX , DebugHeader - > SequenceNo ) ;
2013-01-25 03:36:18 +01:00
break ;
}
2015-01-20 09:46:31 +01:00
if ( DebugHeader - > SequenceNo > = SequenceNo ) {
2013-01-25 03:36:18 +01:00
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
}
}
}
2013-05-06 09:36:32 +02:00
/**
Send packet with response data to HOST .
2015-01-20 09:46:31 +01:00
@ param [ in ] Data Pointer to response data buffer .
@ param [ in ] DataSize Size of response data in byte .
@ param [ in , out ] DebugHeader Pointer to a buffer for creating response packet and receiving ACK packet ,
to minimize the stack usage .
2013-05-06 09:36:32 +02:00
@ retval RETURN_SUCCESS Response data was sent successfully .
* */
RETURN_STATUS
SendDataResponsePacket (
2015-01-20 09:46:31 +01:00
IN UINT8 * Data ,
IN UINT16 DataSize ,
IN OUT DEBUG_PACKET_HEADER * DebugHeader
2010-09-12 08:43:36 +02:00
)
{
2015-01-20 09:46:31 +01:00
return ReadMemoryAndSendResponsePacket ( Data , DataSize , 1 , DebugHeader ) ;
2010-09-12 08:43:36 +02:00
}
2012-06-11 04:15:11 +02:00
/**
Try to attach the HOST .
2014-11-04 02:29:20 +01:00
2012-06-11 04:15:11 +02:00
Send init break packet to HOST :
2014-11-04 02:29:20 +01:00
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 ( ) ;
2014-11-04 02:29:20 +01:00
2012-06-11 04:15:11 +02:00
//
// 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
//
2017-09-01 03:32:10 +02:00
// If the incompatible Debug Packet received, the HOST should be running transfer protocol before PcdTransferProtocolRevision.
2013-01-25 03:36:18 +01:00
// 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 ( ) ;
}
2014-11-04 02:29:20 +01:00
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 ;
}
/**
2014-11-04 02:29:20 +01:00
Send Break point packet to HOST .
2012-06-11 04:15:11 +02:00
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 .
2014-11-04 02:29:20 +01:00
2012-06-11 04:15:11 +02:00
* */
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 ;
2014-11-04 02:29:20 +01:00
2012-06-11 04:15:11 +02:00
Handle = GetDebugPortHandle ( ) ;
2014-11-04 02:29:20 +01:00
2012-06-11 04:15:11 +02:00
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
2014-11-04 02:29:20 +01:00
//
2012-06-11 04:15:11 +02:00
do {
2015-04-01 09:51:15 +02:00
DebugAgentReadBuffer ( Handle , & InputCharacter , 1 , 0 ) ;
2012-06-11 04:15:11 +02:00
} while ( InputCharacter ! = DEBUG_STARTING_SYMBOL_ATTACH ) ;
SendAckPacket ( DEBUG_COMMAND_OK ) ;
2014-11-04 02:29:20 +01:00
2012-06-11 04:15:11 +02:00
//
// Try to attach HOST
//
2013-01-25 03:36:18 +01:00
while ( AttachHost ( BreakCause , 0 , NULL ) ! = RETURN_SUCCESS ) ;
2014-11-04 02:29:20 +01:00
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 ;
2013-05-06 09:36:32 +02:00
UINT8 InputPacketBuffer [ DEBUG_DATA_UPPER_LIMIT + sizeof ( UINT64 ) - 1 ] ;
2012-06-11 04:15:11 +02:00
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 ;
2015-01-20 09:46:31 +01:00
DEBUG_DATA_RESPONSE_BREAK_CAUSE BreakCause ;
2012-06-11 04:15:11 +02:00
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_AGENT_EXCEPTION_BUFFER AgentExceptionBuffer ;
UINT32 IssuedViewPoint ;
2013-01-25 03:36:18 +01:00
DEBUG_AGENT_MAILBOX * Mailbox ;
2013-05-06 09:36:32 +02:00
UINT8 * AlignedDataPtr ;
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 ) {
//
2014-11-04 02:29:20 +01:00
// Only the current view processor could set AgentInProgress Flag.
2012-06-11 04:15:11 +02:00
//
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 ) ;
2014-11-04 02:29:20 +01:00
}
2012-06-11 04:15:11 +02:00
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 " ) ;
2015-01-20 09:46:31 +01:00
Status = ReceivePacket ( ( UINT8 * ) DebugHeader , & BreakReceived , NULL , READ_PACKET_TIMEOUT , TRUE ) ;
2014-11-10 09:47:49 +01:00
if ( Status ! = RETURN_SUCCESS | | ! IS_REQUEST ( DebugHeader ) ) {
2013-01-25 03:36:18 +01:00
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 ;
}
2014-11-04 02:29:20 +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 ) ;
2014-11-04 02:29:20 +01:00
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 ;
}
2014-11-04 02:29:20 +01: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 ) {
//
2014-11-04 02:29:20 +01:00
// If there are still others processors being in break state,
2010-09-12 08:43:36 +02:00
// 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 ( ) ;
//
2014-11-04 02:29:20 +01:00
// Wait for all processors are in running state
2010-09-12 08:43:36 +02:00
//
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 :
2015-01-20 09:46:31 +01:00
BreakCause . StopAddress = CpuContext - > Eip ;
2013-01-25 03:36:18 +01:00
if ( MultiProcessorDebugSupport ( ) & & ProcessorIndex ! = mDebugMpContext . BreakAtCpuIndex ) {
2015-01-20 09:46:31 +01:00
BreakCause . Cause = GetBreakCause ( DEBUG_TIMER_VECTOR , CpuContext ) ;
2010-09-12 08:43:36 +02:00
} else {
2015-01-20 09:46:31 +01:00
BreakCause . Cause = GetBreakCause ( Vector , CpuContext ) ;
2010-09-12 08:43:36 +02:00
}
2015-01-20 09:46:31 +01:00
SendDataResponsePacket ( ( UINT8 * ) & BreakCause , ( UINT16 ) sizeof ( DEBUG_DATA_RESPONSE_BREAK_CAUSE ) , DebugHeader ) ;
2010-09-12 08:43:36 +02:00
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 ) ;
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
// 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 ;
2015-01-20 09:46:31 +01:00
Status = SendDataResponsePacket ( ( UINT8 * ) & Data8 , ( UINT16 ) sizeof ( UINT8 ) , DebugHeader ) ;
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 ) ;
2015-01-20 09:46:31 +01:00
Status = ReadMemoryAndSendResponsePacket ( ( UINT8 * ) ( UINTN ) MemoryRead - > Address , MemoryRead - > Count , MemoryRead - > Width , DebugHeader ) ;
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 ) ;
2013-05-06 09:36:32 +02:00
//
// Copy data into one memory with 8-byte alignment address
//
AlignedDataPtr = ALIGN_POINTER ( ( UINT8 * ) & MemoryWrite - > Data , sizeof ( UINT64 ) ) ;
if ( AlignedDataPtr ! = ( UINT8 * ) & MemoryWrite - > Data ) {
CopyMem ( AlignedDataPtr , ( UINT8 * ) & MemoryWrite - > Data , MemoryWrite - > Count * MemoryWrite - > Width ) ;
}
CopyMemByWidth ( ( UINT8 * ) ( UINTN ) MemoryWrite - > Address , AlignedDataPtr , 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 ;
}
2015-01-20 09:46:31 +01:00
Status = SendDataResponsePacket ( ( UINT8 * ) & Data64 , IoRead - > Width , DebugHeader ) ;
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 :
2015-01-20 09:46:31 +01:00
Status = SendDataResponsePacket ( ( UINT8 * ) CpuContext , sizeof ( * CpuContext ) , DebugHeader ) ;
2012-06-11 04:15:11 +02:00
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 ) ;
2015-01-20 09:46:31 +01:00
Status = SendDataResponsePacket ( RegisterBuffer , Width , DebugHeader ) ;
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 ;
2015-01-20 09:46:31 +01:00
Status = SendDataResponsePacket ( ( UINT8 * ) & Data8 , ( UINT16 ) sizeof ( UINT8 ) , DebugHeader ) ;
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 ) ;
2015-01-20 09:46:31 +01:00
Status = SendDataResponsePacket ( ( UINT8 * ) & Data64 , ( UINT16 ) sizeof ( UINT64 ) , DebugHeader ) ;
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 :
2017-09-01 03:32:10 +02:00
DebugAgentRevision . Revision = PcdGet32 ( PcdTransferProtocolRevision ) ;
2010-09-12 08:43:36 +02:00
DebugAgentRevision . Capabilities = DEBUG_AGENT_CAPABILITIES ;
2015-01-20 09:46:31 +01:00
Status = SendDataResponsePacket ( ( UINT8 * ) & DebugAgentRevision , ( UINT16 ) sizeof ( DEBUG_DATA_RESPONSE_GET_REVISION ) , DebugHeader ) ;
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 ;
2015-01-20 09:46:31 +01:00
Status = SendDataResponsePacket ( ( UINT8 * ) & Exception , ( UINT16 ) sizeof ( DEBUG_DATA_RESPONSE_GET_EXCEPTION ) , DebugHeader ) ;
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 ;
2015-01-20 09:46:31 +01:00
SendDataResponsePacket ( ( UINT8 * ) & Data32 , ( UINT16 ) sizeof ( UINT32 ) , DebugHeader ) ;
2012-06-11 04:15:11 +02:00
break ;
case DEBUG_COMMAND_MEMORY_READY :
2013-01-25 03:36:18 +01:00
Data8 = ( UINT8 ) GetDebugFlag ( DEBUG_AGENT_FLAG_MEMORY_READY ) ;
2015-01-20 09:46:31 +01:00
SendDataResponsePacket ( & Data8 , ( UINT16 ) sizeof ( UINT8 ) , DebugHeader ) ;
2012-06-11 04:15:11 +02:00
break ;
case DEBUG_COMMAND_DETACH :
SetHostAttached ( FALSE ) ;
SendAckPacket ( DEBUG_COMMAND_OK ) ;
break ;
case DEBUG_COMMAND_CPUID :
Cpuid = ( DEBUG_DATA_CPUID * ) ( DebugHeader + 1 ) ;
AsmCpuidEx (
2014-11-04 02:29:20 +01:00
Cpuid - > Eax , Cpuid - > Ecx ,
2012-06-11 04:15:11 +02:00
& CpuidResponse . Eax , & CpuidResponse . Ebx ,
& CpuidResponse . Ecx , & CpuidResponse . Edx
) ;
2015-01-20 09:46:31 +01:00
SendDataResponsePacket ( ( UINT8 * ) & CpuidResponse , ( UINT16 ) sizeof ( CpuidResponse ) , DebugHeader ) ;
2012-06-11 04:15:11 +02:00
break ;
case DEBUG_COMMAND_SEARCH_SIGNATURE :
SearchSignature = ( DEBUG_DATA_SEARCH_SIGNATURE * ) ( DebugHeader + 1 ) ;
2014-11-04 02:29:20 +01:00
if ( ( SearchSignature - > Alignment ! = 0 ) & &
2012-06-11 04:15:11 +02:00
( 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 ;
}
}
2015-01-20 09:46:31 +01:00
SendDataResponsePacket ( ( UINT8 * ) & Data64 , ( UINT16 ) sizeof ( Data64 ) , DebugHeader ) ;
2012-06-11 04:15:11 +02:00
} 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
2014-06-25 08:49:53 +02:00
InputCharacter = 0 ;
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()
2015-04-27 07:26:03 +02:00
// If exception is issued when executing Stepping, will be handled in
// exception handle procedure.
2012-06-11 04:15:11 +02:00
//
2013-01-25 03:36:18 +01:00
if ( GetDebugFlag ( DEBUG_AGENT_FLAG_AGENT_IN_PROGRESS ) = = 1 ) {
2015-04-27 07:26:03 +02:00
DebugAgentMsgPrint (
DEBUG_AGENT_ERROR ,
" Debug agent meet one Exception, ExceptionNum is %d, EIP = 0x%x. \n " ,
Vector ,
( UINTN ) CpuContext - > Eip
) ;
2012-06-11 04:15:11 +02:00
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
//
2014-11-04 02:29:20 +01:00
// If RUN commmand is executing, wait for it done.
2012-06-11 04:15:11 +02:00
//
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 ;
}
2015-04-21 05:14:29 +02:00
//
2015-04-27 07:23:43 +02:00
// Clear Stepping Flag and restore EFLAGS.IF
2015-04-21 05:14:29 +02:00
//
2015-04-27 07:23:43 +02:00
CommandSteppingCleanup ( CpuContext ) ;
SendAckPacket ( DEBUG_COMMAND_OK ) ;
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_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
//
2014-11-04 02:29:20 +01:00
2012-06-11 04:15:11 +02:00
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
2014-11-04 02:29:20 +01:00
//
2012-06-11 04:15:11 +02:00
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 ) ;
2014-11-04 02:29:20 +01: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 ) {
2015-05-25 04:48:00 +02:00
InitializeDebugTimer ( NULL , FALSE ) ;
2015-06-08 08:36:41 +02:00
SaveAndSetDebugTimerInterrupt ( TRUE ) ;
2010-09-12 08:43:36 +02:00
}
}
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 ) {
2015-04-27 07:26:03 +02:00
DebugAgentMsgPrint (
DEBUG_AGENT_ERROR ,
" Exception happened, ExceptionNum is %d, EIP = 0x%x. \n " ,
Vector ,
( UINTN ) CpuContext - > Eip
) ;
2012-06-11 04:15:11 +02:00
if ( BreakCause = = DEBUG_DATA_BREAK_CAUSE_STEPPING ) {
//
2015-04-27 07:26:03 +02:00
// If exception happened when executing Stepping, send Ack package.
// HOST consider Stepping command was finished.
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
mDebugMpContext . BreakAtCpuIndex = ProcessorIndex ;
2010-09-12 08:43:36 +02:00
}
2015-04-27 07:23:43 +02:00
//
// Clear Stepping flag and restore EFLAGS.IF
//
CommandSteppingCleanup ( CpuContext ) ;
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
2014-11-04 02:29:20 +01:00
//
2012-06-11 04:15:11 +02:00
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
}
2014-11-04 02:29:20 +01: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 ;
}