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