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
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.
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.
18 #include "DebugAgent.h"
19 #include "Ia32/DebugException.h"
21 #define INIT_BREAK_ACK_TIMEOUT (200 * 1000)
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";
29 Send a debug message packet to the debug port.
31 @param[in] Buffer The debug message.
32 @param[in] Length The length of debug message.
41 DEBUG_PACKET_HEADER DebugHeader
;
42 DEBUG_PORT_HANDLE Handle
;
44 Handle
= GetDebugPortHandle();
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
));
52 DebugPortWriteBuffer (Handle
, (UINT8
*)&DebugHeader
, sizeof (DEBUG_PACKET_HEADER
));
53 DebugPortWriteBuffer (Handle
, (UINT8
*)Buffer
, Length
);
57 Prints a debug message to the debug port if the specified error level is enabled.
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.
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.
76 DEBUG_AGENT_MAILBOX
*Mailbox
;
77 CHAR8 Buffer
[DEBUG_DATA_MAXIMUM_REAL_DATA
];
80 Mailbox
= GetMailboxPointer ();
82 // Check driver debug mask value and global mask
84 if ((ErrorLevel
& Mailbox
->DebugFlag
.PrintErrorLevel
) == 0) {
89 // Convert the DEBUG() message to an ASCII String
91 VA_START (Marker
, Format
);
92 AsciiVSPrint (Buffer
, sizeof (Buffer
), Format
, Marker
);
95 SendDebugMsgPacket (Buffer
, AsciiStrLen (Buffer
));
99 Prints a debug message to the debug output device if the specified error level is enabled.
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.
105 If Format is NULL, then ASSERT().
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.
115 DebugAgentDataMsgPrint (
122 DEBUG_AGENT_MAILBOX
*Mailbox
;
123 CHAR8 Buffer
[DEBUG_DATA_MAXIMUM_REAL_DATA
];
127 Mailbox
= GetMailboxPointer ();
129 // Check driver debug mask value and global mask
131 if ((ErrorLevel
& Mailbox
->DebugFlag
.PrintErrorLevel
) == 0) {
137 DestBuffer
+= AsciiSPrint (DestBuffer
, DEBUG_DATA_MAXIMUM_REAL_DATA
, "Sent data [ ");
139 DestBuffer
+= AsciiSPrint (DestBuffer
, DEBUG_DATA_MAXIMUM_REAL_DATA
, "Received data [ ");
144 if (DestBuffer
- Buffer
> DEBUG_DATA_MAXIMUM_REAL_DATA
- 6) {
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".
149 SendDebugMsgPacket (Buffer
, DestBuffer
- Buffer
);
152 DestBuffer
+= AsciiSPrint (DestBuffer
, DEBUG_DATA_MAXIMUM_REAL_DATA
- (DestBuffer
- Buffer
), "%02x ", Data
[Index
]);
154 if (Index
>= Length
) {
156 // The last character of debug message has been foramtted in buffer
158 DestBuffer
+= AsciiSPrint(DestBuffer
, DEBUG_DATA_MAXIMUM_REAL_DATA
- (DestBuffer
- Buffer
), "]\n");
159 SendDebugMsgPacket (Buffer
, DestBuffer
- Buffer
);
167 Check if HOST is attached based on Mailbox.
169 @retval TRUE HOST is attached.
170 @retval FALSE HOST is not attached.
178 return (BOOLEAN
) (GetMailboxPointer ()->DebugFlag
.HostAttached
== 1);
182 Set HOST connect flag in Mailbox.
184 @param[in] Attached Attach status.
192 DebugAgentMsgPrint (DEBUG_AGENT_INFO
, "Attach status is %d\n", Attached
);
193 GetMailboxPointer ()->DebugFlag
.HostAttached
= Attached
;
197 Set debug setting of Debug Agent in Mailbox.
199 @param DebugSetting Pointer to Debug Setting defined by transfer protocol.
201 @retval RETURN_SUCCESS The setting is set successfully.
202 @retval RETURN_UNSUPPORTED The Key value is not supported.
207 IN DEBUG_DATA_SET_DEBUG_SETTING
*DebugSetting
210 RETURN_STATUS Status
;
211 DEBUG_AGENT_MAILBOX
*Mailbox
;
213 Mailbox
= GetMailboxPointer ();
215 Status
= RETURN_SUCCESS
;
216 switch (DebugSetting
->Key
) {
217 case DEBUG_AGENT_SETTING_SMM_ENTRY_BREAK
:
218 Mailbox
->DebugFlag
.BreakOnNextSmi
= DebugSetting
->Value
;
220 case DEBUG_AGENT_SETTING_PRINT_ERROR_LEVEL
:
221 Mailbox
->DebugFlag
.PrintErrorLevel
= DebugSetting
->Value
;
224 Status
= RETURN_UNSUPPORTED
;
232 @param[in] CpuContext Pointer to saved CPU context.
237 IN DEBUG_CPU_CONTEXT
*CpuContext
240 IA32_EFLAGS32
*Eflags
;
242 Eflags
= (IA32_EFLAGS32
*) &CpuContext
->Eflags
;
248 Exectue Stepping command.
250 @param[in] CpuContext Pointer to saved CPU context.
255 IN DEBUG_CPU_CONTEXT
*CpuContext
258 IA32_EFLAGS32
*Eflags
;
260 Eflags
= (IA32_EFLAGS32
*) &CpuContext
->Eflags
;
266 Set debug register for hardware breakpoint.
268 @param[in] CpuContext Pointer to saved CPU context.
269 @param[in] SetHwBreakpoint Hardware breakpoint to be set.
274 IN DEBUG_CPU_CONTEXT
*CpuContext
,
275 IN DEBUG_DATA_SET_HW_BREAKPOINT
*SetHwBreakpoint
281 RegisterIndex
= SetHwBreakpoint
->Type
.Index
;
286 * ((UINTN
*) &CpuContext
->Dr0
+ RegisterIndex
) = (UINTN
) SetHwBreakpoint
->Address
;
288 Dr7Value
= CpuContext
->Dr7
;
293 Dr7Value
|= 0x3 << (RegisterIndex
* 2);
297 Dr7Value
&= ~(0xf << (16 + RegisterIndex
* 4));
298 Dr7Value
|= (UINTN
) ((SetHwBreakpoint
->Type
.Length
<< 2) | SetHwBreakpoint
->Type
.Access
) << (16 + RegisterIndex
* 4);
304 CpuContext
->Dr7
= Dr7Value
;
308 Clear debug register for hardware breakpoint.
310 @param[in] CpuContext Pointer to saved CPU context.
311 @param[in] ClearHwBreakpoint Hardware breakpoint to be cleared.
316 IN DEBUG_CPU_CONTEXT
*CpuContext
,
317 IN DEBUG_DATA_CLEAR_HW_BREAKPOINT
*ClearHwBreakpoint
320 if ((ClearHwBreakpoint
->IndexMask
& BIT0
) != 0) {
322 CpuContext
->Dr7
&= ~(0x3 << 0);
324 if ((ClearHwBreakpoint
->IndexMask
& BIT1
) != 0) {
326 CpuContext
->Dr7
&= ~(0x3 << 2);
328 if ((ClearHwBreakpoint
->IndexMask
& BIT2
) != 0) {
330 CpuContext
->Dr7
&= ~(0x3 << 4);
332 if ((ClearHwBreakpoint
->IndexMask
& BIT3
) != 0) {
334 CpuContext
->Dr7
&= ~(0x3 << 6);
340 Return the offset of FP / MMX / XMM registers in the FPU saved state by register index.
342 @param[in] Index Register index.
343 @param[out] Width Register width returned.
345 @return Offset in the FPU Save State.
349 ArchReadFxStatOffset (
354 if (Index
< SOFT_DEBUGGER_REGISTER_ST0
) {
356 case SOFT_DEBUGGER_REGISTER_FP_FCW
:
357 *Width
= (UINT8
) sizeof (UINT16
);
358 return OFFSET_OF(DEBUG_DATA_FX_SAVE_STATE
, Fcw
);
360 case SOFT_DEBUGGER_REGISTER_FP_FSW
:
361 *Width
= (UINT8
) sizeof (UINT16
);
362 return OFFSET_OF(DEBUG_DATA_FX_SAVE_STATE
, Fsw
);
364 case SOFT_DEBUGGER_REGISTER_FP_FTW
:
365 *Width
= (UINT8
) sizeof (UINT16
);
366 return OFFSET_OF(DEBUG_DATA_FX_SAVE_STATE
, Ftw
);
368 case SOFT_DEBUGGER_REGISTER_FP_OPCODE
:
369 *Width
= (UINT8
) sizeof (UINT16
);
370 return OFFSET_OF(DEBUG_DATA_FX_SAVE_STATE
, Opcode
);
372 case SOFT_DEBUGGER_REGISTER_FP_EIP
:
373 *Width
= (UINT8
) sizeof (UINT32
);
374 return OFFSET_OF(DEBUG_DATA_FX_SAVE_STATE
, Eip
);
376 case SOFT_DEBUGGER_REGISTER_FP_CS
:
377 *Width
= (UINT8
) sizeof (UINT16
);
378 return OFFSET_OF(DEBUG_DATA_FX_SAVE_STATE
, Cs
);
380 case SOFT_DEBUGGER_REGISTER_FP_DATAOFFSET
:
381 *Width
= (UINT8
) sizeof (UINT32
);
382 return OFFSET_OF(DEBUG_DATA_FX_SAVE_STATE
, DataOffset
);
384 case SOFT_DEBUGGER_REGISTER_FP_DS
:
385 *Width
= (UINT8
) sizeof (UINT16
);
386 return OFFSET_OF(DEBUG_DATA_FX_SAVE_STATE
, Ds
);
388 case SOFT_DEBUGGER_REGISTER_FP_MXCSR
:
389 *Width
= (UINT8
) sizeof (UINT32
);
390 return OFFSET_OF(DEBUG_DATA_FX_SAVE_STATE
, Mxcsr
);
392 case SOFT_DEBUGGER_REGISTER_FP_MXCSR_MASK
:
393 *Width
= (UINT8
) sizeof (UINT32
);
394 return OFFSET_OF(DEBUG_DATA_FX_SAVE_STATE
, Mxcsr_Mask
);
398 if (Index
<= SOFT_DEBUGGER_REGISTER_ST7
) {
400 } else if (Index
<= SOFT_DEBUGGER_REGISTER_XMM15
) {
407 Index
-= SOFT_DEBUGGER_REGISTER_MM0
- SOFT_DEBUGGER_REGISTER_ST0
;
410 return OFFSET_OF (DEBUG_DATA_FX_SAVE_STATE
, St0Mm0
) + (Index
- SOFT_DEBUGGER_REGISTER_ST0
) * 16;
414 Return the pointer of the register value in the CPU saved context.
416 @param[in] CpuContext Pointer to saved CPU context.
417 @param[in] Index Register index value.
418 @param[out] Width Data width to read.
420 @return The pointer in the CPU saved context.
424 ArchReadRegisterBuffer (
425 IN DEBUG_CPU_CONTEXT
*CpuContext
,
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
);
437 // FPU/MMX/XMM registers
439 Buffer
= (UINT8
*) CpuContext
+ OFFSET_OF (DEBUG_CPU_CONTEXT
, FxSaveState
) + ArchReadFxStatOffset (Index
, Width
);
446 Send the packet without data to HOST.
448 @param[in] CommandType Type of Command.
452 SendPacketWithoutData (
456 DEBUG_PACKET_HEADER DebugHeader
;
457 DEBUG_PORT_HANDLE Handle
;
459 Handle
= GetDebugPortHandle();
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
));
467 DebugAgentDataMsgPrint (DEBUG_AGENT_VERBOSE
, TRUE
, (UINT8
*) &DebugHeader
, DebugHeader
.Length
);
468 DebugPortWriteBuffer (Handle
, (UINT8
*) &DebugHeader
, DebugHeader
.Length
);
472 Send acknowledge packet to HOST.
474 @param[in] AckCommand Type of Acknowledge packet.
482 if (AckCommand
!= DEBUG_COMMAND_OK
) {
483 DebugAgentMsgPrint (DEBUG_AGENT_ERROR
, "Send ACK(%d)\n", AckCommand
);
485 SendPacketWithoutData (AckCommand
);
489 Receive acknowledge packet from HOST in specified time.
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.
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.
510 OUT BOOLEAN
*BreakReceived
, OPTIONAL
511 OUT RETURN_STATUS
*CheckSumStatus OPTIONAL
514 DEBUG_PACKET_HEADER DebugHeader
;
515 DEBUG_PORT_HANDLE Handle
;
517 Handle
= GetDebugPortHandle();
520 if (DebugPortReadBuffer (Handle
, (UINT8
*) &DebugHeader
.StartSymbol
, sizeof (DebugHeader
.StartSymbol
), Timeout
) == 0) {
521 return RETURN_TIMEOUT
;
523 if (DebugHeader
.StartSymbol
== DEBUG_STARTING_SYMBOL_BREAK
) {
524 if (BreakReceived
!= NULL
) {
525 SendAckPacket (DEBUG_COMMAND_HALT_DEFERRED
);
526 *BreakReceived
= TRUE
;
529 if (DebugHeader
.StartSymbol
== DEBUG_STARTING_SYMBOL_NORMAL
) {
532 DebugAgentMsgPrint (DEBUG_AGENT_ERROR
, "Invalid start symbol received [%02x]\n", DebugHeader
.StartSymbol
);
535 // Read ACK packet header till field Length (not including StartSymbol and CheckSum)
537 DebugHeader
.Length
= 0;
538 if (DebugPortReadBuffer (
540 (UINT8
*)&DebugHeader
.Command
,
541 OFFSET_OF (DEBUG_PACKET_HEADER
, Length
) + sizeof (DebugHeader
.Length
) - sizeof (DebugHeader
.StartSymbol
),
544 return RETURN_TIMEOUT
;
547 if (DebugHeader
.Length
== 0) {
549 // The CheckSum field does not exist
551 if (CheckSumStatus
!= NULL
) {
552 *CheckSumStatus
= RETURN_NOT_FOUND
;
555 if (CheckSumStatus
!= NULL
) {
556 *CheckSumStatus
= RETURN_SUCCESS
;
558 if (DebugPortReadBuffer (Handle
, &DebugHeader
.CheckSum
, sizeof (DebugHeader
.CheckSum
), Timeout
) == 0) {
559 return RETURN_TIMEOUT
;
563 DebugAgentDataMsgPrint (DEBUG_AGENT_VERBOSE
, FALSE
, (UINT8
*)&DebugHeader
, DebugHeader
.Length
);
564 *Ack
= DebugHeader
.Command
;
565 return RETURN_SUCCESS
;
569 Receive acknowledge packet OK from HOST in specified time.
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.
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.
587 SendCommandAndWaitForAckOK (
590 OUT BOOLEAN
*BreakReceived
, OPTIONAL
591 OUT RETURN_STATUS
*CheckSumStatus OPTIONAL
594 RETURN_STATUS Status
;
598 SendPacketWithoutData (Command
);
600 Status
= ReceiveAckPacket (&Ack
, Timeout
, BreakReceived
, CheckSumStatus
);
601 if (Status
== RETURN_SUCCESS
&& Ack
== DEBUG_COMMAND_RESEND
) {
603 // Resend the last command
607 if ((Status
== RETURN_SUCCESS
&& Ack
== DEBUG_COMMAND_OK
) ||
608 Status
== RETURN_TIMEOUT
) {
610 // Received Ack OK or timeout
619 Receive valid packet from HOST.
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.
625 @retval RETURN_SUCCESS A valid package was reveived in InputPacket.
626 @retval RETURN_TIMEOUT Timeout occurs.
631 OUT UINT8
*InputPacket
,
632 OUT BOOLEAN
*BreakReceived
635 DEBUG_PACKET_HEADER
*DebugHeader
;
637 DEBUG_PORT_HANDLE Handle
;
640 Handle
= GetDebugPortHandle();
642 DebugHeader
= (DEBUG_PACKET_HEADER
*) InputPacket
;
645 // Find the valid start symbol
647 DebugPortReadBuffer (Handle
, &DebugHeader
->StartSymbol
, sizeof (DebugHeader
->StartSymbol
), 0);
649 if (DebugHeader
->StartSymbol
== DEBUG_STARTING_SYMBOL_BREAK
) {
650 *BreakReceived
= TRUE
;
651 SendAckPacket (DEBUG_COMMAND_HALT_DEFERRED
);
654 if (DebugHeader
->StartSymbol
!= DEBUG_STARTING_SYMBOL_NORMAL
) {
655 DebugAgentMsgPrint (DEBUG_AGENT_ERROR
, "Invalid start symbol received [%02x]\n", DebugHeader
->StartSymbol
);
660 // Read Package header except for checksum
662 Received
= DebugPortReadBuffer (
664 &DebugHeader
->Command
,
665 OFFSET_OF (DEBUG_PACKET_HEADER
, Length
) + sizeof (DebugHeader
->Length
) - sizeof (DebugHeader
->StartSymbol
),
669 return RETURN_TIMEOUT
;
673 // Read the payload data include the checksum
675 Received
= DebugPortReadBuffer (Handle
, &DebugHeader
->CheckSum
, DebugHeader
->Length
- OFFSET_OF (DEBUG_PACKET_HEADER
, CheckSum
), 0);
677 return RETURN_TIMEOUT
;
680 // Calculate the checksum of Debug Packet
682 CheckSum
= CalculateCheckSum8 ((UINT8
*) DebugHeader
, DebugHeader
->Length
);
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
);
691 DebugAgentDataMsgPrint (DEBUG_AGENT_VERBOSE
, FALSE
, (UINT8
*) DebugHeader
, DebugHeader
->Length
);
693 return RETURN_SUCCESS
;
697 Get current break cause.
699 @param[in] Vector Vector value of exception or interrupt.
700 @param[in] CpuContext Pointer to save CPU context.
702 @return The type of break cause defined by XXXX
708 IN DEBUG_CPU_CONTEXT
*CpuContext
713 Cause
= DEBUG_DATA_BREAK_CAUSE_UNKNOWN
;
716 case DEBUG_INT1_VECTOR
:
717 case DEBUG_INT3_VECTOR
:
719 if (Vector
== DEBUG_INT1_VECTOR
) {
723 if ((CpuContext
->Dr6
& BIT14
) != 0) {
724 Cause
= DEBUG_DATA_BREAK_CAUSE_STEPPING
;
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).
732 Cause
= DEBUG_DATA_BREAK_CAUSE_HW_BREAKPOINT
;
738 Cause
= DEBUG_DATA_BREAK_CAUSE_SW_BREAKPOINT
;
741 switch (CpuContext
->Dr0
) {
742 case IMAGE_LOAD_SIGNATURE
:
743 case IMAGE_UNLOAD_SIGNATURE
:
745 if (CpuContext
->Dr3
== IO_PORT_BREAKPOINT_ADDRESS
) {
747 Cause
= (UINT8
) ((CpuContext
->Dr0
== IMAGE_LOAD_SIGNATURE
) ?
748 DEBUG_DATA_BREAK_CAUSE_IMAGE_LOAD
: DEBUG_DATA_BREAK_CAUSE_IMAGE_UNLOAD
);
752 case SOFT_INTERRUPT_SIGNATURE
:
754 if (CpuContext
->Dr1
== MEMORY_READY_SIGNATURE
) {
755 Cause
= DEBUG_DATA_BREAK_CAUSE_MEMORY_READY
;
757 } else if (CpuContext
->Dr1
== SYSTEM_RESET_SIGNATURE
) {
758 Cause
= DEBUG_DATA_BREAK_CAUSE_SYSTEM_RESET
;
770 case DEBUG_TIMER_VECTOR
:
771 Cause
= DEBUG_DATA_BREAK_CAUSE_USER_HALT
;
776 if (GetMailboxPointer()->DebugFlag
.SteppingFlag
== 1) {
778 // If stepping command is executing
780 Cause
= DEBUG_DATA_BREAK_CAUSE_STEPPING
;
782 Cause
= DEBUG_DATA_BREAK_CAUSE_EXCEPTION
;
792 Send command packet with data to HOST.
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.
798 @retval RETURN_SUCCESS Response data was sent successfully.
799 @retval RETURN_DEVICE_ERROR Cannot receive DEBUG_COMMAND_OK from HOST.
803 SendCommandWithDataPacket (
809 DEBUG_PACKET_HEADER
*DebugHeader
;
812 UINT8 DebugPacket
[DEBUG_DATA_UPPER_LIMIT
];
813 DEBUG_PORT_HANDLE Handle
;
815 Handle
= GetDebugPortHandle();
817 DebugHeader
= (DEBUG_PACKET_HEADER
*) &DebugPacket
;
818 DebugHeader
->StartSymbol
= DEBUG_STARTING_SYMBOL_NORMAL
;
821 if (DataSize
<= DEBUG_DATA_MAXIMUM_REAL_DATA
) {
823 DebugHeader
->Command
= Command
;
824 DebugHeader
->Length
= (UINT8
) (DataSize
+ sizeof (DEBUG_PACKET_HEADER
));
825 DebugHeader
->CheckSum
= 0;
826 CopyMem (DebugHeader
+ 1, Data
, DataSize
);
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
);
837 // Calculate and fill the checksum
839 DebugHeader
->CheckSum
= CalculateCheckSum8 ((UINT8
*) DebugHeader
, DebugHeader
->Length
);
841 DebugAgentDataMsgPrint (DEBUG_AGENT_VERBOSE
, TRUE
, (UINT8
*) DebugHeader
, DebugHeader
->Length
);
843 DebugPortWriteBuffer (Handle
, (UINT8
*) DebugHeader
, DebugHeader
->Length
);
845 ReceiveAckPacket(&Ack
, 0, NULL
, NULL
);
847 case DEBUG_COMMAND_RESEND
:
849 // Send the packet again
851 DebugAgentMsgPrint (DEBUG_AGENT_WARNING
, "Received DEBUG_COMMAND_RESEND.\n");
854 case DEBUG_COMMAND_CONTINUE
:
856 // Send the rest packet
858 Data
+= DEBUG_DATA_MAXIMUM_REAL_DATA
;
859 DataSize
-= DEBUG_DATA_MAXIMUM_REAL_DATA
;
862 case DEBUG_COMMAND_OK
:
865 // If this is the last packet, return RETURN_SUCCESS.
867 return RETURN_SUCCESS
;
869 return RETURN_DEVICE_ERROR
;
873 return RETURN_DEVICE_ERROR
;
880 Send packet with response data to HOST.
882 @param[in] Data Pointer to response data buffer.
883 @param[in] DataSize Size of response data in byte.
885 @retval RETURN_SUCCESS Response data was sent successfully.
886 @retval RETURN_DEVICE_ERROR Cannot receive DEBUG_COMMAND_OK from HOST.
890 SendDataResponsePacket (
895 return SendCommandWithDataPacket (DEBUG_COMMAND_OK
, Data
, DataSize
);
899 Send break cause packet to HOST.
901 @param[in] Vector Vector value of exception or interrutp.
902 @param[in] CpuContext Pointer to save CPU context.
904 @retval RETURN_SUCCESS Response data was sent successfully.
905 @retval RETURN_DEVICE_ERROR Cannot receive DEBUG_COMMAND_OK from HOST.
909 SendBreakCausePacket (
911 IN DEBUG_CPU_CONTEXT
*CpuContext
914 DEBUG_DATA_RESPONSE_BREAK_CAUSE DebugDataBreakCause
;
916 DebugDataBreakCause
.StopAddress
= CpuContext
->Eip
;
917 DebugDataBreakCause
.Cause
= GetBreakCause (Vector
, CpuContext
);
919 return SendDataResponsePacket ((UINT8
*) &DebugDataBreakCause
, (UINT16
) sizeof (DEBUG_DATA_RESPONSE_BREAK_CAUSE
));
923 Try to attach the HOST.
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.
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.
939 OUT BOOLEAN
*BreakReceived
942 RETURN_STATUS Status
;
943 DEBUG_PORT_HANDLE Handle
;
944 RETURN_STATUS CheckSumStatus
;
946 Handle
= GetDebugPortHandle();
949 // Send init break and wait ack in Timeout
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
));
958 if (CheckSumStatus
== RETURN_NOT_FOUND
) {
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.
964 DebugPortWriteBuffer (Handle
, (UINT8
*) mErrorMsgVersionAlert
, AsciiStrLen (mErrorMsgVersionAlert
));
968 DebugPortWriteBuffer (Handle
, (UINT8
*) mErrorMsgConnectOK
, AsciiStrLen (mErrorMsgConnectOK
));
972 SetHostAttached (TRUE
);
978 Send Break point packet to HOST.
980 Only the first breaking processor could sent BREAK_POINT packet.
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.
989 SendBreakPacketToHost (
990 IN UINT32 ProcessorIndex
,
991 OUT BOOLEAN
*BreakReceived
994 UINT8 InputCharacter
;
995 DEBUG_PORT_HANDLE Handle
;
997 Handle
= GetDebugPortHandle();
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
);
1003 DebugAgentMsgPrint (DEBUG_AGENT_INFO
, "processor[%x]:Try to attach HOST.\n", ProcessorIndex
);
1005 // If HOST is not attached, try to attach it firstly.
1008 // Poll Attach symbols from HOST and ack OK
1011 DebugPortReadBuffer (Handle
, &InputCharacter
, 1, 0);
1012 } while (InputCharacter
!= DEBUG_STARTING_SYMBOL_ATTACH
);
1013 SendAckPacket (DEBUG_COMMAND_OK
);
1016 // Try to attach HOST
1018 while (AttachHost (0, NULL
) != RETURN_SUCCESS
);
1024 The main function to process communication with HOST.
1026 It received the command packet from HOST, and sent response data packet to HOST.
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.
1035 CommandCommunication (
1037 IN OUT DEBUG_CPU_CONTEXT
*CpuContext
,
1038 IN BOOLEAN BreakReceived
1041 RETURN_STATUS Status
;
1042 UINT8 InputPacketBuffer
[DEBUG_DATA_UPPER_LIMIT
];
1043 DEBUG_PACKET_HEADER
*DebugHeader
;
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
;
1070 IssuedViewPoint
= 0;
1071 HaltDeferred
= BreakReceived
;
1073 if (MultiProcessorDebugSupport
) {
1074 ProcessorIndex
= GetProcessorIndex ();
1075 SetCpuStopFlagByIndex (ProcessorIndex
, TRUE
);
1076 if (mDebugMpContext
.ViewPointIndex
== ProcessorIndex
) {
1078 // Only the current view processor could set AgentInProgress Flag.
1080 IssuedViewPoint
= ProcessorIndex
;
1084 if (IssuedViewPoint
== ProcessorIndex
) {
1086 // Set AgentInProgress Flag.
1088 GetMailboxPointer()->DebugFlag
.AgentInProgress
= 1;
1091 Handle
= GetDebugPortHandle();
1095 if (MultiProcessorDebugSupport
) {
1097 // Check if the current processor is HOST view point
1099 if (mDebugMpContext
.ViewPointIndex
!= ProcessorIndex
) {
1100 if (mDebugMpContext
.RunCommandSet
) {
1102 // If HOST view point sets RUN flag, run GO command to leave
1104 SetCpuStopFlagByIndex (ProcessorIndex
, FALSE
);
1105 CommandGo (CpuContext
);
1109 // Run into loop again
1117 AcquireDebugPortControl ();
1119 Status
= ReceivePacket (InputPacketBuffer
, &BreakReceived
);
1121 if (BreakReceived
) {
1122 HaltDeferred
= TRUE
;
1123 BreakReceived
= FALSE
;
1126 if (Status
!= RETURN_SUCCESS
) {
1127 ReleaseDebugPortControl ();
1133 DebugHeader
=(DEBUG_PACKET_HEADER
*) InputPacketBuffer
;
1135 GetMailboxPointer()->ExceptionBufferPointer
= (UINT64
)(UINTN
) &AgentExceptionBuffer
.JumpBuffer
;
1137 // Save CPU content before executing HOST commond
1139 if (SetJump (&AgentExceptionBuffer
.JumpBuffer
) != 0) {
1141 // If HOST command failed, continue to wait for HOST's next command
1142 // If needed, agent could send exception info to HOST.
1144 SendAckPacket (DEBUG_COMMAND_ABORT
);
1145 ReleaseDebugPortControl ();
1149 DebugAgentMsgPrint (DEBUG_AGENT_INFO
, "Processor[%x]:Received one command(%x)\n", mDebugMpContext
.ViewPointIndex
, DebugHeader
->Command
);
1151 switch (DebugHeader
->Command
) {
1153 case DEBUG_COMMAND_RESET
:
1154 SendAckPacket (DEBUG_COMMAND_OK
);
1155 ReleaseDebugPortControl ();
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.
1162 MicroSecondDelay (2000000);
1163 SendAckPacket (DEBUG_COMMAND_TIMEOUT
);
1166 case DEBUG_COMMAND_GO
:
1167 CommandGo (CpuContext
);
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
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;
1177 // Clear Stepping Flag
1179 GetMailboxPointer()->DebugFlag
.SteppingFlag
= 0;
1181 if (!HaltDeferred
) {
1183 // If no HALT command received when being in-active mode
1185 if (MultiProcessorDebugSupport
) {
1186 Data32
= FindNextPendingBreakCpu ();
1189 // If there are still others processors being in break state,
1190 // send OK packet to HOST to finish this go command
1192 SendAckPacket (DEBUG_COMMAND_OK
);
1195 // Set current view to the next breaking processor
1197 mDebugMpContext
.ViewPointIndex
= Data32
;
1198 mDebugMpContext
.BreakAtCpuIndex
= mDebugMpContext
.ViewPointIndex
;
1199 SetCpuBreakFlagByIndex (mDebugMpContext
.ViewPointIndex
, FALSE
);
1201 // Send break packet to HOST to let HOST break again
1203 SendBreakPacketToHost (0, &BreakReceived
);
1205 // Continue to run into loop to read command packet from HOST
1207 ReleaseDebugPortControl ();
1212 // If no else processor break, set stop bitmask,
1213 // and set Running flag for all processors.
1215 SetCpuStopFlagByIndex (ProcessorIndex
, FALSE
);
1216 SetCpuRunningFlag (TRUE
);
1219 // Wait for all processors are in running state
1222 if (IsAllCpuRunning ()) {
1227 // Set BSP to be current view point.
1229 SetDebugViewPoint (mDebugMpContext
.BspIndex
);
1232 // Clear breaking processor index and running flag
1234 mDebugMpContext
.BreakAtCpuIndex
= (UINT32
) (-1);
1235 SetCpuRunningFlag (FALSE
);
1239 // Send OK packet to HOST to finish this go command
1241 SendAckPacket (DEBUG_COMMAND_OK
);
1243 ReleaseDebugPortControl ();
1249 // If reveived HALT command, need to defer the GO command
1251 SendAckPacket (DEBUG_COMMAND_HALT_PROCESSED
);
1252 HaltDeferred
= FALSE
;
1254 Vector
= DEBUG_TIMER_VECTOR
;
1258 case DEBUG_COMMAND_BREAK_CAUSE
:
1260 if (MultiProcessorDebugSupport
&& ProcessorIndex
!= mDebugMpContext
.BreakAtCpuIndex
) {
1261 Status
= SendBreakCausePacket (DEBUG_TIMER_VECTOR
, CpuContext
);
1264 Status
= SendBreakCausePacket (Vector
, CpuContext
);
1269 case DEBUG_COMMAND_SET_HW_BREAKPOINT
:
1270 SetDebugRegister (CpuContext
, (DEBUG_DATA_SET_HW_BREAKPOINT
*) (DebugHeader
+ 1));
1271 SendAckPacket (DEBUG_COMMAND_OK
);
1274 case DEBUG_COMMAND_CLEAR_HW_BREAKPOINT
:
1275 ClearDebugRegister (CpuContext
, (DEBUG_DATA_CLEAR_HW_BREAKPOINT
*) (DebugHeader
+ 1));
1276 SendAckPacket (DEBUG_COMMAND_OK
);
1279 case DEBUG_COMMAND_SINGLE_STEPPING
:
1280 CommandStepping (CpuContext
);
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
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;
1290 mDebugMpContext
.BreakAtCpuIndex
= (UINT32
) (-1);
1292 // Set Stepping Flag
1294 GetMailboxPointer()->DebugFlag
.SteppingFlag
= 1;
1295 ReleaseDebugPortControl ();
1297 // Executing stepping command directly without sending ACK packet,
1298 // ACK packet will be sent after stepping done.
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
));
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
));
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
);
1320 case DEBUG_COMMAND_READ_IO
:
1321 IoRead
= (DEBUG_DATA_READ_IO
*) (DebugHeader
+ 1);
1322 switch (IoRead
->Width
) {
1324 Data64
= IoRead8 ((UINTN
) IoRead
->Port
);
1327 Data64
= IoRead16 ((UINTN
) IoRead
->Port
);
1330 Data64
= IoRead32 ((UINTN
) IoRead
->Port
);
1333 Data64
= IoRead64 ((UINTN
) IoRead
->Port
);
1336 Data64
= (UINT64
) -1;
1338 Status
= SendDataResponsePacket ((UINT8
*) &Data64
, IoRead
->Width
);
1341 case DEBUG_COMMAND_WRITE_IO
:
1342 IoWrite
= (DEBUG_DATA_WRITE_IO
*) (DebugHeader
+ 1);
1343 switch (IoWrite
->Width
) {
1345 Data64
= IoWrite8 ((UINTN
) IoWrite
->Port
, *(UINT8
*) &IoWrite
->Data
);
1348 Data64
= IoWrite16 ((UINTN
) IoWrite
->Port
, *(UINT16
*) &IoWrite
->Data
);
1351 Data64
= IoWrite32 ((UINTN
) IoWrite
->Port
, *(UINT32
*) &IoWrite
->Data
);
1354 Data64
= IoWrite64 ((UINTN
) IoWrite
->Port
, *(UINT64
*) &IoWrite
->Data
);
1357 Data64
= (UINT64
) -1;
1359 SendAckPacket (DEBUG_COMMAND_OK
);
1362 case DEBUG_COMMAND_READ_ALL_REGISTERS
:
1363 Status
= SendDataResponsePacket ((UINT8
*) CpuContext
, sizeof (*CpuContext
));
1366 case DEBUG_COMMAND_READ_REGISTER
:
1367 RegisterRead
= (DEBUG_DATA_READ_REGISTER
*) (DebugHeader
+ 1);
1369 if (RegisterRead
->Index
<= SOFT_DEBUGGER_REGISTER_MAX
) {
1370 RegisterBuffer
= ArchReadRegisterBuffer (CpuContext
, RegisterRead
->Index
, &Width
);
1371 Status
= SendDataResponsePacket (RegisterBuffer
, Width
);
1373 Status
= RETURN_UNSUPPORTED
;
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
);
1385 Status
= RETURN_UNSUPPORTED
;
1389 case DEBUG_COMMAND_ARCH_MODE
:
1390 Data8
= DEBUG_ARCH_SYMBOL
;
1391 Status
= SendDataResponsePacket ((UINT8
*) &Data8
, (UINT16
) sizeof (UINT8
));
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
));
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
);
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
);
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
));
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
));
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
);
1433 // If CPU is not halted
1435 SendAckPacket (DEBUG_COMMAND_NOT_SUPPORTED
);
1437 } else if (SetViewPoint
->ViewPoint
== 0) {
1438 SendAckPacket (DEBUG_COMMAND_OK
);
1441 SendAckPacket (DEBUG_COMMAND_NOT_SUPPORTED
);
1446 case DEBUG_COMMAND_GET_VIEWPOINT
:
1447 Data32
= mDebugMpContext
.ViewPointIndex
;
1448 SendDataResponsePacket((UINT8
*) &Data32
, (UINT16
) sizeof (UINT32
));
1451 case DEBUG_COMMAND_MEMORY_READY
:
1452 Data8
= (UINT8
) GetMailboxPointer ()->DebugFlag
.MemoryReady
;
1453 SendDataResponsePacket (&Data8
, (UINT16
) sizeof (UINT8
));
1456 case DEBUG_COMMAND_DETACH
:
1457 SetHostAttached (FALSE
);
1458 SendAckPacket (DEBUG_COMMAND_OK
);
1461 case DEBUG_COMMAND_CPUID
:
1462 Cpuid
= (DEBUG_DATA_CPUID
*) (DebugHeader
+ 1);
1464 Cpuid
->Eax
, Cpuid
->Ecx
,
1465 &CpuidResponse
.Eax
, &CpuidResponse
.Ebx
,
1466 &CpuidResponse
.Ecx
, &CpuidResponse
.Edx
1468 SendDataResponsePacket ((UINT8
*) &CpuidResponse
, (UINT16
) sizeof (CpuidResponse
));
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
))
1476 if (SearchSignature
->Positive
) {
1478 Data64
= ALIGN_VALUE ((UINTN
) SearchSignature
->Start
, SearchSignature
->Alignment
);
1479 Data64
<= SearchSignature
->Start
+ SearchSignature
->Count
- SearchSignature
->DataLength
;
1480 Data64
+= SearchSignature
->Alignment
1482 if (CompareMem ((VOID
*) (UINTN
) Data64
, &SearchSignature
->Data
, SearchSignature
->DataLength
) == 0) {
1486 if (Data64
> SearchSignature
->Start
+ SearchSignature
->Count
- SearchSignature
->DataLength
) {
1487 Data64
= (UINT64
) -1;
1491 Data64
= ALIGN_VALUE ((UINTN
) SearchSignature
->Start
- SearchSignature
->Alignment
, SearchSignature
->Alignment
);
1492 Data64
>= SearchSignature
->Start
- SearchSignature
->Count
;
1493 Data64
-= SearchSignature
->Alignment
1495 if (CompareMem ((VOID
*) (UINTN
) Data64
, &SearchSignature
->Data
, SearchSignature
->DataLength
) == 0) {
1499 if (Data64
< SearchSignature
->Start
- SearchSignature
->Count
) {
1500 Data64
= (UINT64
) -1;
1503 SendDataResponsePacket ((UINT8
*) &Data64
, (UINT16
) sizeof (Data64
));
1505 Status
= RETURN_UNSUPPORTED
;
1510 SendAckPacket (DEBUG_COMMAND_NOT_SUPPORTED
);
1514 if (Status
== RETURN_UNSUPPORTED
) {
1515 SendAckPacket (DEBUG_COMMAND_NOT_SUPPORTED
);
1516 } else if (Status
!= RETURN_SUCCESS
) {
1517 SendAckPacket (DEBUG_COMMAND_ABORT
);
1520 ReleaseDebugPortControl ();
1526 C function called in interrupt handler.
1528 @param[in] Vector Vector value of exception or interrutp.
1529 @param[in] CpuContext Pointer to save CPU context.
1536 IN DEBUG_CPU_CONTEXT
*CpuContext
1539 UINT8 InputCharacter
;
1542 BOOLEAN BreakReceived
;
1543 UINT32 ProcessorIndex
;
1544 UINT32 CurrentDebugTimerInitCount
;
1545 DEBUG_PORT_HANDLE Handle
;
1548 UINT32 IssuedViewPoint
;
1549 DEBUG_AGENT_EXCEPTION_BUFFER
*ExceptionBuffer
;
1552 IssuedViewPoint
= 0;
1553 BreakReceived
= FALSE
;
1555 if (MultiProcessorDebugSupport
) {
1556 ProcessorIndex
= GetProcessorIndex ();
1558 // If this processor has alreay halted before, need to check it later
1560 if (IsCpuStopped (ProcessorIndex
)) {
1561 IssuedViewPoint
= ProcessorIndex
;
1565 if (IssuedViewPoint
== ProcessorIndex
) {
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()
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);
1580 if (MultiProcessorDebugSupport
) {
1582 // If RUN commmand is executing, wait for it done.
1584 while (mDebugMpContext
.RunCommandSet
) {
1589 Handle
= GetDebugPortHandle();
1592 case DEBUG_INT1_VECTOR
:
1593 case DEBUG_INT3_VECTOR
:
1594 BreakCause
= GetBreakCause (Vector
, CpuContext
);
1596 switch (BreakCause
) {
1597 case DEBUG_DATA_BREAK_CAUSE_SYSTEM_RESET
:
1598 if (AttachHost (INIT_BREAK_ACK_TIMEOUT
, &BreakReceived
) != RETURN_SUCCESS
) {
1600 // Try to connect HOST, return if fails
1604 CommandCommunication (Vector
, CpuContext
, BreakReceived
);
1607 case DEBUG_DATA_BREAK_CAUSE_STEPPING
:
1609 // Stepping is finished, send Ack package.
1611 if (MultiProcessorDebugSupport
) {
1612 mDebugMpContext
.BreakAtCpuIndex
= ProcessorIndex
;
1614 SendAckPacket (DEBUG_COMMAND_OK
);
1615 CommandCommunication (Vector
, CpuContext
, BreakReceived
);
1618 case DEBUG_DATA_BREAK_CAUSE_MEMORY_READY
:
1622 SendCommandAndWaitForAckOK (DEBUG_COMMAND_MEMORY_READY
, 0, &BreakReceived
, NULL
);
1623 CommandCommunication (Vector
, CpuContext
, BreakReceived
);
1626 case DEBUG_DATA_BREAK_CAUSE_IMAGE_LOAD
:
1627 case DEBUG_DATA_BREAK_CAUSE_IMAGE_UNLOAD
:
1629 // Set AL to DEBUG_AGENT_IMAGE_CONTINUE
1631 Al
= ArchReadRegisterBuffer (CpuContext
, SOFT_DEBUGGER_REGISTER_AX
, &Data8
);
1632 *Al
= DEBUG_AGENT_IMAGE_CONTINUE
;
1634 if (!IsHostAttached ()) {
1636 // If HOST is not connected for image load/unload, return
1641 // Continue to run the following common code
1644 case DEBUG_DATA_BREAK_CAUSE_HW_BREAKPOINT
:
1645 case DEBUG_DATA_BREAK_CAUSE_SW_BREAKPOINT
:
1648 // Send Break packet to HOST
1650 AcquireDebugPortControl ();
1652 // Only the first breaking processor could send BREAK_POINT to HOST
1654 if (IsFirstBreakProcessor (ProcessorIndex
)) {
1655 SendBreakPacketToHost (ProcessorIndex
, &BreakReceived
);
1657 ReleaseDebugPortControl ();
1659 if (Vector
== DEBUG_INT3_VECTOR
) {
1661 // go back address located "0xCC"
1664 SavedEip
= CpuContext
->Eip
;
1665 CommandCommunication (Vector
, CpuContext
, BreakReceived
);
1666 if ((SavedEip
== CpuContext
->Eip
) &&
1667 (*(UINT8
*) (UINTN
) CpuContext
->Eip
== DEBUG_SW_BREAKPOINT_SYMBOL
)) {
1669 // If this is not a software breakpoint set by HOST,
1675 CommandCommunication (Vector
, CpuContext
, BreakReceived
);
1682 case DEBUG_TIMER_VECTOR
:
1684 AcquireDebugPortControl ();
1686 if (MultiProcessorDebugSupport
) {
1687 if (IsBsp (ProcessorIndex
)) {
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
1693 CurrentDebugTimerInitCount
= GetApicTimerInitCount ();
1694 if (mDebugMpContext
.DebugTimerInitCount
!= CurrentDebugTimerInitCount
) {
1695 InitializeDebugTimer ();
1699 if (!IsBsp (ProcessorIndex
) || mDebugMpContext
.IpiSentByAp
) {
1700 ReleaseDebugPortControl ();
1702 // If current processor is not BSP or this is one IPI sent by AP
1704 if (mDebugMpContext
.BreakAtCpuIndex
!= (UINT32
) (-1)) {
1705 CommandCommunication (Vector
, CpuContext
, FALSE
);
1709 // Clear EOI before exiting interrupt process routine.
1717 // Only BSP could run here
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.
1725 if (DebugReadBreakSymbol (Handle
, &InputCharacter
) == EFI_NOT_FOUND
) {
1728 if ((!IsHostAttached () && (InputCharacter
== DEBUG_STARTING_SYMBOL_ATTACH
)) ||
1729 (IsHostAttached () && (InputCharacter
== DEBUG_STARTING_SYMBOL_BREAK
))
1731 DebugAgentMsgPrint (DEBUG_AGENT_VERBOSE
, "Received data [%02x]\n", InputCharacter
);
1733 // Ack OK for break-in symbol
1735 SendAckPacket (DEBUG_COMMAND_OK
);
1737 if (!IsHostAttached ()) {
1739 // Try to attach HOST, if no ack received after 200ms, return
1741 if (AttachHost (INIT_BREAK_ACK_TIMEOUT
, &BreakReceived
) != RETURN_SUCCESS
) {
1746 if (MultiProcessorDebugSupport
) {
1747 if(FindNextPendingBreakCpu () != -1) {
1748 SetCpuBreakFlagByIndex (ProcessorIndex
, TRUE
);
1750 HaltOtherProcessors (ProcessorIndex
);
1753 ReleaseDebugPortControl ();
1754 CommandCommunication (Vector
, CpuContext
, BreakReceived
);
1755 AcquireDebugPortControl ();
1761 // Clear EOI before exiting interrupt process routine.
1765 ReleaseDebugPortControl ();
1771 if (Vector
<= DEBUG_EXCEPT_SIMD
) {
1772 BreakCause
= GetBreakCause (Vector
, CpuContext
);
1773 if (BreakCause
== DEBUG_DATA_BREAK_CAUSE_STEPPING
) {
1775 // Stepping is finished, send Ack package.
1777 if (MultiProcessorDebugSupport
) {
1778 mDebugMpContext
.BreakAtCpuIndex
= ProcessorIndex
;
1780 SendAckPacket (DEBUG_COMMAND_OK
);
1783 // Exception occurs, send Break packet to HOST
1785 AcquireDebugPortControl ();
1787 // Only the first breaking processor could send BREAK_POINT to HOST
1789 if (IsFirstBreakProcessor (ProcessorIndex
)) {
1790 SendBreakPacketToHost (ProcessorIndex
, &BreakReceived
);
1792 ReleaseDebugPortControl ();
1795 CommandCommunication (Vector
, CpuContext
, BreakReceived
);
1800 if (MultiProcessorDebugSupport
) {
1802 // Clear flag and wait for all processors run here
1804 SetIpiSentByApFlag (FALSE
);
1805 while (mDebugMpContext
.RunCommandSet
) {
1810 // Only current (view) processor could clean up AgentInProgress flag.
1812 if (mDebugMpContext
.ViewPointIndex
== ProcessorIndex
) {
1813 IssuedViewPoint
= mDebugMpContext
.ViewPointIndex
;
1817 if (IssuedViewPoint
== ProcessorIndex
) {
1819 // Clean up AgentInProgress flag
1821 GetMailboxPointer()->DebugFlag
.AgentInProgress
= 0;