Processor.c 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692
  1. /** @file
  2. Processor specific parts of the GDB stub
  3. Copyright (c) 2008 - 2009, Apple Inc. All rights reserved.<BR>
  4. SPDX-License-Identifier: BSD-2-Clause-Patent
  5. **/
  6. #include <GdbStubInternal.h>
  7. #include <Library/CacheMaintenanceLib.h>
  8. #include <Library/PrintLib.h>
  9. //
  10. // Array of exception types that need to be hooked by the debugger
  11. // (efi, gdb) //efi number
  12. //
  13. EFI_EXCEPTION_TYPE_ENTRY gExceptionType[] = {
  14. { EXCEPT_ARM_SOFTWARE_INTERRUPT, GDB_SIGTRAP }
  15. // { EXCEPT_ARM_UNDEFINED_INSTRUCTION, GDB_SIGTRAP },
  16. // { EXCEPT_ARM_PREFETCH_ABORT, GDB_SIGTRAP },
  17. // { EXCEPT_ARM_DATA_ABORT, GDB_SIGEMT },
  18. // { EXCEPT_ARM_RESERVED, GDB_SIGILL }
  19. };
  20. // Shut up some annoying RVCT warnings
  21. #ifdef __CC_ARM
  22. #pragma diag_suppress 1296
  23. #endif
  24. UINTN gRegisterOffsets[] = {
  25. OFFSET_OF (EFI_SYSTEM_CONTEXT_ARM, R0),
  26. OFFSET_OF (EFI_SYSTEM_CONTEXT_ARM, R1),
  27. OFFSET_OF (EFI_SYSTEM_CONTEXT_ARM, R2),
  28. OFFSET_OF (EFI_SYSTEM_CONTEXT_ARM, R3),
  29. OFFSET_OF (EFI_SYSTEM_CONTEXT_ARM, R4),
  30. OFFSET_OF (EFI_SYSTEM_CONTEXT_ARM, R5),
  31. OFFSET_OF (EFI_SYSTEM_CONTEXT_ARM, R6),
  32. OFFSET_OF (EFI_SYSTEM_CONTEXT_ARM, R7),
  33. OFFSET_OF (EFI_SYSTEM_CONTEXT_ARM, R8),
  34. OFFSET_OF (EFI_SYSTEM_CONTEXT_ARM, R9),
  35. OFFSET_OF (EFI_SYSTEM_CONTEXT_ARM, R10),
  36. OFFSET_OF (EFI_SYSTEM_CONTEXT_ARM, R11),
  37. OFFSET_OF (EFI_SYSTEM_CONTEXT_ARM, R12),
  38. OFFSET_OF (EFI_SYSTEM_CONTEXT_ARM, SP),
  39. OFFSET_OF (EFI_SYSTEM_CONTEXT_ARM, LR),
  40. OFFSET_OF (EFI_SYSTEM_CONTEXT_ARM, PC),
  41. 0x00000F01, // f0
  42. 0x00000F02,
  43. 0x00000F03,
  44. 0x00000F11, // f1
  45. 0x00000F12,
  46. 0x00000F13,
  47. 0x00000F21, // f2
  48. 0x00000F22,
  49. 0x00000F23,
  50. 0x00000F31, // f3
  51. 0x00000F32,
  52. 0x00000F33,
  53. 0x00000F41, // f4
  54. 0x00000F42,
  55. 0x00000F43,
  56. 0x00000F51, // f5
  57. 0x00000F52,
  58. 0x00000F53,
  59. 0x00000F61, // f6
  60. 0x00000F62,
  61. 0x00000F63,
  62. 0x00000F71, // f7
  63. 0x00000F72,
  64. 0x00000F73,
  65. 0x00000FFF, // fps
  66. OFFSET_OF (EFI_SYSTEM_CONTEXT_ARM, CPSR)
  67. };
  68. // restore warnings for RVCT
  69. #ifdef __CC_ARM
  70. #pragma diag_default 1296
  71. #endif
  72. /**
  73. Return the number of entries in the gExceptionType[]
  74. @retval UINTN, the number of entries in the gExceptionType[] array.
  75. **/
  76. UINTN
  77. MaxEfiException (
  78. VOID
  79. )
  80. {
  81. return sizeof (gExceptionType) / sizeof (EFI_EXCEPTION_TYPE_ENTRY);
  82. }
  83. /**
  84. Return the number of entries in the gRegisters[]
  85. @retval UINTN, the number of entries (registers) in the gRegisters[] array.
  86. **/
  87. UINTN
  88. MaxRegisterCount (
  89. VOID
  90. )
  91. {
  92. return sizeof (gRegisterOffsets) / sizeof (UINTN);
  93. }
  94. /**
  95. Check to see if the ISA is supported.
  96. ISA = Instruction Set Architecture
  97. @retval TRUE if Isa is supported
  98. **/
  99. BOOLEAN
  100. CheckIsa (
  101. IN EFI_INSTRUCTION_SET_ARCHITECTURE Isa
  102. )
  103. {
  104. if (Isa == IsaArm) {
  105. return TRUE;
  106. } else {
  107. return FALSE;
  108. }
  109. }
  110. /**
  111. This takes in the register number and the System Context, and returns a pointer to the RegNumber-th register in gdb ordering
  112. It is, by default, set to find the register pointer of the ARM member
  113. @param SystemContext Register content at time of the exception
  114. @param RegNumber The register to which we want to find a pointer
  115. @retval the pointer to the RegNumber-th pointer
  116. **/
  117. UINTN *
  118. FindPointerToRegister (
  119. IN EFI_SYSTEM_CONTEXT SystemContext,
  120. IN UINTN RegNumber
  121. )
  122. {
  123. UINT8 *TempPtr;
  124. ASSERT (gRegisterOffsets[RegNumber] < 0xF00);
  125. TempPtr = ((UINT8 *)SystemContext.SystemContextArm) + gRegisterOffsets[RegNumber];
  126. return (UINT32 *)TempPtr;
  127. }
  128. /**
  129. Adds the RegNumber-th register's value to the output buffer, starting at the given OutBufPtr
  130. @param SystemContext Register content at time of the exception
  131. @param RegNumber the number of the register that we want to read
  132. @param OutBufPtr pointer to the output buffer's end. the new data will be added from this point on.
  133. @retval the pointer to the next character of the output buffer that is available to be written on.
  134. **/
  135. CHAR8 *
  136. BasicReadRegister (
  137. IN EFI_SYSTEM_CONTEXT SystemContext,
  138. IN UINTN RegNumber,
  139. IN CHAR8 *OutBufPtr
  140. )
  141. {
  142. UINTN RegSize;
  143. CHAR8 Char;
  144. if (gRegisterOffsets[RegNumber] > 0xF00) {
  145. AsciiSPrint (OutBufPtr, 9, "00000000");
  146. OutBufPtr += 8;
  147. return OutBufPtr;
  148. }
  149. RegSize = 0;
  150. while (RegSize < 32) {
  151. Char = mHexToStr[(UINT8)((*FindPointerToRegister (SystemContext, RegNumber) >> (RegSize+4)) & 0xf)];
  152. if ((Char >= 'A') && (Char <= 'F')) {
  153. Char = Char - 'A' + 'a';
  154. }
  155. *OutBufPtr++ = Char;
  156. Char = mHexToStr[(UINT8)((*FindPointerToRegister (SystemContext, RegNumber) >> RegSize) & 0xf)];
  157. if ((Char >= 'A') && (Char <= 'F')) {
  158. Char = Char - 'A' + 'a';
  159. }
  160. *OutBufPtr++ = Char;
  161. RegSize = RegSize + 8;
  162. }
  163. return OutBufPtr;
  164. }
  165. /**
  166. Reads the n-th register's value into an output buffer and sends it as a packet
  167. @param SystemContext Register content at time of the exception
  168. @param InBuffer Pointer to the input buffer received from gdb server
  169. **/
  170. VOID
  171. ReadNthRegister (
  172. IN EFI_SYSTEM_CONTEXT SystemContext,
  173. IN CHAR8 *InBuffer
  174. )
  175. {
  176. UINTN RegNumber;
  177. CHAR8 OutBuffer[9]; // 1 reg=8 hex chars, and the end '\0' (escape seq)
  178. CHAR8 *OutBufPtr; // pointer to the output buffer
  179. RegNumber = AsciiStrHexToUintn (&InBuffer[1]);
  180. if (RegNumber >= MaxRegisterCount ()) {
  181. SendError (GDB_EINVALIDREGNUM);
  182. return;
  183. }
  184. OutBufPtr = OutBuffer;
  185. OutBufPtr = BasicReadRegister (SystemContext, RegNumber, OutBufPtr);
  186. *OutBufPtr = '\0'; // the end of the buffer
  187. SendPacket (OutBuffer);
  188. }
  189. /**
  190. Reads the general registers into an output buffer and sends it as a packet
  191. @param SystemContext Register content at time of the exception
  192. **/
  193. VOID
  194. EFIAPI
  195. ReadGeneralRegisters (
  196. IN EFI_SYSTEM_CONTEXT SystemContext
  197. )
  198. {
  199. UINTN Index;
  200. CHAR8 *OutBuffer;
  201. CHAR8 *OutBufPtr;
  202. UINTN RegisterCount = MaxRegisterCount ();
  203. // It is not safe to allocate pool here....
  204. OutBuffer = AllocatePool ((RegisterCount * 8) + 1); // 8 bytes per register in string format plus a null to terminate
  205. OutBufPtr = OutBuffer;
  206. for (Index = 0; Index < RegisterCount; Index++) {
  207. OutBufPtr = BasicReadRegister (SystemContext, Index, OutBufPtr);
  208. }
  209. *OutBufPtr = '\0';
  210. SendPacket (OutBuffer);
  211. FreePool (OutBuffer);
  212. }
  213. /**
  214. Adds the RegNumber-th register's value to the output buffer, starting at the given OutBufPtr
  215. @param SystemContext Register content at time of the exception
  216. @param RegNumber the number of the register that we want to write
  217. @param InBufPtr pointer to the output buffer. the new data will be extracted from the input buffer from this point on.
  218. @retval the pointer to the next character of the input buffer that can be used
  219. **/
  220. CHAR8
  221. *
  222. BasicWriteRegister (
  223. IN EFI_SYSTEM_CONTEXT SystemContext,
  224. IN UINTN RegNumber,
  225. IN CHAR8 *InBufPtr
  226. )
  227. {
  228. UINTN RegSize;
  229. UINTN TempValue; // the value transferred from a hex char
  230. UINT32 NewValue; // the new value of the RegNumber-th Register
  231. if (gRegisterOffsets[RegNumber] > 0xF00) {
  232. return InBufPtr + 8;
  233. }
  234. NewValue = 0;
  235. RegSize = 0;
  236. while (RegSize < 32) {
  237. TempValue = HexCharToInt (*InBufPtr++);
  238. if ((INTN)TempValue < 0) {
  239. SendError (GDB_EBADMEMDATA);
  240. return NULL;
  241. }
  242. NewValue += (TempValue << (RegSize+4));
  243. TempValue = HexCharToInt (*InBufPtr++);
  244. if ((INTN)TempValue < 0) {
  245. SendError (GDB_EBADMEMDATA);
  246. return NULL;
  247. }
  248. NewValue += (TempValue << RegSize);
  249. RegSize = RegSize + 8;
  250. }
  251. *(FindPointerToRegister (SystemContext, RegNumber)) = NewValue;
  252. return InBufPtr;
  253. }
  254. /** ‘P n...=r...’
  255. Writes the new value of n-th register received into the input buffer to the n-th register
  256. @param SystemContext Register content at time of the exception
  257. @param InBuffer Pointer to the input buffer received from gdb server
  258. **/
  259. VOID
  260. WriteNthRegister (
  261. IN EFI_SYSTEM_CONTEXT SystemContext,
  262. IN CHAR8 *InBuffer
  263. )
  264. {
  265. UINTN RegNumber;
  266. CHAR8 RegNumBuffer[MAX_REG_NUM_BUF_SIZE]; // put the 'n..' part of the message into this array
  267. CHAR8 *RegNumBufPtr;
  268. CHAR8 *InBufPtr; // pointer to the input buffer
  269. // find the register number to write
  270. InBufPtr = &InBuffer[1];
  271. RegNumBufPtr = RegNumBuffer;
  272. while (*InBufPtr != '=') {
  273. *RegNumBufPtr++ = *InBufPtr++;
  274. }
  275. *RegNumBufPtr = '\0';
  276. RegNumber = AsciiStrHexToUintn (RegNumBuffer);
  277. // check if this is a valid Register Number
  278. if (RegNumber >= MaxRegisterCount ()) {
  279. SendError (GDB_EINVALIDREGNUM);
  280. return;
  281. }
  282. InBufPtr++; // skips the '=' character
  283. BasicWriteRegister (SystemContext, RegNumber, InBufPtr);
  284. SendSuccess ();
  285. }
  286. /** ‘G XX...’
  287. Writes the new values received into the input buffer to the general registers
  288. @param SystemContext Register content at time of the exception
  289. @param InBuffer Pointer to the input buffer received from gdb server
  290. **/
  291. VOID
  292. EFIAPI
  293. WriteGeneralRegisters (
  294. IN EFI_SYSTEM_CONTEXT SystemContext,
  295. IN CHAR8 *InBuffer
  296. )
  297. {
  298. UINTN i;
  299. CHAR8 *InBufPtr; /// pointer to the input buffer
  300. UINTN MinLength;
  301. UINTN RegisterCount = MaxRegisterCount ();
  302. MinLength = (RegisterCount * 8) + 1; // 'G' plus the registers in ASCII format
  303. if (AsciiStrLen (InBuffer) < MinLength) {
  304. // Bad message. Message is not the right length
  305. SendError (GDB_EBADBUFSIZE);
  306. return;
  307. }
  308. InBufPtr = &InBuffer[1];
  309. // Read the new values for the registers from the input buffer to an array, NewValueArray.
  310. // The values in the array are in the gdb ordering
  311. for (i = 0; i < RegisterCount; i++) {
  312. InBufPtr = BasicWriteRegister (SystemContext, i, InBufPtr);
  313. }
  314. SendSuccess ();
  315. }
  316. // What about Thumb?
  317. // Use SWI 0xdbdbdb as the debug instruction
  318. #define GDB_ARM_BKPT 0xefdbdbdb
  319. BOOLEAN mSingleStepActive = FALSE;
  320. UINT32 mSingleStepPC;
  321. UINT32 mSingleStepData;
  322. UINTN mSingleStepDataSize;
  323. typedef struct {
  324. LIST_ENTRY Link;
  325. UINT64 Signature;
  326. UINT32 Address;
  327. UINT32 Instruction;
  328. } ARM_SOFTWARE_BREAKPOINT;
  329. #define ARM_SOFTWARE_BREAKPOINT_SIGNATURE SIGNATURE_64('A', 'R', 'M', 'B', 'R', 'K', 'P', 'T')
  330. #define ARM_SOFTWARE_BREAKPOINT_FROM_LINK(a) CR(a, ARM_SOFTWARE_BREAKPOINT, Link, ARM_SOFTWARE_BREAKPOINT_SIGNATURE)
  331. LIST_ENTRY BreakpointList;
  332. /**
  333. Insert Single Step in the SystemContext
  334. @param SystemContext Register content at time of the exception
  335. **/
  336. VOID
  337. AddSingleStep (
  338. IN EFI_SYSTEM_CONTEXT SystemContext
  339. )
  340. {
  341. if (mSingleStepActive) {
  342. // Currently don't support nesting
  343. return;
  344. }
  345. mSingleStepActive = TRUE;
  346. mSingleStepPC = SystemContext.SystemContextArm->PC;
  347. mSingleStepDataSize = sizeof (UINT32);
  348. mSingleStepData = (*(UINT32 *)mSingleStepPC);
  349. *(UINT32 *)mSingleStepPC = GDB_ARM_BKPT;
  350. if (*(UINT32 *)mSingleStepPC != GDB_ARM_BKPT) {
  351. // For some reason our breakpoint did not take
  352. mSingleStepActive = FALSE;
  353. }
  354. InvalidateInstructionCacheRange ((VOID *)mSingleStepPC, mSingleStepDataSize);
  355. // DEBUG((DEBUG_ERROR, "AddSingleStep at 0x%08x (was: 0x%08x is:0x%08x)\n", SystemContext.SystemContextArm->PC, mSingleStepData, *(UINT32 *)mSingleStepPC));
  356. }
  357. /**
  358. Remove Single Step in the SystemContext
  359. @param SystemContext Register content at time of the exception
  360. **/
  361. VOID
  362. RemoveSingleStep (
  363. IN EFI_SYSTEM_CONTEXT SystemContext
  364. )
  365. {
  366. if (!mSingleStepActive) {
  367. return;
  368. }
  369. if (mSingleStepDataSize == sizeof (UINT16)) {
  370. *(UINT16 *)mSingleStepPC = (UINT16)mSingleStepData;
  371. } else {
  372. // DEBUG((DEBUG_ERROR, "RemoveSingleStep at 0x%08x (was: 0x%08x is:0x%08x)\n", SystemContext.SystemContextArm->PC, *(UINT32 *)mSingleStepPC, mSingleStepData));
  373. *(UINT32 *)mSingleStepPC = mSingleStepData;
  374. }
  375. InvalidateInstructionCacheRange ((VOID *)mSingleStepPC, mSingleStepDataSize);
  376. mSingleStepActive = FALSE;
  377. }
  378. /**
  379. Continue. addr is Address to resume. If addr is omitted, resume at current
  380. Address.
  381. @param SystemContext Register content at time of the exception
  382. **/
  383. VOID
  384. EFIAPI
  385. ContinueAtAddress (
  386. IN EFI_SYSTEM_CONTEXT SystemContext,
  387. IN CHAR8 *PacketData
  388. )
  389. {
  390. if (PacketData[1] != '\0') {
  391. SystemContext.SystemContextArm->PC = AsciiStrHexToUintn (&PacketData[1]);
  392. }
  393. }
  394. /** ‘s [addr ]’
  395. Single step. addr is the Address at which to resume. If addr is omitted, resume
  396. at same Address.
  397. @param SystemContext Register content at time of the exception
  398. **/
  399. VOID
  400. EFIAPI
  401. SingleStep (
  402. IN EFI_SYSTEM_CONTEXT SystemContext,
  403. IN CHAR8 *PacketData
  404. )
  405. {
  406. SendNotSupported ();
  407. }
  408. UINTN
  409. GetBreakpointDataAddress (
  410. IN EFI_SYSTEM_CONTEXT SystemContext,
  411. IN UINTN BreakpointNumber
  412. )
  413. {
  414. return 0;
  415. }
  416. UINTN
  417. GetBreakpointDetected (
  418. IN EFI_SYSTEM_CONTEXT SystemContext
  419. )
  420. {
  421. return 0;
  422. }
  423. BREAK_TYPE
  424. GetBreakpointType (
  425. IN EFI_SYSTEM_CONTEXT SystemContext,
  426. IN UINTN BreakpointNumber
  427. )
  428. {
  429. return NotSupported;
  430. }
  431. ARM_SOFTWARE_BREAKPOINT *
  432. SearchBreakpointList (
  433. IN UINT32 Address
  434. )
  435. {
  436. LIST_ENTRY *Current;
  437. ARM_SOFTWARE_BREAKPOINT *Breakpoint;
  438. Current = GetFirstNode (&BreakpointList);
  439. while (!IsNull (&BreakpointList, Current)) {
  440. Breakpoint = ARM_SOFTWARE_BREAKPOINT_FROM_LINK (Current);
  441. if (Address == Breakpoint->Address) {
  442. return Breakpoint;
  443. }
  444. Current = GetNextNode (&BreakpointList, Current);
  445. }
  446. return NULL;
  447. }
  448. VOID
  449. SetBreakpoint (
  450. IN UINT32 Address
  451. )
  452. {
  453. ARM_SOFTWARE_BREAKPOINT *Breakpoint;
  454. Breakpoint = SearchBreakpointList (Address);
  455. if (Breakpoint != NULL) {
  456. return;
  457. }
  458. // create and fill breakpoint structure
  459. Breakpoint = AllocatePool (sizeof (ARM_SOFTWARE_BREAKPOINT));
  460. Breakpoint->Signature = ARM_SOFTWARE_BREAKPOINT_SIGNATURE;
  461. Breakpoint->Address = Address;
  462. Breakpoint->Instruction = *(UINT32 *)Address;
  463. // Add it to the list
  464. InsertTailList (&BreakpointList, &Breakpoint->Link);
  465. // Insert the software breakpoint
  466. *(UINT32 *)Address = GDB_ARM_BKPT;
  467. InvalidateInstructionCacheRange ((VOID *)Address, 4);
  468. // DEBUG((DEBUG_ERROR, "SetBreakpoint at 0x%08x (was: 0x%08x is:0x%08x)\n", Address, Breakpoint->Instruction, *(UINT32 *)Address));
  469. }
  470. VOID
  471. ClearBreakpoint (
  472. IN UINT32 Address
  473. )
  474. {
  475. ARM_SOFTWARE_BREAKPOINT *Breakpoint;
  476. Breakpoint = SearchBreakpointList (Address);
  477. if (Breakpoint == NULL) {
  478. return;
  479. }
  480. // Add it to the list
  481. RemoveEntryList (&Breakpoint->Link);
  482. // Restore the original instruction
  483. *(UINT32 *)Address = Breakpoint->Instruction;
  484. InvalidateInstructionCacheRange ((VOID *)Address, 4);
  485. // DEBUG((DEBUG_ERROR, "ClearBreakpoint at 0x%08x (was: 0x%08x is:0x%08x)\n", Address, GDB_ARM_BKPT, *(UINT32 *)Address));
  486. FreePool (Breakpoint);
  487. }
  488. VOID
  489. EFIAPI
  490. InsertBreakPoint (
  491. IN EFI_SYSTEM_CONTEXT SystemContext,
  492. IN CHAR8 *PacketData
  493. )
  494. {
  495. UINTN Type;
  496. UINTN Address;
  497. UINTN Length;
  498. UINTN ErrorCode;
  499. ErrorCode = ParseBreakpointPacket (PacketData, &Type, &Address, &Length);
  500. if (ErrorCode > 0) {
  501. SendError ((UINT8)ErrorCode);
  502. return;
  503. }
  504. switch (Type) {
  505. case 0: // Software breakpoint
  506. break;
  507. default:
  508. DEBUG ((DEBUG_ERROR, "Insert breakpoint default: %x\n", Type));
  509. SendError (GDB_EINVALIDBRKPOINTTYPE);
  510. return;
  511. }
  512. SetBreakpoint (Address);
  513. SendSuccess ();
  514. }
  515. VOID
  516. EFIAPI
  517. RemoveBreakPoint (
  518. IN EFI_SYSTEM_CONTEXT SystemContext,
  519. IN CHAR8 *PacketData
  520. )
  521. {
  522. UINTN Type;
  523. UINTN Address;
  524. UINTN Length;
  525. UINTN ErrorCode;
  526. // Parse breakpoint packet data
  527. ErrorCode = ParseBreakpointPacket (PacketData, &Type, &Address, &Length);
  528. if (ErrorCode > 0) {
  529. SendError ((UINT8)ErrorCode);
  530. return;
  531. }
  532. switch (Type) {
  533. case 0: // Software breakpoint
  534. break;
  535. default:
  536. SendError (GDB_EINVALIDBRKPOINTTYPE);
  537. return;
  538. }
  539. ClearBreakpoint (Address);
  540. SendSuccess ();
  541. }
  542. VOID
  543. InitializeProcessor (
  544. VOID
  545. )
  546. {
  547. // Initialize breakpoint list
  548. InitializeListHead (&BreakpointList);
  549. }
  550. BOOLEAN
  551. ValidateAddress (
  552. IN VOID *Address
  553. )
  554. {
  555. if ((UINT32)Address < 0x80000000) {
  556. return FALSE;
  557. } else {
  558. return TRUE;
  559. }
  560. }
  561. BOOLEAN
  562. ValidateException (
  563. IN EFI_EXCEPTION_TYPE ExceptionType,
  564. IN OUT EFI_SYSTEM_CONTEXT SystemContext
  565. )
  566. {
  567. UINT32 ExceptionAddress;
  568. UINT32 Instruction;
  569. // Is it a debugger SWI?
  570. ExceptionAddress = SystemContext.SystemContextArm->PC -= 4;
  571. Instruction = *(UINT32 *)ExceptionAddress;
  572. if (Instruction != GDB_ARM_BKPT) {
  573. return FALSE;
  574. }
  575. // Special for SWI-based exception handling. SWI sets up the context
  576. // to return to the instruction following the SWI instruction - NOT what we want
  577. // for a debugger!
  578. SystemContext.SystemContextArm->PC = ExceptionAddress;
  579. return TRUE;
  580. }