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