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