/** @file Copyright (c) 2007 - 2016, Intel Corporation. All rights reserved.
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; }