]> git.proxmox.com Git - mirror_edk2.git/blame_incremental - SourceLevelDebugPkg/Library/DebugAgent/DebugAgentCommon/DebugAgent.c
Fix infinite loop bug in secure boot UI driver.
[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 - 2012, 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
21#define INIT_BREAK_ACK_TIMEOUT (200 * 1000)\r
22\r
23CHAR8 mErrorMsgVersionAlert[] = "\rThe SourceLevelDebugPkg you are using requires a newer version of the Intel(R) UDK Debugger Tool.\r\n";\r
24CHAR8 mErrorMsgSendInitPacket[] = "\rSend INIT break packet to HOST ...\r\n";\r
25CHAR8 mErrorMsgConnectOK[] = "HOST connection is successful!\r\n";\r
26CHAR8 mErrorMsgConnectFail[] = "HOST connection is failed!\r\n";\r
27\r
28/**\r
29 Send a debug message packet to the debug port.\r
30\r
31 @param[in] Buffer The debug message.\r
32 @param[in] Length The length of debug message.\r
33\r
34**/\r
35VOID\r
36SendDebugMsgPacket (\r
37 IN CHAR8 *Buffer,\r
38 IN UINTN Length \r
39 )\r
40{\r
41 DEBUG_PACKET_HEADER DebugHeader;\r
42 DEBUG_PORT_HANDLE Handle;\r
43 \r
44 Handle = GetDebugPortHandle();\r
45\r
46 DebugHeader.StartSymbol = DEBUG_STARTING_SYMBOL_NORMAL;\r
47 DebugHeader.Command = DEBUG_COMMAND_PRINT_MESSAGE;\r
48 DebugHeader.Length = sizeof (DEBUG_PACKET_HEADER) + (UINT8) Length;\r
49 DebugHeader.CheckSum = 0;\r
50 DebugHeader.CheckSum = CalculateCheckSum8 ((UINT8 *)&DebugHeader, sizeof (DEBUG_PACKET_HEADER));\r
51\r
52 DebugPortWriteBuffer (Handle, (UINT8 *)&DebugHeader, sizeof (DEBUG_PACKET_HEADER));\r
53 DebugPortWriteBuffer (Handle, (UINT8 *)Buffer, Length);\r
54}\r
55\r
56/**\r
57 Prints a debug message to the debug port if the specified error level is enabled.\r
58\r
59 If any bit in ErrorLevel is also set in Mainbox, then print the message specified\r
60 by Format and the associated variable argument list to the debug port.\r
61\r
62 @param[in] ErrorLevel The error level of the debug message.\r
63 @param[in] Format Format string for the debug message to print.\r
64 @param[in] ... Variable argument list whose contents are accessed \r
65 based on the format string specified by Format.\r
66\r
67**/\r
68VOID\r
69EFIAPI\r
70DebugAgentMsgPrint (\r
71 IN UINT8 ErrorLevel,\r
72 IN CHAR8 *Format,\r
73 ...\r
74 )\r
75{\r
76 DEBUG_AGENT_MAILBOX *Mailbox;\r
77 CHAR8 Buffer[DEBUG_DATA_MAXIMUM_REAL_DATA];\r
78 VA_LIST Marker;\r
79\r
80 Mailbox = GetMailboxPointer ();\r
81 //\r
82 // Check driver debug mask value and global mask\r
83 //\r
84 if ((ErrorLevel & Mailbox->DebugFlag.PrintErrorLevel) == 0) {\r
85 return;\r
86 }\r
87\r
88 //\r
89 // Convert the DEBUG() message to an ASCII String\r
90 //\r
91 VA_START (Marker, Format);\r
92 AsciiVSPrint (Buffer, sizeof (Buffer), Format, Marker);\r
93 VA_END (Marker);\r
94\r
95 SendDebugMsgPacket (Buffer, AsciiStrLen (Buffer));\r
96}\r
97\r
98/**\r
99 Prints a debug message to the debug output device if the specified error level is enabled.\r
100\r
101 If any bit in ErrorLevel is also set in DebugPrintErrorLevelLib function \r
102 GetDebugPrintErrorLevel (), then print the message specified by Format and the \r
103 associated variable argument list to the debug output device.\r
104\r
105 If Format is NULL, then ASSERT().\r
106\r
107 @param[in] ErrorLevel The error level of the debug message.\r
108 @param[in] IsSend Flag of debug message to declare that the data is being sent or being received.\r
109 @param[in] Data Variable argument list whose contents are accessed \r
110 @param[in] Length based on the format string specified by Format.\r
111\r
112**/\r
113VOID\r
114EFIAPI\r
115DebugAgentDataMsgPrint (\r
116 IN UINT8 ErrorLevel,\r
117 IN BOOLEAN IsSend,\r
118 IN UINT8 *Data,\r
119 IN UINT8 Length \r
120 )\r
121{\r
122 DEBUG_AGENT_MAILBOX *Mailbox;\r
123 CHAR8 Buffer[DEBUG_DATA_MAXIMUM_REAL_DATA];\r
124 CHAR8 *DestBuffer;\r
125 UINTN Index;\r
126\r
127 Mailbox = GetMailboxPointer ();\r
128 //\r
129 // Check driver debug mask value and global mask\r
130 //\r
131 if ((ErrorLevel & Mailbox->DebugFlag.PrintErrorLevel) == 0) {\r
132 return;\r
133 }\r
134\r
135 DestBuffer = Buffer;\r
136 if (IsSend) {\r
137 DestBuffer += AsciiSPrint (DestBuffer, DEBUG_DATA_MAXIMUM_REAL_DATA, "Sent data [ ");\r
138 } else {\r
139 DestBuffer += AsciiSPrint (DestBuffer, DEBUG_DATA_MAXIMUM_REAL_DATA, "Received data [ ");\r
140 }\r
141\r
142 Index = 0;\r
143 while (TRUE) {\r
144 if (DestBuffer - Buffer > DEBUG_DATA_MAXIMUM_REAL_DATA - 6) {\r
145 //\r
146 // If there was no enough space in buffer, send out the debug message, \r
147 // reserving 6 bytes is for the last data and end characters "]\n".\r
148 //\r
149 SendDebugMsgPacket (Buffer, DestBuffer - Buffer);\r
150 DestBuffer = Buffer;\r
151 }\r
152 DestBuffer += AsciiSPrint (DestBuffer, DEBUG_DATA_MAXIMUM_REAL_DATA - (DestBuffer - Buffer), "%02x ", Data[Index]);\r
153 Index ++;\r
154 if (Index >= Length) {\r
155 //s\r
156 // The last character of debug message has been foramtted in buffer\r
157 //\r
158 DestBuffer += AsciiSPrint(DestBuffer, DEBUG_DATA_MAXIMUM_REAL_DATA - (DestBuffer - Buffer), "]\n");\r
159 SendDebugMsgPacket (Buffer, DestBuffer - Buffer);\r
160 break;\r
161 }\r
162 }\r
163}\r
164\r
165\r
166/**\r
167 Check if HOST is attached based on Mailbox.\r
168\r
169 @retval TRUE HOST is attached.\r
170 @retval FALSE HOST is not attached.\r
171\r
172**/\r
173BOOLEAN\r
174IsHostAttached (\r
175 VOID\r
176 )\r
177{\r
178 return (BOOLEAN) (GetMailboxPointer ()->DebugFlag.HostAttached == 1);\r
179}\r
180\r
181/**\r
182 Set HOST connect flag in Mailbox.\r
183\r
184 @param[in] Attached Attach status.\r
185 \r
186**/\r
187VOID\r
188SetHostAttached (\r
189 IN BOOLEAN Attached\r
190 )\r
191{\r
192 DebugAgentMsgPrint (DEBUG_AGENT_INFO, "Attach status is %d\n", Attached);\r
193 GetMailboxPointer ()->DebugFlag.HostAttached = Attached;\r
194}\r
195\r
196/**\r
197 Set debug setting of Debug Agent in Mailbox.\r
198\r
199 @param DebugSetting Pointer to Debug Setting defined by transfer protocol.\r
200 \r
201 @retval RETURN_SUCCESS The setting is set successfully.\r
202 @retval RETURN_UNSUPPORTED The Key value is not supported.\r
203\r
204**/\r
205RETURN_STATUS\r
206SetDebugSetting (\r
207 IN DEBUG_DATA_SET_DEBUG_SETTING *DebugSetting \r
208 )\r
209{\r
210 RETURN_STATUS Status;\r
211 DEBUG_AGENT_MAILBOX *Mailbox;\r
212\r
213 Mailbox = GetMailboxPointer ();\r
214\r
215 Status = RETURN_SUCCESS;\r
216 switch (DebugSetting->Key) {\r
217 case DEBUG_AGENT_SETTING_SMM_ENTRY_BREAK:\r
218 Mailbox->DebugFlag.BreakOnNextSmi = DebugSetting->Value;\r
219 break;\r
220 case DEBUG_AGENT_SETTING_PRINT_ERROR_LEVEL:\r
221 Mailbox->DebugFlag.PrintErrorLevel = DebugSetting->Value;\r
222 break;\r
223 default:\r
224 Status = RETURN_UNSUPPORTED;\r
225 }\r
226 return Status;\r
227}\r
228\r
229/**\r
230 Exectue GO command.\r
231\r
232 @param[in] CpuContext Pointer to saved CPU context.\r
233\r
234**/\r
235VOID\r
236CommandGo (\r
237 IN DEBUG_CPU_CONTEXT *CpuContext\r
238 )\r
239{\r
240 IA32_EFLAGS32 *Eflags;\r
241\r
242 Eflags = (IA32_EFLAGS32 *) &CpuContext->Eflags;\r
243 Eflags->Bits.TF = 0;\r
244 Eflags->Bits.RF = 1;\r
245}\r
246\r
247/**\r
248 Exectue Stepping command.\r
249\r
250 @param[in] CpuContext Pointer to saved CPU context.\r
251\r
252**/\r
253VOID\r
254CommandStepping (\r
255 IN DEBUG_CPU_CONTEXT *CpuContext\r
256 )\r
257{\r
258 IA32_EFLAGS32 *Eflags;\r
259\r
260 Eflags = (IA32_EFLAGS32 *) &CpuContext->Eflags;\r
261 Eflags->Bits.TF = 1;\r
262 Eflags->Bits.RF = 1;\r
263}\r
264\r
265/**\r
266 Set debug register for hardware breakpoint.\r
267\r
268 @param[in] CpuContext Pointer to saved CPU context.\r
269 @param[in] SetHwBreakpoint Hardware breakpoint to be set.\r
270\r
271**/\r
272VOID\r
273SetDebugRegister (\r
274 IN DEBUG_CPU_CONTEXT *CpuContext,\r
275 IN DEBUG_DATA_SET_HW_BREAKPOINT *SetHwBreakpoint\r
276 )\r
277{\r
278 UINT8 RegisterIndex;\r
279 UINTN Dr7Value;\r
280\r
281 RegisterIndex = SetHwBreakpoint->Type.Index;\r
282\r
283 //\r
284 // Set debug address\r
285 //\r
286 * ((UINTN *) &CpuContext->Dr0 + RegisterIndex) = (UINTN) SetHwBreakpoint->Address;\r
287\r
288 Dr7Value = CpuContext->Dr7;\r
289\r
290 //\r
291 // Enable Gx, Lx\r
292 //\r
293 Dr7Value |= 0x3 << (RegisterIndex * 2);\r
294 //\r
295 // Set RWx and Lenx\r
296 //\r
297 Dr7Value &= ~(0xf << (16 + RegisterIndex * 4));\r
298 Dr7Value |= (UINTN) ((SetHwBreakpoint->Type.Length << 2) | SetHwBreakpoint->Type.Access) << (16 + RegisterIndex * 4);\r
299 //\r
300 // Enable GE, LE\r
301 //\r
302 Dr7Value |= 0x300;\r
303\r
304 CpuContext->Dr7 = Dr7Value;\r
305}\r
306\r
307/**\r
308 Clear debug register for hardware breakpoint.\r
309\r
310 @param[in] CpuContext Pointer to saved CPU context.\r
311 @param[in] ClearHwBreakpoint Hardware breakpoint to be cleared.\r
312\r
313**/\r
314VOID\r
315ClearDebugRegister (\r
316 IN DEBUG_CPU_CONTEXT *CpuContext,\r
317 IN DEBUG_DATA_CLEAR_HW_BREAKPOINT *ClearHwBreakpoint\r
318 )\r
319{\r
320 if ((ClearHwBreakpoint->IndexMask & BIT0) != 0) {\r
321 CpuContext->Dr0 = 0;\r
322 CpuContext->Dr7 &= ~(0x3 << 0);\r
323 }\r
324 if ((ClearHwBreakpoint->IndexMask & BIT1) != 0) {\r
325 CpuContext->Dr1 = 0;\r
326 CpuContext->Dr7 &= ~(0x3 << 2);\r
327 }\r
328 if ((ClearHwBreakpoint->IndexMask & BIT2) != 0) {\r
329 CpuContext->Dr2 = 0;\r
330 CpuContext->Dr7 &= ~(0x3 << 4);\r
331 }\r
332 if ((ClearHwBreakpoint->IndexMask & BIT3) != 0) {\r
333 CpuContext->Dr3 = 0;\r
334 CpuContext->Dr7 &= ~(0x3 << 6);\r
335 }\r
336}\r
337\r
338\r
339/**\r
340 Return the offset of FP / MMX / XMM registers in the FPU saved state by register index.\r
341\r
342 @param[in] Index Register index.\r
343 @param[out] Width Register width returned.\r
344\r
345 @return Offset in the FPU Save State.\r
346\r
347**/\r
348UINT16\r
349ArchReadFxStatOffset (\r
350 IN UINT8 Index,\r
351 OUT UINT8 *Width\r
352 )\r
353{\r
354 if (Index < SOFT_DEBUGGER_REGISTER_ST0) {\r
355 switch (Index) {\r
356 case SOFT_DEBUGGER_REGISTER_FP_FCW:\r
357 *Width = (UINT8) sizeof (UINT16);\r
358 return OFFSET_OF(DEBUG_DATA_FX_SAVE_STATE, Fcw);\r
359\r
360 case SOFT_DEBUGGER_REGISTER_FP_FSW:\r
361 *Width = (UINT8) sizeof (UINT16);\r
362 return OFFSET_OF(DEBUG_DATA_FX_SAVE_STATE, Fsw);\r
363\r
364 case SOFT_DEBUGGER_REGISTER_FP_FTW:\r
365 *Width = (UINT8) sizeof (UINT16);\r
366 return OFFSET_OF(DEBUG_DATA_FX_SAVE_STATE, Ftw);\r
367\r
368 case SOFT_DEBUGGER_REGISTER_FP_OPCODE:\r
369 *Width = (UINT8) sizeof (UINT16);\r
370 return OFFSET_OF(DEBUG_DATA_FX_SAVE_STATE, Opcode);\r
371\r
372 case SOFT_DEBUGGER_REGISTER_FP_EIP:\r
373 *Width = (UINT8) sizeof (UINT32);\r
374 return OFFSET_OF(DEBUG_DATA_FX_SAVE_STATE, Eip);\r
375\r
376 case SOFT_DEBUGGER_REGISTER_FP_CS:\r
377 *Width = (UINT8) sizeof (UINT16);\r
378 return OFFSET_OF(DEBUG_DATA_FX_SAVE_STATE, Cs);\r
379\r
380 case SOFT_DEBUGGER_REGISTER_FP_DATAOFFSET:\r
381 *Width = (UINT8) sizeof (UINT32);\r
382 return OFFSET_OF(DEBUG_DATA_FX_SAVE_STATE, DataOffset);\r
383\r
384 case SOFT_DEBUGGER_REGISTER_FP_DS:\r
385 *Width = (UINT8) sizeof (UINT16);\r
386 return OFFSET_OF(DEBUG_DATA_FX_SAVE_STATE, Ds);\r
387\r
388 case SOFT_DEBUGGER_REGISTER_FP_MXCSR:\r
389 *Width = (UINT8) sizeof (UINT32);\r
390 return OFFSET_OF(DEBUG_DATA_FX_SAVE_STATE, Mxcsr);\r
391\r
392 case SOFT_DEBUGGER_REGISTER_FP_MXCSR_MASK:\r
393 *Width = (UINT8) sizeof (UINT32);\r
394 return OFFSET_OF(DEBUG_DATA_FX_SAVE_STATE, Mxcsr_Mask);\r
395 }\r
396 }\r
397\r
398 if (Index <= SOFT_DEBUGGER_REGISTER_ST7) {\r
399 *Width = 10;\r
400 } else if (Index <= SOFT_DEBUGGER_REGISTER_XMM15) {\r
401 *Width = 16;\r
402 } else {\r
403 //\r
404 // MMX register\r
405 //\r
406 *Width = 8;\r
407 Index -= SOFT_DEBUGGER_REGISTER_MM0 - SOFT_DEBUGGER_REGISTER_ST0;\r
408 }\r
409\r
410 return OFFSET_OF (DEBUG_DATA_FX_SAVE_STATE, St0Mm0) + (Index - SOFT_DEBUGGER_REGISTER_ST0) * 16;\r
411}\r
412\r
413/**\r
414 Return the pointer of the register value in the CPU saved context.\r
415\r
416 @param[in] CpuContext Pointer to saved CPU context.\r
417 @param[in] Index Register index value.\r
418 @param[out] Width Data width to read.\r
419\r
420 @return The pointer in the CPU saved context.\r
421\r
422**/\r
423UINT8 *\r
424ArchReadRegisterBuffer (\r
425 IN DEBUG_CPU_CONTEXT *CpuContext,\r
426 IN UINT8 Index,\r
427 OUT UINT8 *Width\r
428 )\r
429{\r
430 UINT8 *Buffer;\r
431\r
432 if (Index < SOFT_DEBUGGER_REGISTER_FP_BASE) {\r
433 Buffer = (UINT8 *) CpuContext + OFFSET_OF (DEBUG_CPU_CONTEXT, Dr0) + Index * sizeof (UINTN);\r
434 *Width = (UINT8) sizeof (UINTN);\r
435 } else {\r
436 //\r
437 // FPU/MMX/XMM registers\r
438 //\r
439 Buffer = (UINT8 *) CpuContext + OFFSET_OF (DEBUG_CPU_CONTEXT, FxSaveState) + ArchReadFxStatOffset (Index, Width);\r
440 }\r
441\r
442 return Buffer;\r
443}\r
444\r
445/**\r
446 Send the packet without data to HOST.\r
447\r
448 @param[in] CommandType Type of Command.\r
449\r
450**/\r
451VOID\r
452SendPacketWithoutData (\r
453 IN UINT8 CommandType\r
454 )\r
455{\r
456 DEBUG_PACKET_HEADER DebugHeader;\r
457 DEBUG_PORT_HANDLE Handle;\r
458\r
459 Handle = GetDebugPortHandle();\r
460\r
461 DebugHeader.StartSymbol = DEBUG_STARTING_SYMBOL_NORMAL;\r
462 DebugHeader.Command = CommandType;\r
463 DebugHeader.Length = sizeof (DEBUG_PACKET_HEADER);\r
464 DebugHeader.CheckSum = 0;\r
465 DebugHeader.CheckSum = CalculateCheckSum8 ((UINT8 *)&DebugHeader, sizeof (DEBUG_PACKET_HEADER));\r
466\r
467 DebugAgentDataMsgPrint (DEBUG_AGENT_VERBOSE, TRUE, (UINT8 *) &DebugHeader, DebugHeader.Length);\r
468 DebugPortWriteBuffer (Handle, (UINT8 *) &DebugHeader, DebugHeader.Length);\r
469}\r
470\r
471/**\r
472 Send acknowledge packet to HOST.\r
473\r
474 @param[in] AckCommand Type of Acknowledge packet.\r
475\r
476**/\r
477VOID\r
478SendAckPacket (\r
479 IN UINT8 AckCommand\r
480 )\r
481{\r
482 if (AckCommand != DEBUG_COMMAND_OK) {\r
483 DebugAgentMsgPrint (DEBUG_AGENT_ERROR, "Send ACK(%d)\n", AckCommand);\r
484 }\r
485 SendPacketWithoutData (AckCommand);\r
486}\r
487\r
488/**\r
489 Receive acknowledge packet from HOST in specified time.\r
490\r
491 @param[out] Ack Returned acknowlege type from HOST.\r
492 @param[in] Timeout Time out value to wait for acknowlege from HOST.\r
493 The unit is microsecond.\r
494 @param[out] BreakReceived If BreakReceived is not NULL,\r
495 TRUE is retured if break-in symbol received.\r
496 FALSE is retured if break-in symbol not received.\r
497 @param[out] CheckSumStatus If CheckSumStatus is not NULL,\r
498 RETURN_SUCCESS CheckSum is OK.\r
499 RETURN_NOT_FOUND Not find the CheckSum field.\r
500\r
501 @retval RETRUEN_SUCCESS Succeed to receive acknowlege packet from HOST,\r
502 the type of acknowlege packet saved in Ack.\r
503 @retval RETURN_TIMEOUT Specified timeout value was up.\r
504\r
505**/\r
506RETURN_STATUS\r
507ReceiveAckPacket (\r
508 OUT UINT8 *Ack,\r
509 IN UINTN Timeout,\r
510 OUT BOOLEAN *BreakReceived, OPTIONAL\r
511 OUT RETURN_STATUS *CheckSumStatus OPTIONAL\r
512 )\r
513{\r
514 DEBUG_PACKET_HEADER DebugHeader;\r
515 DEBUG_PORT_HANDLE Handle;\r
516\r
517 Handle = GetDebugPortHandle();\r
518\r
519 while (TRUE) {\r
520 if (DebugPortReadBuffer (Handle, (UINT8 *) &DebugHeader.StartSymbol, sizeof (DebugHeader.StartSymbol), Timeout) == 0) {\r
521 return RETURN_TIMEOUT;\r
522 }\r
523 if (DebugHeader.StartSymbol == DEBUG_STARTING_SYMBOL_BREAK) {\r
524 if (BreakReceived != NULL) {\r
525 SendAckPacket (DEBUG_COMMAND_HALT_DEFERRED);\r
526 *BreakReceived = TRUE;\r
527 }\r
528 }\r
529 if (DebugHeader.StartSymbol == DEBUG_STARTING_SYMBOL_NORMAL) {\r
530 break;\r
531 }\r
532 DebugAgentMsgPrint (DEBUG_AGENT_ERROR, "Invalid start symbol received [%02x]\n", DebugHeader.StartSymbol);\r
533 }\r
534 //\r
535 // Read ACK packet header till field Length (not including StartSymbol and CheckSum)\r
536 //\r
537 DebugHeader.Length = 0;\r
538 if (DebugPortReadBuffer (\r
539 Handle,\r
540 (UINT8 *)&DebugHeader.Command,\r
541 OFFSET_OF (DEBUG_PACKET_HEADER, Length) + sizeof (DebugHeader.Length) - sizeof (DebugHeader.StartSymbol),\r
542 Timeout\r
543 ) == 0) {\r
544 return RETURN_TIMEOUT;\r
545 }\r
546\r
547 if (DebugHeader.Length == 0) {\r
548 //\r
549 // The CheckSum field does not exist\r
550 //\r
551 if (CheckSumStatus != NULL) {\r
552 *CheckSumStatus = RETURN_NOT_FOUND;\r
553 }\r
554 } else {\r
555 if (CheckSumStatus != NULL) {\r
556 *CheckSumStatus = RETURN_SUCCESS;\r
557 }\r
558 if (DebugPortReadBuffer (Handle, &DebugHeader.CheckSum, sizeof (DebugHeader.CheckSum), Timeout) == 0) {\r
559 return RETURN_TIMEOUT;\r
560 }\r
561 }\r
562\r
563 DebugAgentDataMsgPrint (DEBUG_AGENT_VERBOSE, FALSE, (UINT8 *)&DebugHeader, DebugHeader.Length);\r
564 *Ack = DebugHeader.Command;\r
565 return RETURN_SUCCESS;\r
566}\r
567\r
568/**\r
569 Receive acknowledge packet OK from HOST in specified time.\r
570\r
571 @param[in] Command The command type issued by TARGET.\r
572 @param[in] Timeout Time out value to wait for acknowlege from HOST.\r
573 The unit is microsecond.\r
574 @param[out] BreakReceived If BreakReceived is not NULL,\r
575 TRUE is retured if break-in symbol received.\r
576 FALSE is retured if break-in symbol not received.\r
577 @param[out] CheckSumStatus If CheckSumStatus is not NULL,\r
578 RETURN_SUCCESS CheckSum is OK.\r
579 RETURN_NOT_FOUND Not find the CheckSum field.\r
580\r
581 @retval RETRUEN_SUCCESS Succeed to receive acknowlege packet from HOST,\r
582 the type of acknowlege packet saved in Ack.\r
583 @retval RETURN_TIMEOUT Specified timeout value was up.\r
584\r
585**/\r
586RETURN_STATUS\r
587SendCommandAndWaitForAckOK (\r
588 IN UINT8 Command,\r
589 IN UINTN Timeout,\r
590 OUT BOOLEAN *BreakReceived, OPTIONAL\r
591 OUT RETURN_STATUS *CheckSumStatus OPTIONAL\r
592 )\r
593{\r
594 RETURN_STATUS Status;\r
595 UINT8 Ack;\r
596 \r
597 while (TRUE) {\r
598 SendPacketWithoutData (Command);\r
599 while (TRUE) {\r
600 Status = ReceiveAckPacket (&Ack, Timeout, BreakReceived, CheckSumStatus);\r
601 if (Status == RETURN_SUCCESS && Ack == DEBUG_COMMAND_RESEND) {\r
602 //\r
603 // Resend the last command\r
604 //\r
605 break;\r
606 } \r
607 if ((Status == RETURN_SUCCESS && Ack == DEBUG_COMMAND_OK) ||\r
608 Status == RETURN_TIMEOUT) {\r
609 //\r
610 // Received Ack OK or timeout\r
611 //\r
612 return Status;\r
613 } \r
614 }\r
615 }\r
616}\r
617\r
618/**\r
619 Receive valid packet from HOST.\r
620\r
621 @param[out] InputPacket Buffer to receive packet.\r
622 @param[out] BreakReceived TRUE means break-in symbol received.\r
623 FALSE means break-in symbol not received.\r
624\r
625 @retval RETURN_SUCCESS A valid package was reveived in InputPacket.\r
626 @retval RETURN_TIMEOUT Timeout occurs.\r
627\r
628**/\r
629RETURN_STATUS\r
630ReceivePacket (\r
631 OUT UINT8 *InputPacket,\r
632 OUT BOOLEAN *BreakReceived\r
633 )\r
634{\r
635 DEBUG_PACKET_HEADER *DebugHeader;\r
636 UINTN Received;\r
637 DEBUG_PORT_HANDLE Handle;\r
638 UINT8 CheckSum;\r
639\r
640 Handle = GetDebugPortHandle();\r
641 \r
642 DebugHeader = (DEBUG_PACKET_HEADER *) InputPacket;\r
643 while (TRUE) {\r
644 //\r
645 // Find the valid start symbol\r
646 //\r
647 DebugPortReadBuffer (Handle, &DebugHeader->StartSymbol, sizeof (DebugHeader->StartSymbol), 0);\r
648\r
649 if (DebugHeader->StartSymbol == DEBUG_STARTING_SYMBOL_BREAK) {\r
650 *BreakReceived = TRUE;\r
651 SendAckPacket (DEBUG_COMMAND_HALT_DEFERRED);\r
652 }\r
653\r
654 if (DebugHeader->StartSymbol != DEBUG_STARTING_SYMBOL_NORMAL) {\r
655 DebugAgentMsgPrint (DEBUG_AGENT_ERROR, "Invalid start symbol received [%02x]\n", DebugHeader->StartSymbol);\r
656 continue;\r
657 }\r
658\r
659 //\r
660 // Read Package header except for checksum\r
661 //\r
662 Received = DebugPortReadBuffer (\r
663 Handle,\r
664 &DebugHeader->Command,\r
665 OFFSET_OF (DEBUG_PACKET_HEADER, Length) + sizeof (DebugHeader->Length) - sizeof (DebugHeader->StartSymbol),\r
666 0\r
667 );\r
668 if (Received == 0) {\r
669 return RETURN_TIMEOUT;\r
670 }\r
671\r
672 //\r
673 // Read the payload data include the checksum\r
674 //\r
675 Received = DebugPortReadBuffer (Handle, &DebugHeader->CheckSum, DebugHeader->Length - OFFSET_OF (DEBUG_PACKET_HEADER, CheckSum), 0);\r
676 if (Received == 0) {\r
677 return RETURN_TIMEOUT;\r
678 }\r
679 //\r
680 // Calculate the checksum of Debug Packet\r
681 //\r
682 CheckSum = CalculateCheckSum8 ((UINT8 *) DebugHeader, DebugHeader->Length);\r
683 if (CheckSum == 0) {\r
684 break;\r
685 }\r
686 DebugAgentMsgPrint (DEBUG_AGENT_WARNING, "CheckSum Error (Caculated checksum is %x, received checksum is %x\n", CheckSum, DebugHeader->CheckSum);\r
687 DebugAgentMsgPrint (DEBUG_AGENT_WARNING, "Send DEBUG_COMMAND_RESEND command.\n");\r
688 SendAckPacket (DEBUG_COMMAND_RESEND);\r
689 }\r
690\r
691 DebugAgentDataMsgPrint (DEBUG_AGENT_VERBOSE, FALSE, (UINT8 *) DebugHeader, DebugHeader->Length);\r
692\r
693 return RETURN_SUCCESS;\r
694}\r
695\r
696/**\r
697 Get current break cause.\r
698\r
699 @param[in] Vector Vector value of exception or interrupt.\r
700 @param[in] CpuContext Pointer to save CPU context.\r
701\r
702 @return The type of break cause defined by XXXX\r
703\r
704**/\r
705UINT8\r
706GetBreakCause (\r
707 IN UINTN Vector,\r
708 IN DEBUG_CPU_CONTEXT *CpuContext\r
709 )\r
710{\r
711 UINT8 Cause;\r
712\r
713 Cause = DEBUG_DATA_BREAK_CAUSE_UNKNOWN;\r
714\r
715 switch (Vector) {\r
716 case DEBUG_INT1_VECTOR:\r
717 case DEBUG_INT3_VECTOR:\r
718\r
719 if (Vector == DEBUG_INT1_VECTOR) {\r
720 //\r
721 // INT 1\r
722 //\r
723 if ((CpuContext->Dr6 & BIT14) != 0) {\r
724 Cause = DEBUG_DATA_BREAK_CAUSE_STEPPING;\r
725 //\r
726 // If it's single step, no need to check DR0, to ensure single step work in PeCoffExtraActionLib\r
727 // (right after triggering a breakpoint to report image load/unload).\r
728 //\r
729 return Cause;\r
730\r
731 } else {\r
732 Cause = DEBUG_DATA_BREAK_CAUSE_HW_BREAKPOINT;\r
733 }\r
734 } else {\r
735 //\r
736 // INT 3\r
737 //\r
738 Cause = DEBUG_DATA_BREAK_CAUSE_SW_BREAKPOINT;\r
739 }\r
740\r
741 switch (CpuContext->Dr0) {\r
742 case IMAGE_LOAD_SIGNATURE:\r
743 case IMAGE_UNLOAD_SIGNATURE:\r
744\r
745 if (CpuContext->Dr3 == IO_PORT_BREAKPOINT_ADDRESS) {\r
746\r
747 Cause = (UINT8) ((CpuContext->Dr0 == IMAGE_LOAD_SIGNATURE) ? \r
748 DEBUG_DATA_BREAK_CAUSE_IMAGE_LOAD : DEBUG_DATA_BREAK_CAUSE_IMAGE_UNLOAD);\r
749 }\r
750 break;\r
751\r
752 case SOFT_INTERRUPT_SIGNATURE:\r
753 \r
754 if (CpuContext->Dr1 == MEMORY_READY_SIGNATURE) {\r
755 Cause = DEBUG_DATA_BREAK_CAUSE_MEMORY_READY;\r
756 CpuContext->Dr0 = 0;\r
757 } else if (CpuContext->Dr1 == SYSTEM_RESET_SIGNATURE) {\r
758 Cause = DEBUG_DATA_BREAK_CAUSE_SYSTEM_RESET;\r
759 CpuContext->Dr0 = 0;\r
760 }\r
761 break;\r
762\r
763 default:\r
764 break;\r
765\r
766 }\r
767\r
768 break;\r
769\r
770 case DEBUG_TIMER_VECTOR:\r
771 Cause = DEBUG_DATA_BREAK_CAUSE_USER_HALT;\r
772 break;\r
773\r
774 default:\r
775 if (Vector < 20) {\r
776 if (GetMailboxPointer()->DebugFlag.SteppingFlag == 1) {\r
777 //\r
778 // If stepping command is executing\r
779 //\r
780 Cause = DEBUG_DATA_BREAK_CAUSE_STEPPING;\r
781 } else {\r
782 Cause = DEBUG_DATA_BREAK_CAUSE_EXCEPTION;\r
783 }\r
784 }\r
785 break;\r
786 }\r
787\r
788 return Cause;\r
789}\r
790\r
791/**\r
792 Send command packet with data to HOST.\r
793\r
794 @param[in] Command Command type.\r
795 @param[in] Data Pointer to response data buffer.\r
796 @param[in] DataSize Size of response data in byte.\r
797\r
798 @retval RETURN_SUCCESS Response data was sent successfully.\r
799 @retval RETURN_DEVICE_ERROR Cannot receive DEBUG_COMMAND_OK from HOST.\r
800\r
801**/\r
802RETURN_STATUS\r
803SendCommandWithDataPacket (\r
804 IN UINT8 Command,\r
805 IN UINT8 *Data,\r
806 IN UINT16 DataSize\r
807 )\r
808{\r
809 DEBUG_PACKET_HEADER *DebugHeader;\r
810 BOOLEAN LastPacket;\r
811 UINT8 Ack;\r
812 UINT8 DebugPacket[DEBUG_DATA_UPPER_LIMIT];\r
813 DEBUG_PORT_HANDLE Handle;\r
814\r
815 Handle = GetDebugPortHandle();\r
816\r
817 DebugHeader = (DEBUG_PACKET_HEADER *) &DebugPacket;\r
818 DebugHeader->StartSymbol = DEBUG_STARTING_SYMBOL_NORMAL;\r
819\r
820 while (TRUE) {\r
821 if (DataSize <= DEBUG_DATA_MAXIMUM_REAL_DATA) {\r
822 LastPacket = TRUE;\r
823 DebugHeader->Command = Command;\r
824 DebugHeader->Length = (UINT8) (DataSize + sizeof (DEBUG_PACKET_HEADER));\r
825 DebugHeader->CheckSum = 0;\r
826 CopyMem (DebugHeader + 1, Data, DataSize);\r
827\r
828 } else {\r
829 LastPacket = FALSE;\r
830 DebugHeader->Command = DEBUG_COMMAND_IN_PROGRESS;\r
831 DebugHeader->Length = DEBUG_DATA_MAXIMUM_REAL_DATA + sizeof (DEBUG_PACKET_HEADER);\r
832 DebugHeader->CheckSum = 0;\r
833 CopyMem (DebugHeader + 1, Data, DEBUG_DATA_MAXIMUM_REAL_DATA);\r
834 }\r
835\r
836 //\r
837 // Calculate and fill the checksum\r
838 //\r
839 DebugHeader->CheckSum = CalculateCheckSum8 ((UINT8 *) DebugHeader, DebugHeader->Length);\r
840\r
841 DebugAgentDataMsgPrint (DEBUG_AGENT_VERBOSE, TRUE, (UINT8 *) DebugHeader, DebugHeader->Length);\r
842 \r
843 DebugPortWriteBuffer (Handle, (UINT8 *) DebugHeader, DebugHeader->Length);\r
844\r
845 ReceiveAckPacket(&Ack, 0, NULL, NULL);\r
846 switch (Ack) {\r
847 case DEBUG_COMMAND_RESEND:\r
848 //\r
849 // Send the packet again\r
850 //\r
851 DebugAgentMsgPrint (DEBUG_AGENT_WARNING, "Received DEBUG_COMMAND_RESEND.\n");\r
852 break;\r
853\r
854 case DEBUG_COMMAND_CONTINUE:\r
855 //\r
856 // Send the rest packet\r
857 //\r
858 Data += DEBUG_DATA_MAXIMUM_REAL_DATA;\r
859 DataSize -= DEBUG_DATA_MAXIMUM_REAL_DATA;\r
860 break;\r
861\r
862 case DEBUG_COMMAND_OK:\r
863 if (LastPacket) {\r
864 //\r
865 // If this is the last packet, return RETURN_SUCCESS.\r
866 //\r
867 return RETURN_SUCCESS;\r
868 } else {\r
869 return RETURN_DEVICE_ERROR;\r
870 }\r
871\r
872 default:\r
873 return RETURN_DEVICE_ERROR;\r
874\r
875 }\r
876 }\r
877}\r
878\r
879/**\r
880 Send packet with response data to HOST.\r
881\r
882 @param[in] Data Pointer to response data buffer.\r
883 @param[in] DataSize Size of response data in byte.\r
884\r
885 @retval RETURN_SUCCESS Response data was sent successfully.\r
886 @retval RETURN_DEVICE_ERROR Cannot receive DEBUG_COMMAND_OK from HOST.\r
887\r
888**/\r
889RETURN_STATUS\r
890SendDataResponsePacket (\r
891 IN UINT8 *Data,\r
892 IN UINT16 DataSize\r
893 )\r
894{\r
895 return SendCommandWithDataPacket (DEBUG_COMMAND_OK, Data, DataSize);\r
896}\r
897\r
898/**\r
899 Send break cause packet to HOST.\r
900\r
901 @param[in] Vector Vector value of exception or interrutp.\r
902 @param[in] CpuContext Pointer to save CPU context.\r
903\r
904 @retval RETURN_SUCCESS Response data was sent successfully.\r
905 @retval RETURN_DEVICE_ERROR Cannot receive DEBUG_COMMAND_OK from HOST.\r
906\r
907**/\r
908RETURN_STATUS\r
909SendBreakCausePacket (\r
910 IN UINTN Vector,\r
911 IN DEBUG_CPU_CONTEXT *CpuContext\r
912 )\r
913{\r
914 DEBUG_DATA_RESPONSE_BREAK_CAUSE DebugDataBreakCause;\r
915\r
916 DebugDataBreakCause.StopAddress = CpuContext->Eip;\r
917 DebugDataBreakCause.Cause = GetBreakCause (Vector, CpuContext);\r
918\r
919 return SendDataResponsePacket ((UINT8 *) &DebugDataBreakCause, (UINT16) sizeof (DEBUG_DATA_RESPONSE_BREAK_CAUSE));\r
920}\r
921\r
922/**\r
923 Try to attach the HOST.\r
924 \r
925 Send init break packet to HOST:\r
926 If no acknowlege received in specified Timeout, return RETURN_TIMEOUT. \r
927 If received acknowlege, check the revision of HOST. \r
928 Set Attach Flag if attach successfully. \r
929 \r
930 @param[in] Timeout Time out value to wait for acknowlege from HOST.\r
931 The unit is microsecond.\r
932 @param[out] BreakReceived If BreakReceived is not NULL,\r
933 TRUE is retured if break-in symbol received.\r
934 FALSE is retured if break-in symbol not received.\r
935**/\r
936RETURN_STATUS\r
937AttachHost (\r
938 IN UINTN Timeout,\r
939 OUT BOOLEAN *BreakReceived\r
940 )\r
941{\r
942 RETURN_STATUS Status;\r
943 DEBUG_PORT_HANDLE Handle;\r
944 RETURN_STATUS CheckSumStatus;\r
945\r
946 Handle = GetDebugPortHandle();\r
947 \r
948 //\r
949 // Send init break and wait ack in Timeout\r
950 //\r
951 DebugPortWriteBuffer (Handle, (UINT8 *) mErrorMsgSendInitPacket, AsciiStrLen (mErrorMsgSendInitPacket));\r
952 Status = SendCommandAndWaitForAckOK (DEBUG_COMMAND_INIT_BREAK, Timeout, BreakReceived, &CheckSumStatus);\r
953 if (RETURN_ERROR (Status)) {\r
954 DebugPortWriteBuffer (Handle, (UINT8 *) mErrorMsgConnectFail, AsciiStrLen (mErrorMsgConnectFail));\r
955 return Status;\r
956 }\r
957 \r
958 if (CheckSumStatus == RETURN_NOT_FOUND) {\r
959 //\r
960 // If the CheckSum field does not exist in Debug Packet,\r
961 // the HOST should be running with 0.1 transfer protocol.\r
962 // It could be UDK Debugger for Windows v1.1 or for Linux v0.8.\r
963 //\r
964 DebugPortWriteBuffer (Handle, (UINT8 *) mErrorMsgVersionAlert, AsciiStrLen (mErrorMsgVersionAlert));\r
965 CpuDeadLoop ();\r
966 }\r
967\r
968 DebugPortWriteBuffer (Handle, (UINT8 *) mErrorMsgConnectOK, AsciiStrLen (mErrorMsgConnectOK));\r
969 //\r
970 // Set Attach flag\r
971 //\r
972 SetHostAttached (TRUE);\r
973\r
974 return Status;\r
975}\r
976\r
977/**\r
978 Send Break point packet to HOST. \r
979 \r
980 Only the first breaking processor could sent BREAK_POINT packet.\r
981 \r
982 @param[in] ProcessorIndex Processor index value.\r
983 @param[out] BreakReceived If BreakReceived is not NULL,\r
984 TRUE is retured if break-in symbol received.\r
985 FALSE is retured if break-in symbol not received.\r
986 \r
987**/\r
988VOID\r
989SendBreakPacketToHost (\r
990 IN UINT32 ProcessorIndex,\r
991 OUT BOOLEAN *BreakReceived\r
992 )\r
993{\r
994 UINT8 InputCharacter;\r
995 DEBUG_PORT_HANDLE Handle;\r
996 \r
997 Handle = GetDebugPortHandle();\r
998 \r
999 if (IsHostAttached ()) {\r
1000 DebugAgentMsgPrint (DEBUG_AGENT_INFO, "processor[%x]:Send Break Packet to HOST.\n", ProcessorIndex);\r
1001 SendCommandAndWaitForAckOK (DEBUG_COMMAND_BREAK_POINT, 0, BreakReceived, NULL);\r
1002 } else {\r
1003 DebugAgentMsgPrint (DEBUG_AGENT_INFO, "processor[%x]:Try to attach HOST.\n", ProcessorIndex);\r
1004 //\r
1005 // If HOST is not attached, try to attach it firstly.\r
1006 //\r
1007 //\r
1008 // Poll Attach symbols from HOST and ack OK\r
1009 // \r
1010 do {\r
1011 DebugPortReadBuffer (Handle, &InputCharacter, 1, 0);\r
1012 } while (InputCharacter != DEBUG_STARTING_SYMBOL_ATTACH);\r
1013 SendAckPacket (DEBUG_COMMAND_OK);\r
1014 \r
1015 //\r
1016 // Try to attach HOST\r
1017 //\r
1018 while (AttachHost (0, NULL) != RETURN_SUCCESS);\r
1019 \r
1020 }\r
1021}\r
1022\r
1023/**\r
1024 The main function to process communication with HOST.\r
1025\r
1026 It received the command packet from HOST, and sent response data packet to HOST.\r
1027\r
1028 @param[in] Vector Vector value of exception or interrutp.\r
1029 @param[in, out] CpuContext Pointer to saved CPU context.\r
1030 @param[in] BreakReceived TRUE means break-in symbol received.\r
1031 FALSE means break-in symbol not received.\r
1032\r
1033**/\r
1034VOID\r
1035CommandCommunication (\r
1036 IN UINTN Vector,\r
1037 IN OUT DEBUG_CPU_CONTEXT *CpuContext,\r
1038 IN BOOLEAN BreakReceived\r
1039 )\r
1040{\r
1041 RETURN_STATUS Status;\r
1042 UINT8 InputPacketBuffer[DEBUG_DATA_UPPER_LIMIT];\r
1043 DEBUG_PACKET_HEADER *DebugHeader;\r
1044 UINT8 Width;\r
1045 UINT8 Data8;\r
1046 UINT32 Data32;\r
1047 UINT64 Data64;\r
1048 DEBUG_DATA_READ_MEMORY *MemoryRead;\r
1049 DEBUG_DATA_WRITE_MEMORY *MemoryWrite;\r
1050 DEBUG_DATA_READ_IO *IoRead;\r
1051 DEBUG_DATA_WRITE_IO *IoWrite;\r
1052 DEBUG_DATA_READ_REGISTER *RegisterRead;\r
1053 DEBUG_DATA_WRITE_REGISTER *RegisterWrite;\r
1054 UINT8 *RegisterBuffer;\r
1055 DEBUG_DATA_READ_MSR *MsrRegisterRead;\r
1056 DEBUG_DATA_WRITE_MSR *MsrRegisterWrite;\r
1057 DEBUG_DATA_CPUID *Cpuid;\r
1058 DEBUG_DATA_RESPONSE_CPUID CpuidResponse;\r
1059 DEBUG_DATA_SEARCH_SIGNATURE *SearchSignature;\r
1060 DEBUG_DATA_RESPONSE_GET_EXCEPTION Exception;\r
1061 DEBUG_DATA_RESPONSE_GET_REVISION DebugAgentRevision;\r
1062 DEBUG_DATA_SET_VIEWPOINT *SetViewPoint;\r
1063 BOOLEAN HaltDeferred;\r
1064 UINT32 ProcessorIndex;\r
1065 DEBUG_PORT_HANDLE Handle;\r
1066 DEBUG_AGENT_EXCEPTION_BUFFER AgentExceptionBuffer;\r
1067 UINT32 IssuedViewPoint;\r
1068\r
1069 ProcessorIndex = 0;\r
1070 IssuedViewPoint = 0;\r
1071 HaltDeferred = BreakReceived;\r
1072\r
1073 if (MultiProcessorDebugSupport) {\r
1074 ProcessorIndex = GetProcessorIndex ();\r
1075 SetCpuStopFlagByIndex (ProcessorIndex, TRUE);\r
1076 if (mDebugMpContext.ViewPointIndex == ProcessorIndex) {\r
1077 //\r
1078 // Only the current view processor could set AgentInProgress Flag. \r
1079 //\r
1080 IssuedViewPoint = ProcessorIndex;\r
1081 }\r
1082 }\r
1083\r
1084 if (IssuedViewPoint == ProcessorIndex) {\r
1085 //\r
1086 // Set AgentInProgress Flag.\r
1087 //\r
1088 GetMailboxPointer()->DebugFlag.AgentInProgress = 1;\r
1089 } \r
1090\r
1091 Handle = GetDebugPortHandle();\r
1092\r
1093 while (TRUE) {\r
1094\r
1095 if (MultiProcessorDebugSupport) {\r
1096 //\r
1097 // Check if the current processor is HOST view point\r
1098 //\r
1099 if (mDebugMpContext.ViewPointIndex != ProcessorIndex) {\r
1100 if (mDebugMpContext.RunCommandSet) {\r
1101 //\r
1102 // If HOST view point sets RUN flag, run GO command to leave\r
1103 //\r
1104 SetCpuStopFlagByIndex (ProcessorIndex, FALSE);\r
1105 CommandGo (CpuContext);\r
1106 break;\r
1107 } else {\r
1108 //\r
1109 // Run into loop again\r
1110 //\r
1111 CpuPause ();\r
1112 continue;\r
1113 }\r
1114 }\r
1115 }\r
1116\r
1117 AcquireDebugPortControl ();\r
1118\r
1119 Status = ReceivePacket (InputPacketBuffer, &BreakReceived);\r
1120\r
1121 if (BreakReceived) {\r
1122 HaltDeferred = TRUE;\r
1123 BreakReceived = FALSE;\r
1124 }\r
1125\r
1126 if (Status != RETURN_SUCCESS) {\r
1127 ReleaseDebugPortControl ();\r
1128 continue;\r
1129 }\r
1130\r
1131 Data8 = 1;\r
1132\r
1133 DebugHeader =(DEBUG_PACKET_HEADER *) InputPacketBuffer;\r
1134\r
1135 GetMailboxPointer()->ExceptionBufferPointer = (UINT64)(UINTN) &AgentExceptionBuffer.JumpBuffer;\r
1136 //\r
1137 // Save CPU content before executing HOST commond\r
1138 //\r
1139 if (SetJump (&AgentExceptionBuffer.JumpBuffer) != 0) {\r
1140 //\r
1141 // If HOST command failed, continue to wait for HOST's next command\r
1142 // If needed, agent could send exception info to HOST.\r
1143 //\r
1144 SendAckPacket (DEBUG_COMMAND_ABORT);\r
1145 ReleaseDebugPortControl ();\r
1146 continue;\r
1147 }\r
1148\r
1149 DebugAgentMsgPrint (DEBUG_AGENT_INFO, "Processor[%x]:Received one command(%x)\n", mDebugMpContext.ViewPointIndex, DebugHeader->Command);\r
1150 \r
1151 switch (DebugHeader->Command) {\r
1152\r
1153 case DEBUG_COMMAND_RESET:\r
1154 SendAckPacket (DEBUG_COMMAND_OK);\r
1155 ReleaseDebugPortControl ();\r
1156\r
1157 ResetCold ();\r
1158 //\r
1159 // Assume system resets in 2 seconds, otherwise send TIMEOUT packet.\r
1160 // PCD can be used if 2 seconds isn't long enough for some platforms.\r
1161 //\r
1162 MicroSecondDelay (2000000);\r
1163 SendAckPacket (DEBUG_COMMAND_TIMEOUT);\r
1164 break;\r
1165\r
1166 case DEBUG_COMMAND_GO:\r
1167 CommandGo (CpuContext);\r
1168 //\r
1169 // Clear Dr0 to avoid to be recognized as IMAGE_LOAD/_UNLOAD again when hitting a breakpoint after GO\r
1170 // If HOST changed Dr0 before GO, we will not change Dr0 here\r
1171 //\r
1172 Data8 = GetBreakCause (Vector, CpuContext);\r
1173 if (Data8 == DEBUG_DATA_BREAK_CAUSE_IMAGE_LOAD || Data8 == DEBUG_DATA_BREAK_CAUSE_IMAGE_UNLOAD) {\r
1174 CpuContext->Dr0 = 0;\r
1175 }\r
1176 //\r
1177 // Clear Stepping Flag\r
1178 //\r
1179 GetMailboxPointer()->DebugFlag.SteppingFlag = 0;\r
1180 \r
1181 if (!HaltDeferred) {\r
1182 //\r
1183 // If no HALT command received when being in-active mode\r
1184 //\r
1185 if (MultiProcessorDebugSupport) {\r
1186 Data32 = FindNextPendingBreakCpu ();\r
1187 if (Data32 != -1) {\r
1188 //\r
1189 // If there are still others processors being in break state, \r
1190 // send OK packet to HOST to finish this go command\r
1191 //\r
1192 SendAckPacket (DEBUG_COMMAND_OK);\r
1193 CpuPause ();\r
1194 //\r
1195 // Set current view to the next breaking processor\r
1196 //\r
1197 mDebugMpContext.ViewPointIndex = Data32;\r
1198 mDebugMpContext.BreakAtCpuIndex = mDebugMpContext.ViewPointIndex;\r
1199 SetCpuBreakFlagByIndex (mDebugMpContext.ViewPointIndex, FALSE);\r
1200 //\r
1201 // Send break packet to HOST to let HOST break again\r
1202 //\r
1203 SendBreakPacketToHost (0, &BreakReceived);\r
1204 //\r
1205 // Continue to run into loop to read command packet from HOST\r
1206 //\r
1207 ReleaseDebugPortControl (); \r
1208 break;\r
1209 }\r
1210\r
1211 //\r
1212 // If no else processor break, set stop bitmask,\r
1213 // and set Running flag for all processors.\r
1214 //\r
1215 SetCpuStopFlagByIndex (ProcessorIndex, FALSE);\r
1216 SetCpuRunningFlag (TRUE);\r
1217 CpuPause ();\r
1218 //\r
1219 // Wait for all processors are in running state \r
1220 //\r
1221 while (TRUE) {\r
1222 if (IsAllCpuRunning ()) {\r
1223 break;\r
1224 }\r
1225 }\r
1226 //\r
1227 // Set BSP to be current view point.\r
1228 //\r
1229 SetDebugViewPoint (mDebugMpContext.BspIndex);\r
1230 CpuPause ();\r
1231 //\r
1232 // Clear breaking processor index and running flag\r
1233 //\r
1234 mDebugMpContext.BreakAtCpuIndex = (UINT32) (-1);\r
1235 SetCpuRunningFlag (FALSE);\r
1236 }\r
1237\r
1238 //\r
1239 // Send OK packet to HOST to finish this go command\r
1240 //\r
1241 SendAckPacket (DEBUG_COMMAND_OK);\r
1242\r
1243 ReleaseDebugPortControl ();\r
1244\r
1245 return;\r
1246\r
1247 } else {\r
1248 //\r
1249 // If reveived HALT command, need to defer the GO command\r
1250 //\r
1251 SendAckPacket (DEBUG_COMMAND_HALT_PROCESSED);\r
1252 HaltDeferred = FALSE;\r
1253\r
1254 Vector = DEBUG_TIMER_VECTOR;\r
1255 }\r
1256 break;\r
1257\r
1258 case DEBUG_COMMAND_BREAK_CAUSE:\r
1259\r
1260 if (MultiProcessorDebugSupport && ProcessorIndex != mDebugMpContext.BreakAtCpuIndex) {\r
1261 Status = SendBreakCausePacket (DEBUG_TIMER_VECTOR, CpuContext);\r
1262\r
1263 } else {\r
1264 Status = SendBreakCausePacket (Vector, CpuContext);\r
1265 }\r
1266\r
1267 break;\r
1268\r
1269 case DEBUG_COMMAND_SET_HW_BREAKPOINT:\r
1270 SetDebugRegister (CpuContext, (DEBUG_DATA_SET_HW_BREAKPOINT *) (DebugHeader + 1));\r
1271 SendAckPacket (DEBUG_COMMAND_OK);\r
1272 break;\r
1273\r
1274 case DEBUG_COMMAND_CLEAR_HW_BREAKPOINT:\r
1275 ClearDebugRegister (CpuContext, (DEBUG_DATA_CLEAR_HW_BREAKPOINT *) (DebugHeader + 1));\r
1276 SendAckPacket (DEBUG_COMMAND_OK);\r
1277 break;\r
1278\r
1279 case DEBUG_COMMAND_SINGLE_STEPPING:\r
1280 CommandStepping (CpuContext);\r
1281 //\r
1282 // Clear Dr0 to avoid to be recognized as IMAGE_LOAD/_UNLOAD again when hitting a breakpoint after GO\r
1283 // If HOST changed Dr0 before GO, we will not change Dr0 here\r
1284 //\r
1285 Data8 = GetBreakCause (Vector, CpuContext);\r
1286 if (Data8 == DEBUG_DATA_BREAK_CAUSE_IMAGE_LOAD || Data8 == DEBUG_DATA_BREAK_CAUSE_IMAGE_UNLOAD) {\r
1287 CpuContext->Dr0 = 0;\r
1288 }\r
1289\r
1290 mDebugMpContext.BreakAtCpuIndex = (UINT32) (-1);\r
1291 //\r
1292 // Set Stepping Flag\r
1293 //\r
1294 GetMailboxPointer()->DebugFlag.SteppingFlag = 1;\r
1295 ReleaseDebugPortControl ();\r
1296 //\r
1297 // Executing stepping command directly without sending ACK packet,\r
1298 // ACK packet will be sent after stepping done.\r
1299 //\r
1300 return;\r
1301\r
1302 case DEBUG_COMMAND_SET_SW_BREAKPOINT:\r
1303 Data64 = (UINTN) (((DEBUG_DATA_SET_SW_BREAKPOINT *) (DebugHeader + 1))->Address);\r
1304 Data8 = *(UINT8 *) (UINTN) Data64;\r
1305 *(UINT8 *) (UINTN) Data64 = DEBUG_SW_BREAKPOINT_SYMBOL;\r
1306 Status = SendDataResponsePacket ((UINT8 *) &Data8, (UINT16) sizeof (UINT8));\r
1307 break;\r
1308\r
1309 case DEBUG_COMMAND_READ_MEMORY:\r
1310 MemoryRead = (DEBUG_DATA_READ_MEMORY *) (DebugHeader + 1);\r
1311 Status = SendDataResponsePacket ((UINT8 *) (UINTN) MemoryRead->Address, (UINT16) (MemoryRead->Count * MemoryRead->Width));\r
1312 break;\r
1313\r
1314 case DEBUG_COMMAND_WRITE_MEMORY:\r
1315 MemoryWrite = (DEBUG_DATA_WRITE_MEMORY *) (DebugHeader + 1);\r
1316 CopyMem ((VOID *) (UINTN) MemoryWrite->Address, &MemoryWrite->Data, MemoryWrite->Count * MemoryWrite->Width);\r
1317 SendAckPacket (DEBUG_COMMAND_OK);\r
1318 break;\r
1319\r
1320 case DEBUG_COMMAND_READ_IO:\r
1321 IoRead = (DEBUG_DATA_READ_IO *) (DebugHeader + 1);\r
1322 switch (IoRead->Width) {\r
1323 case 1:\r
1324 Data64 = IoRead8 ((UINTN) IoRead->Port);\r
1325 break;\r
1326 case 2:\r
1327 Data64 = IoRead16 ((UINTN) IoRead->Port);\r
1328 break;\r
1329 case 4:\r
1330 Data64 = IoRead32 ((UINTN) IoRead->Port);\r
1331 break;\r
1332 case 8:\r
1333 Data64 = IoRead64 ((UINTN) IoRead->Port);\r
1334 break;\r
1335 default:\r
1336 Data64 = (UINT64) -1;\r
1337 }\r
1338 Status = SendDataResponsePacket ((UINT8 *) &Data64, IoRead->Width);\r
1339 break;\r
1340\r
1341 case DEBUG_COMMAND_WRITE_IO:\r
1342 IoWrite = (DEBUG_DATA_WRITE_IO *) (DebugHeader + 1);\r
1343 switch (IoWrite->Width) {\r
1344 case 1:\r
1345 Data64 = IoWrite8 ((UINTN) IoWrite->Port, *(UINT8 *) &IoWrite->Data);\r
1346 break;\r
1347 case 2:\r
1348 Data64 = IoWrite16 ((UINTN) IoWrite->Port, *(UINT16 *) &IoWrite->Data);\r
1349 break;\r
1350 case 4:\r
1351 Data64 = IoWrite32 ((UINTN) IoWrite->Port, *(UINT32 *) &IoWrite->Data);\r
1352 break;\r
1353 case 8:\r
1354 Data64 = IoWrite64 ((UINTN) IoWrite->Port, *(UINT64 *) &IoWrite->Data);\r
1355 break;\r
1356 default:\r
1357 Data64 = (UINT64) -1;\r
1358 }\r
1359 SendAckPacket (DEBUG_COMMAND_OK);\r
1360 break;\r
1361\r
1362 case DEBUG_COMMAND_READ_ALL_REGISTERS:\r
1363 Status = SendDataResponsePacket ((UINT8 *) CpuContext, sizeof (*CpuContext));\r
1364 break;\r
1365\r
1366 case DEBUG_COMMAND_READ_REGISTER:\r
1367 RegisterRead = (DEBUG_DATA_READ_REGISTER *) (DebugHeader + 1);\r
1368\r
1369 if (RegisterRead->Index <= SOFT_DEBUGGER_REGISTER_MAX) {\r
1370 RegisterBuffer = ArchReadRegisterBuffer (CpuContext, RegisterRead->Index, &Width);\r
1371 Status = SendDataResponsePacket (RegisterBuffer, Width);\r
1372 } else {\r
1373 Status = RETURN_UNSUPPORTED;\r
1374 }\r
1375 break;\r
1376\r
1377 case DEBUG_COMMAND_WRITE_REGISTER:\r
1378 RegisterWrite = (DEBUG_DATA_WRITE_REGISTER *) (DebugHeader + 1);\r
1379 if (RegisterWrite->Index <= SOFT_DEBUGGER_REGISTER_MAX) {\r
1380 RegisterBuffer = ArchReadRegisterBuffer (CpuContext, RegisterWrite->Index, &Width);\r
1381 ASSERT (Width == RegisterWrite->Length);\r
1382 CopyMem (RegisterBuffer, RegisterWrite->Data, Width);\r
1383 SendAckPacket (DEBUG_COMMAND_OK);\r
1384 } else {\r
1385 Status = RETURN_UNSUPPORTED;\r
1386 }\r
1387 break;\r
1388\r
1389 case DEBUG_COMMAND_ARCH_MODE:\r
1390 Data8 = DEBUG_ARCH_SYMBOL;\r
1391 Status = SendDataResponsePacket ((UINT8 *) &Data8, (UINT16) sizeof (UINT8));\r
1392 break;\r
1393\r
1394 case DEBUG_COMMAND_READ_MSR:\r
1395 MsrRegisterRead = (DEBUG_DATA_READ_MSR *) (DebugHeader + 1);\r
1396 Data64 = AsmReadMsr64 (MsrRegisterRead->Index);\r
1397 Status = SendDataResponsePacket ((UINT8 *) &Data64, (UINT16) sizeof (UINT64));\r
1398 break;\r
1399\r
1400 case DEBUG_COMMAND_WRITE_MSR:\r
1401 MsrRegisterWrite = (DEBUG_DATA_WRITE_MSR *) (DebugHeader + 1);\r
1402 AsmWriteMsr64 (MsrRegisterWrite->Index, MsrRegisterWrite->Value);\r
1403 SendAckPacket (DEBUG_COMMAND_OK);\r
1404 break;\r
1405\r
1406 case DEBUG_COMMAND_SET_DEBUG_SETTING:\r
1407 Status = SetDebugSetting ((DEBUG_DATA_SET_DEBUG_SETTING *)(DebugHeader + 1));\r
1408 if (Status == RETURN_SUCCESS) {\r
1409 SendAckPacket (DEBUG_COMMAND_OK);\r
1410 }\r
1411 break;\r
1412\r
1413 case DEBUG_COMMAND_GET_REVISION:\r
1414 DebugAgentRevision.Revision = DEBUG_AGENT_REVISION;\r
1415 DebugAgentRevision.Capabilities = DEBUG_AGENT_CAPABILITIES;\r
1416 Status = SendDataResponsePacket ((UINT8 *) &DebugAgentRevision, (UINT16) sizeof (DEBUG_DATA_RESPONSE_GET_REVISION));\r
1417 break;\r
1418\r
1419 case DEBUG_COMMAND_GET_EXCEPTION:\r
1420 Exception.ExceptionNum = (UINT8) Vector;\r
1421 Exception.ExceptionData = (UINT32) CpuContext->ExceptionData;\r
1422 Status = SendDataResponsePacket ((UINT8 *) &Exception, (UINT16) sizeof (DEBUG_DATA_RESPONSE_GET_EXCEPTION));\r
1423 break;\r
1424\r
1425 case DEBUG_COMMAND_SET_VIEWPOINT:\r
1426 SetViewPoint = (DEBUG_DATA_SET_VIEWPOINT *) (DebugHeader + 1);\r
1427 if (MultiProcessorDebugSupport) {\r
1428 if (IsCpuStopped (SetViewPoint->ViewPoint)) {\r
1429 SetDebugViewPoint (SetViewPoint->ViewPoint);\r
1430 SendAckPacket (DEBUG_COMMAND_OK);\r
1431 } else {\r
1432 //\r
1433 // If CPU is not halted\r
1434 //\r
1435 SendAckPacket (DEBUG_COMMAND_NOT_SUPPORTED);\r
1436 }\r
1437 } else if (SetViewPoint->ViewPoint == 0) {\r
1438 SendAckPacket (DEBUG_COMMAND_OK);\r
1439\r
1440 } else {\r
1441 SendAckPacket (DEBUG_COMMAND_NOT_SUPPORTED);\r
1442 }\r
1443\r
1444 break;\r
1445\r
1446 case DEBUG_COMMAND_GET_VIEWPOINT:\r
1447 Data32 = mDebugMpContext.ViewPointIndex;\r
1448 SendDataResponsePacket((UINT8 *) &Data32, (UINT16) sizeof (UINT32));\r
1449 break;\r
1450\r
1451 case DEBUG_COMMAND_MEMORY_READY:\r
1452 Data8 = (UINT8) GetMailboxPointer ()->DebugFlag.MemoryReady;\r
1453 SendDataResponsePacket (&Data8, (UINT16) sizeof (UINT8));\r
1454 break;\r
1455\r
1456 case DEBUG_COMMAND_DETACH:\r
1457 SetHostAttached (FALSE);\r
1458 SendAckPacket (DEBUG_COMMAND_OK);\r
1459 break;\r
1460\r
1461 case DEBUG_COMMAND_CPUID:\r
1462 Cpuid = (DEBUG_DATA_CPUID *) (DebugHeader + 1);\r
1463 AsmCpuidEx (\r
1464 Cpuid->Eax, Cpuid->Ecx, \r
1465 &CpuidResponse.Eax, &CpuidResponse.Ebx,\r
1466 &CpuidResponse.Ecx, &CpuidResponse.Edx\r
1467 );\r
1468 SendDataResponsePacket ((UINT8 *) &CpuidResponse, (UINT16) sizeof (CpuidResponse));\r
1469 break;\r
1470\r
1471 case DEBUG_COMMAND_SEARCH_SIGNATURE:\r
1472 SearchSignature = (DEBUG_DATA_SEARCH_SIGNATURE *) (DebugHeader + 1);\r
1473 if ((SearchSignature->Alignment != 0) && \r
1474 (SearchSignature->Alignment == GetPowerOfTwo32 (SearchSignature->Alignment))\r
1475 ) {\r
1476 if (SearchSignature->Positive) {\r
1477 for (\r
1478 Data64 = ALIGN_VALUE ((UINTN) SearchSignature->Start, SearchSignature->Alignment);\r
1479 Data64 <= SearchSignature->Start + SearchSignature->Count - SearchSignature->DataLength;\r
1480 Data64 += SearchSignature->Alignment\r
1481 ) {\r
1482 if (CompareMem ((VOID *) (UINTN) Data64, &SearchSignature->Data, SearchSignature->DataLength) == 0) {\r
1483 break;\r
1484 }\r
1485 }\r
1486 if (Data64 > SearchSignature->Start + SearchSignature->Count - SearchSignature->DataLength) {\r
1487 Data64 = (UINT64) -1;\r
1488 }\r
1489 } else {\r
1490 for (\r
1491 Data64 = ALIGN_VALUE ((UINTN) SearchSignature->Start - SearchSignature->Alignment, SearchSignature->Alignment);\r
1492 Data64 >= SearchSignature->Start - SearchSignature->Count;\r
1493 Data64 -= SearchSignature->Alignment\r
1494 ) {\r
1495 if (CompareMem ((VOID *) (UINTN) Data64, &SearchSignature->Data, SearchSignature->DataLength) == 0) {\r
1496 break;\r
1497 }\r
1498 }\r
1499 if (Data64 < SearchSignature->Start - SearchSignature->Count) {\r
1500 Data64 = (UINT64) -1;\r
1501 }\r
1502 }\r
1503 SendDataResponsePacket ((UINT8 *) &Data64, (UINT16) sizeof (Data64));\r
1504 } else {\r
1505 Status = RETURN_UNSUPPORTED;\r
1506 }\r
1507 break;\r
1508\r
1509 default:\r
1510 SendAckPacket (DEBUG_COMMAND_NOT_SUPPORTED);\r
1511 break;\r
1512 }\r
1513\r
1514 if (Status == RETURN_UNSUPPORTED) {\r
1515 SendAckPacket (DEBUG_COMMAND_NOT_SUPPORTED);\r
1516 } else if (Status != RETURN_SUCCESS) {\r
1517 SendAckPacket (DEBUG_COMMAND_ABORT);\r
1518 }\r
1519\r
1520 ReleaseDebugPortControl ();\r
1521 CpuPause ();\r
1522 }\r
1523}\r
1524\r
1525/**\r
1526 C function called in interrupt handler.\r
1527\r
1528 @param[in] Vector Vector value of exception or interrutp.\r
1529 @param[in] CpuContext Pointer to save CPU context.\r
1530\r
1531**/\r
1532VOID\r
1533EFIAPI\r
1534InterruptProcess (\r
1535 IN UINT32 Vector,\r
1536 IN DEBUG_CPU_CONTEXT *CpuContext\r
1537 )\r
1538{\r
1539 UINT8 InputCharacter;\r
1540 UINT8 BreakCause;\r
1541 UINTN SavedEip;\r
1542 BOOLEAN BreakReceived;\r
1543 UINT32 ProcessorIndex;\r
1544 UINT32 CurrentDebugTimerInitCount;\r
1545 DEBUG_PORT_HANDLE Handle;\r
1546 UINT8 Data8;\r
1547 UINT8 *Al;\r
1548 UINT32 IssuedViewPoint;\r
1549 DEBUG_AGENT_EXCEPTION_BUFFER *ExceptionBuffer;\r
1550\r
1551 ProcessorIndex = 0;\r
1552 IssuedViewPoint = 0;\r
1553 BreakReceived = FALSE;\r
1554\r
1555 if (MultiProcessorDebugSupport) {\r
1556 ProcessorIndex = GetProcessorIndex ();\r
1557 //\r
1558 // If this processor has alreay halted before, need to check it later\r
1559 //\r
1560 if (IsCpuStopped (ProcessorIndex)) {\r
1561 IssuedViewPoint = ProcessorIndex;\r
1562 }\r
1563 }\r
1564\r
1565 if (IssuedViewPoint == ProcessorIndex) {\r
1566 //\r
1567 // Check if this exception is issued by Debug Agent itself\r
1568 // If yes, fill the debug agent exception buffer and LongJump() back to\r
1569 // the saved CPU content in CommandCommunication()\r
1570 //\r
1571 if (GetMailboxPointer()->DebugFlag.AgentInProgress == 1) {\r
1572 DebugAgentMsgPrint (DEBUG_AGENT_ERROR, "Debug agent meet one Exception, ExceptionNum is %d.\n", Vector);\r
1573 ExceptionBuffer = (DEBUG_AGENT_EXCEPTION_BUFFER *) (UINTN) GetMailboxPointer()->ExceptionBufferPointer;\r
1574 ExceptionBuffer->ExceptionContent.ExceptionNum = (UINT8) Vector;\r
1575 ExceptionBuffer->ExceptionContent.ExceptionData = (UINT32) CpuContext->ExceptionData;\r
1576 LongJump ((BASE_LIBRARY_JUMP_BUFFER *)(UINTN)(GetMailboxPointer()->ExceptionBufferPointer), 1);\r
1577 }\r
1578 }\r
1579\r
1580 if (MultiProcessorDebugSupport) {\r
1581 //\r
1582 // If RUN commmand is executing, wait for it done. \r
1583 //\r
1584 while (mDebugMpContext.RunCommandSet) {\r
1585 CpuPause ();\r
1586 }\r
1587 }\r
1588\r
1589 Handle = GetDebugPortHandle();\r
1590\r
1591 switch (Vector) {\r
1592 case DEBUG_INT1_VECTOR:\r
1593 case DEBUG_INT3_VECTOR:\r
1594 BreakCause = GetBreakCause (Vector, CpuContext);\r
1595\r
1596 switch (BreakCause) {\r
1597 case DEBUG_DATA_BREAK_CAUSE_SYSTEM_RESET:\r
1598 if (AttachHost (INIT_BREAK_ACK_TIMEOUT, &BreakReceived) != RETURN_SUCCESS) {\r
1599 //\r
1600 // Try to connect HOST, return if fails\r
1601 //\r
1602 break;\r
1603 }\r
1604 CommandCommunication (Vector, CpuContext, BreakReceived);\r
1605 break;\r
1606\r
1607 case DEBUG_DATA_BREAK_CAUSE_STEPPING:\r
1608 //\r
1609 // Stepping is finished, send Ack package.\r
1610 //\r
1611 if (MultiProcessorDebugSupport) {\r
1612 mDebugMpContext.BreakAtCpuIndex = ProcessorIndex;\r
1613 }\r
1614 SendAckPacket (DEBUG_COMMAND_OK);\r
1615 CommandCommunication (Vector, CpuContext, BreakReceived);\r
1616 break;\r
1617\r
1618 case DEBUG_DATA_BREAK_CAUSE_MEMORY_READY:\r
1619 //\r
1620 // Memory is ready\r
1621 //\r
1622 SendCommandAndWaitForAckOK (DEBUG_COMMAND_MEMORY_READY, 0, &BreakReceived, NULL);\r
1623 CommandCommunication (Vector, CpuContext, BreakReceived);\r
1624 break;\r
1625\r
1626 case DEBUG_DATA_BREAK_CAUSE_IMAGE_LOAD:\r
1627 case DEBUG_DATA_BREAK_CAUSE_IMAGE_UNLOAD:\r
1628 //\r
1629 // Set AL to DEBUG_AGENT_IMAGE_CONTINUE\r
1630 //\r
1631 Al = ArchReadRegisterBuffer (CpuContext, SOFT_DEBUGGER_REGISTER_AX, &Data8);\r
1632 *Al = DEBUG_AGENT_IMAGE_CONTINUE;\r
1633\r
1634 if (!IsHostAttached ()) {\r
1635 //\r
1636 // If HOST is not connected for image load/unload, return\r
1637 //\r
1638 break;\r
1639 }\r
1640 //\r
1641 // Continue to run the following common code\r
1642 //\r
1643 \r
1644 case DEBUG_DATA_BREAK_CAUSE_HW_BREAKPOINT:\r
1645 case DEBUG_DATA_BREAK_CAUSE_SW_BREAKPOINT:\r
1646 default:\r
1647 //\r
1648 // Send Break packet to HOST\r
1649 //\r
1650 AcquireDebugPortControl ();\r
1651 //\r
1652 // Only the first breaking processor could send BREAK_POINT to HOST\r
1653 // \r
1654 if (IsFirstBreakProcessor (ProcessorIndex)) {\r
1655 SendBreakPacketToHost (ProcessorIndex, &BreakReceived);\r
1656 }\r
1657 ReleaseDebugPortControl ();\r
1658 \r
1659 if (Vector == DEBUG_INT3_VECTOR) {\r
1660 //\r
1661 // go back address located "0xCC"\r
1662 //\r
1663 CpuContext->Eip--;\r
1664 SavedEip = CpuContext->Eip;\r
1665 CommandCommunication (Vector, CpuContext, BreakReceived);\r
1666 if ((SavedEip == CpuContext->Eip) &&\r
1667 (*(UINT8 *) (UINTN) CpuContext->Eip == DEBUG_SW_BREAKPOINT_SYMBOL)) {\r
1668 //\r
1669 // If this is not a software breakpoint set by HOST,\r
1670 // restore EIP\r
1671 //\r
1672 CpuContext->Eip++;\r
1673 }\r
1674 } else {\r
1675 CommandCommunication (Vector, CpuContext, BreakReceived);\r
1676 }\r
1677 break;\r
1678 }\r
1679\r
1680 break;\r
1681\r
1682 case DEBUG_TIMER_VECTOR:\r
1683\r
1684 AcquireDebugPortControl ();\r
1685\r
1686 if (MultiProcessorDebugSupport) {\r
1687 if (IsBsp (ProcessorIndex)) {\r
1688 //\r
1689 // If current processor is BSP, check Apic timer's init count if changed,\r
1690 // it may be re-written when switching BSP.\r
1691 // If it changed, re-initialize debug timer\r
1692 //\r
1693 CurrentDebugTimerInitCount = GetApicTimerInitCount ();\r
1694 if (mDebugMpContext.DebugTimerInitCount != CurrentDebugTimerInitCount) {\r
1695 InitializeDebugTimer ();\r
1696 }\r
1697 }\r
1698\r
1699 if (!IsBsp (ProcessorIndex) || mDebugMpContext.IpiSentByAp) {\r
1700 ReleaseDebugPortControl ();\r
1701 //\r
1702 // If current processor is not BSP or this is one IPI sent by AP\r
1703 //\r
1704 if (mDebugMpContext.BreakAtCpuIndex != (UINT32) (-1)) {\r
1705 CommandCommunication (Vector, CpuContext, FALSE);\r
1706 }\r
1707\r
1708 //\r
1709 // Clear EOI before exiting interrupt process routine.\r
1710 //\r
1711 SendApicEoi ();\r
1712 break;\r
1713 }\r
1714 }\r
1715\r
1716 //\r
1717 // Only BSP could run here\r
1718 //\r
1719 while (TRUE) {\r
1720 //\r
1721 // If there is data in debug port, will check whether it is break(attach/break-in) symbol,\r
1722 // If yes, go into communication mode with HOST.\r
1723 // If no, exit interrupt process.\r
1724 //\r
1725 if (DebugReadBreakSymbol (Handle, &InputCharacter) == EFI_NOT_FOUND) {\r
1726 break;\r
1727 }\r
1728 if ((!IsHostAttached () && (InputCharacter == DEBUG_STARTING_SYMBOL_ATTACH)) ||\r
1729 (IsHostAttached () && (InputCharacter == DEBUG_STARTING_SYMBOL_BREAK))\r
1730 ) {\r
1731 DebugAgentMsgPrint (DEBUG_AGENT_VERBOSE, "Received data [%02x]\n", InputCharacter);\r
1732 //\r
1733 // Ack OK for break-in symbol\r
1734 //\r
1735 SendAckPacket (DEBUG_COMMAND_OK);\r
1736\r
1737 if (!IsHostAttached ()) {\r
1738 //\r
1739 // Try to attach HOST, if no ack received after 200ms, return\r
1740 //\r
1741 if (AttachHost (INIT_BREAK_ACK_TIMEOUT, &BreakReceived) != RETURN_SUCCESS) {\r
1742 break;\r
1743 }\r
1744 }\r
1745\r
1746 if (MultiProcessorDebugSupport) {\r
1747 if(FindNextPendingBreakCpu () != -1) {\r
1748 SetCpuBreakFlagByIndex (ProcessorIndex, TRUE);\r
1749 } else {\r
1750 HaltOtherProcessors (ProcessorIndex);\r
1751 }\r
1752 }\r
1753 ReleaseDebugPortControl ();\r
1754 CommandCommunication (Vector, CpuContext, BreakReceived);\r
1755 AcquireDebugPortControl ();\r
1756 break;\r
1757 }\r
1758 }\r
1759\r
1760 //\r
1761 // Clear EOI before exiting interrupt process routine.\r
1762 //\r
1763 SendApicEoi ();\r
1764\r
1765 ReleaseDebugPortControl ();\r
1766\r
1767 break;\r
1768\r
1769 default:\r
1770\r
1771 if (Vector <= DEBUG_EXCEPT_SIMD) {\r
1772 BreakCause = GetBreakCause (Vector, CpuContext);\r
1773 if (BreakCause == DEBUG_DATA_BREAK_CAUSE_STEPPING) {\r
1774 //\r
1775 // Stepping is finished, send Ack package.\r
1776 //\r
1777 if (MultiProcessorDebugSupport) {\r
1778 mDebugMpContext.BreakAtCpuIndex = ProcessorIndex;\r
1779 }\r
1780 SendAckPacket (DEBUG_COMMAND_OK);\r
1781 } else {\r
1782 //\r
1783 // Exception occurs, send Break packet to HOST\r
1784 //\r
1785 AcquireDebugPortControl ();\r
1786 //\r
1787 // Only the first breaking processor could send BREAK_POINT to HOST\r
1788 // \r
1789 if (IsFirstBreakProcessor (ProcessorIndex)) {\r
1790 SendBreakPacketToHost (ProcessorIndex, &BreakReceived);\r
1791 }\r
1792 ReleaseDebugPortControl ();\r
1793 }\r
1794 \r
1795 CommandCommunication (Vector, CpuContext, BreakReceived);\r
1796 }\r
1797 break;\r
1798 }\r
1799\r
1800 if (MultiProcessorDebugSupport) {\r
1801 //\r
1802 // Clear flag and wait for all processors run here\r
1803 //\r
1804 SetIpiSentByApFlag (FALSE);\r
1805 while (mDebugMpContext.RunCommandSet) {\r
1806 CpuPause ();\r
1807 }\r
1808\r
1809 //\r
1810 // Only current (view) processor could clean up AgentInProgress flag.\r
1811 //\r
1812 if (mDebugMpContext.ViewPointIndex == ProcessorIndex) {\r
1813 IssuedViewPoint = mDebugMpContext.ViewPointIndex;\r
1814 }\r
1815 }\r
1816\r
1817 if (IssuedViewPoint == ProcessorIndex) {\r
1818 //\r
1819 // Clean up AgentInProgress flag\r
1820 //\r
1821 GetMailboxPointer()->DebugFlag.AgentInProgress = 0;\r
1822 }\r
1823\r
1824 return;\r
1825}\r
1826\r