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