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