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