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