]> git.proxmox.com Git - mirror_edk2.git/blame - EmbeddedPkg/Library/GdbDebugAgent/GdbDebugAgent.c
Arm Packages: Fixed coding style/Line endings to follow EDK2 coding convention
[mirror_edk2.git] / EmbeddedPkg / Library / GdbDebugAgent / GdbDebugAgent.c
CommitLineData
969eba7b 1/** @file\r
2 Debug Agent library implementition with empty functions.\r
3\r
60274cca
HT
4 Copyright (c) 2010, Intel Corporation. All rights reserved.<BR>\r
5 This program and the accompanying materials\r
969eba7b 6 are licensed and made available under the terms and conditions of the BSD License\r
7 which accompanies this distribution. The full text of the license may be found at\r
8 http://opensource.org/licenses/bsd-license.php\r
9\r
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
12\r
13**/\r
14\r
15#include "GdbDebugAgent.h"\r
16\r
17\r
18UINTN gMaxProcessorIndex = 0;\r
19\r
20//\r
21// Buffers for basic gdb communication\r
22//\r
23CHAR8 gInBuffer[MAX_BUF_SIZE];\r
24CHAR8 gOutBuffer[MAX_BUF_SIZE];\r
25\r
26\r
27//\r
28// Globals for returning XML from qXfer:libraries:read packet\r
29//\r
30UINTN gPacketqXferLibraryOffset = 0;\r
31UINTN gEfiDebugImageTableEntry = 0;\r
32CHAR8 gXferLibraryBuffer[2000];\r
33\r
34GLOBAL_REMOVE_IF_UNREFERENCED CONST CHAR8 mHexToStr[] = {'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};\r
35\r
36\r
37// add-symbol-file c:/work/edk2/Build/BeagleBoard/DEBUG_ARMGCC/ARM/BeagleBoardPkg/Sec/Sec/DEBUG/BeagleBoardSec.dll 0x80008360 \r
38CHAR8 *qXferHack = "<library name=\"c:/work/edk2/Build/BeagleBoard/DEBUG_ARMGCC/ARM/BeagleBoardPkg/Sec/Sec/DEBUG/BeagleBoardSec.dll\"><segment address=\"0x80008360\"/></library>";\r
39\r
40UINTN\r
41gXferObjectReadResponse (\r
42 IN CHAR8 Type,\r
43 IN CHAR8 *Str\r
44 )\r
45{\r
46 CHAR8 *OutBufPtr; // pointer to the output buffer\r
47 CHAR8 Char;\r
48 UINTN Count;\r
49\r
50 // responce starts with 'm' or 'l' if it is the end\r
51 OutBufPtr = gOutBuffer;\r
52 *OutBufPtr++ = Type;\r
53 Count = 1;\r
54\r
55 // Binary data encoding \r
56 OutBufPtr = gOutBuffer;\r
57 while (*Str != '\0') {\r
58 Char = *Str++;\r
59 if ((Char == 0x7d) || (Char == 0x23) || (Char == 0x24) || (Char == 0x2a)) {\r
60 // escape character\r
61 *OutBufPtr++ = 0x7d;\r
62\r
63 Char ^= 0x20;\r
64 }\r
65 *OutBufPtr++ = Char;\r
66 Count++;\r
67 }\r
68\r
69 *OutBufPtr = '\0' ; // the end of the buffer\r
70 SendPacket (gOutBuffer);\r
71 \r
72 return Count;\r
73}\r
74\r
75/** \r
76 Process "qXfer:object:read:annex:offset,length" request.\r
77 \r
78 Returns an XML document that contains loaded libraries. In our case it is \r
79 infomration in the EFI Debug Inmage Table converted into an XML document.\r
80 \r
81 GDB will call with an arbitrary length (it can't know the real length and \r
82 will reply with chunks of XML that are easy for us to deal with. Gdb will \r
83 keep calling until we say we are done. XML doc looks like:\r
84 \r
85 <library-list>\r
86 <library name="/a/a/c/d.dSYM"><segment address="0x10000000"/></library>\r
87 <library name="/a/m/e/e.pdb"><segment address="0x20000000"/></library>\r
88 <library name="/a/l/f/f.dll"><segment address="0x30000000"/></library>\r
89 </library-list>\r
90 \r
91 Since we can not allocate memory in interupt context this module has \r
92 assumptions about how it will get called:\r
93 1) Length will generally be max remote packet size (big enough)\r
94 2) First Offset of an XML document read needs to be 0\r
95 3) This code will return back small chunks of the XML document on every read.\r
96 Each subseqent call will ask for the next availble part of the document.\r
97 \r
98 Note: The only variable size element in the XML is:\r
99 " <library name=\"%s\"><segment address=\"%p\"/></library>\n" and it is \r
100 based on the file path and name of the symbol file. If the symbol file name\r
101 is bigger than the max gdb remote packet size we could update this code\r
102 to respond back in chunks.\r
103\r
104 @param Offset offset into special data area\r
105 @param Length number of bytes to read starting at Offset \r
106 \r
107 **/\r
108VOID\r
109QxferLibrary (\r
110 IN UINTN Offset,\r
111 IN UINTN Length\r
112 )\r
113{\r
114 gPacketqXferLibraryOffset += gXferObjectReadResponse ('m', "<library-list>\n");\r
115 gPacketqXferLibraryOffset += gXferObjectReadResponse ('m', qXferHack);\r
116 gXferObjectReadResponse ('l', "</library-list>\n");\r
117 gPacketqXferLibraryOffset = 0;\r
118}\r
119\r
120/**\r
121 Transfer length bytes of input buffer, starting at Address, to memory.\r
122\r
123 @param length the number of the bytes to be transferred/written\r
124 @param *address the start address of the transferring/writing the memory\r
125 @param *new_data the new data to be written to memory\r
126 **/\r
127\r
128VOID\r
129TransferFromInBufToMem (\r
130 IN UINTN Length,\r
131 IN unsigned char *Address,\r
132 IN CHAR8 *NewData\r
133 )\r
134{\r
135 CHAR8 c1;\r
136 CHAR8 c2;\r
137 \r
138 while (Length-- > 0) {\r
139 c1 = (CHAR8)HexCharToInt (*NewData++);\r
140 c2 = (CHAR8)HexCharToInt (*NewData++);\r
141\r
142 if ((c1 < 0) || (c2 < 0)) {\r
143 SendError (GDB_EBADMEMDATA); \r
144 return;\r
145 }\r
146 *Address++ = (UINT8)((c1 << 4) + c2);\r
147 }\r
148\r
149 SendSuccess();\r
150}\r
151\r
152\r
153/**\r
154 Transfer Length bytes of memory starting at Address to an output buffer, OutBuffer. This function will finally send the buffer\r
155 as a packet.\r
156\r
157 @param Length the number of the bytes to be transferred/read\r
158 @param *address pointer to the start address of the transferring/reading the memory\r
159 **/\r
160\r
161VOID\r
162TransferFromMemToOutBufAndSend (\r
163 IN UINTN Length,\r
164 IN unsigned char *Address\r
165 )\r
166{\r
167 // there are Length bytes and every byte is represented as 2 hex chars\r
168 CHAR8 OutBuffer[MAX_BUF_SIZE];\r
169 CHAR8 *OutBufPtr; // pointer to the output buffer\r
170 CHAR8 Char;\r
171\r
172 OutBufPtr = OutBuffer;\r
173 while (Length > 0) {\r
174 \r
175 Char = mHexToStr[*Address >> 4];\r
176 if ((Char >= 'A') && (Char <= 'F')) {\r
177 Char = Char - 'A' + 'a';\r
178 }\r
179 *OutBufPtr++ = Char;\r
180\r
181 Char = mHexToStr[*Address & 0x0f];\r
182 if ((Char >= 'A') && (Char <= 'F')) {\r
183 Char = Char - 'A' + 'a';\r
184 }\r
185 *OutBufPtr++ = Char;\r
186\r
187 Address++;\r
188 Length--;\r
189 }\r
190\r
191 *OutBufPtr = '\0' ; // the end of the buffer\r
192 SendPacket (OutBuffer);\r
193}\r
194\r
195\r
196\r
197/**\r
198 Send a GDB Remote Serial Protocol Packet\r
199 \r
200 $PacketData#checksum PacketData is passed in and this function adds the packet prefix '$', \r
201 the packet teminating character '#' and the two digit checksum.\r
202 \r
203 If an ack '+' is not sent resend the packet, but timeout eventually so we don't end up \r
204 in an infinit loop. This is so if you unplug the debugger code just keeps running\r
205\r
206 @param PacketData Payload data for the packet \r
207\r
208 \r
209 @retval Number of bytes of packet data sent.\r
210\r
211**/\r
212UINTN\r
213SendPacket (\r
214 IN CHAR8 *PacketData\r
215 )\r
216{\r
217 UINT8 CheckSum;\r
218 UINTN Timeout;\r
219 CHAR8 *Ptr;\r
220 CHAR8 TestChar;\r
221 UINTN Count;\r
222 \r
223 Timeout = PcdGet32 (PcdGdbMaxPacketRetryCount);\r
224\r
225 Count = 0;\r
226 do {\r
227\r
228 Ptr = PacketData;\r
229\r
230 if (Timeout-- == 0) {\r
231 // Only try a finite number of times so we don't get stuck in the loop\r
232 return Count;\r
233 }\r
234 \r
235 // Packet prefix\r
236 GdbPutChar ('$');\r
237 \r
238 for (CheckSum = 0, Count =0 ; *Ptr != '\0'; Ptr++, Count++) {\r
239 GdbPutChar (*Ptr);\r
240 CheckSum = CheckSum + *Ptr;\r
241 }\r
242 \r
243 // Packet terminating character and checksum \r
244 GdbPutChar ('#');\r
245 GdbPutChar (mHexToStr[CheckSum >> 4]);\r
246 GdbPutChar (mHexToStr[CheckSum & 0x0F]);\r
247 \r
248 TestChar = GdbGetChar ();\r
249 } while (TestChar != '+');\r
250 \r
251 return Count;\r
252}\r
253\r
254/**\r
255 Receive a GDB Remote Serial Protocol Packet\r
256 \r
257 $PacketData#checksum PacketData is passed in and this function adds the packet prefix '$', \r
258 the packet teminating character '#' and the two digit checksum.\r
259 \r
260 If host re-starts sending a packet without ending the previous packet, only the last valid packet is proccessed.\r
261 (In other words, if received packet is '$12345$12345$123456#checksum', only '$123456#checksum' will be processed.)\r
262 \r
263 If an ack '+' is not sent resend the packet\r
264\r
265 @param PacketData Payload data for the packet \r
266\r
267 @retval Number of bytes of packet data received.\r
268\r
269**/\r
270UINTN\r
271ReceivePacket (\r
272 OUT CHAR8 *PacketData,\r
273 IN UINTN PacketDataSize\r
274 )\r
275{\r
276 UINT8 CheckSum;\r
277 UINTN Index;\r
278 CHAR8 Char;\r
279 CHAR8 SumString[3];\r
280 CHAR8 TestChar;\r
281 \r
282 ZeroMem (PacketData, PacketDataSize);\r
283 \r
284 for (;;) {\r
285 // wait for the start of a packet\r
286 TestChar = GdbGetChar ();\r
287 while (TestChar != '$') {\r
288 TestChar = GdbGetChar ();\r
289 };\r
290 \r
291 retry:\r
292 for (Index = 0, CheckSum = 0; Index < (PacketDataSize - 1); Index++) {\r
293 Char = GdbGetChar ();\r
294 if (Char == '$') {\r
295 goto retry;\r
296 }\r
297 if (Char == '#') {\r
298 break;\r
299 }\r
300\r
301 PacketData[Index] = Char;\r
302 CheckSum = CheckSum + Char;\r
303 }\r
304 PacketData[Index] = '\0';\r
305\r
306 if (Index == PacketDataSize) {\r
307 continue;\r
308 }\r
309\r
310 SumString[0] = GdbGetChar (); \r
311 SumString[1] = GdbGetChar ();\r
312 SumString[2] = '\0';\r
313 \r
314 if (AsciiStrHexToUintn (SumString) == CheckSum) {\r
315 // Ack: Success\r
316 GdbPutChar ('+');\r
317 \r
318 // Null terminate the callers string\r
319 PacketData[Index] = '\0';\r
320 return Index;\r
321 } else {\r
322 // Ack: Failure\r
323 GdbPutChar ('-');\r
324 }\r
325 }\r
326 \r
327 //return 0;\r
328}\r
329\r
330\r
331/**\r
332 Empties the given buffer \r
333 @param Buf pointer to the first element in buffer to be emptied\r
334 **/\r
335VOID\r
336EmptyBuffer ( \r
337 IN CHAR8 *Buf\r
338 )\r
339{ \r
340 *Buf = '\0';\r
341}\r
342\r
343\r
344/**\r
345 Converts an 8-bit Hex Char into a INTN.\r
346 \r
347 @param Char the hex character to be converted into UINTN\r
348 @retval a INTN, from 0 to 15, that corressponds to Char\r
349 -1 if Char is not a hex character\r
350 **/\r
351INTN\r
352HexCharToInt (\r
353 IN CHAR8 Char\r
354 )\r
355{\r
356 if ((Char >= 'A') && (Char <= 'F')) {\r
357 return Char - 'A' + 10;\r
358 } else if ((Char >= 'a') && (Char <= 'f')) {\r
359 return Char - 'a' + 10;\r
360 } else if ((Char >= '0') && (Char <= '9')) {\r
361 return Char - '0';\r
362 } else { // if not a hex value, return a negative value\r
363 return -1; \r
364 }\r
365}\r
366\r
367 // 'E' + the biggest error number is 255, so its 2 hex digits + buffer end\r
368CHAR8 *gError = "E__";\r
369\r
370/** 'E NN'\r
371 Send an error with the given error number after converting to hex.\r
372 The error number is put into the buffer in hex. '255' is the biggest errno we can send.\r
373 ex: 162 will be sent as A2.\r
374 \r
375 @param errno the error number that will be sent\r
376 **/\r
377VOID\r
378EFIAPI\r
379SendError (\r
380 IN UINT8 ErrorNum\r
381 )\r
382{\r
383 //\r
384 // Replace _, or old data, with current errno\r
385 //\r
386 gError[1] = mHexToStr [ErrorNum >> 4];\r
387 gError[2] = mHexToStr [ErrorNum & 0x0f];\r
388 \r
389 SendPacket (gError); // send buffer\r
390}\r
391\r
392\r
393\r
394/**\r
395 Send 'OK' when the function is done executing successfully.\r
396 **/\r
397VOID\r
398EFIAPI\r
399SendSuccess (\r
400 VOID\r
401 ) \r
402{\r
403 SendPacket ("OK"); // send buffer\r
404}\r
405\r
406\r
407/**\r
408 Send empty packet to specify that particular command/functionality is not supported.\r
409 **/\r
410VOID \r
411EFIAPI \r
412SendNotSupported (\r
413 VOID \r
414 ) \r
415{ \r
416 SendPacket ("");\r
417}\r
418\r
419\r
420\r
421\r
422\r
423/**\r
424 Translates the EFI mapping to GDB mapping\r
425 \r
426 @param EFIExceptionType EFI Exception that is being processed\r
427 @retval UINTN that corresponds to EFIExceptionType's GDB exception type number\r
428 **/\r
429UINT8\r
430ConvertEFItoGDBtype ( \r
431 IN EFI_EXCEPTION_TYPE EFIExceptionType\r
432 )\r
433{ \r
434 UINTN i;\r
435 \r
436 for (i=0; i < MaxEfiException() ; i++) {\r
437 if (gExceptionType[i].Exception == EFIExceptionType) {\r
438 return gExceptionType[i].SignalNo;\r
439 }\r
440 }\r
441 return GDB_SIGTRAP; // this is a GDB trap\r
442}\r
443\r
444\r
445/** "m addr,length"\r
446 Find the Length of the area to read and the start addres. Finally, pass them to \r
447 another function, TransferFromMemToOutBufAndSend, that will read from that memory space and \r
448 send it as a packet.\r
449 **/\r
450\r
451VOID\r
452EFIAPI\r
453ReadFromMemory (\r
454 CHAR8 *PacketData\r
455 )\r
456{\r
457 UINTN Address;\r
458 UINTN Length;\r
459 CHAR8 AddressBuffer[MAX_ADDR_SIZE]; // the buffer that will hold the address in hex chars\r
460 CHAR8 *AddrBufPtr; // pointer to the address buffer\r
461 CHAR8 *InBufPtr; /// pointer to the input buffer\r
462 \r
463 AddrBufPtr = AddressBuffer;\r
464 InBufPtr = &PacketData[1];\r
465 while (*InBufPtr != ',') {\r
466 *AddrBufPtr++ = *InBufPtr++;\r
467 }\r
468 *AddrBufPtr = '\0';\r
469 \r
470 InBufPtr++; // this skips ',' in the buffer\r
471 \r
472 /* Error checking */\r
473 if (AsciiStrLen(AddressBuffer) >= MAX_ADDR_SIZE) {\r
474 SendError (GDB_EBADMEMADDRBUFSIZE); \r
475 return;\r
476 }\r
477 \r
478 // 2 = 'm' + ','\r
479 if (AsciiStrLen(PacketData) - AsciiStrLen(AddressBuffer) - 2 >= MAX_LENGTH_SIZE) {\r
480 SendError (GDB_EBADMEMLENGTH); \r
481 return;\r
482 }\r
483 \r
484 Address = AsciiStrHexToUintn (AddressBuffer);\r
485 Length = AsciiStrHexToUintn (InBufPtr);\r
486 \r
487 TransferFromMemToOutBufAndSend (Length, (unsigned char *)Address);\r
488}\r
489\r
490\r
491/** "M addr,length :XX..."\r
492 Find the Length of the area in bytes to write and the start addres. Finally, pass them to \r
493 another function, TransferFromInBufToMem, that will write to that memory space the info in\r
494 the input buffer.\r
495 **/\r
496VOID\r
497EFIAPI\r
498WriteToMemory (\r
499 IN CHAR8 *PacketData\r
500 )\r
501{\r
502 UINTN Address;\r
503 UINTN Length;\r
504 UINTN MessageLength;\r
505 CHAR8 AddressBuffer[MAX_ADDR_SIZE]; // the buffer that will hold the Address in hex chars\r
506 CHAR8 LengthBuffer[MAX_LENGTH_SIZE]; // the buffer that will hold the Length in hex chars\r
507 CHAR8 *AddrBufPtr; // pointer to the Address buffer\r
508 CHAR8 *LengthBufPtr; // pointer to the Length buffer\r
509 CHAR8 *InBufPtr; /// pointer to the input buffer\r
510 \r
511 AddrBufPtr = AddressBuffer;\r
512 LengthBufPtr = LengthBuffer;\r
513 InBufPtr = &PacketData[1];\r
514 \r
515 while (*InBufPtr != ',') {\r
516 *AddrBufPtr++ = *InBufPtr++;\r
517 }\r
518 *AddrBufPtr = '\0';\r
519 \r
520 InBufPtr++; // this skips ',' in the buffer\r
521 \r
522 while (*InBufPtr != ':') {\r
523 *LengthBufPtr++ = *InBufPtr++;\r
524 }\r
525 *LengthBufPtr = '\0';\r
526 \r
527 InBufPtr++; // this skips ':' in the buffer\r
528 \r
529 Address = AsciiStrHexToUintn (AddressBuffer);\r
530 Length = AsciiStrHexToUintn (LengthBuffer);\r
531 \r
532 /* Error checking */\r
533 \r
534 //Check if Address is not too long.\r
535 if (AsciiStrLen(AddressBuffer) >= MAX_ADDR_SIZE) {\r
536 SendError (GDB_EBADMEMADDRBUFSIZE); \r
537 return;\r
538 }\r
539 \r
540 //Check if message length is not too long\r
541 if (AsciiStrLen(LengthBuffer) >= MAX_LENGTH_SIZE) {\r
542 SendError (GDB_EBADMEMLENGBUFSIZE); \r
543 return;\r
544 }\r
545 \r
546 // Check if Message is not too long/short.\r
547 // 3 = 'M' + ',' + ':'\r
548 MessageLength = (AsciiStrLen(PacketData) - AsciiStrLen(AddressBuffer) - AsciiStrLen(LengthBuffer) - 3);\r
549 if (MessageLength != (2*Length)) {\r
550 //Message too long/short. New data is not the right size.\r
551 SendError (GDB_EBADMEMDATASIZE); \r
552 return;\r
553 }\r
554 TransferFromInBufToMem (Length, (unsigned char *)Address, InBufPtr);\r
555}\r
556\r
557/**\r
558 Parses breakpoint packet data and captures Breakpoint type, Address and length.\r
559 In case of an error, function returns particular error code. Returning 0 meaning\r
560 no error.\r
561\r
562 @param PacketData Pointer to the payload data for the packet.\r
563 @param Type Breakpoint type\r
564 @param Address Breakpoint address\r
565 @param Length Breakpoint length in Bytes (1 byte, 2 byte, 4 byte)\r
566\r
567 @retval 1 Success\r
568 @retval {other} Particular error code\r
569\r
570**/\r
571UINTN\r
572ParseBreakpointPacket (\r
573 IN CHAR8 *PacketData,\r
574 OUT UINTN *Type,\r
575 OUT UINTN *Address,\r
576 OUT UINTN *Length\r
577 )\r
578{\r
579 CHAR8 AddressBuffer[MAX_ADDR_SIZE];\r
580 CHAR8 *AddressBufferPtr;\r
581 CHAR8 *PacketDataPtr;\r
582\r
583 PacketDataPtr = &PacketData[1];\r
584 AddressBufferPtr = AddressBuffer;\r
585\r
586 *Type = AsciiStrHexToUintn (PacketDataPtr);\r
587\r
588 //Breakpoint/watchpoint type should be between 0 to 4\r
589 if (*Type > 4) {\r
590 return 22; //EINVAL: Invalid argument.\r
591 }\r
592\r
593 //Skip ',' in the buffer.\r
594 while (*PacketDataPtr++ != ',');\r
595\r
596 //Parse Address information\r
597 while (*PacketDataPtr != ',') {\r
598 *AddressBufferPtr++ = *PacketDataPtr++;\r
599 }\r
600 *AddressBufferPtr = '\0';\r
601\r
602 //Check if Address is not too long.\r
603 if (AsciiStrLen(AddressBuffer) >= MAX_ADDR_SIZE) {\r
604 return 40; //EMSGSIZE: Message size too long.\r
605 }\r
606\r
607 *Address = AsciiStrHexToUintn (AddressBuffer);\r
608\r
609 PacketDataPtr++; //This skips , in the buffer\r
610\r
611 //Parse Length information\r
612 *Length = AsciiStrHexToUintn (PacketDataPtr);\r
613\r
614 //Length should be 1, 2 or 4 bytes\r
615 if (*Length > 4) {\r
616 return 22; //EINVAL: Invalid argument\r
617 }\r
618\r
619 return 0; //0 = No error\r
620}\r
621\r
622\r
623\r
624/**\r
625 Send the T signal with the given exception type (in gdb order) and possibly with n:r pairs related to the watchpoints\r
626 \r
627 @param SystemContext Register content at time of the exception\r
628 @param GdbExceptionType GDB exception type\r
629 **/\r
630VOID\r
631GdbSendTSignal (\r
632 IN EFI_SYSTEM_CONTEXT SystemContext,\r
633 IN UINT8 GdbExceptionType\r
634 )\r
635{\r
636 CHAR8 TSignalBuffer[128];\r
637 CHAR8 *TSignalPtr;\r
638\r
639 TSignalPtr = &TSignalBuffer[0];\r
640\r
641 //Construct TSignal packet\r
642 *TSignalPtr++ = 'T';\r
643\r
644 //\r
645 // replace _, or previous value, with Exception type\r
646 //\r
647 *TSignalPtr++ = mHexToStr [GdbExceptionType >> 4]; \r
648 *TSignalPtr++ = mHexToStr [GdbExceptionType & 0x0f];\r
649 \r
650 ProcessorSendTSignal (SystemContext, GdbExceptionType, TSignalPtr, sizeof (TSignalBuffer) - 2);\r
651\r
652 SendPacket (TSignalBuffer); \r
653}\r
654\r
655VOID\r
656GdbFWrite (\r
657 IN UINTN Fd,\r
658 IN CHAR8 *Data,\r
659 IN UINTN DataSize\r
660 )\r
661{\r
662 CHAR8 Buffer[128];\r
663\r
664 AsciiSPrint (Buffer, sizeof (Buffer), "Fwrite,%x,%x,%x", Fd, Data, DataSize);\r
665 SendPacket (Buffer);\r
666\r
667 for( ; ; ) {\r
668 ReceivePacket (gInBuffer, MAX_BUF_SIZE);\r
669 \r
670 switch (gInBuffer[0]) {\r
671 case 'm':\r
672 ReadFromMemory (gInBuffer);\r
673 break;\r
674\r
675 case 'M':\r
676 WriteToMemory (gInBuffer);\r
677 break;\r
678\r
679 case 'F':\r
680 return;\r
969eba7b 681 }\r
682 }\r
683}\r
684\r
685\r
686VOID\r
687GdbFPutString (\r
688 IN CHAR8 *String\r
689 )\r
690{\r
691 UINTN Len = AsciiStrSize (String);\r
692\r
693 GdbFWrite (2, String, Len);\r
694}\r
695\r
696\r
697/**\r
698 Exception Hanldler for GDB. It will be called for all exceptions\r
699 registered via the gExceptionType[] array.\r
700 \r
701 @param ExceptionType Exception that is being processed\r
702 @param SystemContext Register content at time of the exception \r
703 **/\r
704VOID\r
705EFIAPI\r
706GdbExceptionHandler ( \r
707 IN EFI_EXCEPTION_TYPE ExceptionType, \r
708 IN OUT EFI_SYSTEM_CONTEXT SystemContext \r
709 )\r
710{\r
711 UINT8 GdbExceptionType;\r
712 CHAR8 *Ptr;\r
713 \r
714 if (ProcessorControlC (ExceptionType, SystemContext)) {\r
715 // We tried to process a control C handler and there is nothing to do\r
716 return;\r
717 }\r
718\r
719 GdbExceptionType = ConvertEFItoGDBtype (ExceptionType);\r
720 GdbSendTSignal (SystemContext, GdbExceptionType);\r
721 \r
722 for( ; ; ) {\r
723 ReceivePacket (gInBuffer, MAX_BUF_SIZE);\r
724 \r
725 switch (gInBuffer[0]) {\r
726 case '?':\r
727 GdbSendTSignal (SystemContext, GdbExceptionType);\r
728 break;\r
729 \r
730 case 'c':\r
731 ContinueAtAddress (SystemContext, gInBuffer); \r
732 return;\r
733\r
734 case 'D':\r
735 // gdb wants to disconnect so return "OK" packet since. \r
736 SendSuccess ();\r
737 return;\r
738\r
739 case 'g':\r
740 ReadGeneralRegisters (SystemContext);\r
741 break;\r
742 \r
743 case 'G':\r
744 WriteGeneralRegisters (SystemContext, gInBuffer);\r
745 break;\r
746 \r
747 case 'H':\r
748 //Return "OK" packet since we don't have more than one thread. \r
749 SendSuccess ();\r
750 break;\r
751 \r
752 case 'm':\r
753 ReadFromMemory (gInBuffer);\r
754 break;\r
755\r
756 case 'M':\r
757 WriteToMemory (gInBuffer);\r
758 break;\r
759\r
760 case 'P':\r
761 WriteNthRegister (SystemContext, gInBuffer);\r
762 break;\r
763\r
764 //\r
765 // Still debugging this code. Not used in Darwin\r
766 //\r
767 case 'q': \r
768 // General Query Packets\r
769 if (AsciiStrnCmp (gInBuffer, "qSupported", 10) == 0) {\r
770 // return what we currently support, we don't parse what gdb suports\r
771 AsciiSPrint (gOutBuffer, MAX_BUF_SIZE, "qXfer:libraries:read+;PacketSize=%d", MAX_BUF_SIZE);\r
772 SendPacket (gOutBuffer);\r
773 } else if (AsciiStrnCmp (gInBuffer, "qXfer:libraries:read::", 22) == 0) {\r
774