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