2 Commond Debug Agent library implementition. It mainly includes
3 the first C function called by exception/interrupt handlers,
4 read/write debug packet to communication with HOST based on transfer
7 Copyright (c) 2010 - 2014, Intel Corporation. All rights reserved.<BR>
8 This program and the accompanying materials
9 are licensed and made available under the terms and conditions of the BSD License
10 which accompanies this distribution. The full text of the license may be found at
11 http://opensource.org/licenses/bsd-license.php.
13 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
14 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
18 #include "DebugAgent.h"
19 #include "Ia32/DebugException.h"
21 GLOBAL_REMOVE_IF_UNREFERENCED CHAR8 mErrorMsgVersionAlert
[] = "\rThe SourceLevelDebugPkg you are using requires a newer version of the Intel(R) UDK Debugger Tool.\r\n";
22 GLOBAL_REMOVE_IF_UNREFERENCED CHAR8 mErrorMsgSendInitPacket
[] = "\rSend INIT break packet and try to connect the HOST (Intel(R) UDK Debugger Tool v1.4) ...\r\n";
23 GLOBAL_REMOVE_IF_UNREFERENCED CHAR8 mErrorMsgConnectOK
[] = "HOST connection is successful!\r\n";
24 GLOBAL_REMOVE_IF_UNREFERENCED CHAR8 mErrorMsgConnectFail
[] = "HOST connection is failed!\r\n";
25 GLOBAL_REMOVE_IF_UNREFERENCED CHAR8 mWarningMsgIngoreBreakpoint
[] = "Ignore break point in SMM for SMI issued during DXE debugging!\r\n";
28 // Vector Handoff Info list used by Debug Agent for persist
30 GLOBAL_REMOVE_IF_UNREFERENCED EFI_VECTOR_HANDOFF_INFO mVectorHandoffInfoDebugAgent
[] = {
32 DEBUG_EXCEPT_DIVIDE_ERROR
, // Vector 0
33 EFI_VECTOR_HANDOFF_HOOK_BEFORE
,
37 DEBUG_EXCEPT_DEBUG
, // Vector 1
38 EFI_VECTOR_HANDOFF_DO_NOT_HOOK
,
42 DEBUG_EXCEPT_NMI
, // Vector 2
43 EFI_VECTOR_HANDOFF_HOOK_BEFORE
,
47 DEBUG_EXCEPT_BREAKPOINT
, // Vector 3
48 EFI_VECTOR_HANDOFF_DO_NOT_HOOK
,
52 DEBUG_EXCEPT_OVERFLOW
, // Vector 4
53 EFI_VECTOR_HANDOFF_HOOK_BEFORE
,
57 DEBUG_EXCEPT_BOUND
, // Vector 5
58 EFI_VECTOR_HANDOFF_HOOK_BEFORE
,
62 DEBUG_EXCEPT_INVALID_OPCODE
, // Vector 6
63 EFI_VECTOR_HANDOFF_HOOK_BEFORE
,
67 DEBUG_EXCEPT_DOUBLE_FAULT
, // Vector 8
68 EFI_VECTOR_HANDOFF_HOOK_BEFORE
,
72 DEBUG_EXCEPT_INVALID_TSS
, // Vector 10
73 EFI_VECTOR_HANDOFF_HOOK_BEFORE
,
77 DEBUG_EXCEPT_SEG_NOT_PRESENT
, // Vector 11
78 EFI_VECTOR_HANDOFF_HOOK_BEFORE
,
82 DEBUG_EXCEPT_STACK_FAULT
, // Vector 12
83 EFI_VECTOR_HANDOFF_HOOK_BEFORE
,
87 DEBUG_EXCEPT_GP_FAULT
, // Vector 13
88 EFI_VECTOR_HANDOFF_HOOK_BEFORE
,
92 DEBUG_EXCEPT_PAGE_FAULT
, // Vector 14
93 EFI_VECTOR_HANDOFF_HOOK_BEFORE
,
97 DEBUG_EXCEPT_FP_ERROR
, // Vector 16
98 EFI_VECTOR_HANDOFF_HOOK_BEFORE
,
102 DEBUG_EXCEPT_ALIGNMENT_CHECK
, // Vector 17
103 EFI_VECTOR_HANDOFF_HOOK_BEFORE
,
107 DEBUG_EXCEPT_MACHINE_CHECK
, // Vector 18
108 EFI_VECTOR_HANDOFF_HOOK_BEFORE
,
112 DEBUG_EXCEPT_SIMD
, // Vector 19
113 EFI_VECTOR_HANDOFF_HOOK_BEFORE
,
117 DEBUG_TIMER_VECTOR
, // Vector 32
118 EFI_VECTOR_HANDOFF_DO_NOT_HOOK
,
122 DEBUG_MAILBOX_VECTOR
, // Vector 33
123 EFI_VECTOR_HANDOFF_DO_NOT_HOOK
,
128 EFI_VECTOR_HANDOFF_LAST_ENTRY
,
133 GLOBAL_REMOVE_IF_UNREFERENCED UINTN mVectorHandoffInfoCount
= sizeof (mVectorHandoffInfoDebugAgent
) / sizeof (EFI_VECTOR_HANDOFF_INFO
);
136 Calculate CRC16 for target data.
138 @param[in] Data The target data.
139 @param[in] DataSize The target data size.
140 @param[in] Crc Initial CRC.
142 @return UINT16 The CRC16 value.
155 for (Index
= 0; Index
< DataSize
; Index
++) {
156 Crc
^= (UINT16
)Data
[Index
];
157 for (BitIndex
= 0; BitIndex
< 8; BitIndex
++) {
158 if ((Crc
& 0x8000) != 0) {
171 Read IDT entry to check if IDT entries are setup by Debug Agent.
173 @retval TRUE IDT entries were setup by Debug Agent.
174 @retval FALSE IDT entries were not setup by Debug Agent.
178 IsDebugAgentInitialzed (
182 UINTN InterruptHandler
;
184 InterruptHandler
= (UINTN
) GetExceptionHandlerInIdtEntry (0);
185 if (InterruptHandler
>= 4 && *(UINT32
*)(InterruptHandler
- 4) == AGENT_HANDLER_SIGNATURE
) {
193 Find and report module image info to HOST.
195 @param[in] AlignSize Image aligned size.
199 FindAndReportModuleImageInfo (
204 EFI_IMAGE_DOS_HEADER
*DosHdr
;
205 EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION Hdr
;
206 PE_COFF_LOADER_IMAGE_CONTEXT ImageContext
;
211 Pe32Data
= ((UINTN
)mErrorMsgVersionAlert
) & ~(AlignSize
- 1);
212 while (Pe32Data
!= 0) {
213 DosHdr
= (EFI_IMAGE_DOS_HEADER
*) Pe32Data
;
214 if (DosHdr
->e_magic
== EFI_IMAGE_DOS_SIGNATURE
) {
216 // DOS image header is present, so read the PE header after the DOS image header.
218 Hdr
.Pe32
= (EFI_IMAGE_NT_HEADERS32
*)(Pe32Data
+ (UINTN
) ((DosHdr
->e_lfanew
) & 0x0ffff));
220 // Make sure PE header address does not overflow and is less than the initial address.
222 if (((UINTN
)Hdr
.Pe32
> Pe32Data
) && ((UINTN
)Hdr
.Pe32
< (UINTN
)mErrorMsgVersionAlert
)) {
223 if (Hdr
.Pe32
->Signature
== EFI_IMAGE_NT_SIGNATURE
) {
232 // DOS image header is not present, TE header is at the image base.
234 Hdr
.Pe32
= (EFI_IMAGE_NT_HEADERS32
*)Pe32Data
;
235 if ((Hdr
.Te
->Signature
== EFI_TE_IMAGE_HEADER_SIGNATURE
) &&
236 ((Hdr
.Te
->Machine
== IMAGE_FILE_MACHINE_I386
) || Hdr
.Te
->Machine
== IMAGE_FILE_MACHINE_X64
)) {
238 // It's TE image, it TE header and Machine type match
245 // Not found the image base, check the previous aligned address
247 Pe32Data
-= AlignSize
;
250 ImageContext
.ImageAddress
= Pe32Data
;
251 ImageContext
.PdbPointer
= PeCoffLoaderGetPdbPointer ((VOID
*) (UINTN
) ImageContext
.ImageAddress
);
252 PeCoffLoaderRelocateImageExtraAction (&ImageContext
);
256 Trigger one software interrupt to debug agent to handle it.
258 @param[in] Signature Software interrupt signature.
262 TriggerSoftInterrupt (
270 // Save Debug Register State
278 AsmWriteDr0 (SOFT_INTERRUPT_SIGNATURE
);
279 AsmWriteDr1 (Signature
);
282 // Do INT3 to communicate with HOST side
287 // Restore Debug Register State only when Host didn't change it inside exception handler.
288 // Dr registers can only be changed by setting the HW breakpoint.
296 Caculate Mailbox checksum and update the checksum field.
298 @param[in] Mailbox Debug Agent Mailbox pointer.
302 UpdateMailboxChecksum (
303 IN DEBUG_AGENT_MAILBOX
*Mailbox
306 Mailbox
->CheckSum
= CalculateCheckSum8 ((UINT8
*)Mailbox
, sizeof (DEBUG_AGENT_MAILBOX
) - 2);
310 Verify Mailbox checksum.
312 If checksum error, print debug message and run init dead loop.
314 @param[in] Mailbox Debug Agent Mailbox pointer.
318 VerifyMailboxChecksum (
319 IN DEBUG_AGENT_MAILBOX
*Mailbox
324 CheckSum
= CalculateCheckSum8 ((UINT8
*) Mailbox
, sizeof (DEBUG_AGENT_MAILBOX
) - 2);
326 // The checksum updating process may be disturbed by hardware SMI, we need to check CheckSum field
327 // and ToBeCheckSum field to validate the mail box.
329 if (CheckSum
!= Mailbox
->CheckSum
&& CheckSum
!= Mailbox
->ToBeCheckSum
) {
330 DEBUG ((EFI_D_ERROR
, "DebugAgent: Mailbox checksum error, stack or heap crashed!\n"));
331 DEBUG ((EFI_D_ERROR
, "DebugAgent: CheckSum = %x, Mailbox->CheckSum = %x, Mailbox->ToBeCheckSum = %x\n", CheckSum
, Mailbox
->CheckSum
, Mailbox
->ToBeCheckSum
));
337 Update Mailbox content by index.
339 @param[in] Mailbox Debug Agent Mailbox pointer.
340 @param[in] Index Mailbox content index.
341 @param[in] Value Value to be set into Mailbox.
345 UpdateMailboxContent (
346 IN DEBUG_AGENT_MAILBOX
*Mailbox
,
351 AcquireMpSpinLock (&mDebugMpContext
.MailboxSpinLock
);
353 case DEBUG_MAILBOX_DEBUG_FLAG_INDEX
:
354 Mailbox
->ToBeCheckSum
= Mailbox
->CheckSum
+ CalculateSum8 ((UINT8
*)&Mailbox
->DebugFlag
.Uint64
, sizeof(UINT64
))
355 - CalculateSum8 ((UINT8
*)&Value
, sizeof(UINT64
));
356 Mailbox
->DebugFlag
.Uint64
= Value
;
358 case DEBUG_MAILBOX_DEBUG_PORT_HANDLE_INDEX
:
359 Mailbox
->ToBeCheckSum
= Mailbox
->CheckSum
+ CalculateSum8 ((UINT8
*)&Mailbox
->DebugPortHandle
, sizeof(UINTN
))
360 - CalculateSum8 ((UINT8
*)&Value
, sizeof(UINTN
));
361 Mailbox
->DebugPortHandle
= (UINTN
) Value
;
363 case DEBUG_MAILBOX_EXCEPTION_BUFFER_POINTER_INDEX
:
364 Mailbox
->ToBeCheckSum
= Mailbox
->CheckSum
+ CalculateSum8 ((UINT8
*)&Mailbox
->ExceptionBufferPointer
, sizeof(UINTN
))
365 - CalculateSum8 ((UINT8
*)&Value
, sizeof(UINTN
));
366 Mailbox
->ExceptionBufferPointer
= (UINTN
) Value
;
368 case DEBUG_MAILBOX_LAST_ACK
:
369 Mailbox
->ToBeCheckSum
= Mailbox
->CheckSum
+ CalculateSum8 ((UINT8
*)&Mailbox
->LastAck
, sizeof(UINT8
))
370 - CalculateSum8 ((UINT8
*)&Value
, sizeof(UINT8
));
371 Mailbox
->LastAck
= (UINT8
) Value
;
373 case DEBUG_MAILBOX_SEQUENCE_NO_INDEX
:
374 Mailbox
->ToBeCheckSum
= Mailbox
->CheckSum
+ CalculateSum8 ((UINT8
*)&Mailbox
->SequenceNo
, sizeof(UINT8
))
375 - CalculateSum8 ((UINT8
*)&Value
, sizeof(UINT8
));
376 Mailbox
->SequenceNo
= (UINT8
) Value
;
378 case DEBUG_MAILBOX_HOST_SEQUENCE_NO_INDEX
:
379 Mailbox
->ToBeCheckSum
= Mailbox
->CheckSum
+ CalculateSum8 ((UINT8
*)&Mailbox
->HostSequenceNo
, sizeof(UINT8
))
380 - CalculateSum8 ((UINT8
*)&Value
, sizeof(UINT8
));
381 Mailbox
->HostSequenceNo
= (UINT8
) Value
;
384 UpdateMailboxChecksum (Mailbox
);
385 ReleaseMpSpinLock (&mDebugMpContext
.MailboxSpinLock
);
388 Set debug flag in mailbox.
390 @param[in] FlagMask Debug flag mask value.
391 @param[in] FlagValue Debug flag value.
400 DEBUG_AGENT_MAILBOX
*Mailbox
;
403 Mailbox
= GetMailboxPointer ();
404 Data64
= (Mailbox
->DebugFlag
.Uint64
& ~FlagMask
) |
405 (LShiftU64 ((UINT64
)FlagValue
, LowBitSet64 (FlagMask
)) & FlagMask
);
406 UpdateMailboxContent (Mailbox
, DEBUG_MAILBOX_DEBUG_FLAG_INDEX
, Data64
);
410 Get debug flag in mailbox.
412 @param[in] FlagMask Debug flag mask value.
414 @return Debug flag value.
422 DEBUG_AGENT_MAILBOX
*Mailbox
;
425 Mailbox
= GetMailboxPointer ();
426 DebugFlag
= (UINT32
) RShiftU64 (Mailbox
->DebugFlag
.Uint64
& FlagMask
, LowBitSet64 (FlagMask
));
432 Send a debug message packet to the debug port.
434 @param[in] Buffer The debug message.
435 @param[in] Length The length of debug message.
444 DEBUG_PACKET_HEADER DebugHeader
;
445 DEBUG_PORT_HANDLE Handle
;
447 Handle
= GetDebugPortHandle();
449 DebugHeader
.StartSymbol
= DEBUG_STARTING_SYMBOL_NORMAL
;
450 DebugHeader
.Command
= DEBUG_COMMAND_PRINT_MESSAGE
;
451 DebugHeader
.Length
= sizeof (DEBUG_PACKET_HEADER
) + (UINT8
) Length
;
452 DebugHeader
.SequenceNo
= 0xEE;
454 DebugHeader
.Crc
= CalculateCrc16 (
455 (UINT8
*)Buffer
, Length
,
456 CalculateCrc16 ((UINT8
*)&DebugHeader
, sizeof (DEBUG_PACKET_HEADER
), 0)
459 DebugPortWriteBuffer (Handle
, (UINT8
*)&DebugHeader
, sizeof (DEBUG_PACKET_HEADER
));
460 DebugPortWriteBuffer (Handle
, (UINT8
*)Buffer
, Length
);
464 Prints a debug message to the debug port if the specified error level is enabled.
466 If any bit in ErrorLevel is also set in Mainbox, then print the message specified
467 by Format and the associated variable argument list to the debug port.
469 @param[in] ErrorLevel The error level of the debug message.
470 @param[in] Format Format string for the debug message to print.
471 @param[in] ... Variable argument list whose contents are accessed
472 based on the format string specified by Format.
483 CHAR8 Buffer
[DEBUG_DATA_MAXIMUM_REAL_DATA
];
487 // Check driver debug mask value and global mask
489 if ((ErrorLevel
& GetDebugFlag (DEBUG_AGENT_FLAG_PRINT_ERROR_LEVEL
)) == 0) {
494 // Convert the DEBUG() message to an ASCII String
496 VA_START (Marker
, Format
);
497 AsciiVSPrint (Buffer
, sizeof (Buffer
), Format
, Marker
);
500 SendDebugMsgPacket (Buffer
, AsciiStrLen (Buffer
));
504 Prints a debug message to the debug output device if the specified error level is enabled.
506 If any bit in ErrorLevel is also set in DebugPrintErrorLevelLib function
507 GetDebugPrintErrorLevel (), then print the message specified by Format and the
508 associated variable argument list to the debug output device.
510 If Format is NULL, then ASSERT().
512 @param[in] ErrorLevel The error level of the debug message.
513 @param[in] IsSend Flag of debug message to declare that the data is being sent or being received.
514 @param[in] Data Variable argument list whose contents are accessed
515 @param[in] Length based on the format string specified by Format.
520 DebugAgentDataMsgPrint (
527 CHAR8 Buffer
[DEBUG_DATA_MAXIMUM_REAL_DATA
];
532 // Check driver debug mask value and global mask
534 if ((ErrorLevel
& GetDebugFlag (DEBUG_AGENT_FLAG_PRINT_ERROR_LEVEL
)) == 0) {
540 DestBuffer
+= AsciiSPrint (DestBuffer
, DEBUG_DATA_MAXIMUM_REAL_DATA
, "Sent data [ ");
542 DestBuffer
+= AsciiSPrint (DestBuffer
, DEBUG_DATA_MAXIMUM_REAL_DATA
, "Received data [ ");
547 if (DestBuffer
- Buffer
> DEBUG_DATA_MAXIMUM_REAL_DATA
- 6) {
549 // If there was no enough space in buffer, send out the debug message,
550 // reserving 6 bytes is for the last data and end characters "]\n".
552 SendDebugMsgPacket (Buffer
, DestBuffer
- Buffer
);
555 DestBuffer
+= AsciiSPrint (DestBuffer
, DEBUG_DATA_MAXIMUM_REAL_DATA
- (DestBuffer
- Buffer
), "%02x ", Data
[Index
]);
557 if (Index
>= Length
) {
559 // The last character of debug message has been foramtted in buffer
561 DestBuffer
+= AsciiSPrint(DestBuffer
, DEBUG_DATA_MAXIMUM_REAL_DATA
- (DestBuffer
- Buffer
), "]\n");
562 SendDebugMsgPacket (Buffer
, DestBuffer
- Buffer
);
569 Read remaing debug packet except for the start symbol
571 @param[in] Handle Pointer to Debug Port handle.
572 @param[in, out] DebugHeader Debug header buffer including start symbol.
574 @retval EFI_SUCCESS Read the symbol in BreakSymbol.
575 @retval EFI_CRC_ERROR CRC check fail.
576 @retval EFI_TIMEOUT Timeout occurs when reading debug packet.
577 @retval EFI_DEVICE_ERROR Receive the old or responsed packet.
581 ReadRemainingBreakPacket (
582 IN DEBUG_PORT_HANDLE Handle
,
583 IN OUT DEBUG_PACKET_HEADER
*DebugHeader
587 DEBUG_AGENT_MAILBOX
*Mailbox
;
590 // Has received start symbol, try to read the rest part
592 if (DebugPortReadBuffer (Handle
, (UINT8
*)DebugHeader
+ OFFSET_OF (DEBUG_PACKET_HEADER
, Command
), sizeof (DEBUG_PACKET_HEADER
) - OFFSET_OF (DEBUG_PACKET_HEADER
, Command
), READ_PACKET_TIMEOUT
) == 0) {
594 // Timeout occur, exit
596 DebugAgentMsgPrint (DEBUG_AGENT_WARNING
, "Timeout in Debug Timer interrupt\n");
600 Crc
= DebugHeader
->Crc
;
601 DebugHeader
->Crc
= 0;
602 if (CalculateCrc16 ((UINT8
*)DebugHeader
, DebugHeader
->Length
, 0) != Crc
) {
603 DebugAgentMsgPrint (DEBUG_AGENT_WARNING
, "Debug Timer CRC (%x) against (%x)\n", Crc
, CalculateCrc16 ((UINT8
*) &DebugHeader
, DebugHeader
->Length
, 0));
604 DebugAgentDataMsgPrint (DEBUG_AGENT_VERBOSE
, FALSE
, (UINT8
*)DebugHeader
, DebugHeader
->Length
);
605 return EFI_CRC_ERROR
;
607 Mailbox
= GetMailboxPointer();
608 if (IS_REQUEST (DebugHeader
)) {
609 if (DebugHeader
->SequenceNo
== (UINT8
) (Mailbox
->HostSequenceNo
+ 1)) {
611 // Only updagte HostSequenceNo for new command packet
613 UpdateMailboxContent (Mailbox
, DEBUG_MAILBOX_HOST_SEQUENCE_NO_INDEX
, DebugHeader
->SequenceNo
);
616 if (DebugHeader
->SequenceNo
== Mailbox
->HostSequenceNo
) {
621 return EFI_DEVICE_ERROR
;
625 Check if HOST is attached based on Mailbox.
627 @retval TRUE HOST is attached.
628 @retval FALSE HOST is not attached.
636 return (BOOLEAN
) (GetDebugFlag (DEBUG_AGENT_FLAG_HOST_ATTACHED
) == 1);
640 Set HOST connect flag in Mailbox.
642 @param[in] Attached Attach status.
650 DebugAgentMsgPrint (DEBUG_AGENT_INFO
, "Attach status is %d\n", Attached
);
651 SetDebugFlag (DEBUG_AGENT_FLAG_HOST_ATTACHED
, (UINT32
)Attached
);
655 Set debug setting of Debug Agent in Mailbox.
657 @param DebugSetting Pointer to Debug Setting defined by transfer protocol.
659 @retval RETURN_SUCCESS The setting is set successfully.
660 @retval RETURN_UNSUPPORTED The Key value is not supported.
665 IN DEBUG_DATA_SET_DEBUG_SETTING
*DebugSetting
668 RETURN_STATUS Status
;
670 Status
= RETURN_SUCCESS
;
671 switch (DebugSetting
->Key
) {
672 case DEBUG_AGENT_SETTING_SMM_ENTRY_BREAK
:
673 SetDebugFlag (DEBUG_AGENT_FLAG_BREAK_ON_NEXT_SMI
, DebugSetting
->Value
);
675 case DEBUG_AGENT_SETTING_PRINT_ERROR_LEVEL
:
676 SetDebugFlag (DEBUG_AGENT_FLAG_PRINT_ERROR_LEVEL
, DebugSetting
->Value
);
678 case DEBUG_AGENT_SETTING_BOOT_SCRIPT_ENTRY_BREAK
:
679 SetDebugFlag (DEBUG_AGENT_FLAG_BREAK_BOOT_SCRIPT
, DebugSetting
->Value
);
682 Status
= RETURN_UNSUPPORTED
;
690 @param[in] CpuContext Pointer to saved CPU context.
695 IN DEBUG_CPU_CONTEXT
*CpuContext
698 IA32_EFLAGS32
*Eflags
;
700 Eflags
= (IA32_EFLAGS32
*) &CpuContext
->Eflags
;
706 Exectue Stepping command.
708 @param[in] CpuContext Pointer to saved CPU context.
713 IN DEBUG_CPU_CONTEXT
*CpuContext
716 IA32_EFLAGS32
*Eflags
;
718 Eflags
= (IA32_EFLAGS32
*) &CpuContext
->Eflags
;
724 Set debug register for hardware breakpoint.
726 @param[in] CpuContext Pointer to saved CPU context.
727 @param[in] SetHwBreakpoint Hardware breakpoint to be set.
732 IN DEBUG_CPU_CONTEXT
*CpuContext
,
733 IN DEBUG_DATA_SET_HW_BREAKPOINT
*SetHwBreakpoint
739 RegisterIndex
= SetHwBreakpoint
->Type
.Index
;
744 * ((UINTN
*) &CpuContext
->Dr0
+ RegisterIndex
) = (UINTN
) SetHwBreakpoint
->Address
;
746 Dr7Value
= CpuContext
->Dr7
;
751 Dr7Value
|= (UINTN
) (0x3 << (RegisterIndex
* 2));
755 Dr7Value
&= (UINTN
) (~(0xf << (16 + RegisterIndex
* 4)));
756 Dr7Value
|= (UINTN
) ((SetHwBreakpoint
->Type
.Length
<< 2) | SetHwBreakpoint
->Type
.Access
) << (16 + RegisterIndex
* 4);
762 CpuContext
->Dr7
= Dr7Value
;
766 Clear debug register for hardware breakpoint.
768 @param[in] CpuContext Pointer to saved CPU context.
769 @param[in] ClearHwBreakpoint Hardware breakpoint to be cleared.
774 IN DEBUG_CPU_CONTEXT
*CpuContext
,
775 IN DEBUG_DATA_CLEAR_HW_BREAKPOINT
*ClearHwBreakpoint
778 if ((ClearHwBreakpoint
->IndexMask
& BIT0
) != 0) {
780 CpuContext
->Dr7
&= (UINTN
)(~(0x3 << 0));
782 if ((ClearHwBreakpoint
->IndexMask
& BIT1
) != 0) {
784 CpuContext
->Dr7
&= (UINTN
)(~(0x3 << 2));
786 if ((ClearHwBreakpoint
->IndexMask
& BIT2
) != 0) {
788 CpuContext
->Dr7
&= (UINTN
)(~(0x3 << 4));
790 if ((ClearHwBreakpoint
->IndexMask
& BIT3
) != 0) {
792 CpuContext
->Dr7
&= (UINTN
)(~(0x3 << 6));
798 Return the offset of FP / MMX / XMM registers in the FPU saved state by register index.
800 @param[in] Index Register index.
801 @param[out] Width Register width returned.
803 @return Offset in the FPU Save State.
807 ArchReadFxStatOffset (
812 if (Index
< SOFT_DEBUGGER_REGISTER_ST0
) {
814 case SOFT_DEBUGGER_REGISTER_FP_FCW
:
815 *Width
= (UINT8
) sizeof (UINT16
);
816 return OFFSET_OF(DEBUG_DATA_FX_SAVE_STATE
, Fcw
);
818 case SOFT_DEBUGGER_REGISTER_FP_FSW
:
819 *Width
= (UINT8
) sizeof (UINT16
);
820 return OFFSET_OF(DEBUG_DATA_FX_SAVE_STATE
, Fsw
);
822 case SOFT_DEBUGGER_REGISTER_FP_FTW
:
823 *Width
= (UINT8
) sizeof (UINT16
);
824 return OFFSET_OF(DEBUG_DATA_FX_SAVE_STATE
, Ftw
);
826 case SOFT_DEBUGGER_REGISTER_FP_OPCODE
:
827 *Width
= (UINT8
) sizeof (UINT16
);
828 return OFFSET_OF(DEBUG_DATA_FX_SAVE_STATE
, Opcode
);
830 case SOFT_DEBUGGER_REGISTER_FP_EIP
:
831 *Width
= (UINT8
) sizeof (UINT32
);
832 return OFFSET_OF(DEBUG_DATA_FX_SAVE_STATE
, Eip
);
834 case SOFT_DEBUGGER_REGISTER_FP_CS
:
835 *Width
= (UINT8
) sizeof (UINT16
);
836 return OFFSET_OF(DEBUG_DATA_FX_SAVE_STATE
, Cs
);
838 case SOFT_DEBUGGER_REGISTER_FP_DATAOFFSET
:
839 *Width
= (UINT8
) sizeof (UINT32
);
840 return OFFSET_OF(DEBUG_DATA_FX_SAVE_STATE
, DataOffset
);
842 case SOFT_DEBUGGER_REGISTER_FP_DS
:
843 *Width
= (UINT8
) sizeof (UINT16
);
844 return OFFSET_OF(DEBUG_DATA_FX_SAVE_STATE
, Ds
);
846 case SOFT_DEBUGGER_REGISTER_FP_MXCSR
:
847 *Width
= (UINT8
) sizeof (UINT32
);
848 return OFFSET_OF(DEBUG_DATA_FX_SAVE_STATE
, Mxcsr
);
850 case SOFT_DEBUGGER_REGISTER_FP_MXCSR_MASK
:
851 *Width
= (UINT8
) sizeof (UINT32
);
852 return OFFSET_OF(DEBUG_DATA_FX_SAVE_STATE
, Mxcsr_Mask
);
856 if (Index
<= SOFT_DEBUGGER_REGISTER_ST7
) {
858 } else if (Index
<= SOFT_DEBUGGER_REGISTER_XMM15
) {
865 Index
-= SOFT_DEBUGGER_REGISTER_MM0
- SOFT_DEBUGGER_REGISTER_ST0
;
868 return OFFSET_OF (DEBUG_DATA_FX_SAVE_STATE
, St0Mm0
) + (Index
- SOFT_DEBUGGER_REGISTER_ST0
) * 16;
872 Return the pointer of the register value in the CPU saved context.
874 @param[in] CpuContext Pointer to saved CPU context.
875 @param[in] Index Register index value.
876 @param[out] Width Data width to read.
878 @return The pointer in the CPU saved context.
882 ArchReadRegisterBuffer (
883 IN DEBUG_CPU_CONTEXT
*CpuContext
,
890 if (Index
< SOFT_DEBUGGER_REGISTER_FP_BASE
) {
891 Buffer
= (UINT8
*) CpuContext
+ OFFSET_OF (DEBUG_CPU_CONTEXT
, Dr0
) + Index
* sizeof (UINTN
);
892 *Width
= (UINT8
) sizeof (UINTN
);
895 // FPU/MMX/XMM registers
897 Buffer
= (UINT8
*) CpuContext
+ OFFSET_OF (DEBUG_CPU_CONTEXT
, FxSaveState
) + ArchReadFxStatOffset (Index
, Width
);
904 Send the packet without data to HOST.
906 @param[in] CommandType Type of Command.
907 @param[in] SequenceNo Sequence number.
911 SendPacketWithoutData (
912 IN UINT8 CommandType
,
916 DEBUG_PACKET_HEADER DebugHeader
;
917 DEBUG_PORT_HANDLE Handle
;
919 Handle
= GetDebugPortHandle();
921 DebugHeader
.StartSymbol
= DEBUG_STARTING_SYMBOL_NORMAL
;
922 DebugHeader
.Command
= CommandType
;
923 DebugHeader
.Length
= sizeof (DEBUG_PACKET_HEADER
);
924 DebugHeader
.SequenceNo
= SequenceNo
;
926 DebugHeader
.Crc
= CalculateCrc16 ((UINT8
*)&DebugHeader
, sizeof (DEBUG_PACKET_HEADER
), 0);
928 DebugAgentDataMsgPrint (DEBUG_AGENT_VERBOSE
, TRUE
, (UINT8
*) &DebugHeader
, DebugHeader
.Length
);
929 DebugPortWriteBuffer (Handle
, (UINT8
*) &DebugHeader
, DebugHeader
.Length
);
933 Send acknowledge packet to HOST.
935 @param[in] AckCommand Type of Acknowledge packet.
944 DEBUG_AGENT_MAILBOX
*Mailbox
;
946 if (AckCommand
!= DEBUG_COMMAND_OK
) {
948 // This is not ACK OK packet
950 DebugAgentMsgPrint (DEBUG_AGENT_ERROR
, "Send ACK(%d)\n", AckCommand
);
952 Mailbox
= GetMailboxPointer();
953 SequenceNo
= Mailbox
->HostSequenceNo
;
954 DebugAgentMsgPrint (DEBUG_AGENT_INFO
, "SendAckPacket: SequenceNo = %x\n", SequenceNo
);
955 SendPacketWithoutData (AckCommand
, SequenceNo
);
956 UpdateMailboxContent (Mailbox
, DEBUG_MAILBOX_LAST_ACK
, AckCommand
);
960 Receive valid packet from HOST.
962 @param[out] InputPacket Buffer to receive packet.
963 @param[out] BreakReceived TRUE means break-in symbol received.
964 FALSE means break-in symbol not received.
965 @param[out] IncompatibilityFlag If IncompatibilityFlag is not NULL, return
966 TRUE: Compatible packet received.
967 FALSE: Incompatible packet received.
968 @param[in] Timeout Time out value to wait for acknowlege from HOST.
969 The unit is microsecond.
970 @param[in] SkipStartSymbol TRUE: Skip time out when reading start symbol.
971 FALSE: Does not Skip time out when reading start symbol.
973 @retval RETURN_SUCCESS A valid package was reveived in InputPacket.
974 @retval RETURN_TIMEOUT Timeout occurs.
979 OUT UINT8
*InputPacket
,
980 OUT BOOLEAN
*BreakReceived
,
981 OUT BOOLEAN
*IncompatibilityFlag
, OPTIONAL
983 IN BOOLEAN SkipStartSymbol
986 DEBUG_PACKET_HEADER
*DebugHeader
;
988 DEBUG_PORT_HANDLE Handle
;
990 UINTN TimeoutForStartSymbol
;
992 Handle
= GetDebugPortHandle();
993 if (SkipStartSymbol
) {
994 TimeoutForStartSymbol
= 0;
996 TimeoutForStartSymbol
= Timeout
;
999 DebugHeader
= (DEBUG_PACKET_HEADER
*) InputPacket
;
1002 // Find the valid start symbol
1004 Received
= DebugPortReadBuffer (Handle
, &DebugHeader
->StartSymbol
, sizeof (DebugHeader
->StartSymbol
), TimeoutForStartSymbol
);
1005 if (Received
< sizeof (DebugHeader
->StartSymbol
)) {
1006 DebugAgentMsgPrint (DEBUG_AGENT_WARNING
, "DebugPortReadBuffer(StartSymbol) timeout\n");
1007 return RETURN_TIMEOUT
;
1010 if (DebugHeader
->StartSymbol
!= DEBUG_STARTING_SYMBOL_NORMAL
) {
1011 DebugAgentMsgPrint (DEBUG_AGENT_WARNING
, "Invalid start symbol received [%02x]\n", DebugHeader
->StartSymbol
);
1016 // Read Package header till field Length
1018 Received
= DebugPortReadBuffer (
1020 (UINT8
*)DebugHeader
+ OFFSET_OF (DEBUG_PACKET_HEADER
, Command
),
1021 OFFSET_OF (DEBUG_PACKET_HEADER
, Length
) + sizeof (DebugHeader
->Length
) - sizeof (DebugHeader
->StartSymbol
),
1024 if (Received
== 0) {
1025 DebugAgentMsgPrint (DEBUG_AGENT_ERROR
, "DebugPortReadBuffer(Command) timeout\n");
1026 return RETURN_TIMEOUT
;
1028 if (DebugHeader
->Length
< sizeof (DEBUG_PACKET_HEADER
)) {
1029 if (IncompatibilityFlag
!= NULL
) {
1031 // This is one old version debug packet format, set Incompatibility flag
1033 *IncompatibilityFlag
= TRUE
;
1036 // Skip the bad small packet
1042 // Read the payload data include the CRC field
1044 Received
= DebugPortReadBuffer (Handle
, &DebugHeader
->SequenceNo
, (UINT8
) (DebugHeader
->Length
- OFFSET_OF (DEBUG_PACKET_HEADER
, SequenceNo
)), Timeout
);
1045 if (Received
== 0) {
1046 DebugAgentMsgPrint (DEBUG_AGENT_ERROR
, "DebugPortReadBuffer(SequenceNo) timeout\n");
1047 return RETURN_TIMEOUT
;
1050 // Calculate the CRC of Debug Packet
1052 Crc
= DebugHeader
->Crc
;
1053 DebugHeader
->Crc
= 0;
1054 if (Crc
== CalculateCrc16 ((UINT8
*) DebugHeader
, DebugHeader
->Length
, 0)) {
1057 DebugAgentMsgPrint (DEBUG_AGENT_WARNING
, "CRC Error (received CRC is %x)\n", Crc
);
1058 DebugAgentDataMsgPrint (DEBUG_AGENT_VERBOSE
, FALSE
, (UINT8
*) DebugHeader
, DebugHeader
->Length
);
1062 DebugAgentDataMsgPrint (DEBUG_AGENT_VERBOSE
, FALSE
, (UINT8
*) DebugHeader
, DebugHeader
->Length
);
1064 return RETURN_SUCCESS
;
1068 Receive acknowledge packet OK from HOST in specified time.
1070 @param[in] Command The command type issued by TARGET.
1071 @param[in] Timeout Time out value to wait for acknowlege from HOST.
1072 The unit is microsecond.
1073 @param[out] BreakReceived If BreakReceived is not NULL,
1074 TRUE is retured if break-in symbol received.
1075 FALSE is retured if break-in symbol not received.
1076 @param[out] IncompatibilityFlag If IncompatibilityFlag is not NULL, return
1077 TRUE: Compatible packet received.
1078 FALSE: Incompatible packet received.
1080 @retval RETRUEN_SUCCESS Succeed to receive acknowlege packet from HOST,
1081 the type of acknowlege packet saved in Ack.
1082 @retval RETURN_TIMEOUT Specified timeout value was up.
1086 SendCommandAndWaitForAckOK (
1089 OUT BOOLEAN
*BreakReceived
, OPTIONAL
1090 OUT BOOLEAN
*IncompatibilityFlag OPTIONAL
1093 RETURN_STATUS Status
;
1094 UINT8 InputPacketBuffer
[DEBUG_DATA_UPPER_LIMIT
];
1095 DEBUG_PACKET_HEADER
*DebugHeader
;
1097 UINT8 HostSequenceNo
;
1101 DebugHeader
= (DEBUG_PACKET_HEADER
*) InputPacketBuffer
;
1102 Status
= RETURN_TIMEOUT
;
1103 while (RetryCount
> 0) {
1104 SequenceNo
= GetMailboxPointer()->SequenceNo
;
1105 HostSequenceNo
= GetMailboxPointer()->HostSequenceNo
;
1106 SendPacketWithoutData (Command
, SequenceNo
);
1107 Status
= ReceivePacket ((UINT8
*) DebugHeader
, BreakReceived
, IncompatibilityFlag
, Timeout
, FALSE
);
1108 if (Status
== RETURN_TIMEOUT
) {
1109 if (Command
== DEBUG_COMMAND_INIT_BREAK
) {
1112 DebugAgentMsgPrint (DEBUG_AGENT_WARNING
, "TARGET: Timeout when waiting for ACK packet.\n");
1116 ASSERT_EFI_ERROR (Status
);
1118 // Status == RETURN_SUCCESS
1120 if (DebugHeader
->Command
== DEBUG_COMMAND_OK
&& DebugHeader
->SequenceNo
== SequenceNo
) {
1124 UpdateMailboxContent (GetMailboxPointer(), DEBUG_MAILBOX_SEQUENCE_NO_INDEX
, ++SequenceNo
);
1127 if (DebugHeader
->Command
== DEBUG_COMMAND_GO
&& (DebugHeader
->SequenceNo
== HostSequenceNo
|| Command
== DEBUG_COMMAND_INIT_BREAK
)) {
1131 if (Command
== DEBUG_COMMAND_INIT_BREAK
) {
1132 DebugAgentMsgPrint (DEBUG_AGENT_WARNING
, "TARGET: Receive GO() in last boot\n");
1134 SendPacketWithoutData (DEBUG_COMMAND_OK
, DebugHeader
->SequenceNo
);
1138 ASSERT (Command
== DEBUG_COMMAND_INIT_BREAK
);
1143 Get current break cause.
1145 @param[in] Vector Vector value of exception or interrupt.
1146 @param[in] CpuContext Pointer to save CPU context.
1148 @return The type of break cause defined by XXXX
1154 IN DEBUG_CPU_CONTEXT
*CpuContext
1159 Cause
= DEBUG_DATA_BREAK_CAUSE_UNKNOWN
;
1162 case DEBUG_INT1_VECTOR
:
1163 case DEBUG_INT3_VECTOR
:
1165 if (Vector
== DEBUG_INT1_VECTOR
) {
1169 if ((CpuContext
->Dr6
& BIT14
) != 0) {
1170 Cause
= DEBUG_DATA_BREAK_CAUSE_STEPPING
;
1172 // If it's single step, no need to check DR0, to ensure single step work in PeCoffExtraActionLib
1173 // (right after triggering a breakpoint to report image load/unload).
1178 Cause
= DEBUG_DATA_BREAK_CAUSE_HW_BREAKPOINT
;
1184 Cause
= DEBUG_DATA_BREAK_CAUSE_SW_BREAKPOINT
;
1187 switch (CpuContext
->Dr0
) {
1188 case IMAGE_LOAD_SIGNATURE
:
1189 case IMAGE_UNLOAD_SIGNATURE
:
1191 if (CpuContext
->Dr3
== IO_PORT_BREAKPOINT_ADDRESS
) {
1193 Cause
= (UINT8
) ((CpuContext
->Dr0
== IMAGE_LOAD_SIGNATURE
) ?
1194 DEBUG_DATA_BREAK_CAUSE_IMAGE_LOAD
: DEBUG_DATA_BREAK_CAUSE_IMAGE_UNLOAD
);
1198 case SOFT_INTERRUPT_SIGNATURE
:
1200 if (CpuContext
->Dr1
== MEMORY_READY_SIGNATURE
) {
1201 Cause
= DEBUG_DATA_BREAK_CAUSE_MEMORY_READY
;
1202 CpuContext
->Dr0
= 0;
1203 } else if (CpuContext
->Dr1
== SYSTEM_RESET_SIGNATURE
) {
1204 Cause
= DEBUG_DATA_BREAK_CAUSE_SYSTEM_RESET
;
1205 CpuContext
->Dr0
= 0;
1216 case DEBUG_TIMER_VECTOR
:
1217 Cause
= DEBUG_DATA_BREAK_CAUSE_USER_HALT
;
1222 if (GetDebugFlag (DEBUG_AGENT_FLAG_STEPPING
) == 1) {
1224 // If stepping command is executing
1226 Cause
= DEBUG_DATA_BREAK_CAUSE_STEPPING
;
1228 Cause
= DEBUG_DATA_BREAK_CAUSE_EXCEPTION
;
1238 Copy memory from source to destination with specified width.
1240 @param[out] Dest A pointer to the destination buffer of the memory copy.
1241 @param[in] Src A pointer to the source buffer of the memory copy.
1242 @param[in] Count The number of data with specified width to copy from source to destination.
1243 @param[in] Width Data width in byte.
1264 // Copy memory from tail to avoid memory overlap
1266 Destination
= Dest
+ (Count
- 1) * Width
;
1267 Source
= Src
+ (Count
- 1) * Width
;
1271 while (Count
-- != 0) {
1274 *(UINT8
*) Destination
= MmioRead8 ((UINTN
) Source
);
1277 *(UINT16
*) Destination
= MmioRead16 ((UINTN
) Source
);
1280 *(UINT32
*) Destination
= MmioRead32 ((UINTN
) Source
);
1283 *(UINT64
*) Destination
= MmioRead64 ((UINTN
) Source
);
1289 Destination
+= Step
;
1294 Read memory with speicifed width and send packet with response data to HOST.
1296 @param[in] Data Pointer to response data buffer.
1297 @param[in] Count The number of data with specified Width.
1298 @param[in] Width Data width in byte.
1300 @retval RETURN_SUCCESS Response data was sent successfully.
1304 ReadMemoryAndSendResponsePacket (
1310 RETURN_STATUS Status
;
1311 DEBUG_PACKET_HEADER
*DebugHeader
;
1313 DEBUG_PACKET_HEADER
*AckDebugHeader
;
1314 UINT8 DebugPacket
[DEBUG_DATA_UPPER_LIMIT
+ sizeof (UINT64
) - 1];
1315 UINT8 InputPacketBuffer
[DEBUG_DATA_UPPER_LIMIT
];
1316 DEBUG_PORT_HANDLE Handle
;
1318 UINTN RemainingDataSize
;
1319 UINTN CurrentDataSize
;
1321 Handle
= GetDebugPortHandle();
1324 // Data is appended end of Debug Packet header, make sure data address
1325 // in Debug Packet 8-byte alignment always
1327 DebugHeader
= (DEBUG_PACKET_HEADER
*) (ALIGN_VALUE ((UINTN
)&DebugPacket
+ sizeof (DEBUG_PACKET_HEADER
), sizeof (UINT64
))
1328 - sizeof (DEBUG_PACKET_HEADER
));
1329 DebugHeader
->StartSymbol
= DEBUG_STARTING_SYMBOL_NORMAL
;
1331 RemainingDataSize
= Count
* Width
;
1333 SequenceNo
= GetMailboxPointer()->HostSequenceNo
;
1334 if (RemainingDataSize
<= DEBUG_DATA_MAXIMUM_REAL_DATA
) {
1336 // If the remaining data is less one real packet size, this is the last data packet
1338 CurrentDataSize
= RemainingDataSize
;
1340 DebugHeader
->Command
= DEBUG_COMMAND_OK
;
1343 // Data is too larger to be sent in one packet, calculate the actual data size could
1344 // be sent in one Maximum data packet
1346 CurrentDataSize
= (DEBUG_DATA_MAXIMUM_REAL_DATA
/ Width
) * Width
;
1348 DebugHeader
->Command
= DEBUG_COMMAND_IN_PROGRESS
;
1351 // Construct the rest Debug header
1353 DebugHeader
->Length
= (UINT8
)(CurrentDataSize
+ sizeof (DEBUG_PACKET_HEADER
));
1354 DebugHeader
->SequenceNo
= SequenceNo
;
1355 DebugHeader
->Crc
= 0;
1356 CopyMemByWidth ((UINT8
*)(DebugHeader
+ 1), Data
, (UINT16
) CurrentDataSize
/ Width
, Width
);
1358 // Calculate and fill the checksum, DebugHeader->Crc should be 0 before invoking CalculateCrc16 ()
1360 DebugHeader
->Crc
= CalculateCrc16 ((UINT8
*) DebugHeader
, DebugHeader
->Length
, 0);
1362 DebugAgentDataMsgPrint (DEBUG_AGENT_VERBOSE
, TRUE
, (UINT8
*) DebugHeader
, DebugHeader
->Length
);
1364 DebugPortWriteBuffer (Handle
, (UINT8
*) DebugHeader
, DebugHeader
->Length
);
1367 Status
= ReceivePacket (InputPacketBuffer
, NULL
, NULL
, READ_PACKET_TIMEOUT
, FALSE
);
1368 if (Status
== RETURN_TIMEOUT
) {
1369 DebugAgentMsgPrint (DEBUG_AGENT_WARNING
, "TARGET: Timeout in SendDataResponsePacket()\n");
1372 AckDebugHeader
= (DEBUG_PACKET_HEADER
*) InputPacketBuffer
;
1373 SequenceNo
= AckDebugHeader
->SequenceNo
;
1374 if (AckDebugHeader
->Command
== DEBUG_COMMAND_OK
&&
1375 SequenceNo
== DebugHeader
->SequenceNo
&&
1378 // If this is the last packet, return RETURN_SUCCESS.
1380 return RETURN_SUCCESS
;
1382 if ((SequenceNo
== (UINT8
) (DebugHeader
->SequenceNo
+ 1)) && (AckDebugHeader
->Command
== DEBUG_COMMAND_CONTINUE
)) {
1384 // Calculate the rest data size
1386 Data
+= CurrentDataSize
;
1387 RemainingDataSize
-= CurrentDataSize
;
1388 UpdateMailboxContent (GetMailboxPointer(), DEBUG_MAILBOX_HOST_SEQUENCE_NO_INDEX
, (UINT8
) SequenceNo
);
1391 if (SequenceNo
>= DebugHeader
->SequenceNo
) {
1392 DebugAgentMsgPrint (DEBUG_AGENT_WARNING
, "TARGET: Received one old or new command(SequenceNo is %x, last SequenceNo is %x)\n", SequenceNo
, DebugHeader
->SequenceNo
);
1400 Send packet with response data to HOST.
1402 @param[in] Data Pointer to response data buffer.
1403 @param[in] DataSize Size of response data in byte.
1405 @retval RETURN_SUCCESS Response data was sent successfully.
1409 SendDataResponsePacket (
1414 return ReadMemoryAndSendResponsePacket (Data
, DataSize
, 1);
1418 Send break cause packet to HOST.
1420 @param[in] Vector Vector value of exception or interrutp.
1421 @param[in] CpuContext Pointer to save CPU context.
1423 @retval RETURN_SUCCESS Response data was sent successfully.
1424 @retval RETURN_DEVICE_ERROR Cannot receive DEBUG_COMMAND_OK from HOST.
1428 SendBreakCausePacket (
1430 IN DEBUG_CPU_CONTEXT
*CpuContext
1433 DEBUG_DATA_RESPONSE_BREAK_CAUSE DebugDataBreakCause
;
1435 DebugDataBreakCause
.StopAddress
= CpuContext
->Eip
;
1436 DebugDataBreakCause
.Cause
= GetBreakCause (Vector
, CpuContext
);
1438 return SendDataResponsePacket ((UINT8
*) &DebugDataBreakCause
, (UINT16
) sizeof (DEBUG_DATA_RESPONSE_BREAK_CAUSE
));
1442 Try to attach the HOST.
1444 Send init break packet to HOST:
1445 If no acknowlege received in specified Timeout, return RETURN_TIMEOUT.
1446 If received acknowlege, check the revision of HOST.
1447 Set Attach Flag if attach successfully.
1449 @param[in] BreakCause Break cause of this break event.
1450 @param[in] Timeout Time out value to wait for acknowlege from HOST.
1451 The unit is microsecond.
1452 @param[out] BreakReceived If BreakReceived is not NULL,
1453 TRUE is retured if break-in symbol received.
1454 FALSE is retured if break-in symbol not received.
1458 IN UINT8 BreakCause
,
1460 OUT BOOLEAN
*BreakReceived
1463 RETURN_STATUS Status
;
1464 DEBUG_PORT_HANDLE Handle
;
1465 BOOLEAN IncompatibilityFlag
;
1467 IncompatibilityFlag
= FALSE
;
1468 Handle
= GetDebugPortHandle();
1471 // Send init break and wait ack in Timeout
1473 DebugPortWriteBuffer (Handle
, (UINT8
*) mErrorMsgSendInitPacket
, AsciiStrLen (mErrorMsgSendInitPacket
));
1474 if (BreakCause
== DEBUG_DATA_BREAK_CAUSE_SYSTEM_RESET
) {
1475 Status
= SendCommandAndWaitForAckOK (DEBUG_COMMAND_INIT_BREAK
, Timeout
, BreakReceived
, &IncompatibilityFlag
);
1477 Status
= SendCommandAndWaitForAckOK (DEBUG_COMMAND_ATTACH_BREAK
, Timeout
, BreakReceived
, &IncompatibilityFlag
);
1479 if (IncompatibilityFlag
) {
1481 // If the incompatible Debug Packet received, the HOST should be running transfer protocol before DEBUG_AGENT_REVISION.
1482 // It could be UDK Debugger for Windows v1.1/v1.2 or for Linux v0.8/v1.2.
1484 DebugPortWriteBuffer (Handle
, (UINT8
*) mErrorMsgVersionAlert
, AsciiStrLen (mErrorMsgVersionAlert
));
1488 if (RETURN_ERROR (Status
)) {
1489 DebugPortWriteBuffer (Handle
, (UINT8
*) mErrorMsgConnectFail
, AsciiStrLen (mErrorMsgConnectFail
));
1491 DebugPortWriteBuffer (Handle
, (UINT8
*) mErrorMsgConnectOK
, AsciiStrLen (mErrorMsgConnectOK
));
1495 SetHostAttached (TRUE
);
1501 Send Break point packet to HOST.
1503 Only the first breaking processor could sent BREAK_POINT packet.
1505 @param[in] BreakCause Break cause of this break event.
1506 @param[in] ProcessorIndex Processor index value.
1507 @param[out] BreakReceived If BreakReceived is not NULL,
1508 TRUE is retured if break-in symbol received.
1509 FALSE is retured if break-in symbol not received.
1513 SendBreakPacketToHost (
1514 IN UINT8 BreakCause
,
1515 IN UINT32 ProcessorIndex
,
1516 OUT BOOLEAN
*BreakReceived
1519 UINT8 InputCharacter
;
1520 DEBUG_PORT_HANDLE Handle
;
1522 Handle
= GetDebugPortHandle();
1524 if (IsHostAttached ()) {
1525 DebugAgentMsgPrint (DEBUG_AGENT_INFO
, "processor[%x]:Send Break Packet to HOST.\n", ProcessorIndex
);
1526 SendCommandAndWaitForAckOK (DEBUG_COMMAND_BREAK_POINT
, READ_PACKET_TIMEOUT
, BreakReceived
, NULL
);
1528 DebugAgentMsgPrint (DEBUG_AGENT_INFO
, "processor[%x]:Try to attach HOST.\n", ProcessorIndex
);
1530 // If HOST is not attached, try to attach it firstly.
1533 // Poll Attach symbols from HOST and ack OK
1536 DebugPortReadBuffer (Handle
, &InputCharacter
, 1, 0);
1537 } while (InputCharacter
!= DEBUG_STARTING_SYMBOL_ATTACH
);
1538 SendAckPacket (DEBUG_COMMAND_OK
);
1541 // Try to attach HOST
1543 while (AttachHost (BreakCause
, 0, NULL
) != RETURN_SUCCESS
);
1549 The main function to process communication with HOST.
1551 It received the command packet from HOST, and sent response data packet to HOST.
1553 @param[in] Vector Vector value of exception or interrutp.
1554 @param[in, out] CpuContext Pointer to saved CPU context.
1555 @param[in] BreakReceived TRUE means break-in symbol received.
1556 FALSE means break-in symbol not received.
1560 CommandCommunication (
1562 IN OUT DEBUG_CPU_CONTEXT
*CpuContext
,
1563 IN BOOLEAN BreakReceived
1566 RETURN_STATUS Status
;
1567 UINT8 InputPacketBuffer
[DEBUG_DATA_UPPER_LIMIT
+ sizeof (UINT64
) - 1];
1568 DEBUG_PACKET_HEADER
*DebugHeader
;
1573 DEBUG_DATA_READ_MEMORY
*MemoryRead
;
1574 DEBUG_DATA_WRITE_MEMORY
*MemoryWrite
;
1575 DEBUG_DATA_READ_IO
*IoRead
;
1576 DEBUG_DATA_WRITE_IO
*IoWrite
;
1577 DEBUG_DATA_READ_REGISTER
*RegisterRead
;
1578 DEBUG_DATA_WRITE_REGISTER
*RegisterWrite
;
1579 UINT8
*RegisterBuffer
;
1580 DEBUG_DATA_READ_MSR
*MsrRegisterRead
;
1581 DEBUG_DATA_WRITE_MSR
*MsrRegisterWrite
;
1582 DEBUG_DATA_CPUID
*Cpuid
;
1583 DEBUG_DATA_RESPONSE_CPUID CpuidResponse
;
1584 DEBUG_DATA_SEARCH_SIGNATURE
*SearchSignature
;
1585 DEBUG_DATA_RESPONSE_GET_EXCEPTION Exception
;
1586 DEBUG_DATA_RESPONSE_GET_REVISION DebugAgentRevision
;
1587 DEBUG_DATA_SET_VIEWPOINT
*SetViewPoint
;
1588 BOOLEAN HaltDeferred
;
1589 UINT32 ProcessorIndex
;
1590 DEBUG_PORT_HANDLE Handle
;
1591 DEBUG_AGENT_EXCEPTION_BUFFER AgentExceptionBuffer
;
1592 UINT32 IssuedViewPoint
;
1593 DEBUG_AGENT_MAILBOX
*Mailbox
;
1594 UINT8
*AlignedDataPtr
;
1597 IssuedViewPoint
= 0;
1598 HaltDeferred
= BreakReceived
;
1600 if (MultiProcessorDebugSupport()) {
1601 ProcessorIndex
= GetProcessorIndex ();
1602 SetCpuStopFlagByIndex (ProcessorIndex
, TRUE
);
1603 if (mDebugMpContext
.ViewPointIndex
== ProcessorIndex
) {
1605 // Only the current view processor could set AgentInProgress Flag.
1607 IssuedViewPoint
= ProcessorIndex
;
1611 if (IssuedViewPoint
== ProcessorIndex
) {
1613 // Set AgentInProgress Flag.
1615 SetDebugFlag (DEBUG_AGENT_FLAG_AGENT_IN_PROGRESS
, 1);
1618 Handle
= GetDebugPortHandle();
1622 if (MultiProcessorDebugSupport()) {
1624 // Check if the current processor is HOST view point
1626 if (mDebugMpContext
.ViewPointIndex
!= ProcessorIndex
) {
1627 if (mDebugMpContext
.RunCommandSet
) {
1629 // If HOST view point sets RUN flag, run GO command to leave
1631 SetCpuStopFlagByIndex (ProcessorIndex
, FALSE
);
1632 CommandGo (CpuContext
);
1636 // Run into loop again
1644 AcquireMpSpinLock (&mDebugMpContext
.DebugPortSpinLock
);
1646 DebugHeader
=(DEBUG_PACKET_HEADER
*) InputPacketBuffer
;
1648 DebugAgentMsgPrint (DEBUG_AGENT_INFO
, "TARGET: Try to get command from HOST...\n");
1649 Status
= ReceivePacket ((UINT8
*)DebugHeader
, &BreakReceived
, NULL
, READ_PACKET_TIMEOUT
, TRUE
);
1650 if (Status
!= RETURN_SUCCESS
|| !IS_REQUEST (DebugHeader
)) {
1651 DebugAgentMsgPrint (DEBUG_AGENT_WARNING
, "TARGET: Get command[%x] sequenceno[%x] returned status is [%x] \n", DebugHeader
->Command
, DebugHeader
->SequenceNo
, Status
);
1652 DebugAgentMsgPrint (DEBUG_AGENT_WARNING
, "TARGET: Get command failed or it's response packet not expected! \n");
1653 ReleaseMpSpinLock (&mDebugMpContext
.DebugPortSpinLock
);
1657 Mailbox
= GetMailboxPointer ();
1658 if (DebugHeader
->SequenceNo
== Mailbox
->HostSequenceNo
) {
1659 DebugAgentMsgPrint (DEBUG_AGENT_WARNING
, "TARGET: Receive one old command[%x] agaist command[%x]\n", DebugHeader
->SequenceNo
, Mailbox
->HostSequenceNo
);
1660 SendAckPacket (Mailbox
->LastAck
);
1661 ReleaseMpSpinLock (&mDebugMpContext
.DebugPortSpinLock
);
1663 } else if (DebugHeader
->SequenceNo
== (UINT8
) (Mailbox
->HostSequenceNo
+ 1)) {
1664 UpdateMailboxContent (Mailbox
, DEBUG_MAILBOX_HOST_SEQUENCE_NO_INDEX
, (UINT8
) DebugHeader
->SequenceNo
);
1666 DebugAgentMsgPrint (DEBUG_AGENT_WARNING
, "Receive one invalid comamnd[%x] agaist command[%x]\n", DebugHeader
->SequenceNo
, Mailbox
->HostSequenceNo
);
1667 ReleaseMpSpinLock (&mDebugMpContext
.DebugPortSpinLock
);
1672 // Save CPU content before executing HOST commond
1674 UpdateMailboxContent (Mailbox
, DEBUG_MAILBOX_EXCEPTION_BUFFER_POINTER_INDEX
, (UINT64
)(UINTN
) &AgentExceptionBuffer
.JumpBuffer
);
1675 if (SetJump (&AgentExceptionBuffer
.JumpBuffer
) != 0) {
1677 // If HOST command failed, continue to wait for HOST's next command
1678 // If needed, agent could send exception info to HOST.
1680 SendAckPacket (DEBUG_COMMAND_ABORT
);
1681 ReleaseMpSpinLock (&mDebugMpContext
.DebugPortSpinLock
);
1685 DebugAgentMsgPrint (DEBUG_AGENT_INFO
, "Processor[%x]:Received one command(%x)\n", mDebugMpContext
.ViewPointIndex
, DebugHeader
->Command
);
1687 switch (DebugHeader
->Command
) {
1689 case DEBUG_COMMAND_HALT
:
1690 SendAckPacket (DEBUG_COMMAND_HALT_DEFERRED
);
1691 HaltDeferred
= TRUE
;
1692 BreakReceived
= FALSE
;
1693 Status
= RETURN_SUCCESS
;
1696 case DEBUG_COMMAND_RESET
:
1697 SendAckPacket (DEBUG_COMMAND_OK
);
1698 SendAckPacket (DEBUG_COMMAND_OK
);
1699 SendAckPacket (DEBUG_COMMAND_OK
);
1700 ReleaseMpSpinLock (&mDebugMpContext
.DebugPortSpinLock
);
1704 // Assume system resets in 2 seconds, otherwise send TIMEOUT packet.
1705 // PCD can be used if 2 seconds isn't long enough for some platforms.
1707 MicroSecondDelay (2000000);
1708 UpdateMailboxContent (Mailbox
, DEBUG_MAILBOX_HOST_SEQUENCE_NO_INDEX
, Mailbox
->HostSequenceNo
+ 1);
1709 SendAckPacket (DEBUG_COMMAND_TIMEOUT
);
1710 SendAckPacket (DEBUG_COMMAND_TIMEOUT
);
1711 SendAckPacket (DEBUG_COMMAND_TIMEOUT
);
1714 case DEBUG_COMMAND_GO
:
1715 CommandGo (CpuContext
);
1717 // Clear Dr0 to avoid to be recognized as IMAGE_LOAD/_UNLOAD again when hitting a breakpoint after GO
1718 // If HOST changed Dr0 before GO, we will not change Dr0 here
1720 Data8
= GetBreakCause (Vector
, CpuContext
);
1721 if (Data8
== DEBUG_DATA_BREAK_CAUSE_IMAGE_LOAD
|| Data8
== DEBUG_DATA_BREAK_CAUSE_IMAGE_UNLOAD
) {
1722 CpuContext
->Dr0
= 0;
1725 // Clear Stepping Flag
1727 SetDebugFlag (DEBUG_AGENT_FLAG_STEPPING
, 0);
1729 if (!HaltDeferred
) {
1731 // If no HALT command received when being in-active mode
1733 if (MultiProcessorDebugSupport()) {
1734 Data32
= FindNextPendingBreakCpu ();
1737 // If there are still others processors being in break state,
1738 // send OK packet to HOST to finish this go command
1740 SendAckPacket (DEBUG_COMMAND_OK
);
1743 // Set current view to the next breaking processor
1745 mDebugMpContext
.ViewPointIndex
= Data32
;
1746 mDebugMpContext
.BreakAtCpuIndex
= mDebugMpContext
.ViewPointIndex
;
1747 SetCpuBreakFlagByIndex (mDebugMpContext
.ViewPointIndex
, FALSE
);
1749 // Send break packet to HOST to let HOST break again
1751 SendBreakPacketToHost (DEBUG_DATA_BREAK_CAUSE_UNKNOWN
, mDebugMpContext
.BreakAtCpuIndex
, &BreakReceived
);
1753 // Continue to run into loop to read command packet from HOST
1755 ReleaseMpSpinLock (&mDebugMpContext
.DebugPortSpinLock
);
1760 // If no else processor break, set stop bitmask,
1761 // and set Running flag for all processors.
1763 SetCpuStopFlagByIndex (ProcessorIndex
, FALSE
);
1764 SetCpuRunningFlag (TRUE
);
1767 // Wait for all processors are in running state
1770 if (IsAllCpuRunning ()) {
1775 // Set BSP to be current view point.
1777 SetDebugViewPoint (mDebugMpContext
.BspIndex
);
1780 // Clear breaking processor index and running flag
1782 mDebugMpContext
.BreakAtCpuIndex
= (UINT32
) (-1);
1783 SetCpuRunningFlag (FALSE
);
1787 // Send OK packet to HOST to finish this go command
1789 SendAckPacket (DEBUG_COMMAND_OK
);
1791 ReleaseMpSpinLock (&mDebugMpContext
.DebugPortSpinLock
);
1793 if (!IsHostAttached()) {
1794 UpdateMailboxContent (Mailbox
, DEBUG_MAILBOX_SEQUENCE_NO_INDEX
, 0);
1795 UpdateMailboxContent (Mailbox
, DEBUG_MAILBOX_HOST_SEQUENCE_NO_INDEX
, 0);
1801 // If reveived HALT command, need to defer the GO command
1803 SendAckPacket (DEBUG_COMMAND_HALT_PROCESSED
);
1804 HaltDeferred
= FALSE
;
1806 Vector
= DEBUG_TIMER_VECTOR
;
1810 case DEBUG_COMMAND_BREAK_CAUSE
:
1812 if (MultiProcessorDebugSupport() && ProcessorIndex
!= mDebugMpContext
.BreakAtCpuIndex
) {
1813 Status
= SendBreakCausePacket (DEBUG_TIMER_VECTOR
, CpuContext
);
1816 Status
= SendBreakCausePacket (Vector
, CpuContext
);
1821 case DEBUG_COMMAND_SET_HW_BREAKPOINT
:
1822 SetDebugRegister (CpuContext
, (DEBUG_DATA_SET_HW_BREAKPOINT
*) (DebugHeader
+ 1));
1823 SendAckPacket (DEBUG_COMMAND_OK
);
1826 case DEBUG_COMMAND_CLEAR_HW_BREAKPOINT
:
1827 ClearDebugRegister (CpuContext
, (DEBUG_DATA_CLEAR_HW_BREAKPOINT
*) (DebugHeader
+ 1));
1828 SendAckPacket (DEBUG_COMMAND_OK
);
1831 case DEBUG_COMMAND_SINGLE_STEPPING
:
1832 CommandStepping (CpuContext
);
1834 // Clear Dr0 to avoid to be recognized as IMAGE_LOAD/_UNLOAD again when hitting a breakpoint after GO
1835 // If HOST changed Dr0 before GO, we will not change Dr0 here
1837 Data8
= GetBreakCause (Vector
, CpuContext
);
1838 if (Data8
== DEBUG_DATA_BREAK_CAUSE_IMAGE_LOAD
|| Data8
== DEBUG_DATA_BREAK_CAUSE_IMAGE_UNLOAD
) {
1839 CpuContext
->Dr0
= 0;
1842 mDebugMpContext
.BreakAtCpuIndex
= (UINT32
) (-1);
1844 // Set Stepping Flag
1846 SetDebugFlag (DEBUG_AGENT_FLAG_STEPPING
, 1);
1847 ReleaseMpSpinLock (&mDebugMpContext
.DebugPortSpinLock
);
1849 // Executing stepping command directly without sending ACK packet,
1850 // ACK packet will be sent after stepping done.
1854 case DEBUG_COMMAND_SET_SW_BREAKPOINT
:
1855 Data64
= (UINTN
) (((DEBUG_DATA_SET_SW_BREAKPOINT
*) (DebugHeader
+ 1))->Address
);
1856 Data8
= *(UINT8
*) (UINTN
) Data64
;
1857 *(UINT8
*) (UINTN
) Data64
= DEBUG_SW_BREAKPOINT_SYMBOL
;
1858 Status
= SendDataResponsePacket ((UINT8
*) &Data8
, (UINT16
) sizeof (UINT8
));
1861 case DEBUG_COMMAND_READ_MEMORY
:
1862 MemoryRead
= (DEBUG_DATA_READ_MEMORY
*) (DebugHeader
+ 1);
1863 Status
= ReadMemoryAndSendResponsePacket ((UINT8
*) (UINTN
) MemoryRead
->Address
, MemoryRead
->Count
, MemoryRead
->Width
);
1866 case DEBUG_COMMAND_WRITE_MEMORY
:
1867 MemoryWrite
= (DEBUG_DATA_WRITE_MEMORY
*) (DebugHeader
+ 1);
1869 // Copy data into one memory with 8-byte alignment address
1871 AlignedDataPtr
= ALIGN_POINTER ((UINT8
*) &MemoryWrite
->Data
, sizeof (UINT64
));
1872 if (AlignedDataPtr
!= (UINT8
*) &MemoryWrite
->Data
) {
1873 CopyMem (AlignedDataPtr
, (UINT8
*) &MemoryWrite
->Data
, MemoryWrite
->Count
* MemoryWrite
->Width
);
1875 CopyMemByWidth ((UINT8
*) (UINTN
) MemoryWrite
->Address
, AlignedDataPtr
, MemoryWrite
->Count
, MemoryWrite
->Width
);
1876 SendAckPacket (DEBUG_COMMAND_OK
);
1879 case DEBUG_COMMAND_READ_IO
:
1880 IoRead
= (DEBUG_DATA_READ_IO
*) (DebugHeader
+ 1);
1881 switch (IoRead
->Width
) {
1883 Data64
= IoRead8 ((UINTN
) IoRead
->Port
);
1886 Data64
= IoRead16 ((UINTN
) IoRead
->Port
);
1889 Data64
= IoRead32 ((UINTN
) IoRead
->Port
);
1892 Data64
= IoRead64 ((UINTN
) IoRead
->Port
);
1895 Data64
= (UINT64
) -1;
1897 Status
= SendDataResponsePacket ((UINT8
*) &Data64
, IoRead
->Width
);
1900 case DEBUG_COMMAND_WRITE_IO
:
1901 IoWrite
= (DEBUG_DATA_WRITE_IO
*) (DebugHeader
+ 1);
1902 switch (IoWrite
->Width
) {
1904 Data64
= IoWrite8 ((UINTN
) IoWrite
->Port
, *(UINT8
*) &IoWrite
->Data
);
1907 Data64
= IoWrite16 ((UINTN
) IoWrite
->Port
, *(UINT16
*) &IoWrite
->Data
);
1910 Data64
= IoWrite32 ((UINTN
) IoWrite
->Port
, *(UINT32
*) &IoWrite
->Data
);
1913 Data64
= IoWrite64 ((UINTN
) IoWrite
->Port
, *(UINT64
*) &IoWrite
->Data
);
1916 Data64
= (UINT64
) -1;
1918 SendAckPacket (DEBUG_COMMAND_OK
);
1921 case DEBUG_COMMAND_READ_ALL_REGISTERS
:
1922 Status
= SendDataResponsePacket ((UINT8
*) CpuContext
, sizeof (*CpuContext
));
1925 case DEBUG_COMMAND_READ_REGISTER
:
1926 RegisterRead
= (DEBUG_DATA_READ_REGISTER
*) (DebugHeader
+ 1);
1928 if (RegisterRead
->Index
<= SOFT_DEBUGGER_REGISTER_MAX
) {
1929 RegisterBuffer
= ArchReadRegisterBuffer (CpuContext
, RegisterRead
->Index
, &Width
);
1930 Status
= SendDataResponsePacket (RegisterBuffer
, Width
);
1932 Status
= RETURN_UNSUPPORTED
;
1936 case DEBUG_COMMAND_WRITE_REGISTER
:
1937 RegisterWrite
= (DEBUG_DATA_WRITE_REGISTER
*) (DebugHeader
+ 1);
1938 if (RegisterWrite
->Index
<= SOFT_DEBUGGER_REGISTER_MAX
) {
1939 RegisterBuffer
= ArchReadRegisterBuffer (CpuContext
, RegisterWrite
->Index
, &Width
);
1940 ASSERT (Width
== RegisterWrite
->Length
);
1941 CopyMem (RegisterBuffer
, RegisterWrite
->Data
, Width
);
1942 SendAckPacket (DEBUG_COMMAND_OK
);
1944 Status
= RETURN_UNSUPPORTED
;
1948 case DEBUG_COMMAND_ARCH_MODE
:
1949 Data8
= DEBUG_ARCH_SYMBOL
;
1950 Status
= SendDataResponsePacket ((UINT8
*) &Data8
, (UINT16
) sizeof (UINT8
));
1953 case DEBUG_COMMAND_READ_MSR
:
1954 MsrRegisterRead
= (DEBUG_DATA_READ_MSR
*) (DebugHeader
+ 1);
1955 Data64
= AsmReadMsr64 (MsrRegisterRead
->Index
);
1956 Status
= SendDataResponsePacket ((UINT8
*) &Data64
, (UINT16
) sizeof (UINT64
));
1959 case DEBUG_COMMAND_WRITE_MSR
:
1960 MsrRegisterWrite
= (DEBUG_DATA_WRITE_MSR
*) (DebugHeader
+ 1);
1961 AsmWriteMsr64 (MsrRegisterWrite
->Index
, MsrRegisterWrite
->Value
);
1962 SendAckPacket (DEBUG_COMMAND_OK
);
1965 case DEBUG_COMMAND_SET_DEBUG_SETTING
:
1966 Status
= SetDebugSetting ((DEBUG_DATA_SET_DEBUG_SETTING
*)(DebugHeader
+ 1));
1967 if (Status
== RETURN_SUCCESS
) {
1968 SendAckPacket (DEBUG_COMMAND_OK
);
1972 case DEBUG_COMMAND_GET_REVISION
:
1973 DebugAgentRevision
.Revision
= DEBUG_AGENT_REVISION
;
1974 DebugAgentRevision
.Capabilities
= DEBUG_AGENT_CAPABILITIES
;
1975 Status
= SendDataResponsePacket ((UINT8
*) &DebugAgentRevision
, (UINT16
) sizeof (DEBUG_DATA_RESPONSE_GET_REVISION
));
1978 case DEBUG_COMMAND_GET_EXCEPTION
:
1979 Exception
.ExceptionNum
= (UINT8
) Vector
;
1980 Exception
.ExceptionData
= (UINT32
) CpuContext
->ExceptionData
;
1981 Status
= SendDataResponsePacket ((UINT8
*) &Exception
, (UINT16
) sizeof (DEBUG_DATA_RESPONSE_GET_EXCEPTION
));
1984 case DEBUG_COMMAND_SET_VIEWPOINT
:
1985 SetViewPoint
= (DEBUG_DATA_SET_VIEWPOINT
*) (DebugHeader
+ 1);
1986 if (MultiProcessorDebugSupport()) {
1987 if (IsCpuStopped (SetViewPoint
->ViewPoint
)) {
1988 SetDebugViewPoint (SetViewPoint
->ViewPoint
);
1989 SendAckPacket (DEBUG_COMMAND_OK
);
1992 // If CPU is not halted
1994 SendAckPacket (DEBUG_COMMAND_NOT_SUPPORTED
);
1996 } else if (SetViewPoint
->ViewPoint
== 0) {
1997 SendAckPacket (DEBUG_COMMAND_OK
);
2000 SendAckPacket (DEBUG_COMMAND_NOT_SUPPORTED
);
2005 case DEBUG_COMMAND_GET_VIEWPOINT
:
2006 Data32
= mDebugMpContext
.ViewPointIndex
;
2007 SendDataResponsePacket((UINT8
*) &Data32
, (UINT16
) sizeof (UINT32
));
2010 case DEBUG_COMMAND_MEMORY_READY
:
2011 Data8
= (UINT8
) GetDebugFlag (DEBUG_AGENT_FLAG_MEMORY_READY
);
2012 SendDataResponsePacket (&Data8
, (UINT16
) sizeof (UINT8
));
2015 case DEBUG_COMMAND_DETACH
:
2016 SetHostAttached (FALSE
);
2017 SendAckPacket (DEBUG_COMMAND_OK
);
2020 case DEBUG_COMMAND_CPUID
:
2021 Cpuid
= (DEBUG_DATA_CPUID
*) (DebugHeader
+ 1);
2023 Cpuid
->Eax
, Cpuid
->Ecx
,
2024 &CpuidResponse
.Eax
, &CpuidResponse
.Ebx
,
2025 &CpuidResponse
.Ecx
, &CpuidResponse
.Edx
2027 SendDataResponsePacket ((UINT8
*) &CpuidResponse
, (UINT16
) sizeof (CpuidResponse
));
2030 case DEBUG_COMMAND_SEARCH_SIGNATURE
:
2031 SearchSignature
= (DEBUG_DATA_SEARCH_SIGNATURE
*) (DebugHeader
+ 1);
2032 if ((SearchSignature
->Alignment
!= 0) &&
2033 (SearchSignature
->Alignment
== GetPowerOfTwo32 (SearchSignature
->Alignment
))
2035 if (SearchSignature
->Positive
) {
2037 Data64
= ALIGN_VALUE ((UINTN
) SearchSignature
->Start
, SearchSignature
->Alignment
);
2038 Data64
<= SearchSignature
->Start
+ SearchSignature
->Count
- SearchSignature
->DataLength
;
2039 Data64
+= SearchSignature
->Alignment
2041 if (CompareMem ((VOID
*) (UINTN
) Data64
, &SearchSignature
->Data
, SearchSignature
->DataLength
) == 0) {
2045 if (Data64
> SearchSignature
->Start
+ SearchSignature
->Count
- SearchSignature
->DataLength
) {
2046 Data64
= (UINT64
) -1;
2050 Data64
= ALIGN_VALUE ((UINTN
) SearchSignature
->Start
- SearchSignature
->Alignment
, SearchSignature
->Alignment
);
2051 Data64
>= SearchSignature
->Start
- SearchSignature
->Count
;
2052 Data64
-= SearchSignature
->Alignment
2054 if (CompareMem ((VOID
*) (UINTN
) Data64
, &SearchSignature
->Data
, SearchSignature
->DataLength
) == 0) {
2058 if (Data64
< SearchSignature
->Start
- SearchSignature
->Count
) {
2059 Data64
= (UINT64
) -1;
2062 SendDataResponsePacket ((UINT8
*) &Data64
, (UINT16
) sizeof (Data64
));
2064 Status
= RETURN_UNSUPPORTED
;
2069 SendAckPacket (DEBUG_COMMAND_NOT_SUPPORTED
);
2073 if (Status
== RETURN_UNSUPPORTED
) {
2074 SendAckPacket (DEBUG_COMMAND_NOT_SUPPORTED
);
2075 } else if (Status
!= RETURN_SUCCESS
) {
2076 SendAckPacket (DEBUG_COMMAND_ABORT
);
2079 ReleaseMpSpinLock (&mDebugMpContext
.DebugPortSpinLock
);
2085 C function called in interrupt handler.
2087 @param[in] Vector Vector value of exception or interrutp.
2088 @param[in] CpuContext Pointer to save CPU context.
2095 IN DEBUG_CPU_CONTEXT
*CpuContext
2098 UINT8 InputCharacter
;
2101 BOOLEAN BreakReceived
;
2102 UINT32 ProcessorIndex
;
2103 UINT32 CurrentDebugTimerInitCount
;
2104 DEBUG_PORT_HANDLE Handle
;
2107 UINT32 IssuedViewPoint
;
2108 DEBUG_AGENT_EXCEPTION_BUFFER
*ExceptionBuffer
;
2112 IssuedViewPoint
= 0;
2113 BreakReceived
= FALSE
;
2115 if (mSkipBreakpoint
) {
2117 // If Skip Breakpoint flag is set, means communication is disturbed by hardware SMI, we need to ignore the break points in SMM
2119 if ((Vector
== DEBUG_INT1_VECTOR
) || (Vector
== DEBUG_INT3_VECTOR
)) {
2120 DebugPortWriteBuffer (GetDebugPortHandle(), (UINT8
*) mWarningMsgIngoreBreakpoint
, AsciiStrLen (mWarningMsgIngoreBreakpoint
));
2125 if (MultiProcessorDebugSupport()) {
2126 ProcessorIndex
= GetProcessorIndex ();
2128 // If this processor has alreay halted before, need to check it later
2130 if (IsCpuStopped (ProcessorIndex
)) {
2131 IssuedViewPoint
= ProcessorIndex
;
2135 if (IssuedViewPoint
== ProcessorIndex
&& GetDebugFlag (DEBUG_AGENT_FLAG_STEPPING
) != 1) {
2137 // Check if this exception is issued by Debug Agent itself
2138 // If yes, fill the debug agent exception buffer and LongJump() back to
2139 // the saved CPU content in CommandCommunication()
2141 if (GetDebugFlag (DEBUG_AGENT_FLAG_AGENT_IN_PROGRESS
) == 1) {
2142 DebugAgentMsgPrint (DEBUG_AGENT_ERROR
, "Debug agent meet one Exception, ExceptionNum is %d, EIP = 0x%x.\n", Vector
, (UINTN
)CpuContext
->Eip
);
2143 ExceptionBuffer
= (DEBUG_AGENT_EXCEPTION_BUFFER
*) (UINTN
) GetMailboxPointer()->ExceptionBufferPointer
;
2144 ExceptionBuffer
->ExceptionContent
.ExceptionNum
= (UINT8
) Vector
;
2145 ExceptionBuffer
->ExceptionContent
.ExceptionData
= (UINT32
) CpuContext
->ExceptionData
;
2146 LongJump ((BASE_LIBRARY_JUMP_BUFFER
*)(UINTN
)(ExceptionBuffer
), 1);
2150 if (MultiProcessorDebugSupport()) {
2152 // If RUN commmand is executing, wait for it done.
2154 while (mDebugMpContext
.RunCommandSet
) {
2159 Handle
= GetDebugPortHandle();
2160 BreakCause
= GetBreakCause (Vector
, CpuContext
);
2162 case DEBUG_INT1_VECTOR
:
2163 case DEBUG_INT3_VECTOR
:
2164 switch (BreakCause
) {
2165 case DEBUG_DATA_BREAK_CAUSE_SYSTEM_RESET
:
2166 if (AttachHost (BreakCause
, READ_PACKET_TIMEOUT
, &BreakReceived
) != RETURN_SUCCESS
) {
2168 // Try to connect HOST, return if fails
2172 CommandCommunication (Vector
, CpuContext
, BreakReceived
);
2175 case DEBUG_DATA_BREAK_CAUSE_STEPPING
:
2177 // Stepping is finished, send Ack package.
2179 if (MultiProcessorDebugSupport()) {
2180 mDebugMpContext
.BreakAtCpuIndex
= ProcessorIndex
;
2182 SendAckPacket (DEBUG_COMMAND_OK
);
2183 CommandCommunication (Vector
, CpuContext
, BreakReceived
);
2186 case DEBUG_DATA_BREAK_CAUSE_MEMORY_READY
:
2190 SendCommandAndWaitForAckOK (DEBUG_COMMAND_MEMORY_READY
, READ_PACKET_TIMEOUT
, &BreakReceived
, NULL
);
2191 CommandCommunication (Vector
, CpuContext
, BreakReceived
);
2194 case DEBUG_DATA_BREAK_CAUSE_IMAGE_LOAD
:
2195 case DEBUG_DATA_BREAK_CAUSE_IMAGE_UNLOAD
:
2197 // Set AL to DEBUG_AGENT_IMAGE_CONTINUE
2199 Al
= ArchReadRegisterBuffer (CpuContext
, SOFT_DEBUGGER_REGISTER_AX
, &Data8
);
2200 *Al
= DEBUG_AGENT_IMAGE_CONTINUE
;
2202 if (!IsHostAttached ()) {
2204 // If HOST is not connected for image load/unload, return
2209 // Continue to run the following common code
2212 case DEBUG_DATA_BREAK_CAUSE_HW_BREAKPOINT
:
2213 case DEBUG_DATA_BREAK_CAUSE_SW_BREAKPOINT
:
2216 // Send Break packet to HOST
2218 AcquireMpSpinLock (&mDebugMpContext
.DebugPortSpinLock
);
2220 // Only the first breaking processor could send BREAK_POINT to HOST
2222 if (IsFirstBreakProcessor (ProcessorIndex
)) {
2223 SendBreakPacketToHost (BreakCause
, ProcessorIndex
, &BreakReceived
);
2225 ReleaseMpSpinLock (&mDebugMpContext
.DebugPortSpinLock
);
2227 if (Vector
== DEBUG_INT3_VECTOR
) {
2229 // go back address located "0xCC"
2232 SavedEip
= CpuContext
->Eip
;
2233 CommandCommunication (Vector
, CpuContext
, BreakReceived
);
2234 if ((SavedEip
== CpuContext
->Eip
) &&
2235 (*(UINT8
*) (UINTN
) CpuContext
->Eip
== DEBUG_SW_BREAKPOINT_SYMBOL
)) {
2237 // If this is not a software breakpoint set by HOST,
2243 CommandCommunication (Vector
, CpuContext
, BreakReceived
);
2250 case DEBUG_TIMER_VECTOR
:
2252 AcquireMpSpinLock (&mDebugMpContext
.DebugPortSpinLock
);
2254 if (MultiProcessorDebugSupport()) {
2255 if (IsBsp (ProcessorIndex
)) {
2257 // If current processor is BSP, check Apic timer's init count if changed,
2258 // it may be re-written when switching BSP.
2259 // If it changed, re-initialize debug timer
2261 CurrentDebugTimerInitCount
= GetApicTimerInitCount ();
2262 if (mDebugMpContext
.DebugTimerInitCount
!= CurrentDebugTimerInitCount
) {
2263 InitializeDebugTimer ();
2267 if (!IsBsp (ProcessorIndex
) || mDebugMpContext
.IpiSentByAp
) {
2268 ReleaseMpSpinLock (&mDebugMpContext
.DebugPortSpinLock
);
2270 // If current processor is not BSP or this is one IPI sent by AP
2272 if (mDebugMpContext
.BreakAtCpuIndex
!= (UINT32
) (-1)) {
2273 CommandCommunication (Vector
, CpuContext
, FALSE
);
2277 // Clear EOI before exiting interrupt process routine.
2285 // Only BSP could run here
2289 // If there is data in debug port, will check whether it is break(attach/break-in) symbol,
2290 // If yes, go into communication mode with HOST.
2291 // If no, exit interrupt process.
2293 if (DebugReadBreakSymbol (Handle
, &InputCharacter
) == EFI_NOT_FOUND
) {
2297 if ((!IsHostAttached () && (InputCharacter
== DEBUG_STARTING_SYMBOL_ATTACH
)) ||
2298 (IsHostAttached () && (InputCharacter
== DEBUG_COMMAND_HALT
)) ||
2299 (IsHostAttached () && (InputCharacter
== DEBUG_COMMAND_GO
))
2301 DebugAgentMsgPrint (DEBUG_AGENT_VERBOSE
, "Received data [%02x]\n", InputCharacter
);
2303 // Ack OK for break-in symbol
2305 SendAckPacket (DEBUG_COMMAND_OK
);
2308 // If receive GO command in Debug Timer, means HOST may lost ACK packet before.
2310 if (InputCharacter
== DEBUG_COMMAND_GO
) {
2314 if (!IsHostAttached ()) {
2316 // Try to attach HOST, if no ack received after 200ms, return
2318 if (AttachHost (BreakCause
, READ_PACKET_TIMEOUT
, &BreakReceived
) != RETURN_SUCCESS
) {
2323 if (MultiProcessorDebugSupport()) {
2324 if(FindNextPendingBreakCpu () != -1) {
2325 SetCpuBreakFlagByIndex (ProcessorIndex
, TRUE
);
2327 HaltOtherProcessors (ProcessorIndex
);
2330 ReleaseMpSpinLock (&mDebugMpContext
.DebugPortSpinLock
);
2331 CommandCommunication (Vector
, CpuContext
, BreakReceived
);
2332 AcquireMpSpinLock (&mDebugMpContext
.DebugPortSpinLock
);
2338 // Clear EOI before exiting interrupt process routine.
2342 ReleaseMpSpinLock (&mDebugMpContext
.DebugPortSpinLock
);
2347 if (Vector
<= DEBUG_EXCEPT_SIMD
) {
2348 if (BreakCause
== DEBUG_DATA_BREAK_CAUSE_STEPPING
) {
2350 // Stepping is finished, send Ack package.
2352 if (MultiProcessorDebugSupport()) {
2353 mDebugMpContext
.BreakAtCpuIndex
= ProcessorIndex
;
2355 SendAckPacket (DEBUG_COMMAND_OK
);
2358 // Exception occurs, send Break packet to HOST
2360 AcquireMpSpinLock (&mDebugMpContext
.DebugPortSpinLock
);
2362 // Only the first breaking processor could send BREAK_POINT to HOST
2364 if (IsFirstBreakProcessor (ProcessorIndex
)) {
2365 SendBreakPacketToHost (BreakCause
, ProcessorIndex
, &BreakReceived
);
2367 ReleaseMpSpinLock (&mDebugMpContext
.DebugPortSpinLock
);
2370 CommandCommunication (Vector
, CpuContext
, BreakReceived
);
2375 if (MultiProcessorDebugSupport()) {
2377 // Clear flag and wait for all processors run here
2379 SetIpiSentByApFlag (FALSE
);
2380 while (mDebugMpContext
.RunCommandSet
) {
2385 // Only current (view) processor could clean up AgentInProgress flag.
2387 if (mDebugMpContext
.ViewPointIndex
== ProcessorIndex
) {
2388 IssuedViewPoint
= mDebugMpContext
.ViewPointIndex
;
2392 if (IssuedViewPoint
== ProcessorIndex
&& GetDebugFlag (DEBUG_AGENT_FLAG_STEPPING
) != 1) {
2394 // If the command is not stepping, clean up AgentInProgress flag
2396 SetDebugFlag (DEBUG_AGENT_FLAG_AGENT_IN_PROGRESS
, 0);