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