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