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 - 2015, 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 Calculate 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 Decompress the Data in place.
962 @param[in, out] Data The compressed data buffer.
963 The buffer is assumed large enough to hold the uncompressed data.
964 @param[in] Length The length of the compressed data buffer.
966 @return The length of the uncompressed data buffer.
969 DecompressDataInPlace (
979 LastChar
= (UINT16
) -1;
981 for (Index
= 0; Index
< Length
; Index
++) {
982 CurrentChar
= Data
[Index
];
983 if (LastCharCount
== 2) {
985 CopyMem (&Data
[Index
+ CurrentChar
], &Data
[Index
+ 1], Length
- Index
- 1);
986 SetMem (&Data
[Index
], CurrentChar
, (UINT8
) LastChar
);
987 LastChar
= (UINT16
) -1;
988 Index
+= CurrentChar
- 1;
989 Length
+= CurrentChar
- 1;
991 if (LastChar
!= CurrentChar
) {
995 LastChar
= CurrentChar
;
999 ASSERT (Length
<= DEBUG_DATA_MAXIMUM_REAL_DATA
);
1001 return (UINT8
) Length
;
1005 Receive valid packet from HOST.
1007 @param[out] InputPacket Buffer to receive packet.
1008 @param[out] BreakReceived TRUE means break-in symbol received.
1009 FALSE means break-in symbol not received.
1010 @param[out] IncompatibilityFlag If IncompatibilityFlag is not NULL, return
1011 TRUE: Compatible packet received.
1012 FALSE: Incompatible packet received.
1013 @param[in] Timeout Time out value to wait for acknowlege from HOST.
1014 The unit is microsecond.
1015 @param[in] SkipStartSymbol TRUE: Skip time out when reading start symbol.
1016 FALSE: Does not Skip time out when reading start symbol.
1018 @retval RETURN_SUCCESS A valid package was reveived in InputPacket.
1019 @retval RETURN_TIMEOUT Timeout occurs.
1024 OUT UINT8
*InputPacket
,
1025 OUT BOOLEAN
*BreakReceived
,
1026 OUT BOOLEAN
*IncompatibilityFlag
, OPTIONAL
1028 IN BOOLEAN SkipStartSymbol
1031 DEBUG_PACKET_HEADER
*DebugHeader
;
1033 DEBUG_PORT_HANDLE Handle
;
1035 UINTN TimeoutForStartSymbol
;
1037 Handle
= GetDebugPortHandle();
1038 if (SkipStartSymbol
) {
1039 TimeoutForStartSymbol
= 0;
1041 TimeoutForStartSymbol
= Timeout
;
1044 DebugHeader
= (DEBUG_PACKET_HEADER
*) InputPacket
;
1047 // Find the valid start symbol
1049 Received
= DebugPortReadBuffer (Handle
, &DebugHeader
->StartSymbol
, sizeof (DebugHeader
->StartSymbol
), TimeoutForStartSymbol
);
1050 if (Received
< sizeof (DebugHeader
->StartSymbol
)) {
1051 DebugAgentMsgPrint (DEBUG_AGENT_WARNING
, "DebugPortReadBuffer(StartSymbol) timeout\n");
1052 return RETURN_TIMEOUT
;
1055 if ((DebugHeader
->StartSymbol
!= DEBUG_STARTING_SYMBOL_NORMAL
) && (DebugHeader
->StartSymbol
!= DEBUG_STARTING_SYMBOL_COMPRESS
)) {
1056 DebugAgentMsgPrint (DEBUG_AGENT_WARNING
, "Invalid start symbol received [%02x]\n", DebugHeader
->StartSymbol
);
1061 // Read Package header till field Length
1063 Received
= DebugPortReadBuffer (
1065 (UINT8
*) DebugHeader
+ OFFSET_OF (DEBUG_PACKET_HEADER
, Command
),
1066 OFFSET_OF (DEBUG_PACKET_HEADER
, Length
) + sizeof (DebugHeader
->Length
) - sizeof (DebugHeader
->StartSymbol
),
1069 if (Received
== 0) {
1070 DebugAgentMsgPrint (DEBUG_AGENT_ERROR
, "DebugPortReadBuffer(Command) timeout\n");
1071 return RETURN_TIMEOUT
;
1073 if (DebugHeader
->Length
< sizeof (DEBUG_PACKET_HEADER
)) {
1074 if (IncompatibilityFlag
!= NULL
) {
1076 // This is one old version debug packet format, set Incompatibility flag
1078 *IncompatibilityFlag
= TRUE
;
1081 // Skip the bad small packet
1087 // Read the payload data include the CRC field
1089 Received
= DebugPortReadBuffer (Handle
, &DebugHeader
->SequenceNo
, (UINT8
) (DebugHeader
->Length
- OFFSET_OF (DEBUG_PACKET_HEADER
, SequenceNo
)), Timeout
);
1090 if (Received
== 0) {
1091 DebugAgentMsgPrint (DEBUG_AGENT_ERROR
, "DebugPortReadBuffer(SequenceNo) timeout\n");
1092 return RETURN_TIMEOUT
;
1095 // Calculate the CRC of Debug Packet
1097 Crc
= DebugHeader
->Crc
;
1098 DebugHeader
->Crc
= 0;
1099 if (Crc
== CalculateCrc16 ((UINT8
*) DebugHeader
, DebugHeader
->Length
, 0)) {
1102 DebugAgentMsgPrint (DEBUG_AGENT_WARNING
, "CRC Error (received CRC is %x)\n", Crc
);
1103 DebugAgentDataMsgPrint (DEBUG_AGENT_VERBOSE
, FALSE
, (UINT8
*) DebugHeader
, DebugHeader
->Length
);
1107 DebugAgentDataMsgPrint (DEBUG_AGENT_VERBOSE
, FALSE
, (UINT8
*) DebugHeader
, DebugHeader
->Length
);
1109 if (DebugHeader
->StartSymbol
== DEBUG_STARTING_SYMBOL_COMPRESS
) {
1110 DebugHeader
->StartSymbol
= DEBUG_STARTING_SYMBOL_NORMAL
;
1111 DebugHeader
->Length
= DecompressDataInPlace (
1112 (UINT8
*) (DebugHeader
+ 1), DebugHeader
->Length
- sizeof (DEBUG_PACKET_HEADER
)
1113 ) + sizeof (DEBUG_PACKET_HEADER
);
1115 return RETURN_SUCCESS
;
1119 Receive acknowledge packet OK from HOST in specified time.
1121 @param[in] Command The command type issued by TARGET.
1122 @param[in] Timeout Time out value to wait for acknowlege from HOST.
1123 The unit is microsecond.
1124 @param[out] BreakReceived If BreakReceived is not NULL,
1125 TRUE is retured if break-in symbol received.
1126 FALSE is retured if break-in symbol not received.
1127 @param[out] IncompatibilityFlag If IncompatibilityFlag is not NULL, return
1128 TRUE: Compatible packet received.
1129 FALSE: Incompatible packet received.
1131 @retval RETRUEN_SUCCESS Succeed to receive acknowlege packet from HOST,
1132 the type of acknowlege packet saved in Ack.
1133 @retval RETURN_TIMEOUT Specified timeout value was up.
1137 SendCommandAndWaitForAckOK (
1140 OUT BOOLEAN
*BreakReceived
, OPTIONAL
1141 OUT BOOLEAN
*IncompatibilityFlag OPTIONAL
1144 RETURN_STATUS Status
;
1145 UINT8 InputPacketBuffer
[DEBUG_DATA_UPPER_LIMIT
];
1146 DEBUG_PACKET_HEADER
*DebugHeader
;
1148 UINT8 HostSequenceNo
;
1152 DebugHeader
= (DEBUG_PACKET_HEADER
*) InputPacketBuffer
;
1153 Status
= RETURN_TIMEOUT
;
1154 while (RetryCount
> 0) {
1155 SequenceNo
= GetMailboxPointer()->SequenceNo
;
1156 HostSequenceNo
= GetMailboxPointer()->HostSequenceNo
;
1157 SendPacketWithoutData (Command
, SequenceNo
);
1158 Status
= ReceivePacket ((UINT8
*) DebugHeader
, BreakReceived
, IncompatibilityFlag
, Timeout
, FALSE
);
1159 if (Status
== RETURN_TIMEOUT
) {
1160 if (Command
== DEBUG_COMMAND_INIT_BREAK
) {
1163 DebugAgentMsgPrint (DEBUG_AGENT_WARNING
, "TARGET: Timeout when waiting for ACK packet.\n");
1167 ASSERT_EFI_ERROR (Status
);
1169 // Status == RETURN_SUCCESS
1171 if (DebugHeader
->Command
== DEBUG_COMMAND_OK
&& DebugHeader
->SequenceNo
== SequenceNo
) {
1175 UpdateMailboxContent (GetMailboxPointer(), DEBUG_MAILBOX_SEQUENCE_NO_INDEX
, ++SequenceNo
);
1178 if (DebugHeader
->Command
== DEBUG_COMMAND_GO
&& (DebugHeader
->SequenceNo
== HostSequenceNo
|| Command
== DEBUG_COMMAND_INIT_BREAK
)) {
1182 if (Command
== DEBUG_COMMAND_INIT_BREAK
) {
1183 DebugAgentMsgPrint (DEBUG_AGENT_WARNING
, "TARGET: Receive GO() in last boot\n");
1185 SendPacketWithoutData (DEBUG_COMMAND_OK
, DebugHeader
->SequenceNo
);
1189 ASSERT (Command
== DEBUG_COMMAND_INIT_BREAK
);
1194 Get current break cause.
1196 @param[in] Vector Vector value of exception or interrupt.
1197 @param[in] CpuContext Pointer to save CPU context.
1199 @return The type of break cause defined by XXXX
1205 IN DEBUG_CPU_CONTEXT
*CpuContext
1210 Cause
= DEBUG_DATA_BREAK_CAUSE_UNKNOWN
;
1213 case DEBUG_INT1_VECTOR
:
1214 case DEBUG_INT3_VECTOR
:
1216 if (Vector
== DEBUG_INT1_VECTOR
) {
1220 if ((CpuContext
->Dr6
& BIT14
) != 0) {
1221 Cause
= DEBUG_DATA_BREAK_CAUSE_STEPPING
;
1223 // If it's single step, no need to check DR0, to ensure single step work in PeCoffExtraActionLib
1224 // (right after triggering a breakpoint to report image load/unload).
1229 Cause
= DEBUG_DATA_BREAK_CAUSE_HW_BREAKPOINT
;
1235 Cause
= DEBUG_DATA_BREAK_CAUSE_SW_BREAKPOINT
;
1238 switch (CpuContext
->Dr0
) {
1239 case IMAGE_LOAD_SIGNATURE
:
1240 case IMAGE_UNLOAD_SIGNATURE
:
1242 if (CpuContext
->Dr3
== IO_PORT_BREAKPOINT_ADDRESS
) {
1244 Cause
= (UINT8
) ((CpuContext
->Dr0
== IMAGE_LOAD_SIGNATURE
) ?
1245 DEBUG_DATA_BREAK_CAUSE_IMAGE_LOAD
: DEBUG_DATA_BREAK_CAUSE_IMAGE_UNLOAD
);
1249 case SOFT_INTERRUPT_SIGNATURE
:
1251 if (CpuContext
->Dr1
== MEMORY_READY_SIGNATURE
) {
1252 Cause
= DEBUG_DATA_BREAK_CAUSE_MEMORY_READY
;
1253 CpuContext
->Dr0
= 0;
1254 } else if (CpuContext
->Dr1
== SYSTEM_RESET_SIGNATURE
) {
1255 Cause
= DEBUG_DATA_BREAK_CAUSE_SYSTEM_RESET
;
1256 CpuContext
->Dr0
= 0;
1267 case DEBUG_TIMER_VECTOR
:
1268 Cause
= DEBUG_DATA_BREAK_CAUSE_USER_HALT
;
1273 if (GetDebugFlag (DEBUG_AGENT_FLAG_STEPPING
) == 1) {
1275 // If stepping command is executing
1277 Cause
= DEBUG_DATA_BREAK_CAUSE_STEPPING
;
1279 Cause
= DEBUG_DATA_BREAK_CAUSE_EXCEPTION
;
1289 Copy memory from source to destination with specified width.
1291 @param[out] Dest A pointer to the destination buffer of the memory copy.
1292 @param[in] Src A pointer to the source buffer of the memory copy.
1293 @param[in] Count The number of data with specified width to copy from source to destination.
1294 @param[in] Width Data width in byte.
1315 // Copy memory from tail to avoid memory overlap
1317 Destination
= Dest
+ (Count
- 1) * Width
;
1318 Source
= Src
+ (Count
- 1) * Width
;
1322 while (Count
-- != 0) {
1325 *(UINT8
*) Destination
= MmioRead8 ((UINTN
) Source
);
1328 *(UINT16
*) Destination
= MmioRead16 ((UINTN
) Source
);
1331 *(UINT32
*) Destination
= MmioRead32 ((UINTN
) Source
);
1334 *(UINT64
*) Destination
= MmioRead64 ((UINTN
) Source
);
1340 Destination
+= Step
;
1345 Compress the data buffer but do not modify the original buffer.
1347 The compressed data is directly send to the debug channel.
1348 Compressing in place doesn't work because the data may become larger
1349 during compressing phase. ("3 3 ..." --> "3 3 0 ...")
1350 The routine is expected to be called three times:
1351 1. Compute the length of the compressed data buffer;
1352 2. Compute the CRC of the compressed data buffer;
1353 3. Compress the data and send to the debug channel.
1355 @param[in] Data The data buffer.
1356 @param[in] Length The length of the data buffer.
1357 @param[out] CompressedLength Return the length of the compressed data buffer.
1358 It may be larger than the Length in some cases.
1359 @param[out] CompressedCrc Return the CRC of the compressed data buffer.
1360 @param[in] Handle The debug channel handle to send the compressed data buffer.
1363 CompressDataThenSend (
1366 OUT UINTN
*CompressedLength
, OPTIONAL
1367 OUT UINT16
*CompressedCrc
, OPTIONAL
1368 IN DEBUG_PORT_HANDLE Handle OPTIONAL
1373 UINT8 LastCharCount
;
1375 UINTN CompressedIndex
;
1377 ASSERT (Length
> 0);
1379 LastChar
= Data
[0] + 1; // Just ensure it's different from the first byte.
1382 for (Index
= 0, CompressedIndex
= 0; Index
<= Length
; Index
++) {
1383 if (Index
< Length
) {
1384 CurrentChar
= Data
[Index
];
1386 CurrentChar
= (UINT8
) LastChar
+ 1; // just ensure it's different from LastChar
1388 if (LastChar
!= CurrentChar
) {
1389 if (LastCharCount
== 1) {
1391 if (CompressedCrc
!= NULL
) {
1392 *CompressedCrc
= CalculateCrc16 (&LastChar
, 1, *CompressedCrc
);
1394 if (Handle
!= NULL
) {
1395 DebugPortWriteBuffer (Handle
, &LastChar
, 1);
1398 } else if (LastCharCount
>= 2) {
1399 CompressedIndex
+= 3;
1401 if (CompressedCrc
!= NULL
) {
1402 *CompressedCrc
= CalculateCrc16 (&LastChar
, 1, *CompressedCrc
);
1403 *CompressedCrc
= CalculateCrc16 (&LastChar
, 1, *CompressedCrc
);
1404 *CompressedCrc
= CalculateCrc16 (&LastCharCount
, 1, *CompressedCrc
);
1406 if (Handle
!= NULL
) {
1407 DebugPortWriteBuffer (Handle
, &LastChar
, 1);
1408 DebugPortWriteBuffer (Handle
, &LastChar
, 1);
1409 DebugPortWriteBuffer (Handle
, &LastCharCount
, 1);
1415 LastChar
= CurrentChar
;
1418 if (CompressedLength
!= NULL
) {
1419 *CompressedLength
= CompressedIndex
;
1424 Read memory with speicifed width and send packet with response data to HOST.
1426 @param[in] Data Pointer to response data buffer.
1427 @param[in] Count The number of data with specified Width.
1428 @param[in] Width Data width in byte.
1429 @param[in] DebugHeader Pointer to a buffer for creating response packet and receiving ACK packet,
1430 to minimize the stack usage.
1432 @retval RETURN_SUCCESS Response data was sent successfully.
1436 ReadMemoryAndSendResponsePacket (
1440 IN DEBUG_PACKET_HEADER
*DebugHeader
1443 RETURN_STATUS Status
;
1445 DEBUG_PORT_HANDLE Handle
;
1447 UINTN RemainingDataSize
;
1448 UINT8 CurrentDataSize
;
1449 UINTN CompressedDataSize
;
1451 Handle
= GetDebugPortHandle();
1453 RemainingDataSize
= Count
* Width
;
1455 SequenceNo
= GetMailboxPointer()->HostSequenceNo
;
1456 if (RemainingDataSize
<= DEBUG_DATA_MAXIMUM_REAL_DATA
) {
1458 // If the remaining data is less one real packet size, this is the last data packet
1460 CurrentDataSize
= (UINT8
) RemainingDataSize
;
1462 DebugHeader
->Command
= DEBUG_COMMAND_OK
;
1465 // Data is too larger to be sent in one packet, calculate the actual data size could
1466 // be sent in one Maximum data packet
1468 CurrentDataSize
= (DEBUG_DATA_MAXIMUM_REAL_DATA
/ Width
) * Width
;
1470 DebugHeader
->Command
= DEBUG_COMMAND_IN_PROGRESS
;
1473 // Construct the rest Debug header
1475 DebugHeader
->StartSymbol
= DEBUG_STARTING_SYMBOL_NORMAL
;
1476 DebugHeader
->Length
= CurrentDataSize
+ sizeof (DEBUG_PACKET_HEADER
);
1477 DebugHeader
->SequenceNo
= SequenceNo
;
1478 DebugHeader
->Crc
= 0;
1479 CopyMemByWidth ((UINT8
*) (DebugHeader
+ 1), Data
, CurrentDataSize
/ Width
, Width
);
1482 // Compression/decompression support was added since revision 0.4.
1483 // Revision 0.3 shouldn't compress the packet.
1485 if (DEBUG_AGENT_REVISION
>= DEBUG_AGENT_REVISION_04
) {
1487 // Get the compressed data size without modifying the packet.
1489 CompressDataThenSend (
1490 (UINT8
*) (DebugHeader
+ 1),
1492 &CompressedDataSize
,
1497 CompressedDataSize
= CurrentDataSize
;
1499 if (CompressedDataSize
< CurrentDataSize
) {
1500 DebugHeader
->Length
= (UINT8
) CompressedDataSize
+ sizeof (DEBUG_PACKET_HEADER
);
1501 DebugHeader
->StartSymbol
= DEBUG_STARTING_SYMBOL_COMPRESS
;
1503 // Compute the CRC of the packet head without modifying the packet.
1505 DebugHeader
->Crc
= CalculateCrc16 ((UINT8
*) DebugHeader
, sizeof (DEBUG_PACKET_HEADER
), 0);
1506 CompressDataThenSend (
1507 (UINT8
*) (DebugHeader
+ 1),
1514 // Send out the packet head.
1516 DebugPortWriteBuffer (Handle
, (UINT8
*) DebugHeader
, sizeof (DEBUG_PACKET_HEADER
));
1518 // Compress and send out the packet data.
1520 CompressDataThenSend (
1521 (UINT8
*) (DebugHeader
+ 1),
1530 // Calculate and fill the checksum, DebugHeader->Crc should be 0 before invoking CalculateCrc16 ()
1532 DebugHeader
->Crc
= CalculateCrc16 ((UINT8
*) DebugHeader
, DebugHeader
->Length
, 0);
1534 DebugAgentDataMsgPrint (DEBUG_AGENT_VERBOSE
, TRUE
, (UINT8
*) DebugHeader
, DebugHeader
->Length
);
1536 DebugPortWriteBuffer (Handle
, (UINT8
*) DebugHeader
, DebugHeader
->Length
);
1540 Status
= ReceivePacket ((UINT8
*) DebugHeader
, NULL
, NULL
, READ_PACKET_TIMEOUT
, FALSE
);
1541 if (Status
== RETURN_TIMEOUT
) {
1542 DebugAgentMsgPrint (DEBUG_AGENT_WARNING
, "TARGET: Timeout in SendDataResponsePacket()\n");
1545 if ((DebugHeader
->Command
== DEBUG_COMMAND_OK
) && (DebugHeader
->SequenceNo
== SequenceNo
) && LastPacket
) {
1547 // If this is the last packet, return RETURN_SUCCESS.
1549 return RETURN_SUCCESS
;
1551 if ((DebugHeader
->Command
== DEBUG_COMMAND_CONTINUE
) && (DebugHeader
->SequenceNo
== (UINT8
) (SequenceNo
+ 1))) {
1553 // Calculate the rest data size
1555 Data
+= CurrentDataSize
;
1556 RemainingDataSize
-= CurrentDataSize
;
1557 UpdateMailboxContent (GetMailboxPointer(), DEBUG_MAILBOX_HOST_SEQUENCE_NO_INDEX
, DebugHeader
->SequenceNo
);
1560 if (DebugHeader
->SequenceNo
>= SequenceNo
) {
1561 DebugAgentMsgPrint (DEBUG_AGENT_WARNING
, "TARGET: Received one old or new command(SequenceNo is %x, last SequenceNo is %x)\n", SequenceNo
, DebugHeader
->SequenceNo
);
1569 Send packet with response data to HOST.
1571 @param[in] Data Pointer to response data buffer.
1572 @param[in] DataSize Size of response data in byte.
1573 @param[in, out] DebugHeader Pointer to a buffer for creating response packet and receiving ACK packet,
1574 to minimize the stack usage.
1576 @retval RETURN_SUCCESS Response data was sent successfully.
1580 SendDataResponsePacket (
1583 IN OUT DEBUG_PACKET_HEADER
*DebugHeader
1586 return ReadMemoryAndSendResponsePacket (Data
, DataSize
, 1, DebugHeader
);
1590 Try to attach the HOST.
1592 Send init break packet to HOST:
1593 If no acknowlege received in specified Timeout, return RETURN_TIMEOUT.
1594 If received acknowlege, check the revision of HOST.
1595 Set Attach Flag if attach successfully.
1597 @param[in] BreakCause Break cause of this break event.
1598 @param[in] Timeout Time out value to wait for acknowlege from HOST.
1599 The unit is microsecond.
1600 @param[out] BreakReceived If BreakReceived is not NULL,
1601 TRUE is retured if break-in symbol received.
1602 FALSE is retured if break-in symbol not received.
1606 IN UINT8 BreakCause
,
1608 OUT BOOLEAN
*BreakReceived
1611 RETURN_STATUS Status
;
1612 DEBUG_PORT_HANDLE Handle
;
1613 BOOLEAN IncompatibilityFlag
;
1615 IncompatibilityFlag
= FALSE
;
1616 Handle
= GetDebugPortHandle();
1619 // Send init break and wait ack in Timeout
1621 DebugPortWriteBuffer (Handle
, (UINT8
*) mErrorMsgSendInitPacket
, AsciiStrLen (mErrorMsgSendInitPacket
));
1622 if (BreakCause
== DEBUG_DATA_BREAK_CAUSE_SYSTEM_RESET
) {
1623 Status
= SendCommandAndWaitForAckOK (DEBUG_COMMAND_INIT_BREAK
, Timeout
, BreakReceived
, &IncompatibilityFlag
);
1625 Status
= SendCommandAndWaitForAckOK (DEBUG_COMMAND_ATTACH_BREAK
, Timeout
, BreakReceived
, &IncompatibilityFlag
);
1627 if (IncompatibilityFlag
) {
1629 // If the incompatible Debug Packet received, the HOST should be running transfer protocol before DEBUG_AGENT_REVISION.
1630 // It could be UDK Debugger for Windows v1.1/v1.2 or for Linux v0.8/v1.2.
1632 DebugPortWriteBuffer (Handle
, (UINT8
*) mErrorMsgVersionAlert
, AsciiStrLen (mErrorMsgVersionAlert
));
1636 if (RETURN_ERROR (Status
)) {
1637 DebugPortWriteBuffer (Handle
, (UINT8
*) mErrorMsgConnectFail
, AsciiStrLen (mErrorMsgConnectFail
));
1639 DebugPortWriteBuffer (Handle
, (UINT8
*) mErrorMsgConnectOK
, AsciiStrLen (mErrorMsgConnectOK
));
1643 SetHostAttached (TRUE
);
1649 Send Break point packet to HOST.
1651 Only the first breaking processor could sent BREAK_POINT packet.
1653 @param[in] BreakCause Break cause of this break event.
1654 @param[in] ProcessorIndex Processor index value.
1655 @param[out] BreakReceived If BreakReceived is not NULL,
1656 TRUE is retured if break-in symbol received.
1657 FALSE is retured if break-in symbol not received.
1661 SendBreakPacketToHost (
1662 IN UINT8 BreakCause
,
1663 IN UINT32 ProcessorIndex
,
1664 OUT BOOLEAN
*BreakReceived
1667 UINT8 InputCharacter
;
1668 DEBUG_PORT_HANDLE Handle
;
1670 Handle
= GetDebugPortHandle();
1672 if (IsHostAttached ()) {
1673 DebugAgentMsgPrint (DEBUG_AGENT_INFO
, "processor[%x]:Send Break Packet to HOST.\n", ProcessorIndex
);
1674 SendCommandAndWaitForAckOK (DEBUG_COMMAND_BREAK_POINT
, READ_PACKET_TIMEOUT
, BreakReceived
, NULL
);
1676 DebugAgentMsgPrint (DEBUG_AGENT_INFO
, "processor[%x]:Try to attach HOST.\n", ProcessorIndex
);
1678 // If HOST is not attached, try to attach it firstly.
1681 // Poll Attach symbols from HOST and ack OK
1684 DebugPortReadBuffer (Handle
, &InputCharacter
, 1, 0);
1685 } while (InputCharacter
!= DEBUG_STARTING_SYMBOL_ATTACH
);
1686 SendAckPacket (DEBUG_COMMAND_OK
);
1689 // Try to attach HOST
1691 while (AttachHost (BreakCause
, 0, NULL
) != RETURN_SUCCESS
);
1697 The main function to process communication with HOST.
1699 It received the command packet from HOST, and sent response data packet to HOST.
1701 @param[in] Vector Vector value of exception or interrutp.
1702 @param[in, out] CpuContext Pointer to saved CPU context.
1703 @param[in] BreakReceived TRUE means break-in symbol received.
1704 FALSE means break-in symbol not received.
1708 CommandCommunication (
1710 IN OUT DEBUG_CPU_CONTEXT
*CpuContext
,
1711 IN BOOLEAN BreakReceived
1714 RETURN_STATUS Status
;
1715 UINT8 InputPacketBuffer
[DEBUG_DATA_UPPER_LIMIT
+ sizeof (UINT64
) - 1];
1716 DEBUG_PACKET_HEADER
*DebugHeader
;
1721 DEBUG_DATA_READ_MEMORY
*MemoryRead
;
1722 DEBUG_DATA_WRITE_MEMORY
*MemoryWrite
;
1723 DEBUG_DATA_READ_IO
*IoRead
;
1724 DEBUG_DATA_WRITE_IO
*IoWrite
;
1725 DEBUG_DATA_READ_REGISTER
*RegisterRead
;
1726 DEBUG_DATA_WRITE_REGISTER
*RegisterWrite
;
1727 UINT8
*RegisterBuffer
;
1728 DEBUG_DATA_READ_MSR
*MsrRegisterRead
;
1729 DEBUG_DATA_WRITE_MSR
*MsrRegisterWrite
;
1730 DEBUG_DATA_CPUID
*Cpuid
;
1731 DEBUG_DATA_RESPONSE_BREAK_CAUSE BreakCause
;
1732 DEBUG_DATA_RESPONSE_CPUID CpuidResponse
;
1733 DEBUG_DATA_SEARCH_SIGNATURE
*SearchSignature
;
1734 DEBUG_DATA_RESPONSE_GET_EXCEPTION Exception
;
1735 DEBUG_DATA_RESPONSE_GET_REVISION DebugAgentRevision
;
1736 DEBUG_DATA_SET_VIEWPOINT
*SetViewPoint
;
1737 BOOLEAN HaltDeferred
;
1738 UINT32 ProcessorIndex
;
1739 DEBUG_PORT_HANDLE Handle
;
1740 DEBUG_AGENT_EXCEPTION_BUFFER AgentExceptionBuffer
;
1741 UINT32 IssuedViewPoint
;
1742 DEBUG_AGENT_MAILBOX
*Mailbox
;
1743 UINT8
*AlignedDataPtr
;
1746 IssuedViewPoint
= 0;
1747 HaltDeferred
= BreakReceived
;
1749 if (MultiProcessorDebugSupport()) {
1750 ProcessorIndex
= GetProcessorIndex ();
1751 SetCpuStopFlagByIndex (ProcessorIndex
, TRUE
);
1752 if (mDebugMpContext
.ViewPointIndex
== ProcessorIndex
) {
1754 // Only the current view processor could set AgentInProgress Flag.
1756 IssuedViewPoint
= ProcessorIndex
;
1760 if (IssuedViewPoint
== ProcessorIndex
) {
1762 // Set AgentInProgress Flag.
1764 SetDebugFlag (DEBUG_AGENT_FLAG_AGENT_IN_PROGRESS
, 1);
1767 Handle
= GetDebugPortHandle();
1771 if (MultiProcessorDebugSupport()) {
1773 // Check if the current processor is HOST view point
1775 if (mDebugMpContext
.ViewPointIndex
!= ProcessorIndex
) {
1776 if (mDebugMpContext
.RunCommandSet
) {
1778 // If HOST view point sets RUN flag, run GO command to leave
1780 SetCpuStopFlagByIndex (ProcessorIndex
, FALSE
);
1781 CommandGo (CpuContext
);
1785 // Run into loop again
1793 AcquireMpSpinLock (&mDebugMpContext
.DebugPortSpinLock
);
1795 DebugHeader
=(DEBUG_PACKET_HEADER
*) InputPacketBuffer
;
1797 DebugAgentMsgPrint (DEBUG_AGENT_INFO
, "TARGET: Try to get command from HOST...\n");
1798 Status
= ReceivePacket ((UINT8
*) DebugHeader
, &BreakReceived
, NULL
, READ_PACKET_TIMEOUT
, TRUE
);
1799 if (Status
!= RETURN_SUCCESS
|| !IS_REQUEST (DebugHeader
)) {
1800 DebugAgentMsgPrint (DEBUG_AGENT_WARNING
, "TARGET: Get command[%x] sequenceno[%x] returned status is [%x] \n", DebugHeader
->Command
, DebugHeader
->SequenceNo
, Status
);
1801 DebugAgentMsgPrint (DEBUG_AGENT_WARNING
, "TARGET: Get command failed or it's response packet not expected! \n");
1802 ReleaseMpSpinLock (&mDebugMpContext
.DebugPortSpinLock
);
1806 Mailbox
= GetMailboxPointer ();
1807 if (DebugHeader
->SequenceNo
== Mailbox
->HostSequenceNo
) {
1808 DebugAgentMsgPrint (DEBUG_AGENT_WARNING
, "TARGET: Receive one old command[%x] agaist command[%x]\n", DebugHeader
->SequenceNo
, Mailbox
->HostSequenceNo
);
1809 SendAckPacket (Mailbox
->LastAck
);
1810 ReleaseMpSpinLock (&mDebugMpContext
.DebugPortSpinLock
);
1812 } else if (DebugHeader
->SequenceNo
== (UINT8
) (Mailbox
->HostSequenceNo
+ 1)) {
1813 UpdateMailboxContent (Mailbox
, DEBUG_MAILBOX_HOST_SEQUENCE_NO_INDEX
, (UINT8
) DebugHeader
->SequenceNo
);
1815 DebugAgentMsgPrint (DEBUG_AGENT_WARNING
, "Receive one invalid comamnd[%x] agaist command[%x]\n", DebugHeader
->SequenceNo
, Mailbox
->HostSequenceNo
);
1816 ReleaseMpSpinLock (&mDebugMpContext
.DebugPortSpinLock
);
1821 // Save CPU content before executing HOST commond
1823 UpdateMailboxContent (Mailbox
, DEBUG_MAILBOX_EXCEPTION_BUFFER_POINTER_INDEX
, (UINT64
)(UINTN
) &AgentExceptionBuffer
.JumpBuffer
);
1824 if (SetJump (&AgentExceptionBuffer
.JumpBuffer
) != 0) {
1826 // If HOST command failed, continue to wait for HOST's next command
1827 // If needed, agent could send exception info to HOST.
1829 SendAckPacket (DEBUG_COMMAND_ABORT
);
1830 ReleaseMpSpinLock (&mDebugMpContext
.DebugPortSpinLock
);
1834 DebugAgentMsgPrint (DEBUG_AGENT_INFO
, "Processor[%x]:Received one command(%x)\n", mDebugMpContext
.ViewPointIndex
, DebugHeader
->Command
);
1836 switch (DebugHeader
->Command
) {
1838 case DEBUG_COMMAND_HALT
:
1839 SendAckPacket (DEBUG_COMMAND_HALT_DEFERRED
);
1840 HaltDeferred
= TRUE
;
1841 BreakReceived
= FALSE
;
1842 Status
= RETURN_SUCCESS
;
1845 case DEBUG_COMMAND_RESET
:
1846 SendAckPacket (DEBUG_COMMAND_OK
);
1847 SendAckPacket (DEBUG_COMMAND_OK
);
1848 SendAckPacket (DEBUG_COMMAND_OK
);
1849 ReleaseMpSpinLock (&mDebugMpContext
.DebugPortSpinLock
);
1853 // Assume system resets in 2 seconds, otherwise send TIMEOUT packet.
1854 // PCD can be used if 2 seconds isn't long enough for some platforms.
1856 MicroSecondDelay (2000000);
1857 UpdateMailboxContent (Mailbox
, DEBUG_MAILBOX_HOST_SEQUENCE_NO_INDEX
, Mailbox
->HostSequenceNo
+ 1);
1858 SendAckPacket (DEBUG_COMMAND_TIMEOUT
);
1859 SendAckPacket (DEBUG_COMMAND_TIMEOUT
);
1860 SendAckPacket (DEBUG_COMMAND_TIMEOUT
);
1863 case DEBUG_COMMAND_GO
:
1864 CommandGo (CpuContext
);
1866 // Clear Dr0 to avoid to be recognized as IMAGE_LOAD/_UNLOAD again when hitting a breakpoint after GO
1867 // If HOST changed Dr0 before GO, we will not change Dr0 here
1869 Data8
= GetBreakCause (Vector
, CpuContext
);
1870 if (Data8
== DEBUG_DATA_BREAK_CAUSE_IMAGE_LOAD
|| Data8
== DEBUG_DATA_BREAK_CAUSE_IMAGE_UNLOAD
) {
1871 CpuContext
->Dr0
= 0;
1874 // Clear Stepping Flag
1876 SetDebugFlag (DEBUG_AGENT_FLAG_STEPPING
, 0);
1878 if (!HaltDeferred
) {
1880 // If no HALT command received when being in-active mode
1882 if (MultiProcessorDebugSupport()) {
1883 Data32
= FindNextPendingBreakCpu ();
1886 // If there are still others processors being in break state,
1887 // send OK packet to HOST to finish this go command
1889 SendAckPacket (DEBUG_COMMAND_OK
);
1892 // Set current view to the next breaking processor
1894 mDebugMpContext
.ViewPointIndex
= Data32
;
1895 mDebugMpContext
.BreakAtCpuIndex
= mDebugMpContext
.ViewPointIndex
;
1896 SetCpuBreakFlagByIndex (mDebugMpContext
.ViewPointIndex
, FALSE
);
1898 // Send break packet to HOST to let HOST break again
1900 SendBreakPacketToHost (DEBUG_DATA_BREAK_CAUSE_UNKNOWN
, mDebugMpContext
.BreakAtCpuIndex
, &BreakReceived
);
1902 // Continue to run into loop to read command packet from HOST
1904 ReleaseMpSpinLock (&mDebugMpContext
.DebugPortSpinLock
);
1909 // If no else processor break, set stop bitmask,
1910 // and set Running flag for all processors.
1912 SetCpuStopFlagByIndex (ProcessorIndex
, FALSE
);
1913 SetCpuRunningFlag (TRUE
);
1916 // Wait for all processors are in running state
1919 if (IsAllCpuRunning ()) {
1924 // Set BSP to be current view point.
1926 SetDebugViewPoint (mDebugMpContext
.BspIndex
);
1929 // Clear breaking processor index and running flag
1931 mDebugMpContext
.BreakAtCpuIndex
= (UINT32
) (-1);
1932 SetCpuRunningFlag (FALSE
);
1936 // Send OK packet to HOST to finish this go command
1938 SendAckPacket (DEBUG_COMMAND_OK
);
1940 ReleaseMpSpinLock (&mDebugMpContext
.DebugPortSpinLock
);
1942 if (!IsHostAttached()) {
1943 UpdateMailboxContent (Mailbox
, DEBUG_MAILBOX_SEQUENCE_NO_INDEX
, 0);
1944 UpdateMailboxContent (Mailbox
, DEBUG_MAILBOX_HOST_SEQUENCE_NO_INDEX
, 0);
1950 // If reveived HALT command, need to defer the GO command
1952 SendAckPacket (DEBUG_COMMAND_HALT_PROCESSED
);
1953 HaltDeferred
= FALSE
;
1955 Vector
= DEBUG_TIMER_VECTOR
;
1959 case DEBUG_COMMAND_BREAK_CAUSE
:
1960 BreakCause
.StopAddress
= CpuContext
->Eip
;
1961 if (MultiProcessorDebugSupport() && ProcessorIndex
!= mDebugMpContext
.BreakAtCpuIndex
) {
1962 BreakCause
.Cause
= GetBreakCause (DEBUG_TIMER_VECTOR
, CpuContext
);
1964 BreakCause
.Cause
= GetBreakCause (Vector
, CpuContext
);
1966 SendDataResponsePacket ((UINT8
*) &BreakCause
, (UINT16
) sizeof (DEBUG_DATA_RESPONSE_BREAK_CAUSE
), DebugHeader
);
1969 case DEBUG_COMMAND_SET_HW_BREAKPOINT
:
1970 SetDebugRegister (CpuContext
, (DEBUG_DATA_SET_HW_BREAKPOINT
*) (DebugHeader
+ 1));
1971 SendAckPacket (DEBUG_COMMAND_OK
);
1974 case DEBUG_COMMAND_CLEAR_HW_BREAKPOINT
:
1975 ClearDebugRegister (CpuContext
, (DEBUG_DATA_CLEAR_HW_BREAKPOINT
*) (DebugHeader
+ 1));
1976 SendAckPacket (DEBUG_COMMAND_OK
);
1979 case DEBUG_COMMAND_SINGLE_STEPPING
:
1980 CommandStepping (CpuContext
);
1982 // Clear Dr0 to avoid to be recognized as IMAGE_LOAD/_UNLOAD again when hitting a breakpoint after GO
1983 // If HOST changed Dr0 before GO, we will not change Dr0 here
1985 Data8
= GetBreakCause (Vector
, CpuContext
);
1986 if (Data8
== DEBUG_DATA_BREAK_CAUSE_IMAGE_LOAD
|| Data8
== DEBUG_DATA_BREAK_CAUSE_IMAGE_UNLOAD
) {
1987 CpuContext
->Dr0
= 0;
1990 mDebugMpContext
.BreakAtCpuIndex
= (UINT32
) (-1);
1992 // Set Stepping Flag
1994 SetDebugFlag (DEBUG_AGENT_FLAG_STEPPING
, 1);
1995 ReleaseMpSpinLock (&mDebugMpContext
.DebugPortSpinLock
);
1997 // Executing stepping command directly without sending ACK packet,
1998 // ACK packet will be sent after stepping done.
2002 case DEBUG_COMMAND_SET_SW_BREAKPOINT
:
2003 Data64
= (UINTN
) (((DEBUG_DATA_SET_SW_BREAKPOINT
*) (DebugHeader
+ 1))->Address
);
2004 Data8
= *(UINT8
*) (UINTN
) Data64
;
2005 *(UINT8
*) (UINTN
) Data64
= DEBUG_SW_BREAKPOINT_SYMBOL
;
2006 Status
= SendDataResponsePacket ((UINT8
*) &Data8
, (UINT16
) sizeof (UINT8
), DebugHeader
);
2009 case DEBUG_COMMAND_READ_MEMORY
:
2010 MemoryRead
= (DEBUG_DATA_READ_MEMORY
*) (DebugHeader
+ 1);
2011 Status
= ReadMemoryAndSendResponsePacket ((UINT8
*) (UINTN
) MemoryRead
->Address
, MemoryRead
->Count
, MemoryRead
->Width
, DebugHeader
);
2014 case DEBUG_COMMAND_WRITE_MEMORY
:
2015 MemoryWrite
= (DEBUG_DATA_WRITE_MEMORY
*) (DebugHeader
+ 1);
2017 // Copy data into one memory with 8-byte alignment address
2019 AlignedDataPtr
= ALIGN_POINTER ((UINT8
*) &MemoryWrite
->Data
, sizeof (UINT64
));
2020 if (AlignedDataPtr
!= (UINT8
*) &MemoryWrite
->Data
) {
2021 CopyMem (AlignedDataPtr
, (UINT8
*) &MemoryWrite
->Data
, MemoryWrite
->Count
* MemoryWrite
->Width
);
2023 CopyMemByWidth ((UINT8
*) (UINTN
) MemoryWrite
->Address
, AlignedDataPtr
, MemoryWrite
->Count
, MemoryWrite
->Width
);
2024 SendAckPacket (DEBUG_COMMAND_OK
);
2027 case DEBUG_COMMAND_READ_IO
:
2028 IoRead
= (DEBUG_DATA_READ_IO
*) (DebugHeader
+ 1);
2029 switch (IoRead
->Width
) {
2031 Data64
= IoRead8 ((UINTN
) IoRead
->Port
);
2034 Data64
= IoRead16 ((UINTN
) IoRead
->Port
);
2037 Data64
= IoRead32 ((UINTN
) IoRead
->Port
);
2040 Data64
= IoRead64 ((UINTN
) IoRead
->Port
);
2043 Data64
= (UINT64
) -1;
2045 Status
= SendDataResponsePacket ((UINT8
*) &Data64
, IoRead
->Width
, DebugHeader
);
2048 case DEBUG_COMMAND_WRITE_IO
:
2049 IoWrite
= (DEBUG_DATA_WRITE_IO
*) (DebugHeader
+ 1);
2050 switch (IoWrite
->Width
) {
2052 Data64
= IoWrite8 ((UINTN
) IoWrite
->Port
, *(UINT8
*) &IoWrite
->Data
);
2055 Data64
= IoWrite16 ((UINTN
) IoWrite
->Port
, *(UINT16
*) &IoWrite
->Data
);
2058 Data64
= IoWrite32 ((UINTN
) IoWrite
->Port
, *(UINT32
*) &IoWrite
->Data
);
2061 Data64
= IoWrite64 ((UINTN
) IoWrite
->Port
, *(UINT64
*) &IoWrite
->Data
);
2064 Data64
= (UINT64
) -1;
2066 SendAckPacket (DEBUG_COMMAND_OK
);
2069 case DEBUG_COMMAND_READ_ALL_REGISTERS
:
2070 Status
= SendDataResponsePacket ((UINT8
*) CpuContext
, sizeof (*CpuContext
), DebugHeader
);
2073 case DEBUG_COMMAND_READ_REGISTER
:
2074 RegisterRead
= (DEBUG_DATA_READ_REGISTER
*) (DebugHeader
+ 1);
2076 if (RegisterRead
->Index
<= SOFT_DEBUGGER_REGISTER_MAX
) {
2077 RegisterBuffer
= ArchReadRegisterBuffer (CpuContext
, RegisterRead
->Index
, &Width
);
2078 Status
= SendDataResponsePacket (RegisterBuffer
, Width
, DebugHeader
);
2080 Status
= RETURN_UNSUPPORTED
;
2084 case DEBUG_COMMAND_WRITE_REGISTER
:
2085 RegisterWrite
= (DEBUG_DATA_WRITE_REGISTER
*) (DebugHeader
+ 1);
2086 if (RegisterWrite
->Index
<= SOFT_DEBUGGER_REGISTER_MAX
) {
2087 RegisterBuffer
= ArchReadRegisterBuffer (CpuContext
, RegisterWrite
->Index
, &Width
);
2088 ASSERT (Width
== RegisterWrite
->Length
);
2089 CopyMem (RegisterBuffer
, RegisterWrite
->Data
, Width
);
2090 SendAckPacket (DEBUG_COMMAND_OK
);
2092 Status
= RETURN_UNSUPPORTED
;
2096 case DEBUG_COMMAND_ARCH_MODE
:
2097 Data8
= DEBUG_ARCH_SYMBOL
;
2098 Status
= SendDataResponsePacket ((UINT8
*) &Data8
, (UINT16
) sizeof (UINT8
), DebugHeader
);
2101 case DEBUG_COMMAND_READ_MSR
:
2102 MsrRegisterRead
= (DEBUG_DATA_READ_MSR
*) (DebugHeader
+ 1);
2103 Data64
= AsmReadMsr64 (MsrRegisterRead
->Index
);
2104 Status
= SendDataResponsePacket ((UINT8
*) &Data64
, (UINT16
) sizeof (UINT64
), DebugHeader
);
2107 case DEBUG_COMMAND_WRITE_MSR
:
2108 MsrRegisterWrite
= (DEBUG_DATA_WRITE_MSR
*) (DebugHeader
+ 1);
2109 AsmWriteMsr64 (MsrRegisterWrite
->Index
, MsrRegisterWrite
->Value
);
2110 SendAckPacket (DEBUG_COMMAND_OK
);
2113 case DEBUG_COMMAND_SET_DEBUG_SETTING
:
2114 Status
= SetDebugSetting ((DEBUG_DATA_SET_DEBUG_SETTING
*)(DebugHeader
+ 1));
2115 if (Status
== RETURN_SUCCESS
) {
2116 SendAckPacket (DEBUG_COMMAND_OK
);
2120 case DEBUG_COMMAND_GET_REVISION
:
2121 DebugAgentRevision
.Revision
= DEBUG_AGENT_REVISION
;
2122 DebugAgentRevision
.Capabilities
= DEBUG_AGENT_CAPABILITIES
;
2123 Status
= SendDataResponsePacket ((UINT8
*) &DebugAgentRevision
, (UINT16
) sizeof (DEBUG_DATA_RESPONSE_GET_REVISION
), DebugHeader
);
2126 case DEBUG_COMMAND_GET_EXCEPTION
:
2127 Exception
.ExceptionNum
= (UINT8
) Vector
;
2128 Exception
.ExceptionData
= (UINT32
) CpuContext
->ExceptionData
;
2129 Status
= SendDataResponsePacket ((UINT8
*) &Exception
, (UINT16
) sizeof (DEBUG_DATA_RESPONSE_GET_EXCEPTION
), DebugHeader
);
2132 case DEBUG_COMMAND_SET_VIEWPOINT
:
2133 SetViewPoint
= (DEBUG_DATA_SET_VIEWPOINT
*) (DebugHeader
+ 1);
2134 if (MultiProcessorDebugSupport()) {
2135 if (IsCpuStopped (SetViewPoint
->ViewPoint
)) {
2136 SetDebugViewPoint (SetViewPoint
->ViewPoint
);
2137 SendAckPacket (DEBUG_COMMAND_OK
);
2140 // If CPU is not halted
2142 SendAckPacket (DEBUG_COMMAND_NOT_SUPPORTED
);
2144 } else if (SetViewPoint
->ViewPoint
== 0) {
2145 SendAckPacket (DEBUG_COMMAND_OK
);
2148 SendAckPacket (DEBUG_COMMAND_NOT_SUPPORTED
);
2153 case DEBUG_COMMAND_GET_VIEWPOINT
:
2154 Data32
= mDebugMpContext
.ViewPointIndex
;
2155 SendDataResponsePacket((UINT8
*) &Data32
, (UINT16
) sizeof (UINT32
), DebugHeader
);
2158 case DEBUG_COMMAND_MEMORY_READY
:
2159 Data8
= (UINT8
) GetDebugFlag (DEBUG_AGENT_FLAG_MEMORY_READY
);
2160 SendDataResponsePacket (&Data8
, (UINT16
) sizeof (UINT8
), DebugHeader
);
2163 case DEBUG_COMMAND_DETACH
:
2164 SetHostAttached (FALSE
);
2165 SendAckPacket (DEBUG_COMMAND_OK
);
2168 case DEBUG_COMMAND_CPUID
:
2169 Cpuid
= (DEBUG_DATA_CPUID
*) (DebugHeader
+ 1);
2171 Cpuid
->Eax
, Cpuid
->Ecx
,
2172 &CpuidResponse
.Eax
, &CpuidResponse
.Ebx
,
2173 &CpuidResponse
.Ecx
, &CpuidResponse
.Edx
2175 SendDataResponsePacket ((UINT8
*) &CpuidResponse
, (UINT16
) sizeof (CpuidResponse
), DebugHeader
);
2178 case DEBUG_COMMAND_SEARCH_SIGNATURE
:
2179 SearchSignature
= (DEBUG_DATA_SEARCH_SIGNATURE
*) (DebugHeader
+ 1);
2180 if ((SearchSignature
->Alignment
!= 0) &&
2181 (SearchSignature
->Alignment
== GetPowerOfTwo32 (SearchSignature
->Alignment
))
2183 if (SearchSignature
->Positive
) {
2185 Data64
= ALIGN_VALUE ((UINTN
) SearchSignature
->Start
, SearchSignature
->Alignment
);
2186 Data64
<= SearchSignature
->Start
+ SearchSignature
->Count
- SearchSignature
->DataLength
;
2187 Data64
+= SearchSignature
->Alignment
2189 if (CompareMem ((VOID
*) (UINTN
) Data64
, &SearchSignature
->Data
, SearchSignature
->DataLength
) == 0) {
2193 if (Data64
> SearchSignature
->Start
+ SearchSignature
->Count
- SearchSignature
->DataLength
) {
2194 Data64
= (UINT64
) -1;
2198 Data64
= ALIGN_VALUE ((UINTN
) SearchSignature
->Start
- SearchSignature
->Alignment
, SearchSignature
->Alignment
);
2199 Data64
>= SearchSignature
->Start
- SearchSignature
->Count
;
2200 Data64
-= SearchSignature
->Alignment
2202 if (CompareMem ((VOID
*) (UINTN
) Data64
, &SearchSignature
->Data
, SearchSignature
->DataLength
) == 0) {
2206 if (Data64
< SearchSignature
->Start
- SearchSignature
->Count
) {
2207 Data64
= (UINT64
) -1;
2210 SendDataResponsePacket ((UINT8
*) &Data64
, (UINT16
) sizeof (Data64
), DebugHeader
);
2212 Status
= RETURN_UNSUPPORTED
;
2217 SendAckPacket (DEBUG_COMMAND_NOT_SUPPORTED
);
2221 if (Status
== RETURN_UNSUPPORTED
) {
2222 SendAckPacket (DEBUG_COMMAND_NOT_SUPPORTED
);
2223 } else if (Status
!= RETURN_SUCCESS
) {
2224 SendAckPacket (DEBUG_COMMAND_ABORT
);
2227 ReleaseMpSpinLock (&mDebugMpContext
.DebugPortSpinLock
);
2233 C function called in interrupt handler.
2235 @param[in] Vector Vector value of exception or interrutp.
2236 @param[in] CpuContext Pointer to save CPU context.
2243 IN DEBUG_CPU_CONTEXT
*CpuContext
2246 UINT8 InputCharacter
;
2249 BOOLEAN BreakReceived
;
2250 UINT32 ProcessorIndex
;
2251 UINT32 CurrentDebugTimerInitCount
;
2252 DEBUG_PORT_HANDLE Handle
;
2255 UINT32 IssuedViewPoint
;
2256 DEBUG_AGENT_EXCEPTION_BUFFER
*ExceptionBuffer
;
2260 IssuedViewPoint
= 0;
2261 BreakReceived
= FALSE
;
2263 if (mSkipBreakpoint
) {
2265 // If Skip Breakpoint flag is set, means communication is disturbed by hardware SMI, we need to ignore the break points in SMM
2267 if ((Vector
== DEBUG_INT1_VECTOR
) || (Vector
== DEBUG_INT3_VECTOR
)) {
2268 DebugPortWriteBuffer (GetDebugPortHandle(), (UINT8
*) mWarningMsgIngoreBreakpoint
, AsciiStrLen (mWarningMsgIngoreBreakpoint
));
2273 if (MultiProcessorDebugSupport()) {
2274 ProcessorIndex
= GetProcessorIndex ();
2276 // If this processor has alreay halted before, need to check it later
2278 if (IsCpuStopped (ProcessorIndex
)) {
2279 IssuedViewPoint
= ProcessorIndex
;
2283 if (IssuedViewPoint
== ProcessorIndex
&& GetDebugFlag (DEBUG_AGENT_FLAG_STEPPING
) != 1) {
2285 // Check if this exception is issued by Debug Agent itself
2286 // If yes, fill the debug agent exception buffer and LongJump() back to
2287 // the saved CPU content in CommandCommunication()
2289 if (GetDebugFlag (DEBUG_AGENT_FLAG_AGENT_IN_PROGRESS
) == 1) {
2290 DebugAgentMsgPrint (DEBUG_AGENT_ERROR
, "Debug agent meet one Exception, ExceptionNum is %d, EIP = 0x%x.\n", Vector
, (UINTN
)CpuContext
->Eip
);
2291 ExceptionBuffer
= (DEBUG_AGENT_EXCEPTION_BUFFER
*) (UINTN
) GetMailboxPointer()->ExceptionBufferPointer
;
2292 ExceptionBuffer
->ExceptionContent
.ExceptionNum
= (UINT8
) Vector
;
2293 ExceptionBuffer
->ExceptionContent
.ExceptionData
= (UINT32
) CpuContext
->ExceptionData
;
2294 LongJump ((BASE_LIBRARY_JUMP_BUFFER
*)(UINTN
)(ExceptionBuffer
), 1);
2298 if (MultiProcessorDebugSupport()) {
2300 // If RUN commmand is executing, wait for it done.
2302 while (mDebugMpContext
.RunCommandSet
) {
2307 Handle
= GetDebugPortHandle();
2308 BreakCause
= GetBreakCause (Vector
, CpuContext
);
2310 case DEBUG_INT1_VECTOR
:
2311 case DEBUG_INT3_VECTOR
:
2312 switch (BreakCause
) {
2313 case DEBUG_DATA_BREAK_CAUSE_SYSTEM_RESET
:
2314 if (AttachHost (BreakCause
, READ_PACKET_TIMEOUT
, &BreakReceived
) != RETURN_SUCCESS
) {
2316 // Try to connect HOST, return if fails
2320 CommandCommunication (Vector
, CpuContext
, BreakReceived
);
2323 case DEBUG_DATA_BREAK_CAUSE_STEPPING
:
2325 // Stepping is finished, send Ack package.
2327 if (MultiProcessorDebugSupport()) {
2328 mDebugMpContext
.BreakAtCpuIndex
= ProcessorIndex
;
2330 SendAckPacket (DEBUG_COMMAND_OK
);
2331 CommandCommunication (Vector
, CpuContext
, BreakReceived
);
2334 case DEBUG_DATA_BREAK_CAUSE_MEMORY_READY
:
2338 SendCommandAndWaitForAckOK (DEBUG_COMMAND_MEMORY_READY
, READ_PACKET_TIMEOUT
, &BreakReceived
, NULL
);
2339 CommandCommunication (Vector
, CpuContext
, BreakReceived
);
2342 case DEBUG_DATA_BREAK_CAUSE_IMAGE_LOAD
:
2343 case DEBUG_DATA_BREAK_CAUSE_IMAGE_UNLOAD
:
2345 // Set AL to DEBUG_AGENT_IMAGE_CONTINUE
2347 Al
= ArchReadRegisterBuffer (CpuContext
, SOFT_DEBUGGER_REGISTER_AX
, &Data8
);
2348 *Al
= DEBUG_AGENT_IMAGE_CONTINUE
;
2350 if (!IsHostAttached ()) {
2352 // If HOST is not connected for image load/unload, return
2357 // Continue to run the following common code
2360 case DEBUG_DATA_BREAK_CAUSE_HW_BREAKPOINT
:
2361 case DEBUG_DATA_BREAK_CAUSE_SW_BREAKPOINT
:
2364 // Send Break packet to HOST
2366 AcquireMpSpinLock (&mDebugMpContext
.DebugPortSpinLock
);
2368 // Only the first breaking processor could send BREAK_POINT to HOST
2370 if (IsFirstBreakProcessor (ProcessorIndex
)) {
2371 SendBreakPacketToHost (BreakCause
, ProcessorIndex
, &BreakReceived
);
2373 ReleaseMpSpinLock (&mDebugMpContext
.DebugPortSpinLock
);
2375 if (Vector
== DEBUG_INT3_VECTOR
) {
2377 // go back address located "0xCC"
2380 SavedEip
= CpuContext
->Eip
;
2381 CommandCommunication (Vector
, CpuContext
, BreakReceived
);
2382 if ((SavedEip
== CpuContext
->Eip
) &&
2383 (*(UINT8
*) (UINTN
) CpuContext
->Eip
== DEBUG_SW_BREAKPOINT_SYMBOL
)) {
2385 // If this is not a software breakpoint set by HOST,
2391 CommandCommunication (Vector
, CpuContext
, BreakReceived
);
2398 case DEBUG_TIMER_VECTOR
:
2400 AcquireMpSpinLock (&mDebugMpContext
.DebugPortSpinLock
);
2402 if (MultiProcessorDebugSupport()) {
2403 if (IsBsp (ProcessorIndex
)) {
2405 // If current processor is BSP, check Apic timer's init count if changed,
2406 // it may be re-written when switching BSP.
2407 // If it changed, re-initialize debug timer
2409 CurrentDebugTimerInitCount
= GetApicTimerInitCount ();
2410 if (mDebugMpContext
.DebugTimerInitCount
!= CurrentDebugTimerInitCount
) {
2411 InitializeDebugTimer ();
2415 if (!IsBsp (ProcessorIndex
) || mDebugMpContext
.IpiSentByAp
) {
2416 ReleaseMpSpinLock (&mDebugMpContext
.DebugPortSpinLock
);
2418 // If current processor is not BSP or this is one IPI sent by AP
2420 if (mDebugMpContext
.BreakAtCpuIndex
!= (UINT32
) (-1)) {
2421 CommandCommunication (Vector
, CpuContext
, FALSE
);
2425 // Clear EOI before exiting interrupt process routine.
2433 // Only BSP could run here
2437 // If there is data in debug port, will check whether it is break(attach/break-in) symbol,
2438 // If yes, go into communication mode with HOST.
2439 // If no, exit interrupt process.
2441 if (DebugReadBreakSymbol (Handle
, &InputCharacter
) == EFI_NOT_FOUND
) {
2445 if ((!IsHostAttached () && (InputCharacter
== DEBUG_STARTING_SYMBOL_ATTACH
)) ||
2446 (IsHostAttached () && (InputCharacter
== DEBUG_COMMAND_HALT
)) ||
2447 (IsHostAttached () && (InputCharacter
== DEBUG_COMMAND_GO
))
2449 DebugAgentMsgPrint (DEBUG_AGENT_VERBOSE
, "Received data [%02x]\n", InputCharacter
);
2451 // Ack OK for break-in symbol
2453 SendAckPacket (DEBUG_COMMAND_OK
);
2456 // If receive GO command in Debug Timer, means HOST may lost ACK packet before.
2458 if (InputCharacter
== DEBUG_COMMAND_GO
) {
2462 if (!IsHostAttached ()) {
2464 // Try to attach HOST, if no ack received after 200ms, return
2466 if (AttachHost (BreakCause
, READ_PACKET_TIMEOUT
, &BreakReceived
) != RETURN_SUCCESS
) {
2471 if (MultiProcessorDebugSupport()) {
2472 if(FindNextPendingBreakCpu () != -1) {
2473 SetCpuBreakFlagByIndex (ProcessorIndex
, TRUE
);
2475 HaltOtherProcessors (ProcessorIndex
);
2478 ReleaseMpSpinLock (&mDebugMpContext
.DebugPortSpinLock
);
2479 CommandCommunication (Vector
, CpuContext
, BreakReceived
);
2480 AcquireMpSpinLock (&mDebugMpContext
.DebugPortSpinLock
);
2486 // Clear EOI before exiting interrupt process routine.
2490 ReleaseMpSpinLock (&mDebugMpContext
.DebugPortSpinLock
);
2495 if (Vector
<= DEBUG_EXCEPT_SIMD
) {
2496 if (BreakCause
== DEBUG_DATA_BREAK_CAUSE_STEPPING
) {
2498 // Stepping is finished, send Ack package.
2500 if (MultiProcessorDebugSupport()) {
2501 mDebugMpContext
.BreakAtCpuIndex
= ProcessorIndex
;
2503 SendAckPacket (DEBUG_COMMAND_OK
);
2506 // Exception occurs, send Break packet to HOST
2508 AcquireMpSpinLock (&mDebugMpContext
.DebugPortSpinLock
);
2510 // Only the first breaking processor could send BREAK_POINT to HOST
2512 if (IsFirstBreakProcessor (ProcessorIndex
)) {
2513 SendBreakPacketToHost (BreakCause
, ProcessorIndex
, &BreakReceived
);
2515 ReleaseMpSpinLock (&mDebugMpContext
.DebugPortSpinLock
);
2518 CommandCommunication (Vector
, CpuContext
, BreakReceived
);
2523 if (MultiProcessorDebugSupport()) {
2525 // Clear flag and wait for all processors run here
2527 SetIpiSentByApFlag (FALSE
);
2528 while (mDebugMpContext
.RunCommandSet
) {
2533 // Only current (view) processor could clean up AgentInProgress flag.
2535 if (mDebugMpContext
.ViewPointIndex
== ProcessorIndex
) {
2536 IssuedViewPoint
= mDebugMpContext
.ViewPointIndex
;
2540 if (IssuedViewPoint
== ProcessorIndex
&& GetDebugFlag (DEBUG_AGENT_FLAG_STEPPING
) != 1) {
2542 // If the command is not stepping, clean up AgentInProgress flag
2544 SetDebugFlag (DEBUG_AGENT_FLAG_AGENT_IN_PROGRESS
, 0);