| /** @file | |
| Copyright (c) 2007 - 2016, Intel Corporation. All rights reserved.<BR> | |
| This program and the accompanying materials | |
| are licensed and made available under the terms and conditions of the BSD License | |
| which accompanies this distribution. The full text of the license may be found at | |
| http://opensource.org/licenses/bsd-license.php | |
| THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, | |
| WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. | |
| **/ | |
| #include "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++) { | |
| DebuggerPrivate->DebuggerBreakpointContext[BpIndex] = DebuggerPrivate->DebuggerBreakpointContext[BpIndex + 1]; | |
| } | |
| 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; | |
| } |