2 Commond 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.
252 Calculate Mailbox checksum and update the checksum field.
254 @param[in] Mailbox Debug Agent Mailbox pointer.
258 UpdateMailboxChecksum (
259 IN DEBUG_AGENT_MAILBOX
*Mailbox
262 Mailbox
->CheckSum
= CalculateCheckSum8 ((UINT8
*)Mailbox
, sizeof (DEBUG_AGENT_MAILBOX
) - 2);
266 Verify Mailbox checksum.
268 If checksum error, print debug message and run init dead loop.
270 @param[in] Mailbox Debug Agent Mailbox pointer.
274 VerifyMailboxChecksum (
275 IN DEBUG_AGENT_MAILBOX
*Mailbox
280 CheckSum
= CalculateCheckSum8 ((UINT8
*) Mailbox
, sizeof (DEBUG_AGENT_MAILBOX
) - 2);
282 // The checksum updating process may be disturbed by hardware SMI, we need to check CheckSum field
283 // and ToBeCheckSum field to validate the mail box.
285 if (CheckSum
!= Mailbox
->CheckSum
&& CheckSum
!= Mailbox
->ToBeCheckSum
) {
286 DEBUG ((EFI_D_ERROR
, "DebugAgent: Mailbox checksum error, stack or heap crashed!\n"));
287 DEBUG ((EFI_D_ERROR
, "DebugAgent: CheckSum = %x, Mailbox->CheckSum = %x, Mailbox->ToBeCheckSum = %x\n", CheckSum
, Mailbox
->CheckSum
, Mailbox
->ToBeCheckSum
));
293 Update Mailbox content by index.
295 @param[in] Mailbox Debug Agent Mailbox pointer.
296 @param[in] Index Mailbox content index.
297 @param[in] Value Value to be set into Mailbox.
301 UpdateMailboxContent (
302 IN DEBUG_AGENT_MAILBOX
*Mailbox
,
307 AcquireMpSpinLock (&mDebugMpContext
.MailboxSpinLock
);
309 case DEBUG_MAILBOX_DEBUG_FLAG_INDEX
:
310 Mailbox
->ToBeCheckSum
= Mailbox
->CheckSum
+ CalculateSum8 ((UINT8
*)&Mailbox
->DebugFlag
.Uint64
, sizeof(UINT64
))
311 - CalculateSum8 ((UINT8
*)&Value
, sizeof(UINT64
));
312 Mailbox
->DebugFlag
.Uint64
= Value
;
314 case DEBUG_MAILBOX_DEBUG_PORT_HANDLE_INDEX
:
315 Mailbox
->ToBeCheckSum
= Mailbox
->CheckSum
+ CalculateSum8 ((UINT8
*)&Mailbox
->DebugPortHandle
, sizeof(UINTN
))
316 - CalculateSum8 ((UINT8
*)&Value
, sizeof(UINTN
));
317 Mailbox
->DebugPortHandle
= (UINTN
) Value
;
319 case DEBUG_MAILBOX_EXCEPTION_BUFFER_POINTER_INDEX
:
320 Mailbox
->ToBeCheckSum
= Mailbox
->CheckSum
+ CalculateSum8 ((UINT8
*)&Mailbox
->ExceptionBufferPointer
, sizeof(UINTN
))
321 - CalculateSum8 ((UINT8
*)&Value
, sizeof(UINTN
));
322 Mailbox
->ExceptionBufferPointer
= (UINTN
) Value
;
324 case DEBUG_MAILBOX_LAST_ACK
:
325 Mailbox
->ToBeCheckSum
= Mailbox
->CheckSum
+ CalculateSum8 ((UINT8
*)&Mailbox
->LastAck
, sizeof(UINT8
))
326 - CalculateSum8 ((UINT8
*)&Value
, sizeof(UINT8
));
327 Mailbox
->LastAck
= (UINT8
) Value
;
329 case DEBUG_MAILBOX_SEQUENCE_NO_INDEX
:
330 Mailbox
->ToBeCheckSum
= Mailbox
->CheckSum
+ CalculateSum8 ((UINT8
*)&Mailbox
->SequenceNo
, sizeof(UINT8
))
331 - CalculateSum8 ((UINT8
*)&Value
, sizeof(UINT8
));
332 Mailbox
->SequenceNo
= (UINT8
) Value
;
334 case DEBUG_MAILBOX_HOST_SEQUENCE_NO_INDEX
:
335 Mailbox
->ToBeCheckSum
= Mailbox
->CheckSum
+ CalculateSum8 ((UINT8
*)&Mailbox
->HostSequenceNo
, sizeof(UINT8
))
336 - CalculateSum8 ((UINT8
*)&Value
, sizeof(UINT8
));
337 Mailbox
->HostSequenceNo
= (UINT8
) Value
;
339 case DEBUG_MAILBOX_DEBUG_TIMER_FREQUENCY
:
340 Mailbox
->ToBeCheckSum
= Mailbox
->CheckSum
+ CalculateSum8 ((UINT8
*)&Mailbox
->DebugTimerFrequency
, sizeof(UINT32
))
341 - CalculateSum8 ((UINT8
*)&Value
, sizeof(UINT32
));
342 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
);
399 while (Index
< NumberOfBytes
) {
400 if (DebugPortPollBuffer (Handle
)) {
401 DebugPortReadBuffer (Handle
, Buffer
+ Index
, 1, 0);
406 if (TimerRound
== 0) {
407 if (IsDebugTimerTimeout (TimerCycle
, Begin
, TimeoutTicker
)) {
409 // If time out occurs.
414 if (IsDebugTimerTimeout (TimerCycle
, Begin
, TimerCycle
/ 2)) {
416 Begin
= GetApicTimerCurrentCount ();
426 Set debug flag in mailbox.
428 @param[in] FlagMask Debug flag mask value.
429 @param[in] FlagValue Debug flag value.
438 DEBUG_AGENT_MAILBOX
*Mailbox
;
441 Mailbox
= GetMailboxPointer ();
442 Data64
= (Mailbox
->DebugFlag
.Uint64
& ~FlagMask
) |
443 (LShiftU64 ((UINT64
)FlagValue
, LowBitSet64 (FlagMask
)) & FlagMask
);
444 UpdateMailboxContent (Mailbox
, DEBUG_MAILBOX_DEBUG_FLAG_INDEX
, Data64
);
448 Get debug flag in mailbox.
450 @param[in] FlagMask Debug flag mask value.
452 @return Debug flag value.
460 DEBUG_AGENT_MAILBOX
*Mailbox
;
463 Mailbox
= GetMailboxPointer ();
464 DebugFlag
= (UINT32
) RShiftU64 (Mailbox
->DebugFlag
.Uint64
& FlagMask
, LowBitSet64 (FlagMask
));
470 Send a debug message packet to the debug port.
472 @param[in] Buffer The debug message.
473 @param[in] Length The length of debug message.
482 DEBUG_PACKET_HEADER DebugHeader
;
483 DEBUG_PORT_HANDLE Handle
;
485 Handle
= GetDebugPortHandle();
487 DebugHeader
.StartSymbol
= DEBUG_STARTING_SYMBOL_NORMAL
;
488 DebugHeader
.Command
= DEBUG_COMMAND_PRINT_MESSAGE
;
489 DebugHeader
.Length
= sizeof (DEBUG_PACKET_HEADER
) + (UINT8
) Length
;
490 DebugHeader
.SequenceNo
= 0xEE;
492 DebugHeader
.Crc
= CalculateCrc16 (
493 (UINT8
*)Buffer
, Length
,
494 CalculateCrc16 ((UINT8
*)&DebugHeader
, sizeof (DEBUG_PACKET_HEADER
), 0)
497 DebugPortWriteBuffer (Handle
, (UINT8
*)&DebugHeader
, sizeof (DEBUG_PACKET_HEADER
));
498 DebugPortWriteBuffer (Handle
, (UINT8
*)Buffer
, Length
);
502 Prints a debug message to the debug port if the specified error level is enabled.
504 If any bit in ErrorLevel is also set in Mainbox, then print the message specified
505 by Format and the associated variable argument list to the debug port.
507 @param[in] ErrorLevel The error level of the debug message.
508 @param[in] Format Format string for the debug message to print.
509 @param[in] ... Variable argument list whose contents are accessed
510 based on the format string specified by Format.
521 CHAR8 Buffer
[DEBUG_DATA_MAXIMUM_REAL_DATA
];
525 // Check driver debug mask value and global mask
527 if ((ErrorLevel
& GetDebugFlag (DEBUG_AGENT_FLAG_PRINT_ERROR_LEVEL
)) == 0) {
532 // Convert the DEBUG() message to an ASCII String
534 VA_START (Marker
, Format
);
535 AsciiVSPrint (Buffer
, sizeof (Buffer
), Format
, Marker
);
538 SendDebugMsgPacket (Buffer
, AsciiStrLen (Buffer
));
542 Prints a debug message to the debug output device if the specified error level is enabled.
544 If any bit in ErrorLevel is also set in DebugPrintErrorLevelLib function
545 GetDebugPrintErrorLevel (), then print the message specified by Format and the
546 associated variable argument list to the debug output device.
548 If Format is NULL, then ASSERT().
550 @param[in] ErrorLevel The error level of the debug message.
551 @param[in] IsSend Flag of debug message to declare that the data is being sent or being received.
552 @param[in] Data Variable argument list whose contents are accessed
553 @param[in] Length based on the format string specified by Format.
558 DebugAgentDataMsgPrint (
565 CHAR8 Buffer
[DEBUG_DATA_MAXIMUM_REAL_DATA
];
570 // Check driver debug mask value and global mask
572 if ((ErrorLevel
& GetDebugFlag (DEBUG_AGENT_FLAG_PRINT_ERROR_LEVEL
)) == 0) {
578 DestBuffer
+= AsciiSPrint (DestBuffer
, DEBUG_DATA_MAXIMUM_REAL_DATA
, "Sent data [ ");
580 DestBuffer
+= AsciiSPrint (DestBuffer
, DEBUG_DATA_MAXIMUM_REAL_DATA
, "Received data [ ");
585 if (DestBuffer
- Buffer
> DEBUG_DATA_MAXIMUM_REAL_DATA
- 6) {
587 // If there was no enough space in buffer, send out the debug message,
588 // reserving 6 bytes is for the last data and end characters "]\n".
590 SendDebugMsgPacket (Buffer
, DestBuffer
- Buffer
);
593 DestBuffer
+= AsciiSPrint (DestBuffer
, DEBUG_DATA_MAXIMUM_REAL_DATA
- (DestBuffer
- Buffer
), "%02x ", Data
[Index
]);
595 if (Index
>= Length
) {
597 // The last character of debug message has been formatted in buffer
599 DestBuffer
+= AsciiSPrint(DestBuffer
, DEBUG_DATA_MAXIMUM_REAL_DATA
- (DestBuffer
- Buffer
), "]\n");
600 SendDebugMsgPacket (Buffer
, DestBuffer
- Buffer
);
607 Read remaing debug packet except for the start symbol
609 @param[in] Handle Pointer to Debug Port handle.
610 @param[in, out] DebugHeader Debug header buffer including start symbol.
612 @retval EFI_SUCCESS Read the symbol in BreakSymbol.
613 @retval EFI_CRC_ERROR CRC check fail.
614 @retval EFI_TIMEOUT Timeout occurs when reading debug packet.
615 @retval EFI_DEVICE_ERROR Receive the old or responsed packet.
619 ReadRemainingBreakPacket (
620 IN DEBUG_PORT_HANDLE Handle
,
621 IN OUT DEBUG_PACKET_HEADER
*DebugHeader
625 DEBUG_AGENT_MAILBOX
*Mailbox
;
628 // Has received start symbol, try to read the rest part
630 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) {
632 // Timeout occur, exit
634 DebugAgentMsgPrint (DEBUG_AGENT_WARNING
, "Timeout in Debug Timer interrupt\n");
638 Crc
= DebugHeader
->Crc
;
639 DebugHeader
->Crc
= 0;
640 if (CalculateCrc16 ((UINT8
*)DebugHeader
, DebugHeader
->Length
, 0) != Crc
) {
641 DebugAgentMsgPrint (DEBUG_AGENT_WARNING
, "Debug Timer CRC (%x) against (%x)\n", Crc
, CalculateCrc16 ((UINT8
*) &DebugHeader
, DebugHeader
->Length
, 0));
642 DebugAgentDataMsgPrint (DEBUG_AGENT_VERBOSE
, FALSE
, (UINT8
*)DebugHeader
, DebugHeader
->Length
);
643 return EFI_CRC_ERROR
;
645 Mailbox
= GetMailboxPointer();
646 if (IS_REQUEST (DebugHeader
)) {
647 if (DebugHeader
->SequenceNo
== (UINT8
) (Mailbox
->HostSequenceNo
+ 1)) {
649 // Only updagte HostSequenceNo for new command packet
651 UpdateMailboxContent (Mailbox
, DEBUG_MAILBOX_HOST_SEQUENCE_NO_INDEX
, DebugHeader
->SequenceNo
);
654 if (DebugHeader
->SequenceNo
== Mailbox
->HostSequenceNo
) {
659 return EFI_DEVICE_ERROR
;
663 Check if HOST is attached based on Mailbox.
665 @retval TRUE HOST is attached.
666 @retval FALSE HOST is not attached.
674 return (BOOLEAN
) (GetDebugFlag (DEBUG_AGENT_FLAG_HOST_ATTACHED
) == 1);
678 Set HOST connect flag in Mailbox.
680 @param[in] Attached Attach status.
688 DebugAgentMsgPrint (DEBUG_AGENT_INFO
, "Attach status is %d\n", Attached
);
689 SetDebugFlag (DEBUG_AGENT_FLAG_HOST_ATTACHED
, (UINT32
)Attached
);
693 Set debug setting of Debug Agent in Mailbox.
695 @param DebugSetting Pointer to Debug Setting defined by transfer protocol.
697 @retval RETURN_SUCCESS The setting is set successfully.
698 @retval RETURN_UNSUPPORTED The Key value is not supported.
703 IN DEBUG_DATA_SET_DEBUG_SETTING
*DebugSetting
706 RETURN_STATUS Status
;
708 Status
= RETURN_SUCCESS
;
709 switch (DebugSetting
->Key
) {
710 case DEBUG_AGENT_SETTING_SMM_ENTRY_BREAK
:
711 SetDebugFlag (DEBUG_AGENT_FLAG_BREAK_ON_NEXT_SMI
, DebugSetting
->Value
);
713 case DEBUG_AGENT_SETTING_PRINT_ERROR_LEVEL
:
714 SetDebugFlag (DEBUG_AGENT_FLAG_PRINT_ERROR_LEVEL
, DebugSetting
->Value
);
716 case DEBUG_AGENT_SETTING_BOOT_SCRIPT_ENTRY_BREAK
:
717 SetDebugFlag (DEBUG_AGENT_FLAG_BREAK_BOOT_SCRIPT
, DebugSetting
->Value
);
720 Status
= RETURN_UNSUPPORTED
;
728 @param[in] CpuContext Pointer to saved CPU context.
733 IN DEBUG_CPU_CONTEXT
*CpuContext
736 IA32_EFLAGS32
*Eflags
;
738 Eflags
= (IA32_EFLAGS32
*) &CpuContext
->Eflags
;
744 Execute Stepping command.
746 @param[in] CpuContext Pointer to saved CPU context.
751 IN DEBUG_CPU_CONTEXT
*CpuContext
754 IA32_EFLAGS32
*Eflags
;
756 Eflags
= (IA32_EFLAGS32
*) &CpuContext
->Eflags
;
760 // Save and clear EFLAGS.IF to avoid interrupt happen when executing Stepping
762 SetDebugFlag (DEBUG_AGENT_FLAG_INTERRUPT_FLAG
, Eflags
->Bits
.IF
);
767 SetDebugFlag (DEBUG_AGENT_FLAG_STEPPING
, 1);
771 Do some cleanup after Stepping command done.
773 @param[in] CpuContext Pointer to saved CPU context.
777 CommandSteppingCleanup (
778 IN DEBUG_CPU_CONTEXT
*CpuContext
781 IA32_EFLAGS32
*Eflags
;
783 Eflags
= (IA32_EFLAGS32
*) &CpuContext
->Eflags
;
787 Eflags
->Bits
.IF
= GetDebugFlag (DEBUG_AGENT_FLAG_INTERRUPT_FLAG
);
789 // Clear Stepping flag
791 SetDebugFlag (DEBUG_AGENT_FLAG_STEPPING
, 0);
795 Set debug register for hardware breakpoint.
797 @param[in] CpuContext Pointer to saved CPU context.
798 @param[in] SetHwBreakpoint Hardware breakpoint to be set.
803 IN DEBUG_CPU_CONTEXT
*CpuContext
,
804 IN DEBUG_DATA_SET_HW_BREAKPOINT
*SetHwBreakpoint
810 RegisterIndex
= SetHwBreakpoint
->Type
.Index
;
815 * ((UINTN
*) &CpuContext
->Dr0
+ RegisterIndex
) = (UINTN
) SetHwBreakpoint
->Address
;
817 Dr7Value
= CpuContext
->Dr7
;
822 Dr7Value
|= (UINTN
) (0x3 << (RegisterIndex
* 2));
826 Dr7Value
&= (UINTN
) (~(0xf << (16 + RegisterIndex
* 4)));
827 Dr7Value
|= (UINTN
) ((SetHwBreakpoint
->Type
.Length
<< 2) | SetHwBreakpoint
->Type
.Access
) << (16 + RegisterIndex
* 4);
833 CpuContext
->Dr7
= Dr7Value
;
837 Clear debug register for hardware breakpoint.
839 @param[in] CpuContext Pointer to saved CPU context.
840 @param[in] ClearHwBreakpoint Hardware breakpoint to be cleared.
845 IN DEBUG_CPU_CONTEXT
*CpuContext
,
846 IN DEBUG_DATA_CLEAR_HW_BREAKPOINT
*ClearHwBreakpoint
849 if ((ClearHwBreakpoint
->IndexMask
& BIT0
) != 0) {
851 CpuContext
->Dr7
&= (UINTN
)(~(0x3 << 0));
853 if ((ClearHwBreakpoint
->IndexMask
& BIT1
) != 0) {
855 CpuContext
->Dr7
&= (UINTN
)(~(0x3 << 2));
857 if ((ClearHwBreakpoint
->IndexMask
& BIT2
) != 0) {
859 CpuContext
->Dr7
&= (UINTN
)(~(0x3 << 4));
861 if ((ClearHwBreakpoint
->IndexMask
& BIT3
) != 0) {
863 CpuContext
->Dr7
&= (UINTN
)(~(0x3 << 6));
869 Return the offset of FP / MMX / XMM registers in the FPU saved state by register index.
871 @param[in] Index Register index.
872 @param[out] Width Register width returned.
874 @return Offset in the FPU Save State.
878 ArchReadFxStatOffset (
883 if (Index
< SOFT_DEBUGGER_REGISTER_ST0
) {
885 case SOFT_DEBUGGER_REGISTER_FP_FCW
:
886 *Width
= (UINT8
) sizeof (UINT16
);
887 return OFFSET_OF(DEBUG_DATA_FX_SAVE_STATE
, Fcw
);
889 case SOFT_DEBUGGER_REGISTER_FP_FSW
:
890 *Width
= (UINT8
) sizeof (UINT16
);
891 return OFFSET_OF(DEBUG_DATA_FX_SAVE_STATE
, Fsw
);
893 case SOFT_DEBUGGER_REGISTER_FP_FTW
:
894 *Width
= (UINT8
) sizeof (UINT16
);
895 return OFFSET_OF(DEBUG_DATA_FX_SAVE_STATE
, Ftw
);
897 case SOFT_DEBUGGER_REGISTER_FP_OPCODE
:
898 *Width
= (UINT8
) sizeof (UINT16
);
899 return OFFSET_OF(DEBUG_DATA_FX_SAVE_STATE
, Opcode
);
901 case SOFT_DEBUGGER_REGISTER_FP_EIP
:
902 *Width
= (UINT8
) sizeof (UINT32
);
903 return OFFSET_OF(DEBUG_DATA_FX_SAVE_STATE
, Eip
);
905 case SOFT_DEBUGGER_REGISTER_FP_CS
:
906 *Width
= (UINT8
) sizeof (UINT16
);
907 return OFFSET_OF(DEBUG_DATA_FX_SAVE_STATE
, Cs
);
909 case SOFT_DEBUGGER_REGISTER_FP_DATAOFFSET
:
910 *Width
= (UINT8
) sizeof (UINT32
);
911 return OFFSET_OF(DEBUG_DATA_FX_SAVE_STATE
, DataOffset
);
913 case SOFT_DEBUGGER_REGISTER_FP_DS
:
914 *Width
= (UINT8
) sizeof (UINT16
);
915 return OFFSET_OF(DEBUG_DATA_FX_SAVE_STATE
, Ds
);
917 case SOFT_DEBUGGER_REGISTER_FP_MXCSR
:
918 *Width
= (UINT8
) sizeof (UINT32
);
919 return OFFSET_OF(DEBUG_DATA_FX_SAVE_STATE
, Mxcsr
);
921 case SOFT_DEBUGGER_REGISTER_FP_MXCSR_MASK
:
922 *Width
= (UINT8
) sizeof (UINT32
);
923 return OFFSET_OF(DEBUG_DATA_FX_SAVE_STATE
, Mxcsr_Mask
);
927 if (Index
<= SOFT_DEBUGGER_REGISTER_ST7
) {
929 } else if (Index
<= SOFT_DEBUGGER_REGISTER_XMM15
) {
936 Index
-= SOFT_DEBUGGER_REGISTER_MM0
- SOFT_DEBUGGER_REGISTER_ST0
;
939 return OFFSET_OF (DEBUG_DATA_FX_SAVE_STATE
, St0Mm0
) + (Index
- SOFT_DEBUGGER_REGISTER_ST0
) * 16;
943 Return the pointer of the register value in the CPU saved context.
945 @param[in] CpuContext Pointer to saved CPU context.
946 @param[in] Index Register index value.
947 @param[out] Width Data width to read.
949 @return The pointer in the CPU saved context.
953 ArchReadRegisterBuffer (
954 IN DEBUG_CPU_CONTEXT
*CpuContext
,
961 if (Index
< SOFT_DEBUGGER_REGISTER_FP_BASE
) {
962 Buffer
= (UINT8
*) CpuContext
+ OFFSET_OF (DEBUG_CPU_CONTEXT
, Dr0
) + Index
* sizeof (UINTN
);
963 *Width
= (UINT8
) sizeof (UINTN
);
966 // FPU/MMX/XMM registers
968 Buffer
= (UINT8
*) CpuContext
+ OFFSET_OF (DEBUG_CPU_CONTEXT
, FxSaveState
) + ArchReadFxStatOffset (Index
, Width
);
975 Send the packet without data to HOST.
977 @param[in] CommandType Type of Command.
978 @param[in] SequenceNo Sequence number.
982 SendPacketWithoutData (
983 IN UINT8 CommandType
,
987 DEBUG_PACKET_HEADER DebugHeader
;
988 DEBUG_PORT_HANDLE Handle
;
990 Handle
= GetDebugPortHandle();
992 DebugHeader
.StartSymbol
= DEBUG_STARTING_SYMBOL_NORMAL
;
993 DebugHeader
.Command
= CommandType
;
994 DebugHeader
.Length
= sizeof (DEBUG_PACKET_HEADER
);
995 DebugHeader
.SequenceNo
= SequenceNo
;
997 DebugHeader
.Crc
= CalculateCrc16 ((UINT8
*)&DebugHeader
, sizeof (DEBUG_PACKET_HEADER
), 0);
999 DebugAgentDataMsgPrint (DEBUG_AGENT_VERBOSE
, TRUE
, (UINT8
*) &DebugHeader
, DebugHeader
.Length
);
1000 DebugPortWriteBuffer (Handle
, (UINT8
*) &DebugHeader
, DebugHeader
.Length
);
1004 Send acknowledge packet to HOST.
1006 @param[in] AckCommand Type of Acknowledge packet.
1015 DEBUG_AGENT_MAILBOX
*Mailbox
;
1017 if (AckCommand
!= DEBUG_COMMAND_OK
) {
1019 // This is not ACK OK packet
1021 DebugAgentMsgPrint (DEBUG_AGENT_ERROR
, "Send ACK(%d)\n", AckCommand
);
1023 Mailbox
= GetMailboxPointer();
1024 SequenceNo
= Mailbox
->HostSequenceNo
;
1025 DebugAgentMsgPrint (DEBUG_AGENT_INFO
, "SendAckPacket: SequenceNo = %x\n", SequenceNo
);
1026 SendPacketWithoutData (AckCommand
, SequenceNo
);
1027 UpdateMailboxContent (Mailbox
, DEBUG_MAILBOX_LAST_ACK
, AckCommand
);
1031 Decompress the Data in place.
1033 @param[in, out] Data The compressed data buffer.
1034 The buffer is assumed large enough to hold the uncompressed data.
1035 @param[in] Length The length of the compressed data buffer.
1037 @return The length of the uncompressed data buffer.
1040 DecompressDataInPlace (
1047 UINTN LastCharCount
;
1050 LastChar
= (UINT16
) -1;
1052 for (Index
= 0; Index
< Length
; Index
++) {
1053 CurrentChar
= Data
[Index
];
1054 if (LastCharCount
== 2) {
1056 CopyMem (&Data
[Index
+ CurrentChar
], &Data
[Index
+ 1], Length
- Index
- 1);
1057 SetMem (&Data
[Index
], CurrentChar
, (UINT8
) LastChar
);
1058 LastChar
= (UINT16
) -1;
1059 Index
+= CurrentChar
- 1;
1060 Length
+= CurrentChar
- 1;
1062 if (LastChar
!= CurrentChar
) {
1066 LastChar
= CurrentChar
;
1070 ASSERT (Length
<= DEBUG_DATA_MAXIMUM_REAL_DATA
);
1072 return (UINT8
) Length
;
1076 Receive valid packet from HOST.
1078 @param[out] InputPacket Buffer to receive packet.
1079 @param[out] BreakReceived TRUE means break-in symbol received.
1080 FALSE means break-in symbol not received.
1081 @param[out] IncompatibilityFlag If IncompatibilityFlag is not NULL, return
1082 TRUE: Compatible packet received.
1083 FALSE: Incompatible packet received.
1084 @param[in] Timeout Time out value to wait for acknowledge from HOST.
1085 The unit is microsecond.
1086 @param[in] SkipStartSymbol TRUE: Skip time out when reading start symbol.
1087 FALSE: Does not Skip time out when reading start symbol.
1089 @retval RETURN_SUCCESS A valid package was received in InputPacket.
1090 @retval RETURN_TIMEOUT Timeout occurs.
1095 OUT UINT8
*InputPacket
,
1096 OUT BOOLEAN
*BreakReceived
,
1097 OUT BOOLEAN
*IncompatibilityFlag
, OPTIONAL
1099 IN BOOLEAN SkipStartSymbol
1102 DEBUG_PACKET_HEADER
*DebugHeader
;
1104 DEBUG_PORT_HANDLE Handle
;
1106 UINTN TimeoutForStartSymbol
;
1108 Handle
= GetDebugPortHandle();
1109 if (SkipStartSymbol
) {
1110 TimeoutForStartSymbol
= 0;
1112 TimeoutForStartSymbol
= Timeout
;
1115 DebugHeader
= (DEBUG_PACKET_HEADER
*) InputPacket
;
1118 // Find the valid start symbol
1120 Received
= DebugAgentReadBuffer (Handle
, &DebugHeader
->StartSymbol
, sizeof (DebugHeader
->StartSymbol
), TimeoutForStartSymbol
);
1121 if (Received
< sizeof (DebugHeader
->StartSymbol
)) {
1122 DebugAgentMsgPrint (DEBUG_AGENT_WARNING
, "DebugAgentReadBuffer(StartSymbol) timeout\n");
1123 return RETURN_TIMEOUT
;
1126 if ((DebugHeader
->StartSymbol
!= DEBUG_STARTING_SYMBOL_NORMAL
) && (DebugHeader
->StartSymbol
!= DEBUG_STARTING_SYMBOL_COMPRESS
)) {
1127 DebugAgentMsgPrint (DEBUG_AGENT_WARNING
, "Invalid start symbol received [%02x]\n", DebugHeader
->StartSymbol
);
1132 // Read Package header till field Length
1134 Received
= DebugAgentReadBuffer (
1136 (UINT8
*) DebugHeader
+ OFFSET_OF (DEBUG_PACKET_HEADER
, Command
),
1137 OFFSET_OF (DEBUG_PACKET_HEADER
, Length
) + sizeof (DebugHeader
->Length
) - sizeof (DebugHeader
->StartSymbol
),
1140 if (Received
== 0) {
1141 DebugAgentMsgPrint (DEBUG_AGENT_ERROR
, "DebugAgentReadBuffer(Command) timeout\n");
1142 return RETURN_TIMEOUT
;
1144 if (DebugHeader
->Length
< sizeof (DEBUG_PACKET_HEADER
)) {
1145 if (IncompatibilityFlag
!= NULL
) {
1147 // This is one old version debug packet format, set Incompatibility flag
1149 *IncompatibilityFlag
= TRUE
;
1152 // Skip the bad small packet
1158 // Read the payload data include the CRC field
1160 Received
= DebugAgentReadBuffer (Handle
, &DebugHeader
->SequenceNo
, (UINT8
) (DebugHeader
->Length
- OFFSET_OF (DEBUG_PACKET_HEADER
, SequenceNo
)), Timeout
);
1161 if (Received
== 0) {
1162 DebugAgentMsgPrint (DEBUG_AGENT_ERROR
, "DebugAgentReadBuffer(SequenceNo) timeout\n");
1163 return RETURN_TIMEOUT
;
1166 // Calculate the CRC of Debug Packet
1168 Crc
= DebugHeader
->Crc
;
1169 DebugHeader
->Crc
= 0;
1170 if (Crc
== CalculateCrc16 ((UINT8
*) DebugHeader
, DebugHeader
->Length
, 0)) {
1173 DebugAgentMsgPrint (DEBUG_AGENT_WARNING
, "CRC Error (received CRC is %x)\n", Crc
);
1174 DebugAgentDataMsgPrint (DEBUG_AGENT_VERBOSE
, FALSE
, (UINT8
*) DebugHeader
, DebugHeader
->Length
);
1178 DebugAgentDataMsgPrint (DEBUG_AGENT_VERBOSE
, FALSE
, (UINT8
*) DebugHeader
, DebugHeader
->Length
);
1180 if (DebugHeader
->StartSymbol
== DEBUG_STARTING_SYMBOL_COMPRESS
) {
1181 DebugHeader
->StartSymbol
= DEBUG_STARTING_SYMBOL_NORMAL
;
1182 DebugHeader
->Length
= DecompressDataInPlace (
1183 (UINT8
*) (DebugHeader
+ 1), DebugHeader
->Length
- sizeof (DEBUG_PACKET_HEADER
)
1184 ) + sizeof (DEBUG_PACKET_HEADER
);
1186 return RETURN_SUCCESS
;
1190 Receive acknowledge packet OK from HOST in specified time.
1192 @param[in] Command The command type issued by TARGET.
1193 @param[in] Timeout Time out value to wait for acknowledge from HOST.
1194 The unit is microsecond.
1195 @param[out] BreakReceived If BreakReceived is not NULL,
1196 TRUE is returned if break-in symbol received.
1197 FALSE is returned if break-in symbol not received.
1198 @param[out] IncompatibilityFlag If IncompatibilityFlag is not NULL, return
1199 TRUE: Compatible packet received.
1200 FALSE: Incompatible packet received.
1202 @retval RETURN_SUCCESS Succeed to receive acknowledge packet from HOST,
1203 the type of acknowledge packet saved in Ack.
1204 @retval RETURN_TIMEOUT Specified timeout value was up.
1208 SendCommandAndWaitForAckOK (
1211 OUT BOOLEAN
*BreakReceived
, OPTIONAL
1212 OUT BOOLEAN
*IncompatibilityFlag OPTIONAL
1215 RETURN_STATUS Status
;
1216 UINT8 InputPacketBuffer
[DEBUG_DATA_UPPER_LIMIT
];
1217 DEBUG_PACKET_HEADER
*DebugHeader
;
1219 UINT8 HostSequenceNo
;
1223 DebugHeader
= (DEBUG_PACKET_HEADER
*) InputPacketBuffer
;
1224 Status
= RETURN_TIMEOUT
;
1225 while (RetryCount
> 0) {
1226 SequenceNo
= GetMailboxPointer()->SequenceNo
;
1227 HostSequenceNo
= GetMailboxPointer()->HostSequenceNo
;
1228 SendPacketWithoutData (Command
, SequenceNo
);
1229 Status
= ReceivePacket ((UINT8
*) DebugHeader
, BreakReceived
, IncompatibilityFlag
, Timeout
, FALSE
);
1230 if (Status
== RETURN_TIMEOUT
) {
1231 if (Command
== DEBUG_COMMAND_INIT_BREAK
) {
1234 DebugAgentMsgPrint (DEBUG_AGENT_WARNING
, "TARGET: Timeout when waiting for ACK packet.\n");
1238 ASSERT_EFI_ERROR (Status
);
1240 // Status == RETURN_SUCCESS
1242 if (DebugHeader
->Command
== DEBUG_COMMAND_OK
&& DebugHeader
->SequenceNo
== SequenceNo
) {
1246 UpdateMailboxContent (GetMailboxPointer(), DEBUG_MAILBOX_SEQUENCE_NO_INDEX
, ++SequenceNo
);
1249 if (DebugHeader
->Command
== DEBUG_COMMAND_GO
&& (DebugHeader
->SequenceNo
== HostSequenceNo
|| Command
== DEBUG_COMMAND_INIT_BREAK
)) {
1253 if (Command
== DEBUG_COMMAND_INIT_BREAK
) {
1254 DebugAgentMsgPrint (DEBUG_AGENT_WARNING
, "TARGET: Receive GO() in last boot\n");
1256 SendPacketWithoutData (DEBUG_COMMAND_OK
, DebugHeader
->SequenceNo
);
1260 ASSERT (Command
== DEBUG_COMMAND_INIT_BREAK
);
1265 Get current break cause.
1267 @param[in] Vector Vector value of exception or interrupt.
1268 @param[in] CpuContext Pointer to save CPU context.
1270 @return The type of break cause defined by XXXX
1276 IN DEBUG_CPU_CONTEXT
*CpuContext
1281 Cause
= DEBUG_DATA_BREAK_CAUSE_UNKNOWN
;
1284 case DEBUG_INT1_VECTOR
:
1285 case DEBUG_INT3_VECTOR
:
1287 if (Vector
== DEBUG_INT1_VECTOR
) {
1291 if ((CpuContext
->Dr6
& BIT14
) != 0) {
1292 Cause
= DEBUG_DATA_BREAK_CAUSE_STEPPING
;
1294 // DR6.BIT14 Indicates (when set) that the debug exception was
1295 // triggered by the single step execution mode.
1296 // The single-step mode is the highest priority debug exception.
1297 // This is single step, no need to check DR0, to ensure single step
1298 // work in PeCoffExtraActionLib (right after triggering a breakpoint
1299 // to report image load/unload).
1304 Cause
= DEBUG_DATA_BREAK_CAUSE_HW_BREAKPOINT
;
1310 Cause
= DEBUG_DATA_BREAK_CAUSE_SW_BREAKPOINT
;
1313 switch (CpuContext
->Dr0
) {
1314 case IMAGE_LOAD_SIGNATURE
:
1315 case IMAGE_UNLOAD_SIGNATURE
:
1317 if (CpuContext
->Dr3
== IO_PORT_BREAKPOINT_ADDRESS
) {
1319 Cause
= (UINT8
) ((CpuContext
->Dr0
== IMAGE_LOAD_SIGNATURE
) ?
1320 DEBUG_DATA_BREAK_CAUSE_IMAGE_LOAD
: DEBUG_DATA_BREAK_CAUSE_IMAGE_UNLOAD
);
1324 case SOFT_INTERRUPT_SIGNATURE
:
1326 if (CpuContext
->Dr1
== MEMORY_READY_SIGNATURE
) {
1327 Cause
= DEBUG_DATA_BREAK_CAUSE_MEMORY_READY
;
1328 CpuContext
->Dr0
= 0;
1329 } else if (CpuContext
->Dr1
== SYSTEM_RESET_SIGNATURE
) {
1330 Cause
= DEBUG_DATA_BREAK_CAUSE_SYSTEM_RESET
;
1331 CpuContext
->Dr0
= 0;
1342 case DEBUG_TIMER_VECTOR
:
1343 Cause
= DEBUG_DATA_BREAK_CAUSE_USER_HALT
;
1348 if (GetDebugFlag (DEBUG_AGENT_FLAG_STEPPING
) == 1) {
1350 // If stepping command is executing
1352 Cause
= DEBUG_DATA_BREAK_CAUSE_STEPPING
;
1354 Cause
= DEBUG_DATA_BREAK_CAUSE_EXCEPTION
;
1364 Copy memory from source to destination with specified width.
1366 @param[out] Dest A pointer to the destination buffer of the memory copy.
1367 @param[in] Src A pointer to the source buffer of the memory copy.
1368 @param[in] Count The number of data with specified width to copy from source to destination.
1369 @param[in] Width Data width in byte.
1390 // Copy memory from tail to avoid memory overlap
1392 Destination
= Dest
+ (Count
- 1) * Width
;
1393 Source
= Src
+ (Count
- 1) * Width
;
1397 while (Count
-- != 0) {
1400 *(UINT8
*) Destination
= MmioRead8 ((UINTN
) Source
);
1403 *(UINT16
*) Destination
= MmioRead16 ((UINTN
) Source
);
1406 *(UINT32
*) Destination
= MmioRead32 ((UINTN
) Source
);
1409 *(UINT64
*) Destination
= MmioRead64 ((UINTN
) Source
);
1415 Destination
+= Step
;
1420 Compress the data buffer but do not modify the original buffer.
1422 The compressed data is directly send to the debug channel.
1423 Compressing in place doesn't work because the data may become larger
1424 during compressing phase. ("3 3 ..." --> "3 3 0 ...")
1425 The routine is expected to be called three times:
1426 1. Compute the length of the compressed data buffer;
1427 2. Compute the CRC of the compressed data buffer;
1428 3. Compress the data and send to the debug channel.
1430 @param[in] Handle The debug channel handle to send the compressed data buffer.
1431 @param[in] Data The data buffer.
1432 @param[in] Length The length of the data buffer.
1433 @param[in] Send TRUE to send the compressed data buffer.
1434 @param[out] CompressedLength Return the length of the compressed data buffer.
1435 It may be larger than the Length in some cases.
1436 @param[out] CompressedCrc Return the CRC of the compressed data buffer.
1440 IN DEBUG_PORT_HANDLE Handle
,
1444 OUT UINTN
*CompressedLength
, OPTIONAL
1445 OUT UINT16
*CompressedCrc OPTIONAL
1450 UINT8 LastCharCount
;
1452 UINTN CompressedIndex
;
1454 ASSERT (Length
> 0);
1455 LastChar
= Data
[0] + 1; // Just ensure it's different from the first byte.
1458 for (Index
= 0, CompressedIndex
= 0; Index
<= Length
; Index
++) {
1459 if (Index
< Length
) {
1460 CurrentChar
= Data
[Index
];
1462 CurrentChar
= (UINT8
) LastChar
+ 1; // just ensure it's different from LastChar
1464 if (LastChar
!= CurrentChar
) {
1465 if (LastCharCount
== 1) {
1467 if (CompressedCrc
!= NULL
) {
1468 *CompressedCrc
= CalculateCrc16 (&LastChar
, 1, *CompressedCrc
);
1471 DebugPortWriteBuffer (Handle
, &LastChar
, 1);
1474 } else if (LastCharCount
>= 2) {
1475 CompressedIndex
+= 3;
1477 if (CompressedCrc
!= NULL
) {
1478 *CompressedCrc
= CalculateCrc16 (&LastChar
, 1, *CompressedCrc
);
1479 *CompressedCrc
= CalculateCrc16 (&LastChar
, 1, *CompressedCrc
);
1480 *CompressedCrc
= CalculateCrc16 (&LastCharCount
, 1, *CompressedCrc
);
1483 DebugPortWriteBuffer (Handle
, &LastChar
, 1);
1484 DebugPortWriteBuffer (Handle
, &LastChar
, 1);
1485 DebugPortWriteBuffer (Handle
, &LastCharCount
, 1);
1491 LastChar
= CurrentChar
;
1494 if (CompressedLength
!= NULL
) {
1495 *CompressedLength
= CompressedIndex
;
1500 Read memory with specified width and send packet with response data to HOST.
1502 @param[in] Data Pointer to response data buffer.
1503 @param[in] Count The number of data with specified Width.
1504 @param[in] Width Data width in byte.
1505 @param[in] DebugHeader Pointer to a buffer for creating response packet and receiving ACK packet,
1506 to minimize the stack usage.
1508 @retval RETURN_SUCCESS Response data was sent successfully.
1512 ReadMemoryAndSendResponsePacket (
1516 IN DEBUG_PACKET_HEADER
*DebugHeader
1519 RETURN_STATUS Status
;
1521 DEBUG_PORT_HANDLE Handle
;
1523 UINTN RemainingDataSize
;
1524 UINT8 CurrentDataSize
;
1525 UINTN CompressedDataSize
;
1527 Handle
= GetDebugPortHandle();
1529 RemainingDataSize
= Count
* Width
;
1531 SequenceNo
= GetMailboxPointer()->HostSequenceNo
;
1532 if (RemainingDataSize
<= DEBUG_DATA_MAXIMUM_REAL_DATA
) {
1534 // If the remaining data is less one real packet size, this is the last data packet
1536 CurrentDataSize
= (UINT8
) RemainingDataSize
;
1538 DebugHeader
->Command
= DEBUG_COMMAND_OK
;
1541 // Data is too larger to be sent in one packet, calculate the actual data size could
1542 // be sent in one Maximum data packet
1544 CurrentDataSize
= (DEBUG_DATA_MAXIMUM_REAL_DATA
/ Width
) * Width
;
1546 DebugHeader
->Command
= DEBUG_COMMAND_IN_PROGRESS
;
1549 // Construct the rest Debug header
1551 DebugHeader
->StartSymbol
= DEBUG_STARTING_SYMBOL_NORMAL
;
1552 DebugHeader
->Length
= CurrentDataSize
+ sizeof (DEBUG_PACKET_HEADER
);
1553 DebugHeader
->SequenceNo
= SequenceNo
;
1554 DebugHeader
->Crc
= 0;
1555 CopyMemByWidth ((UINT8
*) (DebugHeader
+ 1), Data
, CurrentDataSize
/ Width
, Width
);
1558 // Compression/decompression support was added since revision 0.4.
1559 // Revision 0.3 shouldn't compress the packet.
1561 if (PcdGet32(PcdTransferProtocolRevision
) >= DEBUG_AGENT_REVISION_04
) {
1563 // Get the compressed data size without modifying the packet.
1567 (UINT8
*) (DebugHeader
+ 1),
1570 &CompressedDataSize
,
1574 CompressedDataSize
= CurrentDataSize
;
1576 if (CompressedDataSize
< CurrentDataSize
) {
1577 DebugHeader
->Length
= (UINT8
) CompressedDataSize
+ sizeof (DEBUG_PACKET_HEADER
);
1578 DebugHeader
->StartSymbol
= DEBUG_STARTING_SYMBOL_COMPRESS
;
1580 // Compute the CRC of the packet head without modifying the packet.
1582 DebugHeader
->Crc
= CalculateCrc16 ((UINT8
*) DebugHeader
, sizeof (DEBUG_PACKET_HEADER
), 0);
1585 (UINT8
*) (DebugHeader
+ 1),
1592 // Send out the packet head.
1594 DebugPortWriteBuffer (Handle
, (UINT8
*) DebugHeader
, sizeof (DEBUG_PACKET_HEADER
));
1596 // Compress and send out the packet data.
1600 (UINT8
*) (DebugHeader
+ 1),
1609 // Calculate and fill the checksum, DebugHeader->Crc should be 0 before invoking CalculateCrc16 ()
1611 DebugHeader
->Crc
= CalculateCrc16 ((UINT8
*) DebugHeader
, DebugHeader
->Length
, 0);
1613 DebugAgentDataMsgPrint (DEBUG_AGENT_VERBOSE
, TRUE
, (UINT8
*) DebugHeader
, DebugHeader
->Length
);
1615 DebugPortWriteBuffer (Handle
, (UINT8
*) DebugHeader
, DebugHeader
->Length
);
1619 Status
= ReceivePacket ((UINT8
*) DebugHeader
, NULL
, NULL
, READ_PACKET_TIMEOUT
, FALSE
);
1620 if (Status
== RETURN_TIMEOUT
) {
1621 DebugAgentMsgPrint (DEBUG_AGENT_WARNING
, "TARGET: Timeout in SendDataResponsePacket()\n");
1624 if ((DebugHeader
->Command
== DEBUG_COMMAND_OK
) && (DebugHeader
->SequenceNo
== SequenceNo
) && LastPacket
) {
1626 // If this is the last packet, return RETURN_SUCCESS.
1628 return RETURN_SUCCESS
;
1630 if ((DebugHeader
->Command
== DEBUG_COMMAND_CONTINUE
) && (DebugHeader
->SequenceNo
== (UINT8
) (SequenceNo
+ 1))) {
1632 // Calculate the rest data size
1634 Data
+= CurrentDataSize
;
1635 RemainingDataSize
-= CurrentDataSize
;
1636 UpdateMailboxContent (GetMailboxPointer(), DEBUG_MAILBOX_HOST_SEQUENCE_NO_INDEX
, DebugHeader
->SequenceNo
);
1639 if (DebugHeader
->SequenceNo
>= SequenceNo
) {
1640 DebugAgentMsgPrint (DEBUG_AGENT_WARNING
, "TARGET: Received one old or new command(SequenceNo is %x, last SequenceNo is %x)\n", SequenceNo
, DebugHeader
->SequenceNo
);
1648 Send packet with response data to HOST.
1650 @param[in] Data Pointer to response data buffer.
1651 @param[in] DataSize Size of response data in byte.
1652 @param[in, out] DebugHeader Pointer to a buffer for creating response packet and receiving ACK packet,
1653 to minimize the stack usage.
1655 @retval RETURN_SUCCESS Response data was sent successfully.
1659 SendDataResponsePacket (
1662 IN OUT DEBUG_PACKET_HEADER
*DebugHeader
1665 return ReadMemoryAndSendResponsePacket (Data
, DataSize
, 1, DebugHeader
);
1669 Try to attach the HOST.
1671 Send init break packet to HOST:
1672 If no acknowledge received in specified Timeout, return RETURN_TIMEOUT.
1673 If received acknowledge, check the revision of HOST.
1674 Set Attach Flag if attach successfully.
1676 @param[in] BreakCause Break cause of this break event.
1677 @param[in] Timeout Time out value to wait for acknowledge from HOST.
1678 The unit is microsecond.
1679 @param[out] BreakReceived If BreakReceived is not NULL,
1680 TRUE is returned if break-in symbol received.
1681 FALSE is returned if break-in symbol not received.
1685 IN UINT8 BreakCause
,
1687 OUT BOOLEAN
*BreakReceived
1690 RETURN_STATUS Status
;
1691 DEBUG_PORT_HANDLE Handle
;
1692 BOOLEAN IncompatibilityFlag
;
1694 IncompatibilityFlag
= FALSE
;
1695 Handle
= GetDebugPortHandle();
1698 // Send init break and wait ack in Timeout
1700 DebugPortWriteBuffer (Handle
, (UINT8
*) mErrorMsgSendInitPacket
, AsciiStrLen (mErrorMsgSendInitPacket
));
1701 if (BreakCause
== DEBUG_DATA_BREAK_CAUSE_SYSTEM_RESET
) {
1702 Status
= SendCommandAndWaitForAckOK (DEBUG_COMMAND_INIT_BREAK
, Timeout
, BreakReceived
, &IncompatibilityFlag
);
1704 Status
= SendCommandAndWaitForAckOK (DEBUG_COMMAND_ATTACH_BREAK
, Timeout
, BreakReceived
, &IncompatibilityFlag
);
1706 if (IncompatibilityFlag
) {
1708 // If the incompatible Debug Packet received, the HOST should be running transfer protocol before PcdTransferProtocolRevision.
1709 // It could be UDK Debugger for Windows v1.1/v1.2 or for Linux v0.8/v1.2.
1711 DebugPortWriteBuffer (Handle
, (UINT8
*) mErrorMsgVersionAlert
, AsciiStrLen (mErrorMsgVersionAlert
));
1715 if (RETURN_ERROR (Status
)) {
1716 DebugPortWriteBuffer (Handle
, (UINT8
*) mErrorMsgConnectFail
, AsciiStrLen (mErrorMsgConnectFail
));
1718 DebugPortWriteBuffer (Handle
, (UINT8
*) mErrorMsgConnectOK
, AsciiStrLen (mErrorMsgConnectOK
));
1722 SetHostAttached (TRUE
);
1728 Send Break point packet to HOST.
1730 Only the first breaking processor could sent BREAK_POINT packet.
1732 @param[in] BreakCause Break cause of this break event.
1733 @param[in] ProcessorIndex Processor index value.
1734 @param[out] BreakReceived If BreakReceived is not NULL,
1735 TRUE is returned if break-in symbol received.
1736 FALSE is returned if break-in symbol not received.
1740 SendBreakPacketToHost (
1741 IN UINT8 BreakCause
,
1742 IN UINT32 ProcessorIndex
,
1743 OUT BOOLEAN
*BreakReceived
1746 UINT8 InputCharacter
;
1747 DEBUG_PORT_HANDLE Handle
;
1749 Handle
= GetDebugPortHandle();
1751 if (IsHostAttached ()) {
1752 DebugAgentMsgPrint (DEBUG_AGENT_INFO
, "processor[%x]:Send Break Packet to HOST.\n", ProcessorIndex
);
1753 SendCommandAndWaitForAckOK (DEBUG_COMMAND_BREAK_POINT
, READ_PACKET_TIMEOUT
, BreakReceived
, NULL
);
1755 DebugAgentMsgPrint (DEBUG_AGENT_INFO
, "processor[%x]:Try to attach HOST.\n", ProcessorIndex
);
1757 // If HOST is not attached, try to attach it firstly.
1760 // Poll Attach symbols from HOST and ack OK
1763 DebugAgentReadBuffer (Handle
, &InputCharacter
, 1, 0);
1764 } while (InputCharacter
!= DEBUG_STARTING_SYMBOL_ATTACH
);
1765 SendAckPacket (DEBUG_COMMAND_OK
);
1768 // Try to attach HOST
1770 while (AttachHost (BreakCause
, 0, NULL
) != RETURN_SUCCESS
);
1776 The main function to process communication with HOST.
1778 It received the command packet from HOST, and sent response data packet to HOST.
1780 @param[in] Vector Vector value of exception or interrupt.
1781 @param[in, out] CpuContext Pointer to saved CPU context.
1782 @param[in] BreakReceived TRUE means break-in symbol received.
1783 FALSE means break-in symbol not received.
1787 CommandCommunication (
1789 IN OUT DEBUG_CPU_CONTEXT
*CpuContext
,
1790 IN BOOLEAN BreakReceived
1793 RETURN_STATUS Status
;
1794 UINT8 InputPacketBuffer
[DEBUG_DATA_UPPER_LIMIT
+ sizeof (UINT64
) - 1];
1795 DEBUG_PACKET_HEADER
*DebugHeader
;
1800 DEBUG_DATA_READ_MEMORY
*MemoryRead
;
1801 DEBUG_DATA_WRITE_MEMORY
*MemoryWrite
;
1802 DEBUG_DATA_READ_IO
*IoRead
;
1803 DEBUG_DATA_WRITE_IO
*IoWrite
;
1804 DEBUG_DATA_READ_REGISTER
*RegisterRead
;
1805 DEBUG_DATA_WRITE_REGISTER
*RegisterWrite
;
1806 UINT8
*RegisterBuffer
;
1807 DEBUG_DATA_READ_MSR
*MsrRegisterRead
;
1808 DEBUG_DATA_WRITE_MSR
*MsrRegisterWrite
;
1809 DEBUG_DATA_CPUID
*Cpuid
;
1810 DEBUG_DATA_RESPONSE_BREAK_CAUSE BreakCause
;
1811 DEBUG_DATA_RESPONSE_CPUID CpuidResponse
;
1812 DEBUG_DATA_SEARCH_SIGNATURE
*SearchSignature
;
1813 DEBUG_DATA_RESPONSE_GET_EXCEPTION Exception
;
1814 DEBUG_DATA_RESPONSE_GET_REVISION DebugAgentRevision
;
1815 DEBUG_DATA_SET_VIEWPOINT
*SetViewPoint
;
1816 BOOLEAN HaltDeferred
;
1817 UINT32 ProcessorIndex
;
1818 DEBUG_AGENT_EXCEPTION_BUFFER AgentExceptionBuffer
;
1819 UINT32 IssuedViewPoint
;
1820 DEBUG_AGENT_MAILBOX
*Mailbox
;
1821 UINT8
*AlignedDataPtr
;
1824 IssuedViewPoint
= 0;
1825 HaltDeferred
= BreakReceived
;
1827 if (MultiProcessorDebugSupport()) {
1828 ProcessorIndex
= GetProcessorIndex ();
1829 SetCpuStopFlagByIndex (ProcessorIndex
, TRUE
);
1830 if (mDebugMpContext
.ViewPointIndex
== ProcessorIndex
) {
1832 // Only the current view processor could set AgentInProgress Flag.
1834 IssuedViewPoint
= ProcessorIndex
;
1838 if (IssuedViewPoint
== ProcessorIndex
) {
1840 // Set AgentInProgress Flag.
1842 SetDebugFlag (DEBUG_AGENT_FLAG_AGENT_IN_PROGRESS
, 1);
1847 if (MultiProcessorDebugSupport()) {
1849 // Check if the current processor is HOST view point
1851 if (mDebugMpContext
.ViewPointIndex
!= ProcessorIndex
) {
1852 if (mDebugMpContext
.RunCommandSet
) {
1854 // If HOST view point sets RUN flag, run GO command to leave
1856 SetCpuStopFlagByIndex (ProcessorIndex
, FALSE
);
1857 CommandGo (CpuContext
);
1861 // Run into loop again
1869 AcquireMpSpinLock (&mDebugMpContext
.DebugPortSpinLock
);
1871 DebugHeader
=(DEBUG_PACKET_HEADER
*) InputPacketBuffer
;
1873 DebugAgentMsgPrint (DEBUG_AGENT_INFO
, "TARGET: Try to get command from HOST...\n");
1874 Status
= ReceivePacket ((UINT8
*) DebugHeader
, &BreakReceived
, NULL
, READ_PACKET_TIMEOUT
, TRUE
);
1875 if (Status
!= RETURN_SUCCESS
|| !IS_REQUEST (DebugHeader
)) {
1876 DebugAgentMsgPrint (DEBUG_AGENT_WARNING
, "TARGET: Get command[%x] sequenceno[%x] returned status is [%x] \n", DebugHeader
->Command
, DebugHeader
->SequenceNo
, Status
);
1877 DebugAgentMsgPrint (DEBUG_AGENT_WARNING
, "TARGET: Get command failed or it's response packet not expected! \n");
1878 ReleaseMpSpinLock (&mDebugMpContext
.DebugPortSpinLock
);
1882 Mailbox
= GetMailboxPointer ();
1883 if (DebugHeader
->SequenceNo
== Mailbox
->HostSequenceNo
) {
1884 DebugAgentMsgPrint (DEBUG_AGENT_WARNING
, "TARGET: Receive one old command[%x] against command[%x]\n", DebugHeader
->SequenceNo
, Mailbox
->HostSequenceNo
);
1885 SendAckPacket (Mailbox
->LastAck
);
1886 ReleaseMpSpinLock (&mDebugMpContext
.DebugPortSpinLock
);
1888 } else if (DebugHeader
->SequenceNo
== (UINT8
) (Mailbox
->HostSequenceNo
+ 1)) {
1889 UpdateMailboxContent (Mailbox
, DEBUG_MAILBOX_HOST_SEQUENCE_NO_INDEX
, (UINT8
) DebugHeader
->SequenceNo
);
1891 DebugAgentMsgPrint (DEBUG_AGENT_WARNING
, "Receive one invalid command[%x] against command[%x]\n", DebugHeader
->SequenceNo
, Mailbox
->HostSequenceNo
);
1892 ReleaseMpSpinLock (&mDebugMpContext
.DebugPortSpinLock
);
1897 // Save CPU content before executing HOST command
1899 UpdateMailboxContent (Mailbox
, DEBUG_MAILBOX_EXCEPTION_BUFFER_POINTER_INDEX
, (UINT64
)(UINTN
) &AgentExceptionBuffer
.JumpBuffer
);
1900 if (SetJump (&AgentExceptionBuffer
.JumpBuffer
) != 0) {
1902 // If HOST command failed, continue to wait for HOST's next command
1903 // If needed, agent could send exception info to HOST.
1905 SendAckPacket (DEBUG_COMMAND_ABORT
);
1906 ReleaseMpSpinLock (&mDebugMpContext
.DebugPortSpinLock
);
1910 DebugAgentMsgPrint (DEBUG_AGENT_INFO
, "Processor[%x]:Received one command(%x)\n", mDebugMpContext
.ViewPointIndex
, DebugHeader
->Command
);
1912 switch (DebugHeader
->Command
) {
1914 case DEBUG_COMMAND_HALT
:
1915 SendAckPacket (DEBUG_COMMAND_HALT_DEFERRED
);
1916 HaltDeferred
= TRUE
;
1917 BreakReceived
= FALSE
;
1918 Status
= RETURN_SUCCESS
;
1921 case DEBUG_COMMAND_RESET
:
1922 SendAckPacket (DEBUG_COMMAND_OK
);
1923 SendAckPacket (DEBUG_COMMAND_OK
);
1924 SendAckPacket (DEBUG_COMMAND_OK
);
1925 ReleaseMpSpinLock (&mDebugMpContext
.DebugPortSpinLock
);
1929 // Assume system resets in 2 seconds, otherwise send TIMEOUT packet.
1930 // PCD can be used if 2 seconds isn't long enough for some platforms.
1932 MicroSecondDelay (2000000);
1933 UpdateMailboxContent (Mailbox
, DEBUG_MAILBOX_HOST_SEQUENCE_NO_INDEX
, Mailbox
->HostSequenceNo
+ 1);
1934 SendAckPacket (DEBUG_COMMAND_TIMEOUT
);
1935 SendAckPacket (DEBUG_COMMAND_TIMEOUT
);
1936 SendAckPacket (DEBUG_COMMAND_TIMEOUT
);
1939 case DEBUG_COMMAND_GO
:
1940 CommandGo (CpuContext
);
1942 // Clear Dr0 to avoid to be recognized as IMAGE_LOAD/_UNLOAD again when hitting a breakpoint after GO
1943 // If HOST changed Dr0 before GO, we will not change Dr0 here
1945 Data8
= GetBreakCause (Vector
, CpuContext
);
1946 if (Data8
== DEBUG_DATA_BREAK_CAUSE_IMAGE_LOAD
|| Data8
== DEBUG_DATA_BREAK_CAUSE_IMAGE_UNLOAD
) {
1947 CpuContext
->Dr0
= 0;
1950 if (!HaltDeferred
) {
1952 // If no HALT command received when being in-active mode
1954 if (MultiProcessorDebugSupport()) {
1955 Data32
= FindNextPendingBreakCpu ();
1958 // If there are still others processors being in break state,
1959 // send OK packet to HOST to finish this go command
1961 SendAckPacket (DEBUG_COMMAND_OK
);
1964 // Set current view to the next breaking processor
1966 mDebugMpContext
.ViewPointIndex
= Data32
;
1967 mDebugMpContext
.BreakAtCpuIndex
= mDebugMpContext
.ViewPointIndex
;
1968 SetCpuBreakFlagByIndex (mDebugMpContext
.ViewPointIndex
, FALSE
);
1970 // Send break packet to HOST to let HOST break again
1972 SendBreakPacketToHost (DEBUG_DATA_BREAK_CAUSE_UNKNOWN
, mDebugMpContext
.BreakAtCpuIndex
, &BreakReceived
);
1974 // Continue to run into loop to read command packet from HOST
1976 ReleaseMpSpinLock (&mDebugMpContext
.DebugPortSpinLock
);
1981 // If no else processor break, set stop bitmask,
1982 // and set Running flag for all processors.
1984 SetCpuStopFlagByIndex (ProcessorIndex
, FALSE
);
1985 SetCpuRunningFlag (TRUE
);
1988 // Wait for all processors are in running state
1991 if (IsAllCpuRunning ()) {
1996 // Set BSP to be current view point.
1998 SetDebugViewPoint (mDebugMpContext
.BspIndex
);
2001 // Clear breaking processor index and running flag
2003 mDebugMpContext
.BreakAtCpuIndex
= (UINT32
) (-1);
2004 SetCpuRunningFlag (FALSE
);
2008 // Send OK packet to HOST to finish this go command
2010 SendAckPacket (DEBUG_COMMAND_OK
);
2012 ReleaseMpSpinLock (&mDebugMpContext
.DebugPortSpinLock
);
2014 if (!IsHostAttached()) {
2015 UpdateMailboxContent (Mailbox
, DEBUG_MAILBOX_SEQUENCE_NO_INDEX
, 0);
2016 UpdateMailboxContent (Mailbox
, DEBUG_MAILBOX_HOST_SEQUENCE_NO_INDEX
, 0);
2022 // If received HALT command, need to defer the GO command
2024 SendAckPacket (DEBUG_COMMAND_HALT_PROCESSED
);
2025 HaltDeferred
= FALSE
;
2027 Vector
= DEBUG_TIMER_VECTOR
;
2031 case DEBUG_COMMAND_BREAK_CAUSE
:
2032 BreakCause
.StopAddress
= CpuContext
->Eip
;
2033 if (MultiProcessorDebugSupport() && ProcessorIndex
!= mDebugMpContext
.BreakAtCpuIndex
) {
2034 BreakCause
.Cause
= GetBreakCause (DEBUG_TIMER_VECTOR
, CpuContext
);
2036 BreakCause
.Cause
= GetBreakCause (Vector
, CpuContext
);
2038 SendDataResponsePacket ((UINT8
*) &BreakCause
, (UINT16
) sizeof (DEBUG_DATA_RESPONSE_BREAK_CAUSE
), DebugHeader
);
2041 case DEBUG_COMMAND_SET_HW_BREAKPOINT
:
2042 SetDebugRegister (CpuContext
, (DEBUG_DATA_SET_HW_BREAKPOINT
*) (DebugHeader
+ 1));
2043 SendAckPacket (DEBUG_COMMAND_OK
);
2046 case DEBUG_COMMAND_CLEAR_HW_BREAKPOINT
:
2047 ClearDebugRegister (CpuContext
, (DEBUG_DATA_CLEAR_HW_BREAKPOINT
*) (DebugHeader
+ 1));
2048 SendAckPacket (DEBUG_COMMAND_OK
);
2051 case DEBUG_COMMAND_SINGLE_STEPPING
:
2052 CommandStepping (CpuContext
);
2054 // Clear Dr0 to avoid to be recognized as IMAGE_LOAD/_UNLOAD again when hitting a breakpoint after GO
2055 // If HOST changed Dr0 before GO, we will not change Dr0 here
2057 Data8
= GetBreakCause (Vector
, CpuContext
);
2058 if (Data8
== DEBUG_DATA_BREAK_CAUSE_IMAGE_LOAD
|| Data8
== DEBUG_DATA_BREAK_CAUSE_IMAGE_UNLOAD
) {
2059 CpuContext
->Dr0
= 0;
2062 mDebugMpContext
.BreakAtCpuIndex
= (UINT32
) (-1);
2063 ReleaseMpSpinLock (&mDebugMpContext
.DebugPortSpinLock
);
2065 // Executing stepping command directly without sending ACK packet,
2066 // ACK packet will be sent after stepping done.
2070 case DEBUG_COMMAND_SET_SW_BREAKPOINT
:
2071 Data64
= (UINTN
) (((DEBUG_DATA_SET_SW_BREAKPOINT
*) (DebugHeader
+ 1))->Address
);
2072 Data8
= *(UINT8
*) (UINTN
) Data64
;
2073 *(UINT8
*) (UINTN
) Data64
= DEBUG_SW_BREAKPOINT_SYMBOL
;
2074 Status
= SendDataResponsePacket ((UINT8
*) &Data8
, (UINT16
) sizeof (UINT8
), DebugHeader
);
2077 case DEBUG_COMMAND_READ_MEMORY
:
2078 MemoryRead
= (DEBUG_DATA_READ_MEMORY
*) (DebugHeader
+ 1);
2079 Status
= ReadMemoryAndSendResponsePacket ((UINT8
*) (UINTN
) MemoryRead
->Address
, MemoryRead
->Count
, MemoryRead
->Width
, DebugHeader
);
2082 case DEBUG_COMMAND_WRITE_MEMORY
:
2083 MemoryWrite
= (DEBUG_DATA_WRITE_MEMORY
*) (DebugHeader
+ 1);
2085 // Copy data into one memory with 8-byte alignment address
2087 AlignedDataPtr
= ALIGN_POINTER ((UINT8
*) &MemoryWrite
->Data
, sizeof (UINT64
));
2088 if (AlignedDataPtr
!= (UINT8
*) &MemoryWrite
->Data
) {
2089 CopyMem (AlignedDataPtr
, (UINT8
*) &MemoryWrite
->Data
, MemoryWrite
->Count
* MemoryWrite
->Width
);
2091 CopyMemByWidth ((UINT8
*) (UINTN
) MemoryWrite
->Address
, AlignedDataPtr
, MemoryWrite
->Count
, MemoryWrite
->Width
);
2092 SendAckPacket (DEBUG_COMMAND_OK
);
2095 case DEBUG_COMMAND_READ_IO
:
2096 IoRead
= (DEBUG_DATA_READ_IO
*) (DebugHeader
+ 1);
2097 switch (IoRead
->Width
) {
2099 Data64
= IoRead8 ((UINTN
) IoRead
->Port
);
2102 Data64
= IoRead16 ((UINTN
) IoRead
->Port
);
2105 Data64
= IoRead32 ((UINTN
) IoRead
->Port
);
2108 Data64
= IoRead64 ((UINTN
) IoRead
->Port
);
2111 Data64
= (UINT64
) -1;
2113 Status
= SendDataResponsePacket ((UINT8
*) &Data64
, IoRead
->Width
, DebugHeader
);
2116 case DEBUG_COMMAND_WRITE_IO
:
2117 IoWrite
= (DEBUG_DATA_WRITE_IO
*) (DebugHeader
+ 1);
2118 switch (IoWrite
->Width
) {
2120 Data64
= IoWrite8 ((UINTN
) IoWrite
->Port
, *(UINT8
*) &IoWrite
->Data
);
2123 Data64
= IoWrite16 ((UINTN
) IoWrite
->Port
, *(UINT16
*) &IoWrite
->Data
);
2126 Data64
= IoWrite32 ((UINTN
) IoWrite
->Port
, *(UINT32
*) &IoWrite
->Data
);
2129 Data64
= IoWrite64 ((UINTN
) IoWrite
->Port
, *(UINT64
*) &IoWrite
->Data
);
2132 Data64
= (UINT64
) -1;
2134 SendAckPacket (DEBUG_COMMAND_OK
);
2137 case DEBUG_COMMAND_READ_ALL_REGISTERS
:
2138 Status
= SendDataResponsePacket ((UINT8
*) CpuContext
, sizeof (*CpuContext
), DebugHeader
);
2141 case DEBUG_COMMAND_READ_REGISTER
:
2142 RegisterRead
= (DEBUG_DATA_READ_REGISTER
*) (DebugHeader
+ 1);
2144 if (RegisterRead
->Index
<= SOFT_DEBUGGER_REGISTER_MAX
) {
2145 RegisterBuffer
= ArchReadRegisterBuffer (CpuContext
, RegisterRead
->Index
, &Width
);
2146 Status
= SendDataResponsePacket (RegisterBuffer
, Width
, DebugHeader
);
2148 Status
= RETURN_UNSUPPORTED
;
2152 case DEBUG_COMMAND_WRITE_REGISTER
:
2153 RegisterWrite
= (DEBUG_DATA_WRITE_REGISTER
*) (DebugHeader
+ 1);
2154 if (RegisterWrite
->Index
<= SOFT_DEBUGGER_REGISTER_MAX
) {
2155 RegisterBuffer
= ArchReadRegisterBuffer (CpuContext
, RegisterWrite
->Index
, &Width
);
2156 ASSERT (Width
== RegisterWrite
->Length
);
2157 CopyMem (RegisterBuffer
, RegisterWrite
->Data
, Width
);
2158 SendAckPacket (DEBUG_COMMAND_OK
);
2160 Status
= RETURN_UNSUPPORTED
;
2164 case DEBUG_COMMAND_ARCH_MODE
:
2165 Data8
= DEBUG_ARCH_SYMBOL
;
2166 Status
= SendDataResponsePacket ((UINT8
*) &Data8
, (UINT16
) sizeof (UINT8
), DebugHeader
);
2169 case DEBUG_COMMAND_READ_MSR
:
2170 MsrRegisterRead
= (DEBUG_DATA_READ_MSR
*) (DebugHeader
+ 1);
2171 Data64
= AsmReadMsr64 (MsrRegisterRead
->Index
);
2172 Status
= SendDataResponsePacket ((UINT8
*) &Data64
, (UINT16
) sizeof (UINT64
), DebugHeader
);
2175 case DEBUG_COMMAND_WRITE_MSR
:
2176 MsrRegisterWrite
= (DEBUG_DATA_WRITE_MSR
*) (DebugHeader
+ 1);
2177 AsmWriteMsr64 (MsrRegisterWrite
->Index
, MsrRegisterWrite
->Value
);
2178 SendAckPacket (DEBUG_COMMAND_OK
);
2181 case DEBUG_COMMAND_SET_DEBUG_SETTING
:
2182 Status
= SetDebugSetting ((DEBUG_DATA_SET_DEBUG_SETTING
*)(DebugHeader
+ 1));
2183 if (Status
== RETURN_SUCCESS
) {
2184 SendAckPacket (DEBUG_COMMAND_OK
);
2188 case DEBUG_COMMAND_GET_REVISION
:
2189 DebugAgentRevision
.Revision
= PcdGet32(PcdTransferProtocolRevision
);
2190 DebugAgentRevision
.Capabilities
= DEBUG_AGENT_CAPABILITIES
;
2191 Status
= SendDataResponsePacket ((UINT8
*) &DebugAgentRevision
, (UINT16
) sizeof (DEBUG_DATA_RESPONSE_GET_REVISION
), DebugHeader
);
2194 case DEBUG_COMMAND_GET_EXCEPTION
:
2195 Exception
.ExceptionNum
= (UINT8
) Vector
;
2196 Exception
.ExceptionData
= (UINT32
) CpuContext
->ExceptionData
;
2197 Status
= SendDataResponsePacket ((UINT8
*) &Exception
, (UINT16
) sizeof (DEBUG_DATA_RESPONSE_GET_EXCEPTION
), DebugHeader
);
2200 case DEBUG_COMMAND_SET_VIEWPOINT
:
2201 SetViewPoint
= (DEBUG_DATA_SET_VIEWPOINT
*) (DebugHeader
+ 1);
2202 if (MultiProcessorDebugSupport()) {
2203 if (IsCpuStopped (SetViewPoint
->ViewPoint
)) {
2204 SetDebugViewPoint (SetViewPoint
->ViewPoint
);
2205 SendAckPacket (DEBUG_COMMAND_OK
);
2208 // If CPU is not halted
2210 SendAckPacket (DEBUG_COMMAND_NOT_SUPPORTED
);
2212 } else if (SetViewPoint
->ViewPoint
== 0) {
2213 SendAckPacket (DEBUG_COMMAND_OK
);
2216 SendAckPacket (DEBUG_COMMAND_NOT_SUPPORTED
);
2221 case DEBUG_COMMAND_GET_VIEWPOINT
:
2222 Data32
= mDebugMpContext
.ViewPointIndex
;
2223 SendDataResponsePacket((UINT8
*) &Data32
, (UINT16
) sizeof (UINT32
), DebugHeader
);
2226 case DEBUG_COMMAND_MEMORY_READY
:
2227 Data8
= (UINT8
) GetDebugFlag (DEBUG_AGENT_FLAG_MEMORY_READY
);
2228 SendDataResponsePacket (&Data8
, (UINT16
) sizeof (UINT8
), DebugHeader
);
2231 case DEBUG_COMMAND_DETACH
:
2232 SetHostAttached (FALSE
);
2233 SendAckPacket (DEBUG_COMMAND_OK
);
2236 case DEBUG_COMMAND_CPUID
:
2237 Cpuid
= (DEBUG_DATA_CPUID
*) (DebugHeader
+ 1);
2239 Cpuid
->Eax
, Cpuid
->Ecx
,
2240 &CpuidResponse
.Eax
, &CpuidResponse
.Ebx
,
2241 &CpuidResponse
.Ecx
, &CpuidResponse
.Edx
2243 SendDataResponsePacket ((UINT8
*) &CpuidResponse
, (UINT16
) sizeof (CpuidResponse
), DebugHeader
);
2246 case DEBUG_COMMAND_SEARCH_SIGNATURE
:
2247 SearchSignature
= (DEBUG_DATA_SEARCH_SIGNATURE
*) (DebugHeader
+ 1);
2248 if ((SearchSignature
->Alignment
!= 0) &&
2249 (SearchSignature
->Alignment
== GetPowerOfTwo32 (SearchSignature
->Alignment
))
2251 if (SearchSignature
->Positive
) {
2253 Data64
= ALIGN_VALUE ((UINTN
) SearchSignature
->Start
, SearchSignature
->Alignment
);
2254 Data64
<= SearchSignature
->Start
+ SearchSignature
->Count
- SearchSignature
->DataLength
;
2255 Data64
+= SearchSignature
->Alignment
2257 if (CompareMem ((VOID
*) (UINTN
) Data64
, &SearchSignature
->Data
, SearchSignature
->DataLength
) == 0) {
2261 if (Data64
> SearchSignature
->Start
+ SearchSignature
->Count
- SearchSignature
->DataLength
) {
2262 Data64
= (UINT64
) -1;
2266 Data64
= ALIGN_VALUE ((UINTN
) SearchSignature
->Start
- SearchSignature
->Alignment
, SearchSignature
->Alignment
);
2267 Data64
>= SearchSignature
->Start
- SearchSignature
->Count
;
2268 Data64
-= SearchSignature
->Alignment
2270 if (CompareMem ((VOID
*) (UINTN
) Data64
, &SearchSignature
->Data
, SearchSignature
->DataLength
) == 0) {
2274 if (Data64
< SearchSignature
->Start
- SearchSignature
->Count
) {
2275 Data64
= (UINT64
) -1;
2278 SendDataResponsePacket ((UINT8
*) &Data64
, (UINT16
) sizeof (Data64
), DebugHeader
);
2280 Status
= RETURN_UNSUPPORTED
;
2285 SendAckPacket (DEBUG_COMMAND_NOT_SUPPORTED
);
2289 if (Status
== RETURN_UNSUPPORTED
) {
2290 SendAckPacket (DEBUG_COMMAND_NOT_SUPPORTED
);
2291 } else if (Status
!= RETURN_SUCCESS
) {
2292 SendAckPacket (DEBUG_COMMAND_ABORT
);
2295 ReleaseMpSpinLock (&mDebugMpContext
.DebugPortSpinLock
);
2301 C function called in interrupt handler.
2303 @param[in] Vector Vector value of exception or interrupt.
2304 @param[in] CpuContext Pointer to save CPU context.
2311 IN DEBUG_CPU_CONTEXT
*CpuContext
2314 UINT8 InputCharacter
;
2317 BOOLEAN BreakReceived
;
2318 UINT32 ProcessorIndex
;
2319 UINT32 CurrentDebugTimerInitCount
;
2320 DEBUG_PORT_HANDLE Handle
;
2323 UINT32 IssuedViewPoint
;
2324 DEBUG_AGENT_EXCEPTION_BUFFER
*ExceptionBuffer
;
2328 IssuedViewPoint
= 0;
2329 BreakReceived
= FALSE
;
2331 if (mSkipBreakpoint
) {
2333 // If Skip Breakpoint flag is set, means communication is disturbed by hardware SMI, we need to ignore the break points in SMM
2335 if ((Vector
== DEBUG_INT1_VECTOR
) || (Vector
== DEBUG_INT3_VECTOR
)) {
2336 DebugPortWriteBuffer (GetDebugPortHandle(), (UINT8
*) mWarningMsgIngoreBreakpoint
, AsciiStrLen (mWarningMsgIngoreBreakpoint
));
2341 if (MultiProcessorDebugSupport()) {
2342 ProcessorIndex
= GetProcessorIndex ();
2344 // If this processor has already halted before, need to check it later
2346 if (IsCpuStopped (ProcessorIndex
)) {
2347 IssuedViewPoint
= ProcessorIndex
;
2351 if (IssuedViewPoint
== ProcessorIndex
&& GetDebugFlag (DEBUG_AGENT_FLAG_STEPPING
) != 1) {
2353 // Check if this exception is issued by Debug Agent itself
2354 // If yes, fill the debug agent exception buffer and LongJump() back to
2355 // the saved CPU content in CommandCommunication()
2356 // If exception is issued when executing Stepping, will be handled in
2357 // exception handle procedure.
2359 if (GetDebugFlag (DEBUG_AGENT_FLAG_AGENT_IN_PROGRESS
) == 1) {
2360 DebugAgentMsgPrint (
2362 "Debug agent meet one Exception, ExceptionNum is %d, EIP = 0x%x.\n",
2364 (UINTN
)CpuContext
->Eip
2366 ExceptionBuffer
= (DEBUG_AGENT_EXCEPTION_BUFFER
*) (UINTN
) GetMailboxPointer()->ExceptionBufferPointer
;
2367 ExceptionBuffer
->ExceptionContent
.ExceptionNum
= (UINT8
) Vector
;
2368 ExceptionBuffer
->ExceptionContent
.ExceptionData
= (UINT32
) CpuContext
->ExceptionData
;
2369 LongJump ((BASE_LIBRARY_JUMP_BUFFER
*)(UINTN
)(ExceptionBuffer
), 1);
2373 if (MultiProcessorDebugSupport()) {
2375 // If RUN command is executing, wait for it done.
2377 while (mDebugMpContext
.RunCommandSet
) {
2382 Handle
= GetDebugPortHandle();
2383 BreakCause
= GetBreakCause (Vector
, CpuContext
);
2385 case DEBUG_INT1_VECTOR
:
2386 case DEBUG_INT3_VECTOR
:
2387 switch (BreakCause
) {
2388 case DEBUG_DATA_BREAK_CAUSE_SYSTEM_RESET
:
2389 if (AttachHost (BreakCause
, READ_PACKET_TIMEOUT
, &BreakReceived
) != RETURN_SUCCESS
) {
2391 // Try to connect HOST, return if fails
2395 CommandCommunication (Vector
, CpuContext
, BreakReceived
);
2398 case DEBUG_DATA_BREAK_CAUSE_STEPPING
:
2400 // Stepping is finished, send Ack package.
2402 if (MultiProcessorDebugSupport()) {
2403 mDebugMpContext
.BreakAtCpuIndex
= ProcessorIndex
;
2406 // Clear Stepping Flag and restore EFLAGS.IF
2408 CommandSteppingCleanup (CpuContext
);
2409 SendAckPacket (DEBUG_COMMAND_OK
);
2410 CommandCommunication (Vector
, CpuContext
, BreakReceived
);
2413 case DEBUG_DATA_BREAK_CAUSE_MEMORY_READY
:
2417 SendCommandAndWaitForAckOK (DEBUG_COMMAND_MEMORY_READY
, READ_PACKET_TIMEOUT
, &BreakReceived
, NULL
);
2418 CommandCommunication (Vector
, CpuContext
, BreakReceived
);
2421 case DEBUG_DATA_BREAK_CAUSE_IMAGE_LOAD
:
2422 case DEBUG_DATA_BREAK_CAUSE_IMAGE_UNLOAD
:
2424 // Set AL to DEBUG_AGENT_IMAGE_CONTINUE
2426 Al
= ArchReadRegisterBuffer (CpuContext
, SOFT_DEBUGGER_REGISTER_AX
, &Data8
);
2427 *Al
= DEBUG_AGENT_IMAGE_CONTINUE
;
2429 if (!IsHostAttached ()) {
2431 // If HOST is not connected for image load/unload, return
2436 // Continue to run the following common code
2439 case DEBUG_DATA_BREAK_CAUSE_HW_BREAKPOINT
:
2440 case DEBUG_DATA_BREAK_CAUSE_SW_BREAKPOINT
:
2443 // Send Break packet to HOST
2445 AcquireMpSpinLock (&mDebugMpContext
.DebugPortSpinLock
);
2447 // Only the first breaking processor could send BREAK_POINT to HOST
2449 if (IsFirstBreakProcessor (ProcessorIndex
)) {
2450 SendBreakPacketToHost (BreakCause
, ProcessorIndex
, &BreakReceived
);
2452 ReleaseMpSpinLock (&mDebugMpContext
.DebugPortSpinLock
);
2454 if (Vector
== DEBUG_INT3_VECTOR
) {
2456 // go back address located "0xCC"
2459 SavedEip
= CpuContext
->Eip
;
2460 CommandCommunication (Vector
, CpuContext
, BreakReceived
);
2461 if ((SavedEip
== CpuContext
->Eip
) &&
2462 (*(UINT8
*) (UINTN
) CpuContext
->Eip
== DEBUG_SW_BREAKPOINT_SYMBOL
)) {
2464 // If this is not a software breakpoint set by HOST,
2470 CommandCommunication (Vector
, CpuContext
, BreakReceived
);
2477 case DEBUG_TIMER_VECTOR
:
2479 AcquireMpSpinLock (&mDebugMpContext
.DebugPortSpinLock
);
2481 if (MultiProcessorDebugSupport()) {
2482 if (DebugAgentIsBsp (ProcessorIndex
)) {
2484 // If current processor is BSP, check Apic timer's init count if changed,
2485 // it may be re-written when switching BSP.
2486 // If it changed, re-initialize debug timer
2488 CurrentDebugTimerInitCount
= GetApicTimerInitCount ();
2489 if (mDebugMpContext
.DebugTimerInitCount
!= CurrentDebugTimerInitCount
) {
2490 InitializeDebugTimer (NULL
, FALSE
);
2491 SaveAndSetDebugTimerInterrupt (TRUE
);
2495 if (!DebugAgentIsBsp (ProcessorIndex
) || mDebugMpContext
.IpiSentByAp
) {
2496 ReleaseMpSpinLock (&mDebugMpContext
.DebugPortSpinLock
);
2498 // If current processor is not BSP or this is one IPI sent by AP
2500 if (mDebugMpContext
.BreakAtCpuIndex
!= (UINT32
) (-1)) {
2501 CommandCommunication (Vector
, CpuContext
, FALSE
);
2505 // Clear EOI before exiting interrupt process routine.
2513 // Only BSP could run here
2517 // If there is data in debug port, will check whether it is break(attach/break-in) symbol,
2518 // If yes, go into communication mode with HOST.
2519 // If no, exit interrupt process.
2521 if (DebugReadBreakSymbol (Handle
, &InputCharacter
) == EFI_NOT_FOUND
) {
2525 if ((!IsHostAttached () && (InputCharacter
== DEBUG_STARTING_SYMBOL_ATTACH
)) ||
2526 (IsHostAttached () && (InputCharacter
== DEBUG_COMMAND_HALT
)) ||
2527 (IsHostAttached () && (InputCharacter
== DEBUG_COMMAND_GO
))
2529 DebugAgentMsgPrint (DEBUG_AGENT_VERBOSE
, "Received data [%02x]\n", InputCharacter
);
2531 // Ack OK for break-in symbol
2533 SendAckPacket (DEBUG_COMMAND_OK
);
2536 // If receive GO command in Debug Timer, means HOST may lost ACK packet before.
2538 if (InputCharacter
== DEBUG_COMMAND_GO
) {
2542 if (!IsHostAttached ()) {
2544 // Try to attach HOST, if no ack received after 200ms, return
2546 if (AttachHost (BreakCause
, READ_PACKET_TIMEOUT
, &BreakReceived
) != RETURN_SUCCESS
) {
2551 if (MultiProcessorDebugSupport()) {
2552 if(FindNextPendingBreakCpu () != -1) {
2553 SetCpuBreakFlagByIndex (ProcessorIndex
, TRUE
);
2555 HaltOtherProcessors (ProcessorIndex
);
2558 ReleaseMpSpinLock (&mDebugMpContext
.DebugPortSpinLock
);
2559 CommandCommunication (Vector
, CpuContext
, BreakReceived
);
2560 AcquireMpSpinLock (&mDebugMpContext
.DebugPortSpinLock
);
2566 // Clear EOI before exiting interrupt process routine.
2570 ReleaseMpSpinLock (&mDebugMpContext
.DebugPortSpinLock
);
2575 if (Vector
<= DEBUG_EXCEPT_SIMD
) {
2576 DebugAgentMsgPrint (
2578 "Exception happened, ExceptionNum is %d, EIP = 0x%x.\n",
2580 (UINTN
) CpuContext
->Eip
2582 if (BreakCause
== DEBUG_DATA_BREAK_CAUSE_STEPPING
) {
2584 // If exception happened when executing Stepping, send Ack package.
2585 // HOST consider Stepping command was finished.
2587 if (MultiProcessorDebugSupport()) {
2588 mDebugMpContext
.BreakAtCpuIndex
= ProcessorIndex
;
2591 // Clear Stepping flag and restore EFLAGS.IF
2593 CommandSteppingCleanup (CpuContext
);
2594 SendAckPacket (DEBUG_COMMAND_OK
);
2597 // Exception occurs, send Break packet to HOST
2599 AcquireMpSpinLock (&mDebugMpContext
.DebugPortSpinLock
);
2601 // Only the first breaking processor could send BREAK_POINT to HOST
2603 if (IsFirstBreakProcessor (ProcessorIndex
)) {
2604 SendBreakPacketToHost (BreakCause
, ProcessorIndex
, &BreakReceived
);
2606 ReleaseMpSpinLock (&mDebugMpContext
.DebugPortSpinLock
);
2609 CommandCommunication (Vector
, CpuContext
, BreakReceived
);
2614 if (MultiProcessorDebugSupport()) {
2616 // Clear flag and wait for all processors run here
2618 SetIpiSentByApFlag (FALSE
);
2619 while (mDebugMpContext
.RunCommandSet
) {
2624 // Only current (view) processor could clean up AgentInProgress flag.
2626 if (mDebugMpContext
.ViewPointIndex
== ProcessorIndex
) {
2627 IssuedViewPoint
= mDebugMpContext
.ViewPointIndex
;
2631 if (IssuedViewPoint
== ProcessorIndex
&& GetDebugFlag (DEBUG_AGENT_FLAG_STEPPING
) != 1) {
2633 // If the command is not stepping, clean up AgentInProgress flag
2635 SetDebugFlag (DEBUG_AGENT_FLAG_AGENT_IN_PROGRESS
, 0);