]> git.proxmox.com Git - mirror_edk2.git/blame - SourceLevelDebugPkg/Library/DebugAgent/DebugAgentCommon/DebugAgent.c
Roll back r13823.
[mirror_edk2.git] / SourceLevelDebugPkg / Library / DebugAgent / DebugAgentCommon / DebugAgent.c
CommitLineData
18b144ea 1/** @file\r
2 Commond Debug Agent library implementition. It mainly includes\r
3 the first C function called by exception/interrupt handlers,\r
4 read/write debug packet to communication with HOST based on transfer\r
5 protocol.\r
6\r
b4ebbaff 7 Copyright (c) 2010 - 2012, Intel Corporation. All rights reserved.<BR>\r
18b144ea 8 This program and the accompanying materials\r
9 are licensed and made available under the terms and conditions of the BSD License\r
10 which accompanies this distribution. The full text of the license may be found at\r
11 http://opensource.org/licenses/bsd-license.php.\r
12\r
13 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
14 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
15\r
16**/\r
17\r
18#include "DebugAgent.h"\r
19#include "Ia32/DebugException.h"\r
20\r
93c0bdec 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
18b144ea 28/**\r
93c0bdec 29 Send a debug message packet to the debug port.\r
18b144ea 30\r
93c0bdec 31 @param[in] Buffer The debug message.\r
32 @param[in] Length The length of debug message.\r
18b144ea 33\r
34**/\r
93c0bdec 35VOID\r
36SendDebugMsgPacket (\r
37 IN CHAR8 *Buffer,\r
38 IN UINTN Length \r
18b144ea 39 )\r
40{\r
93c0bdec 41 DEBUG_PACKET_HEADER DebugHeader;\r
42 DEBUG_PORT_HANDLE Handle;\r
43 \r
44 Handle = GetDebugPortHandle();\r
18b144ea 45\r
93c0bdec 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
18b144ea 51\r
93c0bdec 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
18b144ea 86 }\r
93c0bdec 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
18b144ea 96}\r
97\r
98/**\r
93c0bdec 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
18b144ea 111\r
112**/\r
113VOID\r
93c0bdec 114EFIAPI\r
115DebugAgentDataMsgPrint (\r
116 IN UINT8 ErrorLevel,\r
117 IN BOOLEAN IsSend,\r
118 IN UINT8 *Data,\r
119 IN UINT8 Length \r
18b144ea 120 )\r
121{\r
93c0bdec 122 DEBUG_AGENT_MAILBOX *Mailbox;\r
123 CHAR8 Buffer[DEBUG_DATA_MAXIMUM_REAL_DATA];\r
124 CHAR8 *DestBuffer;\r
125 UINTN Index;\r
18b144ea 126\r
127 Mailbox = GetMailboxPointer ();\r
93c0bdec 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
18b144ea 141\r
93c0bdec 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
18b144ea 163}\r
164\r
93c0bdec 165\r
18b144ea 166/**\r
93c0bdec 167 Check if HOST is attached based on Mailbox.\r
18b144ea 168\r
93c0bdec 169 @retval TRUE HOST is attached.\r
170 @retval FALSE HOST is not attached.\r
18b144ea 171\r
93c0bdec 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
18b144ea 186**/\r
187VOID\r
93c0bdec 188SetHostAttached (\r
189 IN BOOLEAN Attached\r
18b144ea 190 )\r
191{\r
93c0bdec 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
18b144ea 211 DEBUG_AGENT_MAILBOX *Mailbox;\r
212\r
213 Mailbox = GetMailboxPointer ();\r
214\r
93c0bdec 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
18b144ea 225 }\r
93c0bdec 226 return Status;\r
18b144ea 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
93c0bdec 297 Dr7Value &= ~(0xf << (16 + RegisterIndex * 4));\r
298 Dr7Value |= (UINTN) ((SetHwBreakpoint->Type.Length << 2) | SetHwBreakpoint->Type.Access) << (16 + RegisterIndex * 4);\r
18b144ea 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
93c0bdec 338\r
18b144ea 339/**\r
93c0bdec 340 Return the offset of FP / MMX / XMM registers in the FPU saved state by register index.\r
18b144ea 341\r
93c0bdec 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
18b144ea 449\r
450**/\r
451VOID\r
93c0bdec 452SendPacketWithoutData (\r
453 IN UINT8 CommandType\r
18b144ea 454 )\r
455{\r
93c0bdec 456 DEBUG_PACKET_HEADER DebugHeader;\r
18b144ea 457 DEBUG_PORT_HANDLE Handle;\r
458\r
459 Handle = GetDebugPortHandle();\r
460\r
93c0bdec 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
18b144ea 466\r
93c0bdec 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
18b144ea 486}\r
487\r
488/**\r
489 Receive acknowledge packet from HOST in specified time.\r
490\r
93c0bdec 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
18b144ea 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
93c0bdec 510 OUT BOOLEAN *BreakReceived, OPTIONAL\r
511 OUT RETURN_STATUS *CheckSumStatus OPTIONAL\r
18b144ea 512 )\r
513{\r
93c0bdec 514 DEBUG_PACKET_HEADER DebugHeader;\r
18b144ea 515 DEBUG_PORT_HANDLE Handle;\r
516\r
517 Handle = GetDebugPortHandle();\r
518\r
519 while (TRUE) {\r
93c0bdec 520 if (DebugPortReadBuffer (Handle, (UINT8 *) &DebugHeader.StartSymbol, sizeof (DebugHeader.StartSymbol), Timeout) == 0) {\r
18b144ea 521 return RETURN_TIMEOUT;\r
522 }\r
93c0bdec 523 if (DebugHeader.StartSymbol == DEBUG_STARTING_SYMBOL_BREAK) {\r
18b144ea 524 if (BreakReceived != NULL) {\r
525 SendAckPacket (DEBUG_COMMAND_HALT_DEFERRED);\r
526 *BreakReceived = TRUE;\r
527 }\r
528 }\r
93c0bdec 529 if (DebugHeader.StartSymbol == DEBUG_STARTING_SYMBOL_NORMAL) {\r
18b144ea 530 break;\r
531 }\r
93c0bdec 532 DebugAgentMsgPrint (DEBUG_AGENT_ERROR, "Invalid start symbol received [%02x]\n", DebugHeader.StartSymbol);\r
18b144ea 533 }\r
93c0bdec 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
18b144ea 544 return RETURN_TIMEOUT;\r
545 }\r
546\r
93c0bdec 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
18b144ea 565 return RETURN_SUCCESS;\r
566}\r
567\r
568/**\r
569 Receive acknowledge packet OK from HOST in specified time.\r
570\r
93c0bdec 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
18b144ea 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
93c0bdec 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
18b144ea 592 )\r
593{\r
93c0bdec 594 RETURN_STATUS Status;\r
595 UINT8 Ack;\r
596 \r
18b144ea 597 while (TRUE) {\r
93c0bdec 598 SendPacketWithoutData (Command);\r
599 while (TRUE) {\r
600 Status = ReceiveAckPacket (&Ack, Timeout, BreakReceived, CheckSumStatus);\r
48da9f0d 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
93c0bdec 609 //\r
610 // Received Ack OK or timeout\r
611 //\r
612 return Status;\r
48da9f0d 613 } \r
18b144ea 614 }\r
615 }\r
18b144ea 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
18b144ea 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
93c0bdec 635 DEBUG_PACKET_HEADER *DebugHeader;\r
18b144ea 636 UINTN Received;\r
637 DEBUG_PORT_HANDLE Handle;\r
93c0bdec 638 UINT8 CheckSum;\r
18b144ea 639\r
640 Handle = GetDebugPortHandle();\r
93c0bdec 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
18b144ea 648\r
93c0bdec 649 if (DebugHeader->StartSymbol == DEBUG_STARTING_SYMBOL_BREAK) {\r
650 *BreakReceived = TRUE;\r
651 SendAckPacket (DEBUG_COMMAND_HALT_DEFERRED);\r
652 }\r
18b144ea 653\r
93c0bdec 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
18b144ea 658\r
93c0bdec 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
18b144ea 671\r
93c0bdec 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
18b144ea 676 if (Received == 0) {\r
677 return RETURN_TIMEOUT;\r
678 }\r
93c0bdec 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
18b144ea 689 }\r
690\r
93c0bdec 691 DebugAgentDataMsgPrint (DEBUG_AGENT_VERBOSE, FALSE, (UINT8 *) DebugHeader, DebugHeader->Length);\r
692\r
18b144ea 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
0a16169b 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
18b144ea 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
93c0bdec 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
18b144ea 784 }\r
785 break;\r
786 }\r
787\r
788 return Cause;\r
789}\r
790\r
791/**\r
93c0bdec 792 Send command packet with data to HOST.\r
18b144ea 793\r
93c0bdec 794 @param[in] Command Command type.\r
18b144ea 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
93c0bdec 803SendCommandWithDataPacket (\r
804 IN UINT8 Command,\r
18b144ea 805 IN UINT8 *Data,\r
806 IN UINT16 DataSize\r
807 )\r
808{\r
93c0bdec 809 DEBUG_PACKET_HEADER *DebugHeader;\r
18b144ea 810 BOOLEAN LastPacket;\r
811 UINT8 Ack;\r
93c0bdec 812 UINT8 DebugPacket[DEBUG_DATA_UPPER_LIMIT];\r
18b144ea 813 DEBUG_PORT_HANDLE Handle;\r
814\r
815 Handle = GetDebugPortHandle();\r
816\r
93c0bdec 817 DebugHeader = (DEBUG_PACKET_HEADER *) &DebugPacket;\r
818 DebugHeader->StartSymbol = DEBUG_STARTING_SYMBOL_NORMAL;\r
18b144ea 819\r
820 while (TRUE) {\r
821 if (DataSize <= DEBUG_DATA_MAXIMUM_REAL_DATA) {\r
822 LastPacket = TRUE;\r
93c0bdec 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
18b144ea 827\r
828 } else {\r
829 LastPacket = FALSE;\r
93c0bdec 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
18b144ea 834 }\r
835\r
93c0bdec 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
18b144ea 844\r
93c0bdec 845 ReceiveAckPacket(&Ack, 0, NULL, NULL);\r
18b144ea 846 switch (Ack) {\r
847 case DEBUG_COMMAND_RESEND:\r
848 //\r
849 // Send the packet again\r
850 //\r
93c0bdec 851 DebugAgentMsgPrint (DEBUG_AGENT_WARNING, "Received DEBUG_COMMAND_RESEND.\n");\r
18b144ea 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
93c0bdec 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
18b144ea 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
93c0bdec 919 return SendDataResponsePacket ((UINT8 *) &DebugDataBreakCause, (UINT16) sizeof (DEBUG_DATA_RESPONSE_BREAK_CAUSE));\r
18b144ea 920}\r
921\r
93c0bdec 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
18b144ea 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
93c0bdec 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
18b144ea 1068\r
1069 ProcessorIndex = 0;\r
93c0bdec 1070 IssuedViewPoint = 0;\r
1071 HaltDeferred = BreakReceived;\r
18b144ea 1072\r
1073 if (MultiProcessorDebugSupport) {\r
1074 ProcessorIndex = GetProcessorIndex ();\r
1075 SetCpuStopFlagByIndex (ProcessorIndex, TRUE);\r
93c0bdec 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
18b144ea 1082 }\r
1083\r
93c0bdec 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
18b144ea 1093 while (TRUE) {\r
1094\r
1095 if (MultiProcessorDebugSupport) {\r
93c0bdec 1096 //\r
1097 // Check if the current processor is HOST view point\r
1098 //\r
18b144ea 1099 if (mDebugMpContext.ViewPointIndex != ProcessorIndex) {\r
1100 if (mDebugMpContext.RunCommandSet) {\r
93c0bdec 1101 //\r
1102 // If HOST view point sets RUN flag, run GO command to leave\r
1103 //\r
18b144ea 1104 SetCpuStopFlagByIndex (ProcessorIndex, FALSE);\r
1105 CommandGo (CpuContext);\r
1106 break;\r
1107 } else {\r
93c0bdec 1108 //\r
1109 // Run into loop again\r
1110 //\r
1111 CpuPause ();\r
18b144ea 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
93c0bdec 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
18b144ea 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
b4ebbaff
RN
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
18b144ea 1161 //\r
b4ebbaff
RN
1162 MicroSecondDelay (2000000);\r
1163 SendAckPacket (DEBUG_COMMAND_TIMEOUT);\r
18b144ea 1164 break;\r
1165\r
1166 case DEBUG_COMMAND_GO:\r
1167 CommandGo (CpuContext);\r
93c0bdec 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
18b144ea 1181 if (!HaltDeferred) {\r
1182 //\r
1183 // If no HALT command received when being in-active mode\r
1184 //\r
1185 if (MultiProcessorDebugSupport) {\r
93c0bdec 1186 Data32 = FindNextPendingBreakCpu ();\r
18b144ea 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
93c0bdec 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
18b144ea 1206 //\r
18b144ea 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
18b144ea 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
93c0bdec 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
18b144ea 1289\r
1290 mDebugMpContext.BreakAtCpuIndex = (UINT32) (-1);\r
93c0bdec 1291 //\r
1292 // Set Stepping Flag\r
1293 //\r
1294 GetMailboxPointer()->DebugFlag.SteppingFlag = 1;\r
18b144ea 1295 ReleaseDebugPortControl ();\r
1296 //\r
93c0bdec 1297 // Executing stepping command directly without sending ACK packet,\r
1298 // ACK packet will be sent after stepping done.\r
18b144ea 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
93c0bdec 1306 Status = SendDataResponsePacket ((UINT8 *) &Data8, (UINT16) sizeof (UINT8));\r
18b144ea 1307 break;\r
1308\r
93c0bdec 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
18b144ea 1312 break;\r
1313\r
93c0bdec 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
18b144ea 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
93c0bdec 1324 Data64 = IoRead8 ((UINTN) IoRead->Port);\r
18b144ea 1325 break;\r
1326 case 2:\r
93c0bdec 1327 Data64 = IoRead16 ((UINTN) IoRead->Port);\r
18b144ea 1328 break;\r
1329 case 4:\r
93c0bdec 1330 Data64 = IoRead32 ((UINTN) IoRead->Port);\r
18b144ea 1331 break;\r
1332 case 8:\r
93c0bdec 1333 Data64 = IoRead64 ((UINTN) IoRead->Port);\r
18b144ea 1334 break;\r
1335 default:\r
1336 Data64 = (UINT64) -1;\r
1337 }\r
93c0bdec 1338 Status = SendDataResponsePacket ((UINT8 *) &Data64, IoRead->Width);\r
18b144ea 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
93c0bdec 1345 Data64 = IoWrite8 ((UINTN) IoWrite->Port, *(UINT8 *) &IoWrite->Data);\r
18b144ea 1346 break;\r
1347 case 2:\r
93c0bdec 1348 Data64 = IoWrite16 ((UINTN) IoWrite->Port, *(UINT16 *) &IoWrite->Data);\r
18b144ea 1349 break;\r
1350 case 4:\r
93c0bdec 1351 Data64 = IoWrite32 ((UINTN) IoWrite->Port, *(UINT32 *) &IoWrite->Data);\r
18b144ea 1352 break;\r
1353 case 8:\r
93c0bdec 1354 Data64 = IoWrite64 ((UINTN) IoWrite->Port, *(UINT64 *) &IoWrite->Data);\r
18b144ea 1355 break;\r
1356 default:\r
1357 Data64 = (UINT64) -1;\r
1358 }\r
1359 SendAckPacket (DEBUG_COMMAND_OK);\r
1360 break;\r
1361\r
93c0bdec 1362 case DEBUG_COMMAND_READ_ALL_REGISTERS:\r
1363 Status = SendDataResponsePacket ((UINT8 *) CpuContext, sizeof (*CpuContext));\r
1364 break;\r
1365\r
18b144ea 1366 case DEBUG_COMMAND_READ_REGISTER:\r
1367 RegisterRead = (DEBUG_DATA_READ_REGISTER *) (DebugHeader + 1);\r
1368\r
93c0bdec 1369 if (RegisterRead->Index <= SOFT_DEBUGGER_REGISTER_MAX) {\r
1370 RegisterBuffer = ArchReadRegisterBuffer (CpuContext, RegisterRead->Index, &Width);\r
1371 Status = SendDataResponsePacket (RegisterBuffer, Width);\r
18b144ea 1372 } else {\r
93c0bdec 1373 Status = RETURN_UNSUPPORTED;\r
18b144ea 1374 }\r
1375 break;\r
1376\r
1377 case DEBUG_COMMAND_WRITE_REGISTER:\r
1378 RegisterWrite = (DEBUG_DATA_WRITE_REGISTER *) (DebugHeader + 1);\r
93c0bdec 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
18b144ea 1387 break;\r
1388\r
1389 case DEBUG_COMMAND_ARCH_MODE:\r
1390 Data8 = DEBUG_ARCH_SYMBOL;\r
93c0bdec 1391 Status = SendDataResponsePacket ((UINT8 *) &Data8, (UINT16) sizeof (UINT8));\r
18b144ea 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
93c0bdec 1397 Status = SendDataResponsePacket ((UINT8 *) &Data64, (UINT16) sizeof (UINT64));\r
18b144ea 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
93c0bdec 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
18b144ea 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
93c0bdec 1416 Status = SendDataResponsePacket ((UINT8 *) &DebugAgentRevision, (UINT16) sizeof (DEBUG_DATA_RESPONSE_GET_REVISION));\r
18b144ea 1417 break;\r
1418\r
1419 case DEBUG_COMMAND_GET_EXCEPTION:\r
1420 Exception.ExceptionNum = (UINT8) Vector;\r
93c0bdec 1421 Exception.ExceptionData = (UINT32) CpuContext->ExceptionData;\r
1422 Status = SendDataResponsePacket ((UINT8 *) &Exception, (UINT16) sizeof (DEBUG_DATA_RESPONSE_GET_EXCEPTION));\r
18b144ea 1423 break;\r
1424\r
1425 case DEBUG_COMMAND_SET_VIEWPOINT:\r
93c0bdec 1426 SetViewPoint = (DEBUG_DATA_SET_VIEWPOINT *) (DebugHeader + 1);\r
18b144ea 1427 if (MultiProcessorDebugSupport) {\r
93c0bdec 1428 if (IsCpuStopped (SetViewPoint->ViewPoint)) {\r
1429 SetDebugViewPoint (SetViewPoint->ViewPoint);\r
18b144ea 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
93c0bdec 1437 } else if (SetViewPoint->ViewPoint == 0) {\r
18b144ea 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
93c0bdec 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
18b144ea 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
93c0bdec 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
18b144ea 1550\r
93c0bdec 1551 ProcessorIndex = 0;\r
1552 IssuedViewPoint = 0;\r
1553 BreakReceived = FALSE;\r
18b144ea 1554\r
1555 if (MultiProcessorDebugSupport) {\r
1556 ProcessorIndex = GetProcessorIndex ();\r
93c0bdec 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
18b144ea 1563 }\r
1564\r
93c0bdec 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
18b144ea 1591 switch (Vector) {\r
1592 case DEBUG_INT1_VECTOR:\r
1593 case DEBUG_INT3_VECTOR:\r
18b144ea 1594 BreakCause = GetBreakCause (Vector, CpuContext);\r
1595\r
93c0bdec 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
18b144ea 1602 break;\r
1603 }\r
18b144ea 1604 CommandCommunication (Vector, CpuContext, BreakReceived);\r
93c0bdec 1605 break;\r
18b144ea 1606\r
93c0bdec 1607 case DEBUG_DATA_BREAK_CAUSE_STEPPING:\r
18b144ea 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
93c0bdec 1616 break;\r
18b144ea 1617\r
93c0bdec 1618 case DEBUG_DATA_BREAK_CAUSE_MEMORY_READY:\r
18b144ea 1619 //\r
1620 // Memory is ready\r
1621 //\r
93c0bdec 1622 SendCommandAndWaitForAckOK (DEBUG_COMMAND_MEMORY_READY, 0, &BreakReceived, NULL);\r
18b144ea 1623 CommandCommunication (Vector, CpuContext, BreakReceived);\r
93c0bdec 1624 break;\r
18b144ea 1625\r
93c0bdec 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
18b144ea 1633\r
93c0bdec 1634 if (!IsHostAttached ()) {\r
18b144ea 1635 //\r
93c0bdec 1636 // If HOST is not connected for image load/unload, return\r
18b144ea 1637 //\r
93c0bdec 1638 break;\r
18b144ea 1639 }\r
93c0bdec 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
18b144ea 1650 AcquireDebugPortControl ();\r
93c0bdec 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
18b144ea 1656 }\r
18b144ea 1657 ReleaseDebugPortControl ();\r
93c0bdec 1658 \r
18b144ea 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
93c0bdec 1677 break;\r
18b144ea 1678 }\r
1679\r
1680 break;\r
1681\r
1682 case DEBUG_TIMER_VECTOR:\r
1683\r
93c0bdec 1684 AcquireDebugPortControl ();\r
1685\r
18b144ea 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
93c0bdec 1700 ReleaseDebugPortControl ();\r
18b144ea 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
93c0bdec 1719 while (TRUE) {\r
18b144ea 1720 //\r
93c0bdec 1721 // If there is data in debug port, will check whether it is break(attach/break-in) symbol,\r
18b144ea 1722 // If yes, go into communication mode with HOST.\r
1723 // If no, exit interrupt process.\r
1724 //\r
93c0bdec 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
18b144ea 1735 SendAckPacket (DEBUG_COMMAND_OK);\r
93c0bdec 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
18b144ea 1746 if (MultiProcessorDebugSupport) {\r
93c0bdec 1747 if(FindNextPendingBreakCpu () != -1) {\r
18b144ea 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
93c0bdec 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
18b144ea 1779 }\r
93c0bdec 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
18b144ea 1793 }\r
93c0bdec 1794 \r
18b144ea 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
93c0bdec 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
18b144ea 1822 }\r
1823\r
1824 return;\r
1825}\r
1826\r