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