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