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