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