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#include <Library/CacheMaintenanceLib.h>
182ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH#include <Library/PrintLib.h>
192ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH
202ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH//
212ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH// Array of exception types that need to be hooked by the debugger
222ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH// (efi, gdb) //efi number
232ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH//
242ef2b01e07c02db339f34004445734a2dbdd80e1AJFISHEFI_EXCEPTION_TYPE_ENTRY gExceptionType[] = {
252ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  { EXCEPT_ARM_SOFTWARE_INTERRUPT,  GDB_SIGTRAP }
263402aac7d985bf8a9f9d3c639f3fe93609380513Ronald Cron//  { EXCEPT_ARM_UNDEFINED_INSTRUCTION, GDB_SIGTRAP },
273402aac7d985bf8a9f9d3c639f3fe93609380513Ronald Cron//  { EXCEPT_ARM_PREFETCH_ABORT,        GDB_SIGTRAP },
283402aac7d985bf8a9f9d3c639f3fe93609380513Ronald Cron//  { EXCEPT_ARM_DATA_ABORT,            GDB_SIGEMT  },
293402aac7d985bf8a9f9d3c639f3fe93609380513Ronald Cron//  { EXCEPT_ARM_RESERVED,              GDB_SIGILL  }
302ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH};
312ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH
322ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH// Shut up some annoying RVCT warnings
332ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH#ifdef __CC_ARM
342ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH#pragma diag_suppress 1296
352ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH#endif
362ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH
372ef2b01e07c02db339f34004445734a2dbdd80e1AJFISHUINTN gRegisterOffsets[] = {
382ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  OFFSET_OF(EFI_SYSTEM_CONTEXT_ARM, R0),
392ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  OFFSET_OF(EFI_SYSTEM_CONTEXT_ARM, R1),
402ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  OFFSET_OF(EFI_SYSTEM_CONTEXT_ARM, R2),
412ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  OFFSET_OF(EFI_SYSTEM_CONTEXT_ARM, R3),
422ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  OFFSET_OF(EFI_SYSTEM_CONTEXT_ARM, R4),
432ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  OFFSET_OF(EFI_SYSTEM_CONTEXT_ARM, R5),
442ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  OFFSET_OF(EFI_SYSTEM_CONTEXT_ARM, R6),
452ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  OFFSET_OF(EFI_SYSTEM_CONTEXT_ARM, R7),
462ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  OFFSET_OF(EFI_SYSTEM_CONTEXT_ARM, R8),
472ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  OFFSET_OF(EFI_SYSTEM_CONTEXT_ARM, R9),
482ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  OFFSET_OF(EFI_SYSTEM_CONTEXT_ARM, R10),
492ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  OFFSET_OF(EFI_SYSTEM_CONTEXT_ARM, R11),
502ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  OFFSET_OF(EFI_SYSTEM_CONTEXT_ARM, R12),
512ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  OFFSET_OF(EFI_SYSTEM_CONTEXT_ARM, SP),
522ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  OFFSET_OF(EFI_SYSTEM_CONTEXT_ARM, LR),
532ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  OFFSET_OF(EFI_SYSTEM_CONTEXT_ARM, PC),
542ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  0x00000F01,                               // f0
552ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  0x00000F02,
562ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  0x00000F03,
572ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  0x00000F11,                               // f1
582ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  0x00000F12,
592ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  0x00000F13,
602ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  0x00000F21,                               // f2
612ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  0x00000F22,
622ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  0x00000F23,
632ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  0x00000F31,                               // f3
642ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  0x00000F32,
652ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  0x00000F33,
662ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  0x00000F41,                               // f4
672ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  0x00000F42,
682ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  0x00000F43,
692ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  0x00000F51,                               // f5
702ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  0x00000F52,
712ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  0x00000F53,
722ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  0x00000F61,                               // f6
732ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  0x00000F62,
742ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  0x00000F63,
752ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  0x00000F71,                               // f7
762ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  0x00000F72,
772ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  0x00000F73,
782ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  0x00000FFF,                               // fps
792ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  OFFSET_OF(EFI_SYSTEM_CONTEXT_ARM, CPSR)
802ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH};
812ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH
822ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH// restore warnings for RVCT
832ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH#ifdef __CC_ARM
842ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH#pragma diag_default 1296
852ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH#endif
862ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH
872ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH/**
882ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH Return the number of entries in the gExceptionType[]
893402aac7d985bf8a9f9d3c639f3fe93609380513Ronald Cron
903402aac7d985bf8a9f9d3c639f3fe93609380513Ronald Cron @retval  UINTN, the number of entries in the gExceptionType[] array.
912ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH **/
922ef2b01e07c02db339f34004445734a2dbdd80e1AJFISHUINTN
932ef2b01e07c02db339f34004445734a2dbdd80e1AJFISHMaxEfiException (
942ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  VOID
952ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  )
962ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH{
976f711615bacf7ce3bc42507cba87bc0adcda0461oliviermartin  return sizeof (gExceptionType) / sizeof (EFI_EXCEPTION_TYPE_ENTRY);
982ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH}
992ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH
1002ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH
1012ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH/**
1022ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH Return the number of entries in the gRegisters[]
1033402aac7d985bf8a9f9d3c639f3fe93609380513Ronald Cron
1043402aac7d985bf8a9f9d3c639f3fe93609380513Ronald Cron @retval  UINTN, the number of entries (registers) in the gRegisters[] array.
1052ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH **/
1062ef2b01e07c02db339f34004445734a2dbdd80e1AJFISHUINTN
1072ef2b01e07c02db339f34004445734a2dbdd80e1AJFISHMaxRegisterCount (
1082ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  VOID
1092ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  )
1102ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH{
1116f711615bacf7ce3bc42507cba87bc0adcda0461oliviermartin  return sizeof (gRegisterOffsets) / sizeof (UINTN);
1122ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH}
1132ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH
1142ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH
1152ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH/**
1163402aac7d985bf8a9f9d3c639f3fe93609380513Ronald Cron Check to see if the ISA is supported.
1172ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH ISA = Instruction Set Architecture
1182ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH
1193402aac7d985bf8a9f9d3c639f3fe93609380513Ronald Cron @retval TRUE if Isa is supported
1202ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH
1212ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH**/
1222ef2b01e07c02db339f34004445734a2dbdd80e1AJFISHBOOLEAN
1232ef2b01e07c02db339f34004445734a2dbdd80e1AJFISHCheckIsa (
1242ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  IN  EFI_INSTRUCTION_SET_ARCHITECTURE  Isa
1252ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  )
1262ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH{
1272ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  if (Isa == IsaArm) {
1282ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH    return TRUE;
1292ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  } else {
1302ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH    return FALSE;
1312ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  }
1322ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH}
1332ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH
1342ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH
1352ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH/**
1362ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH This takes in the register number and the System Context, and returns a pointer to the RegNumber-th register in gdb ordering
1372ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH It is, by default, set to find the register pointer of the ARM member
1383402aac7d985bf8a9f9d3c639f3fe93609380513Ronald Cron @param   SystemContext     Register content at time of the exception
1392ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH @param   RegNumber       The register to which we want to find a pointer
1402ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH @retval  the pointer to the RegNumber-th pointer
1413402aac7d985bf8a9f9d3c639f3fe93609380513Ronald Cron **/
1422ef2b01e07c02db339f34004445734a2dbdd80e1AJFISHUINTN *
1436f711615bacf7ce3bc42507cba87bc0adcda0461oliviermartinFindPointerToRegister (
1442ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  IN  EFI_SYSTEM_CONTEXT      SystemContext,
1453402aac7d985bf8a9f9d3c639f3fe93609380513Ronald Cron  IN  UINTN           RegNumber
1462ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  )
1472ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH{
1482ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  UINT8 *TempPtr;
1492ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  ASSERT(gRegisterOffsets[RegNumber] < 0xF00);
1502ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  TempPtr = ((UINT8 *)SystemContext.SystemContextArm) + gRegisterOffsets[RegNumber];
1512ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  return (UINT32 *)TempPtr;
1522ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH}
1532ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH
1542ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH
1552ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH/**
1562ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH Adds the RegNumber-th register's value to the output buffer, starting at the given OutBufPtr
1572ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH @param SystemContext     Register content at time of the exception
1582ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH @param   RegNumber       the number of the register that we want to read
1592ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH @param   OutBufPtr       pointer to the output buffer's end. the new data will be added from this point on.
1602ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH @retval  the pointer to the next character of the output buffer that is available to be written on.
1612ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH **/
1622ef2b01e07c02db339f34004445734a2dbdd80e1AJFISHCHAR8 *
1632ef2b01e07c02db339f34004445734a2dbdd80e1AJFISHBasicReadRegister (
1642ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  IN  EFI_SYSTEM_CONTEXT  SystemContext,
1652ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  IN  UINTN               RegNumber,
1662ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  IN  CHAR8               *OutBufPtr
1672ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  )
1682ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH{
1692ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  UINTN RegSize;
1702ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  CHAR8 Char;
1713402aac7d985bf8a9f9d3c639f3fe93609380513Ronald Cron
1722ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  if (gRegisterOffsets[RegNumber] > 0xF00) {
1736f711615bacf7ce3bc42507cba87bc0adcda0461oliviermartin    AsciiSPrint (OutBufPtr, 9, "00000000");
1742ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH    OutBufPtr += 8;
1752ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH    return OutBufPtr;
1762ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  }
1772ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH
1782ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  RegSize = 0;
1792ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  while (RegSize < 32) {
1806f711615bacf7ce3bc42507cba87bc0adcda0461oliviermartin    Char = mHexToStr[(UINT8)((*FindPointerToRegister (SystemContext, RegNumber) >> (RegSize+4)) & 0xf)];
1812ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH    if ((Char >= 'A') && (Char <= 'F')) {
1822ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH      Char = Char - 'A' + 'a';
1832ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH    }
1842ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH    *OutBufPtr++ = Char;
1853402aac7d985bf8a9f9d3c639f3fe93609380513Ronald Cron
1866f711615bacf7ce3bc42507cba87bc0adcda0461oliviermartin    Char = mHexToStr[(UINT8)((*FindPointerToRegister (SystemContext, RegNumber) >> RegSize) & 0xf)];
1872ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH    if ((Char >= 'A') && (Char <= 'F')) {
1882ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH      Char = Char - 'A' + 'a';
1892ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH    }
1902ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH    *OutBufPtr++ = Char;
1913402aac7d985bf8a9f9d3c639f3fe93609380513Ronald Cron
1922ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH    RegSize = RegSize + 8;
1932ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  }
1942ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  return OutBufPtr;
1952ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH}
1962ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH
1972ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH
19811c20f4e06d252feaa65aa5e526686baf015762doliviermartin/**
1993402aac7d985bf8a9f9d3c639f3fe93609380513Ronald Cron Reads the n-th register's value into an output buffer and sends it as a packet
2002ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH @param   SystemContext   Register content at time of the exception
2012ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH @param   InBuffer      Pointer to the input buffer received from gdb server
2022ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH **/
2032ef2b01e07c02db339f34004445734a2dbdd80e1AJFISHVOID
2042ef2b01e07c02db339f34004445734a2dbdd80e1AJFISHReadNthRegister (
2052ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  IN  EFI_SYSTEM_CONTEXT  SystemContext,
2062ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  IN  CHAR8               *InBuffer
2072ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  )
2082ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH{
2092ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  UINTN RegNumber;
2102ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  CHAR8 OutBuffer[9]; // 1 reg=8 hex chars, and the end '\0' (escape seq)
2112ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  CHAR8 *OutBufPtr;   // pointer to the output buffer
2123402aac7d985bf8a9f9d3c639f3fe93609380513Ronald Cron
2132ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  RegNumber = AsciiStrHexToUintn (&InBuffer[1]);
2143402aac7d985bf8a9f9d3c639f3fe93609380513Ronald Cron
2156f711615bacf7ce3bc42507cba87bc0adcda0461oliviermartin  if (RegNumber >= MaxRegisterCount ()) {
2163402aac7d985bf8a9f9d3c639f3fe93609380513Ronald Cron    SendError (GDB_EINVALIDREGNUM);
2172ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH    return;
2182ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  }
2193402aac7d985bf8a9f9d3c639f3fe93609380513Ronald Cron
2202ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  OutBufPtr = OutBuffer;
2212ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  OutBufPtr = BasicReadRegister (SystemContext, RegNumber, OutBufPtr);
2223402aac7d985bf8a9f9d3c639f3fe93609380513Ronald Cron
2232ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  *OutBufPtr = '\0';  // the end of the buffer
2246f711615bacf7ce3bc42507cba87bc0adcda0461oliviermartin  SendPacket (OutBuffer);
2252ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH}
2262ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH
2272ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH
22811c20f4e06d252feaa65aa5e526686baf015762doliviermartin/**
2293402aac7d985bf8a9f9d3c639f3fe93609380513Ronald Cron Reads the general registers into an output buffer  and sends it as a packet
2302ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH @param   SystemContext     Register content at time of the exception
2312ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH **/
2322ef2b01e07c02db339f34004445734a2dbdd80e1AJFISHVOID
2332ef2b01e07c02db339f34004445734a2dbdd80e1AJFISHEFIAPI
2343402aac7d985bf8a9f9d3c639f3fe93609380513Ronald CronReadGeneralRegisters (
2352ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  IN  EFI_SYSTEM_CONTEXT      SystemContext
2362ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  )
2372ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH{
2382ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  UINTN   Index;
2392ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  CHAR8   *OutBuffer;
2402ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  CHAR8   *OutBufPtr;
2416f711615bacf7ce3bc42507cba87bc0adcda0461oliviermartin  UINTN   RegisterCount = MaxRegisterCount ();
2423402aac7d985bf8a9f9d3c639f3fe93609380513Ronald Cron
2432ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  // It is not safe to allocate pool here....
2446f711615bacf7ce3bc42507cba87bc0adcda0461oliviermartin  OutBuffer = AllocatePool ((RegisterCount * 8) + 1); // 8 bytes per register in string format plus a null to terminate
2452ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  OutBufPtr = OutBuffer;
2462ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  for (Index = 0; Index < RegisterCount; Index++) {
2472ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH    OutBufPtr = BasicReadRegister (SystemContext, Index, OutBufPtr);
2482ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  }
2493402aac7d985bf8a9f9d3c639f3fe93609380513Ronald Cron
2502ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  *OutBufPtr = '\0';
2516f711615bacf7ce3bc42507cba87bc0adcda0461oliviermartin  SendPacket (OutBuffer);
2526f711615bacf7ce3bc42507cba87bc0adcda0461oliviermartin  FreePool (OutBuffer);
2532ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH}
2542ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH
2552ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH
2562ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH/**
2572ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH Adds the RegNumber-th register's value to the output buffer, starting at the given OutBufPtr
2582ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH @param   SystemContext       Register content at time of the exception
2592ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH @param   RegNumber         the number of the register that we want to write
2602ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH @param   InBufPtr          pointer to the output buffer. the new data will be extracted from the input buffer from this point on.
2612ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH @retval  the pointer to the next character of the input buffer that can be used
2622ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH **/
2632ef2b01e07c02db339f34004445734a2dbdd80e1AJFISHCHAR8
2642ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH*BasicWriteRegister (
2652ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  IN  EFI_SYSTEM_CONTEXT      SystemContext,
2662ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  IN  UINTN           RegNumber,
2672ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  IN  CHAR8           *InBufPtr
2682ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  )
2692ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH{
2702ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  UINTN RegSize;
2712ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  UINTN TempValue; // the value transferred from a hex char
2722ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  UINT32 NewValue; // the new value of the RegNumber-th Register
2733402aac7d985bf8a9f9d3c639f3fe93609380513Ronald Cron
2742ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  if (gRegisterOffsets[RegNumber] > 0xF00) {
2752ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH    return InBufPtr + 8;
2762ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  }
2772ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH
2782ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  NewValue = 0;
2792ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  RegSize = 0;
2802ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  while (RegSize < 32) {
2816f711615bacf7ce3bc42507cba87bc0adcda0461oliviermartin    TempValue = HexCharToInt (*InBufPtr++);
2823402aac7d985bf8a9f9d3c639f3fe93609380513Ronald Cron
2832ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH    if ((INTN)TempValue < 0) {
2843402aac7d985bf8a9f9d3c639f3fe93609380513Ronald Cron      SendError (GDB_EBADMEMDATA);
2852ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH      return NULL;
2862ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH    }
2873402aac7d985bf8a9f9d3c639f3fe93609380513Ronald Cron
2882ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH    NewValue += (TempValue << (RegSize+4));
2896f711615bacf7ce3bc42507cba87bc0adcda0461oliviermartin    TempValue = HexCharToInt (*InBufPtr++);
2903402aac7d985bf8a9f9d3c639f3fe93609380513Ronald Cron
2912ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH    if ((INTN)TempValue < 0) {
2923402aac7d985bf8a9f9d3c639f3fe93609380513Ronald Cron      SendError (GDB_EBADMEMDATA);
2932ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH      return NULL;
2942ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH    }
2953402aac7d985bf8a9f9d3c639f3fe93609380513Ronald Cron
2963402aac7d985bf8a9f9d3c639f3fe93609380513Ronald Cron    NewValue += (TempValue << RegSize);
2972ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH    RegSize = RegSize + 8;
2982ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  }
2996f711615bacf7ce3bc42507cba87bc0adcda0461oliviermartin  *(FindPointerToRegister (SystemContext, RegNumber)) = NewValue;
3002ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  return InBufPtr;
3012ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH}
3022ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH
3032ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH
3042ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH/** ‘P n...=r...’
3052ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH Writes the new value of n-th register received into the input buffer to the n-th register
3062ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH @param   SystemContext   Register content at time of the exception
3072ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH @param   InBuffer      Ponter to the input buffer received from gdb server
3082ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH **/
3092ef2b01e07c02db339f34004445734a2dbdd80e1AJFISHVOID
3102ef2b01e07c02db339f34004445734a2dbdd80e1AJFISHWriteNthRegister (
3112ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  IN  EFI_SYSTEM_CONTEXT      SystemContext,
3122ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  IN  CHAR8           *InBuffer
3132ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  )
3142ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH{
3152ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  UINTN RegNumber;
3162ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  CHAR8 RegNumBuffer[MAX_REG_NUM_BUF_SIZE];  // put the 'n..' part of the message into this array
3172ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  CHAR8 *RegNumBufPtr;
3182ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  CHAR8 *InBufPtr; // pointer to the input buffer
3193402aac7d985bf8a9f9d3c639f3fe93609380513Ronald Cron
3202ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  // find the register number to write
3212ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  InBufPtr = &InBuffer[1];
3222ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  RegNumBufPtr = RegNumBuffer;
3232ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  while (*InBufPtr != '=') {
3242ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH    *RegNumBufPtr++ = *InBufPtr++;
3253402aac7d985bf8a9f9d3c639f3fe93609380513Ronald Cron  }
3262ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  *RegNumBufPtr = '\0';
3273402aac7d985bf8a9f9d3c639f3fe93609380513Ronald Cron  RegNumber = AsciiStrHexToUintn (RegNumBuffer);
3283402aac7d985bf8a9f9d3c639f3fe93609380513Ronald Cron
3292ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  // check if this is a valid Register Number
3306f711615bacf7ce3bc42507cba87bc0adcda0461oliviermartin  if (RegNumber >= MaxRegisterCount ()) {
3313402aac7d985bf8a9f9d3c639f3fe93609380513Ronald Cron    SendError (GDB_EINVALIDREGNUM);
3322ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH    return;
3332ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  }
3342ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  InBufPtr++;  // skips the '=' character
3352ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  BasicWriteRegister (SystemContext, RegNumber, InBufPtr);
3362ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  SendSuccess();
3372ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH}
3382ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH
3392ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH
3402ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH/** ‘G XX...’
3412ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH Writes the new values received into the input buffer to the general registers
3422ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH @param   SystemContext       Register content at time of the exception
3432ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH @param   InBuffer          Pointer to the input buffer received from gdb server
3442ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH **/
3452ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH
3462ef2b01e07c02db339f34004445734a2dbdd80e1AJFISHVOID
3472ef2b01e07c02db339f34004445734a2dbdd80e1AJFISHEFIAPI
3482ef2b01e07c02db339f34004445734a2dbdd80e1AJFISHWriteGeneralRegisters (
3492ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  IN  EFI_SYSTEM_CONTEXT  SystemContext,
3502ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  IN  CHAR8               *InBuffer
3512ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  )
3522ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH{
3532ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  UINTN  i;
3542ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  CHAR8  *InBufPtr; /// pointer to the input buffer
3552ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  UINTN  MinLength;
3566f711615bacf7ce3bc42507cba87bc0adcda0461oliviermartin  UINTN  RegisterCount = MaxRegisterCount ();
3572ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH
3582ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  MinLength = (RegisterCount * 8) + 1;  // 'G' plus the registers in ASCII format
3593402aac7d985bf8a9f9d3c639f3fe93609380513Ronald Cron
3606f711615bacf7ce3bc42507cba87bc0adcda0461oliviermartin  if (AsciiStrLen (InBuffer) < MinLength) {
3613402aac7d985bf8a9f9d3c639f3fe93609380513Ronald Cron    //Bad message. Message is not the right length
3623402aac7d985bf8a9f9d3c639f3fe93609380513Ronald Cron    SendError (GDB_EBADBUFSIZE);
3632ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH    return;
3642ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  }
3653402aac7d985bf8a9f9d3c639f3fe93609380513Ronald Cron
3662ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  InBufPtr = &InBuffer[1];
3673402aac7d985bf8a9f9d3c639f3fe93609380513Ronald Cron
3682ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  // Read the new values for the registers from the input buffer to an array, NewValueArray.
3692ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  // The values in the array are in the gdb ordering
3706f711615bacf7ce3bc42507cba87bc0adcda0461oliviermartin  for (i = 0; i < RegisterCount; i++) {
3712ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH    InBufPtr = BasicWriteRegister (SystemContext, i, InBufPtr);
3722ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  }
3733402aac7d985bf8a9f9d3c639f3fe93609380513Ronald Cron
3742ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  SendSuccess ();
3752ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH}
3762ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH
3772ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH// What about Thumb?
3782ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH// Use SWI 0xdbdbdb as the debug instruction
3792ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH#define GDB_ARM_BKPT    0xefdbdbdb
3802ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH
3812ef2b01e07c02db339f34004445734a2dbdd80e1AJFISHBOOLEAN mSingleStepActive = FALSE;
3822ef2b01e07c02db339f34004445734a2dbdd80e1AJFISHUINT32  mSingleStepPC;
3832ef2b01e07c02db339f34004445734a2dbdd80e1AJFISHUINT32  mSingleStepData;
3842ef2b01e07c02db339f34004445734a2dbdd80e1AJFISHUINTN   mSingleStepDataSize;
3852ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH
3862ef2b01e07c02db339f34004445734a2dbdd80e1AJFISHtypedef struct {
3872ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  LIST_ENTRY  Link;
3882ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  UINT64      Signature;
3892ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  UINT32      Address;
3902ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  UINT32      Instruction;
3912ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH} ARM_SOFTWARE_BREAKPOINT;
3922ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH
3932ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH#define ARM_SOFTWARE_BREAKPOINT_SIGNATURE     SIGNATURE_64('A', 'R', 'M', 'B', 'R', 'K', 'P', 'T')
3942ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH#define ARM_SOFTWARE_BREAKPOINT_FROM_LINK(a)  CR(a, ARM_SOFTWARE_BREAKPOINT, Link, ARM_SOFTWARE_BREAKPOINT_SIGNATURE)
3952ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH
3962ef2b01e07c02db339f34004445734a2dbdd80e1AJFISHLIST_ENTRY  BreakpointList;
3972ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH
3983402aac7d985bf8a9f9d3c639f3fe93609380513Ronald Cron/**
3992ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH Insert Single Step in the SystemContext
4003402aac7d985bf8a9f9d3c639f3fe93609380513Ronald Cron
40191c38d4e94c1461f5824b83d3722fe46626aa0d3Ronald Cron @param SystemContext  Register content at time of the exception
4022ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH **/
4032ef2b01e07c02db339f34004445734a2dbdd80e1AJFISHVOID
4042ef2b01e07c02db339f34004445734a2dbdd80e1AJFISHAddSingleStep (
4052ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  IN EFI_SYSTEM_CONTEXT SystemContext
4062ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  )
4072ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH{
4082ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  if (mSingleStepActive) {
4092ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH    // Currently don't support nesting
4102ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH    return;
4112ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  }
4122ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  mSingleStepActive = TRUE;
4133402aac7d985bf8a9f9d3c639f3fe93609380513Ronald Cron
4142ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  mSingleStepPC = SystemContext.SystemContextArm->PC;
4152ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH
4162ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  mSingleStepDataSize = sizeof (UINT32);
4173402aac7d985bf8a9f9d3c639f3fe93609380513Ronald Cron  mSingleStepData = (*(UINT32 *)mSingleStepPC);
4182ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  *(UINT32 *)mSingleStepPC = GDB_ARM_BKPT;
4192ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  if (*(UINT32 *)mSingleStepPC != GDB_ARM_BKPT) {
4202ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH    // For some reason our breakpoint did not take
4212ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH    mSingleStepActive = FALSE;
4222ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  }
4232ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH
4246f711615bacf7ce3bc42507cba87bc0adcda0461oliviermartin  InvalidateInstructionCacheRange ((VOID *)mSingleStepPC, mSingleStepDataSize);
4252ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  //DEBUG((EFI_D_ERROR, "AddSingleStep at 0x%08x (was: 0x%08x is:0x%08x)\n", SystemContext.SystemContextArm->PC, mSingleStepData, *(UINT32 *)mSingleStepPC));
4262ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH}
4272ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH
4283402aac7d985bf8a9f9d3c639f3fe93609380513Ronald Cron
4293402aac7d985bf8a9f9d3c639f3fe93609380513Ronald Cron/**
4302ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH Remove Single Step in the SystemContext
4313402aac7d985bf8a9f9d3c639f3fe93609380513Ronald Cron
43291c38d4e94c1461f5824b83d3722fe46626aa0d3Ronald Cron @param SystemContext  Register content at time of the exception
4332ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH **/
4342ef2b01e07c02db339f34004445734a2dbdd80e1AJFISHVOID
4352ef2b01e07c02db339f34004445734a2dbdd80e1AJFISHRemoveSingleStep (
4362ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  IN  EFI_SYSTEM_CONTEXT  SystemContext
4372ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  )
4382ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH{
4392ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  if (!mSingleStepActive) {
4402ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH    return;
4412ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  }
4423402aac7d985bf8a9f9d3c639f3fe93609380513Ronald Cron
4432ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  if (mSingleStepDataSize == sizeof (UINT16)) {
4442ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH    *(UINT16 *)mSingleStepPC = (UINT16)mSingleStepData;
4452ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  } else {
4462ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH    //DEBUG((EFI_D_ERROR, "RemoveSingleStep at 0x%08x (was: 0x%08x is:0x%08x)\n", SystemContext.SystemContextArm->PC, *(UINT32 *)mSingleStepPC, mSingleStepData));
4472ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH    *(UINT32 *)mSingleStepPC = mSingleStepData;
4482ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  }
4496f711615bacf7ce3bc42507cba87bc0adcda0461oliviermartin  InvalidateInstructionCacheRange ((VOID *)mSingleStepPC, mSingleStepDataSize);
4502ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  mSingleStepActive = FALSE;
4512ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH}
4522ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH
4532ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH
4542ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH
45511c20f4e06d252feaa65aa5e526686baf015762doliviermartin/**
4563402aac7d985bf8a9f9d3c639f3fe93609380513Ronald Cron Continue. addr is Address to resume. If addr is omitted, resume at current
4572ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH Address.
4583402aac7d985bf8a9f9d3c639f3fe93609380513Ronald Cron
4593402aac7d985bf8a9f9d3c639f3fe93609380513Ronald Cron @param   SystemContext     Register content at time of the exception
4602ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH **/
4612ef2b01e07c02db339f34004445734a2dbdd80e1AJFISHVOID
4622ef2b01e07c02db339f34004445734a2dbdd80e1AJFISHEFIAPI
4632ef2b01e07c02db339f34004445734a2dbdd80e1AJFISHContinueAtAddress (
4642ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  IN  EFI_SYSTEM_CONTEXT      SystemContext,
4652ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  IN    CHAR8                 *PacketData
4662ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  )
4672ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH{
4682ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  if (PacketData[1] != '\0') {
4696f711615bacf7ce3bc42507cba87bc0adcda0461oliviermartin    SystemContext.SystemContextArm->PC = AsciiStrHexToUintn (&PacketData[1]);
4703402aac7d985bf8a9f9d3c639f3fe93609380513Ronald Cron  }
4712ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH}
4722ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH
4732ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH
4742ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH/** ‘s [addr ]’
4753402aac7d985bf8a9f9d3c639f3fe93609380513Ronald Cron Single step. addr is the Address at which to resume. If addr is omitted, resume
4762ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH at same Address.
4773402aac7d985bf8a9f9d3c639f3fe93609380513Ronald Cron
4783402aac7d985bf8a9f9d3c639f3fe93609380513Ronald Cron @param   SystemContext     Register content at time of the exception
4792ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH **/
4802ef2b01e07c02db339f34004445734a2dbdd80e1AJFISHVOID
4812ef2b01e07c02db339f34004445734a2dbdd80e1AJFISHEFIAPI
4822ef2b01e07c02db339f34004445734a2dbdd80e1AJFISHSingleStep (
4832ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  IN  EFI_SYSTEM_CONTEXT      SystemContext,
4842ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  IN    CHAR8                       *PacketData
4852ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  )
4862ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH{
4876f711615bacf7ce3bc42507cba87bc0adcda0461oliviermartin  SendNotSupported ();
4882ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH}
4892ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH
4902ef2b01e07c02db339f34004445734a2dbdd80e1AJFISHUINTN
4912ef2b01e07c02db339f34004445734a2dbdd80e1AJFISHGetBreakpointDataAddress (
4922ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  IN  EFI_SYSTEM_CONTEXT  SystemContext,
4932ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  IN  UINTN               BreakpointNumber
4942ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  )
4952ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH{
4962ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  return 0;
4972ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH}
4982ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH
4992ef2b01e07c02db339f34004445734a2dbdd80e1AJFISHUINTN
5002ef2b01e07c02db339f34004445734a2dbdd80e1AJFISHGetBreakpointDetected (
5012ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  IN  EFI_SYSTEM_CONTEXT  SystemContext
5022ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  )
5032ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH{
5042ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  return 0;
5052ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH}
5062ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH
5072ef2b01e07c02db339f34004445734a2dbdd80e1AJFISHBREAK_TYPE
5082ef2b01e07c02db339f34004445734a2dbdd80e1AJFISHGetBreakpointType (
5092ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  IN  EFI_SYSTEM_CONTEXT  SystemContext,
5102ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  IN  UINTN               BreakpointNumber
5112ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  )
5122ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH{
5132ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  return NotSupported;
5142ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH}
5152ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH
5162ef2b01e07c02db339f34004445734a2dbdd80e1AJFISHARM_SOFTWARE_BREAKPOINT *
5172ef2b01e07c02db339f34004445734a2dbdd80e1AJFISHSearchBreakpointList (
5182ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  IN  UINT32  Address
5192ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  )
5202ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH{
5212ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  LIST_ENTRY              *Current;
5222ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  ARM_SOFTWARE_BREAKPOINT *Breakpoint;
5232ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH
5246f711615bacf7ce3bc42507cba87bc0adcda0461oliviermartin  Current = GetFirstNode (&BreakpointList);
5256f711615bacf7ce3bc42507cba87bc0adcda0461oliviermartin  while (!IsNull (&BreakpointList, Current)) {
5262ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH    Breakpoint = ARM_SOFTWARE_BREAKPOINT_FROM_LINK(Current);
5272ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH
5282ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH    if (Address == Breakpoint->Address) {
5292ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH      return Breakpoint;
5302ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH    }
5312ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH
5326f711615bacf7ce3bc42507cba87bc0adcda0461oliviermartin    Current = GetNextNode (&BreakpointList, Current);
5332ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  }
5342ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH
5352ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  return NULL;
5362ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH}
5372ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH
5382ef2b01e07c02db339f34004445734a2dbdd80e1AJFISHVOID
5392ef2b01e07c02db339f34004445734a2dbdd80e1AJFISHSetBreakpoint (
5402ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  IN UINT32 Address
5412ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  )
5422ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH{
5432ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  ARM_SOFTWARE_BREAKPOINT *Breakpoint;
5442ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH
5456f711615bacf7ce3bc42507cba87bc0adcda0461oliviermartin  Breakpoint = SearchBreakpointList (Address);
5462ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH
5472ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  if (Breakpoint != NULL) {
5482ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH    return;
5492ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  }
5502ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH
5512ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  // create and fill breakpoint structure
5526f711615bacf7ce3bc42507cba87bc0adcda0461oliviermartin  Breakpoint = AllocatePool (sizeof(ARM_SOFTWARE_BREAKPOINT));
5532ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH
5542ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  Breakpoint->Signature   = ARM_SOFTWARE_BREAKPOINT_SIGNATURE;
5552ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  Breakpoint->Address     = Address;
5562ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  Breakpoint->Instruction = *(UINT32 *)Address;
5573402aac7d985bf8a9f9d3c639f3fe93609380513Ronald Cron
5582ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  // Add it to the list
5596f711615bacf7ce3bc42507cba87bc0adcda0461oliviermartin  InsertTailList (&BreakpointList, &Breakpoint->Link);
5602ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH
5612ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  // Insert the software breakpoint
5622ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  *(UINT32 *)Address = GDB_ARM_BKPT;
5636f711615bacf7ce3bc42507cba87bc0adcda0461oliviermartin  InvalidateInstructionCacheRange ((VOID *)Address, 4);
5642ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH
5652ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  //DEBUG((EFI_D_ERROR, "SetBreakpoint at 0x%08x (was: 0x%08x is:0x%08x)\n", Address, Breakpoint->Instruction, *(UINT32 *)Address));
5662ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH}
5672ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH
5682ef2b01e07c02db339f34004445734a2dbdd80e1AJFISHVOID
5692ef2b01e07c02db339f34004445734a2dbdd80e1AJFISHClearBreakpoint (
5702ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  IN UINT32 Address
5712ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  )
5722ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH{
5732ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  ARM_SOFTWARE_BREAKPOINT *Breakpoint;
5742ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH
5756f711615bacf7ce3bc42507cba87bc0adcda0461oliviermartin  Breakpoint = SearchBreakpointList (Address);
5762ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH
5772ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  if (Breakpoint == NULL) {
5782ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH    return;
5792ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  }
5802ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH
5812ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  // Add it to the list
5826f711615bacf7ce3bc42507cba87bc0adcda0461oliviermartin  RemoveEntryList (&Breakpoint->Link);
5832ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH
5842ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  // Restore the original instruction
5852ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  *(UINT32 *)Address = Breakpoint->Instruction;
5866f711615bacf7ce3bc42507cba87bc0adcda0461oliviermartin  InvalidateInstructionCacheRange ((VOID *)Address, 4);
5872ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH
5882ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  //DEBUG((EFI_D_ERROR, "ClearBreakpoint at 0x%08x (was: 0x%08x is:0x%08x)\n", Address, GDB_ARM_BKPT, *(UINT32 *)Address));
5892ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH
5906f711615bacf7ce3bc42507cba87bc0adcda0461oliviermartin  FreePool (Breakpoint);
5912ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH}
5922ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH
5932ef2b01e07c02db339f34004445734a2dbdd80e1AJFISHVOID
5942ef2b01e07c02db339f34004445734a2dbdd80e1AJFISHEFIAPI
5952ef2b01e07c02db339f34004445734a2dbdd80e1AJFISHInsertBreakPoint (
5962ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  IN  EFI_SYSTEM_CONTEXT  SystemContext,
5972ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  IN  CHAR8              *PacketData
5982ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  )
5992ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH{
6002ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  UINTN Type;
6012ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  UINTN Address;
6022ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  UINTN Length;
6032ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  UINTN ErrorCode;
6042ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH
6056f711615bacf7ce3bc42507cba87bc0adcda0461oliviermartin  ErrorCode = ParseBreakpointPacket (PacketData, &Type, &Address, &Length);
6062ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  if (ErrorCode > 0) {
6072ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH    SendError ((UINT8)ErrorCode);
6082ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH    return;
6092ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  }
6102ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH
6112ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  switch (Type) {
6122ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH    case 0:   //Software breakpoint
6132ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH      break;
6142ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH
6152ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH    default  :
6162ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH      DEBUG((EFI_D_ERROR, "Insert breakpoint default: %x\n", Type));
6172ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH      SendError (GDB_EINVALIDBRKPOINTTYPE);
6182ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH      return;
6192ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  }
6202ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH
6216f711615bacf7ce3bc42507cba87bc0adcda0461oliviermartin  SetBreakpoint (Address);
6222ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH
6232ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  SendSuccess ();
6242ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH}
6252ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH
6262ef2b01e07c02db339f34004445734a2dbdd80e1AJFISHVOID
6272ef2b01e07c02db339f34004445734a2dbdd80e1AJFISHEFIAPI
6282ef2b01e07c02db339f34004445734a2dbdd80e1AJFISHRemoveBreakPoint (
6292ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  IN  EFI_SYSTEM_CONTEXT  SystemContext,
6302ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  IN  CHAR8               *PacketData
6312ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  )
6322ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH{
6332ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  UINTN      Type;
6342ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  UINTN      Address;
6352ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  UINTN      Length;
6362ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  UINTN      ErrorCode;
6372ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH
6382ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  //Parse breakpoint packet data
6392ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  ErrorCode = ParseBreakpointPacket (PacketData, &Type, &Address, &Length);
6402ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  if (ErrorCode > 0) {
6412ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH    SendError ((UINT8)ErrorCode);
6422ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH    return;
6432ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  }
6442ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH
6452ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  switch (Type) {
6462ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH    case 0:   //Software breakpoint
6472ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH      break;
6483402aac7d985bf8a9f9d3c639f3fe93609380513Ronald Cron
6492ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH    default:
6502ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH      SendError (GDB_EINVALIDBRKPOINTTYPE);
6512ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH      return;
6522ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  }
6532ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH
6546f711615bacf7ce3bc42507cba87bc0adcda0461oliviermartin  ClearBreakpoint (Address);
6552ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH
6562ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  SendSuccess ();
6572ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH}
6582ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH
6592ef2b01e07c02db339f34004445734a2dbdd80e1AJFISHVOID
6602ef2b01e07c02db339f34004445734a2dbdd80e1AJFISHInitializeProcessor (
6612ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  VOID
6622ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  )
6632ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH{
6642ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  // Initialize breakpoint list
6656f711615bacf7ce3bc42507cba87bc0adcda0461oliviermartin  InitializeListHead (&BreakpointList);
6662ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH}
6672ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH
6682ef2b01e07c02db339f34004445734a2dbdd80e1AJFISHBOOLEAN
6692ef2b01e07c02db339f34004445734a2dbdd80e1AJFISHValidateAddress (
6702ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  IN  VOID  *Address
6712ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  )
6722ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH{
6732ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  if ((UINT32)Address < 0x80000000) {
6742ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH    return FALSE;
6752ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  } else {
6762ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH    return TRUE;
6772ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  }
6782ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH}
6792ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH
6802ef2b01e07c02db339f34004445734a2dbdd80e1AJFISHBOOLEAN
6812ef2b01e07c02db339f34004445734a2dbdd80e1AJFISHValidateException (
6823402aac7d985bf8a9f9d3c639f3fe93609380513Ronald Cron  IN  EFI_EXCEPTION_TYPE    ExceptionType,
6833402aac7d985bf8a9f9d3c639f3fe93609380513Ronald Cron  IN OUT EFI_SYSTEM_CONTEXT SystemContext
6842ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  )
6852ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH{
6862ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  UINT32  ExceptionAddress;
6872ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  UINT32  Instruction;
6883402aac7d985bf8a9f9d3c639f3fe93609380513Ronald Cron
6892ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  // Is it a debugger SWI?
6902ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  ExceptionAddress = SystemContext.SystemContextArm->PC -= 4;
6912ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  Instruction      = *(UINT32 *)ExceptionAddress;
6922ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  if (Instruction != GDB_ARM_BKPT) {
6932ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH    return FALSE;
6942ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  }
6952ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH
6962ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  // Special for SWI-based exception handling.  SWI sets up the context
6972ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  // to return to the instruction following the SWI instruction - NOT what we want
6982ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  // for a debugger!
6992ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  SystemContext.SystemContextArm->PC = ExceptionAddress;
7002ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH
7012ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH  return TRUE;
7022ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH}
7032ef2b01e07c02db339f34004445734a2dbdd80e1AJFISH
704