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