]> git.proxmox.com Git - mirror_edk2.git/blame_incremental - SourceLevelDebugPkg/Library/DebugAgent/DebugAgentCommon/DebugAgent.c
1. Separated DxeSmmCpuExceptionHandlerLib.inf into 2 instance DxeCpuExceptionHandlerL...
[mirror_edk2.git] / SourceLevelDebugPkg / Library / DebugAgent / DebugAgentCommon / DebugAgent.c
... / ...
CommitLineData
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
7 Copyright (c) 2010 - 2013, Intel Corporation. All rights reserved.<BR>\r
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
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.1) ...\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
26\r
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
320\r
321/**\r
322 Send a debug message packet to the debug port.\r
323\r
324 @param[in] Buffer The debug message.\r
325 @param[in] Length The length of debug message.\r
326\r
327**/\r
328VOID\r
329SendDebugMsgPacket (\r
330 IN CHAR8 *Buffer,\r
331 IN UINTN Length \r
332 )\r
333{\r
334 DEBUG_PACKET_HEADER DebugHeader;\r
335 DEBUG_PORT_HANDLE Handle;\r
336 \r
337 Handle = GetDebugPortHandle();\r
338\r
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
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
348\r
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
373 CHAR8 Buffer[DEBUG_DATA_MAXIMUM_REAL_DATA];\r
374 VA_LIST Marker;\r
375\r
376 //\r
377 // Check driver debug mask value and global mask\r
378 //\r
379 if ((ErrorLevel & GetDebugFlag (DEBUG_AGENT_FLAG_PRINT_ERROR_LEVEL)) == 0) {\r
380 return;\r
381 }\r
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
391}\r
392\r
393/**\r
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
406\r
407**/\r
408VOID\r
409EFIAPI\r
410DebugAgentDataMsgPrint (\r
411 IN UINT8 ErrorLevel,\r
412 IN BOOLEAN IsSend,\r
413 IN UINT8 *Data,\r
414 IN UINT8 Length \r
415 )\r
416{\r
417 CHAR8 Buffer[DEBUG_DATA_MAXIMUM_REAL_DATA];\r
418 CHAR8 *DestBuffer;\r
419 UINTN Index;\r
420\r
421 //\r
422 // Check driver debug mask value and global mask\r
423 //\r
424 if ((ErrorLevel & GetDebugFlag (DEBUG_AGENT_FLAG_PRINT_ERROR_LEVEL)) == 0) {\r
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
434\r
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
448 //\r
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
456}\r
457\r
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
498\r
499/**\r
500 Check if HOST is attached based on Mailbox.\r
501\r
502 @retval TRUE HOST is attached.\r
503 @retval FALSE HOST is not attached.\r
504\r
505**/\r
506BOOLEAN\r
507IsHostAttached (\r
508 VOID\r
509 )\r
510{\r
511 return (BOOLEAN) (GetDebugFlag (DEBUG_AGENT_FLAG_HOST_ATTACHED) == 1);\r
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
519**/\r
520VOID\r
521SetHostAttached (\r
522 IN BOOLEAN Attached\r
523 )\r
524{\r
525 DebugAgentMsgPrint (DEBUG_AGENT_INFO, "Attach status is %d\n", Attached);\r
526 SetDebugFlag (DEBUG_AGENT_FLAG_HOST_ATTACHED, (UINT32)Attached);\r
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
544\r
545 Status = RETURN_SUCCESS;\r
546 switch (DebugSetting->Key) {\r
547 case DEBUG_AGENT_SETTING_SMM_ENTRY_BREAK:\r
548 SetDebugFlag (DEBUG_AGENT_FLAG_BREAK_ON_NEXT_SMI, DebugSetting->Value);\r
549 break;\r
550 case DEBUG_AGENT_SETTING_PRINT_ERROR_LEVEL:\r
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
555 break;\r
556 default:\r
557 Status = RETURN_UNSUPPORTED;\r
558 }\r
559 return Status;\r
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
630 Dr7Value &= ~(0xf << (16 + RegisterIndex * 4));\r
631 Dr7Value |= (UINTN) ((SetHwBreakpoint->Type.Length << 2) | SetHwBreakpoint->Type.Access) << (16 + RegisterIndex * 4);\r
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
671\r
672/**\r
673 Return the offset of FP / MMX / XMM registers in the FPU saved state by register index.\r
674\r
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
782 @param[in] SequenceNo Sequence number.\r
783\r
784**/\r
785VOID\r
786SendPacketWithoutData (\r
787 IN UINT8 CommandType,\r
788 IN UINT8 SequenceNo\r
789 )\r
790{\r
791 DEBUG_PACKET_HEADER DebugHeader;\r
792 DEBUG_PORT_HANDLE Handle;\r
793\r
794 Handle = GetDebugPortHandle();\r
795\r
796 DebugHeader.StartSymbol = DEBUG_STARTING_SYMBOL_NORMAL;\r
797 DebugHeader.Command = CommandType;\r
798 DebugHeader.Length = sizeof (DEBUG_PACKET_HEADER);\r
799 DebugHeader.SequenceNo = SequenceNo;\r
800 DebugHeader.Crc = 0;\r
801 DebugHeader.Crc = CalculateCrc16 ((UINT8 *)&DebugHeader, sizeof (DEBUG_PACKET_HEADER), 0);\r
802\r
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
818 UINT8 SequenceNo;\r
819 DEBUG_AGENT_MAILBOX *Mailbox;\r
820\r
821 if (AckCommand != DEBUG_COMMAND_OK) {\r
822 //\r
823 // This is not ACK OK packet\r
824 //\r
825 DebugAgentMsgPrint (DEBUG_AGENT_ERROR, "Send ACK(%d)\n", AckCommand);\r
826 }\r
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
832}\r
833\r
834/**\r
835 Receive valid packet from HOST.\r
836\r
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
847\r
848 @retval RETURN_SUCCESS A valid package was reveived in InputPacket.\r
849 @retval RETURN_TIMEOUT Timeout occurs.\r
850\r
851**/\r
852RETURN_STATUS\r
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
859 )\r
860{\r
861 DEBUG_PACKET_HEADER *DebugHeader;\r
862 UINTN Received;\r
863 DEBUG_PORT_HANDLE Handle;\r
864 UINT16 Crc;\r
865 UINTN TimeoutForStartSymbol;\r
866\r
867 Handle = GetDebugPortHandle();\r
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
875 while (TRUE) {\r
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
882 return RETURN_TIMEOUT;\r
883 }\r
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
888 }\r
889\r
890 //\r
891 // Read Package header till field Length\r
892 //\r
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
901 return RETURN_TIMEOUT;\r
902 }\r
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
935 }\r
936\r
937 DebugAgentDataMsgPrint (DEBUG_AGENT_VERBOSE, FALSE, (UINT8 *) DebugHeader, DebugHeader->Length);\r
938\r
939 return RETURN_SUCCESS;\r
940}\r
941\r
942/**\r
943 Receive acknowledge packet OK from HOST in specified time.\r
944\r
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
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
961SendCommandAndWaitForAckOK (\r
962 IN UINT8 Command,\r
963 IN UINTN Timeout,\r
964 OUT BOOLEAN *BreakReceived, OPTIONAL\r
965 OUT BOOLEAN *IncompatibilityFlag OPTIONAL\r
966 )\r
967{\r
968 RETURN_STATUS Status;\r
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
989 continue;\r
990 }\r
991 ASSERT_EFI_ERROR (Status);\r
992 //\r
993 // Status == RETURN_SUCCESS\r
994 //\r
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
1001 }\r
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
1010 }\r
1011 }\r
1012\r
1013 ASSERT (Command == DEBUG_COMMAND_INIT_BREAK);\r
1014 return Status;\r
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
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
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
1097 if (GetDebugFlag (DEBUG_AGENT_FLAG_STEPPING) == 1) {\r
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
1105 }\r
1106 break;\r
1107 }\r
1108\r
1109 return Cause;\r
1110}\r
1111\r
1112/**\r
1113 Copy memory from source to destination with specified width.\r
1114\r
1115 @param[out] Dest A pointer to the destination buffer of the memory copy.\r
1116 @param[in] Src A pointer to the source buffer of the memory copy.\r
1117 @param[in] Count The number of data with specified width to copy from source to destination.\r
1118 @param[in] Width Data width in byte.\r
1119\r
1120**/\r
1121VOID\r
1122CopyMemByWidth (\r
1123 OUT UINT8 *Dest,\r
1124 IN UINT8 *Src,\r
1125 IN UINT16 Count,\r
1126 IN UINT8 Width\r
1127 )\r
1128{\r
1129 UINT8 *Destination;\r
1130 UINT8 *Source;\r
1131 INT8 Step;\r
1132\r
1133 if (Src > Dest) {\r
1134 Destination = Dest;\r
1135 Source = Src;\r
1136 Step = Width;\r
1137 } else {\r
1138 //\r
1139 // Copy memory from tail to avoid memory overlap\r
1140 //\r
1141 Destination = Dest + (Count - 1) * Width;\r
1142 Source = Src + (Count - 1) * Width;\r
1143 Step = -Width;\r
1144 }\r
1145\r
1146 while (Count-- != 0) {\r
1147 switch (Width) {\r
1148 case 1:\r
1149 *(UINT8 *) Destination = MmioRead8 ((UINTN) Source);\r
1150 break;\r
1151 case 2:\r
1152 *(UINT16 *) Destination = MmioRead16 ((UINTN) Source);\r
1153 break;\r
1154 case 4:\r
1155 *(UINT32 *) Destination = MmioRead32 ((UINTN) Source);\r
1156 break;\r
1157 case 8:\r
1158 *(UINT64 *) Destination = MmioRead64 ((UINTN) Source);\r
1159 break;\r
1160 default:\r
1161 ASSERT (FALSE);\r
1162 }\r
1163 Source += Step;\r
1164 Destination += Step;\r
1165 }\r
1166}\r
1167\r
1168/**\r
1169 Read memory with speicifed width and send packet with response data to HOST.\r
1170\r
1171 @param[in] Data Pointer to response data buffer.\r
1172 @param[in] Count The number of data with specified Width.\r
1173 @param[in] Width Data width in byte.\r
1174\r
1175 @retval RETURN_SUCCESS Response data was sent successfully.\r
1176\r
1177**/\r
1178RETURN_STATUS\r
1179ReadMemoryAndSendResponsePacket (\r
1180 IN UINT8 *Data,\r
1181 IN UINT16 Count,\r
1182 IN UINT8 Width\r
1183 )\r
1184{\r
1185 RETURN_STATUS Status;\r
1186 DEBUG_PACKET_HEADER *DebugHeader;\r
1187 BOOLEAN LastPacket;\r
1188 DEBUG_PACKET_HEADER *AckDebugHeader;\r
1189 UINT8 DebugPacket[DEBUG_DATA_UPPER_LIMIT + sizeof (UINT64) - 1];\r
1190 UINT8 InputPacketBuffer[DEBUG_DATA_UPPER_LIMIT];\r
1191 DEBUG_PORT_HANDLE Handle;\r
1192 UINT8 SequenceNo;\r
1193 UINTN RemainingDataSize;\r
1194 UINTN CurrentDataSize;\r
1195\r
1196 Handle = GetDebugPortHandle();\r
1197\r
1198 //\r
1199 // Data is appended end of Debug Packet header, make sure data address\r
1200 // in Debug Packet 8-byte alignment always\r
1201 //\r
1202 DebugHeader = (DEBUG_PACKET_HEADER *) (ALIGN_VALUE ((UINTN)&DebugPacket + sizeof (DEBUG_PACKET_HEADER), sizeof (UINT64))\r
1203 - sizeof (DEBUG_PACKET_HEADER));\r
1204 DebugHeader->StartSymbol = DEBUG_STARTING_SYMBOL_NORMAL;\r
1205\r
1206 RemainingDataSize = Count * Width;\r
1207 while (TRUE) {\r
1208 SequenceNo = GetMailboxPointer()->HostSequenceNo;\r
1209 if (RemainingDataSize <= DEBUG_DATA_MAXIMUM_REAL_DATA) {\r
1210 //\r
1211 // If the remaining data is less one real packet size, this is the last data packet\r
1212 //\r
1213 CurrentDataSize = RemainingDataSize;\r
1214 LastPacket = TRUE;\r
1215 DebugHeader->Command = DEBUG_COMMAND_OK;\r
1216 } else {\r
1217 //\r
1218 // Data is too larger to be sent in one packet, calculate the actual data size could\r
1219 // be sent in one Maximum data packet\r
1220 //\r
1221 CurrentDataSize = (DEBUG_DATA_MAXIMUM_REAL_DATA / Width) * Width;\r
1222 LastPacket = FALSE;\r
1223 DebugHeader->Command = DEBUG_COMMAND_IN_PROGRESS;\r
1224 }\r
1225 //\r
1226 // Construct the rest Debug header\r
1227 //\r
1228 DebugHeader->Length = (UINT8)(CurrentDataSize + sizeof (DEBUG_PACKET_HEADER));\r
1229 DebugHeader->SequenceNo = SequenceNo;\r
1230 DebugHeader->Crc = 0;\r
1231 CopyMemByWidth ((UINT8 *)(DebugHeader + 1), Data, (UINT16) CurrentDataSize / Width, Width);\r
1232 //\r
1233 // Calculate and fill the checksum, DebugHeader->Crc should be 0 before invoking CalculateCrc16 ()\r
1234 //\r
1235 DebugHeader->Crc = CalculateCrc16 ((UINT8 *) DebugHeader, DebugHeader->Length, 0);\r
1236\r
1237 DebugAgentDataMsgPrint (DEBUG_AGENT_VERBOSE, TRUE, (UINT8 *) DebugHeader, DebugHeader->Length);\r
1238 \r
1239 DebugPortWriteBuffer (Handle, (UINT8 *) DebugHeader, DebugHeader->Length);\r
1240\r
1241 while (TRUE) {\r
1242 Status = ReceivePacket (InputPacketBuffer, NULL, NULL, READ_PACKET_TIMEOUT, FALSE);\r
1243 if (Status == RETURN_TIMEOUT) {\r
1244 DebugAgentMsgPrint (DEBUG_AGENT_WARNING, "TARGET: Timeout in SendDataResponsePacket()\n");\r
1245 break;\r
1246 }\r
1247 AckDebugHeader = (DEBUG_PACKET_HEADER *) InputPacketBuffer;\r
1248 SequenceNo = AckDebugHeader->SequenceNo;\r
1249 if (AckDebugHeader->Command == DEBUG_COMMAND_OK &&\r
1250 SequenceNo == DebugHeader->SequenceNo &&\r
1251 LastPacket) {\r
1252 //\r
1253 // If this is the last packet, return RETURN_SUCCESS.\r
1254 //\r
1255 return RETURN_SUCCESS;\r
1256 }\r
1257 if ((SequenceNo == (UINT8) (DebugHeader->SequenceNo + 1)) && (AckDebugHeader->Command == DEBUG_COMMAND_CONTINUE)) {\r
1258 //\r
1259 // Calculate the rest data size\r
1260 //\r
1261 Data += CurrentDataSize;\r
1262 RemainingDataSize -= CurrentDataSize;\r
1263 UpdateMailboxContent (GetMailboxPointer(), DEBUG_MAILBOX_HOST_SEQUENCE_NO_INDEX, (UINT8) SequenceNo);\r
1264 break;\r
1265 }\r
1266 if (SequenceNo >= DebugHeader->SequenceNo) {\r
1267 DebugAgentMsgPrint (DEBUG_AGENT_WARNING, "TARGET: Received one old or new command(SequenceNo is %x, last SequenceNo is %x)\n", SequenceNo, DebugHeader->SequenceNo);\r
1268 break;\r
1269 }\r
1270 }\r
1271 }\r
1272}\r
1273\r
1274/**\r
1275 Send packet with response data to HOST.\r
1276\r
1277 @param[in] Data Pointer to response data buffer.\r
1278 @param[in] DataSize Size of response data in byte.\r
1279\r
1280 @retval RETURN_SUCCESS Response data was sent successfully.\r
1281\r
1282**/\r
1283RETURN_STATUS\r
1284SendDataResponsePacket (\r
1285 IN UINT8 *Data,\r
1286 IN UINT16 DataSize\r
1287 )\r
1288{\r
1289 return ReadMemoryAndSendResponsePacket (Data, DataSize, 1);\r
1290}\r
1291\r
1292/**\r
1293 Send break cause packet to HOST.\r
1294\r
1295 @param[in] Vector Vector value of exception or interrutp.\r
1296 @param[in] CpuContext Pointer to save CPU context.\r
1297\r
1298 @retval RETURN_SUCCESS Response data was sent successfully.\r
1299 @retval RETURN_DEVICE_ERROR Cannot receive DEBUG_COMMAND_OK from HOST.\r
1300\r
1301**/\r
1302RETURN_STATUS\r
1303SendBreakCausePacket (\r
1304 IN UINTN Vector,\r
1305 IN DEBUG_CPU_CONTEXT *CpuContext\r
1306 )\r
1307{\r
1308 DEBUG_DATA_RESPONSE_BREAK_CAUSE DebugDataBreakCause;\r
1309\r
1310 DebugDataBreakCause.StopAddress = CpuContext->Eip;\r
1311 DebugDataBreakCause.Cause = GetBreakCause (Vector, CpuContext);\r
1312\r
1313 return SendDataResponsePacket ((UINT8 *) &DebugDataBreakCause, (UINT16) sizeof (DEBUG_DATA_RESPONSE_BREAK_CAUSE));\r
1314}\r
1315\r
1316/**\r
1317 Try to attach the HOST.\r
1318 \r
1319 Send init break packet to HOST:\r
1320 If no acknowlege received in specified Timeout, return RETURN_TIMEOUT. \r
1321 If received acknowlege, check the revision of HOST. \r
1322 Set Attach Flag if attach successfully. \r
1323 \r
1324 @param[in] BreakCause Break cause of this break event.\r
1325 @param[in] Timeout Time out value to wait for acknowlege from HOST.\r
1326 The unit is microsecond.\r
1327 @param[out] BreakReceived If BreakReceived is not NULL,\r
1328 TRUE is retured if break-in symbol received.\r
1329 FALSE is retured if break-in symbol not received.\r
1330**/\r
1331RETURN_STATUS\r
1332AttachHost (\r
1333 IN UINT8 BreakCause,\r
1334 IN UINTN Timeout,\r
1335 OUT BOOLEAN *BreakReceived\r
1336 )\r
1337{\r
1338 RETURN_STATUS Status;\r
1339 DEBUG_PORT_HANDLE Handle;\r
1340 BOOLEAN IncompatibilityFlag;\r
1341\r
1342 IncompatibilityFlag = FALSE;\r
1343 Handle = GetDebugPortHandle();\r
1344 \r
1345 //\r
1346 // Send init break and wait ack in Timeout\r
1347 //\r
1348 DebugPortWriteBuffer (Handle, (UINT8 *) mErrorMsgSendInitPacket, AsciiStrLen (mErrorMsgSendInitPacket));\r
1349 if (BreakCause == DEBUG_DATA_BREAK_CAUSE_SYSTEM_RESET) {\r
1350 Status = SendCommandAndWaitForAckOK (DEBUG_COMMAND_INIT_BREAK, Timeout, BreakReceived, &IncompatibilityFlag);\r
1351 } else {\r
1352 Status = SendCommandAndWaitForAckOK (DEBUG_COMMAND_ATTACH_BREAK, Timeout, BreakReceived, &IncompatibilityFlag);\r
1353 }\r
1354 if (IncompatibilityFlag) {\r
1355 //\r
1356 // If the incompatible Debug Packet received, the HOST should be running transfer protocol before DEBUG_AGENT_REVISION.\r
1357 // It could be UDK Debugger for Windows v1.1/v1.2 or for Linux v0.8/v1.2.\r
1358 //\r
1359 DebugPortWriteBuffer (Handle, (UINT8 *) mErrorMsgVersionAlert, AsciiStrLen (mErrorMsgVersionAlert));\r
1360 CpuDeadLoop ();\r
1361 }\r
1362 \r
1363 if (RETURN_ERROR (Status)) {\r
1364 DebugPortWriteBuffer (Handle, (UINT8 *) mErrorMsgConnectFail, AsciiStrLen (mErrorMsgConnectFail));\r
1365 } else {\r
1366 DebugPortWriteBuffer (Handle, (UINT8 *) mErrorMsgConnectOK, AsciiStrLen (mErrorMsgConnectOK));\r
1367 //\r
1368 // Set Attach flag\r
1369 //\r
1370 SetHostAttached (TRUE);\r
1371 }\r
1372 return Status;\r
1373}\r
1374\r
1375/**\r
1376 Send Break point packet to HOST. \r
1377 \r
1378 Only the first breaking processor could sent BREAK_POINT packet.\r
1379\r
1380 @param[in] BreakCause Break cause of this break event.\r
1381 @param[in] ProcessorIndex Processor index value.\r
1382 @param[out] BreakReceived If BreakReceived is not NULL,\r
1383 TRUE is retured if break-in symbol received.\r
1384 FALSE is retured if break-in symbol not received.\r
1385 \r
1386**/\r
1387VOID\r
1388SendBreakPacketToHost (\r
1389 IN UINT8 BreakCause,\r
1390 IN UINT32 ProcessorIndex,\r
1391 OUT BOOLEAN *BreakReceived\r
1392 )\r
1393{\r
1394 UINT8 InputCharacter;\r
1395 DEBUG_PORT_HANDLE Handle;\r
1396 \r
1397 Handle = GetDebugPortHandle();\r
1398 \r
1399 if (IsHostAttached ()) {\r
1400 DebugAgentMsgPrint (DEBUG_AGENT_INFO, "processor[%x]:Send Break Packet to HOST.\n", ProcessorIndex);\r
1401 SendCommandAndWaitForAckOK (DEBUG_COMMAND_BREAK_POINT, READ_PACKET_TIMEOUT, BreakReceived, NULL);\r
1402 } else {\r
1403 DebugAgentMsgPrint (DEBUG_AGENT_INFO, "processor[%x]:Try to attach HOST.\n", ProcessorIndex);\r
1404 //\r
1405 // If HOST is not attached, try to attach it firstly.\r
1406 //\r
1407 //\r
1408 // Poll Attach symbols from HOST and ack OK\r
1409 // \r
1410 do {\r
1411 DebugPortReadBuffer (Handle, &InputCharacter, 1, 0);\r
1412 } while (InputCharacter != DEBUG_STARTING_SYMBOL_ATTACH);\r
1413 SendAckPacket (DEBUG_COMMAND_OK);\r
1414 \r
1415 //\r
1416 // Try to attach HOST\r
1417 //\r
1418 while (AttachHost (BreakCause, 0, NULL) != RETURN_SUCCESS);\r
1419 \r
1420 }\r
1421}\r
1422\r
1423/**\r
1424 The main function to process communication with HOST.\r
1425\r
1426 It received the command packet from HOST, and sent response data packet to HOST.\r
1427\r
1428 @param[in] Vector Vector value of exception or interrutp.\r
1429 @param[in, out] CpuContext Pointer to saved CPU context.\r
1430 @param[in] BreakReceived TRUE means break-in symbol received.\r
1431 FALSE means break-in symbol not received.\r
1432\r
1433**/\r
1434VOID\r
1435CommandCommunication (\r
1436 IN UINTN Vector,\r
1437 IN OUT DEBUG_CPU_CONTEXT *CpuContext,\r
1438 IN BOOLEAN BreakReceived\r
1439 )\r
1440{\r
1441 RETURN_STATUS Status;\r
1442 UINT8 InputPacketBuffer[DEBUG_DATA_UPPER_LIMIT + sizeof (UINT64) - 1];\r
1443 DEBUG_PACKET_HEADER *DebugHeader;\r
1444 UINT8 Width;\r
1445 UINT8 Data8;\r
1446 UINT32 Data32;\r
1447 UINT64 Data64;\r
1448 DEBUG_DATA_READ_MEMORY *MemoryRead;\r
1449 DEBUG_DATA_WRITE_MEMORY *MemoryWrite;\r
1450 DEBUG_DATA_READ_IO *IoRead;\r
1451 DEBUG_DATA_WRITE_IO *IoWrite;\r
1452 DEBUG_DATA_READ_REGISTER *RegisterRead;\r
1453 DEBUG_DATA_WRITE_REGISTER *RegisterWrite;\r
1454 UINT8 *RegisterBuffer;\r
1455 DEBUG_DATA_READ_MSR *MsrRegisterRead;\r
1456 DEBUG_DATA_WRITE_MSR *MsrRegisterWrite;\r
1457 DEBUG_DATA_CPUID *Cpuid;\r
1458 DEBUG_DATA_RESPONSE_CPUID CpuidResponse;\r
1459 DEBUG_DATA_SEARCH_SIGNATURE *SearchSignature;\r
1460 DEBUG_DATA_RESPONSE_GET_EXCEPTION Exception;\r
1461 DEBUG_DATA_RESPONSE_GET_REVISION DebugAgentRevision;\r
1462 DEBUG_DATA_SET_VIEWPOINT *SetViewPoint;\r
1463 BOOLEAN HaltDeferred;\r
1464 UINT32 ProcessorIndex;\r
1465 DEBUG_PORT_HANDLE Handle;\r
1466 DEBUG_AGENT_EXCEPTION_BUFFER AgentExceptionBuffer;\r
1467 UINT32 IssuedViewPoint;\r
1468 DEBUG_AGENT_MAILBOX *Mailbox;\r
1469 UINT8 *AlignedDataPtr;\r
1470\r
1471 ProcessorIndex = 0;\r
1472 IssuedViewPoint = 0;\r
1473 HaltDeferred = BreakReceived;\r
1474\r
1475 if (MultiProcessorDebugSupport()) {\r
1476 ProcessorIndex = GetProcessorIndex ();\r
1477 SetCpuStopFlagByIndex (ProcessorIndex, TRUE);\r
1478 if (mDebugMpContext.ViewPointIndex == ProcessorIndex) {\r
1479 //\r
1480 // Only the current view processor could set AgentInProgress Flag. \r
1481 //\r
1482 IssuedViewPoint = ProcessorIndex;\r
1483 }\r
1484 }\r
1485\r
1486 if (IssuedViewPoint == ProcessorIndex) {\r
1487 //\r
1488 // Set AgentInProgress Flag.\r
1489 //\r
1490 SetDebugFlag (DEBUG_AGENT_FLAG_AGENT_IN_PROGRESS, 1);\r
1491 } \r
1492\r
1493 Handle = GetDebugPortHandle();\r
1494\r
1495 while (TRUE) {\r
1496\r
1497 if (MultiProcessorDebugSupport()) {\r
1498 //\r
1499 // Check if the current processor is HOST view point\r
1500 //\r
1501 if (mDebugMpContext.ViewPointIndex != ProcessorIndex) {\r
1502 if (mDebugMpContext.RunCommandSet) {\r
1503 //\r
1504 // If HOST view point sets RUN flag, run GO command to leave\r
1505 //\r
1506 SetCpuStopFlagByIndex (ProcessorIndex, FALSE);\r
1507 CommandGo (CpuContext);\r
1508 break;\r
1509 } else {\r
1510 //\r
1511 // Run into loop again\r
1512 //\r
1513 CpuPause ();\r
1514 continue;\r
1515 }\r
1516 }\r
1517 }\r
1518\r
1519 AcquireMpSpinLock (&mDebugMpContext.DebugPortSpinLock);\r
1520\r
1521 DebugHeader =(DEBUG_PACKET_HEADER *) InputPacketBuffer;\r
1522\r
1523 DebugAgentMsgPrint (DEBUG_AGENT_INFO, "TARGET: Try to get command from HOST...\n");\r
1524 Status = ReceivePacket ((UINT8 *)DebugHeader, &BreakReceived, NULL, READ_PACKET_TIMEOUT, TRUE);\r
1525 if (Status != RETURN_SUCCESS || (DebugHeader->Command & DEBUG_COMMAND_RESPONSE) != 0) {\r
1526 DebugAgentMsgPrint (DEBUG_AGENT_WARNING, "TARGET: Get command[%x] sequenceno[%x] returned status is [%x] \n", DebugHeader->Command, DebugHeader->SequenceNo, Status);\r
1527 DebugAgentMsgPrint (DEBUG_AGENT_WARNING, "TARGET: Get command failed or it's response packet not expected! \n");\r
1528 ReleaseMpSpinLock (&mDebugMpContext.DebugPortSpinLock);\r
1529 continue;\r
1530 }\r
1531\r
1532 Mailbox = GetMailboxPointer ();\r
1533 if (DebugHeader->SequenceNo == Mailbox->HostSequenceNo) {\r
1534 DebugAgentMsgPrint (DEBUG_AGENT_WARNING, "TARGET: Receive one old command[%x] agaist command[%x]\n", DebugHeader->SequenceNo, Mailbox->HostSequenceNo);\r
1535 SendAckPacket (Mailbox->LastAck);\r
1536 ReleaseMpSpinLock (&mDebugMpContext.DebugPortSpinLock);\r
1537 continue;\r
1538 } else if (DebugHeader->SequenceNo == (UINT8) (Mailbox->HostSequenceNo + 1)) {\r
1539 UpdateMailboxContent (Mailbox, DEBUG_MAILBOX_HOST_SEQUENCE_NO_INDEX, (UINT8) DebugHeader->SequenceNo);\r
1540 } else {\r
1541 DebugAgentMsgPrint (DEBUG_AGENT_WARNING, "Receive one invalid comamnd[%x] agaist command[%x]\n", DebugHeader->SequenceNo, Mailbox->HostSequenceNo);\r
1542 ReleaseMpSpinLock (&mDebugMpContext.DebugPortSpinLock);\r
1543 continue;\r
1544 }\r
1545 \r
1546 //\r
1547 // Save CPU content before executing HOST commond\r
1548 //\r
1549 UpdateMailboxContent (Mailbox, DEBUG_MAILBOX_EXCEPTION_BUFFER_POINTER_INDEX, (UINT64)(UINTN) &AgentExceptionBuffer.JumpBuffer);\r
1550 if (SetJump (&AgentExceptionBuffer.JumpBuffer) != 0) {\r
1551 //\r
1552 // If HOST command failed, continue to wait for HOST's next command\r
1553 // If needed, agent could send exception info to HOST.\r
1554 //\r
1555 SendAckPacket (DEBUG_COMMAND_ABORT);\r
1556 ReleaseMpSpinLock (&mDebugMpContext.DebugPortSpinLock);\r
1557 continue;\r
1558 }\r
1559\r
1560 DebugAgentMsgPrint (DEBUG_AGENT_INFO, "Processor[%x]:Received one command(%x)\n", mDebugMpContext.ViewPointIndex, DebugHeader->Command);\r
1561 \r
1562 switch (DebugHeader->Command) {\r
1563\r
1564 case DEBUG_COMMAND_HALT:\r
1565 SendAckPacket (DEBUG_COMMAND_HALT_DEFERRED);\r
1566 HaltDeferred = TRUE;\r
1567 BreakReceived = FALSE;\r
1568 Status = RETURN_SUCCESS;\r
1569 break;\r
1570\r
1571 case DEBUG_COMMAND_RESET:\r
1572 SendAckPacket (DEBUG_COMMAND_OK);\r
1573 SendAckPacket (DEBUG_COMMAND_OK);\r
1574 SendAckPacket (DEBUG_COMMAND_OK);\r
1575 ReleaseMpSpinLock (&mDebugMpContext.DebugPortSpinLock);\r
1576\r
1577 ResetCold ();\r
1578 //\r
1579 // Assume system resets in 2 seconds, otherwise send TIMEOUT packet.\r
1580 // PCD can be used if 2 seconds isn't long enough for some platforms.\r
1581 //\r
1582 MicroSecondDelay (2000000);\r
1583 UpdateMailboxContent (Mailbox, DEBUG_MAILBOX_HOST_SEQUENCE_NO_INDEX, Mailbox->HostSequenceNo + 1);\r
1584 SendAckPacket (DEBUG_COMMAND_TIMEOUT);\r
1585 SendAckPacket (DEBUG_COMMAND_TIMEOUT);\r
1586 SendAckPacket (DEBUG_COMMAND_TIMEOUT);\r
1587 break;\r
1588\r
1589 case DEBUG_COMMAND_GO:\r
1590 CommandGo (CpuContext);\r
1591 //\r
1592 // Clear Dr0 to avoid to be recognized as IMAGE_LOAD/_UNLOAD again when hitting a breakpoint after GO\r
1593 // If HOST changed Dr0 before GO, we will not change Dr0 here\r
1594 //\r
1595 Data8 = GetBreakCause (Vector, CpuContext);\r
1596 if (Data8 == DEBUG_DATA_BREAK_CAUSE_IMAGE_LOAD || Data8 == DEBUG_DATA_BREAK_CAUSE_IMAGE_UNLOAD) {\r
1597 CpuContext->Dr0 = 0;\r
1598 }\r
1599 //\r
1600 // Clear Stepping Flag\r
1601 //\r
1602 SetDebugFlag (DEBUG_AGENT_FLAG_STEPPING, 0);\r
1603 \r
1604 if (!HaltDeferred) {\r
1605 //\r
1606 // If no HALT command received when being in-active mode\r
1607 //\r
1608 if (MultiProcessorDebugSupport()) {\r
1609 Data32 = FindNextPendingBreakCpu ();\r
1610 if (Data32 != -1) {\r
1611 //\r
1612 // If there are still others processors being in break state, \r
1613 // send OK packet to HOST to finish this go command\r
1614 //\r
1615 SendAckPacket (DEBUG_COMMAND_OK);\r
1616 CpuPause ();\r
1617 //\r
1618 // Set current view to the next breaking processor\r
1619 //\r
1620 mDebugMpContext.ViewPointIndex = Data32;\r
1621 mDebugMpContext.BreakAtCpuIndex = mDebugMpContext.ViewPointIndex;\r
1622 SetCpuBreakFlagByIndex (mDebugMpContext.ViewPointIndex, FALSE);\r
1623 //\r
1624 // Send break packet to HOST to let HOST break again\r
1625 //\r
1626 SendBreakPacketToHost (DEBUG_DATA_BREAK_CAUSE_UNKNOWN, mDebugMpContext.BreakAtCpuIndex, &BreakReceived);\r
1627 //\r
1628 // Continue to run into loop to read command packet from HOST\r
1629 //\r
1630 ReleaseMpSpinLock (&mDebugMpContext.DebugPortSpinLock);\r
1631 break;\r
1632 }\r
1633\r
1634 //\r
1635 // If no else processor break, set stop bitmask,\r
1636 // and set Running flag for all processors.\r
1637 //\r
1638 SetCpuStopFlagByIndex (ProcessorIndex, FALSE);\r
1639 SetCpuRunningFlag (TRUE);\r
1640 CpuPause ();\r
1641 //\r
1642 // Wait for all processors are in running state \r
1643 //\r
1644 while (TRUE) {\r
1645 if (IsAllCpuRunning ()) {\r
1646 break;\r
1647 }\r
1648 }\r
1649 //\r
1650 // Set BSP to be current view point.\r
1651 //\r
1652 SetDebugViewPoint (mDebugMpContext.BspIndex);\r
1653 CpuPause ();\r
1654 //\r
1655 // Clear breaking processor index and running flag\r
1656 //\r
1657 mDebugMpContext.BreakAtCpuIndex = (UINT32) (-1);\r
1658 SetCpuRunningFlag (FALSE);\r
1659 }\r
1660\r
1661 //\r
1662 // Send OK packet to HOST to finish this go command\r
1663 //\r
1664 SendAckPacket (DEBUG_COMMAND_OK);\r
1665\r
1666 ReleaseMpSpinLock (&mDebugMpContext.DebugPortSpinLock);\r
1667\r
1668 if (!IsHostAttached()) {\r
1669 UpdateMailboxContent (Mailbox, DEBUG_MAILBOX_SEQUENCE_NO_INDEX, 0);\r
1670 UpdateMailboxContent (Mailbox, DEBUG_MAILBOX_HOST_SEQUENCE_NO_INDEX, 0);\r
1671 }\r
1672 return;\r
1673\r
1674 } else {\r
1675 //\r
1676 // If reveived HALT command, need to defer the GO command\r
1677 //\r
1678 SendAckPacket (DEBUG_COMMAND_HALT_PROCESSED);\r
1679 HaltDeferred = FALSE;\r
1680\r
1681 Vector = DEBUG_TIMER_VECTOR;\r
1682 }\r
1683 break;\r
1684\r
1685 case DEBUG_COMMAND_BREAK_CAUSE:\r
1686\r
1687 if (MultiProcessorDebugSupport() && ProcessorIndex != mDebugMpContext.BreakAtCpuIndex) {\r
1688 Status = SendBreakCausePacket (DEBUG_TIMER_VECTOR, CpuContext);\r
1689\r
1690 } else {\r
1691 Status = SendBreakCausePacket (Vector, CpuContext);\r
1692 }\r
1693\r
1694 break;\r
1695\r
1696 case DEBUG_COMMAND_SET_HW_BREAKPOINT:\r
1697 SetDebugRegister (CpuContext, (DEBUG_DATA_SET_HW_BREAKPOINT *) (DebugHeader + 1));\r
1698 SendAckPacket (DEBUG_COMMAND_OK);\r
1699 break;\r
1700\r
1701 case DEBUG_COMMAND_CLEAR_HW_BREAKPOINT:\r
1702 ClearDebugRegister (CpuContext, (DEBUG_DATA_CLEAR_HW_BREAKPOINT *) (DebugHeader + 1));\r
1703 SendAckPacket (DEBUG_COMMAND_OK);\r
1704 break;\r
1705\r
1706 case DEBUG_COMMAND_SINGLE_STEPPING:\r
1707 CommandStepping (CpuContext);\r
1708 //\r
1709 // Clear Dr0 to avoid to be recognized as IMAGE_LOAD/_UNLOAD again when hitting a breakpoint after GO\r
1710 // If HOST changed Dr0 before GO, we will not change Dr0 here\r
1711 //\r
1712 Data8 = GetBreakCause (Vector, CpuContext);\r
1713 if (Data8 == DEBUG_DATA_BREAK_CAUSE_IMAGE_LOAD || Data8 == DEBUG_DATA_BREAK_CAUSE_IMAGE_UNLOAD) {\r
1714 CpuContext->Dr0 = 0;\r
1715 }\r
1716\r
1717 mDebugMpContext.BreakAtCpuIndex = (UINT32) (-1);\r
1718 //\r
1719 // Set Stepping Flag\r
1720 //\r
1721 SetDebugFlag (DEBUG_AGENT_FLAG_STEPPING, 1);\r
1722 ReleaseMpSpinLock (&mDebugMpContext.DebugPortSpinLock);\r
1723 //\r
1724 // Executing stepping command directly without sending ACK packet,\r
1725 // ACK packet will be sent after stepping done.\r
1726 //\r
1727 return;\r
1728\r
1729 case DEBUG_COMMAND_SET_SW_BREAKPOINT:\r
1730 Data64 = (UINTN) (((DEBUG_DATA_SET_SW_BREAKPOINT *) (DebugHeader + 1))->Address);\r
1731 Data8 = *(UINT8 *) (UINTN) Data64;\r
1732 *(UINT8 *) (UINTN) Data64 = DEBUG_SW_BREAKPOINT_SYMBOL;\r
1733 Status = SendDataResponsePacket ((UINT8 *) &Data8, (UINT16) sizeof (UINT8));\r
1734 break;\r
1735\r
1736 case DEBUG_COMMAND_READ_MEMORY:\r
1737 MemoryRead = (DEBUG_DATA_READ_MEMORY *) (DebugHeader + 1);\r
1738 Status = ReadMemoryAndSendResponsePacket ((UINT8 *) (UINTN) MemoryRead->Address, MemoryRead->Count, MemoryRead->Width);\r
1739 break;\r
1740\r
1741 case DEBUG_COMMAND_WRITE_MEMORY:\r
1742 MemoryWrite = (DEBUG_DATA_WRITE_MEMORY *) (DebugHeader + 1);\r
1743 //\r
1744 // Copy data into one memory with 8-byte alignment address\r
1745 //\r
1746 AlignedDataPtr = ALIGN_POINTER ((UINT8 *) &MemoryWrite->Data, sizeof (UINT64));\r
1747 if (AlignedDataPtr != (UINT8 *) &MemoryWrite->Data) {\r
1748 CopyMem (AlignedDataPtr, (UINT8 *) &MemoryWrite->Data, MemoryWrite->Count * MemoryWrite->Width);\r
1749 }\r
1750 CopyMemByWidth ((UINT8 *) (UINTN) MemoryWrite->Address, AlignedDataPtr, MemoryWrite->Count, MemoryWrite->Width);\r
1751 SendAckPacket (DEBUG_COMMAND_OK);\r
1752 break;\r
1753\r
1754 case DEBUG_COMMAND_READ_IO:\r
1755 IoRead = (DEBUG_DATA_READ_IO *) (DebugHeader + 1);\r
1756 switch (IoRead->Width) {\r
1757 case 1:\r
1758 Data64 = IoRead8 ((UINTN) IoRead->Port);\r
1759 break;\r
1760 case 2:\r
1761 Data64 = IoRead16 ((UINTN) IoRead->Port);\r
1762 break;\r
1763 case 4:\r
1764 Data64 = IoRead32 ((UINTN) IoRead->Port);\r
1765 break;\r
1766 case 8:\r
1767 Data64 = IoRead64 ((UINTN) IoRead->Port);\r
1768 break;\r
1769 default:\r
1770 Data64 = (UINT64) -1;\r
1771 }\r
1772 Status = SendDataResponsePacket ((UINT8 *) &Data64, IoRead->Width);\r
1773 break;\r
1774\r
1775 case DEBUG_COMMAND_WRITE_IO:\r
1776 IoWrite = (DEBUG_DATA_WRITE_IO *) (DebugHeader + 1);\r
1777 switch (IoWrite->Width) {\r
1778 case 1:\r
1779 Data64 = IoWrite8 ((UINTN) IoWrite->Port, *(UINT8 *) &IoWrite->Data);\r
1780 break;\r
1781 case 2:\r
1782 Data64 = IoWrite16 ((UINTN) IoWrite->Port, *(UINT16 *) &IoWrite->Data);\r
1783 break;\r
1784 case 4:\r
1785 Data64 = IoWrite32 ((UINTN) IoWrite->Port, *(UINT32 *) &IoWrite->Data);\r
1786 break;\r
1787 case 8:\r
1788 Data64 = IoWrite64 ((UINTN) IoWrite->Port, *(UINT64 *) &IoWrite->Data);\r
1789 break;\r
1790 default:\r
1791 Data64 = (UINT64) -1;\r
1792 }\r
1793 SendAckPacket (DEBUG_COMMAND_OK);\r
1794 break;\r
1795\r
1796 case DEBUG_COMMAND_READ_ALL_REGISTERS:\r
1797 Status = SendDataResponsePacket ((UINT8 *) CpuContext, sizeof (*CpuContext));\r
1798 break;\r
1799\r
1800 case DEBUG_COMMAND_READ_REGISTER:\r
1801 RegisterRead = (DEBUG_DATA_READ_REGISTER *) (DebugHeader + 1);\r
1802\r
1803 if (RegisterRead->Index <= SOFT_DEBUGGER_REGISTER_MAX) {\r
1804 RegisterBuffer = ArchReadRegisterBuffer (CpuContext, RegisterRead->Index, &Width);\r
1805 Status = SendDataResponsePacket (RegisterBuffer, Width);\r
1806 } else {\r
1807 Status = RETURN_UNSUPPORTED;\r
1808 }\r
1809 break;\r
1810\r
1811 case DEBUG_COMMAND_WRITE_REGISTER:\r
1812 RegisterWrite = (DEBUG_DATA_WRITE_REGISTER *) (DebugHeader + 1);\r
1813 if (RegisterWrite->Index <= SOFT_DEBUGGER_REGISTER_MAX) {\r
1814 RegisterBuffer = ArchReadRegisterBuffer (CpuContext, RegisterWrite->Index, &Width);\r
1815 ASSERT (Width == RegisterWrite->Length);\r
1816 CopyMem (RegisterBuffer, RegisterWrite->Data, Width);\r
1817 SendAckPacket (DEBUG_COMMAND_OK);\r
1818 } else {\r
1819 Status = RETURN_UNSUPPORTED;\r
1820 }\r
1821 break;\r
1822\r
1823 case DEBUG_COMMAND_ARCH_MODE:\r
1824 Data8 = DEBUG_ARCH_SYMBOL;\r
1825 Status = SendDataResponsePacket ((UINT8 *) &Data8, (UINT16) sizeof (UINT8));\r
1826 break;\r
1827\r
1828 case DEBUG_COMMAND_READ_MSR:\r
1829 MsrRegisterRead = (DEBUG_DATA_READ_MSR *) (DebugHeader + 1);\r
1830 Data64 = AsmReadMsr64 (MsrRegisterRead->Index);\r
1831 Status = SendDataResponsePacket ((UINT8 *) &Data64, (UINT16) sizeof (UINT64));\r
1832 break;\r
1833\r
1834 case DEBUG_COMMAND_WRITE_MSR:\r
1835 MsrRegisterWrite = (DEBUG_DATA_WRITE_MSR *) (DebugHeader + 1);\r
1836 AsmWriteMsr64 (MsrRegisterWrite->Index, MsrRegisterWrite->Value);\r
1837 SendAckPacket (DEBUG_COMMAND_OK);\r
1838 break;\r
1839\r
1840 case DEBUG_COMMAND_SET_DEBUG_SETTING:\r
1841 Status = SetDebugSetting ((DEBUG_DATA_SET_DEBUG_SETTING *)(DebugHeader + 1));\r
1842 if (Status == RETURN_SUCCESS) {\r
1843 SendAckPacket (DEBUG_COMMAND_OK);\r
1844 }\r
1845 break;\r
1846\r
1847 case DEBUG_COMMAND_GET_REVISION:\r
1848 DebugAgentRevision.Revision = DEBUG_AGENT_REVISION;\r
1849 DebugAgentRevision.Capabilities = DEBUG_AGENT_CAPABILITIES;\r
1850 Status = SendDataResponsePacket ((UINT8 *) &DebugAgentRevision, (UINT16) sizeof (DEBUG_DATA_RESPONSE_GET_REVISION));\r
1851 break;\r
1852\r
1853 case DEBUG_COMMAND_GET_EXCEPTION:\r
1854 Exception.ExceptionNum = (UINT8) Vector;\r
1855 Exception.ExceptionData = (UINT32) CpuContext->ExceptionData;\r
1856 Status = SendDataResponsePacket ((UINT8 *) &Exception, (UINT16) sizeof (DEBUG_DATA_RESPONSE_GET_EXCEPTION));\r
1857 break;\r
1858\r
1859 case DEBUG_COMMAND_SET_VIEWPOINT:\r
1860 SetViewPoint = (DEBUG_DATA_SET_VIEWPOINT *) (DebugHeader + 1);\r
1861 if (MultiProcessorDebugSupport()) {\r
1862 if (IsCpuStopped (SetViewPoint->ViewPoint)) {\r
1863 SetDebugViewPoint (SetViewPoint->ViewPoint);\r
1864 SendAckPacket (DEBUG_COMMAND_OK);\r
1865 } else {\r
1866 //\r
1867 // If CPU is not halted\r
1868 //\r
1869 SendAckPacket (DEBUG_COMMAND_NOT_SUPPORTED);\r
1870 }\r
1871 } else if (SetViewPoint->ViewPoint == 0) {\r
1872 SendAckPacket (DEBUG_COMMAND_OK);\r
1873\r
1874 } else {\r
1875 SendAckPacket (DEBUG_COMMAND_NOT_SUPPORTED);\r
1876 }\r
1877\r
1878 break;\r
1879\r
1880 case DEBUG_COMMAND_GET_VIEWPOINT:\r
1881 Data32 = mDebugMpContext.ViewPointIndex;\r
1882 SendDataResponsePacket((UINT8 *) &Data32, (UINT16) sizeof (UINT32));\r
1883 break;\r
1884\r
1885 case DEBUG_COMMAND_MEMORY_READY:\r
1886 Data8 = (UINT8) GetDebugFlag (DEBUG_AGENT_FLAG_MEMORY_READY);\r
1887 SendDataResponsePacket (&Data8, (UINT16) sizeof (UINT8));\r
1888 break;\r
1889\r
1890 case DEBUG_COMMAND_DETACH:\r
1891 SetHostAttached (FALSE);\r
1892 SendAckPacket (DEBUG_COMMAND_OK);\r
1893 break;\r
1894\r
1895 case DEBUG_COMMAND_CPUID:\r
1896 Cpuid = (DEBUG_DATA_CPUID *) (DebugHeader + 1);\r
1897 AsmCpuidEx (\r
1898 Cpuid->Eax, Cpuid->Ecx, \r
1899 &CpuidResponse.Eax, &CpuidResponse.Ebx,\r
1900 &CpuidResponse.Ecx, &CpuidResponse.Edx\r
1901 );\r
1902 SendDataResponsePacket ((UINT8 *) &CpuidResponse, (UINT16) sizeof (CpuidResponse));\r
1903 break;\r
1904\r
1905 case DEBUG_COMMAND_SEARCH_SIGNATURE:\r
1906 SearchSignature = (DEBUG_DATA_SEARCH_SIGNATURE *) (DebugHeader + 1);\r
1907 if ((SearchSignature->Alignment != 0) && \r
1908 (SearchSignature->Alignment == GetPowerOfTwo32 (SearchSignature->Alignment))\r
1909 ) {\r
1910 if (SearchSignature->Positive) {\r
1911 for (\r
1912 Data64 = ALIGN_VALUE ((UINTN) SearchSignature->Start, SearchSignature->Alignment);\r
1913 Data64 <= SearchSignature->Start + SearchSignature->Count - SearchSignature->DataLength;\r
1914 Data64 += SearchSignature->Alignment\r
1915 ) {\r
1916 if (CompareMem ((VOID *) (UINTN) Data64, &SearchSignature->Data, SearchSignature->DataLength) == 0) {\r
1917 break;\r
1918 }\r
1919 }\r
1920 if (Data64 > SearchSignature->Start + SearchSignature->Count - SearchSignature->DataLength) {\r
1921 Data64 = (UINT64) -1;\r
1922 }\r
1923 } else {\r
1924 for (\r
1925 Data64 = ALIGN_VALUE ((UINTN) SearchSignature->Start - SearchSignature->Alignment, SearchSignature->Alignment);\r
1926 Data64 >= SearchSignature->Start - SearchSignature->Count;\r
1927 Data64 -= SearchSignature->Alignment\r
1928 ) {\r
1929 if (CompareMem ((VOID *) (UINTN) Data64, &SearchSignature->Data, SearchSignature->DataLength) == 0) {\r
1930 break;\r
1931 }\r
1932 }\r
1933 if (Data64 < SearchSignature->Start - SearchSignature->Count) {\r
1934 Data64 = (UINT64) -1;\r
1935 }\r
1936 }\r
1937 SendDataResponsePacket ((UINT8 *) &Data64, (UINT16) sizeof (Data64));\r
1938 } else {\r
1939 Status = RETURN_UNSUPPORTED;\r
1940 }\r
1941 break;\r
1942\r
1943 default:\r
1944 SendAckPacket (DEBUG_COMMAND_NOT_SUPPORTED);\r
1945 break;\r
1946 }\r
1947\r
1948 if (Status == RETURN_UNSUPPORTED) {\r
1949 SendAckPacket (DEBUG_COMMAND_NOT_SUPPORTED);\r
1950 } else if (Status != RETURN_SUCCESS) {\r
1951 SendAckPacket (DEBUG_COMMAND_ABORT);\r
1952 }\r
1953\r
1954 ReleaseMpSpinLock (&mDebugMpContext.DebugPortSpinLock);\r
1955 CpuPause ();\r
1956 }\r
1957}\r
1958\r
1959/**\r
1960 C function called in interrupt handler.\r
1961\r
1962 @param[in] Vector Vector value of exception or interrutp.\r
1963 @param[in] CpuContext Pointer to save CPU context.\r
1964\r
1965**/\r
1966VOID\r
1967EFIAPI\r
1968InterruptProcess (\r
1969 IN UINT32 Vector,\r
1970 IN DEBUG_CPU_CONTEXT *CpuContext\r
1971 )\r
1972{\r
1973 UINT8 InputCharacter;\r
1974 UINT8 BreakCause;\r
1975 UINTN SavedEip;\r
1976 BOOLEAN BreakReceived;\r
1977 UINT32 ProcessorIndex;\r
1978 UINT32 CurrentDebugTimerInitCount;\r
1979 DEBUG_PORT_HANDLE Handle;\r
1980 UINT8 Data8;\r
1981 UINT8 *Al;\r
1982 UINT32 IssuedViewPoint;\r
1983 DEBUG_AGENT_EXCEPTION_BUFFER *ExceptionBuffer;\r
1984\r
1985 ProcessorIndex = 0;\r
1986 IssuedViewPoint = 0;\r
1987 BreakReceived = FALSE;\r
1988\r
1989 if (mSkipBreakpoint) {\r
1990 //\r
1991 // If Skip Breakpoint flag is set, means communication is disturbed by hardware SMI, we need to ignore the break points in SMM\r
1992 //\r
1993 if ((Vector == DEBUG_INT1_VECTOR) || (Vector == DEBUG_INT3_VECTOR)) {\r
1994 DebugPortWriteBuffer (GetDebugPortHandle(), (UINT8 *) mWarningMsgIngoreBreakpoint, AsciiStrLen (mWarningMsgIngoreBreakpoint));\r
1995 return;\r
1996 }\r
1997 }\r
1998\r
1999 if (MultiProcessorDebugSupport()) {\r
2000 ProcessorIndex = GetProcessorIndex ();\r
2001 //\r
2002 // If this processor has alreay halted before, need to check it later\r
2003 //\r
2004 if (IsCpuStopped (ProcessorIndex)) {\r
2005 IssuedViewPoint = ProcessorIndex;\r
2006 }\r
2007 }\r
2008\r
2009 if (IssuedViewPoint == ProcessorIndex && GetDebugFlag (DEBUG_AGENT_FLAG_STEPPING) != 1) {\r
2010 //\r
2011 // Check if this exception is issued by Debug Agent itself\r
2012 // If yes, fill the debug agent exception buffer and LongJump() back to\r
2013 // the saved CPU content in CommandCommunication()\r
2014 //\r
2015 if (GetDebugFlag (DEBUG_AGENT_FLAG_AGENT_IN_PROGRESS) == 1) {\r
2016 DebugAgentMsgPrint (DEBUG_AGENT_ERROR, "Debug agent meet one Exception, ExceptionNum is %d, EIP = 0x%x.\n", Vector, (UINTN)CpuContext->Eip);\r
2017 ExceptionBuffer = (DEBUG_AGENT_EXCEPTION_BUFFER *) (UINTN) GetMailboxPointer()->ExceptionBufferPointer;\r
2018 ExceptionBuffer->ExceptionContent.ExceptionNum = (UINT8) Vector;\r
2019 ExceptionBuffer->ExceptionContent.ExceptionData = (UINT32) CpuContext->ExceptionData;\r
2020 LongJump ((BASE_LIBRARY_JUMP_BUFFER *)(UINTN)(ExceptionBuffer), 1);\r
2021 }\r
2022 }\r
2023\r
2024 if (MultiProcessorDebugSupport()) {\r
2025 //\r
2026 // If RUN commmand is executing, wait for it done. \r
2027 //\r
2028 while (mDebugMpContext.RunCommandSet) {\r
2029 CpuPause ();\r
2030 }\r
2031 }\r
2032\r
2033 Handle = GetDebugPortHandle();\r
2034 BreakCause = GetBreakCause (Vector, CpuContext);\r
2035 switch (Vector) {\r
2036 case DEBUG_INT1_VECTOR:\r
2037 case DEBUG_INT3_VECTOR:\r
2038 switch (BreakCause) {\r
2039 case DEBUG_DATA_BREAK_CAUSE_SYSTEM_RESET:\r
2040 if (AttachHost (BreakCause, READ_PACKET_TIMEOUT, &BreakReceived) != RETURN_SUCCESS) {\r
2041 //\r
2042 // Try to connect HOST, return if fails\r
2043 //\r
2044 break;\r
2045 }\r
2046 CommandCommunication (Vector, CpuContext, BreakReceived);\r
2047 break;\r
2048\r
2049 case DEBUG_DATA_BREAK_CAUSE_STEPPING:\r
2050 //\r
2051 // Stepping is finished, send Ack package.\r
2052 //\r
2053 if (MultiProcessorDebugSupport()) {\r
2054 mDebugMpContext.BreakAtCpuIndex = ProcessorIndex;\r
2055 }\r
2056 SendAckPacket (DEBUG_COMMAND_OK);\r
2057 CommandCommunication (Vector, CpuContext, BreakReceived);\r
2058 break;\r
2059\r
2060 case DEBUG_DATA_BREAK_CAUSE_MEMORY_READY:\r
2061 //\r
2062 // Memory is ready\r
2063 //\r
2064 SendCommandAndWaitForAckOK (DEBUG_COMMAND_MEMORY_READY, READ_PACKET_TIMEOUT, &BreakReceived, NULL);\r
2065 CommandCommunication (Vector, CpuContext, BreakReceived);\r
2066 break;\r
2067\r
2068 case DEBUG_DATA_BREAK_CAUSE_IMAGE_LOAD:\r
2069 case DEBUG_DATA_BREAK_CAUSE_IMAGE_UNLOAD:\r
2070 //\r
2071 // Set AL to DEBUG_AGENT_IMAGE_CONTINUE\r
2072 //\r
2073 Al = ArchReadRegisterBuffer (CpuContext, SOFT_DEBUGGER_REGISTER_AX, &Data8);\r
2074 *Al = DEBUG_AGENT_IMAGE_CONTINUE;\r
2075\r
2076 if (!IsHostAttached ()) {\r
2077 //\r
2078 // If HOST is not connected for image load/unload, return\r
2079 //\r
2080 break;\r
2081 }\r
2082 //\r
2083 // Continue to run the following common code\r
2084 //\r
2085 \r
2086 case DEBUG_DATA_BREAK_CAUSE_HW_BREAKPOINT:\r
2087 case DEBUG_DATA_BREAK_CAUSE_SW_BREAKPOINT:\r
2088 default:\r
2089 //\r
2090 // Send Break packet to HOST\r
2091 //\r
2092 AcquireMpSpinLock (&mDebugMpContext.DebugPortSpinLock);\r
2093 //\r
2094 // Only the first breaking processor could send BREAK_POINT to HOST\r
2095 // \r
2096 if (IsFirstBreakProcessor (ProcessorIndex)) {\r
2097 SendBreakPacketToHost (BreakCause, ProcessorIndex, &BreakReceived);\r
2098 }\r
2099 ReleaseMpSpinLock (&mDebugMpContext.DebugPortSpinLock);\r
2100 \r
2101 if (Vector == DEBUG_INT3_VECTOR) {\r
2102 //\r
2103 // go back address located "0xCC"\r
2104 //\r
2105 CpuContext->Eip--;\r
2106 SavedEip = CpuContext->Eip;\r
2107 CommandCommunication (Vector, CpuContext, BreakReceived);\r
2108 if ((SavedEip == CpuContext->Eip) &&\r
2109 (*(UINT8 *) (UINTN) CpuContext->Eip == DEBUG_SW_BREAKPOINT_SYMBOL)) {\r
2110 //\r
2111 // If this is not a software breakpoint set by HOST,\r
2112 // restore EIP\r
2113 //\r
2114 CpuContext->Eip++;\r
2115 }\r
2116 } else {\r
2117 CommandCommunication (Vector, CpuContext, BreakReceived);\r
2118 }\r
2119 break;\r
2120 }\r
2121\r
2122 break;\r
2123\r
2124 case DEBUG_TIMER_VECTOR:\r
2125\r
2126 AcquireMpSpinLock (&mDebugMpContext.DebugPortSpinLock);\r
2127\r
2128 if (MultiProcessorDebugSupport()) {\r
2129 if (IsBsp (ProcessorIndex)) {\r
2130 //\r
2131 // If current processor is BSP, check Apic timer's init count if changed,\r
2132 // it may be re-written when switching BSP.\r
2133 // If it changed, re-initialize debug timer\r
2134 //\r
2135 CurrentDebugTimerInitCount = GetApicTimerInitCount ();\r
2136 if (mDebugMpContext.DebugTimerInitCount != CurrentDebugTimerInitCount) {\r
2137 InitializeDebugTimer ();\r
2138 }\r
2139 }\r
2140\r
2141 if (!IsBsp (ProcessorIndex) || mDebugMpContext.IpiSentByAp) {\r
2142 ReleaseMpSpinLock (&mDebugMpContext.DebugPortSpinLock);\r
2143 //\r
2144 // If current processor is not BSP or this is one IPI sent by AP\r
2145 //\r
2146 if (mDebugMpContext.BreakAtCpuIndex != (UINT32) (-1)) {\r
2147 CommandCommunication (Vector, CpuContext, FALSE);\r
2148 }\r
2149\r
2150 //\r
2151 // Clear EOI before exiting interrupt process routine.\r
2152 //\r
2153 SendApicEoi ();\r
2154 break;\r
2155 }\r
2156 }\r
2157\r
2158 //\r
2159 // Only BSP could run here\r
2160 //\r
2161 while (TRUE) {\r
2162 //\r
2163 // If there is data in debug port, will check whether it is break(attach/break-in) symbol,\r
2164 // If yes, go into communication mode with HOST.\r
2165 // If no, exit interrupt process.\r
2166 //\r
2167 if (DebugReadBreakSymbol (Handle, &InputCharacter) == EFI_NOT_FOUND) {\r
2168 break;\r
2169 }\r
2170\r
2171 if ((!IsHostAttached () && (InputCharacter == DEBUG_STARTING_SYMBOL_ATTACH)) ||\r
2172 (IsHostAttached () && (InputCharacter == DEBUG_COMMAND_HALT)) ||\r
2173 (IsHostAttached () && (InputCharacter == DEBUG_COMMAND_GO))\r
2174 ) {\r
2175 DebugAgentMsgPrint (DEBUG_AGENT_VERBOSE, "Received data [%02x]\n", InputCharacter);\r
2176 //\r
2177 // Ack OK for break-in symbol\r
2178 //\r
2179 SendAckPacket (DEBUG_COMMAND_OK);\r
2180\r
2181 //\r
2182 // If receive GO command in Debug Timer, means HOST may lost ACK packet before.\r
2183 //\r
2184 if (InputCharacter == DEBUG_COMMAND_GO) {\r
2185 break;\r
2186 }\r
2187\r
2188 if (!IsHostAttached ()) {\r
2189 //\r
2190 // Try to attach HOST, if no ack received after 200ms, return\r
2191 //\r
2192 if (AttachHost (BreakCause, READ_PACKET_TIMEOUT, &BreakReceived) != RETURN_SUCCESS) {\r
2193 break;\r
2194 }\r
2195 }\r
2196\r
2197 if (MultiProcessorDebugSupport()) {\r
2198 if(FindNextPendingBreakCpu () != -1) {\r
2199 SetCpuBreakFlagByIndex (ProcessorIndex, TRUE);\r
2200 } else {\r
2201 HaltOtherProcessors (ProcessorIndex);\r
2202 }\r
2203 }\r
2204 ReleaseMpSpinLock (&mDebugMpContext.DebugPortSpinLock);\r
2205 CommandCommunication (Vector, CpuContext, BreakReceived);\r
2206 AcquireMpSpinLock (&mDebugMpContext.DebugPortSpinLock);\r
2207 break;\r
2208 }\r
2209 }\r
2210\r
2211 //\r
2212 // Clear EOI before exiting interrupt process routine.\r
2213 //\r
2214 SendApicEoi ();\r
2215\r
2216 ReleaseMpSpinLock (&mDebugMpContext.DebugPortSpinLock);\r
2217\r
2218 break;\r
2219\r
2220 default:\r
2221 if (Vector <= DEBUG_EXCEPT_SIMD) {\r
2222 if (BreakCause == DEBUG_DATA_BREAK_CAUSE_STEPPING) {\r
2223 //\r
2224 // Stepping is finished, send Ack package.\r
2225 //\r
2226 if (MultiProcessorDebugSupport()) {\r
2227 mDebugMpContext.BreakAtCpuIndex = ProcessorIndex;\r
2228 }\r
2229 SendAckPacket (DEBUG_COMMAND_OK);\r
2230 } else {\r
2231 //\r
2232 // Exception occurs, send Break packet to HOST\r
2233 //\r
2234 AcquireMpSpinLock (&mDebugMpContext.DebugPortSpinLock);\r
2235 //\r
2236 // Only the first breaking processor could send BREAK_POINT to HOST\r
2237 // \r
2238 if (IsFirstBreakProcessor (ProcessorIndex)) {\r
2239 SendBreakPacketToHost (BreakCause, ProcessorIndex, &BreakReceived);\r
2240 }\r
2241 ReleaseMpSpinLock (&mDebugMpContext.DebugPortSpinLock);\r
2242 }\r
2243 \r
2244 CommandCommunication (Vector, CpuContext, BreakReceived);\r
2245 }\r
2246 break;\r
2247 }\r
2248\r
2249 if (MultiProcessorDebugSupport()) {\r
2250 //\r
2251 // Clear flag and wait for all processors run here\r
2252 //\r
2253 SetIpiSentByApFlag (FALSE);\r
2254 while (mDebugMpContext.RunCommandSet) {\r
2255 CpuPause ();\r
2256 }\r
2257\r
2258 //\r
2259 // Only current (view) processor could clean up AgentInProgress flag.\r
2260 //\r
2261 if (mDebugMpContext.ViewPointIndex == ProcessorIndex) {\r
2262 IssuedViewPoint = mDebugMpContext.ViewPointIndex;\r
2263 }\r
2264 }\r
2265\r
2266 if (IssuedViewPoint == ProcessorIndex && GetDebugFlag (DEBUG_AGENT_FLAG_STEPPING) != 1) {\r
2267 //\r
2268 // If the command is not stepping, clean up AgentInProgress flag\r
2269 //\r
2270 SetDebugFlag (DEBUG_AGENT_FLAG_AGENT_IN_PROGRESS, 0);\r
2271 }\r
2272\r
2273 return;\r
2274}\r
2275\r