]> git.proxmox.com Git - mirror_edk2.git/blame_incremental - SourceLevelDebugPkg/Library/DebugAgent/DebugAgentCommon/DebugAgent.c
MdeModulePkg: add error handling when DXE IPL PPI is not found.
[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 }\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 (IS_REQUEST (DebugHeader)) {\r
609 if (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 }\r
616 if (DebugHeader->SequenceNo == Mailbox->HostSequenceNo) {\r
617 return EFI_SUCCESS;\r
618 }\r
619 }\r
620\r
621 return EFI_DEVICE_ERROR;\r
622}\r
623\r
624/**\r
625 Check if HOST is attached based on Mailbox.\r
626\r
627 @retval TRUE HOST is attached.\r
628 @retval FALSE HOST is not attached.\r
629\r
630**/\r
631BOOLEAN\r
632IsHostAttached (\r
633 VOID\r
634 )\r
635{\r
636 return (BOOLEAN) (GetDebugFlag (DEBUG_AGENT_FLAG_HOST_ATTACHED) == 1);\r
637}\r
638\r
639/**\r
640 Set HOST connect flag in Mailbox.\r
641\r
642 @param[in] Attached Attach status.\r
643\r
644**/\r
645VOID\r
646SetHostAttached (\r
647 IN BOOLEAN Attached\r
648 )\r
649{\r
650 DebugAgentMsgPrint (DEBUG_AGENT_INFO, "Attach status is %d\n", Attached);\r
651 SetDebugFlag (DEBUG_AGENT_FLAG_HOST_ATTACHED, (UINT32)Attached);\r
652}\r
653\r
654/**\r
655 Set debug setting of Debug Agent in Mailbox.\r
656\r
657 @param DebugSetting Pointer to Debug Setting defined by transfer protocol.\r
658\r
659 @retval RETURN_SUCCESS The setting is set successfully.\r
660 @retval RETURN_UNSUPPORTED The Key value is not supported.\r
661\r
662**/\r
663RETURN_STATUS\r
664SetDebugSetting (\r
665 IN DEBUG_DATA_SET_DEBUG_SETTING *DebugSetting\r
666 )\r
667{\r
668 RETURN_STATUS Status;\r
669\r
670 Status = RETURN_SUCCESS;\r
671 switch (DebugSetting->Key) {\r
672 case DEBUG_AGENT_SETTING_SMM_ENTRY_BREAK:\r
673 SetDebugFlag (DEBUG_AGENT_FLAG_BREAK_ON_NEXT_SMI, DebugSetting->Value);\r
674 break;\r
675 case DEBUG_AGENT_SETTING_PRINT_ERROR_LEVEL:\r
676 SetDebugFlag (DEBUG_AGENT_FLAG_PRINT_ERROR_LEVEL, DebugSetting->Value);\r
677 break;\r
678 case DEBUG_AGENT_SETTING_BOOT_SCRIPT_ENTRY_BREAK:\r
679 SetDebugFlag (DEBUG_AGENT_FLAG_BREAK_BOOT_SCRIPT, DebugSetting->Value);\r
680 break;\r
681 default:\r
682 Status = RETURN_UNSUPPORTED;\r
683 }\r
684 return Status;\r
685}\r
686\r
687/**\r
688 Exectue GO command.\r
689\r
690 @param[in] CpuContext Pointer to saved CPU context.\r
691\r
692**/\r
693VOID\r
694CommandGo (\r
695 IN DEBUG_CPU_CONTEXT *CpuContext\r
696 )\r
697{\r
698 IA32_EFLAGS32 *Eflags;\r
699\r
700 Eflags = (IA32_EFLAGS32 *) &CpuContext->Eflags;\r
701 Eflags->Bits.TF = 0;\r
702 Eflags->Bits.RF = 1;\r
703}\r
704\r
705/**\r
706 Exectue Stepping command.\r
707\r
708 @param[in] CpuContext Pointer to saved CPU context.\r
709\r
710**/\r
711VOID\r
712CommandStepping (\r
713 IN DEBUG_CPU_CONTEXT *CpuContext\r
714 )\r
715{\r
716 IA32_EFLAGS32 *Eflags;\r
717\r
718 Eflags = (IA32_EFLAGS32 *) &CpuContext->Eflags;\r
719 Eflags->Bits.TF = 1;\r
720 Eflags->Bits.RF = 1;\r
721}\r
722\r
723/**\r
724 Set debug register for hardware breakpoint.\r
725\r
726 @param[in] CpuContext Pointer to saved CPU context.\r
727 @param[in] SetHwBreakpoint Hardware breakpoint to be set.\r
728\r
729**/\r
730VOID\r
731SetDebugRegister (\r
732 IN DEBUG_CPU_CONTEXT *CpuContext,\r
733 IN DEBUG_DATA_SET_HW_BREAKPOINT *SetHwBreakpoint\r
734 )\r
735{\r
736 UINT8 RegisterIndex;\r
737 UINTN Dr7Value;\r
738\r
739 RegisterIndex = SetHwBreakpoint->Type.Index;\r
740\r
741 //\r
742 // Set debug address\r
743 //\r
744 * ((UINTN *) &CpuContext->Dr0 + RegisterIndex) = (UINTN) SetHwBreakpoint->Address;\r
745\r
746 Dr7Value = CpuContext->Dr7;\r
747\r
748 //\r
749 // Enable Gx, Lx\r
750 //\r
751 Dr7Value |= (UINTN) (0x3 << (RegisterIndex * 2));\r
752 //\r
753 // Set RWx and Lenx\r
754 //\r
755 Dr7Value &= (UINTN) (~(0xf << (16 + RegisterIndex * 4)));\r
756 Dr7Value |= (UINTN) ((SetHwBreakpoint->Type.Length << 2) | SetHwBreakpoint->Type.Access) << (16 + RegisterIndex * 4);\r
757 //\r
758 // Enable GE, LE\r
759 //\r
760 Dr7Value |= 0x300;\r
761\r
762 CpuContext->Dr7 = Dr7Value;\r
763}\r
764\r
765/**\r
766 Clear debug register for hardware breakpoint.\r
767\r
768 @param[in] CpuContext Pointer to saved CPU context.\r
769 @param[in] ClearHwBreakpoint Hardware breakpoint to be cleared.\r
770\r
771**/\r
772VOID\r
773ClearDebugRegister (\r
774 IN DEBUG_CPU_CONTEXT *CpuContext,\r
775 IN DEBUG_DATA_CLEAR_HW_BREAKPOINT *ClearHwBreakpoint\r
776 )\r
777{\r
778 if ((ClearHwBreakpoint->IndexMask & BIT0) != 0) {\r
779 CpuContext->Dr0 = 0;\r
780 CpuContext->Dr7 &= (UINTN)(~(0x3 << 0));\r
781 }\r
782 if ((ClearHwBreakpoint->IndexMask & BIT1) != 0) {\r
783 CpuContext->Dr1 = 0;\r
784 CpuContext->Dr7 &= (UINTN)(~(0x3 << 2));\r
785 }\r
786 if ((ClearHwBreakpoint->IndexMask & BIT2) != 0) {\r
787 CpuContext->Dr2 = 0;\r
788 CpuContext->Dr7 &= (UINTN)(~(0x3 << 4));\r
789 }\r
790 if ((ClearHwBreakpoint->IndexMask & BIT3) != 0) {\r
791 CpuContext->Dr3 = 0;\r
792 CpuContext->Dr7 &= (UINTN)(~(0x3 << 6));\r
793 }\r
794}\r
795\r
796\r
797/**\r
798 Return the offset of FP / MMX / XMM registers in the FPU saved state by register index.\r
799\r
800 @param[in] Index Register index.\r
801 @param[out] Width Register width returned.\r
802\r
803 @return Offset in the FPU Save State.\r
804\r
805**/\r
806UINT16\r
807ArchReadFxStatOffset (\r
808 IN UINT8 Index,\r
809 OUT UINT8 *Width\r
810 )\r
811{\r
812 if (Index < SOFT_DEBUGGER_REGISTER_ST0) {\r
813 switch (Index) {\r
814 case SOFT_DEBUGGER_REGISTER_FP_FCW:\r
815 *Width = (UINT8) sizeof (UINT16);\r
816 return OFFSET_OF(DEBUG_DATA_FX_SAVE_STATE, Fcw);\r
817\r
818 case SOFT_DEBUGGER_REGISTER_FP_FSW:\r
819 *Width = (UINT8) sizeof (UINT16);\r
820 return OFFSET_OF(DEBUG_DATA_FX_SAVE_STATE, Fsw);\r
821\r
822 case SOFT_DEBUGGER_REGISTER_FP_FTW:\r
823 *Width = (UINT8) sizeof (UINT16);\r
824 return OFFSET_OF(DEBUG_DATA_FX_SAVE_STATE, Ftw);\r
825\r
826 case SOFT_DEBUGGER_REGISTER_FP_OPCODE:\r
827 *Width = (UINT8) sizeof (UINT16);\r
828 return OFFSET_OF(DEBUG_DATA_FX_SAVE_STATE, Opcode);\r
829\r
830 case SOFT_DEBUGGER_REGISTER_FP_EIP:\r
831 *Width = (UINT8) sizeof (UINT32);\r
832 return OFFSET_OF(DEBUG_DATA_FX_SAVE_STATE, Eip);\r
833\r
834 case SOFT_DEBUGGER_REGISTER_FP_CS:\r
835 *Width = (UINT8) sizeof (UINT16);\r
836 return OFFSET_OF(DEBUG_DATA_FX_SAVE_STATE, Cs);\r
837\r
838 case SOFT_DEBUGGER_REGISTER_FP_DATAOFFSET:\r
839 *Width = (UINT8) sizeof (UINT32);\r
840 return OFFSET_OF(DEBUG_DATA_FX_SAVE_STATE, DataOffset);\r
841\r
842 case SOFT_DEBUGGER_REGISTER_FP_DS:\r
843 *Width = (UINT8) sizeof (UINT16);\r
844 return OFFSET_OF(DEBUG_DATA_FX_SAVE_STATE, Ds);\r
845\r
846 case SOFT_DEBUGGER_REGISTER_FP_MXCSR:\r
847 *Width = (UINT8) sizeof (UINT32);\r
848 return OFFSET_OF(DEBUG_DATA_FX_SAVE_STATE, Mxcsr);\r
849\r
850 case SOFT_DEBUGGER_REGISTER_FP_MXCSR_MASK:\r
851 *Width = (UINT8) sizeof (UINT32);\r
852 return OFFSET_OF(DEBUG_DATA_FX_SAVE_STATE, Mxcsr_Mask);\r
853 }\r
854 }\r
855\r
856 if (Index <= SOFT_DEBUGGER_REGISTER_ST7) {\r
857 *Width = 10;\r
858 } else if (Index <= SOFT_DEBUGGER_REGISTER_XMM15) {\r
859 *Width = 16;\r
860 } else {\r
861 //\r
862 // MMX register\r
863 //\r
864 *Width = 8;\r
865 Index -= SOFT_DEBUGGER_REGISTER_MM0 - SOFT_DEBUGGER_REGISTER_ST0;\r
866 }\r
867\r
868 return OFFSET_OF (DEBUG_DATA_FX_SAVE_STATE, St0Mm0) + (Index - SOFT_DEBUGGER_REGISTER_ST0) * 16;\r
869}\r
870\r
871/**\r
872 Return the pointer of the register value in the CPU saved context.\r
873\r
874 @param[in] CpuContext Pointer to saved CPU context.\r
875 @param[in] Index Register index value.\r
876 @param[out] Width Data width to read.\r
877\r
878 @return The pointer in the CPU saved context.\r
879\r
880**/\r
881UINT8 *\r
882ArchReadRegisterBuffer (\r
883 IN DEBUG_CPU_CONTEXT *CpuContext,\r
884 IN UINT8 Index,\r
885 OUT UINT8 *Width\r
886 )\r
887{\r
888 UINT8 *Buffer;\r
889\r
890 if (Index < SOFT_DEBUGGER_REGISTER_FP_BASE) {\r
891 Buffer = (UINT8 *) CpuContext + OFFSET_OF (DEBUG_CPU_CONTEXT, Dr0) + Index * sizeof (UINTN);\r
892 *Width = (UINT8) sizeof (UINTN);\r
893 } else {\r
894 //\r
895 // FPU/MMX/XMM registers\r
896 //\r
897 Buffer = (UINT8 *) CpuContext + OFFSET_OF (DEBUG_CPU_CONTEXT, FxSaveState) + ArchReadFxStatOffset (Index, Width);\r
898 }\r
899\r
900 return Buffer;\r
901}\r
902\r
903/**\r
904 Send the packet without data to HOST.\r
905\r
906 @param[in] CommandType Type of Command.\r
907 @param[in] SequenceNo Sequence number.\r
908\r
909**/\r
910VOID\r
911SendPacketWithoutData (\r
912 IN UINT8 CommandType,\r
913 IN UINT8 SequenceNo\r
914 )\r
915{\r
916 DEBUG_PACKET_HEADER DebugHeader;\r
917 DEBUG_PORT_HANDLE Handle;\r
918\r
919 Handle = GetDebugPortHandle();\r
920\r
921 DebugHeader.StartSymbol = DEBUG_STARTING_SYMBOL_NORMAL;\r
922 DebugHeader.Command = CommandType;\r
923 DebugHeader.Length = sizeof (DEBUG_PACKET_HEADER);\r
924 DebugHeader.SequenceNo = SequenceNo;\r
925 DebugHeader.Crc = 0;\r
926 DebugHeader.Crc = CalculateCrc16 ((UINT8 *)&DebugHeader, sizeof (DEBUG_PACKET_HEADER), 0);\r
927\r
928 DebugAgentDataMsgPrint (DEBUG_AGENT_VERBOSE, TRUE, (UINT8 *) &DebugHeader, DebugHeader.Length);\r
929 DebugPortWriteBuffer (Handle, (UINT8 *) &DebugHeader, DebugHeader.Length);\r
930}\r
931\r
932/**\r
933 Send acknowledge packet to HOST.\r
934\r
935 @param[in] AckCommand Type of Acknowledge packet.\r
936\r
937**/\r
938VOID\r
939SendAckPacket (\r
940 IN UINT8 AckCommand\r
941 )\r
942{\r
943 UINT8 SequenceNo;\r
944 DEBUG_AGENT_MAILBOX *Mailbox;\r
945\r
946 if (AckCommand != DEBUG_COMMAND_OK) {\r
947 //\r
948 // This is not ACK OK packet\r
949 //\r
950 DebugAgentMsgPrint (DEBUG_AGENT_ERROR, "Send ACK(%d)\n", AckCommand);\r
951 }\r
952 Mailbox = GetMailboxPointer();\r
953 SequenceNo = Mailbox->HostSequenceNo;\r
954 DebugAgentMsgPrint (DEBUG_AGENT_INFO, "SendAckPacket: SequenceNo = %x\n", SequenceNo);\r
955 SendPacketWithoutData (AckCommand, SequenceNo);\r
956 UpdateMailboxContent (Mailbox, DEBUG_MAILBOX_LAST_ACK, AckCommand);\r
957}\r
958\r
959/**\r
960 Decompress the Data in place.\r
961\r
962 @param[in, out] Data The compressed data buffer.\r
963 The buffer is assumed large enough to hold the uncompressed data.\r
964 @param[in] Length The length of the compressed data buffer.\r
965\r
966 @return The length of the uncompressed data buffer.\r
967**/\r
968UINT8\r
969DecompressDataInPlace (\r
970 IN OUT UINT8 *Data,\r
971 IN UINTN Length\r
972 )\r
973{\r
974 UINTN Index;\r
975 UINT16 LastChar;\r
976 UINTN LastCharCount;\r
977 UINT8 CurrentChar;\r
978\r
979 LastChar = (UINT16) -1;\r
980 LastCharCount = 0;\r
981 for (Index = 0; Index < Length; Index++) {\r
982 CurrentChar = Data[Index];\r
983 if (LastCharCount == 2) {\r
984 LastCharCount = 0;\r
985 CopyMem (&Data[Index + CurrentChar], &Data[Index + 1], Length - Index - 1);\r
986 SetMem (&Data[Index], CurrentChar, (UINT8) LastChar);\r
987 LastChar = (UINT16) -1;\r
988 Index += CurrentChar - 1;\r
989 Length += CurrentChar - 1;\r
990 } else {\r
991 if (LastChar != CurrentChar) {\r
992 LastCharCount = 0;\r
993 }\r
994 LastCharCount++;\r
995 LastChar = CurrentChar;\r
996 }\r
997 }\r
998\r
999 ASSERT (Length <= DEBUG_DATA_MAXIMUM_REAL_DATA);\r
1000\r
1001 return (UINT8) Length;\r
1002}\r
1003\r
1004/**\r
1005 Receive valid packet from HOST.\r
1006\r
1007 @param[out] InputPacket Buffer to receive packet.\r
1008 @param[out] BreakReceived TRUE means break-in symbol received.\r
1009 FALSE means break-in symbol not received.\r
1010 @param[out] IncompatibilityFlag If IncompatibilityFlag is not NULL, return\r
1011 TRUE: Compatible packet received.\r
1012 FALSE: Incompatible packet received.\r
1013 @param[in] Timeout Time out value to wait for acknowlege from HOST.\r
1014 The unit is microsecond.\r
1015 @param[in] SkipStartSymbol TRUE: Skip time out when reading start symbol.\r
1016 FALSE: Does not Skip time out when reading start symbol.\r
1017\r
1018 @retval RETURN_SUCCESS A valid package was reveived in InputPacket.\r
1019 @retval RETURN_TIMEOUT Timeout occurs.\r
1020\r
1021**/\r
1022RETURN_STATUS\r
1023ReceivePacket (\r
1024 OUT UINT8 *InputPacket,\r
1025 OUT BOOLEAN *BreakReceived,\r
1026 OUT BOOLEAN *IncompatibilityFlag, OPTIONAL\r
1027 IN UINTN Timeout,\r
1028 IN BOOLEAN SkipStartSymbol\r
1029 )\r
1030{\r
1031 DEBUG_PACKET_HEADER *DebugHeader;\r
1032 UINTN Received;\r
1033 DEBUG_PORT_HANDLE Handle;\r
1034 UINT16 Crc;\r
1035 UINTN TimeoutForStartSymbol;\r
1036\r
1037 Handle = GetDebugPortHandle();\r
1038 if (SkipStartSymbol) {\r
1039 TimeoutForStartSymbol = 0;\r
1040 } else {\r
1041 TimeoutForStartSymbol = Timeout;\r
1042 }\r
1043\r
1044 DebugHeader = (DEBUG_PACKET_HEADER *) InputPacket;\r
1045 while (TRUE) {\r
1046 //\r
1047 // Find the valid start symbol\r
1048 //\r
1049 Received = DebugPortReadBuffer (Handle, &DebugHeader->StartSymbol, sizeof (DebugHeader->StartSymbol), TimeoutForStartSymbol);\r
1050 if (Received < sizeof (DebugHeader->StartSymbol)) {\r
1051 DebugAgentMsgPrint (DEBUG_AGENT_WARNING, "DebugPortReadBuffer(StartSymbol) timeout\n");\r
1052 return RETURN_TIMEOUT;\r
1053 }\r
1054\r
1055 if ((DebugHeader->StartSymbol != DEBUG_STARTING_SYMBOL_NORMAL) && (DebugHeader->StartSymbol != DEBUG_STARTING_SYMBOL_COMPRESS)) {\r
1056 DebugAgentMsgPrint (DEBUG_AGENT_WARNING, "Invalid start symbol received [%02x]\n", DebugHeader->StartSymbol);\r
1057 continue;\r
1058 }\r
1059\r
1060 //\r
1061 // Read Package header till field Length\r
1062 //\r
1063 Received = DebugPortReadBuffer (\r
1064 Handle,\r
1065 (UINT8 *) DebugHeader + OFFSET_OF (DEBUG_PACKET_HEADER, Command),\r
1066 OFFSET_OF (DEBUG_PACKET_HEADER, Length) + sizeof (DebugHeader->Length) - sizeof (DebugHeader->StartSymbol),\r
1067 Timeout\r
1068 );\r
1069 if (Received == 0) {\r
1070 DebugAgentMsgPrint (DEBUG_AGENT_ERROR, "DebugPortReadBuffer(Command) timeout\n");\r
1071 return RETURN_TIMEOUT;\r
1072 }\r
1073 if (DebugHeader->Length < sizeof (DEBUG_PACKET_HEADER)) {\r
1074 if (IncompatibilityFlag != NULL) {\r
1075 //\r
1076 // This is one old version debug packet format, set Incompatibility flag\r
1077 //\r
1078 *IncompatibilityFlag = TRUE;\r
1079 } else {\r
1080 //\r
1081 // Skip the bad small packet\r
1082 //\r
1083 continue;\r
1084 }\r
1085 } else {\r
1086 //\r
1087 // Read the payload data include the CRC field\r
1088 //\r
1089 Received = DebugPortReadBuffer (Handle, &DebugHeader->SequenceNo, (UINT8) (DebugHeader->Length - OFFSET_OF (DEBUG_PACKET_HEADER, SequenceNo)), Timeout);\r
1090 if (Received == 0) {\r
1091 DebugAgentMsgPrint (DEBUG_AGENT_ERROR, "DebugPortReadBuffer(SequenceNo) timeout\n");\r
1092 return RETURN_TIMEOUT;\r
1093 }\r
1094 //\r
1095 // Calculate the CRC of Debug Packet\r
1096 //\r
1097 Crc = DebugHeader->Crc;\r
1098 DebugHeader->Crc = 0;\r
1099 if (Crc == CalculateCrc16 ((UINT8 *) DebugHeader, DebugHeader->Length, 0)) {\r
1100 break;\r
1101 }\r
1102 DebugAgentMsgPrint (DEBUG_AGENT_WARNING, "CRC Error (received CRC is %x)\n", Crc);\r
1103 DebugAgentDataMsgPrint (DEBUG_AGENT_VERBOSE, FALSE, (UINT8 *) DebugHeader, DebugHeader->Length);\r
1104 }\r
1105 }\r
1106\r
1107 DebugAgentDataMsgPrint (DEBUG_AGENT_VERBOSE, FALSE, (UINT8 *) DebugHeader, DebugHeader->Length);\r
1108\r
1109 if (DebugHeader->StartSymbol == DEBUG_STARTING_SYMBOL_COMPRESS) {\r
1110 DebugHeader->StartSymbol = DEBUG_STARTING_SYMBOL_NORMAL;\r
1111 DebugHeader->Length = DecompressDataInPlace (\r
1112 (UINT8 *) (DebugHeader + 1), DebugHeader->Length - sizeof (DEBUG_PACKET_HEADER)\r
1113 ) + sizeof (DEBUG_PACKET_HEADER);\r
1114 }\r
1115 return RETURN_SUCCESS;\r
1116}\r
1117\r
1118/**\r
1119 Receive acknowledge packet OK from HOST in specified time.\r
1120\r
1121 @param[in] Command The command type issued by TARGET.\r
1122 @param[in] Timeout Time out value to wait for acknowlege from HOST.\r
1123 The unit is microsecond.\r
1124 @param[out] BreakReceived If BreakReceived is not NULL,\r
1125 TRUE is retured if break-in symbol received.\r
1126 FALSE is retured if break-in symbol not received.\r
1127 @param[out] IncompatibilityFlag If IncompatibilityFlag is not NULL, return\r
1128 TRUE: Compatible packet received.\r
1129 FALSE: Incompatible packet received.\r
1130\r
1131 @retval RETRUEN_SUCCESS Succeed to receive acknowlege packet from HOST,\r
1132 the type of acknowlege packet saved in Ack.\r
1133 @retval RETURN_TIMEOUT Specified timeout value was up.\r
1134\r
1135**/\r
1136RETURN_STATUS\r
1137SendCommandAndWaitForAckOK (\r
1138 IN UINT8 Command,\r
1139 IN UINTN Timeout,\r
1140 OUT BOOLEAN *BreakReceived, OPTIONAL\r
1141 OUT BOOLEAN *IncompatibilityFlag OPTIONAL\r
1142 )\r
1143{\r
1144 RETURN_STATUS Status;\r
1145 UINT8 InputPacketBuffer[DEBUG_DATA_UPPER_LIMIT];\r
1146 DEBUG_PACKET_HEADER *DebugHeader;\r
1147 UINT8 SequenceNo;\r
1148 UINT8 HostSequenceNo;\r
1149 UINT8 RetryCount;\r
1150\r
1151 RetryCount = 3;\r
1152 DebugHeader = (DEBUG_PACKET_HEADER *) InputPacketBuffer;\r
1153 Status = RETURN_TIMEOUT;\r
1154 while (RetryCount > 0) {\r
1155 SequenceNo = GetMailboxPointer()->SequenceNo;\r
1156 HostSequenceNo = GetMailboxPointer()->HostSequenceNo;\r
1157 SendPacketWithoutData (Command, SequenceNo);\r
1158 Status = ReceivePacket ((UINT8 *) DebugHeader, BreakReceived, IncompatibilityFlag, Timeout, FALSE);\r
1159 if (Status == RETURN_TIMEOUT) {\r
1160 if (Command == DEBUG_COMMAND_INIT_BREAK) {\r
1161 RetryCount--;\r
1162 } else {\r
1163 DebugAgentMsgPrint (DEBUG_AGENT_WARNING, "TARGET: Timeout when waiting for ACK packet.\n");\r
1164 }\r
1165 continue;\r
1166 }\r
1167 ASSERT_EFI_ERROR (Status);\r
1168 //\r
1169 // Status == RETURN_SUCCESS\r
1170 //\r
1171 if (DebugHeader->Command == DEBUG_COMMAND_OK && DebugHeader->SequenceNo == SequenceNo) {\r
1172 //\r
1173 // Received Ack OK\r
1174 //\r
1175 UpdateMailboxContent (GetMailboxPointer(), DEBUG_MAILBOX_SEQUENCE_NO_INDEX, ++SequenceNo);\r
1176 return Status;\r
1177 }\r
1178 if (DebugHeader->Command == DEBUG_COMMAND_GO && (DebugHeader->SequenceNo == HostSequenceNo || Command == DEBUG_COMMAND_INIT_BREAK)) {\r
1179 //\r
1180 // Received Old GO\r
1181 //\r
1182 if (Command == DEBUG_COMMAND_INIT_BREAK) {\r
1183 DebugAgentMsgPrint (DEBUG_AGENT_WARNING, "TARGET: Receive GO() in last boot\n");\r
1184 }\r
1185 SendPacketWithoutData (DEBUG_COMMAND_OK, DebugHeader->SequenceNo);\r
1186 }\r
1187 }\r
1188\r
1189 ASSERT (Command == DEBUG_COMMAND_INIT_BREAK);\r
1190 return Status;\r
1191}\r
1192\r
1193/**\r
1194 Get current break cause.\r
1195\r
1196 @param[in] Vector Vector value of exception or interrupt.\r
1197 @param[in] CpuContext Pointer to save CPU context.\r
1198\r
1199 @return The type of break cause defined by XXXX\r
1200\r
1201**/\r
1202UINT8\r
1203GetBreakCause (\r
1204 IN UINTN Vector,\r
1205 IN DEBUG_CPU_CONTEXT *CpuContext\r
1206 )\r
1207{\r
1208 UINT8 Cause;\r
1209\r
1210 Cause = DEBUG_DATA_BREAK_CAUSE_UNKNOWN;\r
1211\r
1212 switch (Vector) {\r
1213 case DEBUG_INT1_VECTOR:\r
1214 case DEBUG_INT3_VECTOR:\r
1215\r
1216 if (Vector == DEBUG_INT1_VECTOR) {\r
1217 //\r
1218 // INT 1\r
1219 //\r
1220 if ((CpuContext->Dr6 & BIT14) != 0) {\r
1221 Cause = DEBUG_DATA_BREAK_CAUSE_STEPPING;\r
1222 //\r
1223 // If it's single step, no need to check DR0, to ensure single step work in PeCoffExtraActionLib\r
1224 // (right after triggering a breakpoint to report image load/unload).\r
1225 //\r
1226 return Cause;\r
1227\r
1228 } else {\r
1229 Cause = DEBUG_DATA_BREAK_CAUSE_HW_BREAKPOINT;\r
1230 }\r
1231 } else {\r
1232 //\r
1233 // INT 3\r
1234 //\r
1235 Cause = DEBUG_DATA_BREAK_CAUSE_SW_BREAKPOINT;\r
1236 }\r
1237\r
1238 switch (CpuContext->Dr0) {\r
1239 case IMAGE_LOAD_SIGNATURE:\r
1240 case IMAGE_UNLOAD_SIGNATURE:\r
1241\r
1242 if (CpuContext->Dr3 == IO_PORT_BREAKPOINT_ADDRESS) {\r
1243\r
1244 Cause = (UINT8) ((CpuContext->Dr0 == IMAGE_LOAD_SIGNATURE) ?\r
1245 DEBUG_DATA_BREAK_CAUSE_IMAGE_LOAD : DEBUG_DATA_BREAK_CAUSE_IMAGE_UNLOAD);\r
1246 }\r
1247 break;\r
1248\r
1249 case SOFT_INTERRUPT_SIGNATURE:\r
1250\r
1251 if (CpuContext->Dr1 == MEMORY_READY_SIGNATURE) {\r
1252 Cause = DEBUG_DATA_BREAK_CAUSE_MEMORY_READY;\r
1253 CpuContext->Dr0 = 0;\r
1254 } else if (CpuContext->Dr1 == SYSTEM_RESET_SIGNATURE) {\r
1255 Cause = DEBUG_DATA_BREAK_CAUSE_SYSTEM_RESET;\r
1256 CpuContext->Dr0 = 0;\r
1257 }\r
1258 break;\r
1259\r
1260 default:\r
1261 break;\r
1262\r
1263 }\r
1264\r
1265 break;\r
1266\r
1267 case DEBUG_TIMER_VECTOR:\r
1268 Cause = DEBUG_DATA_BREAK_CAUSE_USER_HALT;\r
1269 break;\r
1270\r
1271 default:\r
1272 if (Vector < 20) {\r
1273 if (GetDebugFlag (DEBUG_AGENT_FLAG_STEPPING) == 1) {\r
1274 //\r
1275 // If stepping command is executing\r
1276 //\r
1277 Cause = DEBUG_DATA_BREAK_CAUSE_STEPPING;\r
1278 } else {\r
1279 Cause = DEBUG_DATA_BREAK_CAUSE_EXCEPTION;\r
1280 }\r
1281 }\r
1282 break;\r
1283 }\r
1284\r
1285 return Cause;\r
1286}\r
1287\r
1288/**\r
1289 Copy memory from source to destination with specified width.\r
1290\r
1291 @param[out] Dest A pointer to the destination buffer of the memory copy.\r
1292 @param[in] Src A pointer to the source buffer of the memory copy.\r
1293 @param[in] Count The number of data with specified width to copy from source to destination.\r
1294 @param[in] Width Data width in byte.\r
1295\r
1296**/\r
1297VOID\r
1298CopyMemByWidth (\r
1299 OUT UINT8 *Dest,\r
1300 IN UINT8 *Src,\r
1301 IN UINT16 Count,\r
1302 IN UINT8 Width\r
1303 )\r
1304{\r
1305 UINT8 *Destination;\r
1306 UINT8 *Source;\r
1307 INT8 Step;\r
1308\r
1309 if (Src > Dest) {\r
1310 Destination = Dest;\r
1311 Source = Src;\r
1312 Step = Width;\r
1313 } else {\r
1314 //\r
1315 // Copy memory from tail to avoid memory overlap\r
1316 //\r
1317 Destination = Dest + (Count - 1) * Width;\r
1318 Source = Src + (Count - 1) * Width;\r
1319 Step = -Width;\r
1320 }\r
1321\r
1322 while (Count-- != 0) {\r
1323 switch (Width) {\r
1324 case 1:\r
1325 *(UINT8 *) Destination = MmioRead8 ((UINTN) Source);\r
1326 break;\r
1327 case 2:\r
1328 *(UINT16 *) Destination = MmioRead16 ((UINTN) Source);\r
1329 break;\r
1330 case 4:\r
1331 *(UINT32 *) Destination = MmioRead32 ((UINTN) Source);\r
1332 break;\r
1333 case 8:\r
1334 *(UINT64 *) Destination = MmioRead64 ((UINTN) Source);\r
1335 break;\r
1336 default:\r
1337 ASSERT (FALSE);\r
1338 }\r
1339 Source += Step;\r
1340 Destination += Step;\r
1341 }\r
1342}\r
1343\r
1344/**\r
1345 Compress the data buffer but do not modify the original buffer.\r
1346\r
1347 The compressed data is directly send to the debug channel.\r
1348 Compressing in place doesn't work because the data may become larger\r
1349 during compressing phase. ("3 3 ..." --> "3 3 0 ...")\r
1350 The routine is expected to be called three times:\r
1351 1. Compute the length of the compressed data buffer;\r
1352 2. Compute the CRC of the compressed data buffer;\r
1353 3. Compress the data and send to the debug channel.\r
1354\r
1355 @param[in] Data The data buffer.\r
1356 @param[in] Length The length of the data buffer.\r
1357 @param[out] CompressedLength Return the length of the compressed data buffer.\r
1358 It may be larger than the Length in some cases.\r
1359 @param[out] CompressedCrc Return the CRC of the compressed data buffer.\r
1360 @param[in] Handle The debug channel handle to send the compressed data buffer.\r
1361**/\r
1362VOID\r
1363CompressDataThenSend (\r
1364 IN UINT8 *Data,\r
1365 IN UINT8 Length,\r
1366 OUT UINTN *CompressedLength, OPTIONAL\r
1367 OUT UINT16 *CompressedCrc, OPTIONAL\r
1368 IN DEBUG_PORT_HANDLE Handle OPTIONAL\r
1369 )\r
1370{\r
1371 UINTN Index;\r
1372 UINT8 LastChar;\r
1373 UINT8 LastCharCount;\r
1374 UINT8 CurrentChar;\r
1375 UINTN CompressedIndex;\r
1376\r
1377 ASSERT (Length > 0);\r
1378\r
1379 LastChar = Data[0] + 1; // Just ensure it's different from the first byte.\r
1380 LastCharCount = 0;\r
1381\r
1382 for (Index = 0, CompressedIndex = 0; Index <= Length; Index++) {\r
1383 if (Index < Length) {\r
1384 CurrentChar = Data[Index];\r
1385 } else {\r
1386 CurrentChar = (UINT8) LastChar + 1; // just ensure it's different from LastChar\r
1387 }\r
1388 if (LastChar != CurrentChar) {\r
1389 if (LastCharCount == 1) {\r
1390 CompressedIndex++;\r
1391 if (CompressedCrc != NULL) {\r
1392 *CompressedCrc = CalculateCrc16 (&LastChar, 1, *CompressedCrc);\r
1393 }\r
1394 if (Handle != NULL) {\r
1395 DebugPortWriteBuffer (Handle, &LastChar, 1);\r
1396 }\r
1397 \r
1398 } else if (LastCharCount >= 2) {\r
1399 CompressedIndex += 3;\r
1400 LastCharCount -= 2;\r
1401 if (CompressedCrc != NULL) {\r
1402 *CompressedCrc = CalculateCrc16 (&LastChar, 1, *CompressedCrc);\r
1403 *CompressedCrc = CalculateCrc16 (&LastChar, 1, *CompressedCrc);\r
1404 *CompressedCrc = CalculateCrc16 (&LastCharCount, 1, *CompressedCrc);\r
1405 }\r
1406 if (Handle != NULL) {\r
1407 DebugPortWriteBuffer (Handle, &LastChar, 1);\r
1408 DebugPortWriteBuffer (Handle, &LastChar, 1);\r
1409 DebugPortWriteBuffer (Handle, &LastCharCount, 1);\r
1410 }\r
1411 }\r
1412 LastCharCount = 0;\r
1413 }\r
1414 LastCharCount++;\r
1415 LastChar = CurrentChar;\r
1416 }\r
1417\r
1418 if (CompressedLength != NULL) {\r
1419 *CompressedLength = CompressedIndex;\r
1420 }\r
1421}\r
1422\r
1423/**\r
1424 Read memory with speicifed width and send packet with response data to HOST.\r
1425\r
1426 @param[in] Data Pointer to response data buffer.\r
1427 @param[in] Count The number of data with specified Width.\r
1428 @param[in] Width Data width in byte.\r
1429 @param[in] DebugHeader Pointer to a buffer for creating response packet and receiving ACK packet,\r
1430 to minimize the stack usage.\r
1431\r
1432 @retval RETURN_SUCCESS Response data was sent successfully.\r
1433\r
1434**/\r
1435RETURN_STATUS\r
1436ReadMemoryAndSendResponsePacket (\r
1437 IN UINT8 *Data,\r
1438 IN UINT16 Count,\r
1439 IN UINT8 Width,\r
1440 IN DEBUG_PACKET_HEADER *DebugHeader\r
1441 )\r
1442{\r
1443 RETURN_STATUS Status;\r
1444 BOOLEAN LastPacket;\r
1445 DEBUG_PORT_HANDLE Handle;\r
1446 UINT8 SequenceNo;\r
1447 UINTN RemainingDataSize;\r
1448 UINT8 CurrentDataSize;\r
1449 UINTN CompressedDataSize;\r
1450\r
1451 Handle = GetDebugPortHandle();\r
1452\r
1453 RemainingDataSize = Count * Width;\r
1454 while (TRUE) {\r
1455 SequenceNo = GetMailboxPointer()->HostSequenceNo;\r
1456 if (RemainingDataSize <= DEBUG_DATA_MAXIMUM_REAL_DATA) {\r
1457 //\r
1458 // If the remaining data is less one real packet size, this is the last data packet\r
1459 //\r
1460 CurrentDataSize = (UINT8) RemainingDataSize;\r
1461 LastPacket = TRUE;\r
1462 DebugHeader->Command = DEBUG_COMMAND_OK;\r
1463 } else {\r
1464 //\r
1465 // Data is too larger to be sent in one packet, calculate the actual data size could\r
1466 // be sent in one Maximum data packet\r
1467 //\r
1468 CurrentDataSize = (DEBUG_DATA_MAXIMUM_REAL_DATA / Width) * Width;\r
1469 LastPacket = FALSE;\r
1470 DebugHeader->Command = DEBUG_COMMAND_IN_PROGRESS;\r
1471 }\r
1472 //\r
1473 // Construct the rest Debug header\r
1474 //\r
1475 DebugHeader->StartSymbol = DEBUG_STARTING_SYMBOL_NORMAL;\r
1476 DebugHeader->Length = CurrentDataSize + sizeof (DEBUG_PACKET_HEADER);\r
1477 DebugHeader->SequenceNo = SequenceNo;\r
1478 DebugHeader->Crc = 0;\r
1479 CopyMemByWidth ((UINT8 *) (DebugHeader + 1), Data, CurrentDataSize / Width, Width);\r
1480\r
1481 //\r
1482 // Compression/decompression support was added since revision 0.4.\r
1483 // Revision 0.3 shouldn't compress the packet.\r
1484 //\r
1485 if (DEBUG_AGENT_REVISION >= DEBUG_AGENT_REVISION_04) {\r
1486 //\r
1487 // Get the compressed data size without modifying the packet.\r
1488 //\r
1489 CompressDataThenSend (\r
1490 (UINT8 *) (DebugHeader + 1),\r
1491 CurrentDataSize,\r
1492 &CompressedDataSize,\r
1493 NULL,\r
1494 NULL\r
1495 );\r
1496 } else {\r
1497 CompressedDataSize = CurrentDataSize;\r
1498 }\r
1499 if (CompressedDataSize < CurrentDataSize) {\r
1500 DebugHeader->Length = (UINT8) CompressedDataSize + sizeof (DEBUG_PACKET_HEADER);\r
1501 DebugHeader->StartSymbol = DEBUG_STARTING_SYMBOL_COMPRESS;\r
1502 //\r
1503 // Compute the CRC of the packet head without modifying the packet.\r
1504 //\r
1505 DebugHeader->Crc = CalculateCrc16 ((UINT8 *) DebugHeader, sizeof (DEBUG_PACKET_HEADER), 0);\r
1506 CompressDataThenSend (\r
1507 (UINT8 *) (DebugHeader + 1),\r
1508 CurrentDataSize,\r
1509 NULL,\r
1510 &DebugHeader->Crc,\r
1511 NULL\r
1512 );\r
1513 //\r
1514 // Send out the packet head.\r
1515 //\r
1516 DebugPortWriteBuffer (Handle, (UINT8 *) DebugHeader, sizeof (DEBUG_PACKET_HEADER));\r
1517 //\r
1518 // Compress and send out the packet data.\r
1519 //\r
1520 CompressDataThenSend (\r
1521 (UINT8 *) (DebugHeader + 1),\r
1522 CurrentDataSize,\r
1523 NULL,\r
1524 NULL,\r
1525 Handle\r
1526 );\r
1527 } else {\r
1528\r
1529 //\r
1530 // Calculate and fill the checksum, DebugHeader->Crc should be 0 before invoking CalculateCrc16 ()\r
1531 //\r
1532 DebugHeader->Crc = CalculateCrc16 ((UINT8 *) DebugHeader, DebugHeader->Length, 0);\r
1533\r
1534 DebugAgentDataMsgPrint (DEBUG_AGENT_VERBOSE, TRUE, (UINT8 *) DebugHeader, DebugHeader->Length);\r
1535\r
1536 DebugPortWriteBuffer (Handle, (UINT8 *) DebugHeader, DebugHeader->Length);\r
1537 }\r
1538\r
1539 while (TRUE) {\r
1540 Status = ReceivePacket ((UINT8 *) DebugHeader, NULL, NULL, READ_PACKET_TIMEOUT, FALSE);\r
1541 if (Status == RETURN_TIMEOUT) {\r
1542 DebugAgentMsgPrint (DEBUG_AGENT_WARNING, "TARGET: Timeout in SendDataResponsePacket()\n");\r
1543 break;\r
1544 }\r
1545 if ((DebugHeader->Command == DEBUG_COMMAND_OK) && (DebugHeader->SequenceNo == SequenceNo) && LastPacket) {\r
1546 //\r
1547 // If this is the last packet, return RETURN_SUCCESS.\r
1548 //\r
1549 return RETURN_SUCCESS;\r
1550 }\r
1551 if ((DebugHeader->Command == DEBUG_COMMAND_CONTINUE) && (DebugHeader->SequenceNo == (UINT8) (SequenceNo + 1))) {\r
1552 //\r
1553 // Calculate the rest data size\r
1554 //\r
1555 Data += CurrentDataSize;\r
1556 RemainingDataSize -= CurrentDataSize;\r
1557 UpdateMailboxContent (GetMailboxPointer(), DEBUG_MAILBOX_HOST_SEQUENCE_NO_INDEX, DebugHeader->SequenceNo);\r
1558 break;\r
1559 }\r
1560 if (DebugHeader->SequenceNo >= SequenceNo) {\r
1561 DebugAgentMsgPrint (DEBUG_AGENT_WARNING, "TARGET: Received one old or new command(SequenceNo is %x, last SequenceNo is %x)\n", SequenceNo, DebugHeader->SequenceNo);\r
1562 break;\r
1563 }\r
1564 }\r
1565 }\r
1566}\r
1567\r
1568/**\r
1569 Send packet with response data to HOST.\r
1570\r
1571 @param[in] Data Pointer to response data buffer.\r
1572 @param[in] DataSize Size of response data in byte.\r
1573 @param[in, out] DebugHeader Pointer to a buffer for creating response packet and receiving ACK packet,\r
1574 to minimize the stack usage.\r
1575\r
1576 @retval RETURN_SUCCESS Response data was sent successfully.\r
1577\r
1578**/\r
1579RETURN_STATUS\r
1580SendDataResponsePacket (\r
1581 IN UINT8 *Data,\r
1582 IN UINT16 DataSize,\r
1583 IN OUT DEBUG_PACKET_HEADER *DebugHeader\r
1584 )\r
1585{\r
1586 return ReadMemoryAndSendResponsePacket (Data, DataSize, 1, DebugHeader);\r
1587}\r
1588\r
1589/**\r
1590 Try to attach the HOST.\r
1591\r
1592 Send init break packet to HOST:\r
1593 If no acknowlege received in specified Timeout, return RETURN_TIMEOUT.\r
1594 If received acknowlege, check the revision of HOST.\r
1595 Set Attach Flag if attach successfully.\r
1596\r
1597 @param[in] BreakCause Break cause of this break event.\r
1598 @param[in] Timeout Time out value to wait for acknowlege from HOST.\r
1599 The unit is microsecond.\r
1600 @param[out] BreakReceived If BreakReceived is not NULL,\r
1601 TRUE is retured if break-in symbol received.\r
1602 FALSE is retured if break-in symbol not received.\r
1603**/\r
1604RETURN_STATUS\r
1605AttachHost (\r
1606 IN UINT8 BreakCause,\r
1607 IN UINTN Timeout,\r
1608 OUT BOOLEAN *BreakReceived\r
1609 )\r
1610{\r
1611 RETURN_STATUS Status;\r
1612 DEBUG_PORT_HANDLE Handle;\r
1613 BOOLEAN IncompatibilityFlag;\r
1614\r
1615 IncompatibilityFlag = FALSE;\r
1616 Handle = GetDebugPortHandle();\r
1617\r
1618 //\r
1619 // Send init break and wait ack in Timeout\r
1620 //\r
1621 DebugPortWriteBuffer (Handle, (UINT8 *) mErrorMsgSendInitPacket, AsciiStrLen (mErrorMsgSendInitPacket));\r
1622 if (BreakCause == DEBUG_DATA_BREAK_CAUSE_SYSTEM_RESET) {\r
1623 Status = SendCommandAndWaitForAckOK (DEBUG_COMMAND_INIT_BREAK, Timeout, BreakReceived, &IncompatibilityFlag);\r
1624 } else {\r
1625 Status = SendCommandAndWaitForAckOK (DEBUG_COMMAND_ATTACH_BREAK, Timeout, BreakReceived, &IncompatibilityFlag);\r
1626 }\r
1627 if (IncompatibilityFlag) {\r
1628 //\r
1629 // If the incompatible Debug Packet received, the HOST should be running transfer protocol before DEBUG_AGENT_REVISION.\r
1630 // It could be UDK Debugger for Windows v1.1/v1.2 or for Linux v0.8/v1.2.\r
1631 //\r
1632 DebugPortWriteBuffer (Handle, (UINT8 *) mErrorMsgVersionAlert, AsciiStrLen (mErrorMsgVersionAlert));\r
1633 CpuDeadLoop ();\r
1634 }\r
1635\r
1636 if (RETURN_ERROR (Status)) {\r
1637 DebugPortWriteBuffer (Handle, (UINT8 *) mErrorMsgConnectFail, AsciiStrLen (mErrorMsgConnectFail));\r
1638 } else {\r
1639 DebugPortWriteBuffer (Handle, (UINT8 *) mErrorMsgConnectOK, AsciiStrLen (mErrorMsgConnectOK));\r
1640 //\r
1641 // Set Attach flag\r
1642 //\r
1643 SetHostAttached (TRUE);\r
1644 }\r
1645 return Status;\r
1646}\r
1647\r
1648/**\r
1649 Send Break point packet to HOST.\r
1650\r
1651 Only the first breaking processor could sent BREAK_POINT packet.\r
1652\r
1653 @param[in] BreakCause Break cause of this break event.\r
1654 @param[in] ProcessorIndex Processor index value.\r
1655 @param[out] BreakReceived If BreakReceived is not NULL,\r
1656 TRUE is retured if break-in symbol received.\r
1657 FALSE is retured if break-in symbol not received.\r
1658\r
1659**/\r
1660VOID\r
1661SendBreakPacketToHost (\r
1662 IN UINT8 BreakCause,\r
1663 IN UINT32 ProcessorIndex,\r
1664 OUT BOOLEAN *BreakReceived\r
1665 )\r
1666{\r
1667 UINT8 InputCharacter;\r
1668 DEBUG_PORT_HANDLE Handle;\r
1669\r
1670 Handle = GetDebugPortHandle();\r
1671\r
1672 if (IsHostAttached ()) {\r
1673 DebugAgentMsgPrint (DEBUG_AGENT_INFO, "processor[%x]:Send Break Packet to HOST.\n", ProcessorIndex);\r
1674 SendCommandAndWaitForAckOK (DEBUG_COMMAND_BREAK_POINT, READ_PACKET_TIMEOUT, BreakReceived, NULL);\r
1675 } else {\r
1676 DebugAgentMsgPrint (DEBUG_AGENT_INFO, "processor[%x]:Try to attach HOST.\n", ProcessorIndex);\r
1677 //\r
1678 // If HOST is not attached, try to attach it firstly.\r
1679 //\r
1680 //\r
1681 // Poll Attach symbols from HOST and ack OK\r
1682 //\r
1683 do {\r
1684 DebugPortReadBuffer (Handle, &InputCharacter, 1, 0);\r
1685 } while (InputCharacter != DEBUG_STARTING_SYMBOL_ATTACH);\r
1686 SendAckPacket (DEBUG_COMMAND_OK);\r
1687\r
1688 //\r
1689 // Try to attach HOST\r
1690 //\r
1691 while (AttachHost (BreakCause, 0, NULL) != RETURN_SUCCESS);\r
1692\r
1693 }\r
1694}\r
1695\r
1696/**\r
1697 The main function to process communication with HOST.\r
1698\r
1699 It received the command packet from HOST, and sent response data packet to HOST.\r
1700\r
1701 @param[in] Vector Vector value of exception or interrutp.\r
1702 @param[in, out] CpuContext Pointer to saved CPU context.\r
1703 @param[in] BreakReceived TRUE means break-in symbol received.\r
1704 FALSE means break-in symbol not received.\r
1705\r
1706**/\r
1707VOID\r
1708CommandCommunication (\r
1709 IN UINTN Vector,\r
1710 IN OUT DEBUG_CPU_CONTEXT *CpuContext,\r
1711 IN BOOLEAN BreakReceived\r
1712 )\r
1713{\r
1714 RETURN_STATUS Status;\r
1715 UINT8 InputPacketBuffer[DEBUG_DATA_UPPER_LIMIT + sizeof (UINT64) - 1];\r
1716 DEBUG_PACKET_HEADER *DebugHeader;\r
1717 UINT8 Width;\r
1718 UINT8 Data8;\r
1719 UINT32 Data32;\r
1720 UINT64 Data64;\r
1721 DEBUG_DATA_READ_MEMORY *MemoryRead;\r
1722 DEBUG_DATA_WRITE_MEMORY *MemoryWrite;\r
1723 DEBUG_DATA_READ_IO *IoRead;\r
1724 DEBUG_DATA_WRITE_IO *IoWrite;\r
1725 DEBUG_DATA_READ_REGISTER *RegisterRead;\r
1726 DEBUG_DATA_WRITE_REGISTER *RegisterWrite;\r
1727 UINT8 *RegisterBuffer;\r
1728 DEBUG_DATA_READ_MSR *MsrRegisterRead;\r
1729 DEBUG_DATA_WRITE_MSR *MsrRegisterWrite;\r
1730 DEBUG_DATA_CPUID *Cpuid;\r
1731 DEBUG_DATA_RESPONSE_BREAK_CAUSE BreakCause;\r
1732 DEBUG_DATA_RESPONSE_CPUID CpuidResponse;\r
1733 DEBUG_DATA_SEARCH_SIGNATURE *SearchSignature;\r
1734 DEBUG_DATA_RESPONSE_GET_EXCEPTION Exception;\r
1735 DEBUG_DATA_RESPONSE_GET_REVISION DebugAgentRevision;\r
1736 DEBUG_DATA_SET_VIEWPOINT *SetViewPoint;\r
1737 BOOLEAN HaltDeferred;\r
1738 UINT32 ProcessorIndex;\r
1739 DEBUG_PORT_HANDLE Handle;\r
1740 DEBUG_AGENT_EXCEPTION_BUFFER AgentExceptionBuffer;\r
1741 UINT32 IssuedViewPoint;\r
1742 DEBUG_AGENT_MAILBOX *Mailbox;\r
1743 UINT8 *AlignedDataPtr;\r
1744\r
1745 ProcessorIndex = 0;\r
1746 IssuedViewPoint = 0;\r
1747 HaltDeferred = BreakReceived;\r
1748\r
1749 if (MultiProcessorDebugSupport()) {\r
1750 ProcessorIndex = GetProcessorIndex ();\r
1751 SetCpuStopFlagByIndex (ProcessorIndex, TRUE);\r
1752 if (mDebugMpContext.ViewPointIndex == ProcessorIndex) {\r
1753 //\r
1754 // Only the current view processor could set AgentInProgress Flag.\r
1755 //\r
1756 IssuedViewPoint = ProcessorIndex;\r
1757 }\r
1758 }\r
1759\r
1760 if (IssuedViewPoint == ProcessorIndex) {\r
1761 //\r
1762 // Set AgentInProgress Flag.\r
1763 //\r
1764 SetDebugFlag (DEBUG_AGENT_FLAG_AGENT_IN_PROGRESS, 1);\r
1765 }\r
1766\r
1767 Handle = GetDebugPortHandle();\r
1768\r
1769 while (TRUE) {\r
1770\r
1771 if (MultiProcessorDebugSupport()) {\r
1772 //\r
1773 // Check if the current processor is HOST view point\r
1774 //\r
1775 if (mDebugMpContext.ViewPointIndex != ProcessorIndex) {\r
1776 if (mDebugMpContext.RunCommandSet) {\r
1777 //\r
1778 // If HOST view point sets RUN flag, run GO command to leave\r
1779 //\r
1780 SetCpuStopFlagByIndex (ProcessorIndex, FALSE);\r
1781 CommandGo (CpuContext);\r
1782 break;\r
1783 } else {\r
1784 //\r
1785 // Run into loop again\r
1786 //\r
1787 CpuPause ();\r
1788 continue;\r
1789 }\r
1790 }\r
1791 }\r
1792\r
1793 AcquireMpSpinLock (&mDebugMpContext.DebugPortSpinLock);\r
1794\r
1795 DebugHeader =(DEBUG_PACKET_HEADER *) InputPacketBuffer;\r
1796\r
1797 DebugAgentMsgPrint (DEBUG_AGENT_INFO, "TARGET: Try to get command from HOST...\n");\r
1798 Status = ReceivePacket ((UINT8 *) DebugHeader, &BreakReceived, NULL, READ_PACKET_TIMEOUT, TRUE);\r
1799 if (Status != RETURN_SUCCESS || !IS_REQUEST (DebugHeader)) {\r
1800 DebugAgentMsgPrint (DEBUG_AGENT_WARNING, "TARGET: Get command[%x] sequenceno[%x] returned status is [%x] \n", DebugHeader->Command, DebugHeader->SequenceNo, Status);\r
1801 DebugAgentMsgPrint (DEBUG_AGENT_WARNING, "TARGET: Get command failed or it's response packet not expected! \n");\r
1802 ReleaseMpSpinLock (&mDebugMpContext.DebugPortSpinLock);\r
1803 continue;\r
1804 }\r
1805\r
1806 Mailbox = GetMailboxPointer ();\r
1807 if (DebugHeader->SequenceNo == Mailbox->HostSequenceNo) {\r
1808 DebugAgentMsgPrint (DEBUG_AGENT_WARNING, "TARGET: Receive one old command[%x] agaist command[%x]\n", DebugHeader->SequenceNo, Mailbox->HostSequenceNo);\r
1809 SendAckPacket (Mailbox->LastAck);\r
1810 ReleaseMpSpinLock (&mDebugMpContext.DebugPortSpinLock);\r
1811 continue;\r
1812 } else if (DebugHeader->SequenceNo == (UINT8) (Mailbox->HostSequenceNo + 1)) {\r
1813 UpdateMailboxContent (Mailbox, DEBUG_MAILBOX_HOST_SEQUENCE_NO_INDEX, (UINT8) DebugHeader->SequenceNo);\r
1814 } else {\r
1815 DebugAgentMsgPrint (DEBUG_AGENT_WARNING, "Receive one invalid comamnd[%x] agaist command[%x]\n", DebugHeader->SequenceNo, Mailbox->HostSequenceNo);\r
1816 ReleaseMpSpinLock (&mDebugMpContext.DebugPortSpinLock);\r
1817 continue;\r
1818 }\r
1819\r
1820 //\r
1821 // Save CPU content before executing HOST commond\r
1822 //\r
1823 UpdateMailboxContent (Mailbox, DEBUG_MAILBOX_EXCEPTION_BUFFER_POINTER_INDEX, (UINT64)(UINTN) &AgentExceptionBuffer.JumpBuffer);\r
1824 if (SetJump (&AgentExceptionBuffer.JumpBuffer) != 0) {\r
1825 //\r
1826 // If HOST command failed, continue to wait for HOST's next command\r
1827 // If needed, agent could send exception info to HOST.\r
1828 //\r
1829 SendAckPacket (DEBUG_COMMAND_ABORT);\r
1830 ReleaseMpSpinLock (&mDebugMpContext.DebugPortSpinLock);\r
1831 continue;\r
1832 }\r
1833\r
1834 DebugAgentMsgPrint (DEBUG_AGENT_INFO, "Processor[%x]:Received one command(%x)\n", mDebugMpContext.ViewPointIndex, DebugHeader->Command);\r
1835\r
1836 switch (DebugHeader->Command) {\r
1837\r
1838 case DEBUG_COMMAND_HALT:\r
1839 SendAckPacket (DEBUG_COMMAND_HALT_DEFERRED);\r
1840 HaltDeferred = TRUE;\r
1841 BreakReceived = FALSE;\r
1842 Status = RETURN_SUCCESS;\r
1843 break;\r
1844\r
1845 case DEBUG_COMMAND_RESET:\r
1846 SendAckPacket (DEBUG_COMMAND_OK);\r
1847 SendAckPacket (DEBUG_COMMAND_OK);\r
1848 SendAckPacket (DEBUG_COMMAND_OK);\r
1849 ReleaseMpSpinLock (&mDebugMpContext.DebugPortSpinLock);\r
1850\r
1851 ResetCold ();\r
1852 //\r
1853 // Assume system resets in 2 seconds, otherwise send TIMEOUT packet.\r
1854 // PCD can be used if 2 seconds isn't long enough for some platforms.\r
1855 //\r
1856 MicroSecondDelay (2000000);\r
1857 UpdateMailboxContent (Mailbox, DEBUG_MAILBOX_HOST_SEQUENCE_NO_INDEX, Mailbox->HostSequenceNo + 1);\r
1858 SendAckPacket (DEBUG_COMMAND_TIMEOUT);\r
1859 SendAckPacket (DEBUG_COMMAND_TIMEOUT);\r
1860 SendAckPacket (DEBUG_COMMAND_TIMEOUT);\r
1861 break;\r
1862\r
1863 case DEBUG_COMMAND_GO:\r
1864 CommandGo (CpuContext);\r
1865 //\r
1866 // Clear Dr0 to avoid to be recognized as IMAGE_LOAD/_UNLOAD again when hitting a breakpoint after GO\r
1867 // If HOST changed Dr0 before GO, we will not change Dr0 here\r
1868 //\r
1869 Data8 = GetBreakCause (Vector, CpuContext);\r
1870 if (Data8 == DEBUG_DATA_BREAK_CAUSE_IMAGE_LOAD || Data8 == DEBUG_DATA_BREAK_CAUSE_IMAGE_UNLOAD) {\r
1871 CpuContext->Dr0 = 0;\r
1872 }\r
1873 //\r
1874 // Clear Stepping Flag\r
1875 //\r
1876 SetDebugFlag (DEBUG_AGENT_FLAG_STEPPING, 0);\r
1877\r
1878 if (!HaltDeferred) {\r
1879 //\r
1880 // If no HALT command received when being in-active mode\r
1881 //\r
1882 if (MultiProcessorDebugSupport()) {\r
1883 Data32 = FindNextPendingBreakCpu ();\r
1884 if (Data32 != -1) {\r
1885 //\r
1886 // If there are still others processors being in break state,\r
1887 // send OK packet to HOST to finish this go command\r
1888 //\r
1889 SendAckPacket (DEBUG_COMMAND_OK);\r
1890 CpuPause ();\r
1891 //\r
1892 // Set current view to the next breaking processor\r
1893 //\r
1894 mDebugMpContext.ViewPointIndex = Data32;\r
1895 mDebugMpContext.BreakAtCpuIndex = mDebugMpContext.ViewPointIndex;\r
1896 SetCpuBreakFlagByIndex (mDebugMpContext.ViewPointIndex, FALSE);\r
1897 //\r
1898 // Send break packet to HOST to let HOST break again\r
1899 //\r
1900 SendBreakPacketToHost (DEBUG_DATA_BREAK_CAUSE_UNKNOWN, mDebugMpContext.BreakAtCpuIndex, &BreakReceived);\r
1901 //\r
1902 // Continue to run into loop to read command packet from HOST\r
1903 //\r
1904 ReleaseMpSpinLock (&mDebugMpContext.DebugPortSpinLock);\r
1905 break;\r
1906 }\r
1907\r
1908 //\r
1909 // If no else processor break, set stop bitmask,\r
1910 // and set Running flag for all processors.\r
1911 //\r
1912 SetCpuStopFlagByIndex (ProcessorIndex, FALSE);\r
1913 SetCpuRunningFlag (TRUE);\r
1914 CpuPause ();\r
1915 //\r
1916 // Wait for all processors are in running state\r
1917 //\r
1918 while (TRUE) {\r
1919 if (IsAllCpuRunning ()) {\r
1920 break;\r
1921 }\r
1922 }\r
1923 //\r
1924 // Set BSP to be current view point.\r
1925 //\r
1926 SetDebugViewPoint (mDebugMpContext.BspIndex);\r
1927 CpuPause ();\r
1928 //\r
1929 // Clear breaking processor index and running flag\r
1930 //\r
1931 mDebugMpContext.BreakAtCpuIndex = (UINT32) (-1);\r
1932 SetCpuRunningFlag (FALSE);\r
1933 }\r
1934\r
1935 //\r
1936 // Send OK packet to HOST to finish this go command\r
1937 //\r
1938 SendAckPacket (DEBUG_COMMAND_OK);\r
1939\r
1940 ReleaseMpSpinLock (&mDebugMpContext.DebugPortSpinLock);\r
1941\r
1942 if (!IsHostAttached()) {\r
1943 UpdateMailboxContent (Mailbox, DEBUG_MAILBOX_SEQUENCE_NO_INDEX, 0);\r
1944 UpdateMailboxContent (Mailbox, DEBUG_MAILBOX_HOST_SEQUENCE_NO_INDEX, 0);\r
1945 }\r
1946 return;\r
1947\r
1948 } else {\r
1949 //\r
1950 // If reveived HALT command, need to defer the GO command\r
1951 //\r
1952 SendAckPacket (DEBUG_COMMAND_HALT_PROCESSED);\r
1953 HaltDeferred = FALSE;\r
1954\r
1955 Vector = DEBUG_TIMER_VECTOR;\r
1956 }\r
1957 break;\r
1958\r
1959 case DEBUG_COMMAND_BREAK_CAUSE:\r
1960 BreakCause.StopAddress = CpuContext->Eip;\r
1961 if (MultiProcessorDebugSupport() && ProcessorIndex != mDebugMpContext.BreakAtCpuIndex) {\r
1962 BreakCause.Cause = GetBreakCause (DEBUG_TIMER_VECTOR, CpuContext);\r
1963 } else {\r
1964 BreakCause.Cause = GetBreakCause (Vector, CpuContext);\r
1965 }\r
1966 SendDataResponsePacket ((UINT8 *) &BreakCause, (UINT16) sizeof (DEBUG_DATA_RESPONSE_BREAK_CAUSE), DebugHeader);\r
1967 break;\r
1968\r
1969 case DEBUG_COMMAND_SET_HW_BREAKPOINT:\r
1970 SetDebugRegister (CpuContext, (DEBUG_DATA_SET_HW_BREAKPOINT *) (DebugHeader + 1));\r
1971 SendAckPacket (DEBUG_COMMAND_OK);\r
1972 break;\r
1973\r
1974 case DEBUG_COMMAND_CLEAR_HW_BREAKPOINT:\r
1975 ClearDebugRegister (CpuContext, (DEBUG_DATA_CLEAR_HW_BREAKPOINT *) (DebugHeader + 1));\r
1976 SendAckPacket (DEBUG_COMMAND_OK);\r
1977 break;\r
1978\r
1979 case DEBUG_COMMAND_SINGLE_STEPPING:\r
1980 CommandStepping (CpuContext);\r
1981 //\r
1982 // Clear Dr0 to avoid to be recognized as IMAGE_LOAD/_UNLOAD again when hitting a breakpoint after GO\r
1983 // If HOST changed Dr0 before GO, we will not change Dr0 here\r
1984 //\r
1985 Data8 = GetBreakCause (Vector, CpuContext);\r
1986 if (Data8 == DEBUG_DATA_BREAK_CAUSE_IMAGE_LOAD || Data8 == DEBUG_DATA_BREAK_CAUSE_IMAGE_UNLOAD) {\r
1987 CpuContext->Dr0 = 0;\r
1988 }\r
1989\r
1990 mDebugMpContext.BreakAtCpuIndex = (UINT32) (-1);\r
1991 //\r
1992 // Set Stepping Flag\r
1993 //\r
1994 SetDebugFlag (DEBUG_AGENT_FLAG_STEPPING, 1);\r
1995 ReleaseMpSpinLock (&mDebugMpContext.DebugPortSpinLock);\r
1996 //\r
1997 // Executing stepping command directly without sending ACK packet,\r
1998 // ACK packet will be sent after stepping done.\r
1999 //\r
2000 return;\r
2001\r
2002 case DEBUG_COMMAND_SET_SW_BREAKPOINT:\r
2003 Data64 = (UINTN) (((DEBUG_DATA_SET_SW_BREAKPOINT *) (DebugHeader + 1))->Address);\r
2004 Data8 = *(UINT8 *) (UINTN) Data64;\r
2005 *(UINT8 *) (UINTN) Data64 = DEBUG_SW_BREAKPOINT_SYMBOL;\r
2006 Status = SendDataResponsePacket ((UINT8 *) &Data8, (UINT16) sizeof (UINT8), DebugHeader);\r
2007 break;\r
2008\r
2009 case DEBUG_COMMAND_READ_MEMORY:\r
2010 MemoryRead = (DEBUG_DATA_READ_MEMORY *) (DebugHeader + 1);\r
2011 Status = ReadMemoryAndSendResponsePacket ((UINT8 *) (UINTN) MemoryRead->Address, MemoryRead->Count, MemoryRead->Width, DebugHeader);\r
2012 break;\r
2013\r
2014 case DEBUG_COMMAND_WRITE_MEMORY:\r
2015 MemoryWrite = (DEBUG_DATA_WRITE_MEMORY *) (DebugHeader + 1);\r
2016 //\r
2017 // Copy data into one memory with 8-byte alignment address\r
2018 //\r
2019 AlignedDataPtr = ALIGN_POINTER ((UINT8 *) &MemoryWrite->Data, sizeof (UINT64));\r
2020 if (AlignedDataPtr != (UINT8 *) &MemoryWrite->Data) {\r
2021 CopyMem (AlignedDataPtr, (UINT8 *) &MemoryWrite->Data, MemoryWrite->Count * MemoryWrite->Width);\r
2022 }\r
2023 CopyMemByWidth ((UINT8 *) (UINTN) MemoryWrite->Address, AlignedDataPtr, MemoryWrite->Count, MemoryWrite->Width);\r
2024 SendAckPacket (DEBUG_COMMAND_OK);\r
2025 break;\r
2026\r
2027 case DEBUG_COMMAND_READ_IO:\r
2028 IoRead = (DEBUG_DATA_READ_IO *) (DebugHeader + 1);\r
2029 switch (IoRead->Width) {\r
2030 case 1:\r
2031 Data64 = IoRead8 ((UINTN) IoRead->Port);\r
2032 break;\r
2033 case 2:\r
2034 Data64 = IoRead16 ((UINTN) IoRead->Port);\r
2035 break;\r
2036 case 4:\r
2037 Data64 = IoRead32 ((UINTN) IoRead->Port);\r
2038 break;\r
2039 case 8:\r
2040 Data64 = IoRead64 ((UINTN) IoRead->Port);\r
2041 break;\r
2042 default:\r
2043 Data64 = (UINT64) -1;\r
2044 }\r
2045 Status = SendDataResponsePacket ((UINT8 *) &Data64, IoRead->Width, DebugHeader);\r
2046 break;\r
2047\r
2048 case DEBUG_COMMAND_WRITE_IO:\r
2049 IoWrite = (DEBUG_DATA_WRITE_IO *) (DebugHeader + 1);\r
2050 switch (IoWrite->Width) {\r
2051 case 1:\r
2052 Data64 = IoWrite8 ((UINTN) IoWrite->Port, *(UINT8 *) &IoWrite->Data);\r
2053 break;\r
2054 case 2:\r
2055 Data64 = IoWrite16 ((UINTN) IoWrite->Port, *(UINT16 *) &IoWrite->Data);\r
2056 break;\r
2057 case 4:\r
2058 Data64 = IoWrite32 ((UINTN) IoWrite->Port, *(UINT32 *) &IoWrite->Data);\r
2059 break;\r
2060 case 8:\r
2061 Data64 = IoWrite64 ((UINTN) IoWrite->Port, *(UINT64 *) &IoWrite->Data);\r
2062 break;\r
2063 default:\r
2064 Data64 = (UINT64) -1;\r
2065 }\r
2066 SendAckPacket (DEBUG_COMMAND_OK);\r
2067 break;\r
2068\r
2069 case DEBUG_COMMAND_READ_ALL_REGISTERS:\r
2070 Status = SendDataResponsePacket ((UINT8 *) CpuContext, sizeof (*CpuContext), DebugHeader);\r
2071 break;\r
2072\r
2073 case DEBUG_COMMAND_READ_REGISTER:\r
2074 RegisterRead = (DEBUG_DATA_READ_REGISTER *) (DebugHeader + 1);\r
2075\r
2076 if (RegisterRead->Index <= SOFT_DEBUGGER_REGISTER_MAX) {\r
2077 RegisterBuffer = ArchReadRegisterBuffer (CpuContext, RegisterRead->Index, &Width);\r
2078 Status = SendDataResponsePacket (RegisterBuffer, Width, DebugHeader);\r
2079 } else {\r
2080 Status = RETURN_UNSUPPORTED;\r
2081 }\r
2082 break;\r
2083\r
2084 case DEBUG_COMMAND_WRITE_REGISTER:\r
2085 RegisterWrite = (DEBUG_DATA_WRITE_REGISTER *) (DebugHeader + 1);\r
2086 if (RegisterWrite->Index <= SOFT_DEBUGGER_REGISTER_MAX) {\r
2087 RegisterBuffer = ArchReadRegisterBuffer (CpuContext, RegisterWrite->Index, &Width);\r
2088 ASSERT (Width == RegisterWrite->Length);\r
2089 CopyMem (RegisterBuffer, RegisterWrite->Data, Width);\r
2090 SendAckPacket (DEBUG_COMMAND_OK);\r
2091 } else {\r
2092 Status = RETURN_UNSUPPORTED;\r
2093 }\r
2094 break;\r
2095\r
2096 case DEBUG_COMMAND_ARCH_MODE:\r
2097 Data8 = DEBUG_ARCH_SYMBOL;\r
2098 Status = SendDataResponsePacket ((UINT8 *) &Data8, (UINT16) sizeof (UINT8), DebugHeader);\r
2099 break;\r
2100\r
2101 case DEBUG_COMMAND_READ_MSR:\r
2102 MsrRegisterRead = (DEBUG_DATA_READ_MSR *) (DebugHeader + 1);\r
2103 Data64 = AsmReadMsr64 (MsrRegisterRead->Index);\r
2104 Status = SendDataResponsePacket ((UINT8 *) &Data64, (UINT16) sizeof (UINT64), DebugHeader);\r
2105 break;\r
2106\r
2107 case DEBUG_COMMAND_WRITE_MSR:\r
2108 MsrRegisterWrite = (DEBUG_DATA_WRITE_MSR *) (DebugHeader + 1);\r
2109 AsmWriteMsr64 (MsrRegisterWrite->Index, MsrRegisterWrite->Value);\r
2110 SendAckPacket (DEBUG_COMMAND_OK);\r
2111 break;\r
2112\r
2113 case DEBUG_COMMAND_SET_DEBUG_SETTING:\r
2114 Status = SetDebugSetting ((DEBUG_DATA_SET_DEBUG_SETTING *)(DebugHeader + 1));\r
2115 if (Status == RETURN_SUCCESS) {\r
2116 SendAckPacket (DEBUG_COMMAND_OK);\r
2117 }\r
2118 break;\r
2119\r
2120 case DEBUG_COMMAND_GET_REVISION:\r
2121 DebugAgentRevision.Revision = DEBUG_AGENT_REVISION;\r
2122 DebugAgentRevision.Capabilities = DEBUG_AGENT_CAPABILITIES;\r
2123 Status = SendDataResponsePacket ((UINT8 *) &DebugAgentRevision, (UINT16) sizeof (DEBUG_DATA_RESPONSE_GET_REVISION), DebugHeader);\r
2124 break;\r
2125\r
2126 case DEBUG_COMMAND_GET_EXCEPTION:\r
2127 Exception.ExceptionNum = (UINT8) Vector;\r
2128 Exception.ExceptionData = (UINT32) CpuContext->ExceptionData;\r
2129 Status = SendDataResponsePacket ((UINT8 *) &Exception, (UINT16) sizeof (DEBUG_DATA_RESPONSE_GET_EXCEPTION), DebugHeader);\r
2130 break;\r
2131\r
2132 case DEBUG_COMMAND_SET_VIEWPOINT:\r
2133 SetViewPoint = (DEBUG_DATA_SET_VIEWPOINT *) (DebugHeader + 1);\r
2134 if (MultiProcessorDebugSupport()) {\r
2135 if (IsCpuStopped (SetViewPoint->ViewPoint)) {\r
2136 SetDebugViewPoint (SetViewPoint->ViewPoint);\r
2137 SendAckPacket (DEBUG_COMMAND_OK);\r
2138 } else {\r
2139 //\r
2140 // If CPU is not halted\r
2141 //\r
2142 SendAckPacket (DEBUG_COMMAND_NOT_SUPPORTED);\r
2143 }\r
2144 } else if (SetViewPoint->ViewPoint == 0) {\r
2145 SendAckPacket (DEBUG_COMMAND_OK);\r
2146\r
2147 } else {\r
2148 SendAckPacket (DEBUG_COMMAND_NOT_SUPPORTED);\r
2149 }\r
2150\r
2151 break;\r
2152\r
2153 case DEBUG_COMMAND_GET_VIEWPOINT:\r
2154 Data32 = mDebugMpContext.ViewPointIndex;\r
2155 SendDataResponsePacket((UINT8 *) &Data32, (UINT16) sizeof (UINT32), DebugHeader);\r
2156 break;\r
2157\r
2158 case DEBUG_COMMAND_MEMORY_READY:\r
2159 Data8 = (UINT8) GetDebugFlag (DEBUG_AGENT_FLAG_MEMORY_READY);\r
2160 SendDataResponsePacket (&Data8, (UINT16) sizeof (UINT8), DebugHeader);\r
2161 break;\r
2162\r
2163 case DEBUG_COMMAND_DETACH:\r
2164 SetHostAttached (FALSE);\r
2165 SendAckPacket (DEBUG_COMMAND_OK);\r
2166 break;\r
2167\r
2168 case DEBUG_COMMAND_CPUID:\r
2169 Cpuid = (DEBUG_DATA_CPUID *) (DebugHeader + 1);\r
2170 AsmCpuidEx (\r
2171 Cpuid->Eax, Cpuid->Ecx,\r
2172 &CpuidResponse.Eax, &CpuidResponse.Ebx,\r
2173 &CpuidResponse.Ecx, &CpuidResponse.Edx\r
2174 );\r
2175 SendDataResponsePacket ((UINT8 *) &CpuidResponse, (UINT16) sizeof (CpuidResponse), DebugHeader);\r
2176 break;\r
2177\r
2178 case DEBUG_COMMAND_SEARCH_SIGNATURE:\r
2179 SearchSignature = (DEBUG_DATA_SEARCH_SIGNATURE *) (DebugHeader + 1);\r
2180 if ((SearchSignature->Alignment != 0) &&\r
2181 (SearchSignature->Alignment == GetPowerOfTwo32 (SearchSignature->Alignment))\r
2182 ) {\r
2183 if (SearchSignature->Positive) {\r
2184 for (\r
2185 Data64 = ALIGN_VALUE ((UINTN) SearchSignature->Start, SearchSignature->Alignment);\r
2186 Data64 <= SearchSignature->Start + SearchSignature->Count - SearchSignature->DataLength;\r
2187 Data64 += SearchSignature->Alignment\r
2188 ) {\r
2189 if (CompareMem ((VOID *) (UINTN) Data64, &SearchSignature->Data, SearchSignature->DataLength) == 0) {\r
2190 break;\r
2191 }\r
2192 }\r
2193 if (Data64 > SearchSignature->Start + SearchSignature->Count - SearchSignature->DataLength) {\r
2194 Data64 = (UINT64) -1;\r
2195 }\r
2196 } else {\r
2197 for (\r
2198 Data64 = ALIGN_VALUE ((UINTN) SearchSignature->Start - SearchSignature->Alignment, SearchSignature->Alignment);\r
2199 Data64 >= SearchSignature->Start - SearchSignature->Count;\r
2200 Data64 -= SearchSignature->Alignment\r
2201 ) {\r
2202 if (CompareMem ((VOID *) (UINTN) Data64, &SearchSignature->Data, SearchSignature->DataLength) == 0) {\r
2203 break;\r
2204 }\r
2205 }\r
2206 if (Data64 < SearchSignature->Start - SearchSignature->Count) {\r
2207 Data64 = (UINT64) -1;\r
2208 }\r
2209 }\r
2210 SendDataResponsePacket ((UINT8 *) &Data64, (UINT16) sizeof (Data64), DebugHeader);\r
2211 } else {\r
2212 Status = RETURN_UNSUPPORTED;\r
2213 }\r
2214 break;\r
2215\r
2216 default:\r
2217 SendAckPacket (DEBUG_COMMAND_NOT_SUPPORTED);\r
2218 break;\r
2219 }\r
2220\r
2221 if (Status == RETURN_UNSUPPORTED) {\r
2222 SendAckPacket (DEBUG_COMMAND_NOT_SUPPORTED);\r
2223 } else if (Status != RETURN_SUCCESS) {\r
2224 SendAckPacket (DEBUG_COMMAND_ABORT);\r
2225 }\r
2226\r
2227 ReleaseMpSpinLock (&mDebugMpContext.DebugPortSpinLock);\r
2228 CpuPause ();\r
2229 }\r
2230}\r
2231\r
2232/**\r
2233 C function called in interrupt handler.\r
2234\r
2235 @param[in] Vector Vector value of exception or interrutp.\r
2236 @param[in] CpuContext Pointer to save CPU context.\r
2237\r
2238**/\r
2239VOID\r
2240EFIAPI\r
2241InterruptProcess (\r
2242 IN UINT32 Vector,\r
2243 IN DEBUG_CPU_CONTEXT *CpuContext\r
2244 )\r
2245{\r
2246 UINT8 InputCharacter;\r
2247 UINT8 BreakCause;\r
2248 UINTN SavedEip;\r
2249 BOOLEAN BreakReceived;\r
2250 UINT32 ProcessorIndex;\r
2251 UINT32 CurrentDebugTimerInitCount;\r
2252 DEBUG_PORT_HANDLE Handle;\r
2253 UINT8 Data8;\r
2254 UINT8 *Al;\r
2255 UINT32 IssuedViewPoint;\r
2256 DEBUG_AGENT_EXCEPTION_BUFFER *ExceptionBuffer;\r
2257\r
2258 InputCharacter = 0;\r
2259 ProcessorIndex = 0;\r
2260 IssuedViewPoint = 0;\r
2261 BreakReceived = FALSE;\r
2262\r
2263 if (mSkipBreakpoint) {\r
2264 //\r
2265 // If Skip Breakpoint flag is set, means communication is disturbed by hardware SMI, we need to ignore the break points in SMM\r
2266 //\r
2267 if ((Vector == DEBUG_INT1_VECTOR) || (Vector == DEBUG_INT3_VECTOR)) {\r
2268 DebugPortWriteBuffer (GetDebugPortHandle(), (UINT8 *) mWarningMsgIngoreBreakpoint, AsciiStrLen (mWarningMsgIngoreBreakpoint));\r
2269 return;\r
2270 }\r
2271 }\r
2272\r
2273 if (MultiProcessorDebugSupport()) {\r
2274 ProcessorIndex = GetProcessorIndex ();\r
2275 //\r
2276 // If this processor has alreay halted before, need to check it later\r
2277 //\r
2278 if (IsCpuStopped (ProcessorIndex)) {\r
2279 IssuedViewPoint = ProcessorIndex;\r
2280 }\r
2281 }\r
2282\r
2283 if (IssuedViewPoint == ProcessorIndex && GetDebugFlag (DEBUG_AGENT_FLAG_STEPPING) != 1) {\r
2284 //\r
2285 // Check if this exception is issued by Debug Agent itself\r
2286 // If yes, fill the debug agent exception buffer and LongJump() back to\r
2287 // the saved CPU content in CommandCommunication()\r
2288 //\r
2289 if (GetDebugFlag (DEBUG_AGENT_FLAG_AGENT_IN_PROGRESS) == 1) {\r
2290 DebugAgentMsgPrint (DEBUG_AGENT_ERROR, "Debug agent meet one Exception, ExceptionNum is %d, EIP = 0x%x.\n", Vector, (UINTN)CpuContext->Eip);\r
2291 ExceptionBuffer = (DEBUG_AGENT_EXCEPTION_BUFFER *) (UINTN) GetMailboxPointer()->ExceptionBufferPointer;\r
2292 ExceptionBuffer->ExceptionContent.ExceptionNum = (UINT8) Vector;\r
2293 ExceptionBuffer->ExceptionContent.ExceptionData = (UINT32) CpuContext->ExceptionData;\r
2294 LongJump ((BASE_LIBRARY_JUMP_BUFFER *)(UINTN)(ExceptionBuffer), 1);\r
2295 }\r
2296 }\r
2297\r
2298 if (MultiProcessorDebugSupport()) {\r
2299 //\r
2300 // If RUN commmand is executing, wait for it done.\r
2301 //\r
2302 while (mDebugMpContext.RunCommandSet) {\r
2303 CpuPause ();\r
2304 }\r
2305 }\r
2306\r
2307 Handle = GetDebugPortHandle();\r
2308 BreakCause = GetBreakCause (Vector, CpuContext);\r
2309 switch (Vector) {\r
2310 case DEBUG_INT1_VECTOR:\r
2311 case DEBUG_INT3_VECTOR:\r
2312 switch (BreakCause) {\r
2313 case DEBUG_DATA_BREAK_CAUSE_SYSTEM_RESET:\r
2314 if (AttachHost (BreakCause, READ_PACKET_TIMEOUT, &BreakReceived) != RETURN_SUCCESS) {\r
2315 //\r
2316 // Try to connect HOST, return if fails\r
2317 //\r
2318 break;\r
2319 }\r
2320 CommandCommunication (Vector, CpuContext, BreakReceived);\r
2321 break;\r
2322\r
2323 case DEBUG_DATA_BREAK_CAUSE_STEPPING:\r
2324 //\r
2325 // Stepping is finished, send Ack package.\r
2326 //\r
2327 if (MultiProcessorDebugSupport()) {\r
2328 mDebugMpContext.BreakAtCpuIndex = ProcessorIndex;\r
2329 }\r
2330 SendAckPacket (DEBUG_COMMAND_OK);\r
2331 CommandCommunication (Vector, CpuContext, BreakReceived);\r
2332 break;\r
2333\r
2334 case DEBUG_DATA_BREAK_CAUSE_MEMORY_READY:\r
2335 //\r
2336 // Memory is ready\r
2337 //\r
2338 SendCommandAndWaitForAckOK (DEBUG_COMMAND_MEMORY_READY, READ_PACKET_TIMEOUT, &BreakReceived, NULL);\r
2339 CommandCommunication (Vector, CpuContext, BreakReceived);\r
2340 break;\r
2341\r
2342 case DEBUG_DATA_BREAK_CAUSE_IMAGE_LOAD:\r
2343 case DEBUG_DATA_BREAK_CAUSE_IMAGE_UNLOAD:\r
2344 //\r
2345 // Set AL to DEBUG_AGENT_IMAGE_CONTINUE\r
2346 //\r
2347 Al = ArchReadRegisterBuffer (CpuContext, SOFT_DEBUGGER_REGISTER_AX, &Data8);\r
2348 *Al = DEBUG_AGENT_IMAGE_CONTINUE;\r
2349\r
2350 if (!IsHostAttached ()) {\r
2351 //\r
2352 // If HOST is not connected for image load/unload, return\r
2353 //\r
2354 break;\r
2355 }\r
2356 //\r
2357 // Continue to run the following common code\r
2358 //\r
2359\r
2360 case DEBUG_DATA_BREAK_CAUSE_HW_BREAKPOINT:\r
2361 case DEBUG_DATA_BREAK_CAUSE_SW_BREAKPOINT:\r
2362 default:\r
2363 //\r
2364 // Send Break packet to HOST\r
2365 //\r
2366 AcquireMpSpinLock (&mDebugMpContext.DebugPortSpinLock);\r
2367 //\r
2368 // Only the first breaking processor could send BREAK_POINT to HOST\r
2369 //\r
2370 if (IsFirstBreakProcessor (ProcessorIndex)) {\r
2371 SendBreakPacketToHost (BreakCause, ProcessorIndex, &BreakReceived);\r
2372 }\r
2373 ReleaseMpSpinLock (&mDebugMpContext.DebugPortSpinLock);\r
2374\r
2375 if (Vector == DEBUG_INT3_VECTOR) {\r
2376 //\r
2377 // go back address located "0xCC"\r
2378 //\r
2379 CpuContext->Eip--;\r
2380 SavedEip = CpuContext->Eip;\r
2381 CommandCommunication (Vector, CpuContext, BreakReceived);\r
2382 if ((SavedEip == CpuContext->Eip) &&\r
2383 (*(UINT8 *) (UINTN) CpuContext->Eip == DEBUG_SW_BREAKPOINT_SYMBOL)) {\r
2384 //\r
2385 // If this is not a software breakpoint set by HOST,\r
2386 // restore EIP\r
2387 //\r
2388 CpuContext->Eip++;\r
2389 }\r
2390 } else {\r
2391 CommandCommunication (Vector, CpuContext, BreakReceived);\r
2392 }\r
2393 break;\r
2394 }\r
2395\r
2396 break;\r
2397\r
2398 case DEBUG_TIMER_VECTOR:\r
2399\r
2400 AcquireMpSpinLock (&mDebugMpContext.DebugPortSpinLock);\r
2401\r
2402 if (MultiProcessorDebugSupport()) {\r
2403 if (IsBsp (ProcessorIndex)) {\r
2404 //\r
2405 // If current processor is BSP, check Apic timer's init count if changed,\r
2406 // it may be re-written when switching BSP.\r
2407 // If it changed, re-initialize debug timer\r
2408 //\r
2409 CurrentDebugTimerInitCount = GetApicTimerInitCount ();\r
2410 if (mDebugMpContext.DebugTimerInitCount != CurrentDebugTimerInitCount) {\r
2411 InitializeDebugTimer ();\r
2412 }\r
2413 }\r
2414\r
2415 if (!IsBsp (ProcessorIndex) || mDebugMpContext.IpiSentByAp) {\r
2416 ReleaseMpSpinLock (&mDebugMpContext.DebugPortSpinLock);\r
2417 //\r
2418 // If current processor is not BSP or this is one IPI sent by AP\r
2419 //\r
2420 if (mDebugMpContext.BreakAtCpuIndex != (UINT32) (-1)) {\r
2421 CommandCommunication (Vector, CpuContext, FALSE);\r
2422 }\r
2423\r
2424 //\r
2425 // Clear EOI before exiting interrupt process routine.\r
2426 //\r
2427 SendApicEoi ();\r
2428 break;\r
2429 }\r
2430 }\r
2431\r
2432 //\r
2433 // Only BSP could run here\r
2434 //\r
2435 while (TRUE) {\r
2436 //\r
2437 // If there is data in debug port, will check whether it is break(attach/break-in) symbol,\r
2438 // If yes, go into communication mode with HOST.\r
2439 // If no, exit interrupt process.\r
2440 //\r
2441 if (DebugReadBreakSymbol (Handle, &InputCharacter) == EFI_NOT_FOUND) {\r
2442 break;\r
2443 }\r
2444\r
2445 if ((!IsHostAttached () && (InputCharacter == DEBUG_STARTING_SYMBOL_ATTACH)) ||\r
2446 (IsHostAttached () && (InputCharacter == DEBUG_COMMAND_HALT)) ||\r
2447 (IsHostAttached () && (InputCharacter == DEBUG_COMMAND_GO))\r
2448 ) {\r
2449 DebugAgentMsgPrint (DEBUG_AGENT_VERBOSE, "Received data [%02x]\n", InputCharacter);\r
2450 //\r
2451 // Ack OK for break-in symbol\r
2452 //\r
2453 SendAckPacket (DEBUG_COMMAND_OK);\r
2454\r
2455 //\r
2456 // If receive GO command in Debug Timer, means HOST may lost ACK packet before.\r
2457 //\r
2458 if (InputCharacter == DEBUG_COMMAND_GO) {\r
2459 break;\r
2460 }\r
2461\r
2462 if (!IsHostAttached ()) {\r
2463 //\r
2464 // Try to attach HOST, if no ack received after 200ms, return\r
2465 //\r
2466 if (AttachHost (BreakCause, READ_PACKET_TIMEOUT, &BreakReceived) != RETURN_SUCCESS) {\r
2467 break;\r
2468 }\r
2469 }\r
2470\r
2471 if (MultiProcessorDebugSupport()) {\r
2472 if(FindNextPendingBreakCpu () != -1) {\r
2473 SetCpuBreakFlagByIndex (ProcessorIndex, TRUE);\r
2474 } else {\r
2475 HaltOtherProcessors (ProcessorIndex);\r
2476 }\r
2477 }\r
2478 ReleaseMpSpinLock (&mDebugMpContext.DebugPortSpinLock);\r
2479 CommandCommunication (Vector, CpuContext, BreakReceived);\r
2480 AcquireMpSpinLock (&mDebugMpContext.DebugPortSpinLock);\r
2481 break;\r
2482 }\r
2483 }\r
2484\r
2485 //\r
2486 // Clear EOI before exiting interrupt process routine.\r
2487 //\r
2488 SendApicEoi ();\r
2489\r
2490 ReleaseMpSpinLock (&mDebugMpContext.DebugPortSpinLock);\r
2491\r
2492 break;\r
2493\r
2494 default:\r
2495 if (Vector <= DEBUG_EXCEPT_SIMD) {\r
2496 if (BreakCause == DEBUG_DATA_BREAK_CAUSE_STEPPING) {\r
2497 //\r
2498 // Stepping is finished, send Ack package.\r
2499 //\r
2500 if (MultiProcessorDebugSupport()) {\r
2501 mDebugMpContext.BreakAtCpuIndex = ProcessorIndex;\r
2502 }\r
2503 SendAckPacket (DEBUG_COMMAND_OK);\r
2504 } else {\r
2505 //\r
2506 // Exception occurs, send Break packet to HOST\r
2507 //\r
2508 AcquireMpSpinLock (&mDebugMpContext.DebugPortSpinLock);\r
2509 //\r
2510 // Only the first breaking processor could send BREAK_POINT to HOST\r
2511 //\r
2512 if (IsFirstBreakProcessor (ProcessorIndex)) {\r
2513 SendBreakPacketToHost (BreakCause, ProcessorIndex, &BreakReceived);\r
2514 }\r
2515 ReleaseMpSpinLock (&mDebugMpContext.DebugPortSpinLock);\r
2516 }\r
2517\r
2518 CommandCommunication (Vector, CpuContext, BreakReceived);\r
2519 }\r
2520 break;\r
2521 }\r
2522\r
2523 if (MultiProcessorDebugSupport()) {\r
2524 //\r
2525 // Clear flag and wait for all processors run here\r
2526 //\r
2527 SetIpiSentByApFlag (FALSE);\r
2528 while (mDebugMpContext.RunCommandSet) {\r
2529 CpuPause ();\r
2530 }\r
2531\r
2532 //\r
2533 // Only current (view) processor could clean up AgentInProgress flag.\r
2534 //\r
2535 if (mDebugMpContext.ViewPointIndex == ProcessorIndex) {\r
2536 IssuedViewPoint = mDebugMpContext.ViewPointIndex;\r
2537 }\r
2538 }\r
2539\r
2540 if (IssuedViewPoint == ProcessorIndex && GetDebugFlag (DEBUG_AGENT_FLAG_STEPPING) != 1) {\r
2541 //\r
2542 // If the command is not stepping, clean up AgentInProgress flag\r
2543 //\r
2544 SetDebugFlag (DEBUG_AGENT_FLAG_AGENT_IN_PROGRESS, 0);\r
2545 }\r
2546\r
2547 return;\r
2548}\r
2549\r