2 Common Debug Agent library implementation. 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 - 2018, Intel Corporation. All rights reserved.<BR>
8 SPDX-License-Identifier: BSD-2-Clause-Patent
12 #include "DebugAgent.h"
13 #include "Ia32/DebugException.h"
15 GLOBAL_REMOVE_IF_UNREFERENCED CHAR8 mErrorMsgVersionAlert
[] = "\rThe SourceLevelDebugPkg you are using requires a newer version of the Intel(R) UDK Debugger Tool.\r\n";
16 GLOBAL_REMOVE_IF_UNREFERENCED CHAR8 mErrorMsgSendInitPacket
[] = "\rSend INIT break packet and try to connect the HOST (Intel(R) UDK Debugger Tool v1.5) ...\r\n";
17 GLOBAL_REMOVE_IF_UNREFERENCED CHAR8 mErrorMsgConnectOK
[] = "HOST connection is successful!\r\n";
18 GLOBAL_REMOVE_IF_UNREFERENCED CHAR8 mErrorMsgConnectFail
[] = "HOST connection is failed!\r\n";
19 GLOBAL_REMOVE_IF_UNREFERENCED CHAR8 mWarningMsgIngoreBreakpoint
[] = "Ignore break point in SMM for SMI issued during DXE debugging!\r\n";
22 // Vector Handoff Info list used by Debug Agent for persist
24 GLOBAL_REMOVE_IF_UNREFERENCED EFI_VECTOR_HANDOFF_INFO mVectorHandoffInfoDebugAgent
[] = {
26 DEBUG_EXCEPT_DIVIDE_ERROR
, // Vector 0
27 EFI_VECTOR_HANDOFF_HOOK_BEFORE
,
31 DEBUG_EXCEPT_DEBUG
, // Vector 1
32 EFI_VECTOR_HANDOFF_DO_NOT_HOOK
,
36 DEBUG_EXCEPT_NMI
, // Vector 2
37 EFI_VECTOR_HANDOFF_HOOK_BEFORE
,
41 DEBUG_EXCEPT_BREAKPOINT
, // Vector 3
42 EFI_VECTOR_HANDOFF_DO_NOT_HOOK
,
46 DEBUG_EXCEPT_OVERFLOW
, // Vector 4
47 EFI_VECTOR_HANDOFF_HOOK_BEFORE
,
51 DEBUG_EXCEPT_BOUND
, // Vector 5
52 EFI_VECTOR_HANDOFF_HOOK_BEFORE
,
56 DEBUG_EXCEPT_INVALID_OPCODE
, // Vector 6
57 EFI_VECTOR_HANDOFF_HOOK_BEFORE
,
61 DEBUG_EXCEPT_DOUBLE_FAULT
, // Vector 8
62 EFI_VECTOR_HANDOFF_HOOK_BEFORE
,
66 DEBUG_EXCEPT_INVALID_TSS
, // Vector 10
67 EFI_VECTOR_HANDOFF_HOOK_BEFORE
,
71 DEBUG_EXCEPT_SEG_NOT_PRESENT
, // Vector 11
72 EFI_VECTOR_HANDOFF_HOOK_BEFORE
,
76 DEBUG_EXCEPT_STACK_FAULT
, // Vector 12
77 EFI_VECTOR_HANDOFF_HOOK_BEFORE
,
81 DEBUG_EXCEPT_GP_FAULT
, // Vector 13
82 EFI_VECTOR_HANDOFF_HOOK_BEFORE
,
86 DEBUG_EXCEPT_PAGE_FAULT
, // Vector 14
87 EFI_VECTOR_HANDOFF_HOOK_BEFORE
,
91 DEBUG_EXCEPT_FP_ERROR
, // Vector 16
92 EFI_VECTOR_HANDOFF_HOOK_BEFORE
,
96 DEBUG_EXCEPT_ALIGNMENT_CHECK
, // Vector 17
97 EFI_VECTOR_HANDOFF_HOOK_BEFORE
,
101 DEBUG_EXCEPT_MACHINE_CHECK
, // Vector 18
102 EFI_VECTOR_HANDOFF_HOOK_BEFORE
,
106 DEBUG_EXCEPT_SIMD
, // Vector 19
107 EFI_VECTOR_HANDOFF_HOOK_BEFORE
,
111 DEBUG_TIMER_VECTOR
, // Vector 32
112 EFI_VECTOR_HANDOFF_DO_NOT_HOOK
,
116 DEBUG_MAILBOX_VECTOR
, // Vector 33
117 EFI_VECTOR_HANDOFF_DO_NOT_HOOK
,
122 EFI_VECTOR_HANDOFF_LAST_ENTRY
,
127 GLOBAL_REMOVE_IF_UNREFERENCED UINTN mVectorHandoffInfoCount
= sizeof (mVectorHandoffInfoDebugAgent
) / sizeof (EFI_VECTOR_HANDOFF_INFO
);
130 Calculate CRC16 for target data.
132 @param[in] Data The target data.
133 @param[in] DataSize The target data size.
134 @param[in] Crc Initial CRC.
136 @return UINT16 The CRC16 value.
149 for (Index
= 0; Index
< DataSize
; Index
++) {
150 Crc
^= (UINT16
)Data
[Index
];
151 for (BitIndex
= 0; BitIndex
< 8; BitIndex
++) {
152 if ((Crc
& 0x8000) != 0) {
165 Read IDT entry to check if IDT entries are setup by Debug Agent.
167 @retval TRUE IDT entries were setup by Debug Agent.
168 @retval FALSE IDT entries were not setup by Debug Agent.
172 IsDebugAgentInitialzed (
176 UINTN InterruptHandler
;
178 InterruptHandler
= (UINTN
)GetExceptionHandlerInIdtEntry (0);
179 if ((InterruptHandler
>= 4) && (*(UINT32
*)(InterruptHandler
- 4) == AGENT_HANDLER_SIGNATURE
)) {
187 Find and report module image info to HOST.
189 @param[in] AlignSize Image aligned size.
193 FindAndReportModuleImageInfo (
198 PE_COFF_LOADER_IMAGE_CONTEXT ImageContext
;
203 Pe32Data
= PeCoffSearchImageBase ((UINTN
)mErrorMsgVersionAlert
);
205 ImageContext
.ImageAddress
= Pe32Data
;
206 ImageContext
.PdbPointer
= PeCoffLoaderGetPdbPointer ((VOID
*)(UINTN
)ImageContext
.ImageAddress
);
207 PeCoffLoaderRelocateImageExtraAction (&ImageContext
);
212 Trigger one software interrupt to debug agent to handle it.
214 @param[in] Signature Software interrupt signature.
218 TriggerSoftInterrupt (
226 // Save Debug Register State
234 AsmWriteDr0 (SOFT_INTERRUPT_SIGNATURE
);
235 AsmWriteDr1 (Signature
);
238 // Do INT3 to communicate with HOST side
243 // Restore Debug Register State only when Host didn't change it inside exception handler.
244 // Dr registers can only be changed by setting the HW breakpoint.
251 Calculate Mailbox checksum and update the checksum field.
253 @param[in] Mailbox Debug Agent Mailbox pointer.
257 UpdateMailboxChecksum (
258 IN DEBUG_AGENT_MAILBOX
*Mailbox
261 Mailbox
->CheckSum
= CalculateCheckSum8 ((UINT8
*)Mailbox
, sizeof (DEBUG_AGENT_MAILBOX
) - 2);
265 Verify Mailbox checksum.
267 If checksum error, print debug message and run init dead loop.
269 @param[in] Mailbox Debug Agent Mailbox pointer.
273 VerifyMailboxChecksum (
274 IN DEBUG_AGENT_MAILBOX
*Mailbox
279 CheckSum
= CalculateCheckSum8 ((UINT8
*)Mailbox
, sizeof (DEBUG_AGENT_MAILBOX
) - 2);
281 // The checksum updating process may be disturbed by hardware SMI, we need to check CheckSum field
282 // and ToBeCheckSum field to validate the mail box.
284 if ((CheckSum
!= Mailbox
->CheckSum
) && (CheckSum
!= Mailbox
->ToBeCheckSum
)) {
285 DEBUG ((DEBUG_ERROR
, "DebugAgent: Mailbox checksum error, stack or heap crashed!\n"));
286 DEBUG ((DEBUG_ERROR
, "DebugAgent: CheckSum = %x, Mailbox->CheckSum = %x, Mailbox->ToBeCheckSum = %x\n", CheckSum
, Mailbox
->CheckSum
, Mailbox
->ToBeCheckSum
));
292 Update Mailbox content by index.
294 @param[in] Mailbox Debug Agent Mailbox pointer.
295 @param[in] Index Mailbox content index.
296 @param[in] Value Value to be set into Mailbox.
300 UpdateMailboxContent (
301 IN DEBUG_AGENT_MAILBOX
*Mailbox
,
306 AcquireMpSpinLock (&mDebugMpContext
.MailboxSpinLock
);
308 case DEBUG_MAILBOX_DEBUG_FLAG_INDEX
:
309 Mailbox
->ToBeCheckSum
= Mailbox
->CheckSum
+ CalculateSum8 ((UINT8
*)&Mailbox
->DebugFlag
.Uint64
, sizeof (UINT64
))
310 - CalculateSum8 ((UINT8
*)&Value
, sizeof (UINT64
));
311 Mailbox
->DebugFlag
.Uint64
= Value
;
313 case DEBUG_MAILBOX_DEBUG_PORT_HANDLE_INDEX
:
314 Mailbox
->ToBeCheckSum
= Mailbox
->CheckSum
+ CalculateSum8 ((UINT8
*)&Mailbox
->DebugPortHandle
, sizeof (UINTN
))
315 - CalculateSum8 ((UINT8
*)&Value
, sizeof (UINTN
));
316 Mailbox
->DebugPortHandle
= (UINTN
)Value
;
318 case DEBUG_MAILBOX_EXCEPTION_BUFFER_POINTER_INDEX
:
319 Mailbox
->ToBeCheckSum
= Mailbox
->CheckSum
+ CalculateSum8 ((UINT8
*)&Mailbox
->ExceptionBufferPointer
, sizeof (UINTN
))
320 - CalculateSum8 ((UINT8
*)&Value
, sizeof (UINTN
));
321 Mailbox
->ExceptionBufferPointer
= (UINTN
)Value
;
323 case DEBUG_MAILBOX_LAST_ACK
:
324 Mailbox
->ToBeCheckSum
= Mailbox
->CheckSum
+ CalculateSum8 ((UINT8
*)&Mailbox
->LastAck
, sizeof (UINT8
))
325 - CalculateSum8 ((UINT8
*)&Value
, sizeof (UINT8
));
326 Mailbox
->LastAck
= (UINT8
)Value
;
328 case DEBUG_MAILBOX_SEQUENCE_NO_INDEX
:
329 Mailbox
->ToBeCheckSum
= Mailbox
->CheckSum
+ CalculateSum8 ((UINT8
*)&Mailbox
->SequenceNo
, sizeof (UINT8
))
330 - CalculateSum8 ((UINT8
*)&Value
, sizeof (UINT8
));
331 Mailbox
->SequenceNo
= (UINT8
)Value
;
333 case DEBUG_MAILBOX_HOST_SEQUENCE_NO_INDEX
:
334 Mailbox
->ToBeCheckSum
= Mailbox
->CheckSum
+ CalculateSum8 ((UINT8
*)&Mailbox
->HostSequenceNo
, sizeof (UINT8
))
335 - CalculateSum8 ((UINT8
*)&Value
, sizeof (UINT8
));
336 Mailbox
->HostSequenceNo
= (UINT8
)Value
;
338 case DEBUG_MAILBOX_DEBUG_TIMER_FREQUENCY
:
339 Mailbox
->ToBeCheckSum
= Mailbox
->CheckSum
+ CalculateSum8 ((UINT8
*)&Mailbox
->DebugTimerFrequency
, sizeof (UINT32
))
340 - CalculateSum8 ((UINT8
*)&Value
, sizeof (UINT32
));
341 Mailbox
->DebugTimerFrequency
= (UINT32
)Value
;
345 UpdateMailboxChecksum (Mailbox
);
346 ReleaseMpSpinLock (&mDebugMpContext
.MailboxSpinLock
);
350 Read data from debug device and save the data in buffer.
352 Reads NumberOfBytes data bytes from a debug device into the buffer
353 specified by Buffer. The number of bytes actually read is returned.
354 If the return value is less than NumberOfBytes, then the rest operation failed.
355 If NumberOfBytes is zero, then return 0.
357 @param Handle Debug port handle.
358 @param Buffer Pointer to the data buffer to store the data read from the debug device.
359 @param NumberOfBytes Number of bytes which will be read.
360 @param Timeout Timeout value for reading from debug device. It unit is Microsecond.
362 @retval 0 Read data failed, no data is to be read.
363 @retval >0 Actual number of bytes read from debug device.
367 DebugAgentReadBuffer (
368 IN DEBUG_PORT_HANDLE Handle
,
370 IN UINTN NumberOfBytes
,
376 UINT32 TimeoutTicker
;
378 UINT32 TimerFrequency
;
384 TimerFrequency
= GetMailboxPointer ()->DebugTimerFrequency
;
385 TimerCycle
= GetApicTimerInitCount ();
388 Begin
= GetApicTimerCurrentCount ();
389 TimeoutTicker
= (UINT32
)DivU64x32 (
396 TimerRound
= (UINT32
)DivU64x32Remainder (TimeoutTicker
, TimerCycle
/ 2, &TimeoutTicker
);
400 while (Index
< NumberOfBytes
) {
401 if (DebugPortPollBuffer (Handle
)) {
402 DebugPortReadBuffer (Handle
, Buffer
+ Index
, 1, 0);
408 if (TimerRound
== 0) {
409 if (IsDebugTimerTimeout (TimerCycle
, Begin
, TimeoutTicker
)) {
411 // If time out occurs.
416 if (IsDebugTimerTimeout (TimerCycle
, Begin
, TimerCycle
/ 2)) {
418 Begin
= GetApicTimerCurrentCount ();
428 Set debug flag in mailbox.
430 @param[in] FlagMask Debug flag mask value.
431 @param[in] FlagValue Debug flag value.
440 DEBUG_AGENT_MAILBOX
*Mailbox
;
443 Mailbox
= GetMailboxPointer ();
444 Data64
= (Mailbox
->DebugFlag
.Uint64
& ~FlagMask
) |
445 (LShiftU64 ((UINT64
)FlagValue
, LowBitSet64 (FlagMask
)) & FlagMask
);
446 UpdateMailboxContent (Mailbox
, DEBUG_MAILBOX_DEBUG_FLAG_INDEX
, Data64
);
450 Get debug flag in mailbox.
452 @param[in] FlagMask Debug flag mask value.
454 @return Debug flag value.
462 DEBUG_AGENT_MAILBOX
*Mailbox
;
465 Mailbox
= GetMailboxPointer ();
466 DebugFlag
= (UINT32
)RShiftU64 (Mailbox
->DebugFlag
.Uint64
& FlagMask
, LowBitSet64 (FlagMask
));
472 Send a debug message packet to the debug port.
474 @param[in] Buffer The debug message.
475 @param[in] Length The length of debug message.
484 DEBUG_PACKET_HEADER DebugHeader
;
485 DEBUG_PORT_HANDLE Handle
;
487 Handle
= GetDebugPortHandle ();
489 DebugHeader
.StartSymbol
= DEBUG_STARTING_SYMBOL_NORMAL
;
490 DebugHeader
.Command
= DEBUG_COMMAND_PRINT_MESSAGE
;
491 DebugHeader
.Length
= sizeof (DEBUG_PACKET_HEADER
) + (UINT8
)Length
;
492 DebugHeader
.SequenceNo
= 0xEE;
494 DebugHeader
.Crc
= CalculateCrc16 (
497 CalculateCrc16 ((UINT8
*)&DebugHeader
, sizeof (DEBUG_PACKET_HEADER
), 0)
500 DebugPortWriteBuffer (Handle
, (UINT8
*)&DebugHeader
, sizeof (DEBUG_PACKET_HEADER
));
501 DebugPortWriteBuffer (Handle
, (UINT8
*)Buffer
, Length
);
505 Prints a debug message to the debug port if the specified error level is enabled.
507 If any bit in ErrorLevel is also set in Mainbox, then print the message specified
508 by Format and the associated variable argument list to the debug port.
510 @param[in] ErrorLevel The error level of the debug message.
511 @param[in] Format Format string for the debug message to print.
512 @param[in] ... Variable argument list whose contents are accessed
513 based on the format string specified by Format.
524 CHAR8 Buffer
[DEBUG_DATA_MAXIMUM_REAL_DATA
];
528 // Check driver debug mask value and global mask
530 if ((ErrorLevel
& GetDebugFlag (DEBUG_AGENT_FLAG_PRINT_ERROR_LEVEL
)) == 0) {
535 // Convert the DEBUG() message to an ASCII String
537 VA_START (Marker
, Format
);
538 AsciiVSPrint (Buffer
, sizeof (Buffer
), Format
, Marker
);
541 SendDebugMsgPacket (Buffer
, AsciiStrLen (Buffer
));
545 Prints a debug message to the debug output device if the specified error level is enabled.
547 If any bit in ErrorLevel is also set in DebugPrintErrorLevelLib function
548 GetDebugPrintErrorLevel (), then print the message specified by Format and the
549 associated variable argument list to the debug output device.
551 If Format is NULL, then ASSERT().
553 @param[in] ErrorLevel The error level of the debug message.
554 @param[in] IsSend Flag of debug message to declare that the data is being sent or being received.
555 @param[in] Data Variable argument list whose contents are accessed
556 @param[in] Length based on the format string specified by Format.
561 DebugAgentDataMsgPrint (
568 CHAR8 Buffer
[DEBUG_DATA_MAXIMUM_REAL_DATA
];
573 // Check driver debug mask value and global mask
575 if ((ErrorLevel
& GetDebugFlag (DEBUG_AGENT_FLAG_PRINT_ERROR_LEVEL
)) == 0) {
581 DestBuffer
+= AsciiSPrint (DestBuffer
, DEBUG_DATA_MAXIMUM_REAL_DATA
, "Sent data [ ");
583 DestBuffer
+= AsciiSPrint (DestBuffer
, DEBUG_DATA_MAXIMUM_REAL_DATA
, "Received data [ ");
588 if (DestBuffer
- Buffer
> DEBUG_DATA_MAXIMUM_REAL_DATA
- 6) {
590 // If there was no enough space in buffer, send out the debug message,
591 // reserving 6 bytes is for the last data and end characters "]\n".
593 SendDebugMsgPacket (Buffer
, DestBuffer
- Buffer
);
597 DestBuffer
+= AsciiSPrint (DestBuffer
, DEBUG_DATA_MAXIMUM_REAL_DATA
- (DestBuffer
- Buffer
), "%02x ", Data
[Index
]);
599 if (Index
>= Length
) {
601 // The last character of debug message has been formatted in buffer
603 DestBuffer
+= AsciiSPrint (DestBuffer
, DEBUG_DATA_MAXIMUM_REAL_DATA
- (DestBuffer
- Buffer
), "]\n");
604 SendDebugMsgPacket (Buffer
, DestBuffer
- Buffer
);
611 Read remaining debug packet except for the start symbol
613 @param[in] Handle Pointer to Debug Port handle.
614 @param[in, out] DebugHeader Debug header buffer including start symbol.
616 @retval EFI_SUCCESS Read the symbol in BreakSymbol.
617 @retval EFI_CRC_ERROR CRC check fail.
618 @retval EFI_TIMEOUT Timeout occurs when reading debug packet.
619 @retval EFI_DEVICE_ERROR Receive the old or response packet.
623 ReadRemainingBreakPacket (
624 IN DEBUG_PORT_HANDLE Handle
,
625 IN OUT DEBUG_PACKET_HEADER
*DebugHeader
629 DEBUG_AGENT_MAILBOX
*Mailbox
;
632 // Has received start symbol, try to read the rest part
634 if (DebugAgentReadBuffer (Handle
, (UINT8
*)DebugHeader
+ OFFSET_OF (DEBUG_PACKET_HEADER
, Command
), sizeof (DEBUG_PACKET_HEADER
) - OFFSET_OF (DEBUG_PACKET_HEADER
, Command
), READ_PACKET_TIMEOUT
) == 0) {
636 // Timeout occur, exit
638 DebugAgentMsgPrint (DEBUG_AGENT_WARNING
, "Timeout in Debug Timer interrupt\n");
642 Crc
= DebugHeader
->Crc
;
643 DebugHeader
->Crc
= 0;
644 if (CalculateCrc16 ((UINT8
*)DebugHeader
, DebugHeader
->Length
, 0) != Crc
) {
645 DebugAgentMsgPrint (DEBUG_AGENT_WARNING
, "Debug Timer CRC (%x) against (%x)\n", Crc
, CalculateCrc16 ((UINT8
*)&DebugHeader
, DebugHeader
->Length
, 0));
646 DebugAgentDataMsgPrint (DEBUG_AGENT_VERBOSE
, FALSE
, (UINT8
*)DebugHeader
, DebugHeader
->Length
);
647 return EFI_CRC_ERROR
;
650 Mailbox
= GetMailboxPointer ();
651 if (IS_REQUEST (DebugHeader
)) {
652 if (DebugHeader
->SequenceNo
== (UINT8
)(Mailbox
->HostSequenceNo
+ 1)) {
654 // Only update HostSequenceNo for new command packet
656 UpdateMailboxContent (Mailbox
, DEBUG_MAILBOX_HOST_SEQUENCE_NO_INDEX
, DebugHeader
->SequenceNo
);
660 if (DebugHeader
->SequenceNo
== Mailbox
->HostSequenceNo
) {
665 return EFI_DEVICE_ERROR
;
669 Check if HOST is attached based on Mailbox.
671 @retval TRUE HOST is attached.
672 @retval FALSE HOST is not attached.
680 return (BOOLEAN
)(GetDebugFlag (DEBUG_AGENT_FLAG_HOST_ATTACHED
) == 1);
684 Set HOST connect flag in Mailbox.
686 @param[in] Attached Attach status.
694 DebugAgentMsgPrint (DEBUG_AGENT_INFO
, "Attach status is %d\n", Attached
);
695 SetDebugFlag (DEBUG_AGENT_FLAG_HOST_ATTACHED
, (UINT32
)Attached
);
699 Set debug setting of Debug Agent in Mailbox.
701 @param DebugSetting Pointer to Debug Setting defined by transfer protocol.
703 @retval RETURN_SUCCESS The setting is set successfully.
704 @retval RETURN_UNSUPPORTED The Key value is not supported.
709 IN DEBUG_DATA_SET_DEBUG_SETTING
*DebugSetting
712 RETURN_STATUS Status
;
714 Status
= RETURN_SUCCESS
;
715 switch (DebugSetting
->Key
) {
716 case DEBUG_AGENT_SETTING_SMM_ENTRY_BREAK
:
717 SetDebugFlag (DEBUG_AGENT_FLAG_BREAK_ON_NEXT_SMI
, DebugSetting
->Value
);
719 case DEBUG_AGENT_SETTING_PRINT_ERROR_LEVEL
:
720 SetDebugFlag (DEBUG_AGENT_FLAG_PRINT_ERROR_LEVEL
, DebugSetting
->Value
);
722 case DEBUG_AGENT_SETTING_BOOT_SCRIPT_ENTRY_BREAK
:
723 SetDebugFlag (DEBUG_AGENT_FLAG_BREAK_BOOT_SCRIPT
, DebugSetting
->Value
);
726 Status
= RETURN_UNSUPPORTED
;
735 @param[in] CpuContext Pointer to saved CPU context.
740 IN DEBUG_CPU_CONTEXT
*CpuContext
743 IA32_EFLAGS32
*Eflags
;
745 Eflags
= (IA32_EFLAGS32
*)&CpuContext
->Eflags
;
751 Execute Stepping command.
753 @param[in] CpuContext Pointer to saved CPU context.
758 IN DEBUG_CPU_CONTEXT
*CpuContext
761 IA32_EFLAGS32
*Eflags
;
763 Eflags
= (IA32_EFLAGS32
*)&CpuContext
->Eflags
;
767 // Save and clear EFLAGS.IF to avoid interrupt happen when executing Stepping
769 SetDebugFlag (DEBUG_AGENT_FLAG_INTERRUPT_FLAG
, Eflags
->Bits
.IF
);
774 SetDebugFlag (DEBUG_AGENT_FLAG_STEPPING
, 1);
778 Do some cleanup after Stepping command done.
780 @param[in] CpuContext Pointer to saved CPU context.
784 CommandSteppingCleanup (
785 IN DEBUG_CPU_CONTEXT
*CpuContext
788 IA32_EFLAGS32
*Eflags
;
790 Eflags
= (IA32_EFLAGS32
*)&CpuContext
->Eflags
;
794 Eflags
->Bits
.IF
= GetDebugFlag (DEBUG_AGENT_FLAG_INTERRUPT_FLAG
);
796 // Clear Stepping flag
798 SetDebugFlag (DEBUG_AGENT_FLAG_STEPPING
, 0);
802 Set debug register for hardware breakpoint.
804 @param[in] CpuContext Pointer to saved CPU context.
805 @param[in] SetHwBreakpoint Hardware breakpoint to be set.
810 IN DEBUG_CPU_CONTEXT
*CpuContext
,
811 IN DEBUG_DATA_SET_HW_BREAKPOINT
*SetHwBreakpoint
817 RegisterIndex
= SetHwBreakpoint
->Type
.Index
;
822 *((UINTN
*)&CpuContext
->Dr0
+ RegisterIndex
) = (UINTN
)SetHwBreakpoint
->Address
;
824 Dr7Value
= CpuContext
->Dr7
;
829 Dr7Value
|= (UINTN
)(0x3 << (RegisterIndex
* 2));
833 Dr7Value
&= (UINTN
)(~(0xf << (16 + RegisterIndex
* 4)));
834 Dr7Value
|= (UINTN
)((SetHwBreakpoint
->Type
.Length
<< 2) | SetHwBreakpoint
->Type
.Access
) << (16 + RegisterIndex
* 4);
840 CpuContext
->Dr7
= Dr7Value
;
844 Clear debug register for hardware breakpoint.
846 @param[in] CpuContext Pointer to saved CPU context.
847 @param[in] ClearHwBreakpoint Hardware breakpoint to be cleared.
852 IN DEBUG_CPU_CONTEXT
*CpuContext
,
853 IN DEBUG_DATA_CLEAR_HW_BREAKPOINT
*ClearHwBreakpoint
856 if ((ClearHwBreakpoint
->IndexMask
& BIT0
) != 0) {
858 CpuContext
->Dr7
&= (UINTN
)(~(0x3 << 0));
861 if ((ClearHwBreakpoint
->IndexMask
& BIT1
) != 0) {
863 CpuContext
->Dr7
&= (UINTN
)(~(0x3 << 2));
866 if ((ClearHwBreakpoint
->IndexMask
& BIT2
) != 0) {
868 CpuContext
->Dr7
&= (UINTN
)(~(0x3 << 4));
871 if ((ClearHwBreakpoint
->IndexMask
& BIT3
) != 0) {
873 CpuContext
->Dr7
&= (UINTN
)(~(0x3 << 6));
878 Return the offset of FP / MMX / XMM registers in the FPU saved state by register index.
880 @param[in] Index Register index.
881 @param[out] Width Register width returned.
883 @return Offset in the FPU Save State.
887 ArchReadFxStatOffset (
892 if (Index
< SOFT_DEBUGGER_REGISTER_ST0
) {
894 case SOFT_DEBUGGER_REGISTER_FP_FCW
:
895 *Width
= (UINT8
)sizeof (UINT16
);
896 return OFFSET_OF (DEBUG_DATA_FX_SAVE_STATE
, Fcw
);
898 case SOFT_DEBUGGER_REGISTER_FP_FSW
:
899 *Width
= (UINT8
)sizeof (UINT16
);
900 return OFFSET_OF (DEBUG_DATA_FX_SAVE_STATE
, Fsw
);
902 case SOFT_DEBUGGER_REGISTER_FP_FTW
:
903 *Width
= (UINT8
)sizeof (UINT16
);
904 return OFFSET_OF (DEBUG_DATA_FX_SAVE_STATE
, Ftw
);
906 case SOFT_DEBUGGER_REGISTER_FP_OPCODE
:
907 *Width
= (UINT8
)sizeof (UINT16
);
908 return OFFSET_OF (DEBUG_DATA_FX_SAVE_STATE
, Opcode
);
910 case SOFT_DEBUGGER_REGISTER_FP_EIP
:
911 *Width
= (UINT8
)sizeof (UINT32
);
912 return OFFSET_OF (DEBUG_DATA_FX_SAVE_STATE
, Eip
);
914 case SOFT_DEBUGGER_REGISTER_FP_CS
:
915 *Width
= (UINT8
)sizeof (UINT16
);
916 return OFFSET_OF (DEBUG_DATA_FX_SAVE_STATE
, Cs
);
918 case SOFT_DEBUGGER_REGISTER_FP_DATAOFFSET
:
919 *Width
= (UINT8
)sizeof (UINT32
);
920 return OFFSET_OF (DEBUG_DATA_FX_SAVE_STATE
, DataOffset
);
922 case SOFT_DEBUGGER_REGISTER_FP_DS
:
923 *Width
= (UINT8
)sizeof (UINT16
);
924 return OFFSET_OF (DEBUG_DATA_FX_SAVE_STATE
, Ds
);
926 case SOFT_DEBUGGER_REGISTER_FP_MXCSR
:
927 *Width
= (UINT8
)sizeof (UINT32
);
928 return OFFSET_OF (DEBUG_DATA_FX_SAVE_STATE
, Mxcsr
);
930 case SOFT_DEBUGGER_REGISTER_FP_MXCSR_MASK
:
931 *Width
= (UINT8
)sizeof (UINT32
);
932 return OFFSET_OF (DEBUG_DATA_FX_SAVE_STATE
, Mxcsr_Mask
);
936 if (Index
<= SOFT_DEBUGGER_REGISTER_ST7
) {
938 } else if (Index
<= SOFT_DEBUGGER_REGISTER_XMM15
) {
945 Index
-= SOFT_DEBUGGER_REGISTER_MM0
- SOFT_DEBUGGER_REGISTER_ST0
;
948 return OFFSET_OF (DEBUG_DATA_FX_SAVE_STATE
, St0Mm0
) + (Index
- SOFT_DEBUGGER_REGISTER_ST0
) * 16;
952 Return the pointer of the register value in the CPU saved context.
954 @param[in] CpuContext Pointer to saved CPU context.
955 @param[in] Index Register index value.
956 @param[out] Width Data width to read.
958 @return The pointer in the CPU saved context.
962 ArchReadRegisterBuffer (
963 IN DEBUG_CPU_CONTEXT
*CpuContext
,
970 if (Index
< SOFT_DEBUGGER_REGISTER_FP_BASE
) {
971 Buffer
= (UINT8
*)CpuContext
+ OFFSET_OF (DEBUG_CPU_CONTEXT
, Dr0
) + Index
* sizeof (UINTN
);
972 *Width
= (UINT8
)sizeof (UINTN
);
975 // FPU/MMX/XMM registers
977 Buffer
= (UINT8
*)CpuContext
+ OFFSET_OF (DEBUG_CPU_CONTEXT
, FxSaveState
) + ArchReadFxStatOffset (Index
, Width
);
984 Send the packet without data to HOST.
986 @param[in] CommandType Type of Command.
987 @param[in] SequenceNo Sequence number.
991 SendPacketWithoutData (
992 IN UINT8 CommandType
,
996 DEBUG_PACKET_HEADER DebugHeader
;
997 DEBUG_PORT_HANDLE Handle
;
999 Handle
= GetDebugPortHandle ();
1001 DebugHeader
.StartSymbol
= DEBUG_STARTING_SYMBOL_NORMAL
;
1002 DebugHeader
.Command
= CommandType
;
1003 DebugHeader
.Length
= sizeof (DEBUG_PACKET_HEADER
);
1004 DebugHeader
.SequenceNo
= SequenceNo
;
1005 DebugHeader
.Crc
= 0;
1006 DebugHeader
.Crc
= CalculateCrc16 ((UINT8
*)&DebugHeader
, sizeof (DEBUG_PACKET_HEADER
), 0);
1008 DebugAgentDataMsgPrint (DEBUG_AGENT_VERBOSE
, TRUE
, (UINT8
*)&DebugHeader
, DebugHeader
.Length
);
1009 DebugPortWriteBuffer (Handle
, (UINT8
*)&DebugHeader
, DebugHeader
.Length
);
1013 Send acknowledge packet to HOST.
1015 @param[in] AckCommand Type of Acknowledge packet.
1024 DEBUG_AGENT_MAILBOX
*Mailbox
;
1026 if (AckCommand
!= DEBUG_COMMAND_OK
) {
1028 // This is not ACK OK packet
1030 DebugAgentMsgPrint (DEBUG_AGENT_ERROR
, "Send ACK(%d)\n", AckCommand
);
1033 Mailbox
= GetMailboxPointer ();
1034 SequenceNo
= Mailbox
->HostSequenceNo
;
1035 DebugAgentMsgPrint (DEBUG_AGENT_INFO
, "SendAckPacket: SequenceNo = %x\n", SequenceNo
);
1036 SendPacketWithoutData (AckCommand
, SequenceNo
);
1037 UpdateMailboxContent (Mailbox
, DEBUG_MAILBOX_LAST_ACK
, AckCommand
);
1041 Decompress the Data in place.
1043 @param[in, out] Data The compressed data buffer.
1044 The buffer is assumed large enough to hold the uncompressed data.
1045 @param[in] Length The length of the compressed data buffer.
1047 @return The length of the uncompressed data buffer.
1050 DecompressDataInPlace (
1057 UINTN LastCharCount
;
1060 LastChar
= (UINT16
)-1;
1062 for (Index
= 0; Index
< Length
; Index
++) {
1063 CurrentChar
= Data
[Index
];
1064 if (LastCharCount
== 2) {
1066 CopyMem (&Data
[Index
+ CurrentChar
], &Data
[Index
+ 1], Length
- Index
- 1);
1067 SetMem (&Data
[Index
], CurrentChar
, (UINT8
)LastChar
);
1068 LastChar
= (UINT16
)-1;
1069 Index
+= CurrentChar
- 1;
1070 Length
+= CurrentChar
- 1;
1072 if (LastChar
!= CurrentChar
) {
1077 LastChar
= CurrentChar
;
1081 ASSERT (Length
<= DEBUG_DATA_MAXIMUM_REAL_DATA
);
1083 return (UINT8
)Length
;
1087 Receive valid packet from HOST.
1089 @param[out] InputPacket Buffer to receive packet.
1090 @param[out] BreakReceived TRUE means break-in symbol received.
1091 FALSE means break-in symbol not received.
1092 @param[out] IncompatibilityFlag If IncompatibilityFlag is not NULL, return
1093 TRUE: Compatible packet received.
1094 FALSE: Incompatible packet received.
1095 @param[in] Timeout Time out value to wait for acknowledge from HOST.
1096 The unit is microsecond.
1097 @param[in] SkipStartSymbol TRUE: Skip time out when reading start symbol.
1098 FALSE: Does not Skip time out when reading start symbol.
1100 @retval RETURN_SUCCESS A valid package was received in InputPacket.
1101 @retval RETURN_TIMEOUT Timeout occurs.
1106 OUT UINT8
*InputPacket
,
1107 OUT BOOLEAN
*BreakReceived
,
1108 OUT BOOLEAN
*IncompatibilityFlag OPTIONAL
,
1110 IN BOOLEAN SkipStartSymbol
1113 DEBUG_PACKET_HEADER
*DebugHeader
;
1115 DEBUG_PORT_HANDLE Handle
;
1117 UINTN TimeoutForStartSymbol
;
1119 Handle
= GetDebugPortHandle ();
1120 if (SkipStartSymbol
) {
1121 TimeoutForStartSymbol
= 0;
1123 TimeoutForStartSymbol
= Timeout
;
1126 DebugHeader
= (DEBUG_PACKET_HEADER
*)InputPacket
;
1129 // Find the valid start symbol
1131 Received
= DebugAgentReadBuffer (Handle
, &DebugHeader
->StartSymbol
, sizeof (DebugHeader
->StartSymbol
), TimeoutForStartSymbol
);
1132 if (Received
< sizeof (DebugHeader
->StartSymbol
)) {
1133 DebugAgentMsgPrint (DEBUG_AGENT_WARNING
, "DebugAgentReadBuffer(StartSymbol) timeout\n");
1134 return RETURN_TIMEOUT
;
1137 if ((DebugHeader
->StartSymbol
!= DEBUG_STARTING_SYMBOL_NORMAL
) && (DebugHeader
->StartSymbol
!= DEBUG_STARTING_SYMBOL_COMPRESS
)) {
1138 DebugAgentMsgPrint (DEBUG_AGENT_WARNING
, "Invalid start symbol received [%02x]\n", DebugHeader
->StartSymbol
);
1143 // Read Package header till field Length
1145 Received
= DebugAgentReadBuffer (
1147 (UINT8
*)DebugHeader
+ OFFSET_OF (DEBUG_PACKET_HEADER
, Command
),
1148 OFFSET_OF (DEBUG_PACKET_HEADER
, Length
) + sizeof (DebugHeader
->Length
) - sizeof (DebugHeader
->StartSymbol
),
1151 if (Received
== 0) {
1152 DebugAgentMsgPrint (DEBUG_AGENT_ERROR
, "DebugAgentReadBuffer(Command) timeout\n");
1153 return RETURN_TIMEOUT
;
1156 if (DebugHeader
->Length
< sizeof (DEBUG_PACKET_HEADER
)) {
1157 if (IncompatibilityFlag
!= NULL
) {
1159 // This is one old version debug packet format, set Incompatibility flag
1161 *IncompatibilityFlag
= TRUE
;
1164 // Skip the bad small packet
1170 // Read the payload data include the CRC field
1172 Received
= DebugAgentReadBuffer (Handle
, &DebugHeader
->SequenceNo
, (UINT8
)(DebugHeader
->Length
- OFFSET_OF (DEBUG_PACKET_HEADER
, SequenceNo
)), Timeout
);
1173 if (Received
== 0) {
1174 DebugAgentMsgPrint (DEBUG_AGENT_ERROR
, "DebugAgentReadBuffer(SequenceNo) timeout\n");
1175 return RETURN_TIMEOUT
;
1179 // Calculate the CRC of Debug Packet
1181 Crc
= DebugHeader
->Crc
;
1182 DebugHeader
->Crc
= 0;
1183 if (Crc
== CalculateCrc16 ((UINT8
*)DebugHeader
, DebugHeader
->Length
, 0)) {
1187 DebugAgentMsgPrint (DEBUG_AGENT_WARNING
, "CRC Error (received CRC is %x)\n", Crc
);
1188 DebugAgentDataMsgPrint (DEBUG_AGENT_VERBOSE
, FALSE
, (UINT8
*)DebugHeader
, DebugHeader
->Length
);
1192 DebugAgentDataMsgPrint (DEBUG_AGENT_VERBOSE
, FALSE
, (UINT8
*)DebugHeader
, DebugHeader
->Length
);
1194 if (DebugHeader
->StartSymbol
== DEBUG_STARTING_SYMBOL_COMPRESS
) {
1195 DebugHeader
->StartSymbol
= DEBUG_STARTING_SYMBOL_NORMAL
;
1196 DebugHeader
->Length
= DecompressDataInPlace (
1197 (UINT8
*)(DebugHeader
+ 1),
1198 DebugHeader
->Length
- sizeof (DEBUG_PACKET_HEADER
)
1199 ) + sizeof (DEBUG_PACKET_HEADER
);
1202 return RETURN_SUCCESS
;
1206 Receive acknowledge packet OK from HOST in specified time.
1208 @param[in] Command The command type issued by TARGET.
1209 @param[in] Timeout Time out value to wait for acknowledge from HOST.
1210 The unit is microsecond.
1211 @param[out] BreakReceived If BreakReceived is not NULL,
1212 TRUE is returned if break-in symbol received.
1213 FALSE is returned if break-in symbol not received.
1214 @param[out] IncompatibilityFlag If IncompatibilityFlag is not NULL, return
1215 TRUE: Compatible packet received.
1216 FALSE: Incompatible packet received.
1218 @retval RETURN_SUCCESS Succeed to receive acknowledge packet from HOST,
1219 the type of acknowledge packet saved in Ack.
1220 @retval RETURN_TIMEOUT Specified timeout value was up.
1224 SendCommandAndWaitForAckOK (
1227 OUT BOOLEAN
*BreakReceived OPTIONAL
,
1228 OUT BOOLEAN
*IncompatibilityFlag OPTIONAL
1231 RETURN_STATUS Status
;
1232 UINT8 InputPacketBuffer
[DEBUG_DATA_UPPER_LIMIT
];
1233 DEBUG_PACKET_HEADER
*DebugHeader
;
1235 UINT8 HostSequenceNo
;
1239 DebugHeader
= (DEBUG_PACKET_HEADER
*)InputPacketBuffer
;
1240 Status
= RETURN_TIMEOUT
;
1241 while (RetryCount
> 0) {
1242 SequenceNo
= GetMailboxPointer ()->SequenceNo
;
1243 HostSequenceNo
= GetMailboxPointer ()->HostSequenceNo
;
1244 SendPacketWithoutData (Command
, SequenceNo
);
1245 Status
= ReceivePacket ((UINT8
*)DebugHeader
, BreakReceived
, IncompatibilityFlag
, Timeout
, FALSE
);
1246 if (Status
== RETURN_TIMEOUT
) {
1247 if (Command
== DEBUG_COMMAND_INIT_BREAK
) {
1250 DebugAgentMsgPrint (DEBUG_AGENT_WARNING
, "TARGET: Timeout when waiting for ACK packet.\n");
1256 ASSERT_EFI_ERROR (Status
);
1258 // Status == RETURN_SUCCESS
1260 if ((DebugHeader
->Command
== DEBUG_COMMAND_OK
) && (DebugHeader
->SequenceNo
== SequenceNo
)) {
1264 UpdateMailboxContent (GetMailboxPointer (), DEBUG_MAILBOX_SEQUENCE_NO_INDEX
, ++SequenceNo
);
1268 if ((DebugHeader
->Command
== DEBUG_COMMAND_GO
) && ((DebugHeader
->SequenceNo
== HostSequenceNo
) || (Command
== DEBUG_COMMAND_INIT_BREAK
))) {
1272 if (Command
== DEBUG_COMMAND_INIT_BREAK
) {
1273 DebugAgentMsgPrint (DEBUG_AGENT_WARNING
, "TARGET: Receive GO() in last boot\n");
1276 SendPacketWithoutData (DEBUG_COMMAND_OK
, DebugHeader
->SequenceNo
);
1280 ASSERT (Command
== DEBUG_COMMAND_INIT_BREAK
);
1285 Get current break cause.
1287 @param[in] Vector Vector value of exception or interrupt.
1288 @param[in] CpuContext Pointer to save CPU context.
1290 @return The type of break cause defined by XXXX
1296 IN DEBUG_CPU_CONTEXT
*CpuContext
1301 Cause
= DEBUG_DATA_BREAK_CAUSE_UNKNOWN
;
1304 case DEBUG_INT1_VECTOR
:
1305 case DEBUG_INT3_VECTOR
:
1307 if (Vector
== DEBUG_INT1_VECTOR
) {
1311 if ((CpuContext
->Dr6
& BIT14
) != 0) {
1312 Cause
= DEBUG_DATA_BREAK_CAUSE_STEPPING
;
1314 // DR6.BIT14 Indicates (when set) that the debug exception was
1315 // triggered by the single step execution mode.
1316 // The single-step mode is the highest priority debug exception.
1317 // This is single step, no need to check DR0, to ensure single step
1318 // work in PeCoffExtraActionLib (right after triggering a breakpoint
1319 // to report image load/unload).
1323 Cause
= DEBUG_DATA_BREAK_CAUSE_HW_BREAKPOINT
;
1329 Cause
= DEBUG_DATA_BREAK_CAUSE_SW_BREAKPOINT
;
1332 switch (CpuContext
->Dr0
) {
1333 case IMAGE_LOAD_SIGNATURE
:
1334 case IMAGE_UNLOAD_SIGNATURE
:
1336 if (CpuContext
->Dr3
== IO_PORT_BREAKPOINT_ADDRESS
) {
1337 Cause
= (UINT8
)((CpuContext
->Dr0
== IMAGE_LOAD_SIGNATURE
) ?
1338 DEBUG_DATA_BREAK_CAUSE_IMAGE_LOAD
: DEBUG_DATA_BREAK_CAUSE_IMAGE_UNLOAD
);
1343 case SOFT_INTERRUPT_SIGNATURE
:
1345 if (CpuContext
->Dr1
== MEMORY_READY_SIGNATURE
) {
1346 Cause
= DEBUG_DATA_BREAK_CAUSE_MEMORY_READY
;
1347 CpuContext
->Dr0
= 0;
1348 } else if (CpuContext
->Dr1
== SYSTEM_RESET_SIGNATURE
) {
1349 Cause
= DEBUG_DATA_BREAK_CAUSE_SYSTEM_RESET
;
1350 CpuContext
->Dr0
= 0;
1361 case DEBUG_TIMER_VECTOR
:
1362 Cause
= DEBUG_DATA_BREAK_CAUSE_USER_HALT
;
1367 if (GetDebugFlag (DEBUG_AGENT_FLAG_STEPPING
) == 1) {
1369 // If stepping command is executing
1371 Cause
= DEBUG_DATA_BREAK_CAUSE_STEPPING
;
1373 Cause
= DEBUG_DATA_BREAK_CAUSE_EXCEPTION
;
1384 Copy memory from source to destination with specified width.
1386 @param[out] Dest A pointer to the destination buffer of the memory copy.
1387 @param[in] Src A pointer to the source buffer of the memory copy.
1388 @param[in] Count The number of data with specified width to copy from source to destination.
1389 @param[in] Width Data width in byte.
1410 // Copy memory from tail to avoid memory overlap
1412 Destination
= Dest
+ (Count
- 1) * Width
;
1413 Source
= Src
+ (Count
- 1) * Width
;
1417 while (Count
-- != 0) {
1420 *(UINT8
*)Destination
= MmioRead8 ((UINTN
)Source
);
1423 *(UINT16
*)Destination
= MmioRead16 ((UINTN
)Source
);
1426 *(UINT32
*)Destination
= MmioRead32 ((UINTN
)Source
);
1429 *(UINT64
*)Destination
= MmioRead64 ((UINTN
)Source
);
1436 Destination
+= Step
;
1441 Compress the data buffer but do not modify the original buffer.
1443 The compressed data is directly send to the debug channel.
1444 Compressing in place doesn't work because the data may become larger
1445 during compressing phase. ("3 3 ..." --> "3 3 0 ...")
1446 The routine is expected to be called three times:
1447 1. Compute the length of the compressed data buffer;
1448 2. Compute the CRC of the compressed data buffer;
1449 3. Compress the data and send to the debug channel.
1451 @param[in] Handle The debug channel handle to send the compressed data buffer.
1452 @param[in] Data The data buffer.
1453 @param[in] Length The length of the data buffer.
1454 @param[in] Send TRUE to send the compressed data buffer.
1455 @param[out] CompressedLength Return the length of the compressed data buffer.
1456 It may be larger than the Length in some cases.
1457 @param[out] CompressedCrc Return the CRC of the compressed data buffer.
1461 IN DEBUG_PORT_HANDLE Handle
,
1465 OUT UINTN
*CompressedLength OPTIONAL
,
1466 OUT UINT16
*CompressedCrc OPTIONAL
1471 UINT8 LastCharCount
;
1473 UINTN CompressedIndex
;
1475 ASSERT (Length
> 0);
1476 LastChar
= Data
[0] + 1; // Just ensure it's different from the first byte.
1479 for (Index
= 0, CompressedIndex
= 0; Index
<= Length
; Index
++) {
1480 if (Index
< Length
) {
1481 CurrentChar
= Data
[Index
];
1483 CurrentChar
= (UINT8
)LastChar
+ 1; // just ensure it's different from LastChar
1486 if (LastChar
!= CurrentChar
) {
1487 if (LastCharCount
== 1) {
1489 if (CompressedCrc
!= NULL
) {
1490 *CompressedCrc
= CalculateCrc16 (&LastChar
, 1, *CompressedCrc
);
1494 DebugPortWriteBuffer (Handle
, &LastChar
, 1);
1496 } else if (LastCharCount
>= 2) {
1497 CompressedIndex
+= 3;
1499 if (CompressedCrc
!= NULL
) {
1500 *CompressedCrc
= CalculateCrc16 (&LastChar
, 1, *CompressedCrc
);
1501 *CompressedCrc
= CalculateCrc16 (&LastChar
, 1, *CompressedCrc
);
1502 *CompressedCrc
= CalculateCrc16 (&LastCharCount
, 1, *CompressedCrc
);
1506 DebugPortWriteBuffer (Handle
, &LastChar
, 1);
1507 DebugPortWriteBuffer (Handle
, &LastChar
, 1);
1508 DebugPortWriteBuffer (Handle
, &LastCharCount
, 1);
1516 LastChar
= CurrentChar
;
1519 if (CompressedLength
!= NULL
) {
1520 *CompressedLength
= CompressedIndex
;
1525 Read memory with specified width and send packet with response data to HOST.
1527 @param[in] Data Pointer to response data buffer.
1528 @param[in] Count The number of data with specified Width.
1529 @param[in] Width Data width in byte.
1530 @param[in] DebugHeader Pointer to a buffer for creating response packet and receiving ACK packet,
1531 to minimize the stack usage.
1533 @retval RETURN_SUCCESS Response data was sent successfully.
1537 ReadMemoryAndSendResponsePacket (
1541 IN DEBUG_PACKET_HEADER
*DebugHeader
1544 RETURN_STATUS Status
;
1546 DEBUG_PORT_HANDLE Handle
;
1548 UINTN RemainingDataSize
;
1549 UINT8 CurrentDataSize
;
1550 UINTN CompressedDataSize
;
1552 Handle
= GetDebugPortHandle ();
1554 RemainingDataSize
= Count
* Width
;
1556 SequenceNo
= GetMailboxPointer ()->HostSequenceNo
;
1557 if (RemainingDataSize
<= DEBUG_DATA_MAXIMUM_REAL_DATA
) {
1559 // If the remaining data is less one real packet size, this is the last data packet
1561 CurrentDataSize
= (UINT8
)RemainingDataSize
;
1563 DebugHeader
->Command
= DEBUG_COMMAND_OK
;
1566 // Data is too larger to be sent in one packet, calculate the actual data size could
1567 // be sent in one Maximum data packet
1569 CurrentDataSize
= (DEBUG_DATA_MAXIMUM_REAL_DATA
/ Width
) * Width
;
1571 DebugHeader
->Command
= DEBUG_COMMAND_IN_PROGRESS
;
1575 // Construct the rest Debug header
1577 DebugHeader
->StartSymbol
= DEBUG_STARTING_SYMBOL_NORMAL
;
1578 DebugHeader
->Length
= CurrentDataSize
+ sizeof (DEBUG_PACKET_HEADER
);
1579 DebugHeader
->SequenceNo
= SequenceNo
;
1580 DebugHeader
->Crc
= 0;
1581 CopyMemByWidth ((UINT8
*)(DebugHeader
+ 1), Data
, CurrentDataSize
/ Width
, Width
);
1584 // Compression/decompression support was added since revision 0.4.
1585 // Revision 0.3 shouldn't compress the packet.
1587 if (PcdGet32 (PcdTransferProtocolRevision
) >= DEBUG_AGENT_REVISION_04
) {
1589 // Get the compressed data size without modifying the packet.
1593 (UINT8
*)(DebugHeader
+ 1),
1596 &CompressedDataSize
,
1600 CompressedDataSize
= CurrentDataSize
;
1603 if (CompressedDataSize
< CurrentDataSize
) {
1604 DebugHeader
->Length
= (UINT8
)CompressedDataSize
+ sizeof (DEBUG_PACKET_HEADER
);
1605 DebugHeader
->StartSymbol
= DEBUG_STARTING_SYMBOL_COMPRESS
;
1607 // Compute the CRC of the packet head without modifying the packet.
1609 DebugHeader
->Crc
= CalculateCrc16 ((UINT8
*)DebugHeader
, sizeof (DEBUG_PACKET_HEADER
), 0);
1612 (UINT8
*)(DebugHeader
+ 1),
1619 // Send out the packet head.
1621 DebugPortWriteBuffer (Handle
, (UINT8
*)DebugHeader
, sizeof (DEBUG_PACKET_HEADER
));
1623 // Compress and send out the packet data.
1627 (UINT8
*)(DebugHeader
+ 1),
1635 // Calculate and fill the checksum, DebugHeader->Crc should be 0 before invoking CalculateCrc16 ()
1637 DebugHeader
->Crc
= CalculateCrc16 ((UINT8
*)DebugHeader
, DebugHeader
->Length
, 0);
1639 DebugAgentDataMsgPrint (DEBUG_AGENT_VERBOSE
, TRUE
, (UINT8
*)DebugHeader
, DebugHeader
->Length
);
1641 DebugPortWriteBuffer (Handle
, (UINT8
*)DebugHeader
, DebugHeader
->Length
);
1645 Status
= ReceivePacket ((UINT8
*)DebugHeader
, NULL
, NULL
, READ_PACKET_TIMEOUT
, FALSE
);
1646 if (Status
== RETURN_TIMEOUT
) {
1647 DebugAgentMsgPrint (DEBUG_AGENT_WARNING
, "TARGET: Timeout in SendDataResponsePacket()\n");
1651 if ((DebugHeader
->Command
== DEBUG_COMMAND_OK
) && (DebugHeader
->SequenceNo
== SequenceNo
) && LastPacket
) {
1653 // If this is the last packet, return RETURN_SUCCESS.
1655 return RETURN_SUCCESS
;
1658 if ((DebugHeader
->Command
== DEBUG_COMMAND_CONTINUE
) && (DebugHeader
->SequenceNo
== (UINT8
)(SequenceNo
+ 1))) {
1660 // Calculate the rest data size
1662 Data
+= CurrentDataSize
;
1663 RemainingDataSize
-= CurrentDataSize
;
1664 UpdateMailboxContent (GetMailboxPointer (), DEBUG_MAILBOX_HOST_SEQUENCE_NO_INDEX
, DebugHeader
->SequenceNo
);
1668 if (DebugHeader
->SequenceNo
>= SequenceNo
) {
1669 DebugAgentMsgPrint (DEBUG_AGENT_WARNING
, "TARGET: Received one old or new command(SequenceNo is %x, last SequenceNo is %x)\n", SequenceNo
, DebugHeader
->SequenceNo
);
1677 Send packet with response data to HOST.
1679 @param[in] Data Pointer to response data buffer.
1680 @param[in] DataSize Size of response data in byte.
1681 @param[in, out] DebugHeader Pointer to a buffer for creating response packet and receiving ACK packet,
1682 to minimize the stack usage.
1684 @retval RETURN_SUCCESS Response data was sent successfully.
1688 SendDataResponsePacket (
1691 IN OUT DEBUG_PACKET_HEADER
*DebugHeader
1694 return ReadMemoryAndSendResponsePacket (Data
, DataSize
, 1, DebugHeader
);
1698 Try to attach the HOST.
1700 Send init break packet to HOST:
1701 If no acknowledge received in specified Timeout, return RETURN_TIMEOUT.
1702 If received acknowledge, check the revision of HOST.
1703 Set Attach Flag if attach successfully.
1705 @param[in] BreakCause Break cause of this break event.
1706 @param[in] Timeout Time out value to wait for acknowledge from HOST.
1707 The unit is microsecond.
1708 @param[out] BreakReceived If BreakReceived is not NULL,
1709 TRUE is returned if break-in symbol received.
1710 FALSE is returned if break-in symbol not received.
1714 IN UINT8 BreakCause
,
1716 OUT BOOLEAN
*BreakReceived
1719 RETURN_STATUS Status
;
1720 DEBUG_PORT_HANDLE Handle
;
1721 BOOLEAN IncompatibilityFlag
;
1723 IncompatibilityFlag
= FALSE
;
1724 Handle
= GetDebugPortHandle ();
1727 // Send init break and wait ack in Timeout
1729 DebugPortWriteBuffer (Handle
, (UINT8
*)mErrorMsgSendInitPacket
, AsciiStrLen (mErrorMsgSendInitPacket
));
1730 if (BreakCause
== DEBUG_DATA_BREAK_CAUSE_SYSTEM_RESET
) {
1731 Status
= SendCommandAndWaitForAckOK (DEBUG_COMMAND_INIT_BREAK
, Timeout
, BreakReceived
, &IncompatibilityFlag
);
1733 Status
= SendCommandAndWaitForAckOK (DEBUG_COMMAND_ATTACH_BREAK
, Timeout
, BreakReceived
, &IncompatibilityFlag
);
1736 if (IncompatibilityFlag
) {
1738 // If the incompatible Debug Packet received, the HOST should be running transfer protocol before PcdTransferProtocolRevision.
1739 // It could be UDK Debugger for Windows v1.1/v1.2 or for Linux v0.8/v1.2.
1741 DebugPortWriteBuffer (Handle
, (UINT8
*)mErrorMsgVersionAlert
, AsciiStrLen (mErrorMsgVersionAlert
));
1745 if (RETURN_ERROR (Status
)) {
1746 DebugPortWriteBuffer (Handle
, (UINT8
*)mErrorMsgConnectFail
, AsciiStrLen (mErrorMsgConnectFail
));
1748 DebugPortWriteBuffer (Handle
, (UINT8
*)mErrorMsgConnectOK
, AsciiStrLen (mErrorMsgConnectOK
));
1752 SetHostAttached (TRUE
);
1759 Send Break point packet to HOST.
1761 Only the first breaking processor could sent BREAK_POINT packet.
1763 @param[in] BreakCause Break cause of this break event.
1764 @param[in] ProcessorIndex Processor index value.
1765 @param[out] BreakReceived If BreakReceived is not NULL,
1766 TRUE is returned if break-in symbol received.
1767 FALSE is returned if break-in symbol not received.
1771 SendBreakPacketToHost (
1772 IN UINT8 BreakCause
,
1773 IN UINT32 ProcessorIndex
,
1774 OUT BOOLEAN
*BreakReceived
1777 UINT8 InputCharacter
;
1778 DEBUG_PORT_HANDLE Handle
;
1780 Handle
= GetDebugPortHandle ();
1782 if (IsHostAttached ()) {
1783 DebugAgentMsgPrint (DEBUG_AGENT_INFO
, "processor[%x]:Send Break Packet to HOST.\n", ProcessorIndex
);
1784 SendCommandAndWaitForAckOK (DEBUG_COMMAND_BREAK_POINT
, READ_PACKET_TIMEOUT
, BreakReceived
, NULL
);
1786 DebugAgentMsgPrint (DEBUG_AGENT_INFO
, "processor[%x]:Try to attach HOST.\n", ProcessorIndex
);
1788 // If HOST is not attached, try to attach it firstly.
1791 // Poll Attach symbols from HOST and ack OK
1794 DebugAgentReadBuffer (Handle
, &InputCharacter
, 1, 0);
1795 } while (InputCharacter
!= DEBUG_STARTING_SYMBOL_ATTACH
);
1797 SendAckPacket (DEBUG_COMMAND_OK
);
1800 // Try to attach HOST
1802 while (AttachHost (BreakCause
, 0, NULL
) != RETURN_SUCCESS
) {
1808 The main function to process communication with HOST.
1810 It received the command packet from HOST, and sent response data packet to HOST.
1812 @param[in] Vector Vector value of exception or interrupt.
1813 @param[in, out] CpuContext Pointer to saved CPU context.
1814 @param[in] BreakReceived TRUE means break-in symbol received.
1815 FALSE means break-in symbol not received.
1819 CommandCommunication (
1821 IN OUT DEBUG_CPU_CONTEXT
*CpuContext
,
1822 IN BOOLEAN BreakReceived
1825 RETURN_STATUS Status
;
1826 UINT8 InputPacketBuffer
[DEBUG_DATA_UPPER_LIMIT
+ sizeof (UINT64
) - 1];
1827 DEBUG_PACKET_HEADER
*DebugHeader
;
1832 DEBUG_DATA_READ_MEMORY
*MemoryRead
;
1833 DEBUG_DATA_WRITE_MEMORY
*MemoryWrite
;
1834 DEBUG_DATA_READ_IO
*IoRead
;
1835 DEBUG_DATA_WRITE_IO
*IoWrite
;
1836 DEBUG_DATA_READ_REGISTER
*RegisterRead
;
1837 DEBUG_DATA_WRITE_REGISTER
*RegisterWrite
;
1838 UINT8
*RegisterBuffer
;
1839 DEBUG_DATA_READ_MSR
*MsrRegisterRead
;
1840 DEBUG_DATA_WRITE_MSR
*MsrRegisterWrite
;
1841 DEBUG_DATA_CPUID
*Cpuid
;
1842 DEBUG_DATA_RESPONSE_BREAK_CAUSE BreakCause
;
1843 DEBUG_DATA_RESPONSE_CPUID CpuidResponse
;
1844 DEBUG_DATA_SEARCH_SIGNATURE
*SearchSignature
;
1845 DEBUG_DATA_RESPONSE_GET_EXCEPTION Exception
;
1846 DEBUG_DATA_RESPONSE_GET_REVISION DebugAgentRevision
;
1847 DEBUG_DATA_SET_VIEWPOINT
*SetViewPoint
;
1848 BOOLEAN HaltDeferred
;
1849 UINT32 ProcessorIndex
;
1850 DEBUG_AGENT_EXCEPTION_BUFFER AgentExceptionBuffer
;
1851 UINT32 IssuedViewPoint
;
1852 DEBUG_AGENT_MAILBOX
*Mailbox
;
1853 UINT8
*AlignedDataPtr
;
1856 IssuedViewPoint
= 0;
1857 HaltDeferred
= BreakReceived
;
1859 if (MultiProcessorDebugSupport ()) {
1860 ProcessorIndex
= GetProcessorIndex ();
1861 SetCpuStopFlagByIndex (ProcessorIndex
, TRUE
);
1862 if (mDebugMpContext
.ViewPointIndex
== ProcessorIndex
) {
1864 // Only the current view processor could set AgentInProgress Flag.
1866 IssuedViewPoint
= ProcessorIndex
;
1870 if (IssuedViewPoint
== ProcessorIndex
) {
1872 // Set AgentInProgress Flag.
1874 SetDebugFlag (DEBUG_AGENT_FLAG_AGENT_IN_PROGRESS
, 1);
1878 if (MultiProcessorDebugSupport ()) {
1880 // Check if the current processor is HOST view point
1882 if (mDebugMpContext
.ViewPointIndex
!= ProcessorIndex
) {
1883 if (mDebugMpContext
.RunCommandSet
) {
1885 // If HOST view point sets RUN flag, run GO command to leave
1887 SetCpuStopFlagByIndex (ProcessorIndex
, FALSE
);
1888 CommandGo (CpuContext
);
1892 // Run into loop again
1900 AcquireMpSpinLock (&mDebugMpContext
.DebugPortSpinLock
);
1902 DebugHeader
= (DEBUG_PACKET_HEADER
*)InputPacketBuffer
;
1904 DebugAgentMsgPrint (DEBUG_AGENT_INFO
, "TARGET: Try to get command from HOST...\n");
1905 Status
= ReceivePacket ((UINT8
*)DebugHeader
, &BreakReceived
, NULL
, READ_PACKET_TIMEOUT
, TRUE
);
1906 if ((Status
!= RETURN_SUCCESS
) || !IS_REQUEST (DebugHeader
)) {
1907 DebugAgentMsgPrint (DEBUG_AGENT_WARNING
, "TARGET: Get command[%x] sequenceno[%x] returned status is [%x] \n", DebugHeader
->Command
, DebugHeader
->SequenceNo
, Status
);
1908 DebugAgentMsgPrint (DEBUG_AGENT_WARNING
, "TARGET: Get command failed or it's response packet not expected! \n");
1909 ReleaseMpSpinLock (&mDebugMpContext
.DebugPortSpinLock
);
1913 Mailbox
= GetMailboxPointer ();
1914 if (DebugHeader
->SequenceNo
== Mailbox
->HostSequenceNo
) {
1915 DebugAgentMsgPrint (DEBUG_AGENT_WARNING
, "TARGET: Receive one old command[%x] against command[%x]\n", DebugHeader
->SequenceNo
, Mailbox
->HostSequenceNo
);
1916 SendAckPacket (Mailbox
->LastAck
);
1917 ReleaseMpSpinLock (&mDebugMpContext
.DebugPortSpinLock
);
1919 } else if (DebugHeader
->SequenceNo
== (UINT8
)(Mailbox
->HostSequenceNo
+ 1)) {
1920 UpdateMailboxContent (Mailbox
, DEBUG_MAILBOX_HOST_SEQUENCE_NO_INDEX
, (UINT8
)DebugHeader
->SequenceNo
);
1922 DebugAgentMsgPrint (DEBUG_AGENT_WARNING
, "Receive one invalid command[%x] against command[%x]\n", DebugHeader
->SequenceNo
, Mailbox
->HostSequenceNo
);
1923 ReleaseMpSpinLock (&mDebugMpContext
.DebugPortSpinLock
);
1928 // Save CPU content before executing HOST command
1930 UpdateMailboxContent (Mailbox
, DEBUG_MAILBOX_EXCEPTION_BUFFER_POINTER_INDEX
, (UINT64
)(UINTN
)&AgentExceptionBuffer
.JumpBuffer
);
1931 if (SetJump (&AgentExceptionBuffer
.JumpBuffer
) != 0) {
1933 // If HOST command failed, continue to wait for HOST's next command
1934 // If needed, agent could send exception info to HOST.
1936 SendAckPacket (DEBUG_COMMAND_ABORT
);
1937 ReleaseMpSpinLock (&mDebugMpContext
.DebugPortSpinLock
);
1941 DebugAgentMsgPrint (DEBUG_AGENT_INFO
, "Processor[%x]:Received one command(%x)\n", mDebugMpContext
.ViewPointIndex
, DebugHeader
->Command
);
1943 switch (DebugHeader
->Command
) {
1944 case DEBUG_COMMAND_HALT
:
1945 SendAckPacket (DEBUG_COMMAND_HALT_DEFERRED
);
1946 HaltDeferred
= TRUE
;
1947 BreakReceived
= FALSE
;
1948 Status
= RETURN_SUCCESS
;
1951 case DEBUG_COMMAND_RESET
:
1952 SendAckPacket (DEBUG_COMMAND_OK
);
1953 SendAckPacket (DEBUG_COMMAND_OK
);
1954 SendAckPacket (DEBUG_COMMAND_OK
);
1955 ReleaseMpSpinLock (&mDebugMpContext
.DebugPortSpinLock
);
1959 // Assume system resets in 2 seconds, otherwise send TIMEOUT packet.
1960 // PCD can be used if 2 seconds isn't long enough for some platforms.
1962 MicroSecondDelay (2000000);
1963 UpdateMailboxContent (Mailbox
, DEBUG_MAILBOX_HOST_SEQUENCE_NO_INDEX
, Mailbox
->HostSequenceNo
+ 1);
1964 SendAckPacket (DEBUG_COMMAND_TIMEOUT
);
1965 SendAckPacket (DEBUG_COMMAND_TIMEOUT
);
1966 SendAckPacket (DEBUG_COMMAND_TIMEOUT
);
1969 case DEBUG_COMMAND_GO
:
1970 CommandGo (CpuContext
);
1972 // Clear Dr0 to avoid to be recognized as IMAGE_LOAD/_UNLOAD again when hitting a breakpoint after GO
1973 // If HOST changed Dr0 before GO, we will not change Dr0 here
1975 Data8
= GetBreakCause (Vector
, CpuContext
);
1976 if ((Data8
== DEBUG_DATA_BREAK_CAUSE_IMAGE_LOAD
) || (Data8
== DEBUG_DATA_BREAK_CAUSE_IMAGE_UNLOAD
)) {
1977 CpuContext
->Dr0
= 0;
1980 if (!HaltDeferred
) {
1982 // If no HALT command received when being in-active mode
1984 if (MultiProcessorDebugSupport ()) {
1985 Data32
= FindNextPendingBreakCpu ();
1988 // If there are still others processors being in break state,
1989 // send OK packet to HOST to finish this go command
1991 SendAckPacket (DEBUG_COMMAND_OK
);
1994 // Set current view to the next breaking processor
1996 mDebugMpContext
.ViewPointIndex
= Data32
;
1997 mDebugMpContext
.BreakAtCpuIndex
= mDebugMpContext
.ViewPointIndex
;
1998 SetCpuBreakFlagByIndex (mDebugMpContext
.ViewPointIndex
, FALSE
);
2000 // Send break packet to HOST to let HOST break again
2002 SendBreakPacketToHost (DEBUG_DATA_BREAK_CAUSE_UNKNOWN
, mDebugMpContext
.BreakAtCpuIndex
, &BreakReceived
);
2004 // Continue to run into loop to read command packet from HOST
2006 ReleaseMpSpinLock (&mDebugMpContext
.DebugPortSpinLock
);
2011 // If no else processor break, set stop bitmask,
2012 // and set Running flag for all processors.
2014 SetCpuStopFlagByIndex (ProcessorIndex
, FALSE
);
2015 SetCpuRunningFlag (TRUE
);
2018 // Wait for all processors are in running state
2021 if (IsAllCpuRunning ()) {
2027 // Set BSP to be current view point.
2029 SetDebugViewPoint (mDebugMpContext
.BspIndex
);
2032 // Clear breaking processor index and running flag
2034 mDebugMpContext
.BreakAtCpuIndex
= (UINT32
)(-1);
2035 SetCpuRunningFlag (FALSE
);
2039 // Send OK packet to HOST to finish this go command
2041 SendAckPacket (DEBUG_COMMAND_OK
);
2043 ReleaseMpSpinLock (&mDebugMpContext
.DebugPortSpinLock
);
2045 if (!IsHostAttached ()) {
2046 UpdateMailboxContent (Mailbox
, DEBUG_MAILBOX_SEQUENCE_NO_INDEX
, 0);
2047 UpdateMailboxContent (Mailbox
, DEBUG_MAILBOX_HOST_SEQUENCE_NO_INDEX
, 0);
2053 // If received HALT command, need to defer the GO command
2055 SendAckPacket (DEBUG_COMMAND_HALT_PROCESSED
);
2056 HaltDeferred
= FALSE
;
2058 Vector
= DEBUG_TIMER_VECTOR
;
2063 case DEBUG_COMMAND_BREAK_CAUSE
:
2064 BreakCause
.StopAddress
= CpuContext
->Eip
;
2065 if (MultiProcessorDebugSupport () && (ProcessorIndex
!= mDebugMpContext
.BreakAtCpuIndex
)) {
2066 BreakCause
.Cause
= GetBreakCause (DEBUG_TIMER_VECTOR
, CpuContext
);
2068 BreakCause
.Cause
= GetBreakCause (Vector
, CpuContext
);
2071 SendDataResponsePacket ((UINT8
*)&BreakCause
, (UINT16
)sizeof (DEBUG_DATA_RESPONSE_BREAK_CAUSE
), DebugHeader
);
2074 case DEBUG_COMMAND_SET_HW_BREAKPOINT
:
2075 SetDebugRegister (CpuContext
, (DEBUG_DATA_SET_HW_BREAKPOINT
*)(DebugHeader
+ 1));
2076 SendAckPacket (DEBUG_COMMAND_OK
);
2079 case DEBUG_COMMAND_CLEAR_HW_BREAKPOINT
:
2080 ClearDebugRegister (CpuContext
, (DEBUG_DATA_CLEAR_HW_BREAKPOINT
*)(DebugHeader
+ 1));
2081 SendAckPacket (DEBUG_COMMAND_OK
);
2084 case DEBUG_COMMAND_SINGLE_STEPPING
:
2085 CommandStepping (CpuContext
);
2087 // Clear Dr0 to avoid to be recognized as IMAGE_LOAD/_UNLOAD again when hitting a breakpoint after GO
2088 // If HOST changed Dr0 before GO, we will not change Dr0 here
2090 Data8
= GetBreakCause (Vector
, CpuContext
);
2091 if ((Data8
== DEBUG_DATA_BREAK_CAUSE_IMAGE_LOAD
) || (Data8
== DEBUG_DATA_BREAK_CAUSE_IMAGE_UNLOAD
)) {
2092 CpuContext
->Dr0
= 0;
2095 mDebugMpContext
.BreakAtCpuIndex
= (UINT32
)(-1);
2096 ReleaseMpSpinLock (&mDebugMpContext
.DebugPortSpinLock
);
2098 // Executing stepping command directly without sending ACK packet,
2099 // ACK packet will be sent after stepping done.
2103 case DEBUG_COMMAND_SET_SW_BREAKPOINT
:
2104 Data64
= (UINTN
)(((DEBUG_DATA_SET_SW_BREAKPOINT
*)(DebugHeader
+ 1))->Address
);
2105 Data8
= *(UINT8
*)(UINTN
)Data64
;
2106 *(UINT8
*)(UINTN
)Data64
= DEBUG_SW_BREAKPOINT_SYMBOL
;
2107 Status
= SendDataResponsePacket ((UINT8
*)&Data8
, (UINT16
)sizeof (UINT8
), DebugHeader
);
2110 case DEBUG_COMMAND_READ_MEMORY
:
2111 MemoryRead
= (DEBUG_DATA_READ_MEMORY
*)(DebugHeader
+ 1);
2112 Status
= ReadMemoryAndSendResponsePacket ((UINT8
*)(UINTN
)MemoryRead
->Address
, MemoryRead
->Count
, MemoryRead
->Width
, DebugHeader
);
2115 case DEBUG_COMMAND_WRITE_MEMORY
:
2116 MemoryWrite
= (DEBUG_DATA_WRITE_MEMORY
*)(DebugHeader
+ 1);
2118 // Copy data into one memory with 8-byte alignment address
2120 AlignedDataPtr
= ALIGN_POINTER ((UINT8
*)&MemoryWrite
->Data
, sizeof (UINT64
));
2121 if (AlignedDataPtr
!= (UINT8
*)&MemoryWrite
->Data
) {
2122 CopyMem (AlignedDataPtr
, (UINT8
*)&MemoryWrite
->Data
, MemoryWrite
->Count
* MemoryWrite
->Width
);
2125 CopyMemByWidth ((UINT8
*)(UINTN
)MemoryWrite
->Address
, AlignedDataPtr
, MemoryWrite
->Count
, MemoryWrite
->Width
);
2126 SendAckPacket (DEBUG_COMMAND_OK
);
2129 case DEBUG_COMMAND_READ_IO
:
2130 IoRead
= (DEBUG_DATA_READ_IO
*)(DebugHeader
+ 1);
2131 switch (IoRead
->Width
) {
2133 Data64
= IoRead8 ((UINTN
)IoRead
->Port
);
2136 Data64
= IoRead16 ((UINTN
)IoRead
->Port
);
2139 Data64
= IoRead32 ((UINTN
)IoRead
->Port
);
2142 Data64
= IoRead64 ((UINTN
)IoRead
->Port
);
2145 Data64
= (UINT64
)-1;
2148 Status
= SendDataResponsePacket ((UINT8
*)&Data64
, IoRead
->Width
, DebugHeader
);
2151 case DEBUG_COMMAND_WRITE_IO
:
2152 IoWrite
= (DEBUG_DATA_WRITE_IO
*)(DebugHeader
+ 1);
2153 switch (IoWrite
->Width
) {
2155 Data64
= IoWrite8 ((UINTN
)IoWrite
->Port
, *(UINT8
*)&IoWrite
->Data
);
2158 Data64
= IoWrite16 ((UINTN
)IoWrite
->Port
, *(UINT16
*)&IoWrite
->Data
);
2161 Data64
= IoWrite32 ((UINTN
)IoWrite
->Port
, *(UINT32
*)&IoWrite
->Data
);
2164 Data64
= IoWrite64 ((UINTN
)IoWrite
->Port
, *(UINT64
*)&IoWrite
->Data
);
2167 Data64
= (UINT64
)-1;
2170 SendAckPacket (DEBUG_COMMAND_OK
);
2173 case DEBUG_COMMAND_READ_ALL_REGISTERS
:
2174 Status
= SendDataResponsePacket ((UINT8
*)CpuContext
, sizeof (*CpuContext
), DebugHeader
);
2177 case DEBUG_COMMAND_READ_REGISTER
:
2178 RegisterRead
= (DEBUG_DATA_READ_REGISTER
*)(DebugHeader
+ 1);
2180 if (RegisterRead
->Index
<= SOFT_DEBUGGER_REGISTER_MAX
) {
2181 RegisterBuffer
= ArchReadRegisterBuffer (CpuContext
, RegisterRead
->Index
, &Width
);
2182 Status
= SendDataResponsePacket (RegisterBuffer
, Width
, DebugHeader
);
2184 Status
= RETURN_UNSUPPORTED
;
2189 case DEBUG_COMMAND_WRITE_REGISTER
:
2190 RegisterWrite
= (DEBUG_DATA_WRITE_REGISTER
*)(DebugHeader
+ 1);
2191 if (RegisterWrite
->Index
<= SOFT_DEBUGGER_REGISTER_MAX
) {
2192 RegisterBuffer
= ArchReadRegisterBuffer (CpuContext
, RegisterWrite
->Index
, &Width
);
2193 ASSERT (Width
== RegisterWrite
->Length
);
2194 CopyMem (RegisterBuffer
, RegisterWrite
->Data
, Width
);
2195 SendAckPacket (DEBUG_COMMAND_OK
);
2197 Status
= RETURN_UNSUPPORTED
;
2202 case DEBUG_COMMAND_ARCH_MODE
:
2203 Data8
= DEBUG_ARCH_SYMBOL
;
2204 Status
= SendDataResponsePacket ((UINT8
*)&Data8
, (UINT16
)sizeof (UINT8
), DebugHeader
);
2207 case DEBUG_COMMAND_READ_MSR
:
2208 MsrRegisterRead
= (DEBUG_DATA_READ_MSR
*)(DebugHeader
+ 1);
2209 Data64
= AsmReadMsr64 (MsrRegisterRead
->Index
);
2210 Status
= SendDataResponsePacket ((UINT8
*)&Data64
, (UINT16
)sizeof (UINT64
), DebugHeader
);
2213 case DEBUG_COMMAND_WRITE_MSR
:
2214 MsrRegisterWrite
= (DEBUG_DATA_WRITE_MSR
*)(DebugHeader
+ 1);
2215 AsmWriteMsr64 (MsrRegisterWrite
->Index
, MsrRegisterWrite
->Value
);
2216 SendAckPacket (DEBUG_COMMAND_OK
);
2219 case DEBUG_COMMAND_SET_DEBUG_SETTING
:
2220 Status
= SetDebugSetting ((DEBUG_DATA_SET_DEBUG_SETTING
*)(DebugHeader
+ 1));
2221 if (Status
== RETURN_SUCCESS
) {
2222 SendAckPacket (DEBUG_COMMAND_OK
);
2227 case DEBUG_COMMAND_GET_REVISION
:
2228 DebugAgentRevision
.Revision
= PcdGet32 (PcdTransferProtocolRevision
);
2229 DebugAgentRevision
.Capabilities
= DEBUG_AGENT_CAPABILITIES
;
2230 Status
= SendDataResponsePacket ((UINT8
*)&DebugAgentRevision
, (UINT16
)sizeof (DEBUG_DATA_RESPONSE_GET_REVISION
), DebugHeader
);
2233 case DEBUG_COMMAND_GET_EXCEPTION
:
2234 Exception
.ExceptionNum
= (UINT8
)Vector
;
2235 Exception
.ExceptionData
= (UINT32
)CpuContext
->ExceptionData
;
2236 Status
= SendDataResponsePacket ((UINT8
*)&Exception
, (UINT16
)sizeof (DEBUG_DATA_RESPONSE_GET_EXCEPTION
), DebugHeader
);
2239 case DEBUG_COMMAND_SET_VIEWPOINT
:
2240 SetViewPoint
= (DEBUG_DATA_SET_VIEWPOINT
*)(DebugHeader
+ 1);
2241 if (MultiProcessorDebugSupport ()) {
2242 if (IsCpuStopped (SetViewPoint
->ViewPoint
)) {
2243 SetDebugViewPoint (SetViewPoint
->ViewPoint
);
2244 SendAckPacket (DEBUG_COMMAND_OK
);
2247 // If CPU is not halted
2249 SendAckPacket (DEBUG_COMMAND_NOT_SUPPORTED
);
2251 } else if (SetViewPoint
->ViewPoint
== 0) {
2252 SendAckPacket (DEBUG_COMMAND_OK
);
2254 SendAckPacket (DEBUG_COMMAND_NOT_SUPPORTED
);
2259 case DEBUG_COMMAND_GET_VIEWPOINT
:
2260 Data32
= mDebugMpContext
.ViewPointIndex
;
2261 SendDataResponsePacket ((UINT8
*)&Data32
, (UINT16
)sizeof (UINT32
), DebugHeader
);
2264 case DEBUG_COMMAND_MEMORY_READY
:
2265 Data8
= (UINT8
)GetDebugFlag (DEBUG_AGENT_FLAG_MEMORY_READY
);
2266 SendDataResponsePacket (&Data8
, (UINT16
)sizeof (UINT8
), DebugHeader
);
2269 case DEBUG_COMMAND_DETACH
:
2270 SetHostAttached (FALSE
);
2271 SendAckPacket (DEBUG_COMMAND_OK
);
2274 case DEBUG_COMMAND_CPUID
:
2275 Cpuid
= (DEBUG_DATA_CPUID
*)(DebugHeader
+ 1);
2284 SendDataResponsePacket ((UINT8
*)&CpuidResponse
, (UINT16
)sizeof (CpuidResponse
), DebugHeader
);
2287 case DEBUG_COMMAND_SEARCH_SIGNATURE
:
2288 SearchSignature
= (DEBUG_DATA_SEARCH_SIGNATURE
*)(DebugHeader
+ 1);
2289 if ((SearchSignature
->Alignment
!= 0) &&
2290 (SearchSignature
->Alignment
== GetPowerOfTwo32 (SearchSignature
->Alignment
))
2293 if (SearchSignature
->Positive
) {
2295 Data64
= ALIGN_VALUE ((UINTN
)SearchSignature
->Start
, SearchSignature
->Alignment
);
2296 Data64
<= SearchSignature
->Start
+ SearchSignature
->Count
- SearchSignature
->DataLength
;
2297 Data64
+= SearchSignature
->Alignment
2300 if (CompareMem ((VOID
*)(UINTN
)Data64
, &SearchSignature
->Data
, SearchSignature
->DataLength
) == 0) {
2305 if (Data64
> SearchSignature
->Start
+ SearchSignature
->Count
- SearchSignature
->DataLength
) {
2306 Data64
= (UINT64
)-1;
2310 Data64
= ALIGN_VALUE ((UINTN
)SearchSignature
->Start
- SearchSignature
->Alignment
, SearchSignature
->Alignment
);
2311 Data64
>= SearchSignature
->Start
- SearchSignature
->Count
;
2312 Data64
-= SearchSignature
->Alignment
2315 if (CompareMem ((VOID
*)(UINTN
)Data64
, &SearchSignature
->Data
, SearchSignature
->DataLength
) == 0) {
2320 if (Data64
< SearchSignature
->Start
- SearchSignature
->Count
) {
2321 Data64
= (UINT64
)-1;
2325 SendDataResponsePacket ((UINT8
*)&Data64
, (UINT16
)sizeof (Data64
), DebugHeader
);
2327 Status
= RETURN_UNSUPPORTED
;
2333 SendAckPacket (DEBUG_COMMAND_NOT_SUPPORTED
);
2337 if (Status
== RETURN_UNSUPPORTED
) {
2338 SendAckPacket (DEBUG_COMMAND_NOT_SUPPORTED
);
2339 } else if (Status
!= RETURN_SUCCESS
) {
2340 SendAckPacket (DEBUG_COMMAND_ABORT
);
2343 ReleaseMpSpinLock (&mDebugMpContext
.DebugPortSpinLock
);
2349 C function called in interrupt handler.
2351 @param[in] Vector Vector value of exception or interrupt.
2352 @param[in] CpuContext Pointer to save CPU context.
2359 IN DEBUG_CPU_CONTEXT
*CpuContext
2362 UINT8 InputCharacter
;
2365 BOOLEAN BreakReceived
;
2366 UINT32 ProcessorIndex
;
2367 UINT32 CurrentDebugTimerInitCount
;
2368 DEBUG_PORT_HANDLE Handle
;
2371 UINT32 IssuedViewPoint
;
2372 DEBUG_AGENT_EXCEPTION_BUFFER
*ExceptionBuffer
;
2376 IssuedViewPoint
= 0;
2377 BreakReceived
= FALSE
;
2379 if (mSkipBreakpoint
) {
2381 // If Skip Breakpoint flag is set, means communication is disturbed by hardware SMI, we need to ignore the break points in SMM
2383 if ((Vector
== DEBUG_INT1_VECTOR
) || (Vector
== DEBUG_INT3_VECTOR
)) {
2384 DebugPortWriteBuffer (GetDebugPortHandle (), (UINT8
*)mWarningMsgIngoreBreakpoint
, AsciiStrLen (mWarningMsgIngoreBreakpoint
));
2389 if (MultiProcessorDebugSupport ()) {
2390 ProcessorIndex
= GetProcessorIndex ();
2392 // If this processor has already halted before, need to check it later
2394 if (IsCpuStopped (ProcessorIndex
)) {
2395 IssuedViewPoint
= ProcessorIndex
;
2399 if ((IssuedViewPoint
== ProcessorIndex
) && (GetDebugFlag (DEBUG_AGENT_FLAG_STEPPING
) != 1)) {
2401 // Check if this exception is issued by Debug Agent itself
2402 // If yes, fill the debug agent exception buffer and LongJump() back to
2403 // the saved CPU content in CommandCommunication()
2404 // If exception is issued when executing Stepping, will be handled in
2405 // exception handle procedure.
2407 if (GetDebugFlag (DEBUG_AGENT_FLAG_AGENT_IN_PROGRESS
) == 1) {
2408 DebugAgentMsgPrint (
2410 "Debug agent meet one Exception, ExceptionNum is %d, EIP = 0x%x.\n",
2412 (UINTN
)CpuContext
->Eip
2414 ExceptionBuffer
= (DEBUG_AGENT_EXCEPTION_BUFFER
*)(UINTN
)GetMailboxPointer ()->ExceptionBufferPointer
;
2415 ExceptionBuffer
->ExceptionContent
.ExceptionNum
= (UINT8
)Vector
;
2416 ExceptionBuffer
->ExceptionContent
.ExceptionData
= (UINT32
)CpuContext
->ExceptionData
;
2417 LongJump ((BASE_LIBRARY_JUMP_BUFFER
*)(UINTN
)(ExceptionBuffer
), 1);
2421 if (MultiProcessorDebugSupport ()) {
2423 // If RUN command is executing, wait for it done.
2425 while (mDebugMpContext
.RunCommandSet
) {
2430 Handle
= GetDebugPortHandle ();
2431 BreakCause
= GetBreakCause (Vector
, CpuContext
);
2433 case DEBUG_INT1_VECTOR
:
2434 case DEBUG_INT3_VECTOR
:
2435 switch (BreakCause
) {
2436 case DEBUG_DATA_BREAK_CAUSE_SYSTEM_RESET
:
2437 if (AttachHost (BreakCause
, READ_PACKET_TIMEOUT
, &BreakReceived
) != RETURN_SUCCESS
) {
2439 // Try to connect HOST, return if fails
2444 CommandCommunication (Vector
, CpuContext
, BreakReceived
);
2447 case DEBUG_DATA_BREAK_CAUSE_STEPPING
:
2449 // Stepping is finished, send Ack package.
2451 if (MultiProcessorDebugSupport ()) {
2452 mDebugMpContext
.BreakAtCpuIndex
= ProcessorIndex
;
2456 // Clear Stepping Flag and restore EFLAGS.IF
2458 CommandSteppingCleanup (CpuContext
);
2459 SendAckPacket (DEBUG_COMMAND_OK
);
2460 CommandCommunication (Vector
, CpuContext
, BreakReceived
);
2463 case DEBUG_DATA_BREAK_CAUSE_MEMORY_READY
:
2467 SendCommandAndWaitForAckOK (DEBUG_COMMAND_MEMORY_READY
, READ_PACKET_TIMEOUT
, &BreakReceived
, NULL
);
2468 CommandCommunication (Vector
, CpuContext
, BreakReceived
);
2471 case DEBUG_DATA_BREAK_CAUSE_IMAGE_LOAD
:
2472 case DEBUG_DATA_BREAK_CAUSE_IMAGE_UNLOAD
:
2474 // Set AL to DEBUG_AGENT_IMAGE_CONTINUE
2476 Al
= ArchReadRegisterBuffer (CpuContext
, SOFT_DEBUGGER_REGISTER_AX
, &Data8
);
2477 *Al
= DEBUG_AGENT_IMAGE_CONTINUE
;
2479 if (!IsHostAttached ()) {
2481 // If HOST is not connected for image load/unload, return
2487 // Continue to run the following common code
2490 case DEBUG_DATA_BREAK_CAUSE_HW_BREAKPOINT
:
2491 case DEBUG_DATA_BREAK_CAUSE_SW_BREAKPOINT
:
2494 // Send Break packet to HOST
2496 AcquireMpSpinLock (&mDebugMpContext
.DebugPortSpinLock
);
2498 // Only the first breaking processor could send BREAK_POINT to HOST
2500 if (IsFirstBreakProcessor (ProcessorIndex
)) {
2501 SendBreakPacketToHost (BreakCause
, ProcessorIndex
, &BreakReceived
);
2504 ReleaseMpSpinLock (&mDebugMpContext
.DebugPortSpinLock
);
2506 if (Vector
== DEBUG_INT3_VECTOR
) {
2508 // go back address located "0xCC"
2511 SavedEip
= CpuContext
->Eip
;
2512 CommandCommunication (Vector
, CpuContext
, BreakReceived
);
2513 if ((SavedEip
== CpuContext
->Eip
) &&
2514 (*(UINT8
*)(UINTN
)CpuContext
->Eip
== DEBUG_SW_BREAKPOINT_SYMBOL
))
2517 // If this is not a software breakpoint set by HOST,
2523 CommandCommunication (Vector
, CpuContext
, BreakReceived
);
2531 case DEBUG_TIMER_VECTOR
:
2533 AcquireMpSpinLock (&mDebugMpContext
.DebugPortSpinLock
);
2535 if (MultiProcessorDebugSupport ()) {
2536 if (DebugAgentIsBsp (ProcessorIndex
)) {
2538 // If current processor is BSP, check Apic timer's init count if changed,
2539 // it may be re-written when switching BSP.
2540 // If it changed, re-initialize debug timer
2542 CurrentDebugTimerInitCount
= GetApicTimerInitCount ();
2543 if (mDebugMpContext
.DebugTimerInitCount
!= CurrentDebugTimerInitCount
) {
2544 InitializeDebugTimer (NULL
, FALSE
);
2545 SaveAndSetDebugTimerInterrupt (TRUE
);
2549 if (!DebugAgentIsBsp (ProcessorIndex
) || mDebugMpContext
.IpiSentByAp
) {
2550 ReleaseMpSpinLock (&mDebugMpContext
.DebugPortSpinLock
);
2552 // If current processor is not BSP or this is one IPI sent by AP
2554 if (mDebugMpContext
.BreakAtCpuIndex
!= (UINT32
)(-1)) {
2555 CommandCommunication (Vector
, CpuContext
, FALSE
);
2559 // Clear EOI before exiting interrupt process routine.
2567 // Only BSP could run here
2571 // If there is data in debug port, will check whether it is break(attach/break-in) symbol,
2572 // If yes, go into communication mode with HOST.
2573 // If no, exit interrupt process.
2575 if (DebugReadBreakSymbol (Handle
, &InputCharacter
) == EFI_NOT_FOUND
) {
2579 if ((!IsHostAttached () && (InputCharacter
== DEBUG_STARTING_SYMBOL_ATTACH
)) ||
2580 (IsHostAttached () && (InputCharacter
== DEBUG_COMMAND_HALT
)) ||
2581 (IsHostAttached () && (InputCharacter
== DEBUG_COMMAND_GO
))
2584 DebugAgentMsgPrint (DEBUG_AGENT_VERBOSE
, "Received data [%02x]\n", InputCharacter
);
2586 // Ack OK for break-in symbol
2588 SendAckPacket (DEBUG_COMMAND_OK
);
2591 // If receive GO command in Debug Timer, means HOST may lost ACK packet before.
2593 if (InputCharacter
== DEBUG_COMMAND_GO
) {
2597 if (!IsHostAttached ()) {
2599 // Try to attach HOST, if no ack received after 200ms, return
2601 if (AttachHost (BreakCause
, READ_PACKET_TIMEOUT
, &BreakReceived
) != RETURN_SUCCESS
) {
2606 if (MultiProcessorDebugSupport ()) {
2607 if (FindNextPendingBreakCpu () != -1) {
2608 SetCpuBreakFlagByIndex (ProcessorIndex
, TRUE
);
2610 HaltOtherProcessors (ProcessorIndex
);
2614 ReleaseMpSpinLock (&mDebugMpContext
.DebugPortSpinLock
);
2615 CommandCommunication (Vector
, CpuContext
, BreakReceived
);
2616 AcquireMpSpinLock (&mDebugMpContext
.DebugPortSpinLock
);
2622 // Clear EOI before exiting interrupt process routine.
2626 ReleaseMpSpinLock (&mDebugMpContext
.DebugPortSpinLock
);
2631 if (Vector
<= DEBUG_EXCEPT_SIMD
) {
2632 DebugAgentMsgPrint (
2634 "Exception happened, ExceptionNum is %d, EIP = 0x%x.\n",
2636 (UINTN
)CpuContext
->Eip
2638 if (BreakCause
== DEBUG_DATA_BREAK_CAUSE_STEPPING
) {
2640 // If exception happened when executing Stepping, send Ack package.
2641 // HOST consider Stepping command was finished.
2643 if (MultiProcessorDebugSupport ()) {
2644 mDebugMpContext
.BreakAtCpuIndex
= ProcessorIndex
;
2648 // Clear Stepping flag and restore EFLAGS.IF
2650 CommandSteppingCleanup (CpuContext
);
2651 SendAckPacket (DEBUG_COMMAND_OK
);
2654 // Exception occurs, send Break packet to HOST
2656 AcquireMpSpinLock (&mDebugMpContext
.DebugPortSpinLock
);
2658 // Only the first breaking processor could send BREAK_POINT to HOST
2660 if (IsFirstBreakProcessor (ProcessorIndex
)) {
2661 SendBreakPacketToHost (BreakCause
, ProcessorIndex
, &BreakReceived
);
2664 ReleaseMpSpinLock (&mDebugMpContext
.DebugPortSpinLock
);
2667 CommandCommunication (Vector
, CpuContext
, BreakReceived
);
2673 if (MultiProcessorDebugSupport ()) {
2675 // Clear flag and wait for all processors run here
2677 SetIpiSentByApFlag (FALSE
);
2678 while (mDebugMpContext
.RunCommandSet
) {
2683 // Only current (view) processor could clean up AgentInProgress flag.
2685 if (mDebugMpContext
.ViewPointIndex
== ProcessorIndex
) {
2686 IssuedViewPoint
= mDebugMpContext
.ViewPointIndex
;
2690 if ((IssuedViewPoint
== ProcessorIndex
) && (GetDebugFlag (DEBUG_AGENT_FLAG_STEPPING
) != 1)) {
2692 // If the command is not stepping, clean up AgentInProgress flag
2694 SetDebugFlag (DEBUG_AGENT_FLAG_AGENT_IN_PROGRESS
, 0);