/** @file | |
Copyright (c) 2007 - 2016, Intel Corporation. All rights reserved.<BR> | |
SPDX-License-Identifier: BSD-2-Clause-Patent | |
**/ | |
#include "Edb.h" | |
/** | |
Check whether current IP is EBC BREAK3 instruction. | |
@param Address EBC IP address. | |
@retval TRUE Current IP is EBC BREAK3 instruction | |
@retval FALSE Current IP is not EBC BREAK3 instruction | |
**/ | |
BOOLEAN | |
IsEBCBREAK3 ( | |
IN UINTN Address | |
) | |
{ | |
if (GET_OPCODE (Address) != OPCODE_BREAK) { | |
return FALSE; | |
} | |
if (GET_OPERANDS (Address) != 3) { | |
return FALSE; | |
} else { | |
return TRUE; | |
} | |
} | |
/** | |
Check whether the Address is already set in breakpoint. | |
@param DebuggerPrivate EBC Debugger private data structure | |
@param Address Breakpoint Address | |
@retval TRUE breakpoint is found | |
@retval FALSE breakpoint is not found | |
**/ | |
BOOLEAN | |
DebuggerBreakpointIsDuplicated ( | |
IN EFI_DEBUGGER_PRIVATE_DATA *DebuggerPrivate, | |
IN UINTN Address | |
) | |
{ | |
UINTN Index; | |
// | |
// Go through each breakpoint context | |
// | |
for (Index = 0; Index < DebuggerPrivate->DebuggerBreakpointCount; Index++) { | |
if (DebuggerPrivate->DebuggerBreakpointContext[Index].BreakpointAddress == Address) { | |
// | |
// Found it | |
// | |
return TRUE; | |
} | |
} | |
// | |
// Not found | |
// | |
return FALSE; | |
} | |
/** | |
Add this breakpoint. | |
@param DebuggerPrivate EBC Debugger private data structure | |
@param Address Breakpoint Address | |
@retval EFI_SUCCESS breakpoint added successfully | |
@retval EFI_ALREADY_STARTED breakpoint is already added | |
@retval EFI_OUT_OF_RESOURCES all the breakpoint entries are used | |
**/ | |
EFI_STATUS | |
DebuggerBreakpointAdd ( | |
IN EFI_DEBUGGER_PRIVATE_DATA *DebuggerPrivate, | |
IN UINTN Address | |
) | |
{ | |
// | |
// Check duplicated breakpoint | |
// | |
if (DebuggerBreakpointIsDuplicated (DebuggerPrivate, Address)) { | |
EDBPrint (L"Breakpoint duplicated!\n"); | |
return EFI_ALREADY_STARTED; | |
} | |
// | |
// Check whether the address is a breakpoint 3 instruction | |
// | |
if (IsEBCBREAK3 (Address)) { | |
EDBPrint (L"Breakpoint can not be set on BREAK 3 instruction!\n"); | |
return EFI_ALREADY_STARTED; | |
} | |
if (DebuggerPrivate->DebuggerBreakpointCount >= EFI_DEBUGGER_BREAKPOINT_MAX) { | |
EDBPrint (L"Breakpoint out of resource!\n"); | |
return EFI_OUT_OF_RESOURCES; | |
} | |
// | |
// Set the breakpoint | |
// | |
DebuggerPrivate->DebuggerBreakpointContext[DebuggerPrivate->DebuggerBreakpointCount].BreakpointAddress = Address; | |
DebuggerPrivate->DebuggerBreakpointContext[DebuggerPrivate->DebuggerBreakpointCount].State = TRUE; | |
DebuggerPrivate->DebuggerBreakpointContext[DebuggerPrivate->DebuggerBreakpointCount].OldInstruction = 0; | |
CopyMem ( | |
&DebuggerPrivate->DebuggerBreakpointContext[DebuggerPrivate->DebuggerBreakpointCount].OldInstruction, | |
(VOID *)Address, | |
sizeof (UINT16) | |
); | |
DebuggerPrivate->DebuggerBreakpointCount++; | |
// | |
// Done | |
// | |
return EFI_SUCCESS; | |
} | |
/** | |
Delete this breakpoint. | |
@param DebuggerPrivate EBC Debugger private data structure | |
@param Index Breakpoint Index | |
@retval EFI_SUCCESS breakpoint deleted successfully | |
@retval EFI_NOT_FOUND breakpoint not found | |
**/ | |
EFI_STATUS | |
DebuggerBreakpointDel ( | |
IN EFI_DEBUGGER_PRIVATE_DATA *DebuggerPrivate, | |
IN UINTN Index | |
) | |
{ | |
UINTN BpIndex; | |
if ((Index >= EFI_DEBUGGER_BREAKPOINT_MAX) || | |
(Index >= DebuggerPrivate->DebuggerBreakpointCount)) | |
{ | |
return EFI_NOT_FOUND; | |
} | |
// | |
// Delete this breakpoint | |
// | |
for (BpIndex = Index; BpIndex < DebuggerPrivate->DebuggerBreakpointCount - 1; BpIndex++) { | |
CopyMem ( | |
&DebuggerPrivate->DebuggerBreakpointContext[BpIndex], | |
&DebuggerPrivate->DebuggerBreakpointContext[BpIndex + 1], | |
sizeof (DebuggerPrivate->DebuggerBreakpointContext[BpIndex]) | |
); | |
} | |
ZeroMem ( | |
&DebuggerPrivate->DebuggerBreakpointContext[BpIndex], | |
sizeof (DebuggerPrivate->DebuggerBreakpointContext[BpIndex]) | |
); | |
DebuggerPrivate->DebuggerBreakpointCount--; | |
// | |
// Done | |
// | |
return EFI_SUCCESS; | |
} | |
/** | |
Disable this breakpoint. | |
@param DebuggerPrivate EBC Debugger private data structure | |
@param Index Breakpoint Index | |
@retval EFI_SUCCESS breakpoint disabled successfully | |
@retval EFI_NOT_FOUND breakpoint not found | |
**/ | |
EFI_STATUS | |
DebuggerBreakpointDis ( | |
IN EFI_DEBUGGER_PRIVATE_DATA *DebuggerPrivate, | |
IN UINTN Index | |
) | |
{ | |
if ((Index >= EFI_DEBUGGER_BREAKPOINT_MAX) || | |
(Index >= DebuggerPrivate->DebuggerBreakpointCount)) | |
{ | |
return EFI_NOT_FOUND; | |
} | |
// | |
// Disable this breakpoint | |
// | |
DebuggerPrivate->DebuggerBreakpointContext[Index].State = FALSE; | |
return EFI_SUCCESS; | |
} | |
/** | |
Enable this breakpoint. | |
@param DebuggerPrivate - EBC Debugger private data structure | |
@param Index - Breakpoint Index | |
@retval EFI_SUCCESS - breakpoint enabled successfully | |
@retval EFI_NOT_FOUND - breakpoint not found | |
**/ | |
EFI_STATUS | |
DebuggerBreakpointEn ( | |
IN EFI_DEBUGGER_PRIVATE_DATA *DebuggerPrivate, | |
IN UINTN Index | |
) | |
{ | |
if ((Index >= EFI_DEBUGGER_BREAKPOINT_MAX) || | |
(Index >= DebuggerPrivate->DebuggerBreakpointCount)) | |
{ | |
return EFI_NOT_FOUND; | |
} | |
// | |
// Enable this breakpoint | |
// | |
DebuggerPrivate->DebuggerBreakpointContext[Index].State = TRUE; | |
return EFI_SUCCESS; | |
} | |
/** | |
DebuggerCommand - BreakpointList. | |
@param CommandArg - The argument for this command | |
@param DebuggerPrivate - EBC Debugger private data structure | |
@param ExceptionType - Exception type. | |
@param SystemContext - EBC system context. | |
@retval EFI_DEBUG_CONTINUE - formal return value | |
**/ | |
EFI_DEBUG_STATUS | |
DebuggerBreakpointList ( | |
IN CHAR16 *CommandArg, | |
IN EFI_DEBUGGER_PRIVATE_DATA *DebuggerPrivate, | |
IN EFI_EXCEPTION_TYPE ExceptionType, | |
IN OUT EFI_SYSTEM_CONTEXT SystemContext | |
) | |
{ | |
UINTN Index; | |
// | |
// Check breakpoint cound | |
// | |
if (DebuggerPrivate->DebuggerBreakpointCount == 0) { | |
EDBPrint (L"No Breakpoint\n"); | |
return EFI_DEBUG_CONTINUE; | |
} else if (DebuggerPrivate->DebuggerBreakpointCount > EFI_DEBUGGER_BREAKPOINT_MAX) { | |
EDBPrint (L"Breakpoint too many!\n"); | |
DebuggerPrivate->DebuggerBreakpointCount = 0; | |
return EFI_DEBUG_CONTINUE; | |
} | |
// | |
// Go through each breakpoint | |
// | |
EDBPrint (L"Breakpoint :\n"); | |
EDBPrint (L" Index Address Status\n"); | |
EDBPrint (L"======= ================== ========\n"); | |
// EDBPrint (L" 1 0xFFFFFFFF00000000 *\n"); | |
// EDBPrint (L" 12 0x00000000FFFFFFFF\n"); | |
for (Index = 0; Index < DebuggerPrivate->DebuggerBreakpointCount; Index++) { | |
// | |
// Print the breakpoint | |
// | |
EDBPrint (L" %2d 0x%016lx", Index, DebuggerPrivate->DebuggerBreakpointContext[Index].BreakpointAddress); | |
if (DebuggerPrivate->DebuggerBreakpointContext[Index].State) { | |
EDBPrint (L" *\n"); | |
} else { | |
EDBPrint (L"\n"); | |
} | |
} | |
// | |
// Done | |
// | |
return EFI_DEBUG_CONTINUE; | |
} | |
/** | |
DebuggerCommand - BreakpointSet. | |
@param CommandArg The argument for this command | |
@param DebuggerPrivate EBC Debugger private data structure | |
@param ExceptionType Exception type. | |
@param SystemContext EBC system context. | |
@retval EFI_DEBUG_CONTINUE - formal return value | |
**/ | |
EFI_DEBUG_STATUS | |
DebuggerBreakpointSet ( | |
IN CHAR16 *CommandArg, | |
IN EFI_DEBUGGER_PRIVATE_DATA *DebuggerPrivate, | |
IN EFI_EXCEPTION_TYPE ExceptionType, | |
IN OUT EFI_SYSTEM_CONTEXT SystemContext | |
) | |
{ | |
UINTN Address; | |
EFI_STATUS Status; | |
if (CommandArg == NULL) { | |
EDBPrint (L"BreakpointSet Argument error!\n"); | |
return EFI_DEBUG_CONTINUE; | |
} | |
// | |
// Get breakpoint address | |
// | |
Status = Symboltoi (CommandArg, &Address); | |
if (EFI_ERROR (Status)) { | |
if (Status == EFI_NOT_FOUND) { | |
Address = Xtoi (CommandArg); | |
} else { | |
// | |
// Something wrong, let Symboltoi print error info. | |
// | |
EDBPrint (L"Command Argument error!\n"); | |
return EFI_DEBUG_CONTINUE; | |
} | |
} | |
// | |
// Add breakpoint | |
// | |
Status = DebuggerBreakpointAdd (DebuggerPrivate, Address); | |
if (EFI_ERROR (Status)) { | |
EDBPrint (L"BreakpointSet error!\n"); | |
} | |
// | |
// Done | |
// | |
return EFI_DEBUG_CONTINUE; | |
} | |
/** | |
DebuggerCommand - BreakpointClear | |
@param CommandArg The argument for this command | |
@param DebuggerPrivate EBC Debugger private data structure | |
@param ExceptionType Exception type. | |
@param SystemContext EBC system context. | |
@retval EFI_DEBUG_CONTINUE formal return value | |
**/ | |
EFI_DEBUG_STATUS | |
DebuggerBreakpointClear ( | |
IN CHAR16 *CommandArg, | |
IN EFI_DEBUGGER_PRIVATE_DATA *DebuggerPrivate, | |
IN EFI_EXCEPTION_TYPE ExceptionType, | |
IN OUT EFI_SYSTEM_CONTEXT SystemContext | |
) | |
{ | |
UINTN Index; | |
EFI_STATUS Status; | |
if (CommandArg == NULL) { | |
EDBPrint (L"BreakpointClear Argument error!\n"); | |
return EFI_DEBUG_CONTINUE; | |
} | |
if (StriCmp (CommandArg, L"*") == 0) { | |
// | |
// delete all breakpoint | |
// | |
DebuggerPrivate->DebuggerBreakpointCount = 0; | |
ZeroMem (DebuggerPrivate->DebuggerBreakpointContext, sizeof (DebuggerPrivate->DebuggerBreakpointContext)); | |
EDBPrint (L"All the Breakpoint is cleared\n"); | |
return EFI_DEBUG_CONTINUE; | |
} | |
// | |
// Get breakpoint index | |
// | |
Index = Atoi (CommandArg); | |
if (Index == (UINTN)-1) { | |
EDBPrint (L"BreakpointClear Argument error!\n"); | |
return EFI_DEBUG_CONTINUE; | |
} | |
if ((Index >= EFI_DEBUGGER_BREAKPOINT_MAX) || | |
(Index >= DebuggerPrivate->DebuggerBreakpointCount)) | |
{ | |
EDBPrint (L"BreakpointClear error!\n"); | |
return EFI_DEBUG_CONTINUE; | |
} | |
// | |
// Delete breakpoint | |
// | |
Status = DebuggerBreakpointDel (DebuggerPrivate, Index); | |
if (EFI_ERROR (Status)) { | |
EDBPrint (L"BreakpointClear error!\n"); | |
} | |
// | |
// Done | |
// | |
return EFI_DEBUG_CONTINUE; | |
} | |
/** | |
DebuggerCommand - BreakpointDisable | |
@param CommandArg The argument for this command | |
@param DebuggerPrivate EBC Debugger private data structure | |
@param ExceptionType Exception type. | |
@param SystemContext EBC system context. | |
@retval EFI_DEBUG_CONTINUE formal return value | |
**/ | |
EFI_DEBUG_STATUS | |
DebuggerBreakpointDisable ( | |
IN CHAR16 *CommandArg, | |
IN EFI_DEBUGGER_PRIVATE_DATA *DebuggerPrivate, | |
IN EFI_EXCEPTION_TYPE ExceptionType, | |
IN OUT EFI_SYSTEM_CONTEXT SystemContext | |
) | |
{ | |
UINTN Index; | |
EFI_STATUS Status; | |
if (CommandArg == NULL) { | |
EDBPrint (L"BreakpointDisable Argument error!\n"); | |
return EFI_DEBUG_CONTINUE; | |
} | |
if (StriCmp (CommandArg, L"*") == 0) { | |
// | |
// disable all breakpoint | |
// | |
for (Index = 0; Index < DebuggerPrivate->DebuggerBreakpointCount; Index++) { | |
Status = DebuggerBreakpointDis (DebuggerPrivate, Index); | |
} | |
EDBPrint (L"All the Breakpoint is disabled\n"); | |
return EFI_DEBUG_CONTINUE; | |
} | |
// | |
// Get breakpoint index | |
// | |
Index = Atoi (CommandArg); | |
if (Index == (UINTN)-1) { | |
EDBPrint (L"BreakpointDisable Argument error!\n"); | |
return EFI_DEBUG_CONTINUE; | |
} | |
// | |
// Disable breakpoint | |
// | |
Status = DebuggerBreakpointDis (DebuggerPrivate, Index); | |
if (EFI_ERROR (Status)) { | |
EDBPrint (L"BreakpointDisable error!\n"); | |
} | |
// | |
// Done | |
// | |
return EFI_DEBUG_CONTINUE; | |
} | |
/** | |
DebuggerCommand - BreakpointEnable. | |
@param CommandArg The argument for this command | |
@param DebuggerPrivate EBC Debugger private data structure | |
@param ExceptionType Exception type. | |
@param SystemContext EBC system context. | |
@retval EFI_DEBUG_CONTINUE formal return value | |
**/ | |
EFI_DEBUG_STATUS | |
DebuggerBreakpointEnable ( | |
IN CHAR16 *CommandArg, | |
IN EFI_DEBUGGER_PRIVATE_DATA *DebuggerPrivate, | |
IN EFI_EXCEPTION_TYPE ExceptionType, | |
IN OUT EFI_SYSTEM_CONTEXT SystemContext | |
) | |
{ | |
UINTN Index; | |
EFI_STATUS Status; | |
if (CommandArg == NULL) { | |
EDBPrint (L"BreakpointEnable Argument error!\n"); | |
return EFI_DEBUG_CONTINUE; | |
} | |
if (StriCmp (CommandArg, L"*") == 0) { | |
// | |
// enable all breakpoint | |
// | |
for (Index = 0; Index < DebuggerPrivate->DebuggerBreakpointCount; Index++) { | |
Status = DebuggerBreakpointEn (DebuggerPrivate, Index); | |
} | |
EDBPrint (L"All the Breakpoint is enabled\n"); | |
return EFI_DEBUG_CONTINUE; | |
} | |
// | |
// Get breakpoint index | |
// | |
Index = Atoi (CommandArg); | |
if (Index == (UINTN)-1) { | |
EDBPrint (L"BreakpointEnable Argument error!\n"); | |
return EFI_DEBUG_CONTINUE; | |
} | |
// | |
// Enable breakpoint | |
// | |
Status = DebuggerBreakpointEn (DebuggerPrivate, Index); | |
if (EFI_ERROR (Status)) { | |
EDBPrint (L"BreakpointEnable error!\n"); | |
} | |
// | |
// Done | |
// | |
return EFI_DEBUG_CONTINUE; | |
} |