12ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH/** @file
22ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  Processor specific parts of the GDB stub
32ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH
460274ccab831d7874129a6b6c271969418296960hhtian  Copyright (c) 2008 - 2009, Apple Inc. All rights reserved.<BR>
53402aac7d985bf8a9f9d3c639f3fe93609380513Ronald Cron
660274ccab831d7874129a6b6c271969418296960hhtian  This program and the accompanying materials
72ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  are licensed and made available under the terms and conditions of the BSD License
82ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  which accompanies this distribution.  The full text of the license may be found at
92ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  http://opensource.org/licenses/bsd-license.php
102ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH
112ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
122ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
132ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH
142ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH**/
152ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH
162ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH#include <GdbStubInternal.h>
172ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH
182ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH//
192ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH// Array of exception types that need to be hooked by the debugger
202ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH//
212ef2b01e07c02db339f34004445734a2dbdd80e1AJFISHEFI_EXCEPTION_TYPE_ENTRY gExceptionType[] = {
223402aac7d985bf8a9f9d3c639f3fe93609380513Ronald Cron  { EXCEPT_X64_DIVIDE_ERROR,    GDB_SIGFPE  },
232ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  { EXCEPT_X64_DEBUG,           GDB_SIGTRAP },
242ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  { EXCEPT_X64_NMI,             GDB_SIGEMT  },
252ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  { EXCEPT_X64_BREAKPOINT,      GDB_SIGTRAP },
262ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  { EXCEPT_X64_OVERFLOW,        GDB_SIGSEGV },
272ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  { EXCEPT_X64_BOUND,           GDB_SIGSEGV },
282ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  { EXCEPT_X64_INVALID_OPCODE,  GDB_SIGILL  },
292ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  { EXCEPT_X64_DOUBLE_FAULT,    GDB_SIGEMT  },
302ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  { EXCEPT_X64_STACK_FAULT,     GDB_SIGSEGV },
312ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  { EXCEPT_X64_GP_FAULT,        GDB_SIGSEGV },
322ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  { EXCEPT_X64_PAGE_FAULT,      GDB_SIGSEGV },
332ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  { EXCEPT_X64_FP_ERROR,        GDB_SIGEMT  },
342ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  { EXCEPT_X64_ALIGNMENT_CHECK, GDB_SIGEMT  },
352ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  { EXCEPT_X64_MACHINE_CHECK,   GDB_SIGEMT  }
362ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH};
372ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH
382ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH
392ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH// The offsets of registers SystemContextX64.
403402aac7d985bf8a9f9d3c639f3fe93609380513Ronald Cron// The fields in the array are in the gdb ordering.
412ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH// HAVE TO DOUBLE-CHECK THE ORDER of the 24 regs
422ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH//
432ef2b01e07c02db339f34004445734a2dbdd80e1AJFISHUINTN gRegisterOffsets[] = {
442ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  OFFSET_OF(EFI_SYSTEM_CONTEXT_X64, Rax),
452ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  OFFSET_OF(EFI_SYSTEM_CONTEXT_X64, Rcx),
462ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  OFFSET_OF(EFI_SYSTEM_CONTEXT_X64, Rdx),
472ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  OFFSET_OF(EFI_SYSTEM_CONTEXT_X64, Rbx),
482ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  OFFSET_OF(EFI_SYSTEM_CONTEXT_X64, Rsp),
492ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  OFFSET_OF(EFI_SYSTEM_CONTEXT_X64, Rbp),
502ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  OFFSET_OF(EFI_SYSTEM_CONTEXT_X64, Rsi),
512ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  OFFSET_OF(EFI_SYSTEM_CONTEXT_X64, Rdi),
522ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  OFFSET_OF(EFI_SYSTEM_CONTEXT_X64, Rip),
532ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  OFFSET_OF(EFI_SYSTEM_CONTEXT_X64, Rflags),
542ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  OFFSET_OF(EFI_SYSTEM_CONTEXT_X64, Cs),
552ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  OFFSET_OF(EFI_SYSTEM_CONTEXT_X64, Ss),
562ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  OFFSET_OF(EFI_SYSTEM_CONTEXT_X64, Ds),
572ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  OFFSET_OF(EFI_SYSTEM_CONTEXT_X64, Es),
582ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  OFFSET_OF(EFI_SYSTEM_CONTEXT_X64, Fs),
592ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  OFFSET_OF(EFI_SYSTEM_CONTEXT_X64, Gs),
602ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  OFFSET_OF(EFI_SYSTEM_CONTEXT_X64, R8),
612ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  OFFSET_OF(EFI_SYSTEM_CONTEXT_X64, R9),
622ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  OFFSET_OF(EFI_SYSTEM_CONTEXT_X64, R10),
632ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  OFFSET_OF(EFI_SYSTEM_CONTEXT_X64, R11),
642ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  OFFSET_OF(EFI_SYSTEM_CONTEXT_X64, R12),
652ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  OFFSET_OF(EFI_SYSTEM_CONTEXT_X64, R13),
662ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  OFFSET_OF(EFI_SYSTEM_CONTEXT_X64, R14),
672ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  OFFSET_OF(EFI_SYSTEM_CONTEXT_X64, R15)
682ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH};
692ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH
702ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH
712ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH/**
722ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH Return the number of entries in the gExceptionType[]
733402aac7d985bf8a9f9d3c639f3fe93609380513Ronald Cron
743402aac7d985bf8a9f9d3c639f3fe93609380513Ronald Cron @retval  UINTN, the number of entries in the gExceptionType[] array.
752ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH **/
762ef2b01e07c02db339f34004445734a2dbdd80e1AJFISHUINTN
772ef2b01e07c02db339f34004445734a2dbdd80e1AJFISHMaxEfiException (
782ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  VOID
792ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  )
802ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH{
812ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  return sizeof (gExceptionType)/sizeof (EFI_EXCEPTION_TYPE_ENTRY);
822ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH}
832ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH
842ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH
852ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH/**
862ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH Return the number of entries in the gRegisters[]
873402aac7d985bf8a9f9d3c639f3fe93609380513Ronald Cron
883402aac7d985bf8a9f9d3c639f3fe93609380513Ronald Cron @retval  UINTN, the number of entries (registers) in the gRegisters[] array.
892ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH **/
902ef2b01e07c02db339f34004445734a2dbdd80e1AJFISHUINTN
912ef2b01e07c02db339f34004445734a2dbdd80e1AJFISHMaxRegisterCount (
922ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  VOID
932ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  )
942ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH{
952ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  return sizeof (gRegisterOffsets)/sizeof (UINTN);
962ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH}
972ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH
983402aac7d985bf8a9f9d3c639f3fe93609380513Ronald Cron
992ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH/**
1003402aac7d985bf8a9f9d3c639f3fe93609380513Ronald Cron  Check to see if the ISA is supported.
1012ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  ISA = Instruction Set Architecture
1022ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH
1032ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  @retval TRUE if Isa is supported
1042ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH**/
1052ef2b01e07c02db339f34004445734a2dbdd80e1AJFISHBOOLEAN
1062ef2b01e07c02db339f34004445734a2dbdd80e1AJFISHCheckIsa (
1072ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  IN  EFI_INSTRUCTION_SET_ARCHITECTURE  Isa
1082ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  )
1092ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH{
1102ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  return (BOOLEAN)(Isa == IsaX64);
1112ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH}
1122ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH
1132ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH
1142ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH/**
1152ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH This takes in the register number and the System Context, and returns a pointer to the RegNumber-th register in gdb ordering
1162ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH It is, by default, set to find the register pointer of the X64 member
1173402aac7d985bf8a9f9d3c639f3fe93609380513Ronald Cron @param   SystemContext     Register content at time of the exception
1182ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH @param   RegNumber       The register to which we want to find a pointer
1192ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH @retval  the pointer to the RegNumber-th pointer
1202ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH **/
1212ef2b01e07c02db339f34004445734a2dbdd80e1AJFISHUINTN *
1222ef2b01e07c02db339f34004445734a2dbdd80e1AJFISHFindPointerToRegister(
1232ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  IN  EFI_SYSTEM_CONTEXT  SystemContext,
1243402aac7d985bf8a9f9d3c639f3fe93609380513Ronald Cron  IN  UINTN               RegNumber
1252ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  )
1262ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH{
1272ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  UINT8 *TempPtr;
1282ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  TempPtr = ((UINT8 *)SystemContext.SystemContextX64) + gRegisterOffsets[RegNumber];
1292ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  return (UINTN *)TempPtr;
1302ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH}
1312ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH
1322ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH
1332ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH/**
1342ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH Adds the RegNumber-th register's value to the output buffer, starting at the given OutBufPtr
1352ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH @param   SystemContext     Register content at time of the exception
1362ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH @param   RegNumber       the number of the register that we want to read
1372ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH @param   OutBufPtr       pointer to the output buffer's end. the new data will be added from this point on.
1382ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH @retval  the pointer to the next character of the output buffer that is available to be written on.
1392ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH **/
1402ef2b01e07c02db339f34004445734a2dbdd80e1AJFISHCHAR8 *
1412ef2b01e07c02db339f34004445734a2dbdd80e1AJFISHBasicReadRegister (
1422ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  IN  EFI_SYSTEM_CONTEXT      SystemContext,
1432ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  IN  UINTN           RegNumber,
1442ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  IN  CHAR8           *OutBufPtr
1452ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  )
1462ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH{
1472ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  UINTN RegSize;
1483402aac7d985bf8a9f9d3c639f3fe93609380513Ronald Cron
1492ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  RegSize = 0;
1502ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  while (RegSize < 64) {
1512ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH    *OutBufPtr++ = mHexToStr[((*FindPointerToRegister(SystemContext, RegNumber) >> (RegSize+4)) & 0xf)];
1522ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH    *OutBufPtr++ = mHexToStr[((*FindPointerToRegister(SystemContext, RegNumber) >> RegSize) & 0xf)];
1532ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH    RegSize = RegSize + 8;
1542ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  }
1552ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  return OutBufPtr;
1562ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH}
1572ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH
1582ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH
1593402aac7d985bf8a9f9d3c639f3fe93609380513Ronald Cron/** ‘p n’
1603402aac7d985bf8a9f9d3c639f3fe93609380513Ronald Cron Reads the n-th register's value into an output buffer and sends it as a packet
1612ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH @param   SystemContext   Register content at time of the exception
1622ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH @param   InBuffer      Pointer to the input buffer received from gdb server
1632ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH **/
1642ef2b01e07c02db339f34004445734a2dbdd80e1AJFISHVOID
1652ef2b01e07c02db339f34004445734a2dbdd80e1AJFISHReadNthRegister (
1662ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  IN  EFI_SYSTEM_CONTEXT   SystemContext,
1672ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  IN  CHAR8                *InBuffer
1682ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  )
1692ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH{
1702ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  UINTN RegNumber;
1712ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  CHAR8 OutBuffer[17];  // 1 reg=16 hex chars, and the end '\0' (escape seq)
1722ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  CHAR8 *OutBufPtr;   // pointer to the output buffer
1733402aac7d985bf8a9f9d3c639f3fe93609380513Ronald Cron
1742ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  RegNumber = AsciiStrHexToUintn (&InBuffer[1]);
1753402aac7d985bf8a9f9d3c639f3fe93609380513Ronald Cron
1762ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  if ((RegNumber < 0) || (RegNumber >= MaxRegisterCount())) {
1773402aac7d985bf8a9f9d3c639f3fe93609380513Ronald Cron    SendError (GDB_EINVALIDREGNUM);
1782ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH    return;
1792ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  }
1803402aac7d985bf8a9f9d3c639f3fe93609380513Ronald Cron
1812ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  OutBufPtr = OutBuffer;
1822ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  OutBufPtr = BasicReadRegister(SystemContext, RegNumber, OutBufPtr);
1833402aac7d985bf8a9f9d3c639f3fe93609380513Ronald Cron
1842ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  *OutBufPtr = '\0';  // the end of the buffer
1852ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  SendPacket (OutBuffer);
1862ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH}
1872ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH
1882ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH
1893402aac7d985bf8a9f9d3c639f3fe93609380513Ronald Cron/** ‘g’
1903402aac7d985bf8a9f9d3c639f3fe93609380513Ronald Cron Reads the general registers into an output buffer  and sends it as a packet
1912ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH
1922ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH @param   SystemContext     Register content at time of the exception
1932ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH **/
1942ef2b01e07c02db339f34004445734a2dbdd80e1AJFISHVOID
1952ef2b01e07c02db339f34004445734a2dbdd80e1AJFISHEFIAPI
1963402aac7d985bf8a9f9d3c639f3fe93609380513Ronald CronReadGeneralRegisters (
1972ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  IN  EFI_SYSTEM_CONTEXT      SystemContext
1982ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  )
1992ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH{
2002ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  UINTN   i;
2012ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  CHAR8 OutBuffer[385]; // 24 regs, 16 hex chars each, and the end '\0' (escape seq)
2022ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  CHAR8 *OutBufPtr;   // pointer to the output buffer
2033402aac7d985bf8a9f9d3c639f3fe93609380513Ronald Cron
2042ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  OutBufPtr = OutBuffer;
2053402aac7d985bf8a9f9d3c639f3fe93609380513Ronald Cron  for(i = 0 ; i < MaxRegisterCount() ; i++) {  // there are only 24 registers to read
2062ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH    OutBufPtr = BasicReadRegister(SystemContext, i, OutBufPtr);
2072ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  }
2083402aac7d985bf8a9f9d3c639f3fe93609380513Ronald Cron
2092ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  *OutBufPtr = '\0';  // the end of the buffer
2102ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  SendPacket (OutBuffer);
2112ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH}
2122ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH
2132ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH
2142ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH/**
2152ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH Adds the RegNumber-th register's value to the output buffer, starting at the given OutBufPtr
2162ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH
2172ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH @param   SystemContext       Register content at time of the exception
2182ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH @param   RegNumber         the number of the register that we want to write
2192ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH @param   InBufPtr          pointer to the output buffer. the new data will be extracted from the input buffer from this point on.
2202ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH @retval  the pointer to the next character of the input buffer that can be used
2212ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH **/
2222ef2b01e07c02db339f34004445734a2dbdd80e1AJFISHCHAR8 *
2232ef2b01e07c02db339f34004445734a2dbdd80e1AJFISHBasicWriteRegister (
2242ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  IN  EFI_SYSTEM_CONTEXT  SystemContext,
2252ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  IN  UINTN               RegNumber,
2262ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  IN  CHAR8               *InBufPtr
2272ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  )
2282ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH{
2292ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  UINTN RegSize;
2302ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  UINTN TempValue; // the value transferred from a hex char
2312ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  UINT64 NewValue; // the new value of the RegNumber-th Register
2323402aac7d985bf8a9f9d3c639f3fe93609380513Ronald Cron
2332ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  NewValue = 0;
2342ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  RegSize = 0;
2352ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  while (RegSize < 64) {
2362ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH    TempValue = HexCharToInt(*InBufPtr++);
2373402aac7d985bf8a9f9d3c639f3fe93609380513Ronald Cron
2382ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH    if (TempValue < 0) {
2393402aac7d985bf8a9f9d3c639f3fe93609380513Ronald Cron      SendError (GDB_EBADMEMDATA);
2402ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH      return NULL;
2412ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH    }
2423402aac7d985bf8a9f9d3c639f3fe93609380513Ronald Cron
2432ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH    NewValue += (TempValue << (RegSize+4));
2442ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH    TempValue = HexCharToInt(*InBufPtr++);
2453402aac7d985bf8a9f9d3c639f3fe93609380513Ronald Cron
2462ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH    if (TempValue < 0) {
2473402aac7d985bf8a9f9d3c639f3fe93609380513Ronald Cron      SendError (GDB_EBADMEMDATA);
2482ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH      return NULL;
2492ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  }
2503402aac7d985bf8a9f9d3c639f3fe93609380513Ronald Cron
2513402aac7d985bf8a9f9d3c639f3fe93609380513Ronald Cron    NewValue += (TempValue << RegSize);
2522ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH    RegSize = RegSize + 8;
2532ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  }
2542ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  *(FindPointerToRegister(SystemContext, RegNumber)) = NewValue;
2552ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  return InBufPtr;
2562ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH}
2572ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH
2582ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH
2592ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH/** ‘P n...=r...’
2602ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH Writes the new value of n-th register received into the input buffer to the n-th register
2612ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH
2622ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH @param   SystemContext   Register content at time of the exception
2632ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH @param   InBuffer      Ponter to the input buffer received from gdb server
2642ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH **/
2652ef2b01e07c02db339f34004445734a2dbdd80e1AJFISHVOID
2662ef2b01e07c02db339f34004445734a2dbdd80e1AJFISHEFIAPI
2672ef2b01e07c02db339f34004445734a2dbdd80e1AJFISHWriteNthRegister (
2682ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  IN  EFI_SYSTEM_CONTEXT      SystemContext,
2692ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  IN  CHAR8           *InBuffer
2702ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  )
2712ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH{
2722ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  UINTN RegNumber;
2732ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  CHAR8 RegNumBuffer[MAX_REG_NUM_BUF_SIZE];  // put the 'n..' part of the message into this array
2742ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  CHAR8 *RegNumBufPtr;
2752ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  CHAR8 *InBufPtr; // pointer to the input buffer
2763402aac7d985bf8a9f9d3c639f3fe93609380513Ronald Cron
2772ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  // find the register number to write
2782ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  InBufPtr = &InBuffer[1];
2792ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  RegNumBufPtr = RegNumBuffer;
2802ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  while (*InBufPtr != '=') {
2812ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH    *RegNumBufPtr++ = *InBufPtr++;
2823402aac7d985bf8a9f9d3c639f3fe93609380513Ronald Cron  }
2832ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  *RegNumBufPtr = '\0';
2843402aac7d985bf8a9f9d3c639f3fe93609380513Ronald Cron  RegNumber = AsciiStrHexToUintn (RegNumBuffer);
2852ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH
2862ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  // check if this is a valid Register Number
2872ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  if ((RegNumber < 0) || (RegNumber >= MaxRegisterCount())) {
28891c38d4e94c1461f5824b83d3722fe46626aa0d3Ronald Cron    SendError (GDB_EINVALIDREGNUM);
2892ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH    return;
2902ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  }
2912ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  InBufPtr++;  // skips the '=' character
2922ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  BasicWriteRegister (SystemContext, RegNumber, InBufPtr);
2932ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  SendSuccess();
2942ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH}
2952ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH
2962ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH
2972ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH/** ‘G XX...’
2982ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH Writes the new values received into the input buffer to the general registers
2992ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH
3002ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH @param   SystemContext       Register content at time of the exception
3012ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH @param   InBuffer          Pointer to the input buffer received from gdb server
3022ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH **/
3032ef2b01e07c02db339f34004445734a2dbdd80e1AJFISHVOID
3042ef2b01e07c02db339f34004445734a2dbdd80e1AJFISHEFIAPI
3052ef2b01e07c02db339f34004445734a2dbdd80e1AJFISHWriteGeneralRegisters (
3062ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  IN  EFI_SYSTEM_CONTEXT    SystemContext,
3072ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  IN  CHAR8                 *InBuffer
3082ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  )
3092ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH{
3102ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  UINTN  i;
3112ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  CHAR8 *InBufPtr; /// pointer to the input buffer
3123402aac7d985bf8a9f9d3c639f3fe93609380513Ronald Cron
3133402aac7d985bf8a9f9d3c639f3fe93609380513Ronald Cron  // check to see if the buffer is the right size which is
3143402aac7d985bf8a9f9d3c639f3fe93609380513Ronald Cron  // 1 (for 'G') + 16 (for 16 registers) * 8 ( for 8 hex chars each) = 385
3152ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  if (AsciiStrLen(InBuffer) != 385) { // 24 regs, 16 hex chars each, and the end '\0' (escape seq)
3163402aac7d985bf8a9f9d3c639f3fe93609380513Ronald Cron    //Bad message. Message is not the right length
3173402aac7d985bf8a9f9d3c639f3fe93609380513Ronald Cron    SendError (GDB_EBADBUFSIZE);
3182ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH    return;
3192ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  }
3203402aac7d985bf8a9f9d3c639f3fe93609380513Ronald Cron
3212ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  InBufPtr = &InBuffer[1];
3223402aac7d985bf8a9f9d3c639f3fe93609380513Ronald Cron
3232ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  // Read the new values for the registers from the input buffer to an array, NewValueArray.
3242ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  // The values in the array are in the gdb ordering
3252ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  for(i=0; i < MaxRegisterCount(); i++) {  // there are only 16 registers to write
3262ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH    InBufPtr = BasicWriteRegister(SystemContext, i, InBufPtr);
3272ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  }
3283402aac7d985bf8a9f9d3c639f3fe93609380513Ronald Cron
3292ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  SendSuccess();
3302ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH}
3312ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH
3322ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH
3333402aac7d985bf8a9f9d3c639f3fe93609380513Ronald Cron /**
3342ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH Insert Single Step in the SystemContext
3353402aac7d985bf8a9f9d3c639f3fe93609380513Ronald Cron
3362ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH @param SystemContext Register content at time of the exception
3372ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH **/
3382ef2b01e07c02db339f34004445734a2dbdd80e1AJFISHVOID
3392ef2b01e07c02db339f34004445734a2dbdd80e1AJFISHAddSingleStep (
3402ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  IN  EFI_SYSTEM_CONTEXT  SystemContext
3412ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  )
3422ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH{
3432ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  SystemContext.SystemContextX64->Rflags |= TF_BIT; //Setting the TF bit.
3442ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH}
3452ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH
3463402aac7d985bf8a9f9d3c639f3fe93609380513Ronald Cron
3473402aac7d985bf8a9f9d3c639f3fe93609380513Ronald Cron
3483402aac7d985bf8a9f9d3c639f3fe93609380513Ronald Cron/**
3492ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH Remove Single Step in the SystemContext
3503402aac7d985bf8a9f9d3c639f3fe93609380513Ronald Cron
3512ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH @param SystemContext Register content at time of the exception
3522ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH **/
3532ef2b01e07c02db339f34004445734a2dbdd80e1AJFISHVOID
3542ef2b01e07c02db339f34004445734a2dbdd80e1AJFISHRemoveSingleStep (
3552ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  IN  EFI_SYSTEM_CONTEXT  SystemContext
3562ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  )
3572ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH{
3582ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  SystemContext.SystemContextX64->Rflags &= ~TF_BIT;  // clearing the TF bit.
3592ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH}
3602ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH
3612ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH
3622ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH
3633402aac7d985bf8a9f9d3c639f3fe93609380513Ronald Cron/** ‘c [addr ]’
3643402aac7d985bf8a9f9d3c639f3fe93609380513Ronald Cron Continue. addr is Address to resume. If addr is omitted, resume at current
3652ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH Address.
3663402aac7d985bf8a9f9d3c639f3fe93609380513Ronald Cron
3673402aac7d985bf8a9f9d3c639f3fe93609380513Ronald Cron @param   SystemContext     Register content at time of the exception
3682ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH **/
3692ef2b01e07c02db339f34004445734a2dbdd80e1AJFISHVOID
3702ef2b01e07c02db339f34004445734a2dbdd80e1AJFISHEFIAPI
3712ef2b01e07c02db339f34004445734a2dbdd80e1AJFISHContinueAtAddress (
3722ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  IN  EFI_SYSTEM_CONTEXT      SystemContext,
3732ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  IN    CHAR8                 *PacketData
3742ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  )
3752ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH{
3762ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  if (PacketData[1] != '\0') {
3772ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH    SystemContext.SystemContextX64->Rip = AsciiStrHexToUintn(&PacketData[1]);
3783402aac7d985bf8a9f9d3c639f3fe93609380513Ronald Cron  }
3792ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH}
3802ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH
3812ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH
3822ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH/** ‘s [addr ]’
3833402aac7d985bf8a9f9d3c639f3fe93609380513Ronald Cron Single step. addr is the Address at which to resume. If addr is omitted, resume
3842ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH at same Address.
3853402aac7d985bf8a9f9d3c639f3fe93609380513Ronald Cron
3863402aac7d985bf8a9f9d3c639f3fe93609380513Ronald Cron @param   SystemContext     Register content at time of the exception
3872ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH **/
3882ef2b01e07c02db339f34004445734a2dbdd80e1AJFISHVOID
3892ef2b01e07c02db339f34004445734a2dbdd80e1AJFISHEFIAPI
3902ef2b01e07c02db339f34004445734a2dbdd80e1AJFISHSingleStep (
3912ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  IN  EFI_SYSTEM_CONTEXT      SystemContext,
3922ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  IN    CHAR8                 *PacketData
3932ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  )
3942ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH{
3952ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  if (PacketData[1] != '\0') {
3962ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH    SystemContext.SystemContextX64->Rip = AsciiStrHexToUintn (&PacketData[1]);
3972ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  }
3983402aac7d985bf8a9f9d3c639f3fe93609380513Ronald Cron
3992ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  AddSingleStep (SystemContext);
4002ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH}
4012ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH
4022ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH
4032ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH/**
4043402aac7d985bf8a9f9d3c639f3fe93609380513Ronald Cron  Returns breakpoint data address from DR0-DR3 based on the input breakpoint
4052ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  number
4062ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH
4072ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  @param  SystemContext      Register content at time of the exception
4082ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  @param  BreakpointNumber   Breakpoint number
4092ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH
4103402aac7d985bf8a9f9d3c639f3fe93609380513Ronald Cron  @retval Address            Data address from DR0-DR3 based on the
4112ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH                             breakpoint number.
4122ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH
4132ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH**/
4142ef2b01e07c02db339f34004445734a2dbdd80e1AJFISHUINTN
4152ef2b01e07c02db339f34004445734a2dbdd80e1AJFISHGetBreakpointDataAddress (
4162ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  IN  EFI_SYSTEM_CONTEXT  SystemContext,
4172ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  IN  UINTN               BreakpointNumber
4182ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  )
4192ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH{
4202ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  UINTN Address;
4212ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH
4222ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  if (BreakpointNumber == 1) {
4232ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH    Address = SystemContext.SystemContextIa32->Dr0;
4242ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  } else if (BreakpointNumber == 2) {
4252ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH    Address = SystemContext.SystemContextIa32->Dr1;
4262ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  } else if (BreakpointNumber == 3) {
4272ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH    Address = SystemContext.SystemContextIa32->Dr2;
4282ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  } else if (BreakpointNumber == 4) {
4292ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH    Address = SystemContext.SystemContextIa32->Dr3;
4302ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  } else {
4312ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH    Address = 0;
4322ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  }
4332ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH
4342ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  return Address;
4352ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH}
4362ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH
4372ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH/**
4383402aac7d985bf8a9f9d3c639f3fe93609380513Ronald Cron  Returns currently detected breakpoint value based on the register
4392ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  DR6 B0-B3 field.
4402ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  If no breakpoint is detected then it returns 0.
4412ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH
4422ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  @param  SystemContext  Register content at time of the exception
4432ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH
4442ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  @retval {1-4}          Currently detected breakpoint value
4452ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  @retval 0              No breakpoint detected.
4462ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH
4472ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH**/
4482ef2b01e07c02db339f34004445734a2dbdd80e1AJFISHUINTN
4492ef2b01e07c02db339f34004445734a2dbdd80e1AJFISHGetBreakpointDetected (
4502ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  IN  EFI_SYSTEM_CONTEXT  SystemContext
4512ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  )
4522ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH{
4532ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  IA32_DR6 Dr6;
4542ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  UINTN BreakpointNumber;
4552ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH
4562ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  Dr6.UintN = SystemContext.SystemContextIa32->Dr6;
4572ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH
4582ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  if (Dr6.Bits.B0 == 1) {
4592ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH    BreakpointNumber = 1;
4602ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  } else if (Dr6.Bits.B1 == 1) {
4612ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH    BreakpointNumber = 2;
4622ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  } else if (Dr6.Bits.B2 == 1) {
4632ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH    BreakpointNumber = 3;
4642ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  } else if (Dr6.Bits.B3 == 1) {
4652ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH    BreakpointNumber = 4;
4662ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  } else {
4672ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH    BreakpointNumber = 0;  //No breakpoint detected
4682ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  }
4692ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH
4702ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  return BreakpointNumber;
4712ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH}
4722ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH
4732ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH/**
4743402aac7d985bf8a9f9d3c639f3fe93609380513Ronald Cron  Returns Breakpoint type (InstructionExecution, DataWrite, DataRead
4752ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  or DataReadWrite) based on the Breakpoint number
4762ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH
4772ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  @param  SystemContext      Register content at time of the exception
4782ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  @param  BreakpointNumber   Breakpoint number
4792ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH
4803402aac7d985bf8a9f9d3c639f3fe93609380513Ronald Cron  @retval BREAK_TYPE         Breakpoint type value read from register DR7 RWn
4812ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH                             field. For unknown value, it returns NotSupported.
4822ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH
4832ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH**/
4842ef2b01e07c02db339f34004445734a2dbdd80e1AJFISHBREAK_TYPE
4852ef2b01e07c02db339f34004445734a2dbdd80e1AJFISHGetBreakpointType (
4862ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  IN  EFI_SYSTEM_CONTEXT  SystemContext,
4872ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  IN  UINTN               BreakpointNumber
4882ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  )
4892ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH{
4902ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  IA32_DR7 Dr7;
4912ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  BREAK_TYPE Type = NotSupported;  //Default is NotSupported type
4922ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH
4932ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  Dr7.UintN = SystemContext.SystemContextIa32->Dr7;
4942ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH
4952ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  if (BreakpointNumber == 1) {
4962ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH    Type = (BREAK_TYPE) Dr7.Bits.RW0;
4972ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  } else if (BreakpointNumber == 2) {
4982ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH    Type = (BREAK_TYPE) Dr7.Bits.RW1;
4992ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  } else if (BreakpointNumber == 3) {
5002ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH    Type = (BREAK_TYPE) Dr7.Bits.RW2;
5012ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  } else if (BreakpointNumber == 4) {
5022ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH    Type = (BREAK_TYPE) Dr7.Bits.RW3;
5032ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  }
5042ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH
5052ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  return Type;
5062ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH}
5072ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH
5082ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH
5093402aac7d985bf8a9f9d3c639f3fe93609380513Ronald Cron/**
5102ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  Parses Length and returns the length which DR7 LENn field accepts.
5113402aac7d985bf8a9f9d3c639f3fe93609380513Ronald Cron  For example: If we receive 1-Byte length then we should return 0.
5122ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH               Zero gets written to DR7 LENn field.
5132ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH
5142ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  @param  Length  Breakpoint length in Bytes (1 byte, 2 byte, 4 byte)
5152ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH
5162ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  @retval Length  Appropriate converted values which DR7 LENn field accepts.
5172ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH
5182ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH**/
5192ef2b01e07c02db339f34004445734a2dbdd80e1AJFISHUINTN
5202ef2b01e07c02db339f34004445734a2dbdd80e1AJFISHConvertLengthData (
5212ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  IN     UINTN   Length
5222ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  )
5232ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH{
5243402aac7d985bf8a9f9d3c639f3fe93609380513Ronald Cron  if (Length == 1) {         //1-Byte length
5252ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH    return 0;
5262ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  } else if (Length == 2) {  //2-Byte length
5272ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH    return 1;
5282ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  } else if (Length == 4) {  //4-Byte length
5292ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH    return 3;
5302ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  } else {                   //Undefined or 8-byte length
5312ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH    return 2;
5322ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  }
5332ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH}
5342ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH
5352ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH
5362ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH/**
5372ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  Finds the next free debug register. If all the registers are occupied then
5382ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  EFI_OUT_OF_RESOURCES is returned.
5392ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH
5402ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  @param  SystemContext  Register content at time of the exception
5412ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  @param  Register       Register value (0 - 3 for the first free debug register)
5422ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH
5432ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  @retval EFI_STATUS     Appropriate status value.
5442ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH
5452ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH**/
5462ef2b01e07c02db339f34004445734a2dbdd80e1AJFISHEFI_STATUS
5472ef2b01e07c02db339f34004445734a2dbdd80e1AJFISHFindNextFreeDebugRegister (
5482ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  IN  EFI_SYSTEM_CONTEXT  SystemContext,
5492ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  OUT UINTN               *Register
5502ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  )
5512ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH{
5522ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  IA32_DR7 Dr7;
5532ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH
5542ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  Dr7.UintN = SystemContext.SystemContextIa32->Dr7;
5552ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH
5562ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  if (Dr7.Bits.G0 == 0) {
5572ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH    *Register = 0;
5582ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  } else if (Dr7.Bits.G1 == 0) {
5592ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH    *Register = 1;
5602ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  } else if (Dr7.Bits.G2 == 0) {
5612ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH    *Register = 2;
5622ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  } else if (Dr7.Bits.G3 == 0) {
5632ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH    *Register = 3;
5642ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  } else {
5652ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH    return EFI_OUT_OF_RESOURCES;
5662ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  }
5672ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH
5682ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  return EFI_SUCCESS;
5692ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH}
5702ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH
5712ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH
5722ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH/**
5732ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  Enables the debug register. Writes Address value to appropriate DR0-3 register.
5742ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  Sets LENn, Gn, RWn bits in DR7 register.
5752ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH
5762ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  @param  SystemContext   Register content at time of the exception
5772ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  @param  Register        Register value (0 - 3)
5782ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  @param  Address         Breakpoint address value
5793402aac7d985bf8a9f9d3c639f3fe93609380513Ronald Cron  @param  Type            Breakpoint type (Instruction, Data write,
5802ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH                          Data read or write etc.)
5812ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH
5822ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  @retval EFI_STATUS      Appropriate status value.
5832ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH
5842ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH**/
5852ef2b01e07c02db339f34004445734a2dbdd80e1AJFISHEFI_STATUS
5862ef2b01e07c02db339f34004445734a2dbdd80e1AJFISHEnableDebugRegister (
5872ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  IN  EFI_SYSTEM_CONTEXT  SystemContext,
5882ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  IN  UINTN               Register,
5892ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  IN  UINTN               Address,
5902ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  IN  UINTN               Length,
5912ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  IN  UINTN               Type
5922ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  )
5932ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH{
5942ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  IA32_DR7  Dr7;
5952ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH
5962ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  //Convert length data
5972ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  Length = ConvertLengthData (Length);
5982ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH
5993402aac7d985bf8a9f9d3c639f3fe93609380513Ronald Cron  //For Instruction execution, length should be 0
6002ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  //(Ref. Intel reference manual 18.2.4)
6012ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  if ((Type == 0) && (Length != 0)) {
6022ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH    return EFI_INVALID_PARAMETER;
6032ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  }
6042ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH
6052ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  //Hardware doesn't support ReadWatch (z3 packet) type. GDB can handle
6062ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  //software breakpoint. We should send empty packet in both these cases.
6073402aac7d985bf8a9f9d3c639f3fe93609380513Ronald Cron  if ((Type == (BREAK_TYPE)DataRead) ||
6082ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH      (Type == (BREAK_TYPE)SoftwareBreakpoint))  {
6092ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH    return EFI_UNSUPPORTED;
6102ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  }
6112ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH
6122ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  //Read DR7 so appropriate Gn, RWn and LENn bits can be modified.
6132ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  Dr7.UintN = SystemContext.SystemContextIa32->Dr7;
6142ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH
6152ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  if (Register == 0) {
6162ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH    SystemContext.SystemContextIa32->Dr0 = Address;
6172ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH    Dr7.Bits.G0 = 1;
6182ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH    Dr7.Bits.RW0 = Type;
6192ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH    Dr7.Bits.LEN0 = Length;
6202ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  } else if (Register == 1) {
6212ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH    SystemContext.SystemContextIa32->Dr1 = Address;
6222ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH    Dr7.Bits.G1 = 1;
6232ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH    Dr7.Bits.RW1 = Type;
6242ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH    Dr7.Bits.LEN1 = Length;
6252ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  } else if (Register == 2) {
6262ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH    SystemContext.SystemContextIa32->Dr2 = Address;
6272ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH    Dr7.Bits.G2 = 1;
6282ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH    Dr7.Bits.RW2 = Type;
6292ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH    Dr7.Bits.LEN2 = Length;
6302ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  } else if (Register == 3) {
6312ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH    SystemContext.SystemContextIa32->Dr3 = Address;
6322ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH    Dr7.Bits.G3 = 1;
6332ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH    Dr7.Bits.RW3 = Type;
6342ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH    Dr7.Bits.LEN3 = Length;
6352ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  } else {
6362ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH    return EFI_INVALID_PARAMETER;
6372ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  }
6382ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH
6392ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  //Update Dr7 with appropriate Gn, RWn and LENn bits
6402ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  SystemContext.SystemContextIa32->Dr7 = Dr7.UintN;
6412ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH
6422ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  return EFI_SUCCESS;
6432ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH}
6442ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH
6452ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH
6463402aac7d985bf8a9f9d3c639f3fe93609380513Ronald Cron/**
6473402aac7d985bf8a9f9d3c639f3fe93609380513Ronald Cron  Returns register number 0 - 3 for the maching debug register.
6483402aac7d985bf8a9f9d3c639f3fe93609380513Ronald Cron  This function compares incoming Address, Type, Length and
6492ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  if there is a match then it returns the appropriate register number.
6502ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  In case of mismatch, function returns EFI_NOT_FOUND message.
6512ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH
6522ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  @param  SystemContext  Register content at time of the exception
6533402aac7d985bf8a9f9d3c639f3fe93609380513Ronald Cron  @param  Address        Breakpoint address value
6542ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  @param  Length         Breakpoint length value
6552ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  @param  Type           Breakpoint type (Instruction, Data write, Data read
6562ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH                         or write etc.)
6572ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  @param  Register       Register value to be returned
6582ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH
6592ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  @retval EFI_STATUS     Appropriate status value.
6602ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH
6612ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH**/
6622ef2b01e07c02db339f34004445734a2dbdd80e1AJFISHEFI_STATUS
6632ef2b01e07c02db339f34004445734a2dbdd80e1AJFISHFindMatchingDebugRegister (
6642ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH IN  EFI_SYSTEM_CONTEXT  SystemContext,
6652ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH IN  UINTN               Address,
6662ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH IN  UINTN               Length,
6672ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH IN  UINTN               Type,
6682ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH OUT UINTN               *Register
6692ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH )
6702ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH{
6712ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  IA32_DR7 Dr7;
6722ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH
6732ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  //Hardware doesn't support ReadWatch (z3 packet) type. GDB can handle
6742ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  //software breakpoint. We should send empty packet in both these cases.
6753402aac7d985bf8a9f9d3c639f3fe93609380513Ronald Cron  if ((Type == (BREAK_TYPE)DataRead) ||
6762ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH      (Type == (BREAK_TYPE)SoftwareBreakpoint)) {
6772ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH    return EFI_UNSUPPORTED;
6782ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  }
6792ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH
6802ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  //Convert length data
6812ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  Length = ConvertLengthData(Length);
6822ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH
6832ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  Dr7.UintN = SystemContext.SystemContextIa32->Dr7;
6842ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH
6853402aac7d985bf8a9f9d3c639f3fe93609380513Ronald Cron  if ((Dr7.Bits.G0 == 1) &&
6862ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH      (Dr7.Bits.LEN0 == Length) &&
6873402aac7d985bf8a9f9d3c639f3fe93609380513Ronald Cron      (Dr7.Bits.RW0 == Type) &&
6882ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH      (Address == SystemContext.SystemContextIa32->Dr0)) {
6892ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH    *Register = 0;
6903402aac7d985bf8a9f9d3c639f3fe93609380513Ronald Cron  } else if ((Dr7.Bits.G1 == 1) &&
6912ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH             (Dr7.Bits.LEN1 == Length) &&
6923402aac7d985bf8a9f9d3c639f3fe93609380513Ronald Cron             (Dr7.Bits.RW1 == Type) &&
6932ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH             (Address == SystemContext.SystemContextIa32->Dr1)) {
6942ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH    *Register = 1;
6953402aac7d985bf8a9f9d3c639f3fe93609380513Ronald Cron  } else if ((Dr7.Bits.G2 == 1) &&
6962ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH             (Dr7.Bits.LEN2 == Length) &&
6973402aac7d985bf8a9f9d3c639f3fe93609380513Ronald Cron             (Dr7.Bits.RW2 == Type) &&
6982ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH             (Address == SystemContext.SystemContextIa32->Dr2)) {
6992ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH    *Register = 2;
7003402aac7d985bf8a9f9d3c639f3fe93609380513Ronald Cron  } else if ((Dr7.Bits.G3 == 1) &&
7012ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH             (Dr7.Bits.LEN3 == Length) &&
7023402aac7d985bf8a9f9d3c639f3fe93609380513Ronald Cron             (Dr7.Bits.RW3 == Type) &&
7032ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH             (Address == SystemContext.SystemContextIa32->Dr3)) {
7042ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH    *Register = 3;
7052ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  } else {
7062ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH    Print ((CHAR16 *)L"No match found..\n");
7072ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH    return EFI_NOT_FOUND;
7082ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  }
7092ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH
7102ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  return EFI_SUCCESS;
7112ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH}
7122ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH
7132ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH
7142ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH/**
7152ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  Disables the particular debug register.
7162ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH
7172ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  @param  SystemContext   Register content at time of the exception
7182ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  @param  Register        Register to be disabled
7192ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH
7202ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  @retval EFI_STATUS      Appropriate status value.
7212ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH
7222ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH**/
7232ef2b01e07c02db339f34004445734a2dbdd80e1AJFISHEFI_STATUS
7242ef2b01e07c02db339f34004445734a2dbdd80e1AJFISHDisableDebugRegister (
7252ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH IN  EFI_SYSTEM_CONTEXT  SystemContext,
7262ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH IN  UINTN               Register
7272ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH )
7282ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH{
7292ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  IA32_DR7  Dr7;
7302ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  UINTN Address = 0;
7312ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH
7322ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  //Read DR7 register so appropriate Gn, RWn and LENn bits can be turned off.
7332ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  Dr7.UintN = SystemContext.SystemContextIa32->Dr7;
7342ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH
7352ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  if (Register == 0) {
7362ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH    SystemContext.SystemContextIa32->Dr0 = Address;
7372ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH    Dr7.Bits.G0 = 0;
7382ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH    Dr7.Bits.RW0 = 0;
7392ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH    Dr7.Bits.LEN0 = 0;
7402ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  } else if (Register == 1) {
7412ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH    SystemContext.SystemContextIa32->Dr1 = Address;
7422ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH    Dr7.Bits.G1 = 0;
7432ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH    Dr7.Bits.RW1 = 0;
7442ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH    Dr7.Bits.LEN1 = 0;
7452ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  } else if (Register == 2) {
7462ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH    SystemContext.SystemContextIa32->Dr2 = Address;
7472ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH    Dr7.Bits.G2 = 0;
7482ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH    Dr7.Bits.RW2 = 0;
7492ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH    Dr7.Bits.LEN2 = 0;
7502ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  } else if (Register == 3) {
7512ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH    SystemContext.SystemContextIa32->Dr3 = Address;
7522ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH    Dr7.Bits.G3 = 0;
7532ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH    Dr7.Bits.RW3 = 0;
7542ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH    Dr7.Bits.LEN3 = 0;
7552ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  } else {
7562ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH    return EFI_INVALID_PARAMETER;
7572ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  }
7582ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH
7592ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  //Update DR7 register so appropriate Gn, RWn and LENn bits can be turned off.
7602ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  SystemContext.SystemContextIa32->Dr7 = Dr7.UintN;
7612ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH
7622ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  return EFI_SUCCESS;
7632ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH}
7642ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH
7652ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH/**
7662ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  ‘Z1, [addr], [length]’
7672ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  ‘Z2, [addr], [length]’
7682ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  ‘Z3, [addr], [length]’
7692ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  ‘Z4, [addr], [length]’
7702ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH
7712ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  Insert hardware breakpoint/watchpoint at address addr of size length
7722ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH
7732ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  @param SystemContext  Register content at time of the exception
7742ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  @param *PacketData    Pointer to the Payload data for the packet
7752ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH
7762ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH**/
7772ef2b01e07c02db339f34004445734a2dbdd80e1AJFISHVOID
7782ef2b01e07c02db339f34004445734a2dbdd80e1AJFISHEFIAPI
7792ef2b01e07c02db339f34004445734a2dbdd80e1AJFISHInsertBreakPoint (
7802ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  IN  EFI_SYSTEM_CONTEXT  SystemContext,
7812ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  IN  CHAR8              *PacketData
7822ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  )
7832ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH{
7842ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  UINTN Type;
7852ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  UINTN Address;
7862ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  UINTN Length;
7872ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  UINTN Register;
7882ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  EFI_STATUS Status;
7892ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  BREAK_TYPE BreakType = NotSupported;
7902ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  UINTN ErrorCode;
7912ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH
7922ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  ErrorCode = ParseBreakpointPacket (PacketData, &Type, &Address, &Length);
7932ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  if (ErrorCode > 0) {
7942ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH    SendError ((UINT8)ErrorCode);
7952ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH    return;
7962ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  }
7972ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH
7982ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  switch (Type) {
7992ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH
8002ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH    case    0:   //Software breakpoint
8012ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH      BreakType = SoftwareBreakpoint;
8022ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH      break;
8032ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH
8042ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH    case    1:   //Hardware breakpoint
8052ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH      BreakType = InstructionExecution;
8062ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH      break;
8072ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH
8082ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH    case    2:   //Write watchpoint
8092ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH      BreakType = DataWrite;
8102ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH      break;
8112ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH
8122ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH    case    3:   //Read watchpoint
8132ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH      BreakType = DataRead;
8142ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH      break;
8152ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH
8162ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH    case    4:   //Access watchpoint
8172ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH      BreakType = DataReadWrite;
8182ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH      break;
8192ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH
8202ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH    default  :
8212ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH      Print ((CHAR16 *)L"Insert breakpoint default: %x\n", Type);
8222ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH      SendError (GDB_EINVALIDBRKPOINTTYPE);
8232ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH      return;
8242ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  }
8252ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH
8262ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  // Find next free debug register
8272ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  Status = FindNextFreeDebugRegister (SystemContext, &Register);
8282ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  if (EFI_ERROR(Status)) {
8292ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH    Print ((CHAR16 *)L"No space left on device\n");
8302ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH    SendError (GDB_ENOSPACE);
8312ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH    return;
8322ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  }
8332ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH
8342ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  // Write Address, length data at particular DR register
8352ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  Status = EnableDebugRegister (SystemContext, Register, Address, Length, (UINTN)BreakType);
8362ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  if (EFI_ERROR(Status)) {
8372ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH
8382ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH    if (Status == EFI_UNSUPPORTED) {
8392ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH      Print ((CHAR16 *)L"Not supported\n");
8402ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH      SendNotSupported();
8412ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH      return;
8422ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH    }
8432ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH
8442ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH    Print ((CHAR16 *)L"Invalid argument\n");
8452ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH    SendError (GDB_EINVALIDARG);
8462ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH    return;
8472ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  }
8482ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH
8492ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  SendSuccess ();
8502ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH}
8512ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH
8522ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH
8532ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH/**
8542ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  ‘z1, [addr], [length]’
8552ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  ‘z2, [addr], [length]’
8562ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  ‘z3, [addr], [length]’
8572ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  ‘z4, [addr], [length]’
8582ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH
8592ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  Remove hardware breakpoint/watchpoint at address addr of size length
8602ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH
8612ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  @param *PacketData    Pointer to the Payload data for the packet
8622ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH
8632ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH**/
8642ef2b01e07c02db339f34004445734a2dbdd80e1AJFISHVOID
8652ef2b01e07c02db339f34004445734a2dbdd80e1AJFISHEFIAPI
8662ef2b01e07c02db339f34004445734a2dbdd80e1AJFISHRemoveBreakPoint (
8672ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  IN  EFI_SYSTEM_CONTEXT  SystemContext,
8682ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  IN  CHAR8               *PacketData
8692ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  )
8702ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH{
8712ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  UINTN      Type;
8722ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  UINTN      Address;
8732ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  UINTN      Length;
8742ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  UINTN      Register;
8752ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  BREAK_TYPE BreakType = NotSupported;
8762ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  EFI_STATUS Status;
8772ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  UINTN      ErrorCode;
8782ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH
8792ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  //Parse breakpoint packet data
8802ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  ErrorCode = ParseBreakpointPacket (PacketData, &Type, &Address, &Length);
8812ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  if (ErrorCode > 0) {
8822ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH    SendError ((UINT8)ErrorCode);
8832ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH    return;
8842ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  }
8852ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH
8862ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  switch (Type) {
8873402aac7d985bf8a9f9d3c639f3fe93609380513Ronald Cron
8882ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH    case    0:   //Software breakpoint
8892ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH      BreakType = SoftwareBreakpoint;
8902ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH      break;
8913402aac7d985bf8a9f9d3c639f3fe93609380513Ronald Cron
8922ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH    case    1:   //Hardware breakpoint
8932ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH      BreakType = InstructionExecution;
8942ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH      break;
8953402aac7d985bf8a9f9d3c639f3fe93609380513Ronald Cron
8962ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH    case    2:   //Write watchpoint
8972ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH      BreakType = DataWrite;
8982ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH      break;
8992ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH
9002ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH    case    3:   //Read watchpoint
9012ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH      BreakType = DataRead;
9022ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH      break;
9032ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH
9042ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH    case    4:   //Access watchpoint
9052ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH      BreakType = DataReadWrite;
9062ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH      break;
9072ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH
9082ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH    default  :
9092ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH      SendError (GDB_EINVALIDBRKPOINTTYPE);
9102ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH      return;
9112ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  }
9122ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH
9132ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  //Find matching debug register
9142ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  Status = FindMatchingDebugRegister (SystemContext, Address, Length, (UINTN)BreakType, &Register);
9152ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  if (EFI_ERROR(Status)) {
9162ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH
9172ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH    if (Status == EFI_UNSUPPORTED) {
9182ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH      Print ((CHAR16 *)L"Not supported.\n");
9192ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH      SendNotSupported();
9202ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH      return;
9212ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH    }
9222ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH
9232ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH    Print ((CHAR16 *)L"No matching register found.\n");
9242ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH    SendError (GDB_ENOSPACE);
9252ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH    return;
9262ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  }
9272ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH
9282ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  //Remove breakpoint
9292ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  Status = DisableDebugRegister(SystemContext, Register);
9302ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  if (EFI_ERROR(Status)) {
9312ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH    Print ((CHAR16 *)L"Invalid argument.\n");
9322ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH    SendError (GDB_EINVALIDARG);
9332ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH    return;
9342ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  }
9352ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH
9362ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  SendSuccess ();
9372ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH}
9382ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH
9392ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH
9402ef2b01e07c02db339f34004445734a2dbdd80e1AJFISHVOID
9412ef2b01e07c02db339f34004445734a2dbdd80e1AJFISHInitializeProcessor (
9422ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  VOID
9432ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  )
9442ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH{
9452ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH}
9462ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH
9472ef2b01e07c02db339f34004445734a2dbdd80e1AJFISHBOOLEAN
9482ef2b01e07c02db339f34004445734a2dbdd80e1AJFISHValidateAddress (
9492ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  IN  VOID  *Address
9502ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  )
9512ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH{
9522ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  return TRUE;
9532ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH}
9542ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH
9552ef2b01e07c02db339f34004445734a2dbdd80e1AJFISHBOOLEAN
9562ef2b01e07c02db339f34004445734a2dbdd80e1AJFISHValidateException (
9573402aac7d985bf8a9f9d3c639f3fe93609380513Ronald Cron  IN  EFI_EXCEPTION_TYPE    ExceptionType,
9583402aac7d985bf8a9f9d3c639f3fe93609380513Ronald Cron  IN OUT EFI_SYSTEM_CONTEXT SystemContext
9592ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  )
9602ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH{
9612ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  return TRUE;
9622ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH}
9632ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH
964