]> git.proxmox.com Git - mirror_edk2.git/blame - EmbeddedPkg/Library/GdbDebugAgent/Arm/Processor.c
ArmPkg|EmbeddedPkg: make PcdCpuVectorBaseAddress 64 bits wide
[mirror_edk2.git] / EmbeddedPkg / Library / GdbDebugAgent / Arm / Processor.c
CommitLineData
969eba7b 1/** @file\r
2 Processor specific parts of the GDB stub\r
3\r
60274cca 4 Copyright (c) 2008 - 2010, Apple Inc. All rights reserved.<BR>\r
3402aac7 5\r
60274cca 6 This program and the accompanying materials\r
969eba7b 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
14**/\r
15\r
16\r
17#include <GdbDebugAgent.h>\r
969eba7b 18#include <Library/PrintLib.h>\r
19#include <Library/ArmLib.h>\r
20\r
21//\r
22// Externs from the exception handler assembly file\r
23//\r
24VOID\r
25ExceptionHandlersStart (\r
26 VOID\r
27 );\r
28\r
29VOID\r
30ExceptionHandlersEnd (\r
31 VOID\r
32 );\r
33\r
34VOID\r
35CommonExceptionEntry (\r
36 VOID\r
37 );\r
38\r
39VOID\r
40AsmCommonExceptionEntry (\r
41 VOID\r
42 );\r
43\r
44\r
45//\r
46// Array of exception types that need to be hooked by the debugger\r
47// (efi, gdb) //efi number\r
48//\r
49EFI_EXCEPTION_TYPE_ENTRY gExceptionType[] = {\r
50 { EXCEPT_ARM_SOFTWARE_INTERRUPT, GDB_SIGTRAP },\r
3402aac7
RC
51 { EXCEPT_ARM_UNDEFINED_INSTRUCTION, GDB_SIGTRAP },\r
52 { EXCEPT_ARM_PREFETCH_ABORT, GDB_SIGTRAP },\r
969eba7b 53 { EXCEPT_ARM_DATA_ABORT, GDB_SIGTRAP }, // GDB_SIGEMT\r
54 { EXCEPT_ARM_RESERVED, GDB_SIGTRAP }, // GDB_SIGILL\r
55 { EXCEPT_ARM_FIQ, GDB_SIGINT } // Used for ctrl-c\r
56};\r
57\r
58// Shut up some annoying RVCT warnings\r
59#ifdef __CC_ARM\r
60#pragma diag_suppress 1296\r
61#endif\r
62\r
63UINTN gRegisterOffsets[] = {\r
64 OFFSET_OF(EFI_SYSTEM_CONTEXT_ARM, R0),\r
65 OFFSET_OF(EFI_SYSTEM_CONTEXT_ARM, R1),\r
66 OFFSET_OF(EFI_SYSTEM_CONTEXT_ARM, R2),\r
67 OFFSET_OF(EFI_SYSTEM_CONTEXT_ARM, R3),\r
68 OFFSET_OF(EFI_SYSTEM_CONTEXT_ARM, R4),\r
69 OFFSET_OF(EFI_SYSTEM_CONTEXT_ARM, R5),\r
70 OFFSET_OF(EFI_SYSTEM_CONTEXT_ARM, R6),\r
71 OFFSET_OF(EFI_SYSTEM_CONTEXT_ARM, R7),\r
72 OFFSET_OF(EFI_SYSTEM_CONTEXT_ARM, R8),\r
73 OFFSET_OF(EFI_SYSTEM_CONTEXT_ARM, R9),\r
74 OFFSET_OF(EFI_SYSTEM_CONTEXT_ARM, R10),\r
75 OFFSET_OF(EFI_SYSTEM_CONTEXT_ARM, R11),\r
76 OFFSET_OF(EFI_SYSTEM_CONTEXT_ARM, R12),\r
77 OFFSET_OF(EFI_SYSTEM_CONTEXT_ARM, SP),\r
78 OFFSET_OF(EFI_SYSTEM_CONTEXT_ARM, LR),\r
79 OFFSET_OF(EFI_SYSTEM_CONTEXT_ARM, PC),\r
80 0x00000F01, // f0\r
81 0x00000F02,\r
82 0x00000F03,\r
83 0x00000F11, // f1\r
84 0x00000F12,\r
85 0x00000F13,\r
86 0x00000F21, // f2\r
87 0x00000F22,\r
88 0x00000F23,\r
89 0x00000F31, // f3\r
90 0x00000F32,\r
91 0x00000F33,\r
92 0x00000F41, // f4\r
93 0x00000F42,\r
94 0x00000F43,\r
95 0x00000F51, // f5\r
96 0x00000F52,\r
97 0x00000F53,\r
98 0x00000F61, // f6\r
99 0x00000F62,\r
100 0x00000F63,\r
101 0x00000F71, // f7\r
102 0x00000F72,\r
103 0x00000F73,\r
104 0x00000FFF, // fps\r
105 OFFSET_OF(EFI_SYSTEM_CONTEXT_ARM, CPSR)\r
106};\r
107\r
108// restore warnings for RVCT\r
109#ifdef __CC_ARM\r
110#pragma diag_default 1296\r
111#endif\r
112\r
113\r
114/**\r
115 Return the number of entries in the gExceptionType[]\r
3402aac7
RC
116\r
117 @retval UINTN, the number of entries in the gExceptionType[] array.\r
969eba7b 118 **/\r
119UINTN\r
120MaxEfiException (\r
121 VOID\r
122 )\r
123{\r
124 return sizeof (gExceptionType)/sizeof (EFI_EXCEPTION_TYPE_ENTRY);\r
125}\r
126\r
127\r
128\r
129\r
130/**\r
3402aac7 131 Check to see if the ISA is supported.\r
969eba7b 132 ISA = Instruction Set Architecture\r
133\r
3402aac7 134 @retval TRUE if Isa is supported\r
969eba7b 135\r
136**/\r
137BOOLEAN\r
138CheckIsa (\r
139 IN EFI_INSTRUCTION_SET_ARCHITECTURE Isa\r
140 )\r
141{\r
142 if (Isa == IsaArm) {\r
143 return TRUE;\r
144 } else {\r
145 return FALSE;\r
146 }\r
147}\r
148\r
149\r
150/**\r
151 This takes in the register number and the System Context, and returns a pointer to the RegNumber-th register in gdb ordering\r
152 It is, by default, set to find the register pointer of the ARM member\r
3402aac7 153 @param SystemContext Register content at time of the exception\r
969eba7b 154 @param RegNumber The register to which we want to find a pointer\r
155 @retval the pointer to the RegNumber-th pointer\r
3402aac7 156 **/\r
969eba7b 157UINTN *\r
158FindPointerToRegister(\r
159 IN EFI_SYSTEM_CONTEXT SystemContext,\r
3402aac7 160 IN UINTN RegNumber\r
969eba7b 161 )\r
162{\r
163 UINT8 *TempPtr;\r
164 ASSERT(gRegisterOffsets[RegNumber] < 0xF00);\r
165 TempPtr = ((UINT8 *)SystemContext.SystemContextArm) + gRegisterOffsets[RegNumber];\r
166 return (UINT32 *)TempPtr;\r
167}\r
168\r
169\r
170/**\r
171 Adds the RegNumber-th register's value to the output buffer, starting at the given OutBufPtr\r
172 @param SystemContext Register content at time of the exception\r
173 @param RegNumber the number of the register that we want to read\r
174 @param OutBufPtr pointer to the output buffer's end. the new data will be added from this point on.\r
175 @retval the pointer to the next character of the output buffer that is available to be written on.\r
176 **/\r
177CHAR8 *\r
178BasicReadRegister (\r
179 IN EFI_SYSTEM_CONTEXT SystemContext,\r
180 IN UINTN RegNumber,\r
181 IN CHAR8 *OutBufPtr\r
182 )\r
183{\r
184 UINTN RegSize;\r
185 CHAR8 Char;\r
3402aac7 186\r
969eba7b 187 if (gRegisterOffsets[RegNumber] > 0xF00) {\r
188 AsciiSPrint(OutBufPtr, 9, "00000000");\r
189 OutBufPtr += 8;\r
190 return OutBufPtr;\r
191 }\r
192\r
193 RegSize = 0;\r
194 while (RegSize < 32) {\r
195 Char = mHexToStr[(UINT8)((*FindPointerToRegister(SystemContext, RegNumber) >> (RegSize+4)) & 0xf)];\r
196 if ((Char >= 'A') && (Char <= 'F')) {\r
197 Char = Char - 'A' + 'a';\r
198 }\r
199 *OutBufPtr++ = Char;\r
3402aac7 200\r
969eba7b 201 Char = mHexToStr[(UINT8)((*FindPointerToRegister(SystemContext, RegNumber) >> RegSize) & 0xf)];\r
202 if ((Char >= 'A') && (Char <= 'F')) {\r
203 Char = Char - 'A' + 'a';\r
204 }\r
205 *OutBufPtr++ = Char;\r
3402aac7 206\r
969eba7b 207 RegSize = RegSize + 8;\r
208 }\r
209 return OutBufPtr;\r
210}\r
211\r
212\r
11c20f4e 213/**\r
3402aac7 214 Reads the n-th register's value into an output buffer and sends it as a packet\r
969eba7b 215 @param SystemContext Register content at time of the exception\r
216 @param InBuffer Pointer to the input buffer received from gdb server\r
217 **/\r
218VOID\r
219ReadNthRegister (\r
220 IN EFI_SYSTEM_CONTEXT SystemContext,\r
221 IN CHAR8 *InBuffer\r
222 )\r
223{\r
224 UINTN RegNumber;\r
225 CHAR8 OutBuffer[9]; // 1 reg=8 hex chars, and the end '\0' (escape seq)\r
226 CHAR8 *OutBufPtr; // pointer to the output buffer\r
3402aac7 227\r
969eba7b 228 RegNumber = AsciiStrHexToUintn (&InBuffer[1]);\r
3402aac7 229\r
969eba7b 230 if (RegNumber >= (sizeof (gRegisterOffsets)/sizeof (UINTN))) {\r
3402aac7 231 SendError (GDB_EINVALIDREGNUM);\r
969eba7b 232 return;\r
233 }\r
3402aac7 234\r
969eba7b 235 OutBufPtr = OutBuffer;\r
236 OutBufPtr = BasicReadRegister (SystemContext, RegNumber, OutBufPtr);\r
3402aac7 237\r
969eba7b 238 *OutBufPtr = '\0'; // the end of the buffer\r
239 SendPacket(OutBuffer);\r
240}\r
241\r
242\r
11c20f4e 243/**\r
3402aac7 244 Reads the general registers into an output buffer and sends it as a packet\r
969eba7b 245 @param SystemContext Register content at time of the exception\r
246 **/\r
247VOID\r
248EFIAPI\r
3402aac7 249ReadGeneralRegisters (\r
969eba7b 250 IN EFI_SYSTEM_CONTEXT SystemContext\r
251 )\r
252{\r
253 UINTN Index;\r
254 // a UINT32 takes 8 ascii characters\r
255 CHAR8 OutBuffer[(sizeof (gRegisterOffsets) * 2) + 1];\r
256 CHAR8 *OutBufPtr;\r
3402aac7 257\r
969eba7b 258 // It is not safe to allocate pool here....\r
259 OutBufPtr = OutBuffer;\r
260 for (Index = 0; Index < (sizeof (gRegisterOffsets)/sizeof (UINTN)); Index++) {\r
261 OutBufPtr = BasicReadRegister (SystemContext, Index, OutBufPtr);\r
262 }\r
3402aac7 263\r
969eba7b 264 *OutBufPtr = '\0';\r
265 SendPacket(OutBuffer);\r
266}\r
267\r
268\r
269/**\r
270 Adds the RegNumber-th register's value to the output buffer, starting at the given OutBufPtr\r
271 @param SystemContext Register content at time of the exception\r
272 @param RegNumber the number of the register that we want to write\r
273 @param InBufPtr pointer to the output buffer. the new data will be extracted from the input buffer from this point on.\r
274 @retval the pointer to the next character of the input buffer that can be used\r
275 **/\r
276CHAR8 *\r
277BasicWriteRegister (\r
278 IN EFI_SYSTEM_CONTEXT SystemContext,\r
279 IN UINTN RegNumber,\r
280 IN CHAR8 *InBufPtr\r
281 )\r
282{\r
283 UINTN RegSize;\r
284 UINTN TempValue; // the value transferred from a hex char\r
285 UINT32 NewValue; // the new value of the RegNumber-th Register\r
3402aac7 286\r
969eba7b 287 if (gRegisterOffsets[RegNumber] > 0xF00) {\r
288 return InBufPtr + 8;\r
289 }\r
290\r
291 NewValue = 0;\r
292 RegSize = 0;\r
293 while (RegSize < 32) {\r
294 TempValue = HexCharToInt(*InBufPtr++);\r
3402aac7 295\r
969eba7b 296 if ((INTN)TempValue < 0) {\r
3402aac7 297 SendError (GDB_EBADMEMDATA);\r
969eba7b 298 return NULL;\r
299 }\r
3402aac7 300\r
969eba7b 301 NewValue += (TempValue << (RegSize+4));\r
302 TempValue = HexCharToInt(*InBufPtr++);\r
3402aac7 303\r
969eba7b 304 if ((INTN)TempValue < 0) {\r
3402aac7 305 SendError (GDB_EBADMEMDATA);\r
969eba7b 306 return NULL;\r
307 }\r
3402aac7
RC
308\r
309 NewValue += (TempValue << RegSize);\r
969eba7b 310 RegSize = RegSize + 8;\r
311 }\r
312 *(FindPointerToRegister(SystemContext, RegNumber)) = NewValue;\r
313 return InBufPtr;\r
314}\r
315\r
316\r
317/** ‘P n...=r...’\r
318 Writes the new value of n-th register received into the input buffer to the n-th register\r
319 @param SystemContext Register content at time of the exception\r
320 @param InBuffer Ponter to the input buffer received from gdb server\r
321 **/\r
322VOID\r
323WriteNthRegister (\r
324 IN EFI_SYSTEM_CONTEXT SystemContext,\r
325 IN CHAR8 *InBuffer\r
326 )\r
327{\r
328 UINTN RegNumber;\r
329 CHAR8 RegNumBuffer[MAX_REG_NUM_BUF_SIZE]; // put the 'n..' part of the message into this array\r
330 CHAR8 *RegNumBufPtr;\r
331 CHAR8 *InBufPtr; // pointer to the input buffer\r
3402aac7 332\r
969eba7b 333 // find the register number to write\r
334 InBufPtr = &InBuffer[1];\r
335 RegNumBufPtr = RegNumBuffer;\r
336 while (*InBufPtr != '=') {\r
337 *RegNumBufPtr++ = *InBufPtr++;\r
3402aac7 338 }\r
969eba7b 339 *RegNumBufPtr = '\0';\r
3402aac7
RC
340 RegNumber = AsciiStrHexToUintn (RegNumBuffer);\r
341\r
969eba7b 342 // check if this is a valid Register Number\r
343 if (RegNumber >= (sizeof (gRegisterOffsets)/sizeof (UINTN))) {\r
3402aac7 344 SendError (GDB_EINVALIDREGNUM);\r
969eba7b 345 return;\r
346 }\r
347 InBufPtr++; // skips the '=' character\r
348 BasicWriteRegister (SystemContext, RegNumber, InBufPtr);\r
349 SendSuccess();\r
350}\r
351\r
352\r
353/** ‘G XX...’\r
354 Writes the new values received into the input buffer to the general registers\r
355 @param SystemContext Register content at time of the exception\r
356 @param InBuffer Pointer to the input buffer received from gdb server\r
357 **/\r
358\r
359VOID\r
360EFIAPI\r
361WriteGeneralRegisters (\r
362 IN EFI_SYSTEM_CONTEXT SystemContext,\r
363 IN CHAR8 *InBuffer\r
364 )\r
365{\r
366 UINTN i;\r
367 CHAR8 *InBufPtr; /// pointer to the input buffer\r
368 UINTN MinLength;\r
369 UINTN RegisterCount = (sizeof (gRegisterOffsets)/sizeof (UINTN));\r
370\r
371 MinLength = (RegisterCount * 8) + 1; // 'G' plus the registers in ASCII format\r
3402aac7 372\r
969eba7b 373 if (AsciiStrLen(InBuffer) < MinLength) {\r
3402aac7
RC
374 //Bad message. Message is not the right length\r
375 SendError (GDB_EBADBUFSIZE);\r
969eba7b 376 return;\r
377 }\r
3402aac7 378\r
969eba7b 379 InBufPtr = &InBuffer[1];\r
3402aac7 380\r
969eba7b 381 // Read the new values for the registers from the input buffer to an array, NewValueArray.\r
382 // The values in the array are in the gdb ordering\r
383 for(i = 0; i < RegisterCount; i++) {\r
384 InBufPtr = BasicWriteRegister (SystemContext, i, InBufPtr);\r
385 }\r
3402aac7 386\r
969eba7b 387 SendSuccess ();\r
388}\r
389\r
390\r
391\r
392\r
11c20f4e 393/**\r
3402aac7 394 Continue. addr is Address to resume. If addr is omitted, resume at current\r
969eba7b 395 Address.\r
3402aac7
RC
396\r
397 @param SystemContext Register content at time of the exception\r
969eba7b 398 **/\r
399VOID\r
400EFIAPI\r
401ContinueAtAddress (\r
402 IN EFI_SYSTEM_CONTEXT SystemContext,\r
403 IN CHAR8 *PacketData\r
404 )\r
405{\r
406 if (PacketData[1] != '\0') {\r
407 SystemContext.SystemContextArm->PC = AsciiStrHexToUintn(&PacketData[1]);\r
3402aac7 408 }\r
969eba7b 409}\r
410\r
411\r
412/** ‘s [addr ]’\r
3402aac7 413 Single step. addr is the Address at which to resume. If addr is omitted, resume\r
969eba7b 414 at same Address.\r
3402aac7
RC
415\r
416 @param SystemContext Register content at time of the exception\r
969eba7b 417 **/\r
418VOID\r
419EFIAPI\r
420SingleStep (\r
421 IN EFI_SYSTEM_CONTEXT SystemContext,\r
422 IN CHAR8 *PacketData\r
423 )\r
424{\r
425 SendNotSupported();\r
426}\r
427\r
428\r
429VOID\r
430EFIAPI\r
431InsertBreakPoint (\r
432 IN EFI_SYSTEM_CONTEXT SystemContext,\r
433 IN CHAR8 *PacketData\r
434 )\r
435{\r
436 SendNotSupported ();\r
437}\r
438\r
439VOID\r
440EFIAPI\r
441RemoveBreakPoint (\r
442 IN EFI_SYSTEM_CONTEXT SystemContext,\r
443 IN CHAR8 *PacketData\r
444 )\r
445{\r
446 SendNotSupported ();\r
447}\r
448\r
449\r
1e57a462 450/**\r
3402aac7 451 Send the T signal with the given exception type (in gdb order) and possibly\r
1e57a462 452 with n:r pairs related to the watchpoints\r
3402aac7 453\r
1e57a462 454 @param SystemContext Register content at time of the exception\r
455 @param GdbExceptionType GDB exception type\r
456 **/\r
457VOID\r
458ProcessorSendTSignal (\r
459 IN EFI_SYSTEM_CONTEXT SystemContext,\r
460 IN UINT8 GdbExceptionType,\r
461 IN OUT CHAR8 *TSignalPtr,\r
462 IN UINTN SizeOfBuffer\r
463 )\r
464{\r
465 *TSignalPtr = '\0';\r
466}\r
969eba7b 467\r
bb5127ae 468/**\r
469 FIQ state is only changed by FIQ exception. We don't want to take FIQ\r
3402aac7 470 ticks in the GDB stub. The stub disables FIQ on entry, but this is the\r
bb5127ae 471 third instruction that executes in the execption handler. Thus we have\r
472 a crack we need to test for.\r
473\r
474 @param PC PC of execption\r
475\r
3402aac7 476 @return TRUE We are in the GDB stub exception preamble\r
bb5127ae 477 @return FALSE We are not in GDB stub code\r
1e57a462 478 **/\r
479BOOLEAN\r
480InFiqCrack (\r
481 IN UINT32 PC\r
482 )\r
483{\r
f0bbcdf8 484 UINT64 VectorBase = PcdGet64 (PcdCpuVectorBaseAddress);\r
1e57a462 485 UINT32 Length = (UINTN)ExceptionHandlersEnd - (UINTN)ExceptionHandlersStart;\r
486\r
487 if ((PC >= VectorBase) && (PC <= (VectorBase + Length))) {\r
488 return TRUE;\r
489 }\r
490\r
491 return FALSE;\r
492}\r
bb5127ae 493\r
494\r
969eba7b 495/**\r
496 Check to see if this exception is related to ctrl-c handling.\r
497\r
3402aac7
RC
498 In this scheme we dedicate FIQ to the ctrl-c handler so it is\r
499 independent of the rest of the system.\r
500\r
501 SaveAndSetDebugTimerInterrupt () can be used to\r
969eba7b 502\r
503 @param ExceptionType Exception that is being processed\r
3402aac7 504 @param SystemContext Register content at time of the exception\r
969eba7b 505\r
506 @return TRUE This was a ctrl-c check that did not find a ctrl-c\r
507 @return FALSE This was not a ctrl-c check or some one hit ctrl-c\r
508 **/\r
509BOOLEAN\r
3402aac7
RC
510ProcessorControlC (\r
511 IN EFI_EXCEPTION_TYPE ExceptionType,\r
512 IN OUT EFI_SYSTEM_CONTEXT SystemContext\r
969eba7b 513 )\r
514{\r
bb5127ae 515 CHAR8 Char;\r
969eba7b 516 BOOLEAN Return = TRUE;\r
517\r
518 if (ExceptionType != EXCEPT_ARM_FIQ) {\r
519 // Skip it as it is not related to ctrl-c\r
520 return FALSE;\r
521 }\r
522\r
bb5127ae 523 if (InFiqCrack (SystemContext.SystemContextArm->PC)) {\r
524 // We are in our own interrupt preable, so skip this tick.\r
525 // We never want to let gdb see the debug stub running if we can help it\r
526 return FALSE;\r
527 }\r
528\r
1e57a462 529 while (TRUE) {\r
530 if (!GdbIsCharAvailable ()) {\r
531 //\r
532 // No characters are pending so exit the loop\r
533 //\r
534 Return = TRUE;\r
535 break;\r
536 }\r
3402aac7 537\r
1e57a462 538 Char = GdbGetChar ();\r
539 if (Char == 0x03) {\r
540 //\r
541 // We have a ctrl-c so exit and process exception for ctrl-c\r
542 //\r
543 Return = FALSE;\r
544 break;\r
545 }\r
546 }\r
969eba7b 547\r
548 DebugAgentTimerEndOfInterrupt ();\r
549\r
550 // Force an exit from the exception handler as we are done\r
551 return Return;\r
552}\r
553\r
554\r
555/**\r
556 Enable/Disable the interrupt of debug timer and return the interrupt state\r
557 prior to the operation.\r
558\r
559 If EnableStatus is TRUE, enable the interrupt of debug timer.\r
560 If EnableStatus is FALSE, disable the interrupt of debug timer.\r
561\r
562 @param[in] EnableStatus Enable/Disable.\r
563\r
bb5127ae 564 @retval TRUE Debug timer interrupt were enabled on entry to this call.\r
565 @retval FALSE Debug timer interrupt were disabled on entry to this call.\r
969eba7b 566\r
567**/\r
568BOOLEAN\r
569EFIAPI\r
570SaveAndSetDebugTimerInterrupt (\r
571 IN BOOLEAN EnableStatus\r
572 )\r
573{\r
574 BOOLEAN FiqEnabled;\r
575\r
576 FiqEnabled = ArmGetFiqState ();\r
577\r
578 if (EnableStatus) {\r
bb5127ae 579 DebugAgentTimerSetPeriod (PcdGet32 (PcdGdbTimerPeriodMilliseconds));\r
969eba7b 580 ArmEnableFiq ();\r
581 } else {\r
582 DebugAgentTimerSetPeriod (0);\r
583 ArmDisableFiq ();\r
584 }\r
585\r
586 return FiqEnabled;\r
587}\r
588\r
bb5127ae 589\r
590\r
969eba7b 591VOID\r
592GdbFPutString (\r
593 IN CHAR8 *String\r
594 );\r
595\r
596/**\r
597 Initialize debug agent.\r
598\r
685f8c76 599 This function is used to set up debug environment to support source level debugging.\r
600 If certain Debug Agent Library instance has to save some private data in the stack,\r
601 this function must work on the mode that doesn't return to the caller, then\r
602 the caller needs to wrap up all rest of logic after InitializeDebugAgent() into one\r
603 function and pass it into InitializeDebugAgent(). InitializeDebugAgent() is\r
604 responsible to invoke the passing-in function at the end of InitializeDebugAgent().\r
969eba7b 605\r
685f8c76 606 If the parameter Function is not NULL, Debug Agent Libary instance will invoke it by\r
607 passing in the Context to be its parameter.\r
608\r
609 If Function() is NULL, Debug Agent Library instance will return after setup debug\r
610 environment.\r
611\r
612 @param[in] InitFlag Init flag is used to decide the initialize process.\r
613 @param[in] Context Context needed according to InitFlag; it was optional.\r
614 @param[in] Function Continue function called by debug agent library; it was\r
615 optional.\r
969eba7b 616\r
617**/\r
618VOID\r
619EFIAPI\r
620InitializeDebugAgent (\r
621 IN UINT32 InitFlag,\r
685f8c76 622 IN VOID *Context, OPTIONAL\r
623 IN DEBUG_AGENT_CONTINUE Function OPTIONAL\r
969eba7b 624 )\r
3402aac7 625{\r
969eba7b 626 UINTN Offset;\r
627 UINTN Length;\r
628 BOOLEAN IrqEnabled;\r
f0bbcdf8 629 UINT64 *VectorBase;\r
969eba7b 630\r
1e57a462 631\r
969eba7b 632 //\r
633 // Disable interrupts\r
634 //\r
635 IrqEnabled = ArmGetInterruptState ();\r
636 ArmDisableInterrupts ();\r
969eba7b 637 ArmDisableFiq ();\r
638\r
639 //\r
640 // Copy an implementation of the ARM exception vectors to PcdCpuVectorBaseAddress.\r
641 //\r
642 Length = (UINTN)ExceptionHandlersEnd - (UINTN)ExceptionHandlersStart;\r
643\r
644 //\r
645 // Reserve space for the exception handlers\r
646 //\r
f0bbcdf8 647 VectorBase = (UINT64 *)(UINTN)PcdGet64 (PcdCpuVectorBaseAddress);\r
969eba7b 648\r
649\r
3402aac7 650 // Copy our assembly code into the page that contains the exception vectors.\r
969eba7b 651 CopyMem ((VOID *)VectorBase, (VOID *)ExceptionHandlersStart, Length);\r
652\r
653 //\r
654 // Patch in the common Assembly exception handler\r
655 //\r
656 Offset = (UINTN)CommonExceptionEntry - (UINTN)ExceptionHandlersStart;\r
657 *(UINTN *) (((UINT8 *)VectorBase) + Offset) = (UINTN)AsmCommonExceptionEntry;\r
658\r
659 // Flush Caches since we updated executable stuff\r
f0bbcdf8 660 InvalidateInstructionCacheRange ((VOID *)PcdGet64(PcdCpuVectorBaseAddress), Length);\r
969eba7b 661\r
bb5127ae 662 // setup a timer so gdb can break in via ctrl-c\r
969eba7b 663 DebugAgentTimerIntialize ();\r
664\r
969eba7b 665 if (IrqEnabled) {\r
666 ArmEnableInterrupts ();\r
667 }\r
668\r
685f8c76 669 if (Function != NULL) {\r
670 Function (Context);\r
671 }\r
672\r
969eba7b 673 return;\r
674}\r
675\r