]> git.proxmox.com Git - mirror_edk2.git/blame - SourceLevelDebugPkg/Library/DebugAgent/DebugAgentCommon/DebugAgent.c
Refine code to make it more safely.
[mirror_edk2.git] / SourceLevelDebugPkg / Library / DebugAgent / DebugAgentCommon / DebugAgent.c
CommitLineData
18b144ea 1/** @file\r
2 Commond Debug Agent library implementition. It mainly includes\r
3 the first C function called by exception/interrupt handlers,\r
4 read/write debug packet to communication with HOST based on transfer\r
5 protocol.\r
6\r
875670e2 7 Copyright (c) 2010 - 2014, Intel Corporation. All rights reserved.<BR>\r
18b144ea 8 This program and the accompanying materials\r
9 are licensed and made available under the terms and conditions of the BSD License\r
10 which accompanies this distribution. The full text of the license may be found at\r
11 http://opensource.org/licenses/bsd-license.php.\r
12\r
13 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
14 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
15\r
16**/\r
17\r
18#include "DebugAgent.h"\r
19#include "Ia32/DebugException.h"\r
20\r
b422b62c 21CHAR8 mErrorMsgVersionAlert[] = "\rThe SourceLevelDebugPkg you are using requires a newer version of the Intel(R) UDK Debugger Tool.\r\n";\r
875670e2 22CHAR8 mErrorMsgSendInitPacket[] = "\rSend INIT break packet and try to connect the HOST (Intel(R) UDK Debugger Tool v1.4) ...\r\n";\r
b422b62c 23CHAR8 mErrorMsgConnectOK[] = "HOST connection is successful!\r\n";\r
24CHAR8 mErrorMsgConnectFail[] = "HOST connection is failed!\r\n";\r
25CHAR8 mWarningMsgIngoreBreakpoint[] = "Ignore break point in SMM for SMI issued during DXE debugging!\r\n";\r
93c0bdec 26\r
8cc26df4
JF
27//\r
28// Vector Handoff Info list used by Debug Agent for persist\r
29//\r
30EFI_VECTOR_HANDOFF_INFO mVectorHandoffInfoDebugAgent[] = {\r
31 {\r
32 DEBUG_EXCEPT_DIVIDE_ERROR, // Vector 0\r
33 EFI_VECTOR_HANDOFF_HOOK_BEFORE,\r
34 EFI_DEBUG_AGENT_GUID\r
35 },\r
36 {\r
37 DEBUG_EXCEPT_DEBUG, // Vector 1\r
38 EFI_VECTOR_HANDOFF_DO_NOT_HOOK,\r
39 EFI_DEBUG_AGENT_GUID\r
40 },\r
41 {\r
42 DEBUG_EXCEPT_NMI, // Vector 2\r
43 EFI_VECTOR_HANDOFF_HOOK_BEFORE,\r
44 EFI_DEBUG_AGENT_GUID\r
45 },\r
46 {\r
47 DEBUG_EXCEPT_BREAKPOINT, // Vector 3\r
48 EFI_VECTOR_HANDOFF_DO_NOT_HOOK,\r
49 EFI_DEBUG_AGENT_GUID\r
50 },\r
51 {\r
52 DEBUG_EXCEPT_OVERFLOW, // Vector 4\r
53 EFI_VECTOR_HANDOFF_HOOK_BEFORE,\r
54 EFI_DEBUG_AGENT_GUID\r
55 },\r
56 {\r
57 DEBUG_EXCEPT_BOUND, // Vector 5\r
58 EFI_VECTOR_HANDOFF_HOOK_BEFORE,\r
59 EFI_DEBUG_AGENT_GUID\r
60 },\r
61 {\r
62 DEBUG_EXCEPT_INVALID_OPCODE, // Vector 6\r
63 EFI_VECTOR_HANDOFF_HOOK_BEFORE,\r
64 EFI_DEBUG_AGENT_GUID\r
65 },\r
66 {\r
67 DEBUG_EXCEPT_DOUBLE_FAULT, // Vector 8\r
68 EFI_VECTOR_HANDOFF_HOOK_BEFORE,\r
69 EFI_DEBUG_AGENT_GUID\r
70 },\r
71 {\r
72 DEBUG_EXCEPT_INVALID_TSS, // Vector 10\r
73 EFI_VECTOR_HANDOFF_HOOK_BEFORE,\r
74 EFI_DEBUG_AGENT_GUID\r
75 },\r
76 {\r
77 DEBUG_EXCEPT_SEG_NOT_PRESENT, // Vector 11\r
78 EFI_VECTOR_HANDOFF_HOOK_BEFORE,\r
79 EFI_DEBUG_AGENT_GUID\r
80 },\r
81 {\r
82 DEBUG_EXCEPT_STACK_FAULT, // Vector 12\r
83 EFI_VECTOR_HANDOFF_HOOK_BEFORE,\r
84 EFI_DEBUG_AGENT_GUID\r
85 },\r
86 {\r
87 DEBUG_EXCEPT_GP_FAULT, // Vector 13\r
88 EFI_VECTOR_HANDOFF_HOOK_BEFORE,\r
89 EFI_DEBUG_AGENT_GUID\r
90 },\r
91 {\r
92 DEBUG_EXCEPT_PAGE_FAULT, // Vector 14\r
93 EFI_VECTOR_HANDOFF_HOOK_BEFORE,\r
94 EFI_DEBUG_AGENT_GUID\r
95 },\r
96 {\r
97 DEBUG_EXCEPT_FP_ERROR, // Vector 16\r
98 EFI_VECTOR_HANDOFF_HOOK_BEFORE,\r
99 EFI_DEBUG_AGENT_GUID\r
100 },\r
101 {\r
102 DEBUG_EXCEPT_ALIGNMENT_CHECK, // Vector 17\r
103 EFI_VECTOR_HANDOFF_HOOK_BEFORE,\r
104 EFI_DEBUG_AGENT_GUID\r
105 },\r
106 {\r
107 DEBUG_EXCEPT_MACHINE_CHECK, // Vector 18\r
108 EFI_VECTOR_HANDOFF_HOOK_BEFORE,\r
109 EFI_DEBUG_AGENT_GUID\r
110 },\r
111 {\r
112 DEBUG_EXCEPT_SIMD, // Vector 19\r
113 EFI_VECTOR_HANDOFF_HOOK_BEFORE,\r
114 EFI_DEBUG_AGENT_GUID\r
115 },\r
116 {\r
117 DEBUG_TIMER_VECTOR, // Vector 32\r
118 EFI_VECTOR_HANDOFF_DO_NOT_HOOK,\r
119 EFI_DEBUG_AGENT_GUID\r
120 },\r
121 {\r
122 DEBUG_MAILBOX_VECTOR, // Vector 33\r
123 EFI_VECTOR_HANDOFF_DO_NOT_HOOK,\r
124 EFI_DEBUG_AGENT_GUID\r
125 },\r
126 {\r
127 0,\r
128 EFI_VECTOR_HANDOFF_LAST_ENTRY,\r
129 { 0 }\r
130 }\r
131};\r
132\r
133UINTN mVectorHandoffInfoCount = sizeof (mVectorHandoffInfoDebugAgent) / sizeof (EFI_VECTOR_HANDOFF_INFO);\r
134\r
b422b62c 135/**\r
136 Calculate CRC16 for target data.\r
137\r
138 @param[in] Data The target data.\r
139 @param[in] DataSize The target data size.\r
140 @param[in] Crc Initial CRC.\r
141\r
142 @return UINT16 The CRC16 value.\r
143\r
144**/\r
145UINT16\r
146CalculateCrc16 (\r
147 IN UINT8 *Data,\r
148 IN UINTN DataSize,\r
149 IN UINT16 Crc\r
150 )\r
151{\r
152 UINTN Index;\r
153 UINTN BitIndex;\r
154\r
155 for (Index = 0; Index < DataSize; Index++) {\r
156 Crc ^= Data[Index];\r
157 for (BitIndex = 0; BitIndex < 8; BitIndex++) {\r
158 if ((Crc & 0x8000) != 0) {\r
159 Crc <<= 1;\r
160 Crc ^= 0x1021;\r
161 } else {\r
162 Crc <<= 1;\r
163 }\r
164 }\r
165 }\r
166 return Crc;\r
167}\r
168\r
169\r
170/**\r
171 Read IDT entry to check if IDT entries are setup by Debug Agent.\r
172\r
173 @retval TRUE IDT entries were setup by Debug Agent.\r
174 @retval FALSE IDT entries were not setup by Debug Agent.\r
175\r
176**/\r
177BOOLEAN \r
178IsDebugAgentInitialzed (\r
179 VOID\r
180 )\r
181{\r
182 UINTN InterruptHandler;\r
183\r
184 InterruptHandler = (UINTN) GetExceptionHandlerInIdtEntry (0);\r
185 if (InterruptHandler >= 4 && *(UINT32 *)(InterruptHandler - 4) == AGENT_HANDLER_SIGNATURE) {\r
186 return TRUE;\r
187 } else {\r
188 return FALSE;\r
189 }\r
190}\r
191\r
192/**\r
193 Find and report module image info to HOST.\r
194 \r
195 @param[in] AlignSize Image aligned size.\r
196 \r
197**/\r
198VOID \r
199FindAndReportModuleImageInfo (\r
200 IN UINTN AlignSize \r
201 )\r
202{\r
203 UINTN Pe32Data;\r
204 EFI_IMAGE_DOS_HEADER *DosHdr;\r
205 EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION Hdr;\r
206 PE_COFF_LOADER_IMAGE_CONTEXT ImageContext;\r
207\r
208 //\r
209 // Find Image Base\r
210 //\r
211 Pe32Data = ((UINTN)mErrorMsgVersionAlert) & ~(AlignSize - 1);\r
212 while (Pe32Data != 0) {\r
213 DosHdr = (EFI_IMAGE_DOS_HEADER *) Pe32Data;\r
214 if (DosHdr->e_magic == EFI_IMAGE_DOS_SIGNATURE) {\r
215 //\r
216 // DOS image header is present, so read the PE header after the DOS image header.\r
217 // Check if address overflow firstly.\r
218 //\r
219 if ((MAX_ADDRESS - (UINTN)DosHdr->e_lfanew) > Pe32Data) {\r
220 Hdr.Pe32 = (EFI_IMAGE_NT_HEADERS32 *)(Pe32Data + (UINTN)(DosHdr->e_lfanew));\r
221 if (Hdr.Pe32->Signature == EFI_IMAGE_NT_SIGNATURE) {\r
222 //\r
223 // It's PE image.\r
224 //\r
225 break;\r
226 }\r
227 }\r
228 } else {\r
229 //\r
230 // DOS image header is not present, TE header is at the image base.\r
231 //\r
232 Hdr.Pe32 = (EFI_IMAGE_NT_HEADERS32 *)Pe32Data;\r
233 if ((Hdr.Te->Signature == EFI_TE_IMAGE_HEADER_SIGNATURE) &&\r
234 ((Hdr.Te->Machine == IMAGE_FILE_MACHINE_I386) || Hdr.Te->Machine == IMAGE_FILE_MACHINE_X64)) {\r
235 //\r
236 // It's TE image, it TE header and Machine type match\r
237 //\r
238 break;\r
239 }\r
240 }\r
241\r
242 //\r
243 // Not found the image base, check the previous aligned address\r
244 // \r
245 Pe32Data -= AlignSize;\r
246 }\r
247\r
248 ImageContext.ImageAddress = Pe32Data;\r
249 ImageContext.PdbPointer = PeCoffLoaderGetPdbPointer ((VOID*) (UINTN) ImageContext.ImageAddress);\r
250 PeCoffLoaderRelocateImageExtraAction (&ImageContext);\r
251}\r
252\r
253/**\r
254 Trigger one software interrupt to debug agent to handle it.\r
255\r
256 @param[in] Signature Software interrupt signature.\r
257\r
258**/\r
259VOID\r
260TriggerSoftInterrupt (\r
261 IN UINT32 Signature\r
262 )\r
263{\r
264 UINTN Dr0;\r
265 UINTN Dr1;\r
266\r
267 //\r
268 // Save Debug Register State\r
269 //\r
270 Dr0 = AsmReadDr0 ();\r
271 Dr1 = AsmReadDr1 ();\r
272\r
273 //\r
274 // DR0 = Signature\r
275 //\r
276 AsmWriteDr0 (SOFT_INTERRUPT_SIGNATURE);\r
277 AsmWriteDr1 (Signature);\r
278\r
279 //\r
280 // Do INT3 to communicate with HOST side\r
281 //\r
282 CpuBreakpoint ();\r
283\r
284 //\r
285 // Restore Debug Register State only when Host didn't change it inside exception handler.\r
286 // Dr registers can only be changed by setting the HW breakpoint.\r
287 //\r
288 AsmWriteDr0 (Dr0);\r
289 AsmWriteDr1 (Dr1);\r
290\r
291}\r
292\r
293/**\r
294 Caculate Mailbox checksum and update the checksum field.\r
295\r
296 @param[in] Mailbox Debug Agent Mailbox pointer.\r
297\r
298**/\r
299VOID\r
300UpdateMailboxChecksum (\r
301 IN DEBUG_AGENT_MAILBOX *Mailbox\r
302 )\r
303{\r
304 Mailbox->CheckSum = CalculateCheckSum8 ((UINT8 *)Mailbox, sizeof (DEBUG_AGENT_MAILBOX) - 2); \r
305}\r
306\r
307/**\r
308 Verify Mailbox checksum.\r
309\r
310 If checksum error, print debug message and run init dead loop.\r
311\r
312 @param[in] Mailbox Debug Agent Mailbox pointer.\r
313\r
314**/\r
315VOID \r
316VerifyMailboxChecksum (\r
317 IN DEBUG_AGENT_MAILBOX *Mailbox\r
318 )\r
319{\r
320 UINT8 CheckSum;\r
321 \r
322 CheckSum = CalculateCheckSum8 ((UINT8 *) Mailbox, sizeof (DEBUG_AGENT_MAILBOX) - 2);\r
323 //\r
324 // The checksum updating process may be disturbed by hardware SMI, we need to check CheckSum field \r
325 // and ToBeCheckSum field to validate the mail box.\r
326 //\r
327 if (CheckSum != Mailbox->CheckSum && CheckSum != Mailbox->ToBeCheckSum) {\r
328 DEBUG ((EFI_D_ERROR, "DebugAgent: Mailbox checksum error, stack or heap crashed!\n"));\r
329 DEBUG ((EFI_D_ERROR, "DebugAgent: CheckSum = %x, Mailbox->CheckSum = %x, Mailbox->ToBeCheckSum = %x\n", CheckSum, Mailbox->CheckSum, Mailbox->ToBeCheckSum));\r
330 CpuDeadLoop ();\r
331 }\r
332}\r
333\r
334/**\r
335 Update Mailbox content by index.\r
336\r
337 @param[in] Mailbox Debug Agent Mailbox pointer.\r
338 @param[in] Index Mailbox content index.\r
339 @param[in] Value Value to be set into Mailbox.\r
340 \r
341**/\r
342VOID\r
343UpdateMailboxContent ( \r
344 IN DEBUG_AGENT_MAILBOX *Mailbox,\r
345 IN UINTN Index,\r
346 IN UINT64 Value\r
347 )\r
348{\r
349 AcquireMpSpinLock (&mDebugMpContext.MailboxSpinLock);\r
350 switch (Index) {\r
351 case DEBUG_MAILBOX_DEBUG_FLAG_INDEX:\r
352 Mailbox->ToBeCheckSum = Mailbox->CheckSum + CalculateSum8 ((UINT8 *)&Mailbox->DebugFlag.Uint64, sizeof(UINT64)) \r
353 - CalculateSum8 ((UINT8 *)&Value, sizeof(UINT64));\r
354 Mailbox->DebugFlag.Uint64 = Value;\r
355 break;\r
356 case DEBUG_MAILBOX_DEBUG_PORT_HANDLE_INDEX:\r
357 Mailbox->ToBeCheckSum = Mailbox->CheckSum + CalculateSum8 ((UINT8 *)&Mailbox->DebugPortHandle, sizeof(UINTN))\r
358 - CalculateSum8 ((UINT8 *)&Value, sizeof(UINTN));\r
359 Mailbox->DebugPortHandle = (UINTN) Value;\r
360 break;\r
361 case DEBUG_MAILBOX_EXCEPTION_BUFFER_POINTER_INDEX:\r
362 Mailbox->ToBeCheckSum = Mailbox->CheckSum + CalculateSum8 ((UINT8 *)&Mailbox->ExceptionBufferPointer, sizeof(UINTN))\r
363 - CalculateSum8 ((UINT8 *)&Value, sizeof(UINTN));\r
364 Mailbox->ExceptionBufferPointer = (UINTN) Value;\r
365 break;\r
366 case DEBUG_MAILBOX_LAST_ACK:\r
367 Mailbox->ToBeCheckSum = Mailbox->CheckSum + CalculateSum8 ((UINT8 *)&Mailbox->LastAck, sizeof(UINT8))\r
368 - CalculateSum8 ((UINT8 *)&Value, sizeof(UINT8));\r
369 Mailbox->LastAck = (UINT8) Value;\r
370 break;\r
371 case DEBUG_MAILBOX_SEQUENCE_NO_INDEX:\r
372 Mailbox->ToBeCheckSum = Mailbox->CheckSum + CalculateSum8 ((UINT8 *)&Mailbox->SequenceNo, sizeof(UINT8))\r
373 - CalculateSum8 ((UINT8 *)&Value, sizeof(UINT8));\r
374 Mailbox->SequenceNo = (UINT8) Value;\r
375 break;\r
376 case DEBUG_MAILBOX_HOST_SEQUENCE_NO_INDEX:\r
377 Mailbox->ToBeCheckSum = Mailbox->CheckSum + CalculateSum8 ((UINT8 *)&Mailbox->HostSequenceNo, sizeof(UINT8))\r
378 - CalculateSum8 ((UINT8 *)&Value, sizeof(UINT8));\r
379 Mailbox->HostSequenceNo = (UINT8) Value;\r
380 break;\r
381 }\r
382 UpdateMailboxChecksum (Mailbox);\r
383 ReleaseMpSpinLock (&mDebugMpContext.MailboxSpinLock);\r
384}\r
385/**\r
386 Set debug flag in mailbox.\r
387\r
388 @param[in] FlagMask Debug flag mask value.\r
389 @param[in] FlagValue Debug flag value.\r
390\r
391**/\r
392VOID \r
393SetDebugFlag (\r
394 IN UINT64 FlagMask,\r
395 IN UINT32 FlagValue \r
396 )\r
397{\r
398 DEBUG_AGENT_MAILBOX *Mailbox;\r
399 UINT64 Data64;\r
400\r
401 Mailbox = GetMailboxPointer ();\r
402 Data64 = (Mailbox->DebugFlag.Uint64 & ~FlagMask) |\r
403 (LShiftU64 ((UINT64)FlagValue, LowBitSet64 (FlagMask)) & FlagMask);\r
404 UpdateMailboxContent (Mailbox, DEBUG_MAILBOX_DEBUG_FLAG_INDEX, Data64);\r
405}\r
406\r
407/**\r
408 Get debug flag in mailbox.\r
409\r
410 @param[in] FlagMask Debug flag mask value.\r
411 \r
412 @return Debug flag value.\r
413\r
414**/\r
415UINT32\r
416GetDebugFlag (\r
417 IN UINT64 FlagMask\r
418 )\r
419{\r
420 DEBUG_AGENT_MAILBOX *Mailbox;\r
421 UINT32 DebugFlag;\r
422\r
423 Mailbox = GetMailboxPointer ();\r
424 DebugFlag = (UINT32) RShiftU64 (Mailbox->DebugFlag.Uint64 & FlagMask, LowBitSet64 (FlagMask));\r
425\r
426 return DebugFlag;\r
427}\r
93c0bdec 428\r
18b144ea 429/**\r
93c0bdec 430 Send a debug message packet to the debug port.\r
18b144ea 431\r
93c0bdec 432 @param[in] Buffer The debug message.\r
433 @param[in] Length The length of debug message.\r
18b144ea 434\r
435**/\r
93c0bdec 436VOID\r
437SendDebugMsgPacket (\r
438 IN CHAR8 *Buffer,\r
439 IN UINTN Length \r
18b144ea 440 )\r
441{\r
93c0bdec 442 DEBUG_PACKET_HEADER DebugHeader;\r
443 DEBUG_PORT_HANDLE Handle;\r
444 \r
445 Handle = GetDebugPortHandle();\r
18b144ea 446\r
93c0bdec 447 DebugHeader.StartSymbol = DEBUG_STARTING_SYMBOL_NORMAL;\r
448 DebugHeader.Command = DEBUG_COMMAND_PRINT_MESSAGE;\r
449 DebugHeader.Length = sizeof (DEBUG_PACKET_HEADER) + (UINT8) Length;\r
b422b62c 450 DebugHeader.SequenceNo = 0xEE;\r
451 DebugHeader.Crc = 0;\r
452 DebugHeader.Crc = CalculateCrc16 (\r
453 (UINT8 *)Buffer, Length,\r
454 CalculateCrc16 ((UINT8 *)&DebugHeader, sizeof (DEBUG_PACKET_HEADER), 0)\r
455 );\r
18b144ea 456\r
93c0bdec 457 DebugPortWriteBuffer (Handle, (UINT8 *)&DebugHeader, sizeof (DEBUG_PACKET_HEADER));\r
458 DebugPortWriteBuffer (Handle, (UINT8 *)Buffer, Length);\r
459}\r
460\r
461/**\r
462 Prints a debug message to the debug port if the specified error level is enabled.\r
463\r
464 If any bit in ErrorLevel is also set in Mainbox, then print the message specified\r
465 by Format and the associated variable argument list to the debug port.\r
466\r
467 @param[in] ErrorLevel The error level of the debug message.\r
468 @param[in] Format Format string for the debug message to print.\r
469 @param[in] ... Variable argument list whose contents are accessed \r
470 based on the format string specified by Format.\r
471\r
472**/\r
473VOID\r
474EFIAPI\r
475DebugAgentMsgPrint (\r
476 IN UINT8 ErrorLevel,\r
477 IN CHAR8 *Format,\r
478 ...\r
479 )\r
480{\r
93c0bdec 481 CHAR8 Buffer[DEBUG_DATA_MAXIMUM_REAL_DATA];\r
482 VA_LIST Marker;\r
483\r
93c0bdec 484 //\r
485 // Check driver debug mask value and global mask\r
486 //\r
b422b62c 487 if ((ErrorLevel & GetDebugFlag (DEBUG_AGENT_FLAG_PRINT_ERROR_LEVEL)) == 0) {\r
93c0bdec 488 return;\r
18b144ea 489 }\r
93c0bdec 490\r
491 //\r
492 // Convert the DEBUG() message to an ASCII String\r
493 //\r
494 VA_START (Marker, Format);\r
495 AsciiVSPrint (Buffer, sizeof (Buffer), Format, Marker);\r
496 VA_END (Marker);\r
497\r
498 SendDebugMsgPacket (Buffer, AsciiStrLen (Buffer));\r
18b144ea 499}\r
500\r
501/**\r
93c0bdec 502 Prints a debug message to the debug output device if the specified error level is enabled.\r
503\r
504 If any bit in ErrorLevel is also set in DebugPrintErrorLevelLib function \r
505 GetDebugPrintErrorLevel (), then print the message specified by Format and the \r
506 associated variable argument list to the debug output device.\r
507\r
508 If Format is NULL, then ASSERT().\r
509\r
510 @param[in] ErrorLevel The error level of the debug message.\r
511 @param[in] IsSend Flag of debug message to declare that the data is being sent or being received.\r
512 @param[in] Data Variable argument list whose contents are accessed \r
513 @param[in] Length based on the format string specified by Format.\r
18b144ea 514\r
515**/\r
516VOID\r
93c0bdec 517EFIAPI\r
518DebugAgentDataMsgPrint (\r
519 IN UINT8 ErrorLevel,\r
520 IN BOOLEAN IsSend,\r
521 IN UINT8 *Data,\r
522 IN UINT8 Length \r
18b144ea 523 )\r
524{\r
93c0bdec 525 CHAR8 Buffer[DEBUG_DATA_MAXIMUM_REAL_DATA];\r
526 CHAR8 *DestBuffer;\r
527 UINTN Index;\r
18b144ea 528\r
93c0bdec 529 //\r
530 // Check driver debug mask value and global mask\r
531 //\r
b422b62c 532 if ((ErrorLevel & GetDebugFlag (DEBUG_AGENT_FLAG_PRINT_ERROR_LEVEL)) == 0) {\r
93c0bdec 533 return;\r
534 }\r
535\r
536 DestBuffer = Buffer;\r
537 if (IsSend) {\r
538 DestBuffer += AsciiSPrint (DestBuffer, DEBUG_DATA_MAXIMUM_REAL_DATA, "Sent data [ ");\r
539 } else {\r
540 DestBuffer += AsciiSPrint (DestBuffer, DEBUG_DATA_MAXIMUM_REAL_DATA, "Received data [ ");\r
541 }\r
18b144ea 542\r
93c0bdec 543 Index = 0;\r
544 while (TRUE) {\r
545 if (DestBuffer - Buffer > DEBUG_DATA_MAXIMUM_REAL_DATA - 6) {\r
546 //\r
547 // If there was no enough space in buffer, send out the debug message, \r
548 // reserving 6 bytes is for the last data and end characters "]\n".\r
549 //\r
550 SendDebugMsgPacket (Buffer, DestBuffer - Buffer);\r
551 DestBuffer = Buffer;\r
552 }\r
553 DestBuffer += AsciiSPrint (DestBuffer, DEBUG_DATA_MAXIMUM_REAL_DATA - (DestBuffer - Buffer), "%02x ", Data[Index]);\r
554 Index ++;\r
555 if (Index >= Length) {\r
b422b62c 556 //\r
93c0bdec 557 // The last character of debug message has been foramtted in buffer\r
558 //\r
559 DestBuffer += AsciiSPrint(DestBuffer, DEBUG_DATA_MAXIMUM_REAL_DATA - (DestBuffer - Buffer), "]\n");\r
560 SendDebugMsgPacket (Buffer, DestBuffer - Buffer);\r
561 break;\r
562 }\r
563 }\r
18b144ea 564}\r
565\r
b422b62c 566/**\r
567 Read remaing debug packet except for the start symbol\r
568\r
569 @param[in] Handle Pointer to Debug Port handle.\r
570 @param[in, out] DebugHeader Debug header buffer including start symbol.\r
571\r
572 @retval EFI_SUCCESS Read the symbol in BreakSymbol.\r
573 @retval EFI_CRC_ERROR CRC check fail.\r
574 @retval EFI_TIMEOUT Timeout occurs when reading debug packet.\r
4692bc0b 575 @retval EFI_DEVICE_ERROR Receive the old or responsed packet.\r
b422b62c 576\r
577**/\r
578EFI_STATUS\r
579ReadRemainingBreakPacket (\r
580 IN DEBUG_PORT_HANDLE Handle,\r
581 IN OUT DEBUG_PACKET_HEADER *DebugHeader\r
582 )\r
583{\r
584 UINT16 Crc;\r
4692bc0b
JF
585 DEBUG_AGENT_MAILBOX *Mailbox;\r
586\r
b422b62c 587 //\r
588 // Has received start symbol, try to read the rest part\r
589 //\r
590 if (DebugPortReadBuffer (Handle, &DebugHeader->Command, sizeof (DEBUG_PACKET_HEADER) - 1, READ_PACKET_TIMEOUT) == 0) {\r
591 //\r
592 // Timeout occur, exit\r
593 //\r
594 DebugAgentMsgPrint (DEBUG_AGENT_WARNING, "Timeout in Debug Timer interrupt\n");\r
595 return EFI_TIMEOUT;\r
596 }\r
597\r
598 Crc = DebugHeader->Crc;\r
599 DebugHeader->Crc = 0;\r
600 if (CalculateCrc16 ((UINT8 *)DebugHeader, DebugHeader->Length, 0) != Crc) {\r
601 DebugAgentMsgPrint (DEBUG_AGENT_WARNING, "Debug Timer CRC (%x) against (%x)\n", Crc, CalculateCrc16 ((UINT8 *) &DebugHeader, DebugHeader->Length, 0));\r
602 DebugAgentDataMsgPrint (DEBUG_AGENT_VERBOSE, FALSE, (UINT8 *)DebugHeader, DebugHeader->Length);\r
603 return EFI_CRC_ERROR;\r
604 }\r
4692bc0b 605 Mailbox = GetMailboxPointer();\r
b8b86ec6 606 if (((DebugHeader->Command & DEBUG_COMMAND_RESPONSE) == 0) &&\r
4692bc0b
JF
607 (DebugHeader->SequenceNo == (UINT8) (Mailbox->HostSequenceNo + 1))) {\r
608 //\r
609 // Only updagte HostSequenceNo for new command packet \r
610 //\r
611 UpdateMailboxContent (Mailbox, DEBUG_MAILBOX_HOST_SEQUENCE_NO_INDEX, DebugHeader->SequenceNo);\r
612 return EFI_SUCCESS;\r
613 } else {\r
614 //\r
615 // If one old command or response packet received, skip it\r
616 //\r
617 return EFI_DEVICE_ERROR;\r
618 }\r
b422b62c 619}\r
93c0bdec 620\r
18b144ea 621/**\r
93c0bdec 622 Check if HOST is attached based on Mailbox.\r
18b144ea 623\r
93c0bdec 624 @retval TRUE HOST is attached.\r
625 @retval FALSE HOST is not attached.\r
18b144ea 626\r
93c0bdec 627**/\r
628BOOLEAN\r
629IsHostAttached (\r
630 VOID\r
631 )\r
632{\r
b422b62c 633 return (BOOLEAN) (GetDebugFlag (DEBUG_AGENT_FLAG_HOST_ATTACHED) == 1);\r
93c0bdec 634}\r
635\r
636/**\r
637 Set HOST connect flag in Mailbox.\r
638\r
639 @param[in] Attached Attach status.\r
640 \r
18b144ea 641**/\r
642VOID\r
93c0bdec 643SetHostAttached (\r
644 IN BOOLEAN Attached\r
18b144ea 645 )\r
646{\r
93c0bdec 647 DebugAgentMsgPrint (DEBUG_AGENT_INFO, "Attach status is %d\n", Attached);\r
b422b62c 648 SetDebugFlag (DEBUG_AGENT_FLAG_HOST_ATTACHED, (UINT32)Attached);\r
93c0bdec 649}\r
650\r
651/**\r
652 Set debug setting of Debug Agent in Mailbox.\r
653\r
654 @param DebugSetting Pointer to Debug Setting defined by transfer protocol.\r
655 \r
656 @retval RETURN_SUCCESS The setting is set successfully.\r
657 @retval RETURN_UNSUPPORTED The Key value is not supported.\r
658\r
659**/\r
660RETURN_STATUS\r
661SetDebugSetting (\r
662 IN DEBUG_DATA_SET_DEBUG_SETTING *DebugSetting \r
663 )\r
664{\r
665 RETURN_STATUS Status;\r
18b144ea 666\r
93c0bdec 667 Status = RETURN_SUCCESS;\r
668 switch (DebugSetting->Key) {\r
669 case DEBUG_AGENT_SETTING_SMM_ENTRY_BREAK:\r
b422b62c 670 SetDebugFlag (DEBUG_AGENT_FLAG_BREAK_ON_NEXT_SMI, DebugSetting->Value);\r
93c0bdec 671 break;\r
672 case DEBUG_AGENT_SETTING_PRINT_ERROR_LEVEL:\r
b422b62c 673 SetDebugFlag (DEBUG_AGENT_FLAG_PRINT_ERROR_LEVEL, DebugSetting->Value);\r
674 break;\r
675 case DEBUG_AGENT_SETTING_BOOT_SCRIPT_ENTRY_BREAK:\r
676 SetDebugFlag (DEBUG_AGENT_FLAG_BREAK_BOOT_SCRIPT, DebugSetting->Value);\r
93c0bdec 677 break;\r
678 default:\r
679 Status = RETURN_UNSUPPORTED;\r
18b144ea 680 }\r
93c0bdec 681 return Status;\r
18b144ea 682}\r
683\r
684/**\r
685 Exectue GO command.\r
686\r
687 @param[in] CpuContext Pointer to saved CPU context.\r
688\r
689**/\r
690VOID\r
691CommandGo (\r
692 IN DEBUG_CPU_CONTEXT *CpuContext\r
693 )\r
694{\r
695 IA32_EFLAGS32 *Eflags;\r
696\r
697 Eflags = (IA32_EFLAGS32 *) &CpuContext->Eflags;\r
698 Eflags->Bits.TF = 0;\r
699 Eflags->Bits.RF = 1;\r
700}\r
701\r
702/**\r
703 Exectue Stepping command.\r
704\r
705 @param[in] CpuContext Pointer to saved CPU context.\r
706\r
707**/\r
708VOID\r
709CommandStepping (\r
710 IN DEBUG_CPU_CONTEXT *CpuContext\r
711 )\r
712{\r
713 IA32_EFLAGS32 *Eflags;\r
714\r
715 Eflags = (IA32_EFLAGS32 *) &CpuContext->Eflags;\r
716 Eflags->Bits.TF = 1;\r
717 Eflags->Bits.RF = 1;\r
718}\r
719\r
720/**\r
721 Set debug register for hardware breakpoint.\r
722\r
723 @param[in] CpuContext Pointer to saved CPU context.\r
724 @param[in] SetHwBreakpoint Hardware breakpoint to be set.\r
725\r
726**/\r
727VOID\r
728SetDebugRegister (\r
729 IN DEBUG_CPU_CONTEXT *CpuContext,\r
730 IN DEBUG_DATA_SET_HW_BREAKPOINT *SetHwBreakpoint\r
731 )\r
732{\r
733 UINT8 RegisterIndex;\r
734 UINTN Dr7Value;\r
735\r
736 RegisterIndex = SetHwBreakpoint->Type.Index;\r
737\r
738 //\r
739 // Set debug address\r
740 //\r
741 * ((UINTN *) &CpuContext->Dr0 + RegisterIndex) = (UINTN) SetHwBreakpoint->Address;\r
742\r
743 Dr7Value = CpuContext->Dr7;\r
744\r
745 //\r
746 // Enable Gx, Lx\r
747 //\r
748 Dr7Value |= 0x3 << (RegisterIndex * 2);\r
749 //\r
750 // Set RWx and Lenx\r
751 //\r
93c0bdec 752 Dr7Value &= ~(0xf << (16 + RegisterIndex * 4));\r
753 Dr7Value |= (UINTN) ((SetHwBreakpoint->Type.Length << 2) | SetHwBreakpoint->Type.Access) << (16 + RegisterIndex * 4);\r
18b144ea 754 //\r
755 // Enable GE, LE\r
756 //\r
757 Dr7Value |= 0x300;\r
758\r
759 CpuContext->Dr7 = Dr7Value;\r
760}\r
761\r
762/**\r
763 Clear debug register for hardware breakpoint.\r
764\r
765 @param[in] CpuContext Pointer to saved CPU context.\r
766 @param[in] ClearHwBreakpoint Hardware breakpoint to be cleared.\r
767\r
768**/\r
769VOID\r
770ClearDebugRegister (\r
771 IN DEBUG_CPU_CONTEXT *CpuContext,\r
772 IN DEBUG_DATA_CLEAR_HW_BREAKPOINT *ClearHwBreakpoint\r
773 )\r
774{\r
775 if ((ClearHwBreakpoint->IndexMask & BIT0) != 0) {\r
776 CpuContext->Dr0 = 0;\r
777 CpuContext->Dr7 &= ~(0x3 << 0);\r
778 }\r
779 if ((ClearHwBreakpoint->IndexMask & BIT1) != 0) {\r
780 CpuContext->Dr1 = 0;\r
781 CpuContext->Dr7 &= ~(0x3 << 2);\r
782 }\r
783 if ((ClearHwBreakpoint->IndexMask & BIT2) != 0) {\r
784 CpuContext->Dr2 = 0;\r
785 CpuContext->Dr7 &= ~(0x3 << 4);\r
786 }\r
787 if ((ClearHwBreakpoint->IndexMask & BIT3) != 0) {\r
788 CpuContext->Dr3 = 0;\r
789 CpuContext->Dr7 &= ~(0x3 << 6);\r
790 }\r
791}\r
792\r
93c0bdec 793\r
18b144ea 794/**\r
93c0bdec 795 Return the offset of FP / MMX / XMM registers in the FPU saved state by register index.\r
18b144ea 796\r
93c0bdec 797 @param[in] Index Register index.\r
798 @param[out] Width Register width returned.\r
799\r
800 @return Offset in the FPU Save State.\r
801\r
802**/\r
803UINT16\r
804ArchReadFxStatOffset (\r
805 IN UINT8 Index,\r
806 OUT UINT8 *Width\r
807 )\r
808{\r
809 if (Index < SOFT_DEBUGGER_REGISTER_ST0) {\r
810 switch (Index) {\r
811 case SOFT_DEBUGGER_REGISTER_FP_FCW:\r
812 *Width = (UINT8) sizeof (UINT16);\r
813 return OFFSET_OF(DEBUG_DATA_FX_SAVE_STATE, Fcw);\r
814\r
815 case SOFT_DEBUGGER_REGISTER_FP_FSW:\r
816 *Width = (UINT8) sizeof (UINT16);\r
817 return OFFSET_OF(DEBUG_DATA_FX_SAVE_STATE, Fsw);\r
818\r
819 case SOFT_DEBUGGER_REGISTER_FP_FTW:\r
820 *Width = (UINT8) sizeof (UINT16);\r
821 return OFFSET_OF(DEBUG_DATA_FX_SAVE_STATE, Ftw);\r
822\r
823 case SOFT_DEBUGGER_REGISTER_FP_OPCODE:\r
824 *Width = (UINT8) sizeof (UINT16);\r
825 return OFFSET_OF(DEBUG_DATA_FX_SAVE_STATE, Opcode);\r
826\r
827 case SOFT_DEBUGGER_REGISTER_FP_EIP:\r
828 *Width = (UINT8) sizeof (UINT32);\r
829 return OFFSET_OF(DEBUG_DATA_FX_SAVE_STATE, Eip);\r
830\r
831 case SOFT_DEBUGGER_REGISTER_FP_CS:\r
832 *Width = (UINT8) sizeof (UINT16);\r
833 return OFFSET_OF(DEBUG_DATA_FX_SAVE_STATE, Cs);\r
834\r
835 case SOFT_DEBUGGER_REGISTER_FP_DATAOFFSET:\r
836 *Width = (UINT8) sizeof (UINT32);\r
837 return OFFSET_OF(DEBUG_DATA_FX_SAVE_STATE, DataOffset);\r
838\r
839 case SOFT_DEBUGGER_REGISTER_FP_DS:\r
840 *Width = (UINT8) sizeof (UINT16);\r
841 return OFFSET_OF(DEBUG_DATA_FX_SAVE_STATE, Ds);\r
842\r
843 case SOFT_DEBUGGER_REGISTER_FP_MXCSR:\r
844 *Width = (UINT8) sizeof (UINT32);\r
845 return OFFSET_OF(DEBUG_DATA_FX_SAVE_STATE, Mxcsr);\r
846\r
847 case SOFT_DEBUGGER_REGISTER_FP_MXCSR_MASK:\r
848 *Width = (UINT8) sizeof (UINT32);\r
849 return OFFSET_OF(DEBUG_DATA_FX_SAVE_STATE, Mxcsr_Mask);\r
850 }\r
851 }\r
852\r
853 if (Index <= SOFT_DEBUGGER_REGISTER_ST7) {\r
854 *Width = 10;\r
855 } else if (Index <= SOFT_DEBUGGER_REGISTER_XMM15) {\r
856 *Width = 16;\r
857 } else {\r
858 //\r
859 // MMX register\r
860 //\r
861 *Width = 8;\r
862 Index -= SOFT_DEBUGGER_REGISTER_MM0 - SOFT_DEBUGGER_REGISTER_ST0;\r
863 }\r
864\r
865 return OFFSET_OF (DEBUG_DATA_FX_SAVE_STATE, St0Mm0) + (Index - SOFT_DEBUGGER_REGISTER_ST0) * 16;\r
866}\r
867\r
868/**\r
869 Return the pointer of the register value in the CPU saved context.\r
870\r
871 @param[in] CpuContext Pointer to saved CPU context.\r
872 @param[in] Index Register index value.\r
873 @param[out] Width Data width to read.\r
874\r
875 @return The pointer in the CPU saved context.\r
876\r
877**/\r
878UINT8 *\r
879ArchReadRegisterBuffer (\r
880 IN DEBUG_CPU_CONTEXT *CpuContext,\r
881 IN UINT8 Index,\r
882 OUT UINT8 *Width\r
883 )\r
884{\r
885 UINT8 *Buffer;\r
886\r
887 if (Index < SOFT_DEBUGGER_REGISTER_FP_BASE) {\r
888 Buffer = (UINT8 *) CpuContext + OFFSET_OF (DEBUG_CPU_CONTEXT, Dr0) + Index * sizeof (UINTN);\r
889 *Width = (UINT8) sizeof (UINTN);\r
890 } else {\r
891 //\r
892 // FPU/MMX/XMM registers\r
893 //\r
894 Buffer = (UINT8 *) CpuContext + OFFSET_OF (DEBUG_CPU_CONTEXT, FxSaveState) + ArchReadFxStatOffset (Index, Width);\r
895 }\r
896\r
897 return Buffer;\r
898}\r
899\r
900/**\r
901 Send the packet without data to HOST.\r
902\r
903 @param[in] CommandType Type of Command.\r
b422b62c 904 @param[in] SequenceNo Sequence number.\r
18b144ea 905\r
906**/\r
907VOID\r
93c0bdec 908SendPacketWithoutData (\r
b422b62c 909 IN UINT8 CommandType,\r
910 IN UINT8 SequenceNo\r
18b144ea 911 )\r
912{\r
93c0bdec 913 DEBUG_PACKET_HEADER DebugHeader;\r
18b144ea 914 DEBUG_PORT_HANDLE Handle;\r
915\r
916 Handle = GetDebugPortHandle();\r
917\r
93c0bdec 918 DebugHeader.StartSymbol = DEBUG_STARTING_SYMBOL_NORMAL;\r
919 DebugHeader.Command = CommandType;\r
920 DebugHeader.Length = sizeof (DEBUG_PACKET_HEADER);\r
b422b62c 921 DebugHeader.SequenceNo = SequenceNo;\r
922 DebugHeader.Crc = 0;\r
923 DebugHeader.Crc = CalculateCrc16 ((UINT8 *)&DebugHeader, sizeof (DEBUG_PACKET_HEADER), 0);\r
18b144ea 924\r
93c0bdec 925 DebugAgentDataMsgPrint (DEBUG_AGENT_VERBOSE, TRUE, (UINT8 *) &DebugHeader, DebugHeader.Length);\r
926 DebugPortWriteBuffer (Handle, (UINT8 *) &DebugHeader, DebugHeader.Length);\r
927}\r
928\r
929/**\r
930 Send acknowledge packet to HOST.\r
931\r
932 @param[in] AckCommand Type of Acknowledge packet.\r
933\r
934**/\r
935VOID\r
936SendAckPacket (\r
937 IN UINT8 AckCommand\r
938 )\r
939{\r
b422b62c 940 UINT8 SequenceNo;\r
941 DEBUG_AGENT_MAILBOX *Mailbox;\r
942\r
93c0bdec 943 if (AckCommand != DEBUG_COMMAND_OK) {\r
b422b62c 944 //\r
945 // This is not ACK OK packet\r
946 //\r
93c0bdec 947 DebugAgentMsgPrint (DEBUG_AGENT_ERROR, "Send ACK(%d)\n", AckCommand);\r
948 }\r
b422b62c 949 Mailbox = GetMailboxPointer();\r
950 SequenceNo = Mailbox->HostSequenceNo;\r
951 DebugAgentMsgPrint (DEBUG_AGENT_INFO, "SendAckPacket: SequenceNo = %x\n", SequenceNo);\r
952 SendPacketWithoutData (AckCommand, SequenceNo);\r
953 UpdateMailboxContent (Mailbox, DEBUG_MAILBOX_LAST_ACK, AckCommand);\r
18b144ea 954}\r
955\r
956/**\r
b422b62c 957 Receive valid packet from HOST.\r
18b144ea 958\r
b422b62c 959 @param[out] InputPacket Buffer to receive packet.\r
960 @param[out] BreakReceived TRUE means break-in symbol received.\r
961 FALSE means break-in symbol not received.\r
962 @param[out] IncompatibilityFlag If IncompatibilityFlag is not NULL, return\r
963 TRUE: Compatible packet received.\r
964 FALSE: Incompatible packet received.\r
965 @param[in] Timeout Time out value to wait for acknowlege from HOST.\r
966 The unit is microsecond.\r
967 @param[in] SkipStartSymbol TRUE: Skip time out when reading start symbol.\r
968 FALSE: Does not Skip time out when reading start symbol.\r
18b144ea 969\r
b422b62c 970 @retval RETURN_SUCCESS A valid package was reveived in InputPacket.\r
971 @retval RETURN_TIMEOUT Timeout occurs.\r
18b144ea 972\r
973**/\r
974RETURN_STATUS\r
b422b62c 975ReceivePacket (\r
976 OUT UINT8 *InputPacket,\r
977 OUT BOOLEAN *BreakReceived,\r
978 OUT BOOLEAN *IncompatibilityFlag, OPTIONAL\r
979 IN UINTN Timeout,\r
980 IN BOOLEAN SkipStartSymbol\r
18b144ea 981 )\r
982{\r
b422b62c 983 DEBUG_PACKET_HEADER *DebugHeader;\r
984 UINTN Received;\r
985 DEBUG_PORT_HANDLE Handle;\r
986 UINT16 Crc;\r
987 UINTN TimeoutForStartSymbol;\r
18b144ea 988\r
989 Handle = GetDebugPortHandle();\r
b422b62c 990 if (SkipStartSymbol) {\r
991 TimeoutForStartSymbol = 0;\r
992 } else {\r
993 TimeoutForStartSymbol = Timeout;\r
994 }\r
995 \r
996 DebugHeader = (DEBUG_PACKET_HEADER *) InputPacket;\r
18b144ea 997 while (TRUE) {\r
b422b62c 998 //\r
999 // Find the valid start symbol\r
1000 //\r
1001 Received = DebugPortReadBuffer (Handle, &DebugHeader->StartSymbol, sizeof (DebugHeader->StartSymbol), TimeoutForStartSymbol);\r
1002 if (Received < sizeof (DebugHeader->StartSymbol)) {\r
1003 DebugAgentMsgPrint (DEBUG_AGENT_WARNING, "DebugPortReadBuffer(StartSymbol) timeout\n");\r
18b144ea 1004 return RETURN_TIMEOUT;\r
1005 }\r
b422b62c 1006\r
1007 if (DebugHeader->StartSymbol != DEBUG_STARTING_SYMBOL_NORMAL) {\r
1008 DebugAgentMsgPrint (DEBUG_AGENT_WARNING, "Invalid start symbol received [%02x]\n", DebugHeader->StartSymbol);\r
1009 continue;\r
18b144ea 1010 }\r
18b144ea 1011\r
93c0bdec 1012 //\r
b422b62c 1013 // Read Package header till field Length\r
93c0bdec 1014 //\r
b422b62c 1015 Received = DebugPortReadBuffer (\r
1016 Handle,\r
1017 &DebugHeader->Command,\r
1018 OFFSET_OF (DEBUG_PACKET_HEADER, Length) + sizeof (DebugHeader->Length) - sizeof (DebugHeader->StartSymbol),\r
1019 Timeout\r
1020 );\r
1021 if (Received == 0) {\r
1022 DebugAgentMsgPrint (DEBUG_AGENT_ERROR, "DebugPortReadBuffer(Command) timeout\n");\r
93c0bdec 1023 return RETURN_TIMEOUT;\r
1024 }\r
b422b62c 1025 if (DebugHeader->Length < sizeof (DEBUG_PACKET_HEADER)) {\r
1026 if (IncompatibilityFlag != NULL) {\r
1027 //\r
1028 // This is one old version debug packet format, set Incompatibility flag\r
1029 //\r
1030 *IncompatibilityFlag = TRUE;\r
1031 } else {\r
1032 //\r
1033 // Skip the bad small packet\r
1034 //\r
1035 continue;\r
1036 }\r
1037 } else {\r
1038 //\r
1039 // Read the payload data include the CRC field\r
1040 //\r
1041 Received = DebugPortReadBuffer (Handle, &DebugHeader->SequenceNo, (UINT8) (DebugHeader->Length - OFFSET_OF (DEBUG_PACKET_HEADER, SequenceNo)), Timeout);\r
1042 if (Received == 0) {\r
1043 DebugAgentMsgPrint (DEBUG_AGENT_ERROR, "DebugPortReadBuffer(SequenceNo) timeout\n");\r
1044 return RETURN_TIMEOUT;\r
1045 }\r
1046 //\r
1047 // Calculate the CRC of Debug Packet\r
1048 //\r
1049 Crc = DebugHeader->Crc;\r
1050 DebugHeader->Crc = 0;\r
1051 if (Crc == CalculateCrc16 ((UINT8 *) DebugHeader, DebugHeader->Length, 0)) {\r
1052 break;\r
1053 }\r
1054 DebugAgentMsgPrint (DEBUG_AGENT_WARNING, "CRC Error (received CRC is %x)\n", Crc);\r
1055 DebugAgentDataMsgPrint (DEBUG_AGENT_VERBOSE, FALSE, (UINT8 *) DebugHeader, DebugHeader->Length);\r
1056 }\r
93c0bdec 1057 }\r
1058\r
b422b62c 1059 DebugAgentDataMsgPrint (DEBUG_AGENT_VERBOSE, FALSE, (UINT8 *) DebugHeader, DebugHeader->Length);\r
1060\r
18b144ea 1061 return RETURN_SUCCESS;\r
1062}\r
1063\r
1064/**\r
1065 Receive acknowledge packet OK from HOST in specified time.\r
1066\r
b422b62c 1067 @param[in] Command The command type issued by TARGET.\r
1068 @param[in] Timeout Time out value to wait for acknowlege from HOST.\r
1069 The unit is microsecond.\r
1070 @param[out] BreakReceived If BreakReceived is not NULL,\r
1071 TRUE is retured if break-in symbol received.\r
1072 FALSE is retured if break-in symbol not received.\r
1073 @param[out] IncompatibilityFlag If IncompatibilityFlag is not NULL, return\r
1074 TRUE: Compatible packet received.\r
1075 FALSE: Incompatible packet received.\r
18b144ea 1076\r
1077 @retval RETRUEN_SUCCESS Succeed to receive acknowlege packet from HOST,\r
1078 the type of acknowlege packet saved in Ack.\r
1079 @retval RETURN_TIMEOUT Specified timeout value was up.\r
1080\r
1081**/\r
1082RETURN_STATUS\r
93c0bdec 1083SendCommandAndWaitForAckOK (\r
1084 IN UINT8 Command,\r
1085 IN UINTN Timeout,\r
1086 OUT BOOLEAN *BreakReceived, OPTIONAL\r
b422b62c 1087 OUT BOOLEAN *IncompatibilityFlag OPTIONAL\r
18b144ea 1088 )\r
1089{\r
93c0bdec 1090 RETURN_STATUS Status;\r
b422b62c 1091 UINT8 InputPacketBuffer[DEBUG_DATA_UPPER_LIMIT];\r
1092 DEBUG_PACKET_HEADER *DebugHeader;\r
1093 UINT8 SequenceNo;\r
1094 UINT8 HostSequenceNo;\r
1095 UINT8 RetryCount;\r
1096\r
1097 RetryCount = 3;\r
1098 DebugHeader = (DEBUG_PACKET_HEADER *) InputPacketBuffer;\r
1099 Status = RETURN_TIMEOUT;\r
1100 while (RetryCount > 0) {\r
1101 SequenceNo = GetMailboxPointer()->SequenceNo;\r
1102 HostSequenceNo = GetMailboxPointer()->HostSequenceNo;\r
1103 SendPacketWithoutData (Command, SequenceNo);\r
1104 Status = ReceivePacket ((UINT8 *) DebugHeader, BreakReceived, IncompatibilityFlag, Timeout, FALSE);\r
1105 if (Status == RETURN_TIMEOUT) {\r
1106 if (Command == DEBUG_COMMAND_INIT_BREAK) {\r
1107 RetryCount--;\r
1108 } else {\r
1109 DebugAgentMsgPrint (DEBUG_AGENT_WARNING, "TARGET: Timeout when waiting for ACK packet.\n");\r
1110 }\r
93c0bdec 1111 continue;\r
1112 }\r
b422b62c 1113 ASSERT_EFI_ERROR (Status);\r
93c0bdec 1114 //\r
b422b62c 1115 // Status == RETURN_SUCCESS\r
93c0bdec 1116 //\r
b422b62c 1117 if (DebugHeader->Command == DEBUG_COMMAND_OK && DebugHeader->SequenceNo == SequenceNo) {\r
1118 //\r
1119 // Received Ack OK\r
1120 //\r
1121 UpdateMailboxContent (GetMailboxPointer(), DEBUG_MAILBOX_SEQUENCE_NO_INDEX, ++SequenceNo);\r
1122 return Status;\r
18b144ea 1123 }\r
b422b62c 1124 if (DebugHeader->Command == DEBUG_COMMAND_GO && (DebugHeader->SequenceNo == HostSequenceNo || Command == DEBUG_COMMAND_INIT_BREAK)) {\r
1125 //\r
1126 // Received Old GO\r
1127 //\r
1128 if (Command == DEBUG_COMMAND_INIT_BREAK) {\r
1129 DebugAgentMsgPrint (DEBUG_AGENT_WARNING, "TARGET: Receive GO() in last boot\n");\r
1130 }\r
1131 SendPacketWithoutData (DEBUG_COMMAND_OK, DebugHeader->SequenceNo);\r
93c0bdec 1132 }\r
18b144ea 1133 }\r
1134\r
b422b62c 1135 ASSERT (Command == DEBUG_COMMAND_INIT_BREAK);\r
1136 return Status;\r
18b144ea 1137}\r
1138\r
1139/**\r
1140 Get current break cause.\r
1141\r
1142 @param[in] Vector Vector value of exception or interrupt.\r
1143 @param[in] CpuContext Pointer to save CPU context.\r
1144\r
1145 @return The type of break cause defined by XXXX\r
1146\r
1147**/\r
1148UINT8\r
1149GetBreakCause (\r
1150 IN UINTN Vector,\r
1151 IN DEBUG_CPU_CONTEXT *CpuContext\r
1152 )\r
1153{\r
1154 UINT8 Cause;\r
1155\r
1156 Cause = DEBUG_DATA_BREAK_CAUSE_UNKNOWN;\r
1157\r
1158 switch (Vector) {\r
1159 case DEBUG_INT1_VECTOR:\r
1160 case DEBUG_INT3_VECTOR:\r
1161\r
1162 if (Vector == DEBUG_INT1_VECTOR) {\r
1163 //\r
1164 // INT 1\r
1165 //\r
1166 if ((CpuContext->Dr6 & BIT14) != 0) {\r
1167 Cause = DEBUG_DATA_BREAK_CAUSE_STEPPING;\r
0a16169b 1168 //\r
1169 // If it's single step, no need to check DR0, to ensure single step work in PeCoffExtraActionLib\r
1170 // (right after triggering a breakpoint to report image load/unload).\r
1171 //\r
1172 return Cause;\r
18b144ea 1173\r
1174 } else {\r
1175 Cause = DEBUG_DATA_BREAK_CAUSE_HW_BREAKPOINT;\r
1176 }\r
1177 } else {\r
1178 //\r
1179 // INT 3\r
1180 //\r
1181 Cause = DEBUG_DATA_BREAK_CAUSE_SW_BREAKPOINT;\r
1182 }\r
1183\r
1184 switch (CpuContext->Dr0) {\r
1185 case IMAGE_LOAD_SIGNATURE:\r
1186 case IMAGE_UNLOAD_SIGNATURE:\r
1187\r
1188 if (CpuContext->Dr3 == IO_PORT_BREAKPOINT_ADDRESS) {\r
1189\r
1190 Cause = (UINT8) ((CpuContext->Dr0 == IMAGE_LOAD_SIGNATURE) ? \r
1191 DEBUG_DATA_BREAK_CAUSE_IMAGE_LOAD : DEBUG_DATA_BREAK_CAUSE_IMAGE_UNLOAD);\r
1192 }\r
1193 break;\r
1194\r
1195 case SOFT_INTERRUPT_SIGNATURE:\r
1196 \r
1197 if (CpuContext->Dr1 == MEMORY_READY_SIGNATURE) {\r
1198 Cause = DEBUG_DATA_BREAK_CAUSE_MEMORY_READY;\r
1199 CpuContext->Dr0 = 0;\r
1200 } else if (CpuContext->Dr1 == SYSTEM_RESET_SIGNATURE) {\r
1201 Cause = DEBUG_DATA_BREAK_CAUSE_SYSTEM_RESET;\r
1202 CpuContext->Dr0 = 0;\r
1203 }\r
1204 break;\r
1205\r
1206 default:\r
1207 break;\r
1208\r
1209 }\r
1210\r
1211 break;\r
1212\r
1213 case DEBUG_TIMER_VECTOR:\r
1214 Cause = DEBUG_DATA_BREAK_CAUSE_USER_HALT;\r
1215 break;\r
1216\r
1217 default:\r
1218 if (Vector < 20) {\r
b422b62c 1219 if (GetDebugFlag (DEBUG_AGENT_FLAG_STEPPING) == 1) {\r
93c0bdec 1220 //\r
1221 // If stepping command is executing\r
1222 //\r
1223 Cause = DEBUG_DATA_BREAK_CAUSE_STEPPING;\r
1224 } else {\r
1225 Cause = DEBUG_DATA_BREAK_CAUSE_EXCEPTION;\r
1226 }\r
18b144ea 1227 }\r
1228 break;\r
1229 }\r
1230\r
1231 return Cause;\r
1232}\r
1233\r
1234/**\r
845a7fe0 1235 Copy memory from source to destination with specified width.\r
1236\r
1237 @param[out] Dest A pointer to the destination buffer of the memory copy.\r
1238 @param[in] Src A pointer to the source buffer of the memory copy.\r
1239 @param[in] Count The number of data with specified width to copy from source to destination.\r
1240 @param[in] Width Data width in byte.\r
1241\r
1242**/\r
1243VOID\r
1244CopyMemByWidth (\r
1245 OUT UINT8 *Dest,\r
1246 IN UINT8 *Src,\r
1247 IN UINT16 Count,\r
1248 IN UINT8 Width\r
1249 )\r
1250{\r
1251 UINT8 *Destination;\r
1252 UINT8 *Source;\r
1253 INT8 Step;\r
1254\r
1255 if (Src > Dest) {\r
1256 Destination = Dest;\r
1257 Source = Src;\r
1258 Step = Width;\r
1259 } else {\r
1260 //\r
1261 // Copy memory from tail to avoid memory overlap\r
1262 //\r
1263 Destination = Dest + (Count - 1) * Width;\r
1264 Source = Src + (Count - 1) * Width;\r
1265 Step = -Width;\r
1266 }\r
1267\r
1268 while (Count-- != 0) {\r
1269 switch (Width) {\r
1270 case 1:\r
1271 *(UINT8 *) Destination = MmioRead8 ((UINTN) Source);\r
1272 break;\r
1273 case 2:\r
1274 *(UINT16 *) Destination = MmioRead16 ((UINTN) Source);\r
1275 break;\r
1276 case 4:\r
1277 *(UINT32 *) Destination = MmioRead32 ((UINTN) Source);\r
1278 break;\r
1279 case 8:\r
1280 *(UINT64 *) Destination = MmioRead64 ((UINTN) Source);\r
1281 break;\r
1282 default:\r
1283 ASSERT (FALSE);\r
1284 }\r
1285 Source += Step;\r
1286 Destination += Step;\r
1287 }\r
1288}\r
1289\r
1290/**\r
1291 Read memory with speicifed width and send packet with response data to HOST.\r
18b144ea 1292\r
18b144ea 1293 @param[in] Data Pointer to response data buffer.\r
845a7fe0 1294 @param[in] Count The number of data with specified Width.\r
1295 @param[in] Width Data width in byte.\r
18b144ea 1296\r
1297 @retval RETURN_SUCCESS Response data was sent successfully.\r
18b144ea 1298\r
1299**/\r
1300RETURN_STATUS\r
845a7fe0 1301ReadMemoryAndSendResponsePacket (\r
18b144ea 1302 IN UINT8 *Data,\r
845a7fe0 1303 IN UINT16 Count,\r
1304 IN UINT8 Width\r
18b144ea 1305 )\r
1306{\r
b422b62c 1307 RETURN_STATUS Status;\r
93c0bdec 1308 DEBUG_PACKET_HEADER *DebugHeader;\r
18b144ea 1309 BOOLEAN LastPacket;\r
b422b62c 1310 DEBUG_PACKET_HEADER *AckDebugHeader;\r
845a7fe0 1311 UINT8 DebugPacket[DEBUG_DATA_UPPER_LIMIT + sizeof (UINT64) - 1];\r
b422b62c 1312 UINT8 InputPacketBuffer[DEBUG_DATA_UPPER_LIMIT];\r
18b144ea 1313 DEBUG_PORT_HANDLE Handle;\r
b422b62c 1314 UINT8 SequenceNo;\r
845a7fe0 1315 UINTN RemainingDataSize;\r
1316 UINTN CurrentDataSize;\r
18b144ea 1317\r
1318 Handle = GetDebugPortHandle();\r
1319\r
845a7fe0 1320 //\r
1321 // Data is appended end of Debug Packet header, make sure data address\r
1322 // in Debug Packet 8-byte alignment always\r
1323 //\r
1324 DebugHeader = (DEBUG_PACKET_HEADER *) (ALIGN_VALUE ((UINTN)&DebugPacket + sizeof (DEBUG_PACKET_HEADER), sizeof (UINT64))\r
1325 - sizeof (DEBUG_PACKET_HEADER));\r
93c0bdec 1326 DebugHeader->StartSymbol = DEBUG_STARTING_SYMBOL_NORMAL;\r
18b144ea 1327\r
845a7fe0 1328 RemainingDataSize = Count * Width;\r
18b144ea 1329 while (TRUE) {\r
b422b62c 1330 SequenceNo = GetMailboxPointer()->HostSequenceNo;\r
845a7fe0 1331 if (RemainingDataSize <= DEBUG_DATA_MAXIMUM_REAL_DATA) {\r
1332 //\r
1333 // If the remaining data is less one real packet size, this is the last data packet\r
1334 //\r
1335 CurrentDataSize = RemainingDataSize;\r
18b144ea 1336 LastPacket = TRUE;\r
845a7fe0 1337 DebugHeader->Command = DEBUG_COMMAND_OK;\r
18b144ea 1338 } else {\r
845a7fe0 1339 //\r
1340 // Data is too larger to be sent in one packet, calculate the actual data size could\r
1341 // be sent in one Maximum data packet\r
1342 //\r
1343 CurrentDataSize = (DEBUG_DATA_MAXIMUM_REAL_DATA / Width) * Width;\r
18b144ea 1344 LastPacket = FALSE;\r
845a7fe0 1345 DebugHeader->Command = DEBUG_COMMAND_IN_PROGRESS;\r
18b144ea 1346 }\r
93c0bdec 1347 //\r
845a7fe0 1348 // Construct the rest Debug header\r
1349 //\r
1350 DebugHeader->Length = (UINT8)(CurrentDataSize + sizeof (DEBUG_PACKET_HEADER));\r
1351 DebugHeader->SequenceNo = SequenceNo;\r
1352 DebugHeader->Crc = 0;\r
1353 CopyMemByWidth ((UINT8 *)(DebugHeader + 1), Data, (UINT16) CurrentDataSize / Width, Width);\r
1354 //\r
1355 // Calculate and fill the checksum, DebugHeader->Crc should be 0 before invoking CalculateCrc16 ()\r
93c0bdec 1356 //\r
b422b62c 1357 DebugHeader->Crc = CalculateCrc16 ((UINT8 *) DebugHeader, DebugHeader->Length, 0);\r
93c0bdec 1358\r
1359 DebugAgentDataMsgPrint (DEBUG_AGENT_VERBOSE, TRUE, (UINT8 *) DebugHeader, DebugHeader->Length);\r
1360 \r
1361 DebugPortWriteBuffer (Handle, (UINT8 *) DebugHeader, DebugHeader->Length);\r
18b144ea 1362\r
b422b62c 1363 while (TRUE) {\r
1364 Status = ReceivePacket (InputPacketBuffer, NULL, NULL, READ_PACKET_TIMEOUT, FALSE);\r
1365 if (Status == RETURN_TIMEOUT) {\r
1366 DebugAgentMsgPrint (DEBUG_AGENT_WARNING, "TARGET: Timeout in SendDataResponsePacket()\n");\r
1367 break;\r
1368 }\r
1369 AckDebugHeader = (DEBUG_PACKET_HEADER *) InputPacketBuffer;\r
1370 SequenceNo = AckDebugHeader->SequenceNo;\r
1371 if (AckDebugHeader->Command == DEBUG_COMMAND_OK &&\r
1372 SequenceNo == DebugHeader->SequenceNo &&\r
1373 LastPacket) {\r
18b144ea 1374 //\r
1375 // If this is the last packet, return RETURN_SUCCESS.\r
1376 //\r
1377 return RETURN_SUCCESS;\r
18b144ea 1378 }\r
b422b62c 1379 if ((SequenceNo == (UINT8) (DebugHeader->SequenceNo + 1)) && (AckDebugHeader->Command == DEBUG_COMMAND_CONTINUE)) {\r
1380 //\r
845a7fe0 1381 // Calculate the rest data size\r
b422b62c 1382 //\r
845a7fe0 1383 Data += CurrentDataSize;\r
1384 RemainingDataSize -= CurrentDataSize;\r
b422b62c 1385 UpdateMailboxContent (GetMailboxPointer(), DEBUG_MAILBOX_HOST_SEQUENCE_NO_INDEX, (UINT8) SequenceNo);\r
1386 break;\r
1387 }\r
1388 if (SequenceNo >= DebugHeader->SequenceNo) {\r
1389 DebugAgentMsgPrint (DEBUG_AGENT_WARNING, "TARGET: Received one old or new command(SequenceNo is %x, last SequenceNo is %x)\n", SequenceNo, DebugHeader->SequenceNo);\r
1390 break;\r
1391 }\r
18b144ea 1392 }\r
1393 }\r
1394}\r
1395\r
845a7fe0 1396/**\r
1397 Send packet with response data to HOST.\r
1398\r
1399 @param[in] Data Pointer to response data buffer.\r
1400 @param[in] DataSize Size of response data in byte.\r
1401\r
1402 @retval RETURN_SUCCESS Response data was sent successfully.\r
1403\r
1404**/\r
1405RETURN_STATUS\r
1406SendDataResponsePacket (\r
1407 IN UINT8 *Data,\r
1408 IN UINT16 DataSize\r
1409 )\r
1410{\r
1411 return ReadMemoryAndSendResponsePacket (Data, DataSize, 1);\r
1412}\r
1413\r
18b144ea 1414/**\r
1415 Send break cause packet to HOST.\r
1416\r
1417 @param[in] Vector Vector value of exception or interrutp.\r
1418 @param[in] CpuContext Pointer to save CPU context.\r
1419\r
1420 @retval RETURN_SUCCESS Response data was sent successfully.\r
1421 @retval RETURN_DEVICE_ERROR Cannot receive DEBUG_COMMAND_OK from HOST.\r
1422\r
1423**/\r
1424RETURN_STATUS\r
1425SendBreakCausePacket (\r
1426 IN UINTN Vector,\r
1427 IN DEBUG_CPU_CONTEXT *CpuContext\r
1428 )\r
1429{\r
1430 DEBUG_DATA_RESPONSE_BREAK_CAUSE DebugDataBreakCause;\r
1431\r
1432 DebugDataBreakCause.StopAddress = CpuContext->Eip;\r
1433 DebugDataBreakCause.Cause = GetBreakCause (Vector, CpuContext);\r
1434\r
93c0bdec 1435 return SendDataResponsePacket ((UINT8 *) &DebugDataBreakCause, (UINT16) sizeof (DEBUG_DATA_RESPONSE_BREAK_CAUSE));\r
18b144ea 1436}\r
1437\r
93c0bdec 1438/**\r
1439 Try to attach the HOST.\r
1440 \r
1441 Send init break packet to HOST:\r
1442 If no acknowlege received in specified Timeout, return RETURN_TIMEOUT. \r
1443 If received acknowlege, check the revision of HOST. \r
1444 Set Attach Flag if attach successfully. \r
1445 \r
b422b62c 1446 @param[in] BreakCause Break cause of this break event.\r
93c0bdec 1447 @param[in] Timeout Time out value to wait for acknowlege from HOST.\r
1448 The unit is microsecond.\r
1449 @param[out] BreakReceived If BreakReceived is not NULL,\r
1450 TRUE is retured if break-in symbol received.\r
1451 FALSE is retured if break-in symbol not received.\r
1452**/\r
1453RETURN_STATUS\r
1454AttachHost (\r
b422b62c 1455 IN UINT8 BreakCause,\r
93c0bdec 1456 IN UINTN Timeout,\r
1457 OUT BOOLEAN *BreakReceived\r
1458 )\r
1459{\r
1460 RETURN_STATUS Status;\r
1461 DEBUG_PORT_HANDLE Handle;\r
b422b62c 1462 BOOLEAN IncompatibilityFlag;\r
93c0bdec 1463\r
b422b62c 1464 IncompatibilityFlag = FALSE;\r
93c0bdec 1465 Handle = GetDebugPortHandle();\r
1466 \r
1467 //\r
1468 // Send init break and wait ack in Timeout\r
1469 //\r
1470 DebugPortWriteBuffer (Handle, (UINT8 *) mErrorMsgSendInitPacket, AsciiStrLen (mErrorMsgSendInitPacket));\r
b422b62c 1471 if (BreakCause == DEBUG_DATA_BREAK_CAUSE_SYSTEM_RESET) {\r
1472 Status = SendCommandAndWaitForAckOK (DEBUG_COMMAND_INIT_BREAK, Timeout, BreakReceived, &IncompatibilityFlag);\r
1473 } else {\r
1474 Status = SendCommandAndWaitForAckOK (DEBUG_COMMAND_ATTACH_BREAK, Timeout, BreakReceived, &IncompatibilityFlag);\r
93c0bdec 1475 }\r
b422b62c 1476 if (IncompatibilityFlag) {\r
93c0bdec 1477 //\r
b422b62c 1478 // If the incompatible Debug Packet received, the HOST should be running transfer protocol before DEBUG_AGENT_REVISION.\r
1479 // It could be UDK Debugger for Windows v1.1/v1.2 or for Linux v0.8/v1.2.\r
93c0bdec 1480 //\r
1481 DebugPortWriteBuffer (Handle, (UINT8 *) mErrorMsgVersionAlert, AsciiStrLen (mErrorMsgVersionAlert));\r
1482 CpuDeadLoop ();\r
1483 }\r
b422b62c 1484 \r
1485 if (RETURN_ERROR (Status)) {\r
1486 DebugPortWriteBuffer (Handle, (UINT8 *) mErrorMsgConnectFail, AsciiStrLen (mErrorMsgConnectFail));\r
1487 } else {\r
1488 DebugPortWriteBuffer (Handle, (UINT8 *) mErrorMsgConnectOK, AsciiStrLen (mErrorMsgConnectOK));\r
1489 //\r
1490 // Set Attach flag\r
1491 //\r
1492 SetHostAttached (TRUE);\r
1493 }\r
93c0bdec 1494 return Status;\r
1495}\r
1496\r
1497/**\r
1498 Send Break point packet to HOST. \r
1499 \r
1500 Only the first breaking processor could sent BREAK_POINT packet.\r
b422b62c 1501\r
1502 @param[in] BreakCause Break cause of this break event.\r
93c0bdec 1503 @param[in] ProcessorIndex Processor index value.\r
1504 @param[out] BreakReceived If BreakReceived is not NULL,\r
1505 TRUE is retured if break-in symbol received.\r
1506 FALSE is retured if break-in symbol not received.\r
1507 \r
1508**/\r
1509VOID\r
1510SendBreakPacketToHost (\r
b422b62c 1511 IN UINT8 BreakCause,\r
93c0bdec 1512 IN UINT32 ProcessorIndex,\r
1513 OUT BOOLEAN *BreakReceived\r
1514 )\r
1515{\r
1516 UINT8 InputCharacter;\r
1517 DEBUG_PORT_HANDLE Handle;\r
1518 \r
1519 Handle = GetDebugPortHandle();\r
1520 \r
1521 if (IsHostAttached ()) {\r
1522 DebugAgentMsgPrint (DEBUG_AGENT_INFO, "processor[%x]:Send Break Packet to HOST.\n", ProcessorIndex);\r
b422b62c 1523 SendCommandAndWaitForAckOK (DEBUG_COMMAND_BREAK_POINT, READ_PACKET_TIMEOUT, BreakReceived, NULL);\r
93c0bdec 1524 } else {\r
1525 DebugAgentMsgPrint (DEBUG_AGENT_INFO, "processor[%x]:Try to attach HOST.\n", ProcessorIndex);\r
1526 //\r
1527 // If HOST is not attached, try to attach it firstly.\r
1528 //\r
1529 //\r
1530 // Poll Attach symbols from HOST and ack OK\r
1531 // \r
1532 do {\r
1533 DebugPortReadBuffer (Handle, &InputCharacter, 1, 0);\r
1534 } while (InputCharacter != DEBUG_STARTING_SYMBOL_ATTACH);\r
1535 SendAckPacket (DEBUG_COMMAND_OK);\r
1536 \r
1537 //\r
1538 // Try to attach HOST\r
1539 //\r
b422b62c 1540 while (AttachHost (BreakCause, 0, NULL) != RETURN_SUCCESS);\r
93c0bdec 1541 \r
1542 }\r
1543}\r
18b144ea 1544\r
1545/**\r
1546 The main function to process communication with HOST.\r
1547\r
1548 It received the command packet from HOST, and sent response data packet to HOST.\r
1549\r
1550 @param[in] Vector Vector value of exception or interrutp.\r
1551 @param[in, out] CpuContext Pointer to saved CPU context.\r
1552 @param[in] BreakReceived TRUE means break-in symbol received.\r
1553 FALSE means break-in symbol not received.\r
1554\r
1555**/\r
1556VOID\r
1557CommandCommunication (\r
1558 IN UINTN Vector,\r
1559 IN OUT DEBUG_CPU_CONTEXT *CpuContext,\r
1560 IN BOOLEAN BreakReceived\r
1561 )\r
1562{\r
93c0bdec 1563 RETURN_STATUS Status;\r
845a7fe0 1564 UINT8 InputPacketBuffer[DEBUG_DATA_UPPER_LIMIT + sizeof (UINT64) - 1];\r
93c0bdec 1565 DEBUG_PACKET_HEADER *DebugHeader;\r
1566 UINT8 Width;\r
1567 UINT8 Data8;\r
1568 UINT32 Data32;\r
1569 UINT64 Data64;\r
1570 DEBUG_DATA_READ_MEMORY *MemoryRead;\r
1571 DEBUG_DATA_WRITE_MEMORY *MemoryWrite;\r
1572 DEBUG_DATA_READ_IO *IoRead;\r
1573 DEBUG_DATA_WRITE_IO *IoWrite;\r
1574 DEBUG_DATA_READ_REGISTER *RegisterRead;\r
1575 DEBUG_DATA_WRITE_REGISTER *RegisterWrite;\r
1576 UINT8 *RegisterBuffer;\r
1577 DEBUG_DATA_READ_MSR *MsrRegisterRead;\r
1578 DEBUG_DATA_WRITE_MSR *MsrRegisterWrite;\r
1579 DEBUG_DATA_CPUID *Cpuid;\r
1580 DEBUG_DATA_RESPONSE_CPUID CpuidResponse;\r
1581 DEBUG_DATA_SEARCH_SIGNATURE *SearchSignature;\r
1582 DEBUG_DATA_RESPONSE_GET_EXCEPTION Exception;\r
1583 DEBUG_DATA_RESPONSE_GET_REVISION DebugAgentRevision;\r
1584 DEBUG_DATA_SET_VIEWPOINT *SetViewPoint;\r
1585 BOOLEAN HaltDeferred;\r
1586 UINT32 ProcessorIndex;\r
1587 DEBUG_PORT_HANDLE Handle;\r
1588 DEBUG_AGENT_EXCEPTION_BUFFER AgentExceptionBuffer;\r
1589 UINT32 IssuedViewPoint;\r
b422b62c 1590 DEBUG_AGENT_MAILBOX *Mailbox;\r
845a7fe0 1591 UINT8 *AlignedDataPtr;\r
18b144ea 1592\r
1593 ProcessorIndex = 0;\r
93c0bdec 1594 IssuedViewPoint = 0;\r
1595 HaltDeferred = BreakReceived;\r
18b144ea 1596\r
b422b62c 1597 if (MultiProcessorDebugSupport()) {\r
18b144ea 1598 ProcessorIndex = GetProcessorIndex ();\r
1599 SetCpuStopFlagByIndex (ProcessorIndex, TRUE);\r
93c0bdec 1600 if (mDebugMpContext.ViewPointIndex == ProcessorIndex) {\r
1601 //\r
1602 // Only the current view processor could set AgentInProgress Flag. \r
1603 //\r
1604 IssuedViewPoint = ProcessorIndex;\r
1605 }\r
18b144ea 1606 }\r
1607\r
93c0bdec 1608 if (IssuedViewPoint == ProcessorIndex) {\r
1609 //\r
1610 // Set AgentInProgress Flag.\r
1611 //\r
b422b62c 1612 SetDebugFlag (DEBUG_AGENT_FLAG_AGENT_IN_PROGRESS, 1);\r
93c0bdec 1613 } \r
1614\r
1615 Handle = GetDebugPortHandle();\r
1616\r
18b144ea 1617 while (TRUE) {\r
1618\r
b422b62c 1619 if (MultiProcessorDebugSupport()) {\r
93c0bdec 1620 //\r
1621 // Check if the current processor is HOST view point\r
1622 //\r
18b144ea 1623 if (mDebugMpContext.ViewPointIndex != ProcessorIndex) {\r
1624 if (mDebugMpContext.RunCommandSet) {\r
93c0bdec 1625 //\r
1626 // If HOST view point sets RUN flag, run GO command to leave\r
1627 //\r
18b144ea 1628 SetCpuStopFlagByIndex (ProcessorIndex, FALSE);\r
1629 CommandGo (CpuContext);\r
1630 break;\r
1631 } else {\r
93c0bdec 1632 //\r
1633 // Run into loop again\r
1634 //\r
1635 CpuPause ();\r
18b144ea 1636 continue;\r
1637 }\r
1638 }\r
1639 }\r
1640\r
b422b62c 1641 AcquireMpSpinLock (&mDebugMpContext.DebugPortSpinLock);\r
18b144ea 1642\r
b422b62c 1643 DebugHeader =(DEBUG_PACKET_HEADER *) InputPacketBuffer;\r
18b144ea 1644\r
b422b62c 1645 DebugAgentMsgPrint (DEBUG_AGENT_INFO, "TARGET: Try to get command from HOST...\n");\r
1646 Status = ReceivePacket ((UINT8 *)DebugHeader, &BreakReceived, NULL, READ_PACKET_TIMEOUT, TRUE);\r
1647 if (Status != RETURN_SUCCESS || (DebugHeader->Command & DEBUG_COMMAND_RESPONSE) != 0) {\r
1648 DebugAgentMsgPrint (DEBUG_AGENT_WARNING, "TARGET: Get command[%x] sequenceno[%x] returned status is [%x] \n", DebugHeader->Command, DebugHeader->SequenceNo, Status);\r
1649 DebugAgentMsgPrint (DEBUG_AGENT_WARNING, "TARGET: Get command failed or it's response packet not expected! \n");\r
1650 ReleaseMpSpinLock (&mDebugMpContext.DebugPortSpinLock);\r
1651 continue;\r
18b144ea 1652 }\r
1653\r
b422b62c 1654 Mailbox = GetMailboxPointer ();\r
1655 if (DebugHeader->SequenceNo == Mailbox->HostSequenceNo) {\r
1656 DebugAgentMsgPrint (DEBUG_AGENT_WARNING, "TARGET: Receive one old command[%x] agaist command[%x]\n", DebugHeader->SequenceNo, Mailbox->HostSequenceNo);\r
1657 SendAckPacket (Mailbox->LastAck);\r
1658 ReleaseMpSpinLock (&mDebugMpContext.DebugPortSpinLock);\r
1659 continue;\r
1660 } else if (DebugHeader->SequenceNo == (UINT8) (Mailbox->HostSequenceNo + 1)) {\r
1661 UpdateMailboxContent (Mailbox, DEBUG_MAILBOX_HOST_SEQUENCE_NO_INDEX, (UINT8) DebugHeader->SequenceNo);\r
1662 } else {\r
1663 DebugAgentMsgPrint (DEBUG_AGENT_WARNING, "Receive one invalid comamnd[%x] agaist command[%x]\n", DebugHeader->SequenceNo, Mailbox->HostSequenceNo);\r
1664 ReleaseMpSpinLock (&mDebugMpContext.DebugPortSpinLock);\r
18b144ea 1665 continue;\r
1666 }\r
b422b62c 1667 \r
93c0bdec 1668 //\r
1669 // Save CPU content before executing HOST commond\r
1670 //\r
b422b62c 1671 UpdateMailboxContent (Mailbox, DEBUG_MAILBOX_EXCEPTION_BUFFER_POINTER_INDEX, (UINT64)(UINTN) &AgentExceptionBuffer.JumpBuffer);\r
93c0bdec 1672 if (SetJump (&AgentExceptionBuffer.JumpBuffer) != 0) {\r
1673 //\r
1674 // If HOST command failed, continue to wait for HOST's next command\r
1675 // If needed, agent could send exception info to HOST.\r
1676 //\r
1677 SendAckPacket (DEBUG_COMMAND_ABORT);\r
b422b62c 1678 ReleaseMpSpinLock (&mDebugMpContext.DebugPortSpinLock);\r
93c0bdec 1679 continue;\r
1680 }\r
1681\r
1682 DebugAgentMsgPrint (DEBUG_AGENT_INFO, "Processor[%x]:Received one command(%x)\n", mDebugMpContext.ViewPointIndex, DebugHeader->Command);\r
1683 \r
18b144ea 1684 switch (DebugHeader->Command) {\r
1685\r
b422b62c 1686 case DEBUG_COMMAND_HALT:\r
1687 SendAckPacket (DEBUG_COMMAND_HALT_DEFERRED);\r
1688 HaltDeferred = TRUE;\r
1689 BreakReceived = FALSE;\r
1690 Status = RETURN_SUCCESS;\r
1691 break;\r
1692\r
18b144ea 1693 case DEBUG_COMMAND_RESET:\r
1694 SendAckPacket (DEBUG_COMMAND_OK);\r
b422b62c 1695 SendAckPacket (DEBUG_COMMAND_OK);\r
1696 SendAckPacket (DEBUG_COMMAND_OK);\r
1697 ReleaseMpSpinLock (&mDebugMpContext.DebugPortSpinLock);\r
18b144ea 1698\r
1699 ResetCold ();\r
1700 //\r
b4ebbaff
RN
1701 // Assume system resets in 2 seconds, otherwise send TIMEOUT packet.\r
1702 // PCD can be used if 2 seconds isn't long enough for some platforms.\r
18b144ea 1703 //\r
b4ebbaff 1704 MicroSecondDelay (2000000);\r
b422b62c 1705 UpdateMailboxContent (Mailbox, DEBUG_MAILBOX_HOST_SEQUENCE_NO_INDEX, Mailbox->HostSequenceNo + 1);\r
1706 SendAckPacket (DEBUG_COMMAND_TIMEOUT);\r
1707 SendAckPacket (DEBUG_COMMAND_TIMEOUT);\r
b4ebbaff 1708 SendAckPacket (DEBUG_COMMAND_TIMEOUT);\r
18b144ea 1709 break;\r
1710\r
1711 case DEBUG_COMMAND_GO:\r
1712 CommandGo (CpuContext);\r
93c0bdec 1713 //\r
1714 // Clear Dr0 to avoid to be recognized as IMAGE_LOAD/_UNLOAD again when hitting a breakpoint after GO\r
1715 // If HOST changed Dr0 before GO, we will not change Dr0 here\r
1716 //\r
1717 Data8 = GetBreakCause (Vector, CpuContext);\r
1718 if (Data8 == DEBUG_DATA_BREAK_CAUSE_IMAGE_LOAD || Data8 == DEBUG_DATA_BREAK_CAUSE_IMAGE_UNLOAD) {\r
1719 CpuContext->Dr0 = 0;\r
1720 }\r
1721 //\r
1722 // Clear Stepping Flag\r
1723 //\r
b422b62c 1724 SetDebugFlag (DEBUG_AGENT_FLAG_STEPPING, 0);\r
93c0bdec 1725 \r
18b144ea 1726 if (!HaltDeferred) {\r
1727 //\r
1728 // If no HALT command received when being in-active mode\r
1729 //\r
b422b62c 1730 if (MultiProcessorDebugSupport()) {\r
93c0bdec 1731 Data32 = FindNextPendingBreakCpu ();\r
18b144ea 1732 if (Data32 != -1) {\r
1733 //\r
1734 // If there are still others processors being in break state, \r
1735 // send OK packet to HOST to finish this go command\r
1736 //\r
1737 SendAckPacket (DEBUG_COMMAND_OK);\r
1738 CpuPause ();\r
1739 //\r
1740 // Set current view to the next breaking processor\r
1741 //\r
1742 mDebugMpContext.ViewPointIndex = Data32;\r
1743 mDebugMpContext.BreakAtCpuIndex = mDebugMpContext.ViewPointIndex;\r
1744 SetCpuBreakFlagByIndex (mDebugMpContext.ViewPointIndex, FALSE);\r
1745 //\r
93c0bdec 1746 // Send break packet to HOST to let HOST break again\r
1747 //\r
b422b62c 1748 SendBreakPacketToHost (DEBUG_DATA_BREAK_CAUSE_UNKNOWN, mDebugMpContext.BreakAtCpuIndex, &BreakReceived);\r
93c0bdec 1749 //\r
1750 // Continue to run into loop to read command packet from HOST\r
18b144ea 1751 //\r
b422b62c 1752 ReleaseMpSpinLock (&mDebugMpContext.DebugPortSpinLock);\r
18b144ea 1753 break;\r
1754 }\r
1755\r
1756 //\r
1757 // If no else processor break, set stop bitmask,\r
1758 // and set Running flag for all processors.\r
1759 //\r
1760 SetCpuStopFlagByIndex (ProcessorIndex, FALSE);\r
1761 SetCpuRunningFlag (TRUE);\r
1762 CpuPause ();\r
1763 //\r
1764 // Wait for all processors are in running state \r
1765 //\r
1766 while (TRUE) {\r
1767 if (IsAllCpuRunning ()) {\r
1768 break;\r
1769 }\r
1770 }\r
1771 //\r
1772 // Set BSP to be current view point.\r
1773 //\r
1774 SetDebugViewPoint (mDebugMpContext.BspIndex);\r
1775 CpuPause ();\r
1776 //\r
1777 // Clear breaking processor index and running flag\r
1778 //\r
1779 mDebugMpContext.BreakAtCpuIndex = (UINT32) (-1);\r
1780 SetCpuRunningFlag (FALSE);\r
1781 }\r
1782\r
1783 //\r
1784 // Send OK packet to HOST to finish this go command\r
1785 //\r
1786 SendAckPacket (DEBUG_COMMAND_OK);\r
1787\r
b422b62c 1788 ReleaseMpSpinLock (&mDebugMpContext.DebugPortSpinLock);\r
18b144ea 1789\r
b422b62c 1790 if (!IsHostAttached()) {\r
1791 UpdateMailboxContent (Mailbox, DEBUG_MAILBOX_SEQUENCE_NO_INDEX, 0);\r
1792 UpdateMailboxContent (Mailbox, DEBUG_MAILBOX_HOST_SEQUENCE_NO_INDEX, 0);\r
1793 }\r
18b144ea 1794 return;\r
1795\r
1796 } else {\r
1797 //\r
1798 // If reveived HALT command, need to defer the GO command\r
1799 //\r
1800 SendAckPacket (DEBUG_COMMAND_HALT_PROCESSED);\r
1801 HaltDeferred = FALSE;\r
18b144ea 1802\r
1803 Vector = DEBUG_TIMER_VECTOR;\r
1804 }\r
1805 break;\r
1806\r
1807 case DEBUG_COMMAND_BREAK_CAUSE:\r
1808\r
b422b62c 1809 if (MultiProcessorDebugSupport() && ProcessorIndex != mDebugMpContext.BreakAtCpuIndex) {\r
18b144ea 1810 Status = SendBreakCausePacket (DEBUG_TIMER_VECTOR, CpuContext);\r
1811\r
1812 } else {\r
1813 Status = SendBreakCausePacket (Vector, CpuContext);\r
1814 }\r
1815\r
1816 break;\r
1817\r
1818 case DEBUG_COMMAND_SET_HW_BREAKPOINT:\r
1819 SetDebugRegister (CpuContext, (DEBUG_DATA_SET_HW_BREAKPOINT *) (DebugHeader + 1));\r
1820 SendAckPacket (DEBUG_COMMAND_OK);\r
1821 break;\r
1822\r
1823 case DEBUG_COMMAND_CLEAR_HW_BREAKPOINT:\r
1824 ClearDebugRegister (CpuContext, (DEBUG_DATA_CLEAR_HW_BREAKPOINT *) (DebugHeader + 1));\r
1825 SendAckPacket (DEBUG_COMMAND_OK);\r
1826 break;\r
1827\r
1828 case DEBUG_COMMAND_SINGLE_STEPPING:\r
1829 CommandStepping (CpuContext);\r
93c0bdec 1830 //\r
1831 // Clear Dr0 to avoid to be recognized as IMAGE_LOAD/_UNLOAD again when hitting a breakpoint after GO\r
1832 // If HOST changed Dr0 before GO, we will not change Dr0 here\r
1833 //\r
1834 Data8 = GetBreakCause (Vector, CpuContext);\r
1835 if (Data8 == DEBUG_DATA_BREAK_CAUSE_IMAGE_LOAD || Data8 == DEBUG_DATA_BREAK_CAUSE_IMAGE_UNLOAD) {\r
1836 CpuContext->Dr0 = 0;\r
1837 }\r
18b144ea 1838\r
1839 mDebugMpContext.BreakAtCpuIndex = (UINT32) (-1);\r
93c0bdec 1840 //\r
1841 // Set Stepping Flag\r
1842 //\r
b422b62c 1843 SetDebugFlag (DEBUG_AGENT_FLAG_STEPPING, 1);\r
1844 ReleaseMpSpinLock (&mDebugMpContext.DebugPortSpinLock);\r
18b144ea 1845 //\r
93c0bdec 1846 // Executing stepping command directly without sending ACK packet,\r
1847 // ACK packet will be sent after stepping done.\r
18b144ea 1848 //\r
1849 return;\r
1850\r
1851 case DEBUG_COMMAND_SET_SW_BREAKPOINT:\r
1852 Data64 = (UINTN) (((DEBUG_DATA_SET_SW_BREAKPOINT *) (DebugHeader + 1))->Address);\r
1853 Data8 = *(UINT8 *) (UINTN) Data64;\r
1854 *(UINT8 *) (UINTN) Data64 = DEBUG_SW_BREAKPOINT_SYMBOL;\r
93c0bdec 1855 Status = SendDataResponsePacket ((UINT8 *) &Data8, (UINT16) sizeof (UINT8));\r
18b144ea 1856 break;\r
1857\r
93c0bdec 1858 case DEBUG_COMMAND_READ_MEMORY:\r
1859 MemoryRead = (DEBUG_DATA_READ_MEMORY *) (DebugHeader + 1);\r
845a7fe0 1860 Status = ReadMemoryAndSendResponsePacket ((UINT8 *) (UINTN) MemoryRead->Address, MemoryRead->Count, MemoryRead->Width);\r
18b144ea 1861 break;\r
1862\r
93c0bdec 1863 case DEBUG_COMMAND_WRITE_MEMORY:\r
1864 MemoryWrite = (DEBUG_DATA_WRITE_MEMORY *) (DebugHeader + 1);\r
845a7fe0 1865 //\r
1866 // Copy data into one memory with 8-byte alignment address\r
1867 //\r
1868 AlignedDataPtr = ALIGN_POINTER ((UINT8 *) &MemoryWrite->Data, sizeof (UINT64));\r
1869 if (AlignedDataPtr != (UINT8 *) &MemoryWrite->Data) {\r
1870 CopyMem (AlignedDataPtr, (UINT8 *) &MemoryWrite->Data, MemoryWrite->Count * MemoryWrite->Width);\r
1871 }\r
1872 CopyMemByWidth ((UINT8 *) (UINTN) MemoryWrite->Address, AlignedDataPtr, MemoryWrite->Count, MemoryWrite->Width);\r
18b144ea 1873 SendAckPacket (DEBUG_COMMAND_OK);\r
1874 break;\r
1875\r
1876 case DEBUG_COMMAND_READ_IO:\r
1877 IoRead = (DEBUG_DATA_READ_IO *) (DebugHeader + 1);\r
1878 switch (IoRead->Width) {\r
1879 case 1:\r
93c0bdec 1880 Data64 = IoRead8 ((UINTN) IoRead->Port);\r
18b144ea 1881 break;\r
1882 case 2:\r
93c0bdec 1883 Data64 = IoRead16 ((UINTN) IoRead->Port);\r
18b144ea 1884 break;\r
1885 case 4:\r
93c0bdec 1886 Data64 = IoRead32 ((UINTN) IoRead->Port);\r
18b144ea 1887 break;\r
1888 case 8:\r
93c0bdec 1889 Data64 = IoRead64 ((UINTN) IoRead->Port);\r
18b144ea 1890 break;\r
1891 default:\r
1892 Data64 = (UINT64) -1;\r
1893 }\r
93c0bdec 1894 Status = SendDataResponsePacket ((UINT8 *) &Data64, IoRead->Width);\r
18b144ea 1895 break;\r
1896\r
1897 case DEBUG_COMMAND_WRITE_IO:\r
1898 IoWrite = (DEBUG_DATA_WRITE_IO *) (DebugHeader + 1);\r
1899 switch (IoWrite->Width) {\r
1900 case 1:\r
93c0bdec 1901 Data64 = IoWrite8 ((UINTN) IoWrite->Port, *(UINT8 *) &IoWrite->Data);\r
18b144ea 1902 break;\r
1903 case 2:\r
93c0bdec 1904 Data64 = IoWrite16 ((UINTN) IoWrite->Port, *(UINT16 *) &IoWrite->Data);\r
18b144ea 1905 break;\r
1906 case 4:\r
93c0bdec 1907 Data64 = IoWrite32 ((UINTN) IoWrite->Port, *(UINT32 *) &IoWrite->Data);\r
18b144ea 1908 break;\r
1909 case 8:\r
93c0bdec 1910 Data64 = IoWrite64 ((UINTN) IoWrite->Port, *(UINT64 *) &IoWrite->Data);\r
18b144ea 1911 break;\r
1912 default:\r
1913 Data64 = (UINT64) -1;\r
1914 }\r
1915 SendAckPacket (DEBUG_COMMAND_OK);\r
1916 break;\r
1917\r
93c0bdec 1918 case DEBUG_COMMAND_READ_ALL_REGISTERS:\r
1919 Status = SendDataResponsePacket ((UINT8 *) CpuContext, sizeof (*CpuContext));\r
1920 break;\r
1921\r
18b144ea 1922 case DEBUG_COMMAND_READ_REGISTER:\r
1923 RegisterRead = (DEBUG_DATA_READ_REGISTER *) (DebugHeader + 1);\r
1924\r
93c0bdec 1925 if (RegisterRead->Index <= SOFT_DEBUGGER_REGISTER_MAX) {\r
1926 RegisterBuffer = ArchReadRegisterBuffer (CpuContext, RegisterRead->Index, &Width);\r
1927 Status = SendDataResponsePacket (RegisterBuffer, Width);\r
18b144ea 1928 } else {\r
93c0bdec 1929 Status = RETURN_UNSUPPORTED;\r
18b144ea 1930 }\r
1931 break;\r
1932\r
1933 case DEBUG_COMMAND_WRITE_REGISTER:\r
1934 RegisterWrite = (DEBUG_DATA_WRITE_REGISTER *) (DebugHeader + 1);\r
93c0bdec 1935 if (RegisterWrite->Index <= SOFT_DEBUGGER_REGISTER_MAX) {\r
1936 RegisterBuffer = ArchReadRegisterBuffer (CpuContext, RegisterWrite->Index, &Width);\r
1937 ASSERT (Width == RegisterWrite->Length);\r
1938 CopyMem (RegisterBuffer, RegisterWrite->Data, Width);\r
1939 SendAckPacket (DEBUG_COMMAND_OK);\r
1940 } else {\r
1941 Status = RETURN_UNSUPPORTED;\r
1942 }\r
18b144ea 1943 break;\r
1944\r
1945 case DEBUG_COMMAND_ARCH_MODE:\r
1946 Data8 = DEBUG_ARCH_SYMBOL;\r
93c0bdec 1947 Status = SendDataResponsePacket ((UINT8 *) &Data8, (UINT16) sizeof (UINT8));\r
18b144ea 1948 break;\r
1949\r
1950 case DEBUG_COMMAND_READ_MSR:\r
1951 MsrRegisterRead = (DEBUG_DATA_READ_MSR *) (DebugHeader + 1);\r
1952 Data64 = AsmReadMsr64 (MsrRegisterRead->Index);\r
93c0bdec 1953 Status = SendDataResponsePacket ((UINT8 *) &Data64, (UINT16) sizeof (UINT64));\r
18b144ea 1954 break;\r
1955\r
1956 case DEBUG_COMMAND_WRITE_MSR:\r
1957 MsrRegisterWrite = (DEBUG_DATA_WRITE_MSR *) (DebugHeader + 1);\r
1958 AsmWriteMsr64 (MsrRegisterWrite->Index, MsrRegisterWrite->Value);\r
1959 SendAckPacket (DEBUG_COMMAND_OK);\r
1960 break;\r
1961\r
93c0bdec 1962 case DEBUG_COMMAND_SET_DEBUG_SETTING:\r
1963 Status = SetDebugSetting ((DEBUG_DATA_SET_DEBUG_SETTING *)(DebugHeader + 1));\r
1964 if (Status == RETURN_SUCCESS) {\r
1965 SendAckPacket (DEBUG_COMMAND_OK);\r
1966 }\r
18b144ea 1967 break;\r
1968\r
1969 case DEBUG_COMMAND_GET_REVISION:\r
1970 DebugAgentRevision.Revision = DEBUG_AGENT_REVISION;\r
1971 DebugAgentRevision.Capabilities = DEBUG_AGENT_CAPABILITIES;\r
93c0bdec 1972 Status = SendDataResponsePacket ((UINT8 *) &DebugAgentRevision, (UINT16) sizeof (DEBUG_DATA_RESPONSE_GET_REVISION));\r
18b144ea 1973 break;\r
1974\r
1975 case DEBUG_COMMAND_GET_EXCEPTION:\r
1976 Exception.ExceptionNum = (UINT8) Vector;\r
93c0bdec 1977 Exception.ExceptionData = (UINT32) CpuContext->ExceptionData;\r
1978 Status = SendDataResponsePacket ((UINT8 *) &Exception, (UINT16) sizeof (DEBUG_DATA_RESPONSE_GET_EXCEPTION));\r
18b144ea 1979 break;\r
1980\r
1981 case DEBUG_COMMAND_SET_VIEWPOINT:\r
93c0bdec 1982 SetViewPoint = (DEBUG_DATA_SET_VIEWPOINT *) (DebugHeader + 1);\r
b422b62c 1983 if (MultiProcessorDebugSupport()) {\r
93c0bdec 1984 if (IsCpuStopped (SetViewPoint->ViewPoint)) {\r
1985 SetDebugViewPoint (SetViewPoint->ViewPoint);\r
18b144ea 1986 SendAckPacket (DEBUG_COMMAND_OK);\r
1987 } else {\r
1988 //\r
1989 // If CPU is not halted\r
1990 //\r
1991 SendAckPacket (DEBUG_COMMAND_NOT_SUPPORTED);\r
1992 }\r
93c0bdec 1993 } else if (SetViewPoint->ViewPoint == 0) {\r
18b144ea 1994 SendAckPacket (DEBUG_COMMAND_OK);\r
1995\r
1996 } else {\r
1997 SendAckPacket (DEBUG_COMMAND_NOT_SUPPORTED);\r
1998 }\r
1999\r
2000 break;\r
2001\r
2002 case DEBUG_COMMAND_GET_VIEWPOINT:\r
2003 Data32 = mDebugMpContext.ViewPointIndex;\r
93c0bdec 2004 SendDataResponsePacket((UINT8 *) &Data32, (UINT16) sizeof (UINT32));\r
2005 break;\r
2006\r
2007 case DEBUG_COMMAND_MEMORY_READY:\r
b422b62c 2008 Data8 = (UINT8) GetDebugFlag (DEBUG_AGENT_FLAG_MEMORY_READY);\r
93c0bdec 2009 SendDataResponsePacket (&Data8, (UINT16) sizeof (UINT8));\r
2010 break;\r
2011\r
2012 case DEBUG_COMMAND_DETACH:\r
2013 SetHostAttached (FALSE);\r
2014 SendAckPacket (DEBUG_COMMAND_OK);\r
2015 break;\r
2016\r
2017 case DEBUG_COMMAND_CPUID:\r
2018 Cpuid = (DEBUG_DATA_CPUID *) (DebugHeader + 1);\r
2019 AsmCpuidEx (\r
2020 Cpuid->Eax, Cpuid->Ecx, \r
2021 &CpuidResponse.Eax, &CpuidResponse.Ebx,\r
2022 &CpuidResponse.Ecx, &CpuidResponse.Edx\r
2023 );\r
2024 SendDataResponsePacket ((UINT8 *) &CpuidResponse, (UINT16) sizeof (CpuidResponse));\r
2025 break;\r
2026\r
2027 case DEBUG_COMMAND_SEARCH_SIGNATURE:\r
2028 SearchSignature = (DEBUG_DATA_SEARCH_SIGNATURE *) (DebugHeader + 1);\r
2029 if ((SearchSignature->Alignment != 0) && \r
2030 (SearchSignature->Alignment == GetPowerOfTwo32 (SearchSignature->Alignment))\r
2031 ) {\r
2032 if (SearchSignature->Positive) {\r
2033 for (\r
2034 Data64 = ALIGN_VALUE ((UINTN) SearchSignature->Start, SearchSignature->Alignment);\r
2035 Data64 <= SearchSignature->Start + SearchSignature->Count - SearchSignature->DataLength;\r
2036 Data64 += SearchSignature->Alignment\r
2037 ) {\r
2038 if (CompareMem ((VOID *) (UINTN) Data64, &SearchSignature->Data, SearchSignature->DataLength) == 0) {\r
2039 break;\r
2040 }\r
2041 }\r
2042 if (Data64 > SearchSignature->Start + SearchSignature->Count - SearchSignature->DataLength) {\r
2043 Data64 = (UINT64) -1;\r
2044 }\r
2045 } else {\r
2046 for (\r
2047 Data64 = ALIGN_VALUE ((UINTN) SearchSignature->Start - SearchSignature->Alignment, SearchSignature->Alignment);\r
2048 Data64 >= SearchSignature->Start - SearchSignature->Count;\r
2049 Data64 -= SearchSignature->Alignment\r
2050 ) {\r
2051 if (CompareMem ((VOID *) (UINTN) Data64, &SearchSignature->Data, SearchSignature->DataLength) == 0) {\r
2052 break;\r
2053 }\r
2054 }\r
2055 if (Data64 < SearchSignature->Start - SearchSignature->Count) {\r
2056 Data64 = (UINT64) -1;\r
2057 }\r
2058 }\r
2059 SendDataResponsePacket ((UINT8 *) &Data64, (UINT16) sizeof (Data64));\r
2060 } else {\r
2061 Status = RETURN_UNSUPPORTED;\r
2062 }\r
18b144ea 2063 break;\r
2064\r
2065 default:\r
2066 SendAckPacket (DEBUG_COMMAND_NOT_SUPPORTED);\r
2067 break;\r
2068 }\r
2069\r
2070 if (Status == RETURN_UNSUPPORTED) {\r
2071 SendAckPacket (DEBUG_COMMAND_NOT_SUPPORTED);\r
2072 } else if (Status != RETURN_SUCCESS) {\r
2073 SendAckPacket (DEBUG_COMMAND_ABORT);\r
2074 }\r
2075\r
b422b62c 2076 ReleaseMpSpinLock (&mDebugMpContext.DebugPortSpinLock);\r
18b144ea 2077 CpuPause ();\r
2078 }\r
2079}\r
2080\r
2081/**\r
2082 C function called in interrupt handler.\r
2083\r
2084 @param[in] Vector Vector value of exception or interrutp.\r
2085 @param[in] CpuContext Pointer to save CPU context.\r
2086\r
2087**/\r
2088VOID\r
2089EFIAPI\r
2090InterruptProcess (\r
2091 IN UINT32 Vector,\r
2092 IN DEBUG_CPU_CONTEXT *CpuContext\r
2093 )\r
2094{\r
93c0bdec 2095 UINT8 InputCharacter;\r
2096 UINT8 BreakCause;\r
2097 UINTN SavedEip;\r
2098 BOOLEAN BreakReceived;\r
2099 UINT32 ProcessorIndex;\r
2100 UINT32 CurrentDebugTimerInitCount;\r
2101 DEBUG_PORT_HANDLE Handle;\r
2102 UINT8 Data8;\r
2103 UINT8 *Al;\r
2104 UINT32 IssuedViewPoint;\r
2105 DEBUG_AGENT_EXCEPTION_BUFFER *ExceptionBuffer;\r
18b144ea 2106\r
93c0bdec 2107 ProcessorIndex = 0;\r
2108 IssuedViewPoint = 0;\r
2109 BreakReceived = FALSE;\r
18b144ea 2110\r
b422b62c 2111 if (mSkipBreakpoint) {\r
2112 //\r
2113 // If Skip Breakpoint flag is set, means communication is disturbed by hardware SMI, we need to ignore the break points in SMM\r
2114 //\r
2115 if ((Vector == DEBUG_INT1_VECTOR) || (Vector == DEBUG_INT3_VECTOR)) {\r
2116 DebugPortWriteBuffer (GetDebugPortHandle(), (UINT8 *) mWarningMsgIngoreBreakpoint, AsciiStrLen (mWarningMsgIngoreBreakpoint));\r
2117 return;\r
2118 }\r
2119 }\r
2120\r
2121 if (MultiProcessorDebugSupport()) {\r
18b144ea 2122 ProcessorIndex = GetProcessorIndex ();\r
93c0bdec 2123 //\r
2124 // If this processor has alreay halted before, need to check it later\r
2125 //\r
2126 if (IsCpuStopped (ProcessorIndex)) {\r
2127 IssuedViewPoint = ProcessorIndex;\r
2128 }\r
18b144ea 2129 }\r
2130\r
b422b62c 2131 if (IssuedViewPoint == ProcessorIndex && GetDebugFlag (DEBUG_AGENT_FLAG_STEPPING) != 1) {\r
93c0bdec 2132 //\r
2133 // Check if this exception is issued by Debug Agent itself\r
2134 // If yes, fill the debug agent exception buffer and LongJump() back to\r
2135 // the saved CPU content in CommandCommunication()\r
2136 //\r
b422b62c 2137 if (GetDebugFlag (DEBUG_AGENT_FLAG_AGENT_IN_PROGRESS) == 1) {\r
845a7fe0 2138 DebugAgentMsgPrint (DEBUG_AGENT_ERROR, "Debug agent meet one Exception, ExceptionNum is %d, EIP = 0x%x.\n", Vector, (UINTN)CpuContext->Eip);\r
93c0bdec 2139 ExceptionBuffer = (DEBUG_AGENT_EXCEPTION_BUFFER *) (UINTN) GetMailboxPointer()->ExceptionBufferPointer;\r
2140 ExceptionBuffer->ExceptionContent.ExceptionNum = (UINT8) Vector;\r
2141 ExceptionBuffer->ExceptionContent.ExceptionData = (UINT32) CpuContext->ExceptionData;\r
b422b62c 2142 LongJump ((BASE_LIBRARY_JUMP_BUFFER *)(UINTN)(ExceptionBuffer), 1);\r
93c0bdec 2143 }\r
2144 }\r
2145\r
b422b62c 2146 if (MultiProcessorDebugSupport()) {\r
93c0bdec 2147 //\r
2148 // If RUN commmand is executing, wait for it done. \r
2149 //\r
2150 while (mDebugMpContext.RunCommandSet) {\r
2151 CpuPause ();\r
2152 }\r
2153 }\r
2154\r
b422b62c 2155 Handle = GetDebugPortHandle();\r
2156 BreakCause = GetBreakCause (Vector, CpuContext);\r
18b144ea 2157 switch (Vector) {\r
2158 case DEBUG_INT1_VECTOR:\r
2159 case DEBUG_INT3_VECTOR:\r
93c0bdec 2160 switch (BreakCause) {\r
2161 case DEBUG_DATA_BREAK_CAUSE_SYSTEM_RESET:\r
b422b62c 2162 if (AttachHost (BreakCause, READ_PACKET_TIMEOUT, &BreakReceived) != RETURN_SUCCESS) {\r
93c0bdec 2163 //\r
2164 // Try to connect HOST, return if fails\r
2165 //\r
18b144ea 2166 break;\r
2167 }\r
18b144ea 2168 CommandCommunication (Vector, CpuContext, BreakReceived);\r
93c0bdec 2169 break;\r
18b144ea 2170\r
93c0bdec 2171 case DEBUG_DATA_BREAK_CAUSE_STEPPING:\r
18b144ea 2172 //\r
2173 // Stepping is finished, send Ack package.\r
2174 //\r
b422b62c 2175 if (MultiProcessorDebugSupport()) {\r
18b144ea 2176 mDebugMpContext.BreakAtCpuIndex = ProcessorIndex;\r
2177 }\r
2178 SendAckPacket (DEBUG_COMMAND_OK);\r
2179 CommandCommunication (Vector, CpuContext, BreakReceived);\r
93c0bdec 2180 break;\r
18b144ea 2181\r
93c0bdec 2182 case DEBUG_DATA_BREAK_CAUSE_MEMORY_READY:\r
18b144ea 2183 //\r
2184 // Memory is ready\r
2185 //\r
b422b62c 2186 SendCommandAndWaitForAckOK (DEBUG_COMMAND_MEMORY_READY, READ_PACKET_TIMEOUT, &BreakReceived, NULL);\r
18b144ea 2187 CommandCommunication (Vector, CpuContext, BreakReceived);\r
93c0bdec 2188 break;\r
18b144ea 2189\r
93c0bdec 2190 case DEBUG_DATA_BREAK_CAUSE_IMAGE_LOAD:\r
2191 case DEBUG_DATA_BREAK_CAUSE_IMAGE_UNLOAD:\r
2192 //\r
2193 // Set AL to DEBUG_AGENT_IMAGE_CONTINUE\r
2194 //\r
2195 Al = ArchReadRegisterBuffer (CpuContext, SOFT_DEBUGGER_REGISTER_AX, &Data8);\r
2196 *Al = DEBUG_AGENT_IMAGE_CONTINUE;\r
18b144ea 2197\r
93c0bdec 2198 if (!IsHostAttached ()) {\r
18b144ea 2199 //\r
93c0bdec 2200 // If HOST is not connected for image load/unload, return\r
18b144ea 2201 //\r
93c0bdec 2202 break;\r
18b144ea 2203 }\r
93c0bdec 2204 //\r
2205 // Continue to run the following common code\r
2206 //\r
2207 \r
2208 case DEBUG_DATA_BREAK_CAUSE_HW_BREAKPOINT:\r
2209 case DEBUG_DATA_BREAK_CAUSE_SW_BREAKPOINT:\r
2210 default:\r
2211 //\r
2212 // Send Break packet to HOST\r
2213 //\r
b422b62c 2214 AcquireMpSpinLock (&mDebugMpContext.DebugPortSpinLock);\r
93c0bdec 2215 //\r
2216 // Only the first breaking processor could send BREAK_POINT to HOST\r
2217 // \r
2218 if (IsFirstBreakProcessor (ProcessorIndex)) {\r
b422b62c 2219 SendBreakPacketToHost (BreakCause, ProcessorIndex, &BreakReceived);\r
18b144ea 2220 }\r
b422b62c 2221 ReleaseMpSpinLock (&mDebugMpContext.DebugPortSpinLock);\r
93c0bdec 2222 \r
18b144ea 2223 if (Vector == DEBUG_INT3_VECTOR) {\r
2224 //\r
2225 // go back address located "0xCC"\r
2226 //\r
2227 CpuContext->Eip--;\r
2228 SavedEip = CpuContext->Eip;\r
2229 CommandCommunication (Vector, CpuContext, BreakReceived);\r
2230 if ((SavedEip == CpuContext->Eip) &&\r
2231 (*(UINT8 *) (UINTN) CpuContext->Eip == DEBUG_SW_BREAKPOINT_SYMBOL)) {\r
2232 //\r
2233 // If this is not a software breakpoint set by HOST,\r
2234 // restore EIP\r
2235 //\r
2236 CpuContext->Eip++;\r
2237 }\r
2238 } else {\r
2239 CommandCommunication (Vector, CpuContext, BreakReceived);\r
2240 }\r
93c0bdec 2241 break;\r
18b144ea 2242 }\r
2243\r
2244 break;\r
2245\r
2246 case DEBUG_TIMER_VECTOR:\r
2247\r
b422b62c 2248 AcquireMpSpinLock (&mDebugMpContext.DebugPortSpinLock);\r
93c0bdec 2249\r
b422b62c 2250 if (MultiProcessorDebugSupport()) {\r
18b144ea 2251 if (IsBsp (ProcessorIndex)) {\r
2252 //\r
2253 // If current processor is BSP, check Apic timer's init count if changed,\r
2254 // it may be re-written when switching BSP.\r
2255 // If it changed, re-initialize debug timer\r
2256 //\r
2257 CurrentDebugTimerInitCount = GetApicTimerInitCount ();\r
2258 if (mDebugMpContext.DebugTimerInitCount != CurrentDebugTimerInitCount) {\r
2259 InitializeDebugTimer ();\r
2260 }\r
2261 }\r
2262\r
2263 if (!IsBsp (ProcessorIndex) || mDebugMpContext.IpiSentByAp) {\r
b422b62c 2264 ReleaseMpSpinLock (&mDebugMpContext.DebugPortSpinLock);\r
18b144ea 2265 //\r
2266 // If current processor is not BSP or this is one IPI sent by AP\r
2267 //\r
2268 if (mDebugMpContext.BreakAtCpuIndex != (UINT32) (-1)) {\r
2269 CommandCommunication (Vector, CpuContext, FALSE);\r
2270 }\r
2271\r
2272 //\r
2273 // Clear EOI before exiting interrupt process routine.\r
2274 //\r
2275 SendApicEoi ();\r
2276 break;\r
2277 }\r
2278 }\r
2279\r
2280 //\r
2281 // Only BSP could run here\r
2282 //\r
93c0bdec 2283 while (TRUE) {\r
18b144ea 2284 //\r
93c0bdec 2285 // If there is data in debug port, will check whether it is break(attach/break-in) symbol,\r
18b144ea 2286 // If yes, go into communication mode with HOST.\r
2287 // If no, exit interrupt process.\r
2288 //\r
93c0bdec 2289 if (DebugReadBreakSymbol (Handle, &InputCharacter) == EFI_NOT_FOUND) {\r
2290 break;\r
2291 }\r
b422b62c 2292\r
93c0bdec 2293 if ((!IsHostAttached () && (InputCharacter == DEBUG_STARTING_SYMBOL_ATTACH)) ||\r
b422b62c 2294 (IsHostAttached () && (InputCharacter == DEBUG_COMMAND_HALT)) ||\r
2295 (IsHostAttached () && (InputCharacter == DEBUG_COMMAND_GO))\r
93c0bdec 2296 ) {\r
2297 DebugAgentMsgPrint (DEBUG_AGENT_VERBOSE, "Received data [%02x]\n", InputCharacter);\r
2298 //\r
2299 // Ack OK for break-in symbol\r
2300 //\r
18b144ea 2301 SendAckPacket (DEBUG_COMMAND_OK);\r
93c0bdec 2302\r
b422b62c 2303 //\r
2304 // If receive GO command in Debug Timer, means HOST may lost ACK packet before.\r
2305 //\r
2306 if (InputCharacter == DEBUG_COMMAND_GO) {\r
2307 break;\r
2308 }\r
2309\r
93c0bdec 2310 if (!IsHostAttached ()) {\r
2311 //\r
2312 // Try to attach HOST, if no ack received after 200ms, return\r
2313 //\r
b422b62c 2314 if (AttachHost (BreakCause, READ_PACKET_TIMEOUT, &BreakReceived) != RETURN_SUCCESS) {\r
93c0bdec 2315 break;\r
2316 }\r
2317 }\r
2318\r
b422b62c 2319 if (MultiProcessorDebugSupport()) {\r
93c0bdec 2320 if(FindNextPendingBreakCpu () != -1) {\r
18b144ea 2321 SetCpuBreakFlagByIndex (ProcessorIndex, TRUE);\r
2322 } else {\r
2323 HaltOtherProcessors (ProcessorIndex);\r
2324 }\r
2325 }\r
b422b62c 2326 ReleaseMpSpinLock (&mDebugMpContext.DebugPortSpinLock);\r
18b144ea 2327 CommandCommunication (Vector, CpuContext, BreakReceived);\r
b422b62c 2328 AcquireMpSpinLock (&mDebugMpContext.DebugPortSpinLock);\r
18b144ea 2329 break;\r
2330 }\r
2331 }\r
2332\r
2333 //\r
2334 // Clear EOI before exiting interrupt process routine.\r
2335 //\r
2336 SendApicEoi ();\r
2337\r
b422b62c 2338 ReleaseMpSpinLock (&mDebugMpContext.DebugPortSpinLock);\r
18b144ea 2339\r
2340 break;\r
2341\r
2342 default:\r
18b144ea 2343 if (Vector <= DEBUG_EXCEPT_SIMD) {\r
93c0bdec 2344 if (BreakCause == DEBUG_DATA_BREAK_CAUSE_STEPPING) {\r
2345 //\r
2346 // Stepping is finished, send Ack package.\r
2347 //\r
b422b62c 2348 if (MultiProcessorDebugSupport()) {\r
93c0bdec 2349 mDebugMpContext.BreakAtCpuIndex = ProcessorIndex;\r
18b144ea 2350 }\r
93c0bdec 2351 SendAckPacket (DEBUG_COMMAND_OK);\r
2352 } else {\r
2353 //\r
2354 // Exception occurs, send Break packet to HOST\r
2355 //\r
b422b62c 2356 AcquireMpSpinLock (&mDebugMpContext.DebugPortSpinLock);\r
93c0bdec 2357 //\r
2358 // Only the first breaking processor could send BREAK_POINT to HOST\r
2359 // \r
2360 if (IsFirstBreakProcessor (ProcessorIndex)) {\r
b422b62c 2361 SendBreakPacketToHost (BreakCause, ProcessorIndex, &BreakReceived);\r
93c0bdec 2362 }\r
b422b62c 2363 ReleaseMpSpinLock (&mDebugMpContext.DebugPortSpinLock);\r
18b144ea 2364 }\r
93c0bdec 2365 \r
18b144ea 2366 CommandCommunication (Vector, CpuContext, BreakReceived);\r
2367 }\r
2368 break;\r
2369 }\r
2370\r
b422b62c 2371 if (MultiProcessorDebugSupport()) {\r
18b144ea 2372 //\r
2373 // Clear flag and wait for all processors run here\r
2374 //\r
2375 SetIpiSentByApFlag (FALSE);\r
93c0bdec 2376 while (mDebugMpContext.RunCommandSet) {\r
2377 CpuPause ();\r
2378 }\r
2379\r
2380 //\r
2381 // Only current (view) processor could clean up AgentInProgress flag.\r
2382 //\r
2383 if (mDebugMpContext.ViewPointIndex == ProcessorIndex) {\r
2384 IssuedViewPoint = mDebugMpContext.ViewPointIndex;\r
2385 }\r
2386 }\r
2387\r
b422b62c 2388 if (IssuedViewPoint == ProcessorIndex && GetDebugFlag (DEBUG_AGENT_FLAG_STEPPING) != 1) {\r
93c0bdec 2389 //\r
b422b62c 2390 // If the command is not stepping, clean up AgentInProgress flag\r
93c0bdec 2391 //\r
b422b62c 2392 SetDebugFlag (DEBUG_AGENT_FLAG_AGENT_IN_PROGRESS, 0);\r
18b144ea 2393 }\r
2394\r
2395 return;\r
2396}\r
2397\r