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