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