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 CHAR8 mErrorMsgVersionAlert
[] = "\rThe SourceLevelDebugPkg you are using requires a newer version of the Intel(R) UDK Debugger Tool.\r\n";
22 CHAR8 mErrorMsgSendInitPacket
[] = "\rSend INIT break packet and try to connect the HOST (Intel(R) UDK Debugger Tool v1.4) ...\r\n";
23 CHAR8 mErrorMsgConnectOK
[] = "HOST connection is successful!\r\n";
24 CHAR8 mErrorMsgConnectFail
[] = "HOST connection is failed!\r\n";
25 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 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 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
++) {
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 (((DebugHeader
->Command
& DEBUG_COMMAND_RESPONSE
) == 0) &&
609 (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
);
617 // If one old command or response packet received, skip it
619 return EFI_DEVICE_ERROR
;
624 Check if HOST is attached based on Mailbox.
626 @retval TRUE HOST is attached.
627 @retval FALSE HOST is not attached.
635 return (BOOLEAN
) (GetDebugFlag (DEBUG_AGENT_FLAG_HOST_ATTACHED
) == 1);
639 Set HOST connect flag in Mailbox.
641 @param[in] Attached Attach status.
649 DebugAgentMsgPrint (DEBUG_AGENT_INFO
, "Attach status is %d\n", Attached
);
650 SetDebugFlag (DEBUG_AGENT_FLAG_HOST_ATTACHED
, (UINT32
)Attached
);
654 Set debug setting of Debug Agent in Mailbox.
656 @param DebugSetting Pointer to Debug Setting defined by transfer protocol.
658 @retval RETURN_SUCCESS The setting is set successfully.
659 @retval RETURN_UNSUPPORTED The Key value is not supported.
664 IN DEBUG_DATA_SET_DEBUG_SETTING
*DebugSetting
667 RETURN_STATUS Status
;
669 Status
= RETURN_SUCCESS
;
670 switch (DebugSetting
->Key
) {
671 case DEBUG_AGENT_SETTING_SMM_ENTRY_BREAK
:
672 SetDebugFlag (DEBUG_AGENT_FLAG_BREAK_ON_NEXT_SMI
, DebugSetting
->Value
);
674 case DEBUG_AGENT_SETTING_PRINT_ERROR_LEVEL
:
675 SetDebugFlag (DEBUG_AGENT_FLAG_PRINT_ERROR_LEVEL
, DebugSetting
->Value
);
677 case DEBUG_AGENT_SETTING_BOOT_SCRIPT_ENTRY_BREAK
:
678 SetDebugFlag (DEBUG_AGENT_FLAG_BREAK_BOOT_SCRIPT
, DebugSetting
->Value
);
681 Status
= RETURN_UNSUPPORTED
;
689 @param[in] CpuContext Pointer to saved CPU context.
694 IN DEBUG_CPU_CONTEXT
*CpuContext
697 IA32_EFLAGS32
*Eflags
;
699 Eflags
= (IA32_EFLAGS32
*) &CpuContext
->Eflags
;
705 Exectue Stepping command.
707 @param[in] CpuContext Pointer to saved CPU context.
712 IN DEBUG_CPU_CONTEXT
*CpuContext
715 IA32_EFLAGS32
*Eflags
;
717 Eflags
= (IA32_EFLAGS32
*) &CpuContext
->Eflags
;
723 Set debug register for hardware breakpoint.
725 @param[in] CpuContext Pointer to saved CPU context.
726 @param[in] SetHwBreakpoint Hardware breakpoint to be set.
731 IN DEBUG_CPU_CONTEXT
*CpuContext
,
732 IN DEBUG_DATA_SET_HW_BREAKPOINT
*SetHwBreakpoint
738 RegisterIndex
= SetHwBreakpoint
->Type
.Index
;
743 * ((UINTN
*) &CpuContext
->Dr0
+ RegisterIndex
) = (UINTN
) SetHwBreakpoint
->Address
;
745 Dr7Value
= CpuContext
->Dr7
;
750 Dr7Value
|= 0x3 << (RegisterIndex
* 2);
754 Dr7Value
&= ~(0xf << (16 + RegisterIndex
* 4));
755 Dr7Value
|= (UINTN
) ((SetHwBreakpoint
->Type
.Length
<< 2) | SetHwBreakpoint
->Type
.Access
) << (16 + RegisterIndex
* 4);
761 CpuContext
->Dr7
= Dr7Value
;
765 Clear debug register for hardware breakpoint.
767 @param[in] CpuContext Pointer to saved CPU context.
768 @param[in] ClearHwBreakpoint Hardware breakpoint to be cleared.
773 IN DEBUG_CPU_CONTEXT
*CpuContext
,
774 IN DEBUG_DATA_CLEAR_HW_BREAKPOINT
*ClearHwBreakpoint
777 if ((ClearHwBreakpoint
->IndexMask
& BIT0
) != 0) {
779 CpuContext
->Dr7
&= ~(0x3 << 0);
781 if ((ClearHwBreakpoint
->IndexMask
& BIT1
) != 0) {
783 CpuContext
->Dr7
&= ~(0x3 << 2);
785 if ((ClearHwBreakpoint
->IndexMask
& BIT2
) != 0) {
787 CpuContext
->Dr7
&= ~(0x3 << 4);
789 if ((ClearHwBreakpoint
->IndexMask
& BIT3
) != 0) {
791 CpuContext
->Dr7
&= ~(0x3 << 6);
797 Return the offset of FP / MMX / XMM registers in the FPU saved state by register index.
799 @param[in] Index Register index.
800 @param[out] Width Register width returned.
802 @return Offset in the FPU Save State.
806 ArchReadFxStatOffset (
811 if (Index
< SOFT_DEBUGGER_REGISTER_ST0
) {
813 case SOFT_DEBUGGER_REGISTER_FP_FCW
:
814 *Width
= (UINT8
) sizeof (UINT16
);
815 return OFFSET_OF(DEBUG_DATA_FX_SAVE_STATE
, Fcw
);
817 case SOFT_DEBUGGER_REGISTER_FP_FSW
:
818 *Width
= (UINT8
) sizeof (UINT16
);
819 return OFFSET_OF(DEBUG_DATA_FX_SAVE_STATE
, Fsw
);
821 case SOFT_DEBUGGER_REGISTER_FP_FTW
:
822 *Width
= (UINT8
) sizeof (UINT16
);
823 return OFFSET_OF(DEBUG_DATA_FX_SAVE_STATE
, Ftw
);
825 case SOFT_DEBUGGER_REGISTER_FP_OPCODE
:
826 *Width
= (UINT8
) sizeof (UINT16
);
827 return OFFSET_OF(DEBUG_DATA_FX_SAVE_STATE
, Opcode
);
829 case SOFT_DEBUGGER_REGISTER_FP_EIP
:
830 *Width
= (UINT8
) sizeof (UINT32
);
831 return OFFSET_OF(DEBUG_DATA_FX_SAVE_STATE
, Eip
);
833 case SOFT_DEBUGGER_REGISTER_FP_CS
:
834 *Width
= (UINT8
) sizeof (UINT16
);
835 return OFFSET_OF(DEBUG_DATA_FX_SAVE_STATE
, Cs
);
837 case SOFT_DEBUGGER_REGISTER_FP_DATAOFFSET
:
838 *Width
= (UINT8
) sizeof (UINT32
);
839 return OFFSET_OF(DEBUG_DATA_FX_SAVE_STATE
, DataOffset
);
841 case SOFT_DEBUGGER_REGISTER_FP_DS
:
842 *Width
= (UINT8
) sizeof (UINT16
);
843 return OFFSET_OF(DEBUG_DATA_FX_SAVE_STATE
, Ds
);
845 case SOFT_DEBUGGER_REGISTER_FP_MXCSR
:
846 *Width
= (UINT8
) sizeof (UINT32
);
847 return OFFSET_OF(DEBUG_DATA_FX_SAVE_STATE
, Mxcsr
);
849 case SOFT_DEBUGGER_REGISTER_FP_MXCSR_MASK
:
850 *Width
= (UINT8
) sizeof (UINT32
);
851 return OFFSET_OF(DEBUG_DATA_FX_SAVE_STATE
, Mxcsr_Mask
);
855 if (Index
<= SOFT_DEBUGGER_REGISTER_ST7
) {
857 } else if (Index
<= SOFT_DEBUGGER_REGISTER_XMM15
) {
864 Index
-= SOFT_DEBUGGER_REGISTER_MM0
- SOFT_DEBUGGER_REGISTER_ST0
;
867 return OFFSET_OF (DEBUG_DATA_FX_SAVE_STATE
, St0Mm0
) + (Index
- SOFT_DEBUGGER_REGISTER_ST0
) * 16;
871 Return the pointer of the register value in the CPU saved context.
873 @param[in] CpuContext Pointer to saved CPU context.
874 @param[in] Index Register index value.
875 @param[out] Width Data width to read.
877 @return The pointer in the CPU saved context.
881 ArchReadRegisterBuffer (
882 IN DEBUG_CPU_CONTEXT
*CpuContext
,
889 if (Index
< SOFT_DEBUGGER_REGISTER_FP_BASE
) {
890 Buffer
= (UINT8
*) CpuContext
+ OFFSET_OF (DEBUG_CPU_CONTEXT
, Dr0
) + Index
* sizeof (UINTN
);
891 *Width
= (UINT8
) sizeof (UINTN
);
894 // FPU/MMX/XMM registers
896 Buffer
= (UINT8
*) CpuContext
+ OFFSET_OF (DEBUG_CPU_CONTEXT
, FxSaveState
) + ArchReadFxStatOffset (Index
, Width
);
903 Send the packet without data to HOST.
905 @param[in] CommandType Type of Command.
906 @param[in] SequenceNo Sequence number.
910 SendPacketWithoutData (
911 IN UINT8 CommandType
,
915 DEBUG_PACKET_HEADER DebugHeader
;
916 DEBUG_PORT_HANDLE Handle
;
918 Handle
= GetDebugPortHandle();
920 DebugHeader
.StartSymbol
= DEBUG_STARTING_SYMBOL_NORMAL
;
921 DebugHeader
.Command
= CommandType
;
922 DebugHeader
.Length
= sizeof (DEBUG_PACKET_HEADER
);
923 DebugHeader
.SequenceNo
= SequenceNo
;
925 DebugHeader
.Crc
= CalculateCrc16 ((UINT8
*)&DebugHeader
, sizeof (DEBUG_PACKET_HEADER
), 0);
927 DebugAgentDataMsgPrint (DEBUG_AGENT_VERBOSE
, TRUE
, (UINT8
*) &DebugHeader
, DebugHeader
.Length
);
928 DebugPortWriteBuffer (Handle
, (UINT8
*) &DebugHeader
, DebugHeader
.Length
);
932 Send acknowledge packet to HOST.
934 @param[in] AckCommand Type of Acknowledge packet.
943 DEBUG_AGENT_MAILBOX
*Mailbox
;
945 if (AckCommand
!= DEBUG_COMMAND_OK
) {
947 // This is not ACK OK packet
949 DebugAgentMsgPrint (DEBUG_AGENT_ERROR
, "Send ACK(%d)\n", AckCommand
);
951 Mailbox
= GetMailboxPointer();
952 SequenceNo
= Mailbox
->HostSequenceNo
;
953 DebugAgentMsgPrint (DEBUG_AGENT_INFO
, "SendAckPacket: SequenceNo = %x\n", SequenceNo
);
954 SendPacketWithoutData (AckCommand
, SequenceNo
);
955 UpdateMailboxContent (Mailbox
, DEBUG_MAILBOX_LAST_ACK
, AckCommand
);
959 Receive valid packet from HOST.
961 @param[out] InputPacket Buffer to receive packet.
962 @param[out] BreakReceived TRUE means break-in symbol received.
963 FALSE means break-in symbol not received.
964 @param[out] IncompatibilityFlag If IncompatibilityFlag is not NULL, return
965 TRUE: Compatible packet received.
966 FALSE: Incompatible packet received.
967 @param[in] Timeout Time out value to wait for acknowlege from HOST.
968 The unit is microsecond.
969 @param[in] SkipStartSymbol TRUE: Skip time out when reading start symbol.
970 FALSE: Does not Skip time out when reading start symbol.
972 @retval RETURN_SUCCESS A valid package was reveived in InputPacket.
973 @retval RETURN_TIMEOUT Timeout occurs.
978 OUT UINT8
*InputPacket
,
979 OUT BOOLEAN
*BreakReceived
,
980 OUT BOOLEAN
*IncompatibilityFlag
, OPTIONAL
982 IN BOOLEAN SkipStartSymbol
985 DEBUG_PACKET_HEADER
*DebugHeader
;
987 DEBUG_PORT_HANDLE Handle
;
989 UINTN TimeoutForStartSymbol
;
991 Handle
= GetDebugPortHandle();
992 if (SkipStartSymbol
) {
993 TimeoutForStartSymbol
= 0;
995 TimeoutForStartSymbol
= Timeout
;
998 DebugHeader
= (DEBUG_PACKET_HEADER
*) InputPacket
;
1001 // Find the valid start symbol
1003 Received
= DebugPortReadBuffer (Handle
, &DebugHeader
->StartSymbol
, sizeof (DebugHeader
->StartSymbol
), TimeoutForStartSymbol
);
1004 if (Received
< sizeof (DebugHeader
->StartSymbol
)) {
1005 DebugAgentMsgPrint (DEBUG_AGENT_WARNING
, "DebugPortReadBuffer(StartSymbol) timeout\n");
1006 return RETURN_TIMEOUT
;
1009 if (DebugHeader
->StartSymbol
!= DEBUG_STARTING_SYMBOL_NORMAL
) {
1010 DebugAgentMsgPrint (DEBUG_AGENT_WARNING
, "Invalid start symbol received [%02x]\n", DebugHeader
->StartSymbol
);
1015 // Read Package header till field Length
1017 Received
= DebugPortReadBuffer (
1019 (UINT8
*)DebugHeader
+ OFFSET_OF (DEBUG_PACKET_HEADER
, Command
),
1020 OFFSET_OF (DEBUG_PACKET_HEADER
, Length
) + sizeof (DebugHeader
->Length
) - sizeof (DebugHeader
->StartSymbol
),
1023 if (Received
== 0) {
1024 DebugAgentMsgPrint (DEBUG_AGENT_ERROR
, "DebugPortReadBuffer(Command) timeout\n");
1025 return RETURN_TIMEOUT
;
1027 if (DebugHeader
->Length
< sizeof (DEBUG_PACKET_HEADER
)) {
1028 if (IncompatibilityFlag
!= NULL
) {
1030 // This is one old version debug packet format, set Incompatibility flag
1032 *IncompatibilityFlag
= TRUE
;
1035 // Skip the bad small packet
1041 // Read the payload data include the CRC field
1043 Received
= DebugPortReadBuffer (Handle
, &DebugHeader
->SequenceNo
, (UINT8
) (DebugHeader
->Length
- OFFSET_OF (DEBUG_PACKET_HEADER
, SequenceNo
)), Timeout
);
1044 if (Received
== 0) {
1045 DebugAgentMsgPrint (DEBUG_AGENT_ERROR
, "DebugPortReadBuffer(SequenceNo) timeout\n");
1046 return RETURN_TIMEOUT
;
1049 // Calculate the CRC of Debug Packet
1051 Crc
= DebugHeader
->Crc
;
1052 DebugHeader
->Crc
= 0;
1053 if (Crc
== CalculateCrc16 ((UINT8
*) DebugHeader
, DebugHeader
->Length
, 0)) {
1056 DebugAgentMsgPrint (DEBUG_AGENT_WARNING
, "CRC Error (received CRC is %x)\n", Crc
);
1057 DebugAgentDataMsgPrint (DEBUG_AGENT_VERBOSE
, FALSE
, (UINT8
*) DebugHeader
, DebugHeader
->Length
);
1061 DebugAgentDataMsgPrint (DEBUG_AGENT_VERBOSE
, FALSE
, (UINT8
*) DebugHeader
, DebugHeader
->Length
);
1063 return RETURN_SUCCESS
;
1067 Receive acknowledge packet OK from HOST in specified time.
1069 @param[in] Command The command type issued by TARGET.
1070 @param[in] Timeout Time out value to wait for acknowlege from HOST.
1071 The unit is microsecond.
1072 @param[out] BreakReceived If BreakReceived is not NULL,
1073 TRUE is retured if break-in symbol received.
1074 FALSE is retured if break-in symbol not received.
1075 @param[out] IncompatibilityFlag If IncompatibilityFlag is not NULL, return
1076 TRUE: Compatible packet received.
1077 FALSE: Incompatible packet received.
1079 @retval RETRUEN_SUCCESS Succeed to receive acknowlege packet from HOST,
1080 the type of acknowlege packet saved in Ack.
1081 @retval RETURN_TIMEOUT Specified timeout value was up.
1085 SendCommandAndWaitForAckOK (
1088 OUT BOOLEAN
*BreakReceived
, OPTIONAL
1089 OUT BOOLEAN
*IncompatibilityFlag OPTIONAL
1092 RETURN_STATUS Status
;
1093 UINT8 InputPacketBuffer
[DEBUG_DATA_UPPER_LIMIT
];
1094 DEBUG_PACKET_HEADER
*DebugHeader
;
1096 UINT8 HostSequenceNo
;
1100 DebugHeader
= (DEBUG_PACKET_HEADER
*) InputPacketBuffer
;
1101 Status
= RETURN_TIMEOUT
;
1102 while (RetryCount
> 0) {
1103 SequenceNo
= GetMailboxPointer()->SequenceNo
;
1104 HostSequenceNo
= GetMailboxPointer()->HostSequenceNo
;
1105 SendPacketWithoutData (Command
, SequenceNo
);
1106 Status
= ReceivePacket ((UINT8
*) DebugHeader
, BreakReceived
, IncompatibilityFlag
, Timeout
, FALSE
);
1107 if (Status
== RETURN_TIMEOUT
) {
1108 if (Command
== DEBUG_COMMAND_INIT_BREAK
) {
1111 DebugAgentMsgPrint (DEBUG_AGENT_WARNING
, "TARGET: Timeout when waiting for ACK packet.\n");
1115 ASSERT_EFI_ERROR (Status
);
1117 // Status == RETURN_SUCCESS
1119 if (DebugHeader
->Command
== DEBUG_COMMAND_OK
&& DebugHeader
->SequenceNo
== SequenceNo
) {
1123 UpdateMailboxContent (GetMailboxPointer(), DEBUG_MAILBOX_SEQUENCE_NO_INDEX
, ++SequenceNo
);
1126 if (DebugHeader
->Command
== DEBUG_COMMAND_GO
&& (DebugHeader
->SequenceNo
== HostSequenceNo
|| Command
== DEBUG_COMMAND_INIT_BREAK
)) {
1130 if (Command
== DEBUG_COMMAND_INIT_BREAK
) {
1131 DebugAgentMsgPrint (DEBUG_AGENT_WARNING
, "TARGET: Receive GO() in last boot\n");
1133 SendPacketWithoutData (DEBUG_COMMAND_OK
, DebugHeader
->SequenceNo
);
1137 ASSERT (Command
== DEBUG_COMMAND_INIT_BREAK
);
1142 Get current break cause.
1144 @param[in] Vector Vector value of exception or interrupt.
1145 @param[in] CpuContext Pointer to save CPU context.
1147 @return The type of break cause defined by XXXX
1153 IN DEBUG_CPU_CONTEXT
*CpuContext
1158 Cause
= DEBUG_DATA_BREAK_CAUSE_UNKNOWN
;
1161 case DEBUG_INT1_VECTOR
:
1162 case DEBUG_INT3_VECTOR
:
1164 if (Vector
== DEBUG_INT1_VECTOR
) {
1168 if ((CpuContext
->Dr6
& BIT14
) != 0) {
1169 Cause
= DEBUG_DATA_BREAK_CAUSE_STEPPING
;
1171 // If it's single step, no need to check DR0, to ensure single step work in PeCoffExtraActionLib
1172 // (right after triggering a breakpoint to report image load/unload).
1177 Cause
= DEBUG_DATA_BREAK_CAUSE_HW_BREAKPOINT
;
1183 Cause
= DEBUG_DATA_BREAK_CAUSE_SW_BREAKPOINT
;
1186 switch (CpuContext
->Dr0
) {
1187 case IMAGE_LOAD_SIGNATURE
:
1188 case IMAGE_UNLOAD_SIGNATURE
:
1190 if (CpuContext
->Dr3
== IO_PORT_BREAKPOINT_ADDRESS
) {
1192 Cause
= (UINT8
) ((CpuContext
->Dr0
== IMAGE_LOAD_SIGNATURE
) ?
1193 DEBUG_DATA_BREAK_CAUSE_IMAGE_LOAD
: DEBUG_DATA_BREAK_CAUSE_IMAGE_UNLOAD
);
1197 case SOFT_INTERRUPT_SIGNATURE
:
1199 if (CpuContext
->Dr1
== MEMORY_READY_SIGNATURE
) {
1200 Cause
= DEBUG_DATA_BREAK_CAUSE_MEMORY_READY
;
1201 CpuContext
->Dr0
= 0;
1202 } else if (CpuContext
->Dr1
== SYSTEM_RESET_SIGNATURE
) {
1203 Cause
= DEBUG_DATA_BREAK_CAUSE_SYSTEM_RESET
;
1204 CpuContext
->Dr0
= 0;
1215 case DEBUG_TIMER_VECTOR
:
1216 Cause
= DEBUG_DATA_BREAK_CAUSE_USER_HALT
;
1221 if (GetDebugFlag (DEBUG_AGENT_FLAG_STEPPING
) == 1) {
1223 // If stepping command is executing
1225 Cause
= DEBUG_DATA_BREAK_CAUSE_STEPPING
;
1227 Cause
= DEBUG_DATA_BREAK_CAUSE_EXCEPTION
;
1237 Copy memory from source to destination with specified width.
1239 @param[out] Dest A pointer to the destination buffer of the memory copy.
1240 @param[in] Src A pointer to the source buffer of the memory copy.
1241 @param[in] Count The number of data with specified width to copy from source to destination.
1242 @param[in] Width Data width in byte.
1263 // Copy memory from tail to avoid memory overlap
1265 Destination
= Dest
+ (Count
- 1) * Width
;
1266 Source
= Src
+ (Count
- 1) * Width
;
1270 while (Count
-- != 0) {
1273 *(UINT8
*) Destination
= MmioRead8 ((UINTN
) Source
);
1276 *(UINT16
*) Destination
= MmioRead16 ((UINTN
) Source
);
1279 *(UINT32
*) Destination
= MmioRead32 ((UINTN
) Source
);
1282 *(UINT64
*) Destination
= MmioRead64 ((UINTN
) Source
);
1288 Destination
+= Step
;
1293 Read memory with speicifed width and send packet with response data to HOST.
1295 @param[in] Data Pointer to response data buffer.
1296 @param[in] Count The number of data with specified Width.
1297 @param[in] Width Data width in byte.
1299 @retval RETURN_SUCCESS Response data was sent successfully.
1303 ReadMemoryAndSendResponsePacket (
1309 RETURN_STATUS Status
;
1310 DEBUG_PACKET_HEADER
*DebugHeader
;
1312 DEBUG_PACKET_HEADER
*AckDebugHeader
;
1313 UINT8 DebugPacket
[DEBUG_DATA_UPPER_LIMIT
+ sizeof (UINT64
) - 1];
1314 UINT8 InputPacketBuffer
[DEBUG_DATA_UPPER_LIMIT
];
1315 DEBUG_PORT_HANDLE Handle
;
1317 UINTN RemainingDataSize
;
1318 UINTN CurrentDataSize
;
1320 Handle
= GetDebugPortHandle();
1323 // Data is appended end of Debug Packet header, make sure data address
1324 // in Debug Packet 8-byte alignment always
1326 DebugHeader
= (DEBUG_PACKET_HEADER
*) (ALIGN_VALUE ((UINTN
)&DebugPacket
+ sizeof (DEBUG_PACKET_HEADER
), sizeof (UINT64
))
1327 - sizeof (DEBUG_PACKET_HEADER
));
1328 DebugHeader
->StartSymbol
= DEBUG_STARTING_SYMBOL_NORMAL
;
1330 RemainingDataSize
= Count
* Width
;
1332 SequenceNo
= GetMailboxPointer()->HostSequenceNo
;
1333 if (RemainingDataSize
<= DEBUG_DATA_MAXIMUM_REAL_DATA
) {
1335 // If the remaining data is less one real packet size, this is the last data packet
1337 CurrentDataSize
= RemainingDataSize
;
1339 DebugHeader
->Command
= DEBUG_COMMAND_OK
;
1342 // Data is too larger to be sent in one packet, calculate the actual data size could
1343 // be sent in one Maximum data packet
1345 CurrentDataSize
= (DEBUG_DATA_MAXIMUM_REAL_DATA
/ Width
) * Width
;
1347 DebugHeader
->Command
= DEBUG_COMMAND_IN_PROGRESS
;
1350 // Construct the rest Debug header
1352 DebugHeader
->Length
= (UINT8
)(CurrentDataSize
+ sizeof (DEBUG_PACKET_HEADER
));
1353 DebugHeader
->SequenceNo
= SequenceNo
;
1354 DebugHeader
->Crc
= 0;
1355 CopyMemByWidth ((UINT8
*)(DebugHeader
+ 1), Data
, (UINT16
) CurrentDataSize
/ Width
, Width
);
1357 // Calculate and fill the checksum, DebugHeader->Crc should be 0 before invoking CalculateCrc16 ()
1359 DebugHeader
->Crc
= CalculateCrc16 ((UINT8
*) DebugHeader
, DebugHeader
->Length
, 0);
1361 DebugAgentDataMsgPrint (DEBUG_AGENT_VERBOSE
, TRUE
, (UINT8
*) DebugHeader
, DebugHeader
->Length
);
1363 DebugPortWriteBuffer (Handle
, (UINT8
*) DebugHeader
, DebugHeader
->Length
);
1366 Status
= ReceivePacket (InputPacketBuffer
, NULL
, NULL
, READ_PACKET_TIMEOUT
, FALSE
);
1367 if (Status
== RETURN_TIMEOUT
) {
1368 DebugAgentMsgPrint (DEBUG_AGENT_WARNING
, "TARGET: Timeout in SendDataResponsePacket()\n");
1371 AckDebugHeader
= (DEBUG_PACKET_HEADER
*) InputPacketBuffer
;
1372 SequenceNo
= AckDebugHeader
->SequenceNo
;
1373 if (AckDebugHeader
->Command
== DEBUG_COMMAND_OK
&&
1374 SequenceNo
== DebugHeader
->SequenceNo
&&
1377 // If this is the last packet, return RETURN_SUCCESS.
1379 return RETURN_SUCCESS
;
1381 if ((SequenceNo
== (UINT8
) (DebugHeader
->SequenceNo
+ 1)) && (AckDebugHeader
->Command
== DEBUG_COMMAND_CONTINUE
)) {
1383 // Calculate the rest data size
1385 Data
+= CurrentDataSize
;
1386 RemainingDataSize
-= CurrentDataSize
;
1387 UpdateMailboxContent (GetMailboxPointer(), DEBUG_MAILBOX_HOST_SEQUENCE_NO_INDEX
, (UINT8
) SequenceNo
);
1390 if (SequenceNo
>= DebugHeader
->SequenceNo
) {
1391 DebugAgentMsgPrint (DEBUG_AGENT_WARNING
, "TARGET: Received one old or new command(SequenceNo is %x, last SequenceNo is %x)\n", SequenceNo
, DebugHeader
->SequenceNo
);
1399 Send packet with response data to HOST.
1401 @param[in] Data Pointer to response data buffer.
1402 @param[in] DataSize Size of response data in byte.
1404 @retval RETURN_SUCCESS Response data was sent successfully.
1408 SendDataResponsePacket (
1413 return ReadMemoryAndSendResponsePacket (Data
, DataSize
, 1);
1417 Send break cause packet to HOST.
1419 @param[in] Vector Vector value of exception or interrutp.
1420 @param[in] CpuContext Pointer to save CPU context.
1422 @retval RETURN_SUCCESS Response data was sent successfully.
1423 @retval RETURN_DEVICE_ERROR Cannot receive DEBUG_COMMAND_OK from HOST.
1427 SendBreakCausePacket (
1429 IN DEBUG_CPU_CONTEXT
*CpuContext
1432 DEBUG_DATA_RESPONSE_BREAK_CAUSE DebugDataBreakCause
;
1434 DebugDataBreakCause
.StopAddress
= CpuContext
->Eip
;
1435 DebugDataBreakCause
.Cause
= GetBreakCause (Vector
, CpuContext
);
1437 return SendDataResponsePacket ((UINT8
*) &DebugDataBreakCause
, (UINT16
) sizeof (DEBUG_DATA_RESPONSE_BREAK_CAUSE
));
1441 Try to attach the HOST.
1443 Send init break packet to HOST:
1444 If no acknowlege received in specified Timeout, return RETURN_TIMEOUT.
1445 If received acknowlege, check the revision of HOST.
1446 Set Attach Flag if attach successfully.
1448 @param[in] BreakCause Break cause of this break event.
1449 @param[in] Timeout Time out value to wait for acknowlege from HOST.
1450 The unit is microsecond.
1451 @param[out] BreakReceived If BreakReceived is not NULL,
1452 TRUE is retured if break-in symbol received.
1453 FALSE is retured if break-in symbol not received.
1457 IN UINT8 BreakCause
,
1459 OUT BOOLEAN
*BreakReceived
1462 RETURN_STATUS Status
;
1463 DEBUG_PORT_HANDLE Handle
;
1464 BOOLEAN IncompatibilityFlag
;
1466 IncompatibilityFlag
= FALSE
;
1467 Handle
= GetDebugPortHandle();
1470 // Send init break and wait ack in Timeout
1472 DebugPortWriteBuffer (Handle
, (UINT8
*) mErrorMsgSendInitPacket
, AsciiStrLen (mErrorMsgSendInitPacket
));
1473 if (BreakCause
== DEBUG_DATA_BREAK_CAUSE_SYSTEM_RESET
) {
1474 Status
= SendCommandAndWaitForAckOK (DEBUG_COMMAND_INIT_BREAK
, Timeout
, BreakReceived
, &IncompatibilityFlag
);
1476 Status
= SendCommandAndWaitForAckOK (DEBUG_COMMAND_ATTACH_BREAK
, Timeout
, BreakReceived
, &IncompatibilityFlag
);
1478 if (IncompatibilityFlag
) {
1480 // If the incompatible Debug Packet received, the HOST should be running transfer protocol before DEBUG_AGENT_REVISION.
1481 // It could be UDK Debugger for Windows v1.1/v1.2 or for Linux v0.8/v1.2.
1483 DebugPortWriteBuffer (Handle
, (UINT8
*) mErrorMsgVersionAlert
, AsciiStrLen (mErrorMsgVersionAlert
));
1487 if (RETURN_ERROR (Status
)) {
1488 DebugPortWriteBuffer (Handle
, (UINT8
*) mErrorMsgConnectFail
, AsciiStrLen (mErrorMsgConnectFail
));
1490 DebugPortWriteBuffer (Handle
, (UINT8
*) mErrorMsgConnectOK
, AsciiStrLen (mErrorMsgConnectOK
));
1494 SetHostAttached (TRUE
);
1500 Send Break point packet to HOST.
1502 Only the first breaking processor could sent BREAK_POINT packet.
1504 @param[in] BreakCause Break cause of this break event.
1505 @param[in] ProcessorIndex Processor index value.
1506 @param[out] BreakReceived If BreakReceived is not NULL,
1507 TRUE is retured if break-in symbol received.
1508 FALSE is retured if break-in symbol not received.
1512 SendBreakPacketToHost (
1513 IN UINT8 BreakCause
,
1514 IN UINT32 ProcessorIndex
,
1515 OUT BOOLEAN
*BreakReceived
1518 UINT8 InputCharacter
;
1519 DEBUG_PORT_HANDLE Handle
;
1521 Handle
= GetDebugPortHandle();
1523 if (IsHostAttached ()) {
1524 DebugAgentMsgPrint (DEBUG_AGENT_INFO
, "processor[%x]:Send Break Packet to HOST.\n", ProcessorIndex
);
1525 SendCommandAndWaitForAckOK (DEBUG_COMMAND_BREAK_POINT
, READ_PACKET_TIMEOUT
, BreakReceived
, NULL
);
1527 DebugAgentMsgPrint (DEBUG_AGENT_INFO
, "processor[%x]:Try to attach HOST.\n", ProcessorIndex
);
1529 // If HOST is not attached, try to attach it firstly.
1532 // Poll Attach symbols from HOST and ack OK
1535 DebugPortReadBuffer (Handle
, &InputCharacter
, 1, 0);
1536 } while (InputCharacter
!= DEBUG_STARTING_SYMBOL_ATTACH
);
1537 SendAckPacket (DEBUG_COMMAND_OK
);
1540 // Try to attach HOST
1542 while (AttachHost (BreakCause
, 0, NULL
) != RETURN_SUCCESS
);
1548 The main function to process communication with HOST.
1550 It received the command packet from HOST, and sent response data packet to HOST.
1552 @param[in] Vector Vector value of exception or interrutp.
1553 @param[in, out] CpuContext Pointer to saved CPU context.
1554 @param[in] BreakReceived TRUE means break-in symbol received.
1555 FALSE means break-in symbol not received.
1559 CommandCommunication (
1561 IN OUT DEBUG_CPU_CONTEXT
*CpuContext
,
1562 IN BOOLEAN BreakReceived
1565 RETURN_STATUS Status
;
1566 UINT8 InputPacketBuffer
[DEBUG_DATA_UPPER_LIMIT
+ sizeof (UINT64
) - 1];
1567 DEBUG_PACKET_HEADER
*DebugHeader
;
1572 DEBUG_DATA_READ_MEMORY
*MemoryRead
;
1573 DEBUG_DATA_WRITE_MEMORY
*MemoryWrite
;
1574 DEBUG_DATA_READ_IO
*IoRead
;
1575 DEBUG_DATA_WRITE_IO
*IoWrite
;
1576 DEBUG_DATA_READ_REGISTER
*RegisterRead
;
1577 DEBUG_DATA_WRITE_REGISTER
*RegisterWrite
;
1578 UINT8
*RegisterBuffer
;
1579 DEBUG_DATA_READ_MSR
*MsrRegisterRead
;
1580 DEBUG_DATA_WRITE_MSR
*MsrRegisterWrite
;
1581 DEBUG_DATA_CPUID
*Cpuid
;
1582 DEBUG_DATA_RESPONSE_CPUID CpuidResponse
;
1583 DEBUG_DATA_SEARCH_SIGNATURE
*SearchSignature
;
1584 DEBUG_DATA_RESPONSE_GET_EXCEPTION Exception
;
1585 DEBUG_DATA_RESPONSE_GET_REVISION DebugAgentRevision
;
1586 DEBUG_DATA_SET_VIEWPOINT
*SetViewPoint
;
1587 BOOLEAN HaltDeferred
;
1588 UINT32 ProcessorIndex
;
1589 DEBUG_PORT_HANDLE Handle
;
1590 DEBUG_AGENT_EXCEPTION_BUFFER AgentExceptionBuffer
;
1591 UINT32 IssuedViewPoint
;
1592 DEBUG_AGENT_MAILBOX
*Mailbox
;
1593 UINT8
*AlignedDataPtr
;
1596 IssuedViewPoint
= 0;
1597 HaltDeferred
= BreakReceived
;
1599 if (MultiProcessorDebugSupport()) {
1600 ProcessorIndex
= GetProcessorIndex ();
1601 SetCpuStopFlagByIndex (ProcessorIndex
, TRUE
);
1602 if (mDebugMpContext
.ViewPointIndex
== ProcessorIndex
) {
1604 // Only the current view processor could set AgentInProgress Flag.
1606 IssuedViewPoint
= ProcessorIndex
;
1610 if (IssuedViewPoint
== ProcessorIndex
) {
1612 // Set AgentInProgress Flag.
1614 SetDebugFlag (DEBUG_AGENT_FLAG_AGENT_IN_PROGRESS
, 1);
1617 Handle
= GetDebugPortHandle();
1621 if (MultiProcessorDebugSupport()) {
1623 // Check if the current processor is HOST view point
1625 if (mDebugMpContext
.ViewPointIndex
!= ProcessorIndex
) {
1626 if (mDebugMpContext
.RunCommandSet
) {
1628 // If HOST view point sets RUN flag, run GO command to leave
1630 SetCpuStopFlagByIndex (ProcessorIndex
, FALSE
);
1631 CommandGo (CpuContext
);
1635 // Run into loop again
1643 AcquireMpSpinLock (&mDebugMpContext
.DebugPortSpinLock
);
1645 DebugHeader
=(DEBUG_PACKET_HEADER
*) InputPacketBuffer
;
1647 DebugAgentMsgPrint (DEBUG_AGENT_INFO
, "TARGET: Try to get command from HOST...\n");
1648 Status
= ReceivePacket ((UINT8
*)DebugHeader
, &BreakReceived
, NULL
, READ_PACKET_TIMEOUT
, TRUE
);
1649 if (Status
!= RETURN_SUCCESS
|| (DebugHeader
->Command
& DEBUG_COMMAND_RESPONSE
) != 0) {
1650 DebugAgentMsgPrint (DEBUG_AGENT_WARNING
, "TARGET: Get command[%x] sequenceno[%x] returned status is [%x] \n", DebugHeader
->Command
, DebugHeader
->SequenceNo
, Status
);
1651 DebugAgentMsgPrint (DEBUG_AGENT_WARNING
, "TARGET: Get command failed or it's response packet not expected! \n");
1652 ReleaseMpSpinLock (&mDebugMpContext
.DebugPortSpinLock
);
1656 Mailbox
= GetMailboxPointer ();
1657 if (DebugHeader
->SequenceNo
== Mailbox
->HostSequenceNo
) {
1658 DebugAgentMsgPrint (DEBUG_AGENT_WARNING
, "TARGET: Receive one old command[%x] agaist command[%x]\n", DebugHeader
->SequenceNo
, Mailbox
->HostSequenceNo
);
1659 SendAckPacket (Mailbox
->LastAck
);
1660 ReleaseMpSpinLock (&mDebugMpContext
.DebugPortSpinLock
);
1662 } else if (DebugHeader
->SequenceNo
== (UINT8
) (Mailbox
->HostSequenceNo
+ 1)) {
1663 UpdateMailboxContent (Mailbox
, DEBUG_MAILBOX_HOST_SEQUENCE_NO_INDEX
, (UINT8
) DebugHeader
->SequenceNo
);
1665 DebugAgentMsgPrint (DEBUG_AGENT_WARNING
, "Receive one invalid comamnd[%x] agaist command[%x]\n", DebugHeader
->SequenceNo
, Mailbox
->HostSequenceNo
);
1666 ReleaseMpSpinLock (&mDebugMpContext
.DebugPortSpinLock
);
1671 // Save CPU content before executing HOST commond
1673 UpdateMailboxContent (Mailbox
, DEBUG_MAILBOX_EXCEPTION_BUFFER_POINTER_INDEX
, (UINT64
)(UINTN
) &AgentExceptionBuffer
.JumpBuffer
);
1674 if (SetJump (&AgentExceptionBuffer
.JumpBuffer
) != 0) {
1676 // If HOST command failed, continue to wait for HOST's next command
1677 // If needed, agent could send exception info to HOST.
1679 SendAckPacket (DEBUG_COMMAND_ABORT
);
1680 ReleaseMpSpinLock (&mDebugMpContext
.DebugPortSpinLock
);
1684 DebugAgentMsgPrint (DEBUG_AGENT_INFO
, "Processor[%x]:Received one command(%x)\n", mDebugMpContext
.ViewPointIndex
, DebugHeader
->Command
);
1686 switch (DebugHeader
->Command
) {
1688 case DEBUG_COMMAND_HALT
:
1689 SendAckPacket (DEBUG_COMMAND_HALT_DEFERRED
);
1690 HaltDeferred
= TRUE
;
1691 BreakReceived
= FALSE
;
1692 Status
= RETURN_SUCCESS
;
1695 case DEBUG_COMMAND_RESET
:
1696 SendAckPacket (DEBUG_COMMAND_OK
);
1697 SendAckPacket (DEBUG_COMMAND_OK
);
1698 SendAckPacket (DEBUG_COMMAND_OK
);
1699 ReleaseMpSpinLock (&mDebugMpContext
.DebugPortSpinLock
);
1703 // Assume system resets in 2 seconds, otherwise send TIMEOUT packet.
1704 // PCD can be used if 2 seconds isn't long enough for some platforms.
1706 MicroSecondDelay (2000000);
1707 UpdateMailboxContent (Mailbox
, DEBUG_MAILBOX_HOST_SEQUENCE_NO_INDEX
, Mailbox
->HostSequenceNo
+ 1);
1708 SendAckPacket (DEBUG_COMMAND_TIMEOUT
);
1709 SendAckPacket (DEBUG_COMMAND_TIMEOUT
);
1710 SendAckPacket (DEBUG_COMMAND_TIMEOUT
);
1713 case DEBUG_COMMAND_GO
:
1714 CommandGo (CpuContext
);
1716 // Clear Dr0 to avoid to be recognized as IMAGE_LOAD/_UNLOAD again when hitting a breakpoint after GO
1717 // If HOST changed Dr0 before GO, we will not change Dr0 here
1719 Data8
= GetBreakCause (Vector
, CpuContext
);
1720 if (Data8
== DEBUG_DATA_BREAK_CAUSE_IMAGE_LOAD
|| Data8
== DEBUG_DATA_BREAK_CAUSE_IMAGE_UNLOAD
) {
1721 CpuContext
->Dr0
= 0;
1724 // Clear Stepping Flag
1726 SetDebugFlag (DEBUG_AGENT_FLAG_STEPPING
, 0);
1728 if (!HaltDeferred
) {
1730 // If no HALT command received when being in-active mode
1732 if (MultiProcessorDebugSupport()) {
1733 Data32
= FindNextPendingBreakCpu ();
1736 // If there are still others processors being in break state,
1737 // send OK packet to HOST to finish this go command
1739 SendAckPacket (DEBUG_COMMAND_OK
);
1742 // Set current view to the next breaking processor
1744 mDebugMpContext
.ViewPointIndex
= Data32
;
1745 mDebugMpContext
.BreakAtCpuIndex
= mDebugMpContext
.ViewPointIndex
;
1746 SetCpuBreakFlagByIndex (mDebugMpContext
.ViewPointIndex
, FALSE
);
1748 // Send break packet to HOST to let HOST break again
1750 SendBreakPacketToHost (DEBUG_DATA_BREAK_CAUSE_UNKNOWN
, mDebugMpContext
.BreakAtCpuIndex
, &BreakReceived
);
1752 // Continue to run into loop to read command packet from HOST
1754 ReleaseMpSpinLock (&mDebugMpContext
.DebugPortSpinLock
);
1759 // If no else processor break, set stop bitmask,
1760 // and set Running flag for all processors.
1762 SetCpuStopFlagByIndex (ProcessorIndex
, FALSE
);
1763 SetCpuRunningFlag (TRUE
);
1766 // Wait for all processors are in running state
1769 if (IsAllCpuRunning ()) {
1774 // Set BSP to be current view point.
1776 SetDebugViewPoint (mDebugMpContext
.BspIndex
);
1779 // Clear breaking processor index and running flag
1781 mDebugMpContext
.BreakAtCpuIndex
= (UINT32
) (-1);
1782 SetCpuRunningFlag (FALSE
);
1786 // Send OK packet to HOST to finish this go command
1788 SendAckPacket (DEBUG_COMMAND_OK
);
1790 ReleaseMpSpinLock (&mDebugMpContext
.DebugPortSpinLock
);
1792 if (!IsHostAttached()) {
1793 UpdateMailboxContent (Mailbox
, DEBUG_MAILBOX_SEQUENCE_NO_INDEX
, 0);
1794 UpdateMailboxContent (Mailbox
, DEBUG_MAILBOX_HOST_SEQUENCE_NO_INDEX
, 0);
1800 // If reveived HALT command, need to defer the GO command
1802 SendAckPacket (DEBUG_COMMAND_HALT_PROCESSED
);
1803 HaltDeferred
= FALSE
;
1805 Vector
= DEBUG_TIMER_VECTOR
;
1809 case DEBUG_COMMAND_BREAK_CAUSE
:
1811 if (MultiProcessorDebugSupport() && ProcessorIndex
!= mDebugMpContext
.BreakAtCpuIndex
) {
1812 Status
= SendBreakCausePacket (DEBUG_TIMER_VECTOR
, CpuContext
);
1815 Status
= SendBreakCausePacket (Vector
, CpuContext
);
1820 case DEBUG_COMMAND_SET_HW_BREAKPOINT
:
1821 SetDebugRegister (CpuContext
, (DEBUG_DATA_SET_HW_BREAKPOINT
*) (DebugHeader
+ 1));
1822 SendAckPacket (DEBUG_COMMAND_OK
);
1825 case DEBUG_COMMAND_CLEAR_HW_BREAKPOINT
:
1826 ClearDebugRegister (CpuContext
, (DEBUG_DATA_CLEAR_HW_BREAKPOINT
*) (DebugHeader
+ 1));
1827 SendAckPacket (DEBUG_COMMAND_OK
);
1830 case DEBUG_COMMAND_SINGLE_STEPPING
:
1831 CommandStepping (CpuContext
);
1833 // Clear Dr0 to avoid to be recognized as IMAGE_LOAD/_UNLOAD again when hitting a breakpoint after GO
1834 // If HOST changed Dr0 before GO, we will not change Dr0 here
1836 Data8
= GetBreakCause (Vector
, CpuContext
);
1837 if (Data8
== DEBUG_DATA_BREAK_CAUSE_IMAGE_LOAD
|| Data8
== DEBUG_DATA_BREAK_CAUSE_IMAGE_UNLOAD
) {
1838 CpuContext
->Dr0
= 0;
1841 mDebugMpContext
.BreakAtCpuIndex
= (UINT32
) (-1);
1843 // Set Stepping Flag
1845 SetDebugFlag (DEBUG_AGENT_FLAG_STEPPING
, 1);
1846 ReleaseMpSpinLock (&mDebugMpContext
.DebugPortSpinLock
);
1848 // Executing stepping command directly without sending ACK packet,
1849 // ACK packet will be sent after stepping done.
1853 case DEBUG_COMMAND_SET_SW_BREAKPOINT
:
1854 Data64
= (UINTN
) (((DEBUG_DATA_SET_SW_BREAKPOINT
*) (DebugHeader
+ 1))->Address
);
1855 Data8
= *(UINT8
*) (UINTN
) Data64
;
1856 *(UINT8
*) (UINTN
) Data64
= DEBUG_SW_BREAKPOINT_SYMBOL
;
1857 Status
= SendDataResponsePacket ((UINT8
*) &Data8
, (UINT16
) sizeof (UINT8
));
1860 case DEBUG_COMMAND_READ_MEMORY
:
1861 MemoryRead
= (DEBUG_DATA_READ_MEMORY
*) (DebugHeader
+ 1);
1862 Status
= ReadMemoryAndSendResponsePacket ((UINT8
*) (UINTN
) MemoryRead
->Address
, MemoryRead
->Count
, MemoryRead
->Width
);
1865 case DEBUG_COMMAND_WRITE_MEMORY
:
1866 MemoryWrite
= (DEBUG_DATA_WRITE_MEMORY
*) (DebugHeader
+ 1);
1868 // Copy data into one memory with 8-byte alignment address
1870 AlignedDataPtr
= ALIGN_POINTER ((UINT8
*) &MemoryWrite
->Data
, sizeof (UINT64
));
1871 if (AlignedDataPtr
!= (UINT8
*) &MemoryWrite
->Data
) {
1872 CopyMem (AlignedDataPtr
, (UINT8
*) &MemoryWrite
->Data
, MemoryWrite
->Count
* MemoryWrite
->Width
);
1874 CopyMemByWidth ((UINT8
*) (UINTN
) MemoryWrite
->Address
, AlignedDataPtr
, MemoryWrite
->Count
, MemoryWrite
->Width
);
1875 SendAckPacket (DEBUG_COMMAND_OK
);
1878 case DEBUG_COMMAND_READ_IO
:
1879 IoRead
= (DEBUG_DATA_READ_IO
*) (DebugHeader
+ 1);
1880 switch (IoRead
->Width
) {
1882 Data64
= IoRead8 ((UINTN
) IoRead
->Port
);
1885 Data64
= IoRead16 ((UINTN
) IoRead
->Port
);
1888 Data64
= IoRead32 ((UINTN
) IoRead
->Port
);
1891 Data64
= IoRead64 ((UINTN
) IoRead
->Port
);
1894 Data64
= (UINT64
) -1;
1896 Status
= SendDataResponsePacket ((UINT8
*) &Data64
, IoRead
->Width
);
1899 case DEBUG_COMMAND_WRITE_IO
:
1900 IoWrite
= (DEBUG_DATA_WRITE_IO
*) (DebugHeader
+ 1);
1901 switch (IoWrite
->Width
) {
1903 Data64
= IoWrite8 ((UINTN
) IoWrite
->Port
, *(UINT8
*) &IoWrite
->Data
);
1906 Data64
= IoWrite16 ((UINTN
) IoWrite
->Port
, *(UINT16
*) &IoWrite
->Data
);
1909 Data64
= IoWrite32 ((UINTN
) IoWrite
->Port
, *(UINT32
*) &IoWrite
->Data
);
1912 Data64
= IoWrite64 ((UINTN
) IoWrite
->Port
, *(UINT64
*) &IoWrite
->Data
);
1915 Data64
= (UINT64
) -1;
1917 SendAckPacket (DEBUG_COMMAND_OK
);
1920 case DEBUG_COMMAND_READ_ALL_REGISTERS
:
1921 Status
= SendDataResponsePacket ((UINT8
*) CpuContext
, sizeof (*CpuContext
));
1924 case DEBUG_COMMAND_READ_REGISTER
:
1925 RegisterRead
= (DEBUG_DATA_READ_REGISTER
*) (DebugHeader
+ 1);
1927 if (RegisterRead
->Index
<= SOFT_DEBUGGER_REGISTER_MAX
) {
1928 RegisterBuffer
= ArchReadRegisterBuffer (CpuContext
, RegisterRead
->Index
, &Width
);
1929 Status
= SendDataResponsePacket (RegisterBuffer
, Width
);
1931 Status
= RETURN_UNSUPPORTED
;
1935 case DEBUG_COMMAND_WRITE_REGISTER
:
1936 RegisterWrite
= (DEBUG_DATA_WRITE_REGISTER
*) (DebugHeader
+ 1);
1937 if (RegisterWrite
->Index
<= SOFT_DEBUGGER_REGISTER_MAX
) {
1938 RegisterBuffer
= ArchReadRegisterBuffer (CpuContext
, RegisterWrite
->Index
, &Width
);
1939 ASSERT (Width
== RegisterWrite
->Length
);
1940 CopyMem (RegisterBuffer
, RegisterWrite
->Data
, Width
);
1941 SendAckPacket (DEBUG_COMMAND_OK
);
1943 Status
= RETURN_UNSUPPORTED
;
1947 case DEBUG_COMMAND_ARCH_MODE
:
1948 Data8
= DEBUG_ARCH_SYMBOL
;
1949 Status
= SendDataResponsePacket ((UINT8
*) &Data8
, (UINT16
) sizeof (UINT8
));
1952 case DEBUG_COMMAND_READ_MSR
:
1953 MsrRegisterRead
= (DEBUG_DATA_READ_MSR
*) (DebugHeader
+ 1);
1954 Data64
= AsmReadMsr64 (MsrRegisterRead
->Index
);
1955 Status
= SendDataResponsePacket ((UINT8
*) &Data64
, (UINT16
) sizeof (UINT64
));
1958 case DEBUG_COMMAND_WRITE_MSR
:
1959 MsrRegisterWrite
= (DEBUG_DATA_WRITE_MSR
*) (DebugHeader
+ 1);
1960 AsmWriteMsr64 (MsrRegisterWrite
->Index
, MsrRegisterWrite
->Value
);
1961 SendAckPacket (DEBUG_COMMAND_OK
);
1964 case DEBUG_COMMAND_SET_DEBUG_SETTING
:
1965 Status
= SetDebugSetting ((DEBUG_DATA_SET_DEBUG_SETTING
*)(DebugHeader
+ 1));
1966 if (Status
== RETURN_SUCCESS
) {
1967 SendAckPacket (DEBUG_COMMAND_OK
);
1971 case DEBUG_COMMAND_GET_REVISION
:
1972 DebugAgentRevision
.Revision
= DEBUG_AGENT_REVISION
;
1973 DebugAgentRevision
.Capabilities
= DEBUG_AGENT_CAPABILITIES
;
1974 Status
= SendDataResponsePacket ((UINT8
*) &DebugAgentRevision
, (UINT16
) sizeof (DEBUG_DATA_RESPONSE_GET_REVISION
));
1977 case DEBUG_COMMAND_GET_EXCEPTION
:
1978 Exception
.ExceptionNum
= (UINT8
) Vector
;
1979 Exception
.ExceptionData
= (UINT32
) CpuContext
->ExceptionData
;
1980 Status
= SendDataResponsePacket ((UINT8
*) &Exception
, (UINT16
) sizeof (DEBUG_DATA_RESPONSE_GET_EXCEPTION
));
1983 case DEBUG_COMMAND_SET_VIEWPOINT
:
1984 SetViewPoint
= (DEBUG_DATA_SET_VIEWPOINT
*) (DebugHeader
+ 1);
1985 if (MultiProcessorDebugSupport()) {
1986 if (IsCpuStopped (SetViewPoint
->ViewPoint
)) {
1987 SetDebugViewPoint (SetViewPoint
->ViewPoint
);
1988 SendAckPacket (DEBUG_COMMAND_OK
);
1991 // If CPU is not halted
1993 SendAckPacket (DEBUG_COMMAND_NOT_SUPPORTED
);
1995 } else if (SetViewPoint
->ViewPoint
== 0) {
1996 SendAckPacket (DEBUG_COMMAND_OK
);
1999 SendAckPacket (DEBUG_COMMAND_NOT_SUPPORTED
);
2004 case DEBUG_COMMAND_GET_VIEWPOINT
:
2005 Data32
= mDebugMpContext
.ViewPointIndex
;
2006 SendDataResponsePacket((UINT8
*) &Data32
, (UINT16
) sizeof (UINT32
));
2009 case DEBUG_COMMAND_MEMORY_READY
:
2010 Data8
= (UINT8
) GetDebugFlag (DEBUG_AGENT_FLAG_MEMORY_READY
);
2011 SendDataResponsePacket (&Data8
, (UINT16
) sizeof (UINT8
));
2014 case DEBUG_COMMAND_DETACH
:
2015 SetHostAttached (FALSE
);
2016 SendAckPacket (DEBUG_COMMAND_OK
);
2019 case DEBUG_COMMAND_CPUID
:
2020 Cpuid
= (DEBUG_DATA_CPUID
*) (DebugHeader
+ 1);
2022 Cpuid
->Eax
, Cpuid
->Ecx
,
2023 &CpuidResponse
.Eax
, &CpuidResponse
.Ebx
,
2024 &CpuidResponse
.Ecx
, &CpuidResponse
.Edx
2026 SendDataResponsePacket ((UINT8
*) &CpuidResponse
, (UINT16
) sizeof (CpuidResponse
));
2029 case DEBUG_COMMAND_SEARCH_SIGNATURE
:
2030 SearchSignature
= (DEBUG_DATA_SEARCH_SIGNATURE
*) (DebugHeader
+ 1);
2031 if ((SearchSignature
->Alignment
!= 0) &&
2032 (SearchSignature
->Alignment
== GetPowerOfTwo32 (SearchSignature
->Alignment
))
2034 if (SearchSignature
->Positive
) {
2036 Data64
= ALIGN_VALUE ((UINTN
) SearchSignature
->Start
, SearchSignature
->Alignment
);
2037 Data64
<= SearchSignature
->Start
+ SearchSignature
->Count
- SearchSignature
->DataLength
;
2038 Data64
+= SearchSignature
->Alignment
2040 if (CompareMem ((VOID
*) (UINTN
) Data64
, &SearchSignature
->Data
, SearchSignature
->DataLength
) == 0) {
2044 if (Data64
> SearchSignature
->Start
+ SearchSignature
->Count
- SearchSignature
->DataLength
) {
2045 Data64
= (UINT64
) -1;
2049 Data64
= ALIGN_VALUE ((UINTN
) SearchSignature
->Start
- SearchSignature
->Alignment
, SearchSignature
->Alignment
);
2050 Data64
>= SearchSignature
->Start
- SearchSignature
->Count
;
2051 Data64
-= SearchSignature
->Alignment
2053 if (CompareMem ((VOID
*) (UINTN
) Data64
, &SearchSignature
->Data
, SearchSignature
->DataLength
) == 0) {
2057 if (Data64
< SearchSignature
->Start
- SearchSignature
->Count
) {
2058 Data64
= (UINT64
) -1;
2061 SendDataResponsePacket ((UINT8
*) &Data64
, (UINT16
) sizeof (Data64
));
2063 Status
= RETURN_UNSUPPORTED
;
2068 SendAckPacket (DEBUG_COMMAND_NOT_SUPPORTED
);
2072 if (Status
== RETURN_UNSUPPORTED
) {
2073 SendAckPacket (DEBUG_COMMAND_NOT_SUPPORTED
);
2074 } else if (Status
!= RETURN_SUCCESS
) {
2075 SendAckPacket (DEBUG_COMMAND_ABORT
);
2078 ReleaseMpSpinLock (&mDebugMpContext
.DebugPortSpinLock
);
2084 C function called in interrupt handler.
2086 @param[in] Vector Vector value of exception or interrutp.
2087 @param[in] CpuContext Pointer to save CPU context.
2094 IN DEBUG_CPU_CONTEXT
*CpuContext
2097 UINT8 InputCharacter
;
2100 BOOLEAN BreakReceived
;
2101 UINT32 ProcessorIndex
;
2102 UINT32 CurrentDebugTimerInitCount
;
2103 DEBUG_PORT_HANDLE Handle
;
2106 UINT32 IssuedViewPoint
;
2107 DEBUG_AGENT_EXCEPTION_BUFFER
*ExceptionBuffer
;
2111 IssuedViewPoint
= 0;
2112 BreakReceived
= FALSE
;
2114 if (mSkipBreakpoint
) {
2116 // If Skip Breakpoint flag is set, means communication is disturbed by hardware SMI, we need to ignore the break points in SMM
2118 if ((Vector
== DEBUG_INT1_VECTOR
) || (Vector
== DEBUG_INT3_VECTOR
)) {
2119 DebugPortWriteBuffer (GetDebugPortHandle(), (UINT8
*) mWarningMsgIngoreBreakpoint
, AsciiStrLen (mWarningMsgIngoreBreakpoint
));
2124 if (MultiProcessorDebugSupport()) {
2125 ProcessorIndex
= GetProcessorIndex ();
2127 // If this processor has alreay halted before, need to check it later
2129 if (IsCpuStopped (ProcessorIndex
)) {
2130 IssuedViewPoint
= ProcessorIndex
;
2134 if (IssuedViewPoint
== ProcessorIndex
&& GetDebugFlag (DEBUG_AGENT_FLAG_STEPPING
) != 1) {
2136 // Check if this exception is issued by Debug Agent itself
2137 // If yes, fill the debug agent exception buffer and LongJump() back to
2138 // the saved CPU content in CommandCommunication()
2140 if (GetDebugFlag (DEBUG_AGENT_FLAG_AGENT_IN_PROGRESS
) == 1) {
2141 DebugAgentMsgPrint (DEBUG_AGENT_ERROR
, "Debug agent meet one Exception, ExceptionNum is %d, EIP = 0x%x.\n", Vector
, (UINTN
)CpuContext
->Eip
);
2142 ExceptionBuffer
= (DEBUG_AGENT_EXCEPTION_BUFFER
*) (UINTN
) GetMailboxPointer()->ExceptionBufferPointer
;
2143 ExceptionBuffer
->ExceptionContent
.ExceptionNum
= (UINT8
) Vector
;
2144 ExceptionBuffer
->ExceptionContent
.ExceptionData
= (UINT32
) CpuContext
->ExceptionData
;
2145 LongJump ((BASE_LIBRARY_JUMP_BUFFER
*)(UINTN
)(ExceptionBuffer
), 1);
2149 if (MultiProcessorDebugSupport()) {
2151 // If RUN commmand is executing, wait for it done.
2153 while (mDebugMpContext
.RunCommandSet
) {
2158 Handle
= GetDebugPortHandle();
2159 BreakCause
= GetBreakCause (Vector
, CpuContext
);
2161 case DEBUG_INT1_VECTOR
:
2162 case DEBUG_INT3_VECTOR
:
2163 switch (BreakCause
) {
2164 case DEBUG_DATA_BREAK_CAUSE_SYSTEM_RESET
:
2165 if (AttachHost (BreakCause
, READ_PACKET_TIMEOUT
, &BreakReceived
) != RETURN_SUCCESS
) {
2167 // Try to connect HOST, return if fails
2171 CommandCommunication (Vector
, CpuContext
, BreakReceived
);
2174 case DEBUG_DATA_BREAK_CAUSE_STEPPING
:
2176 // Stepping is finished, send Ack package.
2178 if (MultiProcessorDebugSupport()) {
2179 mDebugMpContext
.BreakAtCpuIndex
= ProcessorIndex
;
2181 SendAckPacket (DEBUG_COMMAND_OK
);
2182 CommandCommunication (Vector
, CpuContext
, BreakReceived
);
2185 case DEBUG_DATA_BREAK_CAUSE_MEMORY_READY
:
2189 SendCommandAndWaitForAckOK (DEBUG_COMMAND_MEMORY_READY
, READ_PACKET_TIMEOUT
, &BreakReceived
, NULL
);
2190 CommandCommunication (Vector
, CpuContext
, BreakReceived
);
2193 case DEBUG_DATA_BREAK_CAUSE_IMAGE_LOAD
:
2194 case DEBUG_DATA_BREAK_CAUSE_IMAGE_UNLOAD
:
2196 // Set AL to DEBUG_AGENT_IMAGE_CONTINUE
2198 Al
= ArchReadRegisterBuffer (CpuContext
, SOFT_DEBUGGER_REGISTER_AX
, &Data8
);
2199 *Al
= DEBUG_AGENT_IMAGE_CONTINUE
;
2201 if (!IsHostAttached ()) {
2203 // If HOST is not connected for image load/unload, return
2208 // Continue to run the following common code
2211 case DEBUG_DATA_BREAK_CAUSE_HW_BREAKPOINT
:
2212 case DEBUG_DATA_BREAK_CAUSE_SW_BREAKPOINT
:
2215 // Send Break packet to HOST
2217 AcquireMpSpinLock (&mDebugMpContext
.DebugPortSpinLock
);
2219 // Only the first breaking processor could send BREAK_POINT to HOST
2221 if (IsFirstBreakProcessor (ProcessorIndex
)) {
2222 SendBreakPacketToHost (BreakCause
, ProcessorIndex
, &BreakReceived
);
2224 ReleaseMpSpinLock (&mDebugMpContext
.DebugPortSpinLock
);
2226 if (Vector
== DEBUG_INT3_VECTOR
) {
2228 // go back address located "0xCC"
2231 SavedEip
= CpuContext
->Eip
;
2232 CommandCommunication (Vector
, CpuContext
, BreakReceived
);
2233 if ((SavedEip
== CpuContext
->Eip
) &&
2234 (*(UINT8
*) (UINTN
) CpuContext
->Eip
== DEBUG_SW_BREAKPOINT_SYMBOL
)) {
2236 // If this is not a software breakpoint set by HOST,
2242 CommandCommunication (Vector
, CpuContext
, BreakReceived
);
2249 case DEBUG_TIMER_VECTOR
:
2251 AcquireMpSpinLock (&mDebugMpContext
.DebugPortSpinLock
);
2253 if (MultiProcessorDebugSupport()) {
2254 if (IsBsp (ProcessorIndex
)) {
2256 // If current processor is BSP, check Apic timer's init count if changed,
2257 // it may be re-written when switching BSP.
2258 // If it changed, re-initialize debug timer
2260 CurrentDebugTimerInitCount
= GetApicTimerInitCount ();
2261 if (mDebugMpContext
.DebugTimerInitCount
!= CurrentDebugTimerInitCount
) {
2262 InitializeDebugTimer ();
2266 if (!IsBsp (ProcessorIndex
) || mDebugMpContext
.IpiSentByAp
) {
2267 ReleaseMpSpinLock (&mDebugMpContext
.DebugPortSpinLock
);
2269 // If current processor is not BSP or this is one IPI sent by AP
2271 if (mDebugMpContext
.BreakAtCpuIndex
!= (UINT32
) (-1)) {
2272 CommandCommunication (Vector
, CpuContext
, FALSE
);
2276 // Clear EOI before exiting interrupt process routine.
2284 // Only BSP could run here
2288 // If there is data in debug port, will check whether it is break(attach/break-in) symbol,
2289 // If yes, go into communication mode with HOST.
2290 // If no, exit interrupt process.
2292 if (DebugReadBreakSymbol (Handle
, &InputCharacter
) == EFI_NOT_FOUND
) {
2296 if ((!IsHostAttached () && (InputCharacter
== DEBUG_STARTING_SYMBOL_ATTACH
)) ||
2297 (IsHostAttached () && (InputCharacter
== DEBUG_COMMAND_HALT
)) ||
2298 (IsHostAttached () && (InputCharacter
== DEBUG_COMMAND_GO
))
2300 DebugAgentMsgPrint (DEBUG_AGENT_VERBOSE
, "Received data [%02x]\n", InputCharacter
);
2302 // Ack OK for break-in symbol
2304 SendAckPacket (DEBUG_COMMAND_OK
);
2307 // If receive GO command in Debug Timer, means HOST may lost ACK packet before.
2309 if (InputCharacter
== DEBUG_COMMAND_GO
) {
2313 if (!IsHostAttached ()) {
2315 // Try to attach HOST, if no ack received after 200ms, return
2317 if (AttachHost (BreakCause
, READ_PACKET_TIMEOUT
, &BreakReceived
) != RETURN_SUCCESS
) {
2322 if (MultiProcessorDebugSupport()) {
2323 if(FindNextPendingBreakCpu () != -1) {
2324 SetCpuBreakFlagByIndex (ProcessorIndex
, TRUE
);
2326 HaltOtherProcessors (ProcessorIndex
);
2329 ReleaseMpSpinLock (&mDebugMpContext
.DebugPortSpinLock
);
2330 CommandCommunication (Vector
, CpuContext
, BreakReceived
);
2331 AcquireMpSpinLock (&mDebugMpContext
.DebugPortSpinLock
);
2337 // Clear EOI before exiting interrupt process routine.
2341 ReleaseMpSpinLock (&mDebugMpContext
.DebugPortSpinLock
);
2346 if (Vector
<= DEBUG_EXCEPT_SIMD
) {
2347 if (BreakCause
== DEBUG_DATA_BREAK_CAUSE_STEPPING
) {
2349 // Stepping is finished, send Ack package.
2351 if (MultiProcessorDebugSupport()) {
2352 mDebugMpContext
.BreakAtCpuIndex
= ProcessorIndex
;
2354 SendAckPacket (DEBUG_COMMAND_OK
);
2357 // Exception occurs, send Break packet to HOST
2359 AcquireMpSpinLock (&mDebugMpContext
.DebugPortSpinLock
);
2361 // Only the first breaking processor could send BREAK_POINT to HOST
2363 if (IsFirstBreakProcessor (ProcessorIndex
)) {
2364 SendBreakPacketToHost (BreakCause
, ProcessorIndex
, &BreakReceived
);
2366 ReleaseMpSpinLock (&mDebugMpContext
.DebugPortSpinLock
);
2369 CommandCommunication (Vector
, CpuContext
, BreakReceived
);
2374 if (MultiProcessorDebugSupport()) {
2376 // Clear flag and wait for all processors run here
2378 SetIpiSentByApFlag (FALSE
);
2379 while (mDebugMpContext
.RunCommandSet
) {
2384 // Only current (view) processor could clean up AgentInProgress flag.
2386 if (mDebugMpContext
.ViewPointIndex
== ProcessorIndex
) {
2387 IssuedViewPoint
= mDebugMpContext
.ViewPointIndex
;
2391 if (IssuedViewPoint
== ProcessorIndex
&& GetDebugFlag (DEBUG_AGENT_FLAG_STEPPING
) != 1) {
2393 // If the command is not stepping, clean up AgentInProgress flag
2395 SetDebugFlag (DEBUG_AGENT_FLAG_AGENT_IN_PROGRESS
, 0);