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 - 2013, 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.3.1) ...\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.
217 // Check if address overflow firstly.
219 if ((MAX_ADDRESS
- (UINTN
)DosHdr
->e_lfanew
) > Pe32Data
) {
220 Hdr
.Pe32
= (EFI_IMAGE_NT_HEADERS32
*)(Pe32Data
+ (UINTN
)(DosHdr
->e_lfanew
));
221 if (Hdr
.Pe32
->Signature
== EFI_IMAGE_NT_SIGNATURE
) {
230 // DOS image header is not present, TE header is at the image base.
232 Hdr
.Pe32
= (EFI_IMAGE_NT_HEADERS32
*)Pe32Data
;
233 if ((Hdr
.Te
->Signature
== EFI_TE_IMAGE_HEADER_SIGNATURE
) &&
234 ((Hdr
.Te
->Machine
== IMAGE_FILE_MACHINE_I386
) || Hdr
.Te
->Machine
== IMAGE_FILE_MACHINE_X64
)) {
236 // It's TE image, it TE header and Machine type match
243 // Not found the image base, check the previous aligned address
245 Pe32Data
-= AlignSize
;
248 ImageContext
.ImageAddress
= Pe32Data
;
249 ImageContext
.PdbPointer
= PeCoffLoaderGetPdbPointer ((VOID
*) (UINTN
) ImageContext
.ImageAddress
);
250 PeCoffLoaderRelocateImageExtraAction (&ImageContext
);
254 Trigger one software interrupt to debug agent to handle it.
256 @param[in] Signature Software interrupt signature.
260 TriggerSoftInterrupt (
268 // Save Debug Register State
276 AsmWriteDr0 (SOFT_INTERRUPT_SIGNATURE
);
277 AsmWriteDr1 (Signature
);
280 // Do INT3 to communicate with HOST side
285 // Restore Debug Register State only when Host didn't change it inside exception handler.
286 // Dr registers can only be changed by setting the HW breakpoint.
294 Caculate Mailbox checksum and update the checksum field.
296 @param[in] Mailbox Debug Agent Mailbox pointer.
300 UpdateMailboxChecksum (
301 IN DEBUG_AGENT_MAILBOX
*Mailbox
304 Mailbox
->CheckSum
= CalculateCheckSum8 ((UINT8
*)Mailbox
, sizeof (DEBUG_AGENT_MAILBOX
) - 2);
308 Verify Mailbox checksum.
310 If checksum error, print debug message and run init dead loop.
312 @param[in] Mailbox Debug Agent Mailbox pointer.
316 VerifyMailboxChecksum (
317 IN DEBUG_AGENT_MAILBOX
*Mailbox
322 CheckSum
= CalculateCheckSum8 ((UINT8
*) Mailbox
, sizeof (DEBUG_AGENT_MAILBOX
) - 2);
324 // The checksum updating process may be disturbed by hardware SMI, we need to check CheckSum field
325 // and ToBeCheckSum field to validate the mail box.
327 if (CheckSum
!= Mailbox
->CheckSum
&& CheckSum
!= Mailbox
->ToBeCheckSum
) {
328 DEBUG ((EFI_D_ERROR
, "DebugAgent: Mailbox checksum error, stack or heap crashed!\n"));
329 DEBUG ((EFI_D_ERROR
, "DebugAgent: CheckSum = %x, Mailbox->CheckSum = %x, Mailbox->ToBeCheckSum = %x\n", CheckSum
, Mailbox
->CheckSum
, Mailbox
->ToBeCheckSum
));
335 Update Mailbox content by index.
337 @param[in] Mailbox Debug Agent Mailbox pointer.
338 @param[in] Index Mailbox content index.
339 @param[in] Value Value to be set into Mailbox.
343 UpdateMailboxContent (
344 IN DEBUG_AGENT_MAILBOX
*Mailbox
,
349 AcquireMpSpinLock (&mDebugMpContext
.MailboxSpinLock
);
351 case DEBUG_MAILBOX_DEBUG_FLAG_INDEX
:
352 Mailbox
->ToBeCheckSum
= Mailbox
->CheckSum
+ CalculateSum8 ((UINT8
*)&Mailbox
->DebugFlag
.Uint64
, sizeof(UINT64
))
353 - CalculateSum8 ((UINT8
*)&Value
, sizeof(UINT64
));
354 Mailbox
->DebugFlag
.Uint64
= Value
;
356 case DEBUG_MAILBOX_DEBUG_PORT_HANDLE_INDEX
:
357 Mailbox
->ToBeCheckSum
= Mailbox
->CheckSum
+ CalculateSum8 ((UINT8
*)&Mailbox
->DebugPortHandle
, sizeof(UINTN
))
358 - CalculateSum8 ((UINT8
*)&Value
, sizeof(UINTN
));
359 Mailbox
->DebugPortHandle
= (UINTN
) Value
;
361 case DEBUG_MAILBOX_EXCEPTION_BUFFER_POINTER_INDEX
:
362 Mailbox
->ToBeCheckSum
= Mailbox
->CheckSum
+ CalculateSum8 ((UINT8
*)&Mailbox
->ExceptionBufferPointer
, sizeof(UINTN
))
363 - CalculateSum8 ((UINT8
*)&Value
, sizeof(UINTN
));
364 Mailbox
->ExceptionBufferPointer
= (UINTN
) Value
;
366 case DEBUG_MAILBOX_LAST_ACK
:
367 Mailbox
->ToBeCheckSum
= Mailbox
->CheckSum
+ CalculateSum8 ((UINT8
*)&Mailbox
->LastAck
, sizeof(UINT8
))
368 - CalculateSum8 ((UINT8
*)&Value
, sizeof(UINT8
));
369 Mailbox
->LastAck
= (UINT8
) Value
;
371 case DEBUG_MAILBOX_SEQUENCE_NO_INDEX
:
372 Mailbox
->ToBeCheckSum
= Mailbox
->CheckSum
+ CalculateSum8 ((UINT8
*)&Mailbox
->SequenceNo
, sizeof(UINT8
))
373 - CalculateSum8 ((UINT8
*)&Value
, sizeof(UINT8
));
374 Mailbox
->SequenceNo
= (UINT8
) Value
;
376 case DEBUG_MAILBOX_HOST_SEQUENCE_NO_INDEX
:
377 Mailbox
->ToBeCheckSum
= Mailbox
->CheckSum
+ CalculateSum8 ((UINT8
*)&Mailbox
->HostSequenceNo
, sizeof(UINT8
))
378 - CalculateSum8 ((UINT8
*)&Value
, sizeof(UINT8
));
379 Mailbox
->HostSequenceNo
= (UINT8
) Value
;
382 UpdateMailboxChecksum (Mailbox
);
383 ReleaseMpSpinLock (&mDebugMpContext
.MailboxSpinLock
);
386 Set debug flag in mailbox.
388 @param[in] FlagMask Debug flag mask value.
389 @param[in] FlagValue Debug flag value.
398 DEBUG_AGENT_MAILBOX
*Mailbox
;
401 Mailbox
= GetMailboxPointer ();
402 Data64
= (Mailbox
->DebugFlag
.Uint64
& ~FlagMask
) |
403 (LShiftU64 ((UINT64
)FlagValue
, LowBitSet64 (FlagMask
)) & FlagMask
);
404 UpdateMailboxContent (Mailbox
, DEBUG_MAILBOX_DEBUG_FLAG_INDEX
, Data64
);
408 Get debug flag in mailbox.
410 @param[in] FlagMask Debug flag mask value.
412 @return Debug flag value.
420 DEBUG_AGENT_MAILBOX
*Mailbox
;
423 Mailbox
= GetMailboxPointer ();
424 DebugFlag
= (UINT32
) RShiftU64 (Mailbox
->DebugFlag
.Uint64
& FlagMask
, LowBitSet64 (FlagMask
));
430 Send a debug message packet to the debug port.
432 @param[in] Buffer The debug message.
433 @param[in] Length The length of debug message.
442 DEBUG_PACKET_HEADER DebugHeader
;
443 DEBUG_PORT_HANDLE Handle
;
445 Handle
= GetDebugPortHandle();
447 DebugHeader
.StartSymbol
= DEBUG_STARTING_SYMBOL_NORMAL
;
448 DebugHeader
.Command
= DEBUG_COMMAND_PRINT_MESSAGE
;
449 DebugHeader
.Length
= sizeof (DEBUG_PACKET_HEADER
) + (UINT8
) Length
;
450 DebugHeader
.SequenceNo
= 0xEE;
452 DebugHeader
.Crc
= CalculateCrc16 (
453 (UINT8
*)Buffer
, Length
,
454 CalculateCrc16 ((UINT8
*)&DebugHeader
, sizeof (DEBUG_PACKET_HEADER
), 0)
457 DebugPortWriteBuffer (Handle
, (UINT8
*)&DebugHeader
, sizeof (DEBUG_PACKET_HEADER
));
458 DebugPortWriteBuffer (Handle
, (UINT8
*)Buffer
, Length
);
462 Prints a debug message to the debug port if the specified error level is enabled.
464 If any bit in ErrorLevel is also set in Mainbox, then print the message specified
465 by Format and the associated variable argument list to the debug port.
467 @param[in] ErrorLevel The error level of the debug message.
468 @param[in] Format Format string for the debug message to print.
469 @param[in] ... Variable argument list whose contents are accessed
470 based on the format string specified by Format.
481 CHAR8 Buffer
[DEBUG_DATA_MAXIMUM_REAL_DATA
];
485 // Check driver debug mask value and global mask
487 if ((ErrorLevel
& GetDebugFlag (DEBUG_AGENT_FLAG_PRINT_ERROR_LEVEL
)) == 0) {
492 // Convert the DEBUG() message to an ASCII String
494 VA_START (Marker
, Format
);
495 AsciiVSPrint (Buffer
, sizeof (Buffer
), Format
, Marker
);
498 SendDebugMsgPacket (Buffer
, AsciiStrLen (Buffer
));
502 Prints a debug message to the debug output device if the specified error level is enabled.
504 If any bit in ErrorLevel is also set in DebugPrintErrorLevelLib function
505 GetDebugPrintErrorLevel (), then print the message specified by Format and the
506 associated variable argument list to the debug output device.
508 If Format is NULL, then ASSERT().
510 @param[in] ErrorLevel The error level of the debug message.
511 @param[in] IsSend Flag of debug message to declare that the data is being sent or being received.
512 @param[in] Data Variable argument list whose contents are accessed
513 @param[in] Length based on the format string specified by Format.
518 DebugAgentDataMsgPrint (
525 CHAR8 Buffer
[DEBUG_DATA_MAXIMUM_REAL_DATA
];
530 // Check driver debug mask value and global mask
532 if ((ErrorLevel
& GetDebugFlag (DEBUG_AGENT_FLAG_PRINT_ERROR_LEVEL
)) == 0) {
538 DestBuffer
+= AsciiSPrint (DestBuffer
, DEBUG_DATA_MAXIMUM_REAL_DATA
, "Sent data [ ");
540 DestBuffer
+= AsciiSPrint (DestBuffer
, DEBUG_DATA_MAXIMUM_REAL_DATA
, "Received data [ ");
545 if (DestBuffer
- Buffer
> DEBUG_DATA_MAXIMUM_REAL_DATA
- 6) {
547 // If there was no enough space in buffer, send out the debug message,
548 // reserving 6 bytes is for the last data and end characters "]\n".
550 SendDebugMsgPacket (Buffer
, DestBuffer
- Buffer
);
553 DestBuffer
+= AsciiSPrint (DestBuffer
, DEBUG_DATA_MAXIMUM_REAL_DATA
- (DestBuffer
- Buffer
), "%02x ", Data
[Index
]);
555 if (Index
>= Length
) {
557 // The last character of debug message has been foramtted in buffer
559 DestBuffer
+= AsciiSPrint(DestBuffer
, DEBUG_DATA_MAXIMUM_REAL_DATA
- (DestBuffer
- Buffer
), "]\n");
560 SendDebugMsgPacket (Buffer
, DestBuffer
- Buffer
);
567 Read remaing debug packet except for the start symbol
569 @param[in] Handle Pointer to Debug Port handle.
570 @param[in, out] DebugHeader Debug header buffer including start symbol.
572 @retval EFI_SUCCESS Read the symbol in BreakSymbol.
573 @retval EFI_CRC_ERROR CRC check fail.
574 @retval EFI_TIMEOUT Timeout occurs when reading debug packet.
575 @retval EFI_DEVICE_ERROR Receive the old or responsed packet.
579 ReadRemainingBreakPacket (
580 IN DEBUG_PORT_HANDLE Handle
,
581 IN OUT DEBUG_PACKET_HEADER
*DebugHeader
585 DEBUG_AGENT_MAILBOX
*Mailbox
;
588 // Has received start symbol, try to read the rest part
590 if (DebugPortReadBuffer (Handle
, &DebugHeader
->Command
, sizeof (DEBUG_PACKET_HEADER
) - 1, READ_PACKET_TIMEOUT
) == 0) {
592 // Timeout occur, exit
594 DebugAgentMsgPrint (DEBUG_AGENT_WARNING
, "Timeout in Debug Timer interrupt\n");
598 Crc
= DebugHeader
->Crc
;
599 DebugHeader
->Crc
= 0;
600 if (CalculateCrc16 ((UINT8
*)DebugHeader
, DebugHeader
->Length
, 0) != Crc
) {
601 DebugAgentMsgPrint (DEBUG_AGENT_WARNING
, "Debug Timer CRC (%x) against (%x)\n", Crc
, CalculateCrc16 ((UINT8
*) &DebugHeader
, DebugHeader
->Length
, 0));
602 DebugAgentDataMsgPrint (DEBUG_AGENT_VERBOSE
, FALSE
, (UINT8
*)DebugHeader
, DebugHeader
->Length
);
603 return EFI_CRC_ERROR
;
605 Mailbox
= GetMailboxPointer();
606 if (((DebugHeader
->Command
& DEBUG_COMMAND_RESPONSE
) == 0) &&
607 (DebugHeader
->SequenceNo
== (UINT8
) (Mailbox
->HostSequenceNo
+ 1))) {
609 // Only updagte HostSequenceNo for new command packet
611 UpdateMailboxContent (Mailbox
, DEBUG_MAILBOX_HOST_SEQUENCE_NO_INDEX
, DebugHeader
->SequenceNo
);
615 // If one old command or response packet received, skip it
617 return EFI_DEVICE_ERROR
;
622 Check if HOST is attached based on Mailbox.
624 @retval TRUE HOST is attached.
625 @retval FALSE HOST is not attached.
633 return (BOOLEAN
) (GetDebugFlag (DEBUG_AGENT_FLAG_HOST_ATTACHED
) == 1);
637 Set HOST connect flag in Mailbox.
639 @param[in] Attached Attach status.
647 DebugAgentMsgPrint (DEBUG_AGENT_INFO
, "Attach status is %d\n", Attached
);
648 SetDebugFlag (DEBUG_AGENT_FLAG_HOST_ATTACHED
, (UINT32
)Attached
);
652 Set debug setting of Debug Agent in Mailbox.
654 @param DebugSetting Pointer to Debug Setting defined by transfer protocol.
656 @retval RETURN_SUCCESS The setting is set successfully.
657 @retval RETURN_UNSUPPORTED The Key value is not supported.
662 IN DEBUG_DATA_SET_DEBUG_SETTING
*DebugSetting
665 RETURN_STATUS Status
;
667 Status
= RETURN_SUCCESS
;
668 switch (DebugSetting
->Key
) {
669 case DEBUG_AGENT_SETTING_SMM_ENTRY_BREAK
:
670 SetDebugFlag (DEBUG_AGENT_FLAG_BREAK_ON_NEXT_SMI
, DebugSetting
->Value
);
672 case DEBUG_AGENT_SETTING_PRINT_ERROR_LEVEL
:
673 SetDebugFlag (DEBUG_AGENT_FLAG_PRINT_ERROR_LEVEL
, DebugSetting
->Value
);
675 case DEBUG_AGENT_SETTING_BOOT_SCRIPT_ENTRY_BREAK
:
676 SetDebugFlag (DEBUG_AGENT_FLAG_BREAK_BOOT_SCRIPT
, DebugSetting
->Value
);
679 Status
= RETURN_UNSUPPORTED
;
687 @param[in] CpuContext Pointer to saved CPU context.
692 IN DEBUG_CPU_CONTEXT
*CpuContext
695 IA32_EFLAGS32
*Eflags
;
697 Eflags
= (IA32_EFLAGS32
*) &CpuContext
->Eflags
;
703 Exectue Stepping command.
705 @param[in] CpuContext Pointer to saved CPU context.
710 IN DEBUG_CPU_CONTEXT
*CpuContext
713 IA32_EFLAGS32
*Eflags
;
715 Eflags
= (IA32_EFLAGS32
*) &CpuContext
->Eflags
;
721 Set debug register for hardware breakpoint.
723 @param[in] CpuContext Pointer to saved CPU context.
724 @param[in] SetHwBreakpoint Hardware breakpoint to be set.
729 IN DEBUG_CPU_CONTEXT
*CpuContext
,
730 IN DEBUG_DATA_SET_HW_BREAKPOINT
*SetHwBreakpoint
736 RegisterIndex
= SetHwBreakpoint
->Type
.Index
;
741 * ((UINTN
*) &CpuContext
->Dr0
+ RegisterIndex
) = (UINTN
) SetHwBreakpoint
->Address
;
743 Dr7Value
= CpuContext
->Dr7
;
748 Dr7Value
|= 0x3 << (RegisterIndex
* 2);
752 Dr7Value
&= ~(0xf << (16 + RegisterIndex
* 4));
753 Dr7Value
|= (UINTN
) ((SetHwBreakpoint
->Type
.Length
<< 2) | SetHwBreakpoint
->Type
.Access
) << (16 + RegisterIndex
* 4);
759 CpuContext
->Dr7
= Dr7Value
;
763 Clear debug register for hardware breakpoint.
765 @param[in] CpuContext Pointer to saved CPU context.
766 @param[in] ClearHwBreakpoint Hardware breakpoint to be cleared.
771 IN DEBUG_CPU_CONTEXT
*CpuContext
,
772 IN DEBUG_DATA_CLEAR_HW_BREAKPOINT
*ClearHwBreakpoint
775 if ((ClearHwBreakpoint
->IndexMask
& BIT0
) != 0) {
777 CpuContext
->Dr7
&= ~(0x3 << 0);
779 if ((ClearHwBreakpoint
->IndexMask
& BIT1
) != 0) {
781 CpuContext
->Dr7
&= ~(0x3 << 2);
783 if ((ClearHwBreakpoint
->IndexMask
& BIT2
) != 0) {
785 CpuContext
->Dr7
&= ~(0x3 << 4);
787 if ((ClearHwBreakpoint
->IndexMask
& BIT3
) != 0) {
789 CpuContext
->Dr7
&= ~(0x3 << 6);
795 Return the offset of FP / MMX / XMM registers in the FPU saved state by register index.
797 @param[in] Index Register index.
798 @param[out] Width Register width returned.
800 @return Offset in the FPU Save State.
804 ArchReadFxStatOffset (
809 if (Index
< SOFT_DEBUGGER_REGISTER_ST0
) {
811 case SOFT_DEBUGGER_REGISTER_FP_FCW
:
812 *Width
= (UINT8
) sizeof (UINT16
);
813 return OFFSET_OF(DEBUG_DATA_FX_SAVE_STATE
, Fcw
);
815 case SOFT_DEBUGGER_REGISTER_FP_FSW
:
816 *Width
= (UINT8
) sizeof (UINT16
);
817 return OFFSET_OF(DEBUG_DATA_FX_SAVE_STATE
, Fsw
);
819 case SOFT_DEBUGGER_REGISTER_FP_FTW
:
820 *Width
= (UINT8
) sizeof (UINT16
);
821 return OFFSET_OF(DEBUG_DATA_FX_SAVE_STATE
, Ftw
);
823 case SOFT_DEBUGGER_REGISTER_FP_OPCODE
:
824 *Width
= (UINT8
) sizeof (UINT16
);
825 return OFFSET_OF(DEBUG_DATA_FX_SAVE_STATE
, Opcode
);
827 case SOFT_DEBUGGER_REGISTER_FP_EIP
:
828 *Width
= (UINT8
) sizeof (UINT32
);
829 return OFFSET_OF(DEBUG_DATA_FX_SAVE_STATE
, Eip
);
831 case SOFT_DEBUGGER_REGISTER_FP_CS
:
832 *Width
= (UINT8
) sizeof (UINT16
);
833 return OFFSET_OF(DEBUG_DATA_FX_SAVE_STATE
, Cs
);
835 case SOFT_DEBUGGER_REGISTER_FP_DATAOFFSET
:
836 *Width
= (UINT8
) sizeof (UINT32
);
837 return OFFSET_OF(DEBUG_DATA_FX_SAVE_STATE
, DataOffset
);
839 case SOFT_DEBUGGER_REGISTER_FP_DS
:
840 *Width
= (UINT8
) sizeof (UINT16
);
841 return OFFSET_OF(DEBUG_DATA_FX_SAVE_STATE
, Ds
);
843 case SOFT_DEBUGGER_REGISTER_FP_MXCSR
:
844 *Width
= (UINT8
) sizeof (UINT32
);
845 return OFFSET_OF(DEBUG_DATA_FX_SAVE_STATE
, Mxcsr
);
847 case SOFT_DEBUGGER_REGISTER_FP_MXCSR_MASK
:
848 *Width
= (UINT8
) sizeof (UINT32
);
849 return OFFSET_OF(DEBUG_DATA_FX_SAVE_STATE
, Mxcsr_Mask
);
853 if (Index
<= SOFT_DEBUGGER_REGISTER_ST7
) {
855 } else if (Index
<= SOFT_DEBUGGER_REGISTER_XMM15
) {
862 Index
-= SOFT_DEBUGGER_REGISTER_MM0
- SOFT_DEBUGGER_REGISTER_ST0
;
865 return OFFSET_OF (DEBUG_DATA_FX_SAVE_STATE
, St0Mm0
) + (Index
- SOFT_DEBUGGER_REGISTER_ST0
) * 16;
869 Return the pointer of the register value in the CPU saved context.
871 @param[in] CpuContext Pointer to saved CPU context.
872 @param[in] Index Register index value.
873 @param[out] Width Data width to read.
875 @return The pointer in the CPU saved context.
879 ArchReadRegisterBuffer (
880 IN DEBUG_CPU_CONTEXT
*CpuContext
,
887 if (Index
< SOFT_DEBUGGER_REGISTER_FP_BASE
) {
888 Buffer
= (UINT8
*) CpuContext
+ OFFSET_OF (DEBUG_CPU_CONTEXT
, Dr0
) + Index
* sizeof (UINTN
);
889 *Width
= (UINT8
) sizeof (UINTN
);
892 // FPU/MMX/XMM registers
894 Buffer
= (UINT8
*) CpuContext
+ OFFSET_OF (DEBUG_CPU_CONTEXT
, FxSaveState
) + ArchReadFxStatOffset (Index
, Width
);
901 Send the packet without data to HOST.
903 @param[in] CommandType Type of Command.
904 @param[in] SequenceNo Sequence number.
908 SendPacketWithoutData (
909 IN UINT8 CommandType
,
913 DEBUG_PACKET_HEADER DebugHeader
;
914 DEBUG_PORT_HANDLE Handle
;
916 Handle
= GetDebugPortHandle();
918 DebugHeader
.StartSymbol
= DEBUG_STARTING_SYMBOL_NORMAL
;
919 DebugHeader
.Command
= CommandType
;
920 DebugHeader
.Length
= sizeof (DEBUG_PACKET_HEADER
);
921 DebugHeader
.SequenceNo
= SequenceNo
;
923 DebugHeader
.Crc
= CalculateCrc16 ((UINT8
*)&DebugHeader
, sizeof (DEBUG_PACKET_HEADER
), 0);
925 DebugAgentDataMsgPrint (DEBUG_AGENT_VERBOSE
, TRUE
, (UINT8
*) &DebugHeader
, DebugHeader
.Length
);
926 DebugPortWriteBuffer (Handle
, (UINT8
*) &DebugHeader
, DebugHeader
.Length
);
930 Send acknowledge packet to HOST.
932 @param[in] AckCommand Type of Acknowledge packet.
941 DEBUG_AGENT_MAILBOX
*Mailbox
;
943 if (AckCommand
!= DEBUG_COMMAND_OK
) {
945 // This is not ACK OK packet
947 DebugAgentMsgPrint (DEBUG_AGENT_ERROR
, "Send ACK(%d)\n", AckCommand
);
949 Mailbox
= GetMailboxPointer();
950 SequenceNo
= Mailbox
->HostSequenceNo
;
951 DebugAgentMsgPrint (DEBUG_AGENT_INFO
, "SendAckPacket: SequenceNo = %x\n", SequenceNo
);
952 SendPacketWithoutData (AckCommand
, SequenceNo
);
953 UpdateMailboxContent (Mailbox
, DEBUG_MAILBOX_LAST_ACK
, AckCommand
);
957 Receive valid packet from HOST.
959 @param[out] InputPacket Buffer to receive packet.
960 @param[out] BreakReceived TRUE means break-in symbol received.
961 FALSE means break-in symbol not received.
962 @param[out] IncompatibilityFlag If IncompatibilityFlag is not NULL, return
963 TRUE: Compatible packet received.
964 FALSE: Incompatible packet received.
965 @param[in] Timeout Time out value to wait for acknowlege from HOST.
966 The unit is microsecond.
967 @param[in] SkipStartSymbol TRUE: Skip time out when reading start symbol.
968 FALSE: Does not Skip time out when reading start symbol.
970 @retval RETURN_SUCCESS A valid package was reveived in InputPacket.
971 @retval RETURN_TIMEOUT Timeout occurs.
976 OUT UINT8
*InputPacket
,
977 OUT BOOLEAN
*BreakReceived
,
978 OUT BOOLEAN
*IncompatibilityFlag
, OPTIONAL
980 IN BOOLEAN SkipStartSymbol
983 DEBUG_PACKET_HEADER
*DebugHeader
;
985 DEBUG_PORT_HANDLE Handle
;
987 UINTN TimeoutForStartSymbol
;
989 Handle
= GetDebugPortHandle();
990 if (SkipStartSymbol
) {
991 TimeoutForStartSymbol
= 0;
993 TimeoutForStartSymbol
= Timeout
;
996 DebugHeader
= (DEBUG_PACKET_HEADER
*) InputPacket
;
999 // Find the valid start symbol
1001 Received
= DebugPortReadBuffer (Handle
, &DebugHeader
->StartSymbol
, sizeof (DebugHeader
->StartSymbol
), TimeoutForStartSymbol
);
1002 if (Received
< sizeof (DebugHeader
->StartSymbol
)) {
1003 DebugAgentMsgPrint (DEBUG_AGENT_WARNING
, "DebugPortReadBuffer(StartSymbol) timeout\n");
1004 return RETURN_TIMEOUT
;
1007 if (DebugHeader
->StartSymbol
!= DEBUG_STARTING_SYMBOL_NORMAL
) {
1008 DebugAgentMsgPrint (DEBUG_AGENT_WARNING
, "Invalid start symbol received [%02x]\n", DebugHeader
->StartSymbol
);
1013 // Read Package header till field Length
1015 Received
= DebugPortReadBuffer (
1017 &DebugHeader
->Command
,
1018 OFFSET_OF (DEBUG_PACKET_HEADER
, Length
) + sizeof (DebugHeader
->Length
) - sizeof (DebugHeader
->StartSymbol
),
1021 if (Received
== 0) {
1022 DebugAgentMsgPrint (DEBUG_AGENT_ERROR
, "DebugPortReadBuffer(Command) timeout\n");
1023 return RETURN_TIMEOUT
;
1025 if (DebugHeader
->Length
< sizeof (DEBUG_PACKET_HEADER
)) {
1026 if (IncompatibilityFlag
!= NULL
) {
1028 // This is one old version debug packet format, set Incompatibility flag
1030 *IncompatibilityFlag
= TRUE
;
1033 // Skip the bad small packet
1039 // Read the payload data include the CRC field
1041 Received
= DebugPortReadBuffer (Handle
, &DebugHeader
->SequenceNo
, (UINT8
) (DebugHeader
->Length
- OFFSET_OF (DEBUG_PACKET_HEADER
, SequenceNo
)), Timeout
);
1042 if (Received
== 0) {
1043 DebugAgentMsgPrint (DEBUG_AGENT_ERROR
, "DebugPortReadBuffer(SequenceNo) timeout\n");
1044 return RETURN_TIMEOUT
;
1047 // Calculate the CRC of Debug Packet
1049 Crc
= DebugHeader
->Crc
;
1050 DebugHeader
->Crc
= 0;
1051 if (Crc
== CalculateCrc16 ((UINT8
*) DebugHeader
, DebugHeader
->Length
, 0)) {
1054 DebugAgentMsgPrint (DEBUG_AGENT_WARNING
, "CRC Error (received CRC is %x)\n", Crc
);
1055 DebugAgentDataMsgPrint (DEBUG_AGENT_VERBOSE
, FALSE
, (UINT8
*) DebugHeader
, DebugHeader
->Length
);
1059 DebugAgentDataMsgPrint (DEBUG_AGENT_VERBOSE
, FALSE
, (UINT8
*) DebugHeader
, DebugHeader
->Length
);
1061 return RETURN_SUCCESS
;
1065 Receive acknowledge packet OK from HOST in specified time.
1067 @param[in] Command The command type issued by TARGET.
1068 @param[in] Timeout Time out value to wait for acknowlege from HOST.
1069 The unit is microsecond.
1070 @param[out] BreakReceived If BreakReceived is not NULL,
1071 TRUE is retured if break-in symbol received.
1072 FALSE is retured if break-in symbol not received.
1073 @param[out] IncompatibilityFlag If IncompatibilityFlag is not NULL, return
1074 TRUE: Compatible packet received.
1075 FALSE: Incompatible packet received.
1077 @retval RETRUEN_SUCCESS Succeed to receive acknowlege packet from HOST,
1078 the type of acknowlege packet saved in Ack.
1079 @retval RETURN_TIMEOUT Specified timeout value was up.
1083 SendCommandAndWaitForAckOK (
1086 OUT BOOLEAN
*BreakReceived
, OPTIONAL
1087 OUT BOOLEAN
*IncompatibilityFlag OPTIONAL
1090 RETURN_STATUS Status
;
1091 UINT8 InputPacketBuffer
[DEBUG_DATA_UPPER_LIMIT
];
1092 DEBUG_PACKET_HEADER
*DebugHeader
;
1094 UINT8 HostSequenceNo
;
1098 DebugHeader
= (DEBUG_PACKET_HEADER
*) InputPacketBuffer
;
1099 Status
= RETURN_TIMEOUT
;
1100 while (RetryCount
> 0) {
1101 SequenceNo
= GetMailboxPointer()->SequenceNo
;
1102 HostSequenceNo
= GetMailboxPointer()->HostSequenceNo
;
1103 SendPacketWithoutData (Command
, SequenceNo
);
1104 Status
= ReceivePacket ((UINT8
*) DebugHeader
, BreakReceived
, IncompatibilityFlag
, Timeout
, FALSE
);
1105 if (Status
== RETURN_TIMEOUT
) {
1106 if (Command
== DEBUG_COMMAND_INIT_BREAK
) {
1109 DebugAgentMsgPrint (DEBUG_AGENT_WARNING
, "TARGET: Timeout when waiting for ACK packet.\n");
1113 ASSERT_EFI_ERROR (Status
);
1115 // Status == RETURN_SUCCESS
1117 if (DebugHeader
->Command
== DEBUG_COMMAND_OK
&& DebugHeader
->SequenceNo
== SequenceNo
) {
1121 UpdateMailboxContent (GetMailboxPointer(), DEBUG_MAILBOX_SEQUENCE_NO_INDEX
, ++SequenceNo
);
1124 if (DebugHeader
->Command
== DEBUG_COMMAND_GO
&& (DebugHeader
->SequenceNo
== HostSequenceNo
|| Command
== DEBUG_COMMAND_INIT_BREAK
)) {
1128 if (Command
== DEBUG_COMMAND_INIT_BREAK
) {
1129 DebugAgentMsgPrint (DEBUG_AGENT_WARNING
, "TARGET: Receive GO() in last boot\n");
1131 SendPacketWithoutData (DEBUG_COMMAND_OK
, DebugHeader
->SequenceNo
);
1135 ASSERT (Command
== DEBUG_COMMAND_INIT_BREAK
);
1140 Get current break cause.
1142 @param[in] Vector Vector value of exception or interrupt.
1143 @param[in] CpuContext Pointer to save CPU context.
1145 @return The type of break cause defined by XXXX
1151 IN DEBUG_CPU_CONTEXT
*CpuContext
1156 Cause
= DEBUG_DATA_BREAK_CAUSE_UNKNOWN
;
1159 case DEBUG_INT1_VECTOR
:
1160 case DEBUG_INT3_VECTOR
:
1162 if (Vector
== DEBUG_INT1_VECTOR
) {
1166 if ((CpuContext
->Dr6
& BIT14
) != 0) {
1167 Cause
= DEBUG_DATA_BREAK_CAUSE_STEPPING
;
1169 // If it's single step, no need to check DR0, to ensure single step work in PeCoffExtraActionLib
1170 // (right after triggering a breakpoint to report image load/unload).
1175 Cause
= DEBUG_DATA_BREAK_CAUSE_HW_BREAKPOINT
;
1181 Cause
= DEBUG_DATA_BREAK_CAUSE_SW_BREAKPOINT
;
1184 switch (CpuContext
->Dr0
) {
1185 case IMAGE_LOAD_SIGNATURE
:
1186 case IMAGE_UNLOAD_SIGNATURE
:
1188 if (CpuContext
->Dr3
== IO_PORT_BREAKPOINT_ADDRESS
) {
1190 Cause
= (UINT8
) ((CpuContext
->Dr0
== IMAGE_LOAD_SIGNATURE
) ?
1191 DEBUG_DATA_BREAK_CAUSE_IMAGE_LOAD
: DEBUG_DATA_BREAK_CAUSE_IMAGE_UNLOAD
);
1195 case SOFT_INTERRUPT_SIGNATURE
:
1197 if (CpuContext
->Dr1
== MEMORY_READY_SIGNATURE
) {
1198 Cause
= DEBUG_DATA_BREAK_CAUSE_MEMORY_READY
;
1199 CpuContext
->Dr0
= 0;
1200 } else if (CpuContext
->Dr1
== SYSTEM_RESET_SIGNATURE
) {
1201 Cause
= DEBUG_DATA_BREAK_CAUSE_SYSTEM_RESET
;
1202 CpuContext
->Dr0
= 0;
1213 case DEBUG_TIMER_VECTOR
:
1214 Cause
= DEBUG_DATA_BREAK_CAUSE_USER_HALT
;
1219 if (GetDebugFlag (DEBUG_AGENT_FLAG_STEPPING
) == 1) {
1221 // If stepping command is executing
1223 Cause
= DEBUG_DATA_BREAK_CAUSE_STEPPING
;
1225 Cause
= DEBUG_DATA_BREAK_CAUSE_EXCEPTION
;
1235 Copy memory from source to destination with specified width.
1237 @param[out] Dest A pointer to the destination buffer of the memory copy.
1238 @param[in] Src A pointer to the source buffer of the memory copy.
1239 @param[in] Count The number of data with specified width to copy from source to destination.
1240 @param[in] Width Data width in byte.
1261 // Copy memory from tail to avoid memory overlap
1263 Destination
= Dest
+ (Count
- 1) * Width
;
1264 Source
= Src
+ (Count
- 1) * Width
;
1268 while (Count
-- != 0) {
1271 *(UINT8
*) Destination
= MmioRead8 ((UINTN
) Source
);
1274 *(UINT16
*) Destination
= MmioRead16 ((UINTN
) Source
);
1277 *(UINT32
*) Destination
= MmioRead32 ((UINTN
) Source
);
1280 *(UINT64
*) Destination
= MmioRead64 ((UINTN
) Source
);
1286 Destination
+= Step
;
1291 Read memory with speicifed width and send packet with response data to HOST.
1293 @param[in] Data Pointer to response data buffer.
1294 @param[in] Count The number of data with specified Width.
1295 @param[in] Width Data width in byte.
1297 @retval RETURN_SUCCESS Response data was sent successfully.
1301 ReadMemoryAndSendResponsePacket (
1307 RETURN_STATUS Status
;
1308 DEBUG_PACKET_HEADER
*DebugHeader
;
1310 DEBUG_PACKET_HEADER
*AckDebugHeader
;
1311 UINT8 DebugPacket
[DEBUG_DATA_UPPER_LIMIT
+ sizeof (UINT64
) - 1];
1312 UINT8 InputPacketBuffer
[DEBUG_DATA_UPPER_LIMIT
];
1313 DEBUG_PORT_HANDLE Handle
;
1315 UINTN RemainingDataSize
;
1316 UINTN CurrentDataSize
;
1318 Handle
= GetDebugPortHandle();
1321 // Data is appended end of Debug Packet header, make sure data address
1322 // in Debug Packet 8-byte alignment always
1324 DebugHeader
= (DEBUG_PACKET_HEADER
*) (ALIGN_VALUE ((UINTN
)&DebugPacket
+ sizeof (DEBUG_PACKET_HEADER
), sizeof (UINT64
))
1325 - sizeof (DEBUG_PACKET_HEADER
));
1326 DebugHeader
->StartSymbol
= DEBUG_STARTING_SYMBOL_NORMAL
;
1328 RemainingDataSize
= Count
* Width
;
1330 SequenceNo
= GetMailboxPointer()->HostSequenceNo
;
1331 if (RemainingDataSize
<= DEBUG_DATA_MAXIMUM_REAL_DATA
) {
1333 // If the remaining data is less one real packet size, this is the last data packet
1335 CurrentDataSize
= RemainingDataSize
;
1337 DebugHeader
->Command
= DEBUG_COMMAND_OK
;
1340 // Data is too larger to be sent in one packet, calculate the actual data size could
1341 // be sent in one Maximum data packet
1343 CurrentDataSize
= (DEBUG_DATA_MAXIMUM_REAL_DATA
/ Width
) * Width
;
1345 DebugHeader
->Command
= DEBUG_COMMAND_IN_PROGRESS
;
1348 // Construct the rest Debug header
1350 DebugHeader
->Length
= (UINT8
)(CurrentDataSize
+ sizeof (DEBUG_PACKET_HEADER
));
1351 DebugHeader
->SequenceNo
= SequenceNo
;
1352 DebugHeader
->Crc
= 0;
1353 CopyMemByWidth ((UINT8
*)(DebugHeader
+ 1), Data
, (UINT16
) CurrentDataSize
/ Width
, Width
);
1355 // Calculate and fill the checksum, DebugHeader->Crc should be 0 before invoking CalculateCrc16 ()
1357 DebugHeader
->Crc
= CalculateCrc16 ((UINT8
*) DebugHeader
, DebugHeader
->Length
, 0);
1359 DebugAgentDataMsgPrint (DEBUG_AGENT_VERBOSE
, TRUE
, (UINT8
*) DebugHeader
, DebugHeader
->Length
);
1361 DebugPortWriteBuffer (Handle
, (UINT8
*) DebugHeader
, DebugHeader
->Length
);
1364 Status
= ReceivePacket (InputPacketBuffer
, NULL
, NULL
, READ_PACKET_TIMEOUT
, FALSE
);
1365 if (Status
== RETURN_TIMEOUT
) {
1366 DebugAgentMsgPrint (DEBUG_AGENT_WARNING
, "TARGET: Timeout in SendDataResponsePacket()\n");
1369 AckDebugHeader
= (DEBUG_PACKET_HEADER
*) InputPacketBuffer
;
1370 SequenceNo
= AckDebugHeader
->SequenceNo
;
1371 if (AckDebugHeader
->Command
== DEBUG_COMMAND_OK
&&
1372 SequenceNo
== DebugHeader
->SequenceNo
&&
1375 // If this is the last packet, return RETURN_SUCCESS.
1377 return RETURN_SUCCESS
;
1379 if ((SequenceNo
== (UINT8
) (DebugHeader
->SequenceNo
+ 1)) && (AckDebugHeader
->Command
== DEBUG_COMMAND_CONTINUE
)) {
1381 // Calculate the rest data size
1383 Data
+= CurrentDataSize
;
1384 RemainingDataSize
-= CurrentDataSize
;
1385 UpdateMailboxContent (GetMailboxPointer(), DEBUG_MAILBOX_HOST_SEQUENCE_NO_INDEX
, (UINT8
) SequenceNo
);
1388 if (SequenceNo
>= DebugHeader
->SequenceNo
) {
1389 DebugAgentMsgPrint (DEBUG_AGENT_WARNING
, "TARGET: Received one old or new command(SequenceNo is %x, last SequenceNo is %x)\n", SequenceNo
, DebugHeader
->SequenceNo
);
1397 Send packet with response data to HOST.
1399 @param[in] Data Pointer to response data buffer.
1400 @param[in] DataSize Size of response data in byte.
1402 @retval RETURN_SUCCESS Response data was sent successfully.
1406 SendDataResponsePacket (
1411 return ReadMemoryAndSendResponsePacket (Data
, DataSize
, 1);
1415 Send break cause packet to HOST.
1417 @param[in] Vector Vector value of exception or interrutp.
1418 @param[in] CpuContext Pointer to save CPU context.
1420 @retval RETURN_SUCCESS Response data was sent successfully.
1421 @retval RETURN_DEVICE_ERROR Cannot receive DEBUG_COMMAND_OK from HOST.
1425 SendBreakCausePacket (
1427 IN DEBUG_CPU_CONTEXT
*CpuContext
1430 DEBUG_DATA_RESPONSE_BREAK_CAUSE DebugDataBreakCause
;
1432 DebugDataBreakCause
.StopAddress
= CpuContext
->Eip
;
1433 DebugDataBreakCause
.Cause
= GetBreakCause (Vector
, CpuContext
);
1435 return SendDataResponsePacket ((UINT8
*) &DebugDataBreakCause
, (UINT16
) sizeof (DEBUG_DATA_RESPONSE_BREAK_CAUSE
));
1439 Try to attach the HOST.
1441 Send init break packet to HOST:
1442 If no acknowlege received in specified Timeout, return RETURN_TIMEOUT.
1443 If received acknowlege, check the revision of HOST.
1444 Set Attach Flag if attach successfully.
1446 @param[in] BreakCause Break cause of this break event.
1447 @param[in] Timeout Time out value to wait for acknowlege from HOST.
1448 The unit is microsecond.
1449 @param[out] BreakReceived If BreakReceived is not NULL,
1450 TRUE is retured if break-in symbol received.
1451 FALSE is retured if break-in symbol not received.
1455 IN UINT8 BreakCause
,
1457 OUT BOOLEAN
*BreakReceived
1460 RETURN_STATUS Status
;
1461 DEBUG_PORT_HANDLE Handle
;
1462 BOOLEAN IncompatibilityFlag
;
1464 IncompatibilityFlag
= FALSE
;
1465 Handle
= GetDebugPortHandle();
1468 // Send init break and wait ack in Timeout
1470 DebugPortWriteBuffer (Handle
, (UINT8
*) mErrorMsgSendInitPacket
, AsciiStrLen (mErrorMsgSendInitPacket
));
1471 if (BreakCause
== DEBUG_DATA_BREAK_CAUSE_SYSTEM_RESET
) {
1472 Status
= SendCommandAndWaitForAckOK (DEBUG_COMMAND_INIT_BREAK
, Timeout
, BreakReceived
, &IncompatibilityFlag
);
1474 Status
= SendCommandAndWaitForAckOK (DEBUG_COMMAND_ATTACH_BREAK
, Timeout
, BreakReceived
, &IncompatibilityFlag
);
1476 if (IncompatibilityFlag
) {
1478 // If the incompatible Debug Packet received, the HOST should be running transfer protocol before DEBUG_AGENT_REVISION.
1479 // It could be UDK Debugger for Windows v1.1/v1.2 or for Linux v0.8/v1.2.
1481 DebugPortWriteBuffer (Handle
, (UINT8
*) mErrorMsgVersionAlert
, AsciiStrLen (mErrorMsgVersionAlert
));
1485 if (RETURN_ERROR (Status
)) {
1486 DebugPortWriteBuffer (Handle
, (UINT8
*) mErrorMsgConnectFail
, AsciiStrLen (mErrorMsgConnectFail
));
1488 DebugPortWriteBuffer (Handle
, (UINT8
*) mErrorMsgConnectOK
, AsciiStrLen (mErrorMsgConnectOK
));
1492 SetHostAttached (TRUE
);
1498 Send Break point packet to HOST.
1500 Only the first breaking processor could sent BREAK_POINT packet.
1502 @param[in] BreakCause Break cause of this break event.
1503 @param[in] ProcessorIndex Processor index value.
1504 @param[out] BreakReceived If BreakReceived is not NULL,
1505 TRUE is retured if break-in symbol received.
1506 FALSE is retured if break-in symbol not received.
1510 SendBreakPacketToHost (
1511 IN UINT8 BreakCause
,
1512 IN UINT32 ProcessorIndex
,
1513 OUT BOOLEAN
*BreakReceived
1516 UINT8 InputCharacter
;
1517 DEBUG_PORT_HANDLE Handle
;
1519 Handle
= GetDebugPortHandle();
1521 if (IsHostAttached ()) {
1522 DebugAgentMsgPrint (DEBUG_AGENT_INFO
, "processor[%x]:Send Break Packet to HOST.\n", ProcessorIndex
);
1523 SendCommandAndWaitForAckOK (DEBUG_COMMAND_BREAK_POINT
, READ_PACKET_TIMEOUT
, BreakReceived
, NULL
);
1525 DebugAgentMsgPrint (DEBUG_AGENT_INFO
, "processor[%x]:Try to attach HOST.\n", ProcessorIndex
);
1527 // If HOST is not attached, try to attach it firstly.
1530 // Poll Attach symbols from HOST and ack OK
1533 DebugPortReadBuffer (Handle
, &InputCharacter
, 1, 0);
1534 } while (InputCharacter
!= DEBUG_STARTING_SYMBOL_ATTACH
);
1535 SendAckPacket (DEBUG_COMMAND_OK
);
1538 // Try to attach HOST
1540 while (AttachHost (BreakCause
, 0, NULL
) != RETURN_SUCCESS
);
1546 The main function to process communication with HOST.
1548 It received the command packet from HOST, and sent response data packet to HOST.
1550 @param[in] Vector Vector value of exception or interrutp.
1551 @param[in, out] CpuContext Pointer to saved CPU context.
1552 @param[in] BreakReceived TRUE means break-in symbol received.
1553 FALSE means break-in symbol not received.
1557 CommandCommunication (
1559 IN OUT DEBUG_CPU_CONTEXT
*CpuContext
,
1560 IN BOOLEAN BreakReceived
1563 RETURN_STATUS Status
;
1564 UINT8 InputPacketBuffer
[DEBUG_DATA_UPPER_LIMIT
+ sizeof (UINT64
) - 1];
1565 DEBUG_PACKET_HEADER
*DebugHeader
;
1570 DEBUG_DATA_READ_MEMORY
*MemoryRead
;
1571 DEBUG_DATA_WRITE_MEMORY
*MemoryWrite
;
1572 DEBUG_DATA_READ_IO
*IoRead
;
1573 DEBUG_DATA_WRITE_IO
*IoWrite
;
1574 DEBUG_DATA_READ_REGISTER
*RegisterRead
;
1575 DEBUG_DATA_WRITE_REGISTER
*RegisterWrite
;
1576 UINT8
*RegisterBuffer
;
1577 DEBUG_DATA_READ_MSR
*MsrRegisterRead
;
1578 DEBUG_DATA_WRITE_MSR
*MsrRegisterWrite
;
1579 DEBUG_DATA_CPUID
*Cpuid
;
1580 DEBUG_DATA_RESPONSE_CPUID CpuidResponse
;
1581 DEBUG_DATA_SEARCH_SIGNATURE
*SearchSignature
;
1582 DEBUG_DATA_RESPONSE_GET_EXCEPTION Exception
;
1583 DEBUG_DATA_RESPONSE_GET_REVISION DebugAgentRevision
;
1584 DEBUG_DATA_SET_VIEWPOINT
*SetViewPoint
;
1585 BOOLEAN HaltDeferred
;
1586 UINT32 ProcessorIndex
;
1587 DEBUG_PORT_HANDLE Handle
;
1588 DEBUG_AGENT_EXCEPTION_BUFFER AgentExceptionBuffer
;
1589 UINT32 IssuedViewPoint
;
1590 DEBUG_AGENT_MAILBOX
*Mailbox
;
1591 UINT8
*AlignedDataPtr
;
1594 IssuedViewPoint
= 0;
1595 HaltDeferred
= BreakReceived
;
1597 if (MultiProcessorDebugSupport()) {
1598 ProcessorIndex
= GetProcessorIndex ();
1599 SetCpuStopFlagByIndex (ProcessorIndex
, TRUE
);
1600 if (mDebugMpContext
.ViewPointIndex
== ProcessorIndex
) {
1602 // Only the current view processor could set AgentInProgress Flag.
1604 IssuedViewPoint
= ProcessorIndex
;
1608 if (IssuedViewPoint
== ProcessorIndex
) {
1610 // Set AgentInProgress Flag.
1612 SetDebugFlag (DEBUG_AGENT_FLAG_AGENT_IN_PROGRESS
, 1);
1615 Handle
= GetDebugPortHandle();
1619 if (MultiProcessorDebugSupport()) {
1621 // Check if the current processor is HOST view point
1623 if (mDebugMpContext
.ViewPointIndex
!= ProcessorIndex
) {
1624 if (mDebugMpContext
.RunCommandSet
) {
1626 // If HOST view point sets RUN flag, run GO command to leave
1628 SetCpuStopFlagByIndex (ProcessorIndex
, FALSE
);
1629 CommandGo (CpuContext
);
1633 // Run into loop again
1641 AcquireMpSpinLock (&mDebugMpContext
.DebugPortSpinLock
);
1643 DebugHeader
=(DEBUG_PACKET_HEADER
*) InputPacketBuffer
;
1645 DebugAgentMsgPrint (DEBUG_AGENT_INFO
, "TARGET: Try to get command from HOST...\n");
1646 Status
= ReceivePacket ((UINT8
*)DebugHeader
, &BreakReceived
, NULL
, READ_PACKET_TIMEOUT
, TRUE
);
1647 if (Status
!= RETURN_SUCCESS
|| (DebugHeader
->Command
& DEBUG_COMMAND_RESPONSE
) != 0) {
1648 DebugAgentMsgPrint (DEBUG_AGENT_WARNING
, "TARGET: Get command[%x] sequenceno[%x] returned status is [%x] \n", DebugHeader
->Command
, DebugHeader
->SequenceNo
, Status
);
1649 DebugAgentMsgPrint (DEBUG_AGENT_WARNING
, "TARGET: Get command failed or it's response packet not expected! \n");
1650 ReleaseMpSpinLock (&mDebugMpContext
.DebugPortSpinLock
);
1654 Mailbox
= GetMailboxPointer ();
1655 if (DebugHeader
->SequenceNo
== Mailbox
->HostSequenceNo
) {
1656 DebugAgentMsgPrint (DEBUG_AGENT_WARNING
, "TARGET: Receive one old command[%x] agaist command[%x]\n", DebugHeader
->SequenceNo
, Mailbox
->HostSequenceNo
);
1657 SendAckPacket (Mailbox
->LastAck
);
1658 ReleaseMpSpinLock (&mDebugMpContext
.DebugPortSpinLock
);
1660 } else if (DebugHeader
->SequenceNo
== (UINT8
) (Mailbox
->HostSequenceNo
+ 1)) {
1661 UpdateMailboxContent (Mailbox
, DEBUG_MAILBOX_HOST_SEQUENCE_NO_INDEX
, (UINT8
) DebugHeader
->SequenceNo
);
1663 DebugAgentMsgPrint (DEBUG_AGENT_WARNING
, "Receive one invalid comamnd[%x] agaist command[%x]\n", DebugHeader
->SequenceNo
, Mailbox
->HostSequenceNo
);
1664 ReleaseMpSpinLock (&mDebugMpContext
.DebugPortSpinLock
);
1669 // Save CPU content before executing HOST commond
1671 UpdateMailboxContent (Mailbox
, DEBUG_MAILBOX_EXCEPTION_BUFFER_POINTER_INDEX
, (UINT64
)(UINTN
) &AgentExceptionBuffer
.JumpBuffer
);
1672 if (SetJump (&AgentExceptionBuffer
.JumpBuffer
) != 0) {
1674 // If HOST command failed, continue to wait for HOST's next command
1675 // If needed, agent could send exception info to HOST.
1677 SendAckPacket (DEBUG_COMMAND_ABORT
);
1678 ReleaseMpSpinLock (&mDebugMpContext
.DebugPortSpinLock
);
1682 DebugAgentMsgPrint (DEBUG_AGENT_INFO
, "Processor[%x]:Received one command(%x)\n", mDebugMpContext
.ViewPointIndex
, DebugHeader
->Command
);
1684 switch (DebugHeader
->Command
) {
1686 case DEBUG_COMMAND_HALT
:
1687 SendAckPacket (DEBUG_COMMAND_HALT_DEFERRED
);
1688 HaltDeferred
= TRUE
;
1689 BreakReceived
= FALSE
;
1690 Status
= RETURN_SUCCESS
;
1693 case DEBUG_COMMAND_RESET
:
1694 SendAckPacket (DEBUG_COMMAND_OK
);
1695 SendAckPacket (DEBUG_COMMAND_OK
);
1696 SendAckPacket (DEBUG_COMMAND_OK
);
1697 ReleaseMpSpinLock (&mDebugMpContext
.DebugPortSpinLock
);
1701 // Assume system resets in 2 seconds, otherwise send TIMEOUT packet.
1702 // PCD can be used if 2 seconds isn't long enough for some platforms.
1704 MicroSecondDelay (2000000);
1705 UpdateMailboxContent (Mailbox
, DEBUG_MAILBOX_HOST_SEQUENCE_NO_INDEX
, Mailbox
->HostSequenceNo
+ 1);
1706 SendAckPacket (DEBUG_COMMAND_TIMEOUT
);
1707 SendAckPacket (DEBUG_COMMAND_TIMEOUT
);
1708 SendAckPacket (DEBUG_COMMAND_TIMEOUT
);
1711 case DEBUG_COMMAND_GO
:
1712 CommandGo (CpuContext
);
1714 // Clear Dr0 to avoid to be recognized as IMAGE_LOAD/_UNLOAD again when hitting a breakpoint after GO
1715 // If HOST changed Dr0 before GO, we will not change Dr0 here
1717 Data8
= GetBreakCause (Vector
, CpuContext
);
1718 if (Data8
== DEBUG_DATA_BREAK_CAUSE_IMAGE_LOAD
|| Data8
== DEBUG_DATA_BREAK_CAUSE_IMAGE_UNLOAD
) {
1719 CpuContext
->Dr0
= 0;
1722 // Clear Stepping Flag
1724 SetDebugFlag (DEBUG_AGENT_FLAG_STEPPING
, 0);
1726 if (!HaltDeferred
) {
1728 // If no HALT command received when being in-active mode
1730 if (MultiProcessorDebugSupport()) {
1731 Data32
= FindNextPendingBreakCpu ();
1734 // If there are still others processors being in break state,
1735 // send OK packet to HOST to finish this go command
1737 SendAckPacket (DEBUG_COMMAND_OK
);
1740 // Set current view to the next breaking processor
1742 mDebugMpContext
.ViewPointIndex
= Data32
;
1743 mDebugMpContext
.BreakAtCpuIndex
= mDebugMpContext
.ViewPointIndex
;
1744 SetCpuBreakFlagByIndex (mDebugMpContext
.ViewPointIndex
, FALSE
);
1746 // Send break packet to HOST to let HOST break again
1748 SendBreakPacketToHost (DEBUG_DATA_BREAK_CAUSE_UNKNOWN
, mDebugMpContext
.BreakAtCpuIndex
, &BreakReceived
);
1750 // Continue to run into loop to read command packet from HOST
1752 ReleaseMpSpinLock (&mDebugMpContext
.DebugPortSpinLock
);
1757 // If no else processor break, set stop bitmask,
1758 // and set Running flag for all processors.
1760 SetCpuStopFlagByIndex (ProcessorIndex
, FALSE
);
1761 SetCpuRunningFlag (TRUE
);
1764 // Wait for all processors are in running state
1767 if (IsAllCpuRunning ()) {
1772 // Set BSP to be current view point.
1774 SetDebugViewPoint (mDebugMpContext
.BspIndex
);
1777 // Clear breaking processor index and running flag
1779 mDebugMpContext
.BreakAtCpuIndex
= (UINT32
) (-1);
1780 SetCpuRunningFlag (FALSE
);
1784 // Send OK packet to HOST to finish this go command
1786 SendAckPacket (DEBUG_COMMAND_OK
);
1788 ReleaseMpSpinLock (&mDebugMpContext
.DebugPortSpinLock
);
1790 if (!IsHostAttached()) {
1791 UpdateMailboxContent (Mailbox
, DEBUG_MAILBOX_SEQUENCE_NO_INDEX
, 0);
1792 UpdateMailboxContent (Mailbox
, DEBUG_MAILBOX_HOST_SEQUENCE_NO_INDEX
, 0);
1798 // If reveived HALT command, need to defer the GO command
1800 SendAckPacket (DEBUG_COMMAND_HALT_PROCESSED
);
1801 HaltDeferred
= FALSE
;
1803 Vector
= DEBUG_TIMER_VECTOR
;
1807 case DEBUG_COMMAND_BREAK_CAUSE
:
1809 if (MultiProcessorDebugSupport() && ProcessorIndex
!= mDebugMpContext
.BreakAtCpuIndex
) {
1810 Status
= SendBreakCausePacket (DEBUG_TIMER_VECTOR
, CpuContext
);
1813 Status
= SendBreakCausePacket (Vector
, CpuContext
);
1818 case DEBUG_COMMAND_SET_HW_BREAKPOINT
:
1819 SetDebugRegister (CpuContext
, (DEBUG_DATA_SET_HW_BREAKPOINT
*) (DebugHeader
+ 1));
1820 SendAckPacket (DEBUG_COMMAND_OK
);
1823 case DEBUG_COMMAND_CLEAR_HW_BREAKPOINT
:
1824 ClearDebugRegister (CpuContext
, (DEBUG_DATA_CLEAR_HW_BREAKPOINT
*) (DebugHeader
+ 1));
1825 SendAckPacket (DEBUG_COMMAND_OK
);
1828 case DEBUG_COMMAND_SINGLE_STEPPING
:
1829 CommandStepping (CpuContext
);
1831 // Clear Dr0 to avoid to be recognized as IMAGE_LOAD/_UNLOAD again when hitting a breakpoint after GO
1832 // If HOST changed Dr0 before GO, we will not change Dr0 here
1834 Data8
= GetBreakCause (Vector
, CpuContext
);
1835 if (Data8
== DEBUG_DATA_BREAK_CAUSE_IMAGE_LOAD
|| Data8
== DEBUG_DATA_BREAK_CAUSE_IMAGE_UNLOAD
) {
1836 CpuContext
->Dr0
= 0;
1839 mDebugMpContext
.BreakAtCpuIndex
= (UINT32
) (-1);
1841 // Set Stepping Flag
1843 SetDebugFlag (DEBUG_AGENT_FLAG_STEPPING
, 1);
1844 ReleaseMpSpinLock (&mDebugMpContext
.DebugPortSpinLock
);
1846 // Executing stepping command directly without sending ACK packet,
1847 // ACK packet will be sent after stepping done.
1851 case DEBUG_COMMAND_SET_SW_BREAKPOINT
:
1852 Data64
= (UINTN
) (((DEBUG_DATA_SET_SW_BREAKPOINT
*) (DebugHeader
+ 1))->Address
);
1853 Data8
= *(UINT8
*) (UINTN
) Data64
;
1854 *(UINT8
*) (UINTN
) Data64
= DEBUG_SW_BREAKPOINT_SYMBOL
;
1855 Status
= SendDataResponsePacket ((UINT8
*) &Data8
, (UINT16
) sizeof (UINT8
));
1858 case DEBUG_COMMAND_READ_MEMORY
:
1859 MemoryRead
= (DEBUG_DATA_READ_MEMORY
*) (DebugHeader
+ 1);
1860 Status
= ReadMemoryAndSendResponsePacket ((UINT8
*) (UINTN
) MemoryRead
->Address
, MemoryRead
->Count
, MemoryRead
->Width
);
1863 case DEBUG_COMMAND_WRITE_MEMORY
:
1864 MemoryWrite
= (DEBUG_DATA_WRITE_MEMORY
*) (DebugHeader
+ 1);
1866 // Copy data into one memory with 8-byte alignment address
1868 AlignedDataPtr
= ALIGN_POINTER ((UINT8
*) &MemoryWrite
->Data
, sizeof (UINT64
));
1869 if (AlignedDataPtr
!= (UINT8
*) &MemoryWrite
->Data
) {
1870 CopyMem (AlignedDataPtr
, (UINT8
*) &MemoryWrite
->Data
, MemoryWrite
->Count
* MemoryWrite
->Width
);
1872 CopyMemByWidth ((UINT8
*) (UINTN
) MemoryWrite
->Address
, AlignedDataPtr
, MemoryWrite
->Count
, MemoryWrite
->Width
);
1873 SendAckPacket (DEBUG_COMMAND_OK
);
1876 case DEBUG_COMMAND_READ_IO
:
1877 IoRead
= (DEBUG_DATA_READ_IO
*) (DebugHeader
+ 1);
1878 switch (IoRead
->Width
) {
1880 Data64
= IoRead8 ((UINTN
) IoRead
->Port
);
1883 Data64
= IoRead16 ((UINTN
) IoRead
->Port
);
1886 Data64
= IoRead32 ((UINTN
) IoRead
->Port
);
1889 Data64
= IoRead64 ((UINTN
) IoRead
->Port
);
1892 Data64
= (UINT64
) -1;
1894 Status
= SendDataResponsePacket ((UINT8
*) &Data64
, IoRead
->Width
);
1897 case DEBUG_COMMAND_WRITE_IO
:
1898 IoWrite
= (DEBUG_DATA_WRITE_IO
*) (DebugHeader
+ 1);
1899 switch (IoWrite
->Width
) {
1901 Data64
= IoWrite8 ((UINTN
) IoWrite
->Port
, *(UINT8
*) &IoWrite
->Data
);
1904 Data64
= IoWrite16 ((UINTN
) IoWrite
->Port
, *(UINT16
*) &IoWrite
->Data
);
1907 Data64
= IoWrite32 ((UINTN
) IoWrite
->Port
, *(UINT32
*) &IoWrite
->Data
);
1910 Data64
= IoWrite64 ((UINTN
) IoWrite
->Port
, *(UINT64
*) &IoWrite
->Data
);
1913 Data64
= (UINT64
) -1;
1915 SendAckPacket (DEBUG_COMMAND_OK
);
1918 case DEBUG_COMMAND_READ_ALL_REGISTERS
:
1919 Status
= SendDataResponsePacket ((UINT8
*) CpuContext
, sizeof (*CpuContext
));
1922 case DEBUG_COMMAND_READ_REGISTER
:
1923 RegisterRead
= (DEBUG_DATA_READ_REGISTER
*) (DebugHeader
+ 1);
1925 if (RegisterRead
->Index
<= SOFT_DEBUGGER_REGISTER_MAX
) {
1926 RegisterBuffer
= ArchReadRegisterBuffer (CpuContext
, RegisterRead
->Index
, &Width
);
1927 Status
= SendDataResponsePacket (RegisterBuffer
, Width
);
1929 Status
= RETURN_UNSUPPORTED
;
1933 case DEBUG_COMMAND_WRITE_REGISTER
:
1934 RegisterWrite
= (DEBUG_DATA_WRITE_REGISTER
*) (DebugHeader
+ 1);
1935 if (RegisterWrite
->Index
<= SOFT_DEBUGGER_REGISTER_MAX
) {
1936 RegisterBuffer
= ArchReadRegisterBuffer (CpuContext
, RegisterWrite
->Index
, &Width
);
1937 ASSERT (Width
== RegisterWrite
->Length
);
1938 CopyMem (RegisterBuffer
, RegisterWrite
->Data
, Width
);
1939 SendAckPacket (DEBUG_COMMAND_OK
);
1941 Status
= RETURN_UNSUPPORTED
;
1945 case DEBUG_COMMAND_ARCH_MODE
:
1946 Data8
= DEBUG_ARCH_SYMBOL
;
1947 Status
= SendDataResponsePacket ((UINT8
*) &Data8
, (UINT16
) sizeof (UINT8
));
1950 case DEBUG_COMMAND_READ_MSR
:
1951 MsrRegisterRead
= (DEBUG_DATA_READ_MSR
*) (DebugHeader
+ 1);
1952 Data64
= AsmReadMsr64 (MsrRegisterRead
->Index
);
1953 Status
= SendDataResponsePacket ((UINT8
*) &Data64
, (UINT16
) sizeof (UINT64
));
1956 case DEBUG_COMMAND_WRITE_MSR
:
1957 MsrRegisterWrite
= (DEBUG_DATA_WRITE_MSR
*) (DebugHeader
+ 1);
1958 AsmWriteMsr64 (MsrRegisterWrite
->Index
, MsrRegisterWrite
->Value
);
1959 SendAckPacket (DEBUG_COMMAND_OK
);
1962 case DEBUG_COMMAND_SET_DEBUG_SETTING
:
1963 Status
= SetDebugSetting ((DEBUG_DATA_SET_DEBUG_SETTING
*)(DebugHeader
+ 1));
1964 if (Status
== RETURN_SUCCESS
) {
1965 SendAckPacket (DEBUG_COMMAND_OK
);
1969 case DEBUG_COMMAND_GET_REVISION
:
1970 DebugAgentRevision
.Revision
= DEBUG_AGENT_REVISION
;
1971 DebugAgentRevision
.Capabilities
= DEBUG_AGENT_CAPABILITIES
;
1972 Status
= SendDataResponsePacket ((UINT8
*) &DebugAgentRevision
, (UINT16
) sizeof (DEBUG_DATA_RESPONSE_GET_REVISION
));
1975 case DEBUG_COMMAND_GET_EXCEPTION
:
1976 Exception
.ExceptionNum
= (UINT8
) Vector
;
1977 Exception
.ExceptionData
= (UINT32
) CpuContext
->ExceptionData
;
1978 Status
= SendDataResponsePacket ((UINT8
*) &Exception
, (UINT16
) sizeof (DEBUG_DATA_RESPONSE_GET_EXCEPTION
));
1981 case DEBUG_COMMAND_SET_VIEWPOINT
:
1982 SetViewPoint
= (DEBUG_DATA_SET_VIEWPOINT
*) (DebugHeader
+ 1);
1983 if (MultiProcessorDebugSupport()) {
1984 if (IsCpuStopped (SetViewPoint
->ViewPoint
)) {
1985 SetDebugViewPoint (SetViewPoint
->ViewPoint
);
1986 SendAckPacket (DEBUG_COMMAND_OK
);
1989 // If CPU is not halted
1991 SendAckPacket (DEBUG_COMMAND_NOT_SUPPORTED
);
1993 } else if (SetViewPoint
->ViewPoint
== 0) {
1994 SendAckPacket (DEBUG_COMMAND_OK
);
1997 SendAckPacket (DEBUG_COMMAND_NOT_SUPPORTED
);
2002 case DEBUG_COMMAND_GET_VIEWPOINT
:
2003 Data32
= mDebugMpContext
.ViewPointIndex
;
2004 SendDataResponsePacket((UINT8
*) &Data32
, (UINT16
) sizeof (UINT32
));
2007 case DEBUG_COMMAND_MEMORY_READY
:
2008 Data8
= (UINT8
) GetDebugFlag (DEBUG_AGENT_FLAG_MEMORY_READY
);
2009 SendDataResponsePacket (&Data8
, (UINT16
) sizeof (UINT8
));
2012 case DEBUG_COMMAND_DETACH
:
2013 SetHostAttached (FALSE
);
2014 SendAckPacket (DEBUG_COMMAND_OK
);
2017 case DEBUG_COMMAND_CPUID
:
2018 Cpuid
= (DEBUG_DATA_CPUID
*) (DebugHeader
+ 1);
2020 Cpuid
->Eax
, Cpuid
->Ecx
,
2021 &CpuidResponse
.Eax
, &CpuidResponse
.Ebx
,
2022 &CpuidResponse
.Ecx
, &CpuidResponse
.Edx
2024 SendDataResponsePacket ((UINT8
*) &CpuidResponse
, (UINT16
) sizeof (CpuidResponse
));
2027 case DEBUG_COMMAND_SEARCH_SIGNATURE
:
2028 SearchSignature
= (DEBUG_DATA_SEARCH_SIGNATURE
*) (DebugHeader
+ 1);
2029 if ((SearchSignature
->Alignment
!= 0) &&
2030 (SearchSignature
->Alignment
== GetPowerOfTwo32 (SearchSignature
->Alignment
))
2032 if (SearchSignature
->Positive
) {
2034 Data64
= ALIGN_VALUE ((UINTN
) SearchSignature
->Start
, SearchSignature
->Alignment
);
2035 Data64
<= SearchSignature
->Start
+ SearchSignature
->Count
- SearchSignature
->DataLength
;
2036 Data64
+= SearchSignature
->Alignment
2038 if (CompareMem ((VOID
*) (UINTN
) Data64
, &SearchSignature
->Data
, SearchSignature
->DataLength
) == 0) {
2042 if (Data64
> SearchSignature
->Start
+ SearchSignature
->Count
- SearchSignature
->DataLength
) {
2043 Data64
= (UINT64
) -1;
2047 Data64
= ALIGN_VALUE ((UINTN
) SearchSignature
->Start
- SearchSignature
->Alignment
, SearchSignature
->Alignment
);
2048 Data64
>= SearchSignature
->Start
- SearchSignature
->Count
;
2049 Data64
-= SearchSignature
->Alignment
2051 if (CompareMem ((VOID
*) (UINTN
) Data64
, &SearchSignature
->Data
, SearchSignature
->DataLength
) == 0) {
2055 if (Data64
< SearchSignature
->Start
- SearchSignature
->Count
) {
2056 Data64
= (UINT64
) -1;
2059 SendDataResponsePacket ((UINT8
*) &Data64
, (UINT16
) sizeof (Data64
));
2061 Status
= RETURN_UNSUPPORTED
;
2066 SendAckPacket (DEBUG_COMMAND_NOT_SUPPORTED
);
2070 if (Status
== RETURN_UNSUPPORTED
) {
2071 SendAckPacket (DEBUG_COMMAND_NOT_SUPPORTED
);
2072 } else if (Status
!= RETURN_SUCCESS
) {
2073 SendAckPacket (DEBUG_COMMAND_ABORT
);
2076 ReleaseMpSpinLock (&mDebugMpContext
.DebugPortSpinLock
);
2082 C function called in interrupt handler.
2084 @param[in] Vector Vector value of exception or interrutp.
2085 @param[in] CpuContext Pointer to save CPU context.
2092 IN DEBUG_CPU_CONTEXT
*CpuContext
2095 UINT8 InputCharacter
;
2098 BOOLEAN BreakReceived
;
2099 UINT32 ProcessorIndex
;
2100 UINT32 CurrentDebugTimerInitCount
;
2101 DEBUG_PORT_HANDLE Handle
;
2104 UINT32 IssuedViewPoint
;
2105 DEBUG_AGENT_EXCEPTION_BUFFER
*ExceptionBuffer
;
2108 IssuedViewPoint
= 0;
2109 BreakReceived
= FALSE
;
2111 if (mSkipBreakpoint
) {
2113 // If Skip Breakpoint flag is set, means communication is disturbed by hardware SMI, we need to ignore the break points in SMM
2115 if ((Vector
== DEBUG_INT1_VECTOR
) || (Vector
== DEBUG_INT3_VECTOR
)) {
2116 DebugPortWriteBuffer (GetDebugPortHandle(), (UINT8
*) mWarningMsgIngoreBreakpoint
, AsciiStrLen (mWarningMsgIngoreBreakpoint
));
2121 if (MultiProcessorDebugSupport()) {
2122 ProcessorIndex
= GetProcessorIndex ();
2124 // If this processor has alreay halted before, need to check it later
2126 if (IsCpuStopped (ProcessorIndex
)) {
2127 IssuedViewPoint
= ProcessorIndex
;
2131 if (IssuedViewPoint
== ProcessorIndex
&& GetDebugFlag (DEBUG_AGENT_FLAG_STEPPING
) != 1) {
2133 // Check if this exception is issued by Debug Agent itself
2134 // If yes, fill the debug agent exception buffer and LongJump() back to
2135 // the saved CPU content in CommandCommunication()
2137 if (GetDebugFlag (DEBUG_AGENT_FLAG_AGENT_IN_PROGRESS
) == 1) {
2138 DebugAgentMsgPrint (DEBUG_AGENT_ERROR
, "Debug agent meet one Exception, ExceptionNum is %d, EIP = 0x%x.\n", Vector
, (UINTN
)CpuContext
->Eip
);
2139 ExceptionBuffer
= (DEBUG_AGENT_EXCEPTION_BUFFER
*) (UINTN
) GetMailboxPointer()->ExceptionBufferPointer
;
2140 ExceptionBuffer
->ExceptionContent
.ExceptionNum
= (UINT8
) Vector
;
2141 ExceptionBuffer
->ExceptionContent
.ExceptionData
= (UINT32
) CpuContext
->ExceptionData
;
2142 LongJump ((BASE_LIBRARY_JUMP_BUFFER
*)(UINTN
)(ExceptionBuffer
), 1);
2146 if (MultiProcessorDebugSupport()) {
2148 // If RUN commmand is executing, wait for it done.
2150 while (mDebugMpContext
.RunCommandSet
) {
2155 Handle
= GetDebugPortHandle();
2156 BreakCause
= GetBreakCause (Vector
, CpuContext
);
2158 case DEBUG_INT1_VECTOR
:
2159 case DEBUG_INT3_VECTOR
:
2160 switch (BreakCause
) {
2161 case DEBUG_DATA_BREAK_CAUSE_SYSTEM_RESET
:
2162 if (AttachHost (BreakCause
, READ_PACKET_TIMEOUT
, &BreakReceived
) != RETURN_SUCCESS
) {
2164 // Try to connect HOST, return if fails
2168 CommandCommunication (Vector
, CpuContext
, BreakReceived
);
2171 case DEBUG_DATA_BREAK_CAUSE_STEPPING
:
2173 // Stepping is finished, send Ack package.
2175 if (MultiProcessorDebugSupport()) {
2176 mDebugMpContext
.BreakAtCpuIndex
= ProcessorIndex
;
2178 SendAckPacket (DEBUG_COMMAND_OK
);
2179 CommandCommunication (Vector
, CpuContext
, BreakReceived
);
2182 case DEBUG_DATA_BREAK_CAUSE_MEMORY_READY
:
2186 SendCommandAndWaitForAckOK (DEBUG_COMMAND_MEMORY_READY
, READ_PACKET_TIMEOUT
, &BreakReceived
, NULL
);
2187 CommandCommunication (Vector
, CpuContext
, BreakReceived
);
2190 case DEBUG_DATA_BREAK_CAUSE_IMAGE_LOAD
:
2191 case DEBUG_DATA_BREAK_CAUSE_IMAGE_UNLOAD
:
2193 // Set AL to DEBUG_AGENT_IMAGE_CONTINUE
2195 Al
= ArchReadRegisterBuffer (CpuContext
, SOFT_DEBUGGER_REGISTER_AX
, &Data8
);
2196 *Al
= DEBUG_AGENT_IMAGE_CONTINUE
;
2198 if (!IsHostAttached ()) {
2200 // If HOST is not connected for image load/unload, return
2205 // Continue to run the following common code
2208 case DEBUG_DATA_BREAK_CAUSE_HW_BREAKPOINT
:
2209 case DEBUG_DATA_BREAK_CAUSE_SW_BREAKPOINT
:
2212 // Send Break packet to HOST
2214 AcquireMpSpinLock (&mDebugMpContext
.DebugPortSpinLock
);
2216 // Only the first breaking processor could send BREAK_POINT to HOST
2218 if (IsFirstBreakProcessor (ProcessorIndex
)) {
2219 SendBreakPacketToHost (BreakCause
, ProcessorIndex
, &BreakReceived
);
2221 ReleaseMpSpinLock (&mDebugMpContext
.DebugPortSpinLock
);
2223 if (Vector
== DEBUG_INT3_VECTOR
) {
2225 // go back address located "0xCC"
2228 SavedEip
= CpuContext
->Eip
;
2229 CommandCommunication (Vector
, CpuContext
, BreakReceived
);
2230 if ((SavedEip
== CpuContext
->Eip
) &&
2231 (*(UINT8
*) (UINTN
) CpuContext
->Eip
== DEBUG_SW_BREAKPOINT_SYMBOL
)) {
2233 // If this is not a software breakpoint set by HOST,
2239 CommandCommunication (Vector
, CpuContext
, BreakReceived
);
2246 case DEBUG_TIMER_VECTOR
:
2248 AcquireMpSpinLock (&mDebugMpContext
.DebugPortSpinLock
);
2250 if (MultiProcessorDebugSupport()) {
2251 if (IsBsp (ProcessorIndex
)) {
2253 // If current processor is BSP, check Apic timer's init count if changed,
2254 // it may be re-written when switching BSP.
2255 // If it changed, re-initialize debug timer
2257 CurrentDebugTimerInitCount
= GetApicTimerInitCount ();
2258 if (mDebugMpContext
.DebugTimerInitCount
!= CurrentDebugTimerInitCount
) {
2259 InitializeDebugTimer ();
2263 if (!IsBsp (ProcessorIndex
) || mDebugMpContext
.IpiSentByAp
) {
2264 ReleaseMpSpinLock (&mDebugMpContext
.DebugPortSpinLock
);
2266 // If current processor is not BSP or this is one IPI sent by AP
2268 if (mDebugMpContext
.BreakAtCpuIndex
!= (UINT32
) (-1)) {
2269 CommandCommunication (Vector
, CpuContext
, FALSE
);
2273 // Clear EOI before exiting interrupt process routine.
2281 // Only BSP could run here
2285 // If there is data in debug port, will check whether it is break(attach/break-in) symbol,
2286 // If yes, go into communication mode with HOST.
2287 // If no, exit interrupt process.
2289 if (DebugReadBreakSymbol (Handle
, &InputCharacter
) == EFI_NOT_FOUND
) {
2293 if ((!IsHostAttached () && (InputCharacter
== DEBUG_STARTING_SYMBOL_ATTACH
)) ||
2294 (IsHostAttached () && (InputCharacter
== DEBUG_COMMAND_HALT
)) ||
2295 (IsHostAttached () && (InputCharacter
== DEBUG_COMMAND_GO
))
2297 DebugAgentMsgPrint (DEBUG_AGENT_VERBOSE
, "Received data [%02x]\n", InputCharacter
);
2299 // Ack OK for break-in symbol
2301 SendAckPacket (DEBUG_COMMAND_OK
);
2304 // If receive GO command in Debug Timer, means HOST may lost ACK packet before.
2306 if (InputCharacter
== DEBUG_COMMAND_GO
) {
2310 if (!IsHostAttached ()) {
2312 // Try to attach HOST, if no ack received after 200ms, return
2314 if (AttachHost (BreakCause
, READ_PACKET_TIMEOUT
, &BreakReceived
) != RETURN_SUCCESS
) {
2319 if (MultiProcessorDebugSupport()) {
2320 if(FindNextPendingBreakCpu () != -1) {
2321 SetCpuBreakFlagByIndex (ProcessorIndex
, TRUE
);
2323 HaltOtherProcessors (ProcessorIndex
);
2326 ReleaseMpSpinLock (&mDebugMpContext
.DebugPortSpinLock
);
2327 CommandCommunication (Vector
, CpuContext
, BreakReceived
);
2328 AcquireMpSpinLock (&mDebugMpContext
.DebugPortSpinLock
);
2334 // Clear EOI before exiting interrupt process routine.
2338 ReleaseMpSpinLock (&mDebugMpContext
.DebugPortSpinLock
);
2343 if (Vector
<= DEBUG_EXCEPT_SIMD
) {
2344 if (BreakCause
== DEBUG_DATA_BREAK_CAUSE_STEPPING
) {
2346 // Stepping is finished, send Ack package.
2348 if (MultiProcessorDebugSupport()) {
2349 mDebugMpContext
.BreakAtCpuIndex
= ProcessorIndex
;
2351 SendAckPacket (DEBUG_COMMAND_OK
);
2354 // Exception occurs, send Break packet to HOST
2356 AcquireMpSpinLock (&mDebugMpContext
.DebugPortSpinLock
);
2358 // Only the first breaking processor could send BREAK_POINT to HOST
2360 if (IsFirstBreakProcessor (ProcessorIndex
)) {
2361 SendBreakPacketToHost (BreakCause
, ProcessorIndex
, &BreakReceived
);
2363 ReleaseMpSpinLock (&mDebugMpContext
.DebugPortSpinLock
);
2366 CommandCommunication (Vector
, CpuContext
, BreakReceived
);
2371 if (MultiProcessorDebugSupport()) {
2373 // Clear flag and wait for all processors run here
2375 SetIpiSentByApFlag (FALSE
);
2376 while (mDebugMpContext
.RunCommandSet
) {
2381 // Only current (view) processor could clean up AgentInProgress flag.
2383 if (mDebugMpContext
.ViewPointIndex
== ProcessorIndex
) {
2384 IssuedViewPoint
= mDebugMpContext
.ViewPointIndex
;
2388 if (IssuedViewPoint
== ProcessorIndex
&& GetDebugFlag (DEBUG_AGENT_FLAG_STEPPING
) != 1) {
2390 // If the command is not stepping, clean up AgentInProgress flag
2392 SetDebugFlag (DEBUG_AGENT_FLAG_AGENT_IN_PROGRESS
, 0);