]> git.proxmox.com Git - mirror_edk2.git/blame - SourceLevelDebugPkg/Library/DebugAgent/DebugAgentCommon/DebugAgent.c
MdeModulePkg: Fix typo.
[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
d9044ec5 7 Copyright (c) 2010 - 2015, 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
d9044ec5
RN
959/**\r
960 Decompress the Data in place.\r
961\r
962 @param[in, out] Data The compressed data buffer.\r
963 The buffer is assumed large enough to hold the uncompressed data.\r
964 @param[in] Length The length of the compressed data buffer.\r
965\r
966 @return The length of the uncompressed data buffer.\r
967**/\r
968UINT8\r
969DecompressDataInPlace (\r
970 IN OUT UINT8 *Data,\r
971 IN UINTN Length\r
972 )\r
973{\r
974 UINTN Index;\r
975 UINT16 LastChar;\r
976 UINTN LastCharCount;\r
977 UINT8 CurrentChar;\r
978\r
979 LastChar = (UINT16) -1;\r
980 LastCharCount = 0;\r
981 for (Index = 0; Index < Length; Index++) {\r
982 CurrentChar = Data[Index];\r
983 if (LastCharCount == 2) {\r
984 LastCharCount = 0;\r
985 CopyMem (&Data[Index + CurrentChar], &Data[Index + 1], Length - Index - 1);\r
986 SetMem (&Data[Index], CurrentChar, (UINT8) LastChar);\r
987 LastChar = (UINT16) -1;\r
988 Index += CurrentChar - 1;\r
989 Length += CurrentChar - 1;\r
990 } else {\r
991 if (LastChar != CurrentChar) {\r
992 LastCharCount = 0;\r
993 }\r
994 LastCharCount++;\r
995 LastChar = CurrentChar;\r
996 }\r
997 }\r
998\r
999 ASSERT (Length <= DEBUG_DATA_MAXIMUM_REAL_DATA);\r
1000\r
1001 return (UINT8) Length;\r
1002}\r
1003\r
18b144ea 1004/**\r
b422b62c 1005 Receive valid packet from HOST.\r
18b144ea 1006\r
b422b62c 1007 @param[out] InputPacket Buffer to receive packet.\r
1008 @param[out] BreakReceived TRUE means break-in symbol received.\r
1009 FALSE means break-in symbol not received.\r
1010 @param[out] IncompatibilityFlag If IncompatibilityFlag is not NULL, return\r
1011 TRUE: Compatible packet received.\r
1012 FALSE: Incompatible packet received.\r
1013 @param[in] Timeout Time out value to wait for acknowlege from HOST.\r
1014 The unit is microsecond.\r
1015 @param[in] SkipStartSymbol TRUE: Skip time out when reading start symbol.\r
1016 FALSE: Does not Skip time out when reading start symbol.\r
18b144ea 1017\r
b422b62c 1018 @retval RETURN_SUCCESS A valid package was reveived in InputPacket.\r
1019 @retval RETURN_TIMEOUT Timeout occurs.\r
18b144ea 1020\r
1021**/\r
1022RETURN_STATUS\r
b422b62c 1023ReceivePacket (\r
1024 OUT UINT8 *InputPacket,\r
1025 OUT BOOLEAN *BreakReceived,\r
1026 OUT BOOLEAN *IncompatibilityFlag, OPTIONAL\r
1027 IN UINTN Timeout,\r
1028 IN BOOLEAN SkipStartSymbol\r
18b144ea 1029 )\r
1030{\r
b422b62c 1031 DEBUG_PACKET_HEADER *DebugHeader;\r
1032 UINTN Received;\r
1033 DEBUG_PORT_HANDLE Handle;\r
1034 UINT16 Crc;\r
1035 UINTN TimeoutForStartSymbol;\r
18b144ea 1036\r
1037 Handle = GetDebugPortHandle();\r
b422b62c 1038 if (SkipStartSymbol) {\r
1039 TimeoutForStartSymbol = 0;\r
1040 } else {\r
1041 TimeoutForStartSymbol = Timeout;\r
1042 }\r
4fe43eb3 1043\r
b422b62c 1044 DebugHeader = (DEBUG_PACKET_HEADER *) InputPacket;\r
18b144ea 1045 while (TRUE) {\r
b422b62c 1046 //\r
1047 // Find the valid start symbol\r
1048 //\r
1049 Received = DebugPortReadBuffer (Handle, &DebugHeader->StartSymbol, sizeof (DebugHeader->StartSymbol), TimeoutForStartSymbol);\r
1050 if (Received < sizeof (DebugHeader->StartSymbol)) {\r
1051 DebugAgentMsgPrint (DEBUG_AGENT_WARNING, "DebugPortReadBuffer(StartSymbol) timeout\n");\r
18b144ea 1052 return RETURN_TIMEOUT;\r
1053 }\r
b422b62c 1054\r
d9044ec5 1055 if ((DebugHeader->StartSymbol != DEBUG_STARTING_SYMBOL_NORMAL) && (DebugHeader->StartSymbol != DEBUG_STARTING_SYMBOL_COMPRESS)) {\r
b422b62c 1056 DebugAgentMsgPrint (DEBUG_AGENT_WARNING, "Invalid start symbol received [%02x]\n", DebugHeader->StartSymbol);\r
1057 continue;\r
18b144ea 1058 }\r
18b144ea 1059\r
93c0bdec 1060 //\r
b422b62c 1061 // Read Package header till field Length\r
93c0bdec 1062 //\r
b422b62c 1063 Received = DebugPortReadBuffer (\r
1064 Handle,\r
d9044ec5 1065 (UINT8 *) DebugHeader + OFFSET_OF (DEBUG_PACKET_HEADER, Command),\r
b422b62c 1066 OFFSET_OF (DEBUG_PACKET_HEADER, Length) + sizeof (DebugHeader->Length) - sizeof (DebugHeader->StartSymbol),\r
1067 Timeout\r
1068 );\r
1069 if (Received == 0) {\r
1070 DebugAgentMsgPrint (DEBUG_AGENT_ERROR, "DebugPortReadBuffer(Command) timeout\n");\r
93c0bdec 1071 return RETURN_TIMEOUT;\r
1072 }\r
b422b62c 1073 if (DebugHeader->Length < sizeof (DEBUG_PACKET_HEADER)) {\r
1074 if (IncompatibilityFlag != NULL) {\r
1075 //\r
1076 // This is one old version debug packet format, set Incompatibility flag\r
1077 //\r
1078 *IncompatibilityFlag = TRUE;\r
1079 } else {\r
1080 //\r
1081 // Skip the bad small packet\r
1082 //\r
1083 continue;\r
1084 }\r
1085 } else {\r
1086 //\r
1087 // Read the payload data include the CRC field\r
1088 //\r
1089 Received = DebugPortReadBuffer (Handle, &DebugHeader->SequenceNo, (UINT8) (DebugHeader->Length - OFFSET_OF (DEBUG_PACKET_HEADER, SequenceNo)), Timeout);\r
1090 if (Received == 0) {\r
1091 DebugAgentMsgPrint (DEBUG_AGENT_ERROR, "DebugPortReadBuffer(SequenceNo) timeout\n");\r
1092 return RETURN_TIMEOUT;\r
1093 }\r
1094 //\r
1095 // Calculate the CRC of Debug Packet\r
1096 //\r
1097 Crc = DebugHeader->Crc;\r
1098 DebugHeader->Crc = 0;\r
1099 if (Crc == CalculateCrc16 ((UINT8 *) DebugHeader, DebugHeader->Length, 0)) {\r
1100 break;\r
1101 }\r
1102 DebugAgentMsgPrint (DEBUG_AGENT_WARNING, "CRC Error (received CRC is %x)\n", Crc);\r
1103 DebugAgentDataMsgPrint (DEBUG_AGENT_VERBOSE, FALSE, (UINT8 *) DebugHeader, DebugHeader->Length);\r
1104 }\r
93c0bdec 1105 }\r
1106\r
b422b62c 1107 DebugAgentDataMsgPrint (DEBUG_AGENT_VERBOSE, FALSE, (UINT8 *) DebugHeader, DebugHeader->Length);\r
1108\r
d9044ec5
RN
1109 if (DebugHeader->StartSymbol == DEBUG_STARTING_SYMBOL_COMPRESS) {\r
1110 DebugHeader->StartSymbol = DEBUG_STARTING_SYMBOL_NORMAL;\r
1111 DebugHeader->Length = DecompressDataInPlace (\r
1112 (UINT8 *) (DebugHeader + 1), DebugHeader->Length - sizeof (DEBUG_PACKET_HEADER)\r
1113 ) + sizeof (DEBUG_PACKET_HEADER);\r
1114 }\r
18b144ea 1115 return RETURN_SUCCESS;\r
1116}\r
1117\r
1118/**\r
1119 Receive acknowledge packet OK from HOST in specified time.\r
1120\r
b422b62c 1121 @param[in] Command The command type issued by TARGET.\r
1122 @param[in] Timeout Time out value to wait for acknowlege from HOST.\r
1123 The unit is microsecond.\r
1124 @param[out] BreakReceived If BreakReceived is not NULL,\r
1125 TRUE is retured if break-in symbol received.\r
1126 FALSE is retured if break-in symbol not received.\r
1127 @param[out] IncompatibilityFlag If IncompatibilityFlag is not NULL, return\r
1128 TRUE: Compatible packet received.\r
1129 FALSE: Incompatible packet received.\r
18b144ea 1130\r
1131 @retval RETRUEN_SUCCESS Succeed to receive acknowlege packet from HOST,\r
1132 the type of acknowlege packet saved in Ack.\r
1133 @retval RETURN_TIMEOUT Specified timeout value was up.\r
1134\r
1135**/\r
1136RETURN_STATUS\r
93c0bdec 1137SendCommandAndWaitForAckOK (\r
1138 IN UINT8 Command,\r
1139 IN UINTN Timeout,\r
1140 OUT BOOLEAN *BreakReceived, OPTIONAL\r
b422b62c 1141 OUT BOOLEAN *IncompatibilityFlag OPTIONAL\r
18b144ea 1142 )\r
1143{\r
93c0bdec 1144 RETURN_STATUS Status;\r
b422b62c 1145 UINT8 InputPacketBuffer[DEBUG_DATA_UPPER_LIMIT];\r
1146 DEBUG_PACKET_HEADER *DebugHeader;\r
1147 UINT8 SequenceNo;\r
1148 UINT8 HostSequenceNo;\r
1149 UINT8 RetryCount;\r
1150\r
1151 RetryCount = 3;\r
1152 DebugHeader = (DEBUG_PACKET_HEADER *) InputPacketBuffer;\r
1153 Status = RETURN_TIMEOUT;\r
1154 while (RetryCount > 0) {\r
1155 SequenceNo = GetMailboxPointer()->SequenceNo;\r
1156 HostSequenceNo = GetMailboxPointer()->HostSequenceNo;\r
1157 SendPacketWithoutData (Command, SequenceNo);\r
1158 Status = ReceivePacket ((UINT8 *) DebugHeader, BreakReceived, IncompatibilityFlag, Timeout, FALSE);\r
1159 if (Status == RETURN_TIMEOUT) {\r
1160 if (Command == DEBUG_COMMAND_INIT_BREAK) {\r
1161 RetryCount--;\r
1162 } else {\r
1163 DebugAgentMsgPrint (DEBUG_AGENT_WARNING, "TARGET: Timeout when waiting for ACK packet.\n");\r
1164 }\r
93c0bdec 1165 continue;\r
1166 }\r
b422b62c 1167 ASSERT_EFI_ERROR (Status);\r
93c0bdec 1168 //\r
b422b62c 1169 // Status == RETURN_SUCCESS\r
93c0bdec 1170 //\r
b422b62c 1171 if (DebugHeader->Command == DEBUG_COMMAND_OK && DebugHeader->SequenceNo == SequenceNo) {\r
1172 //\r
1173 // Received Ack OK\r
1174 //\r
1175 UpdateMailboxContent (GetMailboxPointer(), DEBUG_MAILBOX_SEQUENCE_NO_INDEX, ++SequenceNo);\r
1176 return Status;\r
18b144ea 1177 }\r
b422b62c 1178 if (DebugHeader->Command == DEBUG_COMMAND_GO && (DebugHeader->SequenceNo == HostSequenceNo || Command == DEBUG_COMMAND_INIT_BREAK)) {\r
1179 //\r
1180 // Received Old GO\r
1181 //\r
1182 if (Command == DEBUG_COMMAND_INIT_BREAK) {\r
1183 DebugAgentMsgPrint (DEBUG_AGENT_WARNING, "TARGET: Receive GO() in last boot\n");\r
1184 }\r
1185 SendPacketWithoutData (DEBUG_COMMAND_OK, DebugHeader->SequenceNo);\r
93c0bdec 1186 }\r
18b144ea 1187 }\r
1188\r
b422b62c 1189 ASSERT (Command == DEBUG_COMMAND_INIT_BREAK);\r
1190 return Status;\r
18b144ea 1191}\r
1192\r
1193/**\r
1194 Get current break cause.\r
1195\r
1196 @param[in] Vector Vector value of exception or interrupt.\r
1197 @param[in] CpuContext Pointer to save CPU context.\r
1198\r
1199 @return The type of break cause defined by XXXX\r
1200\r
1201**/\r
1202UINT8\r
1203GetBreakCause (\r
1204 IN UINTN Vector,\r
1205 IN DEBUG_CPU_CONTEXT *CpuContext\r
1206 )\r
1207{\r
1208 UINT8 Cause;\r
1209\r
1210 Cause = DEBUG_DATA_BREAK_CAUSE_UNKNOWN;\r
1211\r
1212 switch (Vector) {\r
1213 case DEBUG_INT1_VECTOR:\r
1214 case DEBUG_INT3_VECTOR:\r
1215\r
1216 if (Vector == DEBUG_INT1_VECTOR) {\r
1217 //\r
1218 // INT 1\r
1219 //\r
1220 if ((CpuContext->Dr6 & BIT14) != 0) {\r
1221 Cause = DEBUG_DATA_BREAK_CAUSE_STEPPING;\r
0a16169b 1222 //\r
1223 // If it's single step, no need to check DR0, to ensure single step work in PeCoffExtraActionLib\r
1224 // (right after triggering a breakpoint to report image load/unload).\r
1225 //\r
1226 return Cause;\r
18b144ea 1227\r
1228 } else {\r
1229 Cause = DEBUG_DATA_BREAK_CAUSE_HW_BREAKPOINT;\r
1230 }\r
1231 } else {\r
1232 //\r
1233 // INT 3\r
1234 //\r
1235 Cause = DEBUG_DATA_BREAK_CAUSE_SW_BREAKPOINT;\r
1236 }\r
1237\r
1238 switch (CpuContext->Dr0) {\r
1239 case IMAGE_LOAD_SIGNATURE:\r
1240 case IMAGE_UNLOAD_SIGNATURE:\r
1241\r
1242 if (CpuContext->Dr3 == IO_PORT_BREAKPOINT_ADDRESS) {\r
1243\r
4fe43eb3 1244 Cause = (UINT8) ((CpuContext->Dr0 == IMAGE_LOAD_SIGNATURE) ?\r
18b144ea 1245 DEBUG_DATA_BREAK_CAUSE_IMAGE_LOAD : DEBUG_DATA_BREAK_CAUSE_IMAGE_UNLOAD);\r
1246 }\r
1247 break;\r
1248\r
1249 case SOFT_INTERRUPT_SIGNATURE:\r
4fe43eb3 1250\r
18b144ea 1251 if (CpuContext->Dr1 == MEMORY_READY_SIGNATURE) {\r
1252 Cause = DEBUG_DATA_BREAK_CAUSE_MEMORY_READY;\r
1253 CpuContext->Dr0 = 0;\r
1254 } else if (CpuContext->Dr1 == SYSTEM_RESET_SIGNATURE) {\r
1255 Cause = DEBUG_DATA_BREAK_CAUSE_SYSTEM_RESET;\r
1256 CpuContext->Dr0 = 0;\r
1257 }\r
1258 break;\r
1259\r
1260 default:\r
1261 break;\r
1262\r
1263 }\r
1264\r
1265 break;\r
1266\r
1267 case DEBUG_TIMER_VECTOR:\r
1268 Cause = DEBUG_DATA_BREAK_CAUSE_USER_HALT;\r
1269 break;\r
1270\r
1271 default:\r
1272 if (Vector < 20) {\r
b422b62c 1273 if (GetDebugFlag (DEBUG_AGENT_FLAG_STEPPING) == 1) {\r
93c0bdec 1274 //\r
1275 // If stepping command is executing\r
1276 //\r
1277 Cause = DEBUG_DATA_BREAK_CAUSE_STEPPING;\r
1278 } else {\r
1279 Cause = DEBUG_DATA_BREAK_CAUSE_EXCEPTION;\r
1280 }\r
18b144ea 1281 }\r
1282 break;\r
1283 }\r
1284\r
1285 return Cause;\r
1286}\r
1287\r
1288/**\r
845a7fe0 1289 Copy memory from source to destination with specified width.\r
1290\r
1291 @param[out] Dest A pointer to the destination buffer of the memory copy.\r
1292 @param[in] Src A pointer to the source buffer of the memory copy.\r
1293 @param[in] Count The number of data with specified width to copy from source to destination.\r
1294 @param[in] Width Data width in byte.\r
1295\r
1296**/\r
1297VOID\r
1298CopyMemByWidth (\r
1299 OUT UINT8 *Dest,\r
1300 IN UINT8 *Src,\r
1301 IN UINT16 Count,\r
1302 IN UINT8 Width\r
1303 )\r
1304{\r
1305 UINT8 *Destination;\r
1306 UINT8 *Source;\r
1307 INT8 Step;\r
1308\r
1309 if (Src > Dest) {\r
1310 Destination = Dest;\r
1311 Source = Src;\r
1312 Step = Width;\r
1313 } else {\r
1314 //\r
1315 // Copy memory from tail to avoid memory overlap\r
1316 //\r
1317 Destination = Dest + (Count - 1) * Width;\r
1318 Source = Src + (Count - 1) * Width;\r
1319 Step = -Width;\r
1320 }\r
1321\r
1322 while (Count-- != 0) {\r
1323 switch (Width) {\r
1324 case 1:\r
1325 *(UINT8 *) Destination = MmioRead8 ((UINTN) Source);\r
1326 break;\r
1327 case 2:\r
1328 *(UINT16 *) Destination = MmioRead16 ((UINTN) Source);\r
1329 break;\r
1330 case 4:\r
1331 *(UINT32 *) Destination = MmioRead32 ((UINTN) Source);\r
1332 break;\r
1333 case 8:\r
1334 *(UINT64 *) Destination = MmioRead64 ((UINTN) Source);\r
1335 break;\r
1336 default:\r
1337 ASSERT (FALSE);\r
1338 }\r
1339 Source += Step;\r
1340 Destination += Step;\r
1341 }\r
1342}\r
1343\r
d9044ec5
RN
1344/**\r
1345 Compress the data buffer but do not modify the original buffer.\r
1346\r
1347 The compressed data is directly send to the debug channel.\r
1348 Compressing in place doesn't work because the data may become larger\r
1349 during compressing phase. ("3 3 ..." --> "3 3 0 ...")\r
1350 The routine is expected to be called three times:\r
1351 1. Compute the length of the compressed data buffer;\r
1352 2. Compute the CRC of the compressed data buffer;\r
1353 3. Compress the data and send to the debug channel.\r
1354\r
1355 @param[in] Data The data buffer.\r
1356 @param[in] Length The length of the data buffer.\r
1357 @param[out] CompressedLength Return the length of the compressed data buffer.\r
1358 It may be larger than the Length in some cases.\r
1359 @param[out] CompressedCrc Return the CRC of the compressed data buffer.\r
1360 @param[in] Handle The debug channel handle to send the compressed data buffer.\r
1361**/\r
1362VOID\r
1363CompressDataThenSend (\r
1364 IN UINT8 *Data,\r
1365 IN UINT8 Length,\r
1366 OUT UINTN *CompressedLength, OPTIONAL\r
1367 OUT UINT16 *CompressedCrc, OPTIONAL\r
1368 IN DEBUG_PORT_HANDLE Handle OPTIONAL\r
1369 )\r
1370{\r
1371 UINTN Index;\r
1372 UINT8 LastChar;\r
1373 UINT8 LastCharCount;\r
1374 UINT8 CurrentChar;\r
1375 UINTN CompressedIndex;\r
1376\r
1377 ASSERT (Length > 0);\r
1378\r
1379 LastChar = Data[0] + 1; // Just ensure it's different from the first byte.\r
1380 LastCharCount = 0;\r
1381\r
1382 for (Index = 0, CompressedIndex = 0; Index <= Length; Index++) {\r
1383 if (Index < Length) {\r
1384 CurrentChar = Data[Index];\r
1385 } else {\r
1386 CurrentChar = (UINT8) LastChar + 1; // just ensure it's different from LastChar\r
1387 }\r
1388 if (LastChar != CurrentChar) {\r
1389 if (LastCharCount == 1) {\r
1390 CompressedIndex++;\r
1391 if (CompressedCrc != NULL) {\r
1392 *CompressedCrc = CalculateCrc16 (&LastChar, 1, *CompressedCrc);\r
1393 }\r
1394 if (Handle != NULL) {\r
1395 DebugPortWriteBuffer (Handle, &LastChar, 1);\r
1396 }\r
1397 \r
1398 } else if (LastCharCount >= 2) {\r
1399 CompressedIndex += 3;\r
1400 LastCharCount -= 2;\r
1401 if (CompressedCrc != NULL) {\r
1402 *CompressedCrc = CalculateCrc16 (&LastChar, 1, *CompressedCrc);\r
1403 *CompressedCrc = CalculateCrc16 (&LastChar, 1, *CompressedCrc);\r
1404 *CompressedCrc = CalculateCrc16 (&LastCharCount, 1, *CompressedCrc);\r
1405 }\r
1406 if (Handle != NULL) {\r
1407 DebugPortWriteBuffer (Handle, &LastChar, 1);\r
1408 DebugPortWriteBuffer (Handle, &LastChar, 1);\r
1409 DebugPortWriteBuffer (Handle, &LastCharCount, 1);\r
1410 }\r
1411 }\r
1412 LastCharCount = 0;\r
1413 }\r
1414 LastCharCount++;\r
1415 LastChar = CurrentChar;\r
1416 }\r
1417\r
1418 if (CompressedLength != NULL) {\r
1419 *CompressedLength = CompressedIndex;\r
1420 }\r
1421}\r
1422\r
845a7fe0 1423/**\r
1424 Read memory with speicifed width and send packet with response data to HOST.\r
18b144ea 1425\r
18b144ea 1426 @param[in] Data Pointer to response data buffer.\r
845a7fe0 1427 @param[in] Count The number of data with specified Width.\r
1428 @param[in] Width Data width in byte.\r
d9044ec5
RN
1429 @param[in] DebugHeader Pointer to a buffer for creating response packet and receiving ACK packet,\r
1430 to minimize the stack usage.\r
18b144ea 1431\r
1432 @retval RETURN_SUCCESS Response data was sent successfully.\r
18b144ea 1433\r
1434**/\r
1435RETURN_STATUS\r
845a7fe0 1436ReadMemoryAndSendResponsePacket (\r
d9044ec5
RN
1437 IN UINT8 *Data,\r
1438 IN UINT16 Count,\r
1439 IN UINT8 Width,\r
1440 IN DEBUG_PACKET_HEADER *DebugHeader\r
18b144ea 1441 )\r
1442{\r
b422b62c 1443 RETURN_STATUS Status;\r
18b144ea 1444 BOOLEAN LastPacket;\r
18b144ea 1445 DEBUG_PORT_HANDLE Handle;\r
b422b62c 1446 UINT8 SequenceNo;\r
845a7fe0 1447 UINTN RemainingDataSize;\r
d9044ec5
RN
1448 UINT8 CurrentDataSize;\r
1449 UINTN CompressedDataSize;\r
18b144ea 1450\r
1451 Handle = GetDebugPortHandle();\r
1452\r
845a7fe0 1453 RemainingDataSize = Count * Width;\r
18b144ea 1454 while (TRUE) {\r
b422b62c 1455 SequenceNo = GetMailboxPointer()->HostSequenceNo;\r
845a7fe0 1456 if (RemainingDataSize <= DEBUG_DATA_MAXIMUM_REAL_DATA) {\r
1457 //\r
1458 // If the remaining data is less one real packet size, this is the last data packet\r
1459 //\r
d9044ec5 1460 CurrentDataSize = (UINT8) RemainingDataSize;\r
18b144ea 1461 LastPacket = TRUE;\r
845a7fe0 1462 DebugHeader->Command = DEBUG_COMMAND_OK;\r
18b144ea 1463 } else {\r
845a7fe0 1464 //\r
1465 // Data is too larger to be sent in one packet, calculate the actual data size could\r
1466 // be sent in one Maximum data packet\r
1467 //\r
1468 CurrentDataSize = (DEBUG_DATA_MAXIMUM_REAL_DATA / Width) * Width;\r
18b144ea 1469 LastPacket = FALSE;\r
845a7fe0 1470 DebugHeader->Command = DEBUG_COMMAND_IN_PROGRESS;\r
18b144ea 1471 }\r
93c0bdec 1472 //\r
845a7fe0 1473 // Construct the rest Debug header\r
1474 //\r
d9044ec5
RN
1475 DebugHeader->StartSymbol = DEBUG_STARTING_SYMBOL_NORMAL;\r
1476 DebugHeader->Length = CurrentDataSize + sizeof (DEBUG_PACKET_HEADER);\r
1477 DebugHeader->SequenceNo = SequenceNo;\r
1478 DebugHeader->Crc = 0;\r
1479 CopyMemByWidth ((UINT8 *) (DebugHeader + 1), Data, CurrentDataSize / Width, Width);\r
1480\r
845a7fe0 1481 //\r
d9044ec5
RN
1482 // Compression/decompression support was added since revision 0.4.\r
1483 // Revision 0.3 shouldn't compress the packet.\r
93c0bdec 1484 //\r
d9044ec5
RN
1485 if (DEBUG_AGENT_REVISION >= DEBUG_AGENT_REVISION_04) {\r
1486 //\r
1487 // Get the compressed data size without modifying the packet.\r
1488 //\r
1489 CompressDataThenSend (\r
1490 (UINT8 *) (DebugHeader + 1),\r
1491 CurrentDataSize,\r
1492 &CompressedDataSize,\r
1493 NULL,\r
1494 NULL\r
1495 );\r
1496 } else {\r
1497 CompressedDataSize = CurrentDataSize;\r
1498 }\r
1499 if (CompressedDataSize < CurrentDataSize) {\r
1500 DebugHeader->Length = (UINT8) CompressedDataSize + sizeof (DEBUG_PACKET_HEADER);\r
1501 DebugHeader->StartSymbol = DEBUG_STARTING_SYMBOL_COMPRESS;\r
1502 //\r
1503 // Compute the CRC of the packet head without modifying the packet.\r
1504 //\r
1505 DebugHeader->Crc = CalculateCrc16 ((UINT8 *) DebugHeader, sizeof (DEBUG_PACKET_HEADER), 0);\r
1506 CompressDataThenSend (\r
1507 (UINT8 *) (DebugHeader + 1),\r
1508 CurrentDataSize,\r
1509 NULL,\r
1510 &DebugHeader->Crc,\r
1511 NULL\r
1512 );\r
1513 //\r
1514 // Send out the packet head.\r
1515 //\r
1516 DebugPortWriteBuffer (Handle, (UINT8 *) DebugHeader, sizeof (DEBUG_PACKET_HEADER));\r
1517 //\r
1518 // Compress and send out the packet data.\r
1519 //\r
1520 CompressDataThenSend (\r
1521 (UINT8 *) (DebugHeader + 1),\r
1522 CurrentDataSize,\r
1523 NULL,\r
1524 NULL,\r
1525 Handle\r
1526 );\r
1527 } else {\r
93c0bdec 1528\r
d9044ec5
RN
1529 //\r
1530 // Calculate and fill the checksum, DebugHeader->Crc should be 0 before invoking CalculateCrc16 ()\r
1531 //\r
1532 DebugHeader->Crc = CalculateCrc16 ((UINT8 *) DebugHeader, DebugHeader->Length, 0);\r
4fe43eb3 1533\r
d9044ec5
RN
1534 DebugAgentDataMsgPrint (DEBUG_AGENT_VERBOSE, TRUE, (UINT8 *) DebugHeader, DebugHeader->Length);\r
1535\r
1536 DebugPortWriteBuffer (Handle, (UINT8 *) DebugHeader, DebugHeader->Length);\r
1537 }\r
18b144ea 1538\r
b422b62c 1539 while (TRUE) {\r
d9044ec5 1540 Status = ReceivePacket ((UINT8 *) DebugHeader, NULL, NULL, READ_PACKET_TIMEOUT, FALSE);\r
b422b62c 1541 if (Status == RETURN_TIMEOUT) {\r
1542 DebugAgentMsgPrint (DEBUG_AGENT_WARNING, "TARGET: Timeout in SendDataResponsePacket()\n");\r
1543 break;\r
1544 }\r
d9044ec5 1545 if ((DebugHeader->Command == DEBUG_COMMAND_OK) && (DebugHeader->SequenceNo == SequenceNo) && LastPacket) {\r
18b144ea 1546 //\r
1547 // If this is the last packet, return RETURN_SUCCESS.\r
1548 //\r
1549 return RETURN_SUCCESS;\r
18b144ea 1550 }\r
d9044ec5 1551 if ((DebugHeader->Command == DEBUG_COMMAND_CONTINUE) && (DebugHeader->SequenceNo == (UINT8) (SequenceNo + 1))) {\r
b422b62c 1552 //\r
845a7fe0 1553 // Calculate the rest data size\r
b422b62c 1554 //\r
845a7fe0 1555 Data += CurrentDataSize;\r
1556 RemainingDataSize -= CurrentDataSize;\r
d9044ec5 1557 UpdateMailboxContent (GetMailboxPointer(), DEBUG_MAILBOX_HOST_SEQUENCE_NO_INDEX, DebugHeader->SequenceNo);\r
b422b62c 1558 break;\r
1559 }\r
d9044ec5 1560 if (DebugHeader->SequenceNo >= SequenceNo) {\r
b422b62c 1561 DebugAgentMsgPrint (DEBUG_AGENT_WARNING, "TARGET: Received one old or new command(SequenceNo is %x, last SequenceNo is %x)\n", SequenceNo, DebugHeader->SequenceNo);\r
1562 break;\r
1563 }\r
18b144ea 1564 }\r
1565 }\r
1566}\r
1567\r
845a7fe0 1568/**\r
1569 Send packet with response data to HOST.\r
1570\r
d9044ec5
RN
1571 @param[in] Data Pointer to response data buffer.\r
1572 @param[in] DataSize Size of response data in byte.\r
1573 @param[in, out] DebugHeader Pointer to a buffer for creating response packet and receiving ACK packet,\r
1574 to minimize the stack usage.\r
845a7fe0 1575\r
1576 @retval RETURN_SUCCESS Response data was sent successfully.\r
1577\r
1578**/\r
1579RETURN_STATUS\r
1580SendDataResponsePacket (\r
d9044ec5
RN
1581 IN UINT8 *Data,\r
1582 IN UINT16 DataSize,\r
1583 IN OUT DEBUG_PACKET_HEADER *DebugHeader\r
18b144ea 1584 )\r
1585{\r
d9044ec5 1586 return ReadMemoryAndSendResponsePacket (Data, DataSize, 1, DebugHeader);\r
18b144ea 1587}\r
1588\r
93c0bdec 1589/**\r
1590 Try to attach the HOST.\r
4fe43eb3 1591\r
93c0bdec 1592 Send init break packet to HOST:\r
4fe43eb3
JF
1593 If no acknowlege received in specified Timeout, return RETURN_TIMEOUT.\r
1594 If received acknowlege, check the revision of HOST.\r
1595 Set Attach Flag if attach successfully.\r
1596\r
b422b62c 1597 @param[in] BreakCause Break cause of this break event.\r
93c0bdec 1598 @param[in] Timeout Time out value to wait for acknowlege from HOST.\r
1599 The unit is microsecond.\r
1600 @param[out] BreakReceived If BreakReceived is not NULL,\r
1601 TRUE is retured if break-in symbol received.\r
1602 FALSE is retured if break-in symbol not received.\r
1603**/\r
1604RETURN_STATUS\r
1605AttachHost (\r
b422b62c 1606 IN UINT8 BreakCause,\r
93c0bdec 1607 IN UINTN Timeout,\r
1608 OUT BOOLEAN *BreakReceived\r
1609 )\r
1610{\r
1611 RETURN_STATUS Status;\r
1612 DEBUG_PORT_HANDLE Handle;\r
b422b62c 1613 BOOLEAN IncompatibilityFlag;\r
93c0bdec 1614\r
b422b62c 1615 IncompatibilityFlag = FALSE;\r
93c0bdec 1616 Handle = GetDebugPortHandle();\r
4fe43eb3 1617\r
93c0bdec 1618 //\r
1619 // Send init break and wait ack in Timeout\r
1620 //\r
1621 DebugPortWriteBuffer (Handle, (UINT8 *) mErrorMsgSendInitPacket, AsciiStrLen (mErrorMsgSendInitPacket));\r
b422b62c 1622 if (BreakCause == DEBUG_DATA_BREAK_CAUSE_SYSTEM_RESET) {\r
1623 Status = SendCommandAndWaitForAckOK (DEBUG_COMMAND_INIT_BREAK, Timeout, BreakReceived, &IncompatibilityFlag);\r
1624 } else {\r
1625 Status = SendCommandAndWaitForAckOK (DEBUG_COMMAND_ATTACH_BREAK, Timeout, BreakReceived, &IncompatibilityFlag);\r
93c0bdec 1626 }\r
b422b62c 1627 if (IncompatibilityFlag) {\r
93c0bdec 1628 //\r
b422b62c 1629 // If the incompatible Debug Packet received, the HOST should be running transfer protocol before DEBUG_AGENT_REVISION.\r
1630 // It could be UDK Debugger for Windows v1.1/v1.2 or for Linux v0.8/v1.2.\r
93c0bdec 1631 //\r
1632 DebugPortWriteBuffer (Handle, (UINT8 *) mErrorMsgVersionAlert, AsciiStrLen (mErrorMsgVersionAlert));\r
1633 CpuDeadLoop ();\r
1634 }\r
4fe43eb3 1635\r
b422b62c 1636 if (RETURN_ERROR (Status)) {\r
1637 DebugPortWriteBuffer (Handle, (UINT8 *) mErrorMsgConnectFail, AsciiStrLen (mErrorMsgConnectFail));\r
1638 } else {\r
1639 DebugPortWriteBuffer (Handle, (UINT8 *) mErrorMsgConnectOK, AsciiStrLen (mErrorMsgConnectOK));\r
1640 //\r
1641 // Set Attach flag\r
1642 //\r
1643 SetHostAttached (TRUE);\r
1644 }\r
93c0bdec 1645 return Status;\r
1646}\r
1647\r
1648/**\r
4fe43eb3
JF
1649 Send Break point packet to HOST.\r
1650\r
93c0bdec 1651 Only the first breaking processor could sent BREAK_POINT packet.\r
b422b62c 1652\r
1653 @param[in] BreakCause Break cause of this break event.\r
93c0bdec 1654 @param[in] ProcessorIndex Processor index value.\r
1655 @param[out] BreakReceived If BreakReceived is not NULL,\r
1656 TRUE is retured if break-in symbol received.\r
1657 FALSE is retured if break-in symbol not received.\r
4fe43eb3 1658\r
93c0bdec 1659**/\r
1660VOID\r
1661SendBreakPacketToHost (\r
b422b62c 1662 IN UINT8 BreakCause,\r
93c0bdec 1663 IN UINT32 ProcessorIndex,\r
1664 OUT BOOLEAN *BreakReceived\r
1665 )\r
1666{\r
1667 UINT8 InputCharacter;\r
1668 DEBUG_PORT_HANDLE Handle;\r
4fe43eb3 1669\r
93c0bdec 1670 Handle = GetDebugPortHandle();\r
4fe43eb3 1671\r
93c0bdec 1672 if (IsHostAttached ()) {\r
1673 DebugAgentMsgPrint (DEBUG_AGENT_INFO, "processor[%x]:Send Break Packet to HOST.\n", ProcessorIndex);\r
b422b62c 1674 SendCommandAndWaitForAckOK (DEBUG_COMMAND_BREAK_POINT, READ_PACKET_TIMEOUT, BreakReceived, NULL);\r
93c0bdec 1675 } else {\r
1676 DebugAgentMsgPrint (DEBUG_AGENT_INFO, "processor[%x]:Try to attach HOST.\n", ProcessorIndex);\r
1677 //\r
1678 // If HOST is not attached, try to attach it firstly.\r
1679 //\r
1680 //\r
1681 // Poll Attach symbols from HOST and ack OK\r
4fe43eb3 1682 //\r
93c0bdec 1683 do {\r
1684 DebugPortReadBuffer (Handle, &InputCharacter, 1, 0);\r
1685 } while (InputCharacter != DEBUG_STARTING_SYMBOL_ATTACH);\r
1686 SendAckPacket (DEBUG_COMMAND_OK);\r
4fe43eb3 1687\r
93c0bdec 1688 //\r
1689 // Try to attach HOST\r
1690 //\r
b422b62c 1691 while (AttachHost (BreakCause, 0, NULL) != RETURN_SUCCESS);\r
4fe43eb3 1692\r
93c0bdec 1693 }\r
1694}\r
18b144ea 1695\r
1696/**\r
1697 The main function to process communication with HOST.\r
1698\r
1699 It received the command packet from HOST, and sent response data packet to HOST.\r
1700\r
1701 @param[in] Vector Vector value of exception or interrutp.\r
1702 @param[in, out] CpuContext Pointer to saved CPU context.\r
1703 @param[in] BreakReceived TRUE means break-in symbol received.\r
1704 FALSE means break-in symbol not received.\r
1705\r
1706**/\r
1707VOID\r
1708CommandCommunication (\r
1709 IN UINTN Vector,\r
1710 IN OUT DEBUG_CPU_CONTEXT *CpuContext,\r
1711 IN BOOLEAN BreakReceived\r
1712 )\r
1713{\r
93c0bdec 1714 RETURN_STATUS Status;\r
845a7fe0 1715 UINT8 InputPacketBuffer[DEBUG_DATA_UPPER_LIMIT + sizeof (UINT64) - 1];\r
93c0bdec 1716 DEBUG_PACKET_HEADER *DebugHeader;\r
1717 UINT8 Width;\r
1718 UINT8 Data8;\r
1719 UINT32 Data32;\r
1720 UINT64 Data64;\r
1721 DEBUG_DATA_READ_MEMORY *MemoryRead;\r
1722 DEBUG_DATA_WRITE_MEMORY *MemoryWrite;\r
1723 DEBUG_DATA_READ_IO *IoRead;\r
1724 DEBUG_DATA_WRITE_IO *IoWrite;\r
1725 DEBUG_DATA_READ_REGISTER *RegisterRead;\r
1726 DEBUG_DATA_WRITE_REGISTER *RegisterWrite;\r
1727 UINT8 *RegisterBuffer;\r
1728 DEBUG_DATA_READ_MSR *MsrRegisterRead;\r
1729 DEBUG_DATA_WRITE_MSR *MsrRegisterWrite;\r
1730 DEBUG_DATA_CPUID *Cpuid;\r
d9044ec5 1731 DEBUG_DATA_RESPONSE_BREAK_CAUSE BreakCause;\r
93c0bdec 1732 DEBUG_DATA_RESPONSE_CPUID CpuidResponse;\r
1733 DEBUG_DATA_SEARCH_SIGNATURE *SearchSignature;\r
1734 DEBUG_DATA_RESPONSE_GET_EXCEPTION Exception;\r
1735 DEBUG_DATA_RESPONSE_GET_REVISION DebugAgentRevision;\r
1736 DEBUG_DATA_SET_VIEWPOINT *SetViewPoint;\r
1737 BOOLEAN HaltDeferred;\r
1738 UINT32 ProcessorIndex;\r
1739 DEBUG_PORT_HANDLE Handle;\r
1740 DEBUG_AGENT_EXCEPTION_BUFFER AgentExceptionBuffer;\r
1741 UINT32 IssuedViewPoint;\r
b422b62c 1742 DEBUG_AGENT_MAILBOX *Mailbox;\r
845a7fe0 1743 UINT8 *AlignedDataPtr;\r
18b144ea 1744\r
1745 ProcessorIndex = 0;\r
93c0bdec 1746 IssuedViewPoint = 0;\r
1747 HaltDeferred = BreakReceived;\r
18b144ea 1748\r
b422b62c 1749 if (MultiProcessorDebugSupport()) {\r
18b144ea 1750 ProcessorIndex = GetProcessorIndex ();\r
1751 SetCpuStopFlagByIndex (ProcessorIndex, TRUE);\r
93c0bdec 1752 if (mDebugMpContext.ViewPointIndex == ProcessorIndex) {\r
1753 //\r
4fe43eb3 1754 // Only the current view processor could set AgentInProgress Flag.\r
93c0bdec 1755 //\r
1756 IssuedViewPoint = ProcessorIndex;\r
1757 }\r
18b144ea 1758 }\r
1759\r
93c0bdec 1760 if (IssuedViewPoint == ProcessorIndex) {\r
1761 //\r
1762 // Set AgentInProgress Flag.\r
1763 //\r
b422b62c 1764 SetDebugFlag (DEBUG_AGENT_FLAG_AGENT_IN_PROGRESS, 1);\r
4fe43eb3 1765 }\r
93c0bdec 1766\r
1767 Handle = GetDebugPortHandle();\r
1768\r
18b144ea 1769 while (TRUE) {\r
1770\r
b422b62c 1771 if (MultiProcessorDebugSupport()) {\r
93c0bdec 1772 //\r
1773 // Check if the current processor is HOST view point\r
1774 //\r
18b144ea 1775 if (mDebugMpContext.ViewPointIndex != ProcessorIndex) {\r
1776 if (mDebugMpContext.RunCommandSet) {\r
93c0bdec 1777 //\r
1778 // If HOST view point sets RUN flag, run GO command to leave\r
1779 //\r
18b144ea 1780 SetCpuStopFlagByIndex (ProcessorIndex, FALSE);\r
1781 CommandGo (CpuContext);\r
1782 break;\r
1783 } else {\r
93c0bdec 1784 //\r
1785 // Run into loop again\r
1786 //\r
1787 CpuPause ();\r
18b144ea 1788 continue;\r
1789 }\r
1790 }\r
1791 }\r
1792\r
b422b62c 1793 AcquireMpSpinLock (&mDebugMpContext.DebugPortSpinLock);\r
18b144ea 1794\r
b422b62c 1795 DebugHeader =(DEBUG_PACKET_HEADER *) InputPacketBuffer;\r
18b144ea 1796\r
b422b62c 1797 DebugAgentMsgPrint (DEBUG_AGENT_INFO, "TARGET: Try to get command from HOST...\n");\r
d9044ec5 1798 Status = ReceivePacket ((UINT8 *) DebugHeader, &BreakReceived, NULL, READ_PACKET_TIMEOUT, TRUE);\r
ace354f1 1799 if (Status != RETURN_SUCCESS || !IS_REQUEST (DebugHeader)) {\r
b422b62c 1800 DebugAgentMsgPrint (DEBUG_AGENT_WARNING, "TARGET: Get command[%x] sequenceno[%x] returned status is [%x] \n", DebugHeader->Command, DebugHeader->SequenceNo, Status);\r
1801 DebugAgentMsgPrint (DEBUG_AGENT_WARNING, "TARGET: Get command failed or it's response packet not expected! \n");\r
1802 ReleaseMpSpinLock (&mDebugMpContext.DebugPortSpinLock);\r
1803 continue;\r
18b144ea 1804 }\r
1805\r
b422b62c 1806 Mailbox = GetMailboxPointer ();\r
1807 if (DebugHeader->SequenceNo == Mailbox->HostSequenceNo) {\r
1808 DebugAgentMsgPrint (DEBUG_AGENT_WARNING, "TARGET: Receive one old command[%x] agaist command[%x]\n", DebugHeader->SequenceNo, Mailbox->HostSequenceNo);\r
1809 SendAckPacket (Mailbox->LastAck);\r
1810 ReleaseMpSpinLock (&mDebugMpContext.DebugPortSpinLock);\r
1811 continue;\r
1812 } else if (DebugHeader->SequenceNo == (UINT8) (Mailbox->HostSequenceNo + 1)) {\r
1813 UpdateMailboxContent (Mailbox, DEBUG_MAILBOX_HOST_SEQUENCE_NO_INDEX, (UINT8) DebugHeader->SequenceNo);\r
1814 } else {\r
1815 DebugAgentMsgPrint (DEBUG_AGENT_WARNING, "Receive one invalid comamnd[%x] agaist command[%x]\n", DebugHeader->SequenceNo, Mailbox->HostSequenceNo);\r
1816 ReleaseMpSpinLock (&mDebugMpContext.DebugPortSpinLock);\r
18b144ea 1817 continue;\r
1818 }\r
4fe43eb3 1819\r
93c0bdec 1820 //\r
1821 // Save CPU content before executing HOST commond\r
1822 //\r
b422b62c 1823 UpdateMailboxContent (Mailbox, DEBUG_MAILBOX_EXCEPTION_BUFFER_POINTER_INDEX, (UINT64)(UINTN) &AgentExceptionBuffer.JumpBuffer);\r
93c0bdec 1824 if (SetJump (&AgentExceptionBuffer.JumpBuffer) != 0) {\r
1825 //\r
1826 // If HOST command failed, continue to wait for HOST's next command\r
1827 // If needed, agent could send exception info to HOST.\r
1828 //\r
1829 SendAckPacket (DEBUG_COMMAND_ABORT);\r
b422b62c 1830 ReleaseMpSpinLock (&mDebugMpContext.DebugPortSpinLock);\r
93c0bdec 1831 continue;\r
1832 }\r
1833\r
1834 DebugAgentMsgPrint (DEBUG_AGENT_INFO, "Processor[%x]:Received one command(%x)\n", mDebugMpContext.ViewPointIndex, DebugHeader->Command);\r
4fe43eb3 1835\r
18b144ea 1836 switch (DebugHeader->Command) {\r
1837\r
b422b62c 1838 case DEBUG_COMMAND_HALT:\r
1839 SendAckPacket (DEBUG_COMMAND_HALT_DEFERRED);\r
1840 HaltDeferred = TRUE;\r
1841 BreakReceived = FALSE;\r
1842 Status = RETURN_SUCCESS;\r
1843 break;\r
1844\r
18b144ea 1845 case DEBUG_COMMAND_RESET:\r
1846 SendAckPacket (DEBUG_COMMAND_OK);\r
b422b62c 1847 SendAckPacket (DEBUG_COMMAND_OK);\r
1848 SendAckPacket (DEBUG_COMMAND_OK);\r
1849 ReleaseMpSpinLock (&mDebugMpContext.DebugPortSpinLock);\r
18b144ea 1850\r
1851 ResetCold ();\r
1852 //\r
b4ebbaff
RN
1853 // Assume system resets in 2 seconds, otherwise send TIMEOUT packet.\r
1854 // PCD can be used if 2 seconds isn't long enough for some platforms.\r
18b144ea 1855 //\r
b4ebbaff 1856 MicroSecondDelay (2000000);\r
b422b62c 1857 UpdateMailboxContent (Mailbox, DEBUG_MAILBOX_HOST_SEQUENCE_NO_INDEX, Mailbox->HostSequenceNo + 1);\r
1858 SendAckPacket (DEBUG_COMMAND_TIMEOUT);\r
1859 SendAckPacket (DEBUG_COMMAND_TIMEOUT);\r
b4ebbaff 1860 SendAckPacket (DEBUG_COMMAND_TIMEOUT);\r
18b144ea 1861 break;\r
1862\r
1863 case DEBUG_COMMAND_GO:\r
1864 CommandGo (CpuContext);\r
93c0bdec 1865 //\r
1866 // Clear Dr0 to avoid to be recognized as IMAGE_LOAD/_UNLOAD again when hitting a breakpoint after GO\r
1867 // If HOST changed Dr0 before GO, we will not change Dr0 here\r
1868 //\r
1869 Data8 = GetBreakCause (Vector, CpuContext);\r
1870 if (Data8 == DEBUG_DATA_BREAK_CAUSE_IMAGE_LOAD || Data8 == DEBUG_DATA_BREAK_CAUSE_IMAGE_UNLOAD) {\r
1871 CpuContext->Dr0 = 0;\r
1872 }\r
1873 //\r
1874 // Clear Stepping Flag\r
1875 //\r
b422b62c 1876 SetDebugFlag (DEBUG_AGENT_FLAG_STEPPING, 0);\r
4fe43eb3 1877\r
18b144ea 1878 if (!HaltDeferred) {\r
1879 //\r
1880 // If no HALT command received when being in-active mode\r
1881 //\r
b422b62c 1882 if (MultiProcessorDebugSupport()) {\r
93c0bdec 1883 Data32 = FindNextPendingBreakCpu ();\r
18b144ea 1884 if (Data32 != -1) {\r
1885 //\r
4fe43eb3 1886 // If there are still others processors being in break state,\r
18b144ea 1887 // send OK packet to HOST to finish this go command\r
1888 //\r
1889 SendAckPacket (DEBUG_COMMAND_OK);\r
1890 CpuPause ();\r
1891 //\r
1892 // Set current view to the next breaking processor\r
1893 //\r
1894 mDebugMpContext.ViewPointIndex = Data32;\r
1895 mDebugMpContext.BreakAtCpuIndex = mDebugMpContext.ViewPointIndex;\r
1896 SetCpuBreakFlagByIndex (mDebugMpContext.ViewPointIndex, FALSE);\r
1897 //\r
93c0bdec 1898 // Send break packet to HOST to let HOST break again\r
1899 //\r
b422b62c 1900 SendBreakPacketToHost (DEBUG_DATA_BREAK_CAUSE_UNKNOWN, mDebugMpContext.BreakAtCpuIndex, &BreakReceived);\r
93c0bdec 1901 //\r
1902 // Continue to run into loop to read command packet from HOST\r
18b144ea 1903 //\r
b422b62c 1904 ReleaseMpSpinLock (&mDebugMpContext.DebugPortSpinLock);\r
18b144ea 1905 break;\r
1906 }\r
1907\r
1908 //\r
1909 // If no else processor break, set stop bitmask,\r
1910 // and set Running flag for all processors.\r
1911 //\r
1912 SetCpuStopFlagByIndex (ProcessorIndex, FALSE);\r
1913 SetCpuRunningFlag (TRUE);\r
1914 CpuPause ();\r
1915 //\r
4fe43eb3 1916 // Wait for all processors are in running state\r
18b144ea 1917 //\r
1918 while (TRUE) {\r
1919 if (IsAllCpuRunning ()) {\r
1920 break;\r
1921 }\r
1922 }\r
1923 //\r
1924 // Set BSP to be current view point.\r
1925 //\r
1926 SetDebugViewPoint (mDebugMpContext.BspIndex);\r
1927 CpuPause ();\r
1928 //\r
1929 // Clear breaking processor index and running flag\r
1930 //\r
1931 mDebugMpContext.BreakAtCpuIndex = (UINT32) (-1);\r
1932 SetCpuRunningFlag (FALSE);\r
1933 }\r
1934\r
1935 //\r
1936 // Send OK packet to HOST to finish this go command\r
1937 //\r
1938 SendAckPacket (DEBUG_COMMAND_OK);\r
1939\r
b422b62c 1940 ReleaseMpSpinLock (&mDebugMpContext.DebugPortSpinLock);\r
18b144ea 1941\r
b422b62c 1942 if (!IsHostAttached()) {\r
1943 UpdateMailboxContent (Mailbox, DEBUG_MAILBOX_SEQUENCE_NO_INDEX, 0);\r
1944 UpdateMailboxContent (Mailbox, DEBUG_MAILBOX_HOST_SEQUENCE_NO_INDEX, 0);\r
1945 }\r
18b144ea 1946 return;\r
1947\r
1948 } else {\r
1949 //\r
1950 // If reveived HALT command, need to defer the GO command\r
1951 //\r
1952 SendAckPacket (DEBUG_COMMAND_HALT_PROCESSED);\r
1953 HaltDeferred = FALSE;\r
18b144ea 1954\r
1955 Vector = DEBUG_TIMER_VECTOR;\r
1956 }\r
1957 break;\r
1958\r
1959 case DEBUG_COMMAND_BREAK_CAUSE:\r
d9044ec5 1960 BreakCause.StopAddress = CpuContext->Eip;\r
b422b62c 1961 if (MultiProcessorDebugSupport() && ProcessorIndex != mDebugMpContext.BreakAtCpuIndex) {\r
d9044ec5 1962 BreakCause.Cause = GetBreakCause (DEBUG_TIMER_VECTOR, CpuContext);\r
18b144ea 1963 } else {\r
d9044ec5 1964 BreakCause.Cause = GetBreakCause (Vector, CpuContext);\r
18b144ea 1965 }\r
d9044ec5 1966 SendDataResponsePacket ((UINT8 *) &BreakCause, (UINT16) sizeof (DEBUG_DATA_RESPONSE_BREAK_CAUSE), DebugHeader);\r
18b144ea 1967 break;\r
1968\r
1969 case DEBUG_COMMAND_SET_HW_BREAKPOINT:\r
1970 SetDebugRegister (CpuContext, (DEBUG_DATA_SET_HW_BREAKPOINT *) (DebugHeader + 1));\r
1971 SendAckPacket (DEBUG_COMMAND_OK);\r
1972 break;\r
1973\r
1974 case DEBUG_COMMAND_CLEAR_HW_BREAKPOINT:\r
1975 ClearDebugRegister (CpuContext, (DEBUG_DATA_CLEAR_HW_BREAKPOINT *) (DebugHeader + 1));\r
1976 SendAckPacket (DEBUG_COMMAND_OK);\r
1977 break;\r
1978\r
1979 case DEBUG_COMMAND_SINGLE_STEPPING:\r
1980 CommandStepping (CpuContext);\r
93c0bdec 1981 //\r
1982 // Clear Dr0 to avoid to be recognized as IMAGE_LOAD/_UNLOAD again when hitting a breakpoint after GO\r
1983 // If HOST changed Dr0 before GO, we will not change Dr0 here\r
1984 //\r
1985 Data8 = GetBreakCause (Vector, CpuContext);\r
1986 if (Data8 == DEBUG_DATA_BREAK_CAUSE_IMAGE_LOAD || Data8 == DEBUG_DATA_BREAK_CAUSE_IMAGE_UNLOAD) {\r
1987 CpuContext->Dr0 = 0;\r
1988 }\r
18b144ea 1989\r
1990 mDebugMpContext.BreakAtCpuIndex = (UINT32) (-1);\r
93c0bdec 1991 //\r
1992 // Set Stepping Flag\r
1993 //\r
b422b62c 1994 SetDebugFlag (DEBUG_AGENT_FLAG_STEPPING, 1);\r
1995 ReleaseMpSpinLock (&mDebugMpContext.DebugPortSpinLock);\r
18b144ea 1996 //\r
93c0bdec 1997 // Executing stepping command directly without sending ACK packet,\r
1998 // ACK packet will be sent after stepping done.\r
18b144ea 1999 //\r
2000 return;\r
2001\r
2002 case DEBUG_COMMAND_SET_SW_BREAKPOINT:\r
2003 Data64 = (UINTN) (((DEBUG_DATA_SET_SW_BREAKPOINT *) (DebugHeader + 1))->Address);\r
2004 Data8 = *(UINT8 *) (UINTN) Data64;\r
2005 *(UINT8 *) (UINTN) Data64 = DEBUG_SW_BREAKPOINT_SYMBOL;\r
d9044ec5 2006 Status = SendDataResponsePacket ((UINT8 *) &Data8, (UINT16) sizeof (UINT8), DebugHeader);\r
18b144ea 2007 break;\r
2008\r
93c0bdec 2009 case DEBUG_COMMAND_READ_MEMORY:\r
2010 MemoryRead = (DEBUG_DATA_READ_MEMORY *) (DebugHeader + 1);\r
d9044ec5 2011 Status = ReadMemoryAndSendResponsePacket ((UINT8 *) (UINTN) MemoryRead->Address, MemoryRead->Count, MemoryRead->Width, DebugHeader);\r
18b144ea 2012 break;\r
2013\r
93c0bdec 2014 case DEBUG_COMMAND_WRITE_MEMORY:\r
2015 MemoryWrite = (DEBUG_DATA_WRITE_MEMORY *) (DebugHeader + 1);\r
845a7fe0 2016 //\r
2017 // Copy data into one memory with 8-byte alignment address\r
2018 //\r
2019 AlignedDataPtr = ALIGN_POINTER ((UINT8 *) &MemoryWrite->Data, sizeof (UINT64));\r
2020 if (AlignedDataPtr != (UINT8 *) &MemoryWrite->Data) {\r
2021 CopyMem (AlignedDataPtr, (UINT8 *) &MemoryWrite->Data, MemoryWrite->Count * MemoryWrite->Width);\r
2022 }\r
2023 CopyMemByWidth ((UINT8 *) (UINTN) MemoryWrite->Address, AlignedDataPtr, MemoryWrite->Count, MemoryWrite->Width);\r
18b144ea 2024 SendAckPacket (DEBUG_COMMAND_OK);\r
2025 break;\r
2026\r
2027 case DEBUG_COMMAND_READ_IO:\r
2028 IoRead = (DEBUG_DATA_READ_IO *) (DebugHeader + 1);\r
2029 switch (IoRead->Width) {\r
2030 case 1:\r
93c0bdec 2031 Data64 = IoRead8 ((UINTN) IoRead->Port);\r
18b144ea 2032 break;\r
2033 case 2:\r
93c0bdec 2034 Data64 = IoRead16 ((UINTN) IoRead->Port);\r
18b144ea 2035 break;\r
2036 case 4:\r
93c0bdec 2037 Data64 = IoRead32 ((UINTN) IoRead->Port);\r
18b144ea 2038 break;\r
2039 case 8:\r
93c0bdec 2040 Data64 = IoRead64 ((UINTN) IoRead->Port);\r
18b144ea 2041 break;\r
2042 default:\r
2043 Data64 = (UINT64) -1;\r
2044 }\r
d9044ec5 2045 Status = SendDataResponsePacket ((UINT8 *) &Data64, IoRead->Width, DebugHeader);\r
18b144ea 2046 break;\r
2047\r
2048 case DEBUG_COMMAND_WRITE_IO:\r
2049 IoWrite = (DEBUG_DATA_WRITE_IO *) (DebugHeader + 1);\r
2050 switch (IoWrite->Width) {\r
2051 case 1:\r
93c0bdec 2052 Data64 = IoWrite8 ((UINTN) IoWrite->Port, *(UINT8 *) &IoWrite->Data);\r
18b144ea 2053 break;\r
2054 case 2:\r
93c0bdec 2055 Data64 = IoWrite16 ((UINTN) IoWrite->Port, *(UINT16 *) &IoWrite->Data);\r
18b144ea 2056 break;\r
2057 case 4:\r
93c0bdec 2058 Data64 = IoWrite32 ((UINTN) IoWrite->Port, *(UINT32 *) &IoWrite->Data);\r
18b144ea 2059 break;\r
2060 case 8:\r
93c0bdec 2061 Data64 = IoWrite64 ((UINTN) IoWrite->Port, *(UINT64 *) &IoWrite->Data);\r
18b144ea 2062 break;\r
2063 default:\r
2064 Data64 = (UINT64) -1;\r
2065 }\r
2066 SendAckPacket (DEBUG_COMMAND_OK);\r
2067 break;\r
2068\r
93c0bdec 2069 case DEBUG_COMMAND_READ_ALL_REGISTERS:\r
d9044ec5 2070 Status = SendDataResponsePacket ((UINT8 *) CpuContext, sizeof (*CpuContext), DebugHeader);\r
93c0bdec 2071 break;\r
2072\r
18b144ea 2073 case DEBUG_COMMAND_READ_REGISTER:\r
2074 RegisterRead = (DEBUG_DATA_READ_REGISTER *) (DebugHeader + 1);\r
2075\r
93c0bdec 2076 if (RegisterRead->Index <= SOFT_DEBUGGER_REGISTER_MAX) {\r
2077 RegisterBuffer = ArchReadRegisterBuffer (CpuContext, RegisterRead->Index, &Width);\r
d9044ec5 2078 Status = SendDataResponsePacket (RegisterBuffer, Width, DebugHeader);\r
18b144ea 2079 } else {\r
93c0bdec 2080 Status = RETURN_UNSUPPORTED;\r
18b144ea 2081 }\r
2082 break;\r
2083\r
2084 case DEBUG_COMMAND_WRITE_REGISTER:\r
2085 RegisterWrite = (DEBUG_DATA_WRITE_REGISTER *) (DebugHeader + 1);\r
93c0bdec 2086 if (RegisterWrite->Index <= SOFT_DEBUGGER_REGISTER_MAX) {\r
2087 RegisterBuffer = ArchReadRegisterBuffer (CpuContext, RegisterWrite->Index, &Width);\r
2088 ASSERT (Width == RegisterWrite->Length);\r
2089 CopyMem (RegisterBuffer, RegisterWrite->Data, Width);\r
2090 SendAckPacket (DEBUG_COMMAND_OK);\r
2091 } else {\r
2092 Status = RETURN_UNSUPPORTED;\r
2093 }\r
18b144ea 2094 break;\r
2095\r
2096 case DEBUG_COMMAND_ARCH_MODE:\r
2097 Data8 = DEBUG_ARCH_SYMBOL;\r
d9044ec5 2098 Status = SendDataResponsePacket ((UINT8 *) &Data8, (UINT16) sizeof (UINT8), DebugHeader);\r
18b144ea 2099 break;\r
2100\r
2101 case DEBUG_COMMAND_READ_MSR:\r
2102 MsrRegisterRead = (DEBUG_DATA_READ_MSR *) (DebugHeader + 1);\r
2103 Data64 = AsmReadMsr64 (MsrRegisterRead->Index);\r
d9044ec5 2104 Status = SendDataResponsePacket ((UINT8 *) &Data64, (UINT16) sizeof (UINT64), DebugHeader);\r
18b144ea 2105 break;\r
2106\r
2107 case DEBUG_COMMAND_WRITE_MSR:\r
2108 MsrRegisterWrite = (DEBUG_DATA_WRITE_MSR *) (DebugHeader + 1);\r
2109 AsmWriteMsr64 (MsrRegisterWrite->Index, MsrRegisterWrite->Value);\r
2110 SendAckPacket (DEBUG_COMMAND_OK);\r
2111 break;\r
2112\r
93c0bdec 2113 case DEBUG_COMMAND_SET_DEBUG_SETTING:\r
2114 Status = SetDebugSetting ((DEBUG_DATA_SET_DEBUG_SETTING *)(DebugHeader + 1));\r
2115 if (Status == RETURN_SUCCESS) {\r
2116 SendAckPacket (DEBUG_COMMAND_OK);\r
2117 }\r
18b144ea 2118 break;\r
2119\r
2120 case DEBUG_COMMAND_GET_REVISION:\r
2121 DebugAgentRevision.Revision = DEBUG_AGENT_REVISION;\r
2122 DebugAgentRevision.Capabilities = DEBUG_AGENT_CAPABILITIES;\r
d9044ec5 2123 Status = SendDataResponsePacket ((UINT8 *) &DebugAgentRevision, (UINT16) sizeof (DEBUG_DATA_RESPONSE_GET_REVISION), DebugHeader);\r
18b144ea 2124 break;\r
2125\r
2126 case DEBUG_COMMAND_GET_EXCEPTION:\r
2127 Exception.ExceptionNum = (UINT8) Vector;\r
93c0bdec 2128 Exception.ExceptionData = (UINT32) CpuContext->ExceptionData;\r
d9044ec5 2129 Status = SendDataResponsePacket ((UINT8 *) &Exception, (UINT16) sizeof (DEBUG_DATA_RESPONSE_GET_EXCEPTION), DebugHeader);\r
18b144ea 2130 break;\r
2131\r
2132 case DEBUG_COMMAND_SET_VIEWPOINT:\r
93c0bdec 2133 SetViewPoint = (DEBUG_DATA_SET_VIEWPOINT *) (DebugHeader + 1);\r
b422b62c 2134 if (MultiProcessorDebugSupport()) {\r
93c0bdec 2135 if (IsCpuStopped (SetViewPoint->ViewPoint)) {\r
2136 SetDebugViewPoint (SetViewPoint->ViewPoint);\r
18b144ea 2137 SendAckPacket (DEBUG_COMMAND_OK);\r
2138 } else {\r
2139 //\r
2140 // If CPU is not halted\r
2141 //\r
2142 SendAckPacket (DEBUG_COMMAND_NOT_SUPPORTED);\r
2143 }\r
93c0bdec 2144 } else if (SetViewPoint->ViewPoint == 0) {\r
18b144ea 2145 SendAckPacket (DEBUG_COMMAND_OK);\r
2146\r
2147 } else {\r
2148 SendAckPacket (DEBUG_COMMAND_NOT_SUPPORTED);\r
2149 }\r
2150\r
2151 break;\r
2152\r
2153 case DEBUG_COMMAND_GET_VIEWPOINT:\r
2154 Data32 = mDebugMpContext.ViewPointIndex;\r
d9044ec5 2155 SendDataResponsePacket((UINT8 *) &Data32, (UINT16) sizeof (UINT32), DebugHeader);\r
93c0bdec 2156 break;\r
2157\r
2158 case DEBUG_COMMAND_MEMORY_READY:\r
b422b62c 2159 Data8 = (UINT8) GetDebugFlag (DEBUG_AGENT_FLAG_MEMORY_READY);\r
d9044ec5 2160 SendDataResponsePacket (&Data8, (UINT16) sizeof (UINT8), DebugHeader);\r
93c0bdec 2161 break;\r
2162\r
2163 case DEBUG_COMMAND_DETACH:\r
2164 SetHostAttached (FALSE);\r
2165 SendAckPacket (DEBUG_COMMAND_OK);\r
2166 break;\r
2167\r
2168 case DEBUG_COMMAND_CPUID:\r
2169 Cpuid = (DEBUG_DATA_CPUID *) (DebugHeader + 1);\r
2170 AsmCpuidEx (\r
4fe43eb3 2171 Cpuid->Eax, Cpuid->Ecx,\r
93c0bdec 2172 &CpuidResponse.Eax, &CpuidResponse.Ebx,\r
2173 &CpuidResponse.Ecx, &CpuidResponse.Edx\r
2174 );\r
d9044ec5 2175 SendDataResponsePacket ((UINT8 *) &CpuidResponse, (UINT16) sizeof (CpuidResponse), DebugHeader);\r
93c0bdec 2176 break;\r
2177\r
2178 case DEBUG_COMMAND_SEARCH_SIGNATURE:\r
2179 SearchSignature = (DEBUG_DATA_SEARCH_SIGNATURE *) (DebugHeader + 1);\r
4fe43eb3 2180 if ((SearchSignature->Alignment != 0) &&\r
93c0bdec 2181 (SearchSignature->Alignment == GetPowerOfTwo32 (SearchSignature->Alignment))\r
2182 ) {\r
2183 if (SearchSignature->Positive) {\r
2184 for (\r
2185 Data64 = ALIGN_VALUE ((UINTN) SearchSignature->Start, SearchSignature->Alignment);\r
2186 Data64 <= SearchSignature->Start + SearchSignature->Count - SearchSignature->DataLength;\r
2187 Data64 += SearchSignature->Alignment\r
2188 ) {\r
2189 if (CompareMem ((VOID *) (UINTN) Data64, &SearchSignature->Data, SearchSignature->DataLength) == 0) {\r
2190 break;\r
2191 }\r
2192 }\r
2193 if (Data64 > SearchSignature->Start + SearchSignature->Count - SearchSignature->DataLength) {\r
2194 Data64 = (UINT64) -1;\r
2195 }\r
2196 } else {\r
2197 for (\r
2198 Data64 = ALIGN_VALUE ((UINTN) SearchSignature->Start - SearchSignature->Alignment, SearchSignature->Alignment);\r
2199 Data64 >= SearchSignature->Start - SearchSignature->Count;\r
2200 Data64 -= SearchSignature->Alignment\r
2201 ) {\r
2202 if (CompareMem ((VOID *) (UINTN) Data64, &SearchSignature->Data, SearchSignature->DataLength) == 0) {\r
2203 break;\r
2204 }\r
2205 }\r
2206 if (Data64 < SearchSignature->Start - SearchSignature->Count) {\r
2207 Data64 = (UINT64) -1;\r
2208 }\r
2209 }\r
d9044ec5 2210 SendDataResponsePacket ((UINT8 *) &Data64, (UINT16) sizeof (Data64), DebugHeader);\r
93c0bdec 2211 } else {\r
2212 Status = RETURN_UNSUPPORTED;\r
2213 }\r
18b144ea 2214 break;\r
2215\r
2216 default:\r
2217 SendAckPacket (DEBUG_COMMAND_NOT_SUPPORTED);\r
2218 break;\r
2219 }\r
2220\r
2221 if (Status == RETURN_UNSUPPORTED) {\r
2222 SendAckPacket (DEBUG_COMMAND_NOT_SUPPORTED);\r
2223 } else if (Status != RETURN_SUCCESS) {\r
2224 SendAckPacket (DEBUG_COMMAND_ABORT);\r
2225 }\r
2226\r
b422b62c 2227 ReleaseMpSpinLock (&mDebugMpContext.DebugPortSpinLock);\r
18b144ea 2228 CpuPause ();\r
2229 }\r
2230}\r
2231\r
2232/**\r
2233 C function called in interrupt handler.\r
2234\r
2235 @param[in] Vector Vector value of exception or interrutp.\r
2236 @param[in] CpuContext Pointer to save CPU context.\r
2237\r
2238**/\r
2239VOID\r
2240EFIAPI\r
2241InterruptProcess (\r
2242 IN UINT32 Vector,\r
2243 IN DEBUG_CPU_CONTEXT *CpuContext\r
2244 )\r
2245{\r
93c0bdec 2246 UINT8 InputCharacter;\r
2247 UINT8 BreakCause;\r
2248 UINTN SavedEip;\r
2249 BOOLEAN BreakReceived;\r
2250 UINT32 ProcessorIndex;\r
2251 UINT32 CurrentDebugTimerInitCount;\r
2252 DEBUG_PORT_HANDLE Handle;\r
2253 UINT8 Data8;\r
2254 UINT8 *Al;\r
2255 UINT32 IssuedViewPoint;\r
2256 DEBUG_AGENT_EXCEPTION_BUFFER *ExceptionBuffer;\r
18b144ea 2257\r
79ecd2db 2258 InputCharacter = 0;\r
93c0bdec 2259 ProcessorIndex = 0;\r
2260 IssuedViewPoint = 0;\r
2261 BreakReceived = FALSE;\r
18b144ea 2262\r
b422b62c 2263 if (mSkipBreakpoint) {\r
2264 //\r
2265 // If Skip Breakpoint flag is set, means communication is disturbed by hardware SMI, we need to ignore the break points in SMM\r
2266 //\r
2267 if ((Vector == DEBUG_INT1_VECTOR) || (Vector == DEBUG_INT3_VECTOR)) {\r
2268 DebugPortWriteBuffer (GetDebugPortHandle(), (UINT8 *) mWarningMsgIngoreBreakpoint, AsciiStrLen (mWarningMsgIngoreBreakpoint));\r
2269 return;\r
2270 }\r
2271 }\r
2272\r
2273 if (MultiProcessorDebugSupport()) {\r
18b144ea 2274 ProcessorIndex = GetProcessorIndex ();\r
93c0bdec 2275 //\r
2276 // If this processor has alreay halted before, need to check it later\r
2277 //\r
2278 if (IsCpuStopped (ProcessorIndex)) {\r
2279 IssuedViewPoint = ProcessorIndex;\r
2280 }\r
18b144ea 2281 }\r
2282\r
b422b62c 2283 if (IssuedViewPoint == ProcessorIndex && GetDebugFlag (DEBUG_AGENT_FLAG_STEPPING) != 1) {\r
93c0bdec 2284 //\r
2285 // Check if this exception is issued by Debug Agent itself\r
2286 // If yes, fill the debug agent exception buffer and LongJump() back to\r
2287 // the saved CPU content in CommandCommunication()\r
2288 //\r
b422b62c 2289 if (GetDebugFlag (DEBUG_AGENT_FLAG_AGENT_IN_PROGRESS) == 1) {\r
845a7fe0 2290 DebugAgentMsgPrint (DEBUG_AGENT_ERROR, "Debug agent meet one Exception, ExceptionNum is %d, EIP = 0x%x.\n", Vector, (UINTN)CpuContext->Eip);\r
93c0bdec 2291 ExceptionBuffer = (DEBUG_AGENT_EXCEPTION_BUFFER *) (UINTN) GetMailboxPointer()->ExceptionBufferPointer;\r
2292 ExceptionBuffer->ExceptionContent.ExceptionNum = (UINT8) Vector;\r
2293 ExceptionBuffer->ExceptionContent.ExceptionData = (UINT32) CpuContext->ExceptionData;\r
b422b62c 2294 LongJump ((BASE_LIBRARY_JUMP_BUFFER *)(UINTN)(ExceptionBuffer), 1);\r
93c0bdec 2295 }\r
2296 }\r
2297\r
b422b62c 2298 if (MultiProcessorDebugSupport()) {\r
93c0bdec 2299 //\r
4fe43eb3 2300 // If RUN commmand is executing, wait for it done.\r
93c0bdec 2301 //\r
2302 while (mDebugMpContext.RunCommandSet) {\r
2303 CpuPause ();\r
2304 }\r
2305 }\r
2306\r
b422b62c 2307 Handle = GetDebugPortHandle();\r
2308 BreakCause = GetBreakCause (Vector, CpuContext);\r
18b144ea 2309 switch (Vector) {\r
2310 case DEBUG_INT1_VECTOR:\r
2311 case DEBUG_INT3_VECTOR:\r
93c0bdec 2312 switch (BreakCause) {\r
2313 case DEBUG_DATA_BREAK_CAUSE_SYSTEM_RESET:\r
b422b62c 2314 if (AttachHost (BreakCause, READ_PACKET_TIMEOUT, &BreakReceived) != RETURN_SUCCESS) {\r
93c0bdec 2315 //\r
2316 // Try to connect HOST, return if fails\r
2317 //\r
18b144ea 2318 break;\r
2319 }\r
18b144ea 2320 CommandCommunication (Vector, CpuContext, BreakReceived);\r
93c0bdec 2321 break;\r
18b144ea 2322\r
93c0bdec 2323 case DEBUG_DATA_BREAK_CAUSE_STEPPING:\r
18b144ea 2324 //\r
2325 // Stepping is finished, send Ack package.\r
2326 //\r
b422b62c 2327 if (MultiProcessorDebugSupport()) {\r
18b144ea 2328 mDebugMpContext.BreakAtCpuIndex = ProcessorIndex;\r
2329 }\r
2330 SendAckPacket (DEBUG_COMMAND_OK);\r
2331 CommandCommunication (Vector, CpuContext, BreakReceived);\r
93c0bdec 2332 break;\r
18b144ea 2333\r
93c0bdec 2334 case DEBUG_DATA_BREAK_CAUSE_MEMORY_READY:\r
18b144ea 2335 //\r
2336 // Memory is ready\r
2337 //\r
b422b62c 2338 SendCommandAndWaitForAckOK (DEBUG_COMMAND_MEMORY_READY, READ_PACKET_TIMEOUT, &BreakReceived, NULL);\r
18b144ea 2339 CommandCommunication (Vector, CpuContext, BreakReceived);\r
93c0bdec 2340 break;\r
18b144ea 2341\r
93c0bdec 2342 case DEBUG_DATA_BREAK_CAUSE_IMAGE_LOAD:\r
2343 case DEBUG_DATA_BREAK_CAUSE_IMAGE_UNLOAD:\r
2344 //\r
2345 // Set AL to DEBUG_AGENT_IMAGE_CONTINUE\r
2346 //\r
2347 Al = ArchReadRegisterBuffer (CpuContext, SOFT_DEBUGGER_REGISTER_AX, &Data8);\r
2348 *Al = DEBUG_AGENT_IMAGE_CONTINUE;\r
18b144ea 2349\r
93c0bdec 2350 if (!IsHostAttached ()) {\r
18b144ea 2351 //\r
93c0bdec 2352 // If HOST is not connected for image load/unload, return\r
18b144ea 2353 //\r
93c0bdec 2354 break;\r
18b144ea 2355 }\r
93c0bdec 2356 //\r
2357 // Continue to run the following common code\r
2358 //\r
4fe43eb3 2359\r
93c0bdec 2360 case DEBUG_DATA_BREAK_CAUSE_HW_BREAKPOINT:\r
2361 case DEBUG_DATA_BREAK_CAUSE_SW_BREAKPOINT:\r
2362 default:\r
2363 //\r
2364 // Send Break packet to HOST\r
2365 //\r
b422b62c 2366 AcquireMpSpinLock (&mDebugMpContext.DebugPortSpinLock);\r
93c0bdec 2367 //\r
2368 // Only the first breaking processor could send BREAK_POINT to HOST\r
4fe43eb3 2369 //\r
93c0bdec 2370 if (IsFirstBreakProcessor (ProcessorIndex)) {\r
b422b62c 2371 SendBreakPacketToHost (BreakCause, ProcessorIndex, &BreakReceived);\r
18b144ea 2372 }\r
b422b62c 2373 ReleaseMpSpinLock (&mDebugMpContext.DebugPortSpinLock);\r
4fe43eb3 2374\r
18b144ea 2375 if (Vector == DEBUG_INT3_VECTOR) {\r
2376 //\r
2377 // go back address located "0xCC"\r
2378 //\r
2379 CpuContext->Eip--;\r
2380 SavedEip = CpuContext->Eip;\r
2381 CommandCommunication (Vector, CpuContext, BreakReceived);\r
2382 if ((SavedEip == CpuContext->Eip) &&\r
2383 (*(UINT8 *) (UINTN) CpuContext->Eip == DEBUG_SW_BREAKPOINT_SYMBOL)) {\r
2384 //\r
2385 // If this is not a software breakpoint set by HOST,\r
2386 // restore EIP\r
2387 //\r
2388 CpuContext->Eip++;\r
2389 }\r
2390 } else {\r
2391 CommandCommunication (Vector, CpuContext, BreakReceived);\r
2392 }\r
93c0bdec 2393 break;\r
18b144ea 2394 }\r
2395\r
2396 break;\r
2397\r
2398 case DEBUG_TIMER_VECTOR:\r
2399\r
b422b62c 2400 AcquireMpSpinLock (&mDebugMpContext.DebugPortSpinLock);\r
93c0bdec 2401\r
b422b62c 2402 if (MultiProcessorDebugSupport()) {\r
18b144ea 2403 if (IsBsp (ProcessorIndex)) {\r
2404 //\r
2405 // If current processor is BSP, check Apic timer's init count if changed,\r
2406 // it may be re-written when switching BSP.\r
2407 // If it changed, re-initialize debug timer\r
2408 //\r
2409 CurrentDebugTimerInitCount = GetApicTimerInitCount ();\r
2410 if (mDebugMpContext.DebugTimerInitCount != CurrentDebugTimerInitCount) {\r
2411 InitializeDebugTimer ();\r
2412 }\r
2413 }\r
2414\r
2415 if (!IsBsp (ProcessorIndex) || mDebugMpContext.IpiSentByAp) {\r
b422b62c 2416 ReleaseMpSpinLock (&mDebugMpContext.DebugPortSpinLock);\r
18b144ea 2417 //\r
2418 // If current processor is not BSP or this is one IPI sent by AP\r
2419 //\r
2420 if (mDebugMpContext.BreakAtCpuIndex != (UINT32) (-1)) {\r
2421 CommandCommunication (Vector, CpuContext, FALSE);\r
2422 }\r
2423\r
2424 //\r
2425 // Clear EOI before exiting interrupt process routine.\r
2426 //\r
2427 SendApicEoi ();\r
2428 break;\r
2429 }\r
2430 }\r
2431\r
2432 //\r
2433 // Only BSP could run here\r
2434 //\r
93c0bdec 2435 while (TRUE) {\r
18b144ea 2436 //\r
93c0bdec 2437 // If there is data in debug port, will check whether it is break(attach/break-in) symbol,\r
18b144ea 2438 // If yes, go into communication mode with HOST.\r
2439 // If no, exit interrupt process.\r
2440 //\r
93c0bdec 2441 if (DebugReadBreakSymbol (Handle, &InputCharacter) == EFI_NOT_FOUND) {\r
2442 break;\r
2443 }\r
b422b62c 2444\r
93c0bdec 2445 if ((!IsHostAttached () && (InputCharacter == DEBUG_STARTING_SYMBOL_ATTACH)) ||\r
b422b62c 2446 (IsHostAttached () && (InputCharacter == DEBUG_COMMAND_HALT)) ||\r
2447 (IsHostAttached () && (InputCharacter == DEBUG_COMMAND_GO))\r
93c0bdec 2448 ) {\r
2449 DebugAgentMsgPrint (DEBUG_AGENT_VERBOSE, "Received data [%02x]\n", InputCharacter);\r
2450 //\r
2451 // Ack OK for break-in symbol\r
2452 //\r
18b144ea 2453 SendAckPacket (DEBUG_COMMAND_OK);\r
93c0bdec 2454\r
b422b62c 2455 //\r
2456 // If receive GO command in Debug Timer, means HOST may lost ACK packet before.\r
2457 //\r
2458 if (InputCharacter == DEBUG_COMMAND_GO) {\r
2459 break;\r
2460 }\r
2461\r
93c0bdec 2462 if (!IsHostAttached ()) {\r
2463 //\r
2464 // Try to attach HOST, if no ack received after 200ms, return\r
2465 //\r
b422b62c 2466 if (AttachHost (BreakCause, READ_PACKET_TIMEOUT, &BreakReceived) != RETURN_SUCCESS) {\r
93c0bdec 2467 break;\r
2468 }\r
2469 }\r
2470\r
b422b62c 2471 if (MultiProcessorDebugSupport()) {\r
93c0bdec 2472 if(FindNextPendingBreakCpu () != -1) {\r
18b144ea 2473 SetCpuBreakFlagByIndex (ProcessorIndex, TRUE);\r
2474 } else {\r
2475 HaltOtherProcessors (ProcessorIndex);\r
2476 }\r
2477 }\r
b422b62c 2478 ReleaseMpSpinLock (&mDebugMpContext.DebugPortSpinLock);\r
18b144ea 2479 CommandCommunication (Vector, CpuContext, BreakReceived);\r
b422b62c 2480 AcquireMpSpinLock (&mDebugMpContext.DebugPortSpinLock);\r
18b144ea 2481 break;\r
2482 }\r
2483 }\r
2484\r
2485 //\r
2486 // Clear EOI before exiting interrupt process routine.\r
2487 //\r
2488 SendApicEoi ();\r
2489\r
b422b62c 2490 ReleaseMpSpinLock (&mDebugMpContext.DebugPortSpinLock);\r
18b144ea 2491\r
2492 break;\r
2493\r
2494 default:\r
18b144ea 2495 if (Vector <= DEBUG_EXCEPT_SIMD) {\r
93c0bdec 2496 if (BreakCause == DEBUG_DATA_BREAK_CAUSE_STEPPING) {\r
2497 //\r
2498 // Stepping is finished, send Ack package.\r
2499 //\r
b422b62c 2500 if (MultiProcessorDebugSupport()) {\r
93c0bdec 2501 mDebugMpContext.BreakAtCpuIndex = ProcessorIndex;\r
18b144ea 2502 }\r
93c0bdec 2503 SendAckPacket (DEBUG_COMMAND_OK);\r
2504 } else {\r
2505 //\r
2506 // Exception occurs, send Break packet to HOST\r
2507 //\r
b422b62c 2508 AcquireMpSpinLock (&mDebugMpContext.DebugPortSpinLock);\r
93c0bdec 2509 //\r
2510 // Only the first breaking processor could send BREAK_POINT to HOST\r
4fe43eb3 2511 //\r
93c0bdec 2512 if (IsFirstBreakProcessor (ProcessorIndex)) {\r
b422b62c 2513 SendBreakPacketToHost (BreakCause, ProcessorIndex, &BreakReceived);\r
93c0bdec 2514 }\r
b422b62c 2515 ReleaseMpSpinLock (&mDebugMpContext.DebugPortSpinLock);\r
18b144ea 2516 }\r
4fe43eb3 2517\r
18b144ea 2518 CommandCommunication (Vector, CpuContext, BreakReceived);\r
2519 }\r
2520 break;\r
2521 }\r
2522\r
b422b62c 2523 if (MultiProcessorDebugSupport()) {\r
18b144ea 2524 //\r
2525 // Clear flag and wait for all processors run here\r
2526 //\r
2527 SetIpiSentByApFlag (FALSE);\r
93c0bdec 2528 while (mDebugMpContext.RunCommandSet) {\r
2529 CpuPause ();\r
2530 }\r
2531\r
2532 //\r
2533 // Only current (view) processor could clean up AgentInProgress flag.\r
2534 //\r
2535 if (mDebugMpContext.ViewPointIndex == ProcessorIndex) {\r
2536 IssuedViewPoint = mDebugMpContext.ViewPointIndex;\r
2537 }\r
2538 }\r
2539\r
b422b62c 2540 if (IssuedViewPoint == ProcessorIndex && GetDebugFlag (DEBUG_AGENT_FLAG_STEPPING) != 1) {\r
93c0bdec 2541 //\r
b422b62c 2542 // If the command is not stepping, clean up AgentInProgress flag\r
93c0bdec 2543 //\r
b422b62c 2544 SetDebugFlag (DEBUG_AGENT_FLAG_AGENT_IN_PROGRESS, 0);\r
18b144ea 2545 }\r
2546\r
2547 return;\r
2548}\r
2549\r