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.
578 ReadRemainingBreakPacket (
579 IN DEBUG_PORT_HANDLE Handle
,
580 IN OUT DEBUG_PACKET_HEADER
*DebugHeader
585 // Has received start symbol, try to read the rest part
587 if (DebugPortReadBuffer (Handle
, &DebugHeader
->Command
, sizeof (DEBUG_PACKET_HEADER
) - 1, READ_PACKET_TIMEOUT
) == 0) {
589 // Timeout occur, exit
591 DebugAgentMsgPrint (DEBUG_AGENT_WARNING
, "Timeout in Debug Timer interrupt\n");
595 Crc
= DebugHeader
->Crc
;
596 DebugHeader
->Crc
= 0;
597 if (CalculateCrc16 ((UINT8
*)DebugHeader
, DebugHeader
->Length
, 0) != Crc
) {
598 DebugAgentMsgPrint (DEBUG_AGENT_WARNING
, "Debug Timer CRC (%x) against (%x)\n", Crc
, CalculateCrc16 ((UINT8
*) &DebugHeader
, DebugHeader
->Length
, 0));
599 DebugAgentDataMsgPrint (DEBUG_AGENT_VERBOSE
, FALSE
, (UINT8
*)DebugHeader
, DebugHeader
->Length
);
600 return EFI_CRC_ERROR
;
603 UpdateMailboxContent (GetMailboxPointer(), DEBUG_MAILBOX_HOST_SEQUENCE_NO_INDEX
, DebugHeader
->SequenceNo
);
608 Check if HOST is attached based on Mailbox.
610 @retval TRUE HOST is attached.
611 @retval FALSE HOST is not attached.
619 return (BOOLEAN
) (GetDebugFlag (DEBUG_AGENT_FLAG_HOST_ATTACHED
) == 1);
623 Set HOST connect flag in Mailbox.
625 @param[in] Attached Attach status.
633 DebugAgentMsgPrint (DEBUG_AGENT_INFO
, "Attach status is %d\n", Attached
);
634 SetDebugFlag (DEBUG_AGENT_FLAG_HOST_ATTACHED
, (UINT32
)Attached
);
638 Set debug setting of Debug Agent in Mailbox.
640 @param DebugSetting Pointer to Debug Setting defined by transfer protocol.
642 @retval RETURN_SUCCESS The setting is set successfully.
643 @retval RETURN_UNSUPPORTED The Key value is not supported.
648 IN DEBUG_DATA_SET_DEBUG_SETTING
*DebugSetting
651 RETURN_STATUS Status
;
653 Status
= RETURN_SUCCESS
;
654 switch (DebugSetting
->Key
) {
655 case DEBUG_AGENT_SETTING_SMM_ENTRY_BREAK
:
656 SetDebugFlag (DEBUG_AGENT_FLAG_BREAK_ON_NEXT_SMI
, DebugSetting
->Value
);
658 case DEBUG_AGENT_SETTING_PRINT_ERROR_LEVEL
:
659 SetDebugFlag (DEBUG_AGENT_FLAG_PRINT_ERROR_LEVEL
, DebugSetting
->Value
);
661 case DEBUG_AGENT_SETTING_BOOT_SCRIPT_ENTRY_BREAK
:
662 SetDebugFlag (DEBUG_AGENT_FLAG_BREAK_BOOT_SCRIPT
, DebugSetting
->Value
);
665 Status
= RETURN_UNSUPPORTED
;
673 @param[in] CpuContext Pointer to saved CPU context.
678 IN DEBUG_CPU_CONTEXT
*CpuContext
681 IA32_EFLAGS32
*Eflags
;
683 Eflags
= (IA32_EFLAGS32
*) &CpuContext
->Eflags
;
689 Exectue Stepping command.
691 @param[in] CpuContext Pointer to saved CPU context.
696 IN DEBUG_CPU_CONTEXT
*CpuContext
699 IA32_EFLAGS32
*Eflags
;
701 Eflags
= (IA32_EFLAGS32
*) &CpuContext
->Eflags
;
707 Set debug register for hardware breakpoint.
709 @param[in] CpuContext Pointer to saved CPU context.
710 @param[in] SetHwBreakpoint Hardware breakpoint to be set.
715 IN DEBUG_CPU_CONTEXT
*CpuContext
,
716 IN DEBUG_DATA_SET_HW_BREAKPOINT
*SetHwBreakpoint
722 RegisterIndex
= SetHwBreakpoint
->Type
.Index
;
727 * ((UINTN
*) &CpuContext
->Dr0
+ RegisterIndex
) = (UINTN
) SetHwBreakpoint
->Address
;
729 Dr7Value
= CpuContext
->Dr7
;
734 Dr7Value
|= 0x3 << (RegisterIndex
* 2);
738 Dr7Value
&= ~(0xf << (16 + RegisterIndex
* 4));
739 Dr7Value
|= (UINTN
) ((SetHwBreakpoint
->Type
.Length
<< 2) | SetHwBreakpoint
->Type
.Access
) << (16 + RegisterIndex
* 4);
745 CpuContext
->Dr7
= Dr7Value
;
749 Clear debug register for hardware breakpoint.
751 @param[in] CpuContext Pointer to saved CPU context.
752 @param[in] ClearHwBreakpoint Hardware breakpoint to be cleared.
757 IN DEBUG_CPU_CONTEXT
*CpuContext
,
758 IN DEBUG_DATA_CLEAR_HW_BREAKPOINT
*ClearHwBreakpoint
761 if ((ClearHwBreakpoint
->IndexMask
& BIT0
) != 0) {
763 CpuContext
->Dr7
&= ~(0x3 << 0);
765 if ((ClearHwBreakpoint
->IndexMask
& BIT1
) != 0) {
767 CpuContext
->Dr7
&= ~(0x3 << 2);
769 if ((ClearHwBreakpoint
->IndexMask
& BIT2
) != 0) {
771 CpuContext
->Dr7
&= ~(0x3 << 4);
773 if ((ClearHwBreakpoint
->IndexMask
& BIT3
) != 0) {
775 CpuContext
->Dr7
&= ~(0x3 << 6);
781 Return the offset of FP / MMX / XMM registers in the FPU saved state by register index.
783 @param[in] Index Register index.
784 @param[out] Width Register width returned.
786 @return Offset in the FPU Save State.
790 ArchReadFxStatOffset (
795 if (Index
< SOFT_DEBUGGER_REGISTER_ST0
) {
797 case SOFT_DEBUGGER_REGISTER_FP_FCW
:
798 *Width
= (UINT8
) sizeof (UINT16
);
799 return OFFSET_OF(DEBUG_DATA_FX_SAVE_STATE
, Fcw
);
801 case SOFT_DEBUGGER_REGISTER_FP_FSW
:
802 *Width
= (UINT8
) sizeof (UINT16
);
803 return OFFSET_OF(DEBUG_DATA_FX_SAVE_STATE
, Fsw
);
805 case SOFT_DEBUGGER_REGISTER_FP_FTW
:
806 *Width
= (UINT8
) sizeof (UINT16
);
807 return OFFSET_OF(DEBUG_DATA_FX_SAVE_STATE
, Ftw
);
809 case SOFT_DEBUGGER_REGISTER_FP_OPCODE
:
810 *Width
= (UINT8
) sizeof (UINT16
);
811 return OFFSET_OF(DEBUG_DATA_FX_SAVE_STATE
, Opcode
);
813 case SOFT_DEBUGGER_REGISTER_FP_EIP
:
814 *Width
= (UINT8
) sizeof (UINT32
);
815 return OFFSET_OF(DEBUG_DATA_FX_SAVE_STATE
, Eip
);
817 case SOFT_DEBUGGER_REGISTER_FP_CS
:
818 *Width
= (UINT8
) sizeof (UINT16
);
819 return OFFSET_OF(DEBUG_DATA_FX_SAVE_STATE
, Cs
);
821 case SOFT_DEBUGGER_REGISTER_FP_DATAOFFSET
:
822 *Width
= (UINT8
) sizeof (UINT32
);
823 return OFFSET_OF(DEBUG_DATA_FX_SAVE_STATE
, DataOffset
);
825 case SOFT_DEBUGGER_REGISTER_FP_DS
:
826 *Width
= (UINT8
) sizeof (UINT16
);
827 return OFFSET_OF(DEBUG_DATA_FX_SAVE_STATE
, Ds
);
829 case SOFT_DEBUGGER_REGISTER_FP_MXCSR
:
830 *Width
= (UINT8
) sizeof (UINT32
);
831 return OFFSET_OF(DEBUG_DATA_FX_SAVE_STATE
, Mxcsr
);
833 case SOFT_DEBUGGER_REGISTER_FP_MXCSR_MASK
:
834 *Width
= (UINT8
) sizeof (UINT32
);
835 return OFFSET_OF(DEBUG_DATA_FX_SAVE_STATE
, Mxcsr_Mask
);
839 if (Index
<= SOFT_DEBUGGER_REGISTER_ST7
) {
841 } else if (Index
<= SOFT_DEBUGGER_REGISTER_XMM15
) {
848 Index
-= SOFT_DEBUGGER_REGISTER_MM0
- SOFT_DEBUGGER_REGISTER_ST0
;
851 return OFFSET_OF (DEBUG_DATA_FX_SAVE_STATE
, St0Mm0
) + (Index
- SOFT_DEBUGGER_REGISTER_ST0
) * 16;
855 Return the pointer of the register value in the CPU saved context.
857 @param[in] CpuContext Pointer to saved CPU context.
858 @param[in] Index Register index value.
859 @param[out] Width Data width to read.
861 @return The pointer in the CPU saved context.
865 ArchReadRegisterBuffer (
866 IN DEBUG_CPU_CONTEXT
*CpuContext
,
873 if (Index
< SOFT_DEBUGGER_REGISTER_FP_BASE
) {
874 Buffer
= (UINT8
*) CpuContext
+ OFFSET_OF (DEBUG_CPU_CONTEXT
, Dr0
) + Index
* sizeof (UINTN
);
875 *Width
= (UINT8
) sizeof (UINTN
);
878 // FPU/MMX/XMM registers
880 Buffer
= (UINT8
*) CpuContext
+ OFFSET_OF (DEBUG_CPU_CONTEXT
, FxSaveState
) + ArchReadFxStatOffset (Index
, Width
);
887 Send the packet without data to HOST.
889 @param[in] CommandType Type of Command.
890 @param[in] SequenceNo Sequence number.
894 SendPacketWithoutData (
895 IN UINT8 CommandType
,
899 DEBUG_PACKET_HEADER DebugHeader
;
900 DEBUG_PORT_HANDLE Handle
;
902 Handle
= GetDebugPortHandle();
904 DebugHeader
.StartSymbol
= DEBUG_STARTING_SYMBOL_NORMAL
;
905 DebugHeader
.Command
= CommandType
;
906 DebugHeader
.Length
= sizeof (DEBUG_PACKET_HEADER
);
907 DebugHeader
.SequenceNo
= SequenceNo
;
909 DebugHeader
.Crc
= CalculateCrc16 ((UINT8
*)&DebugHeader
, sizeof (DEBUG_PACKET_HEADER
), 0);
911 DebugAgentDataMsgPrint (DEBUG_AGENT_VERBOSE
, TRUE
, (UINT8
*) &DebugHeader
, DebugHeader
.Length
);
912 DebugPortWriteBuffer (Handle
, (UINT8
*) &DebugHeader
, DebugHeader
.Length
);
916 Send acknowledge packet to HOST.
918 @param[in] AckCommand Type of Acknowledge packet.
927 DEBUG_AGENT_MAILBOX
*Mailbox
;
929 if (AckCommand
!= DEBUG_COMMAND_OK
) {
931 // This is not ACK OK packet
933 DebugAgentMsgPrint (DEBUG_AGENT_ERROR
, "Send ACK(%d)\n", AckCommand
);
935 Mailbox
= GetMailboxPointer();
936 SequenceNo
= Mailbox
->HostSequenceNo
;
937 DebugAgentMsgPrint (DEBUG_AGENT_INFO
, "SendAckPacket: SequenceNo = %x\n", SequenceNo
);
938 SendPacketWithoutData (AckCommand
, SequenceNo
);
939 UpdateMailboxContent (Mailbox
, DEBUG_MAILBOX_LAST_ACK
, AckCommand
);
943 Receive valid packet from HOST.
945 @param[out] InputPacket Buffer to receive packet.
946 @param[out] BreakReceived TRUE means break-in symbol received.
947 FALSE means break-in symbol not received.
948 @param[out] IncompatibilityFlag If IncompatibilityFlag is not NULL, return
949 TRUE: Compatible packet received.
950 FALSE: Incompatible packet received.
951 @param[in] Timeout Time out value to wait for acknowlege from HOST.
952 The unit is microsecond.
953 @param[in] SkipStartSymbol TRUE: Skip time out when reading start symbol.
954 FALSE: Does not Skip time out when reading start symbol.
956 @retval RETURN_SUCCESS A valid package was reveived in InputPacket.
957 @retval RETURN_TIMEOUT Timeout occurs.
962 OUT UINT8
*InputPacket
,
963 OUT BOOLEAN
*BreakReceived
,
964 OUT BOOLEAN
*IncompatibilityFlag
, OPTIONAL
966 IN BOOLEAN SkipStartSymbol
969 DEBUG_PACKET_HEADER
*DebugHeader
;
971 DEBUG_PORT_HANDLE Handle
;
973 UINTN TimeoutForStartSymbol
;
975 Handle
= GetDebugPortHandle();
976 if (SkipStartSymbol
) {
977 TimeoutForStartSymbol
= 0;
979 TimeoutForStartSymbol
= Timeout
;
982 DebugHeader
= (DEBUG_PACKET_HEADER
*) InputPacket
;
985 // Find the valid start symbol
987 Received
= DebugPortReadBuffer (Handle
, &DebugHeader
->StartSymbol
, sizeof (DebugHeader
->StartSymbol
), TimeoutForStartSymbol
);
988 if (Received
< sizeof (DebugHeader
->StartSymbol
)) {
989 DebugAgentMsgPrint (DEBUG_AGENT_WARNING
, "DebugPortReadBuffer(StartSymbol) timeout\n");
990 return RETURN_TIMEOUT
;
993 if (DebugHeader
->StartSymbol
!= DEBUG_STARTING_SYMBOL_NORMAL
) {
994 DebugAgentMsgPrint (DEBUG_AGENT_WARNING
, "Invalid start symbol received [%02x]\n", DebugHeader
->StartSymbol
);
999 // Read Package header till field Length
1001 Received
= DebugPortReadBuffer (
1003 &DebugHeader
->Command
,
1004 OFFSET_OF (DEBUG_PACKET_HEADER
, Length
) + sizeof (DebugHeader
->Length
) - sizeof (DebugHeader
->StartSymbol
),
1007 if (Received
== 0) {
1008 DebugAgentMsgPrint (DEBUG_AGENT_ERROR
, "DebugPortReadBuffer(Command) timeout\n");
1009 return RETURN_TIMEOUT
;
1011 if (DebugHeader
->Length
< sizeof (DEBUG_PACKET_HEADER
)) {
1012 if (IncompatibilityFlag
!= NULL
) {
1014 // This is one old version debug packet format, set Incompatibility flag
1016 *IncompatibilityFlag
= TRUE
;
1019 // Skip the bad small packet
1025 // Read the payload data include the CRC field
1027 Received
= DebugPortReadBuffer (Handle
, &DebugHeader
->SequenceNo
, (UINT8
) (DebugHeader
->Length
- OFFSET_OF (DEBUG_PACKET_HEADER
, SequenceNo
)), Timeout
);
1028 if (Received
== 0) {
1029 DebugAgentMsgPrint (DEBUG_AGENT_ERROR
, "DebugPortReadBuffer(SequenceNo) timeout\n");
1030 return RETURN_TIMEOUT
;
1033 // Calculate the CRC of Debug Packet
1035 Crc
= DebugHeader
->Crc
;
1036 DebugHeader
->Crc
= 0;
1037 if (Crc
== CalculateCrc16 ((UINT8
*) DebugHeader
, DebugHeader
->Length
, 0)) {
1040 DebugAgentMsgPrint (DEBUG_AGENT_WARNING
, "CRC Error (received CRC is %x)\n", Crc
);
1041 DebugAgentDataMsgPrint (DEBUG_AGENT_VERBOSE
, FALSE
, (UINT8
*) DebugHeader
, DebugHeader
->Length
);
1045 DebugAgentDataMsgPrint (DEBUG_AGENT_VERBOSE
, FALSE
, (UINT8
*) DebugHeader
, DebugHeader
->Length
);
1047 return RETURN_SUCCESS
;
1051 Receive acknowledge packet OK from HOST in specified time.
1053 @param[in] Command The command type issued by TARGET.
1054 @param[in] Timeout Time out value to wait for acknowlege from HOST.
1055 The unit is microsecond.
1056 @param[out] BreakReceived If BreakReceived is not NULL,
1057 TRUE is retured if break-in symbol received.
1058 FALSE is retured if break-in symbol not received.
1059 @param[out] IncompatibilityFlag If IncompatibilityFlag is not NULL, return
1060 TRUE: Compatible packet received.
1061 FALSE: Incompatible packet received.
1063 @retval RETRUEN_SUCCESS Succeed to receive acknowlege packet from HOST,
1064 the type of acknowlege packet saved in Ack.
1065 @retval RETURN_TIMEOUT Specified timeout value was up.
1069 SendCommandAndWaitForAckOK (
1072 OUT BOOLEAN
*BreakReceived
, OPTIONAL
1073 OUT BOOLEAN
*IncompatibilityFlag OPTIONAL
1076 RETURN_STATUS Status
;
1077 UINT8 InputPacketBuffer
[DEBUG_DATA_UPPER_LIMIT
];
1078 DEBUG_PACKET_HEADER
*DebugHeader
;
1080 UINT8 HostSequenceNo
;
1084 DebugHeader
= (DEBUG_PACKET_HEADER
*) InputPacketBuffer
;
1085 Status
= RETURN_TIMEOUT
;
1086 while (RetryCount
> 0) {
1087 SequenceNo
= GetMailboxPointer()->SequenceNo
;
1088 HostSequenceNo
= GetMailboxPointer()->HostSequenceNo
;
1089 SendPacketWithoutData (Command
, SequenceNo
);
1090 Status
= ReceivePacket ((UINT8
*) DebugHeader
, BreakReceived
, IncompatibilityFlag
, Timeout
, FALSE
);
1091 if (Status
== RETURN_TIMEOUT
) {
1092 if (Command
== DEBUG_COMMAND_INIT_BREAK
) {
1095 DebugAgentMsgPrint (DEBUG_AGENT_WARNING
, "TARGET: Timeout when waiting for ACK packet.\n");
1099 ASSERT_EFI_ERROR (Status
);
1101 // Status == RETURN_SUCCESS
1103 if (DebugHeader
->Command
== DEBUG_COMMAND_OK
&& DebugHeader
->SequenceNo
== SequenceNo
) {
1107 UpdateMailboxContent (GetMailboxPointer(), DEBUG_MAILBOX_SEQUENCE_NO_INDEX
, ++SequenceNo
);
1110 if (DebugHeader
->Command
== DEBUG_COMMAND_GO
&& (DebugHeader
->SequenceNo
== HostSequenceNo
|| Command
== DEBUG_COMMAND_INIT_BREAK
)) {
1114 if (Command
== DEBUG_COMMAND_INIT_BREAK
) {
1115 DebugAgentMsgPrint (DEBUG_AGENT_WARNING
, "TARGET: Receive GO() in last boot\n");
1117 SendPacketWithoutData (DEBUG_COMMAND_OK
, DebugHeader
->SequenceNo
);
1121 ASSERT (Command
== DEBUG_COMMAND_INIT_BREAK
);
1126 Get current break cause.
1128 @param[in] Vector Vector value of exception or interrupt.
1129 @param[in] CpuContext Pointer to save CPU context.
1131 @return The type of break cause defined by XXXX
1137 IN DEBUG_CPU_CONTEXT
*CpuContext
1142 Cause
= DEBUG_DATA_BREAK_CAUSE_UNKNOWN
;
1145 case DEBUG_INT1_VECTOR
:
1146 case DEBUG_INT3_VECTOR
:
1148 if (Vector
== DEBUG_INT1_VECTOR
) {
1152 if ((CpuContext
->Dr6
& BIT14
) != 0) {
1153 Cause
= DEBUG_DATA_BREAK_CAUSE_STEPPING
;
1155 // If it's single step, no need to check DR0, to ensure single step work in PeCoffExtraActionLib
1156 // (right after triggering a breakpoint to report image load/unload).
1161 Cause
= DEBUG_DATA_BREAK_CAUSE_HW_BREAKPOINT
;
1167 Cause
= DEBUG_DATA_BREAK_CAUSE_SW_BREAKPOINT
;
1170 switch (CpuContext
->Dr0
) {
1171 case IMAGE_LOAD_SIGNATURE
:
1172 case IMAGE_UNLOAD_SIGNATURE
:
1174 if (CpuContext
->Dr3
== IO_PORT_BREAKPOINT_ADDRESS
) {
1176 Cause
= (UINT8
) ((CpuContext
->Dr0
== IMAGE_LOAD_SIGNATURE
) ?
1177 DEBUG_DATA_BREAK_CAUSE_IMAGE_LOAD
: DEBUG_DATA_BREAK_CAUSE_IMAGE_UNLOAD
);
1181 case SOFT_INTERRUPT_SIGNATURE
:
1183 if (CpuContext
->Dr1
== MEMORY_READY_SIGNATURE
) {
1184 Cause
= DEBUG_DATA_BREAK_CAUSE_MEMORY_READY
;
1185 CpuContext
->Dr0
= 0;
1186 } else if (CpuContext
->Dr1
== SYSTEM_RESET_SIGNATURE
) {
1187 Cause
= DEBUG_DATA_BREAK_CAUSE_SYSTEM_RESET
;
1188 CpuContext
->Dr0
= 0;
1199 case DEBUG_TIMER_VECTOR
:
1200 Cause
= DEBUG_DATA_BREAK_CAUSE_USER_HALT
;
1205 if (GetDebugFlag (DEBUG_AGENT_FLAG_STEPPING
) == 1) {
1207 // If stepping command is executing
1209 Cause
= DEBUG_DATA_BREAK_CAUSE_STEPPING
;
1211 Cause
= DEBUG_DATA_BREAK_CAUSE_EXCEPTION
;
1221 Copy memory from source to destination with specified width.
1223 @param[out] Dest A pointer to the destination buffer of the memory copy.
1224 @param[in] Src A pointer to the source buffer of the memory copy.
1225 @param[in] Count The number of data with specified width to copy from source to destination.
1226 @param[in] Width Data width in byte.
1247 // Copy memory from tail to avoid memory overlap
1249 Destination
= Dest
+ (Count
- 1) * Width
;
1250 Source
= Src
+ (Count
- 1) * Width
;
1254 while (Count
-- != 0) {
1257 *(UINT8
*) Destination
= MmioRead8 ((UINTN
) Source
);
1260 *(UINT16
*) Destination
= MmioRead16 ((UINTN
) Source
);
1263 *(UINT32
*) Destination
= MmioRead32 ((UINTN
) Source
);
1266 *(UINT64
*) Destination
= MmioRead64 ((UINTN
) Source
);
1272 Destination
+= Step
;
1277 Read memory with speicifed width and send packet with response data to HOST.
1279 @param[in] Data Pointer to response data buffer.
1280 @param[in] Count The number of data with specified Width.
1281 @param[in] Width Data width in byte.
1283 @retval RETURN_SUCCESS Response data was sent successfully.
1287 ReadMemoryAndSendResponsePacket (
1293 RETURN_STATUS Status
;
1294 DEBUG_PACKET_HEADER
*DebugHeader
;
1296 DEBUG_PACKET_HEADER
*AckDebugHeader
;
1297 UINT8 DebugPacket
[DEBUG_DATA_UPPER_LIMIT
+ sizeof (UINT64
) - 1];
1298 UINT8 InputPacketBuffer
[DEBUG_DATA_UPPER_LIMIT
];
1299 DEBUG_PORT_HANDLE Handle
;
1301 UINTN RemainingDataSize
;
1302 UINTN CurrentDataSize
;
1304 Handle
= GetDebugPortHandle();
1307 // Data is appended end of Debug Packet header, make sure data address
1308 // in Debug Packet 8-byte alignment always
1310 DebugHeader
= (DEBUG_PACKET_HEADER
*) (ALIGN_VALUE ((UINTN
)&DebugPacket
+ sizeof (DEBUG_PACKET_HEADER
), sizeof (UINT64
))
1311 - sizeof (DEBUG_PACKET_HEADER
));
1312 DebugHeader
->StartSymbol
= DEBUG_STARTING_SYMBOL_NORMAL
;
1314 RemainingDataSize
= Count
* Width
;
1316 SequenceNo
= GetMailboxPointer()->HostSequenceNo
;
1317 if (RemainingDataSize
<= DEBUG_DATA_MAXIMUM_REAL_DATA
) {
1319 // If the remaining data is less one real packet size, this is the last data packet
1321 CurrentDataSize
= RemainingDataSize
;
1323 DebugHeader
->Command
= DEBUG_COMMAND_OK
;
1326 // Data is too larger to be sent in one packet, calculate the actual data size could
1327 // be sent in one Maximum data packet
1329 CurrentDataSize
= (DEBUG_DATA_MAXIMUM_REAL_DATA
/ Width
) * Width
;
1331 DebugHeader
->Command
= DEBUG_COMMAND_IN_PROGRESS
;
1334 // Construct the rest Debug header
1336 DebugHeader
->Length
= (UINT8
)(CurrentDataSize
+ sizeof (DEBUG_PACKET_HEADER
));
1337 DebugHeader
->SequenceNo
= SequenceNo
;
1338 DebugHeader
->Crc
= 0;
1339 CopyMemByWidth ((UINT8
*)(DebugHeader
+ 1), Data
, (UINT16
) CurrentDataSize
/ Width
, Width
);
1341 // Calculate and fill the checksum, DebugHeader->Crc should be 0 before invoking CalculateCrc16 ()
1343 DebugHeader
->Crc
= CalculateCrc16 ((UINT8
*) DebugHeader
, DebugHeader
->Length
, 0);
1345 DebugAgentDataMsgPrint (DEBUG_AGENT_VERBOSE
, TRUE
, (UINT8
*) DebugHeader
, DebugHeader
->Length
);
1347 DebugPortWriteBuffer (Handle
, (UINT8
*) DebugHeader
, DebugHeader
->Length
);
1350 Status
= ReceivePacket (InputPacketBuffer
, NULL
, NULL
, READ_PACKET_TIMEOUT
, FALSE
);
1351 if (Status
== RETURN_TIMEOUT
) {
1352 DebugAgentMsgPrint (DEBUG_AGENT_WARNING
, "TARGET: Timeout in SendDataResponsePacket()\n");
1355 AckDebugHeader
= (DEBUG_PACKET_HEADER
*) InputPacketBuffer
;
1356 SequenceNo
= AckDebugHeader
->SequenceNo
;
1357 if (AckDebugHeader
->Command
== DEBUG_COMMAND_OK
&&
1358 SequenceNo
== DebugHeader
->SequenceNo
&&
1361 // If this is the last packet, return RETURN_SUCCESS.
1363 return RETURN_SUCCESS
;
1365 if ((SequenceNo
== (UINT8
) (DebugHeader
->SequenceNo
+ 1)) && (AckDebugHeader
->Command
== DEBUG_COMMAND_CONTINUE
)) {
1367 // Calculate the rest data size
1369 Data
+= CurrentDataSize
;
1370 RemainingDataSize
-= CurrentDataSize
;
1371 UpdateMailboxContent (GetMailboxPointer(), DEBUG_MAILBOX_HOST_SEQUENCE_NO_INDEX
, (UINT8
) SequenceNo
);
1374 if (SequenceNo
>= DebugHeader
->SequenceNo
) {
1375 DebugAgentMsgPrint (DEBUG_AGENT_WARNING
, "TARGET: Received one old or new command(SequenceNo is %x, last SequenceNo is %x)\n", SequenceNo
, DebugHeader
->SequenceNo
);
1383 Send packet with response data to HOST.
1385 @param[in] Data Pointer to response data buffer.
1386 @param[in] DataSize Size of response data in byte.
1388 @retval RETURN_SUCCESS Response data was sent successfully.
1392 SendDataResponsePacket (
1397 return ReadMemoryAndSendResponsePacket (Data
, DataSize
, 1);
1401 Send break cause packet to HOST.
1403 @param[in] Vector Vector value of exception or interrutp.
1404 @param[in] CpuContext Pointer to save CPU context.
1406 @retval RETURN_SUCCESS Response data was sent successfully.
1407 @retval RETURN_DEVICE_ERROR Cannot receive DEBUG_COMMAND_OK from HOST.
1411 SendBreakCausePacket (
1413 IN DEBUG_CPU_CONTEXT
*CpuContext
1416 DEBUG_DATA_RESPONSE_BREAK_CAUSE DebugDataBreakCause
;
1418 DebugDataBreakCause
.StopAddress
= CpuContext
->Eip
;
1419 DebugDataBreakCause
.Cause
= GetBreakCause (Vector
, CpuContext
);
1421 return SendDataResponsePacket ((UINT8
*) &DebugDataBreakCause
, (UINT16
) sizeof (DEBUG_DATA_RESPONSE_BREAK_CAUSE
));
1425 Try to attach the HOST.
1427 Send init break packet to HOST:
1428 If no acknowlege received in specified Timeout, return RETURN_TIMEOUT.
1429 If received acknowlege, check the revision of HOST.
1430 Set Attach Flag if attach successfully.
1432 @param[in] BreakCause Break cause of this break event.
1433 @param[in] Timeout Time out value to wait for acknowlege from HOST.
1434 The unit is microsecond.
1435 @param[out] BreakReceived If BreakReceived is not NULL,
1436 TRUE is retured if break-in symbol received.
1437 FALSE is retured if break-in symbol not received.
1441 IN UINT8 BreakCause
,
1443 OUT BOOLEAN
*BreakReceived
1446 RETURN_STATUS Status
;
1447 DEBUG_PORT_HANDLE Handle
;
1448 BOOLEAN IncompatibilityFlag
;
1450 IncompatibilityFlag
= FALSE
;
1451 Handle
= GetDebugPortHandle();
1454 // Send init break and wait ack in Timeout
1456 DebugPortWriteBuffer (Handle
, (UINT8
*) mErrorMsgSendInitPacket
, AsciiStrLen (mErrorMsgSendInitPacket
));
1457 if (BreakCause
== DEBUG_DATA_BREAK_CAUSE_SYSTEM_RESET
) {
1458 Status
= SendCommandAndWaitForAckOK (DEBUG_COMMAND_INIT_BREAK
, Timeout
, BreakReceived
, &IncompatibilityFlag
);
1460 Status
= SendCommandAndWaitForAckOK (DEBUG_COMMAND_ATTACH_BREAK
, Timeout
, BreakReceived
, &IncompatibilityFlag
);
1462 if (IncompatibilityFlag
) {
1464 // If the incompatible Debug Packet received, the HOST should be running transfer protocol before DEBUG_AGENT_REVISION.
1465 // It could be UDK Debugger for Windows v1.1/v1.2 or for Linux v0.8/v1.2.
1467 DebugPortWriteBuffer (Handle
, (UINT8
*) mErrorMsgVersionAlert
, AsciiStrLen (mErrorMsgVersionAlert
));
1471 if (RETURN_ERROR (Status
)) {
1472 DebugPortWriteBuffer (Handle
, (UINT8
*) mErrorMsgConnectFail
, AsciiStrLen (mErrorMsgConnectFail
));
1474 DebugPortWriteBuffer (Handle
, (UINT8
*) mErrorMsgConnectOK
, AsciiStrLen (mErrorMsgConnectOK
));
1478 SetHostAttached (TRUE
);
1484 Send Break point packet to HOST.
1486 Only the first breaking processor could sent BREAK_POINT packet.
1488 @param[in] BreakCause Break cause of this break event.
1489 @param[in] ProcessorIndex Processor index value.
1490 @param[out] BreakReceived If BreakReceived is not NULL,
1491 TRUE is retured if break-in symbol received.
1492 FALSE is retured if break-in symbol not received.
1496 SendBreakPacketToHost (
1497 IN UINT8 BreakCause
,
1498 IN UINT32 ProcessorIndex
,
1499 OUT BOOLEAN
*BreakReceived
1502 UINT8 InputCharacter
;
1503 DEBUG_PORT_HANDLE Handle
;
1505 Handle
= GetDebugPortHandle();
1507 if (IsHostAttached ()) {
1508 DebugAgentMsgPrint (DEBUG_AGENT_INFO
, "processor[%x]:Send Break Packet to HOST.\n", ProcessorIndex
);
1509 SendCommandAndWaitForAckOK (DEBUG_COMMAND_BREAK_POINT
, READ_PACKET_TIMEOUT
, BreakReceived
, NULL
);
1511 DebugAgentMsgPrint (DEBUG_AGENT_INFO
, "processor[%x]:Try to attach HOST.\n", ProcessorIndex
);
1513 // If HOST is not attached, try to attach it firstly.
1516 // Poll Attach symbols from HOST and ack OK
1519 DebugPortReadBuffer (Handle
, &InputCharacter
, 1, 0);
1520 } while (InputCharacter
!= DEBUG_STARTING_SYMBOL_ATTACH
);
1521 SendAckPacket (DEBUG_COMMAND_OK
);
1524 // Try to attach HOST
1526 while (AttachHost (BreakCause
, 0, NULL
) != RETURN_SUCCESS
);
1532 The main function to process communication with HOST.
1534 It received the command packet from HOST, and sent response data packet to HOST.
1536 @param[in] Vector Vector value of exception or interrutp.
1537 @param[in, out] CpuContext Pointer to saved CPU context.
1538 @param[in] BreakReceived TRUE means break-in symbol received.
1539 FALSE means break-in symbol not received.
1543 CommandCommunication (
1545 IN OUT DEBUG_CPU_CONTEXT
*CpuContext
,
1546 IN BOOLEAN BreakReceived
1549 RETURN_STATUS Status
;
1550 UINT8 InputPacketBuffer
[DEBUG_DATA_UPPER_LIMIT
+ sizeof (UINT64
) - 1];
1551 DEBUG_PACKET_HEADER
*DebugHeader
;
1556 DEBUG_DATA_READ_MEMORY
*MemoryRead
;
1557 DEBUG_DATA_WRITE_MEMORY
*MemoryWrite
;
1558 DEBUG_DATA_READ_IO
*IoRead
;
1559 DEBUG_DATA_WRITE_IO
*IoWrite
;
1560 DEBUG_DATA_READ_REGISTER
*RegisterRead
;
1561 DEBUG_DATA_WRITE_REGISTER
*RegisterWrite
;
1562 UINT8
*RegisterBuffer
;
1563 DEBUG_DATA_READ_MSR
*MsrRegisterRead
;
1564 DEBUG_DATA_WRITE_MSR
*MsrRegisterWrite
;
1565 DEBUG_DATA_CPUID
*Cpuid
;
1566 DEBUG_DATA_RESPONSE_CPUID CpuidResponse
;
1567 DEBUG_DATA_SEARCH_SIGNATURE
*SearchSignature
;
1568 DEBUG_DATA_RESPONSE_GET_EXCEPTION Exception
;
1569 DEBUG_DATA_RESPONSE_GET_REVISION DebugAgentRevision
;
1570 DEBUG_DATA_SET_VIEWPOINT
*SetViewPoint
;
1571 BOOLEAN HaltDeferred
;
1572 UINT32 ProcessorIndex
;
1573 DEBUG_PORT_HANDLE Handle
;
1574 DEBUG_AGENT_EXCEPTION_BUFFER AgentExceptionBuffer
;
1575 UINT32 IssuedViewPoint
;
1576 DEBUG_AGENT_MAILBOX
*Mailbox
;
1577 UINT8
*AlignedDataPtr
;
1580 IssuedViewPoint
= 0;
1581 HaltDeferred
= BreakReceived
;
1583 if (MultiProcessorDebugSupport()) {
1584 ProcessorIndex
= GetProcessorIndex ();
1585 SetCpuStopFlagByIndex (ProcessorIndex
, TRUE
);
1586 if (mDebugMpContext
.ViewPointIndex
== ProcessorIndex
) {
1588 // Only the current view processor could set AgentInProgress Flag.
1590 IssuedViewPoint
= ProcessorIndex
;
1594 if (IssuedViewPoint
== ProcessorIndex
) {
1596 // Set AgentInProgress Flag.
1598 SetDebugFlag (DEBUG_AGENT_FLAG_AGENT_IN_PROGRESS
, 1);
1601 Handle
= GetDebugPortHandle();
1605 if (MultiProcessorDebugSupport()) {
1607 // Check if the current processor is HOST view point
1609 if (mDebugMpContext
.ViewPointIndex
!= ProcessorIndex
) {
1610 if (mDebugMpContext
.RunCommandSet
) {
1612 // If HOST view point sets RUN flag, run GO command to leave
1614 SetCpuStopFlagByIndex (ProcessorIndex
, FALSE
);
1615 CommandGo (CpuContext
);
1619 // Run into loop again
1627 AcquireMpSpinLock (&mDebugMpContext
.DebugPortSpinLock
);
1629 DebugHeader
=(DEBUG_PACKET_HEADER
*) InputPacketBuffer
;
1631 DebugAgentMsgPrint (DEBUG_AGENT_INFO
, "TARGET: Try to get command from HOST...\n");
1632 Status
= ReceivePacket ((UINT8
*)DebugHeader
, &BreakReceived
, NULL
, READ_PACKET_TIMEOUT
, TRUE
);
1633 if (Status
!= RETURN_SUCCESS
|| (DebugHeader
->Command
& DEBUG_COMMAND_RESPONSE
) != 0) {
1634 DebugAgentMsgPrint (DEBUG_AGENT_WARNING
, "TARGET: Get command[%x] sequenceno[%x] returned status is [%x] \n", DebugHeader
->Command
, DebugHeader
->SequenceNo
, Status
);
1635 DebugAgentMsgPrint (DEBUG_AGENT_WARNING
, "TARGET: Get command failed or it's response packet not expected! \n");
1636 ReleaseMpSpinLock (&mDebugMpContext
.DebugPortSpinLock
);
1640 Mailbox
= GetMailboxPointer ();
1641 if (DebugHeader
->SequenceNo
== Mailbox
->HostSequenceNo
) {
1642 DebugAgentMsgPrint (DEBUG_AGENT_WARNING
, "TARGET: Receive one old command[%x] agaist command[%x]\n", DebugHeader
->SequenceNo
, Mailbox
->HostSequenceNo
);
1643 SendAckPacket (Mailbox
->LastAck
);
1644 ReleaseMpSpinLock (&mDebugMpContext
.DebugPortSpinLock
);
1646 } else if (DebugHeader
->SequenceNo
== (UINT8
) (Mailbox
->HostSequenceNo
+ 1)) {
1647 UpdateMailboxContent (Mailbox
, DEBUG_MAILBOX_HOST_SEQUENCE_NO_INDEX
, (UINT8
) DebugHeader
->SequenceNo
);
1649 DebugAgentMsgPrint (DEBUG_AGENT_WARNING
, "Receive one invalid comamnd[%x] agaist command[%x]\n", DebugHeader
->SequenceNo
, Mailbox
->HostSequenceNo
);
1650 ReleaseMpSpinLock (&mDebugMpContext
.DebugPortSpinLock
);
1655 // Save CPU content before executing HOST commond
1657 UpdateMailboxContent (Mailbox
, DEBUG_MAILBOX_EXCEPTION_BUFFER_POINTER_INDEX
, (UINT64
)(UINTN
) &AgentExceptionBuffer
.JumpBuffer
);
1658 if (SetJump (&AgentExceptionBuffer
.JumpBuffer
) != 0) {
1660 // If HOST command failed, continue to wait for HOST's next command
1661 // If needed, agent could send exception info to HOST.
1663 SendAckPacket (DEBUG_COMMAND_ABORT
);
1664 ReleaseMpSpinLock (&mDebugMpContext
.DebugPortSpinLock
);
1668 DebugAgentMsgPrint (DEBUG_AGENT_INFO
, "Processor[%x]:Received one command(%x)\n", mDebugMpContext
.ViewPointIndex
, DebugHeader
->Command
);
1670 switch (DebugHeader
->Command
) {
1672 case DEBUG_COMMAND_HALT
:
1673 SendAckPacket (DEBUG_COMMAND_HALT_DEFERRED
);
1674 HaltDeferred
= TRUE
;
1675 BreakReceived
= FALSE
;
1676 Status
= RETURN_SUCCESS
;
1679 case DEBUG_COMMAND_RESET
:
1680 SendAckPacket (DEBUG_COMMAND_OK
);
1681 SendAckPacket (DEBUG_COMMAND_OK
);
1682 SendAckPacket (DEBUG_COMMAND_OK
);
1683 ReleaseMpSpinLock (&mDebugMpContext
.DebugPortSpinLock
);
1687 // Assume system resets in 2 seconds, otherwise send TIMEOUT packet.
1688 // PCD can be used if 2 seconds isn't long enough for some platforms.
1690 MicroSecondDelay (2000000);
1691 UpdateMailboxContent (Mailbox
, DEBUG_MAILBOX_HOST_SEQUENCE_NO_INDEX
, Mailbox
->HostSequenceNo
+ 1);
1692 SendAckPacket (DEBUG_COMMAND_TIMEOUT
);
1693 SendAckPacket (DEBUG_COMMAND_TIMEOUT
);
1694 SendAckPacket (DEBUG_COMMAND_TIMEOUT
);
1697 case DEBUG_COMMAND_GO
:
1698 CommandGo (CpuContext
);
1700 // Clear Dr0 to avoid to be recognized as IMAGE_LOAD/_UNLOAD again when hitting a breakpoint after GO
1701 // If HOST changed Dr0 before GO, we will not change Dr0 here
1703 Data8
= GetBreakCause (Vector
, CpuContext
);
1704 if (Data8
== DEBUG_DATA_BREAK_CAUSE_IMAGE_LOAD
|| Data8
== DEBUG_DATA_BREAK_CAUSE_IMAGE_UNLOAD
) {
1705 CpuContext
->Dr0
= 0;
1708 // Clear Stepping Flag
1710 SetDebugFlag (DEBUG_AGENT_FLAG_STEPPING
, 0);
1712 if (!HaltDeferred
) {
1714 // If no HALT command received when being in-active mode
1716 if (MultiProcessorDebugSupport()) {
1717 Data32
= FindNextPendingBreakCpu ();
1720 // If there are still others processors being in break state,
1721 // send OK packet to HOST to finish this go command
1723 SendAckPacket (DEBUG_COMMAND_OK
);
1726 // Set current view to the next breaking processor
1728 mDebugMpContext
.ViewPointIndex
= Data32
;
1729 mDebugMpContext
.BreakAtCpuIndex
= mDebugMpContext
.ViewPointIndex
;
1730 SetCpuBreakFlagByIndex (mDebugMpContext
.ViewPointIndex
, FALSE
);
1732 // Send break packet to HOST to let HOST break again
1734 SendBreakPacketToHost (DEBUG_DATA_BREAK_CAUSE_UNKNOWN
, mDebugMpContext
.BreakAtCpuIndex
, &BreakReceived
);
1736 // Continue to run into loop to read command packet from HOST
1738 ReleaseMpSpinLock (&mDebugMpContext
.DebugPortSpinLock
);
1743 // If no else processor break, set stop bitmask,
1744 // and set Running flag for all processors.
1746 SetCpuStopFlagByIndex (ProcessorIndex
, FALSE
);
1747 SetCpuRunningFlag (TRUE
);
1750 // Wait for all processors are in running state
1753 if (IsAllCpuRunning ()) {
1758 // Set BSP to be current view point.
1760 SetDebugViewPoint (mDebugMpContext
.BspIndex
);
1763 // Clear breaking processor index and running flag
1765 mDebugMpContext
.BreakAtCpuIndex
= (UINT32
) (-1);
1766 SetCpuRunningFlag (FALSE
);
1770 // Send OK packet to HOST to finish this go command
1772 SendAckPacket (DEBUG_COMMAND_OK
);
1774 ReleaseMpSpinLock (&mDebugMpContext
.DebugPortSpinLock
);
1776 if (!IsHostAttached()) {
1777 UpdateMailboxContent (Mailbox
, DEBUG_MAILBOX_SEQUENCE_NO_INDEX
, 0);
1778 UpdateMailboxContent (Mailbox
, DEBUG_MAILBOX_HOST_SEQUENCE_NO_INDEX
, 0);
1784 // If reveived HALT command, need to defer the GO command
1786 SendAckPacket (DEBUG_COMMAND_HALT_PROCESSED
);
1787 HaltDeferred
= FALSE
;
1789 Vector
= DEBUG_TIMER_VECTOR
;
1793 case DEBUG_COMMAND_BREAK_CAUSE
:
1795 if (MultiProcessorDebugSupport() && ProcessorIndex
!= mDebugMpContext
.BreakAtCpuIndex
) {
1796 Status
= SendBreakCausePacket (DEBUG_TIMER_VECTOR
, CpuContext
);
1799 Status
= SendBreakCausePacket (Vector
, CpuContext
);
1804 case DEBUG_COMMAND_SET_HW_BREAKPOINT
:
1805 SetDebugRegister (CpuContext
, (DEBUG_DATA_SET_HW_BREAKPOINT
*) (DebugHeader
+ 1));
1806 SendAckPacket (DEBUG_COMMAND_OK
);
1809 case DEBUG_COMMAND_CLEAR_HW_BREAKPOINT
:
1810 ClearDebugRegister (CpuContext
, (DEBUG_DATA_CLEAR_HW_BREAKPOINT
*) (DebugHeader
+ 1));
1811 SendAckPacket (DEBUG_COMMAND_OK
);
1814 case DEBUG_COMMAND_SINGLE_STEPPING
:
1815 CommandStepping (CpuContext
);
1817 // Clear Dr0 to avoid to be recognized as IMAGE_LOAD/_UNLOAD again when hitting a breakpoint after GO
1818 // If HOST changed Dr0 before GO, we will not change Dr0 here
1820 Data8
= GetBreakCause (Vector
, CpuContext
);
1821 if (Data8
== DEBUG_DATA_BREAK_CAUSE_IMAGE_LOAD
|| Data8
== DEBUG_DATA_BREAK_CAUSE_IMAGE_UNLOAD
) {
1822 CpuContext
->Dr0
= 0;
1825 mDebugMpContext
.BreakAtCpuIndex
= (UINT32
) (-1);
1827 // Set Stepping Flag
1829 SetDebugFlag (DEBUG_AGENT_FLAG_STEPPING
, 1);
1830 ReleaseMpSpinLock (&mDebugMpContext
.DebugPortSpinLock
);
1832 // Executing stepping command directly without sending ACK packet,
1833 // ACK packet will be sent after stepping done.
1837 case DEBUG_COMMAND_SET_SW_BREAKPOINT
:
1838 Data64
= (UINTN
) (((DEBUG_DATA_SET_SW_BREAKPOINT
*) (DebugHeader
+ 1))->Address
);
1839 Data8
= *(UINT8
*) (UINTN
) Data64
;
1840 *(UINT8
*) (UINTN
) Data64
= DEBUG_SW_BREAKPOINT_SYMBOL
;
1841 Status
= SendDataResponsePacket ((UINT8
*) &Data8
, (UINT16
) sizeof (UINT8
));
1844 case DEBUG_COMMAND_READ_MEMORY
:
1845 MemoryRead
= (DEBUG_DATA_READ_MEMORY
*) (DebugHeader
+ 1);
1846 Status
= ReadMemoryAndSendResponsePacket ((UINT8
*) (UINTN
) MemoryRead
->Address
, MemoryRead
->Count
, MemoryRead
->Width
);
1849 case DEBUG_COMMAND_WRITE_MEMORY
:
1850 MemoryWrite
= (DEBUG_DATA_WRITE_MEMORY
*) (DebugHeader
+ 1);
1852 // Copy data into one memory with 8-byte alignment address
1854 AlignedDataPtr
= ALIGN_POINTER ((UINT8
*) &MemoryWrite
->Data
, sizeof (UINT64
));
1855 if (AlignedDataPtr
!= (UINT8
*) &MemoryWrite
->Data
) {
1856 CopyMem (AlignedDataPtr
, (UINT8
*) &MemoryWrite
->Data
, MemoryWrite
->Count
* MemoryWrite
->Width
);
1858 CopyMemByWidth ((UINT8
*) (UINTN
) MemoryWrite
->Address
, AlignedDataPtr
, MemoryWrite
->Count
, MemoryWrite
->Width
);
1859 SendAckPacket (DEBUG_COMMAND_OK
);
1862 case DEBUG_COMMAND_READ_IO
:
1863 IoRead
= (DEBUG_DATA_READ_IO
*) (DebugHeader
+ 1);
1864 switch (IoRead
->Width
) {
1866 Data64
= IoRead8 ((UINTN
) IoRead
->Port
);
1869 Data64
= IoRead16 ((UINTN
) IoRead
->Port
);
1872 Data64
= IoRead32 ((UINTN
) IoRead
->Port
);
1875 Data64
= IoRead64 ((UINTN
) IoRead
->Port
);
1878 Data64
= (UINT64
) -1;
1880 Status
= SendDataResponsePacket ((UINT8
*) &Data64
, IoRead
->Width
);
1883 case DEBUG_COMMAND_WRITE_IO
:
1884 IoWrite
= (DEBUG_DATA_WRITE_IO
*) (DebugHeader
+ 1);
1885 switch (IoWrite
->Width
) {
1887 Data64
= IoWrite8 ((UINTN
) IoWrite
->Port
, *(UINT8
*) &IoWrite
->Data
);
1890 Data64
= IoWrite16 ((UINTN
) IoWrite
->Port
, *(UINT16
*) &IoWrite
->Data
);
1893 Data64
= IoWrite32 ((UINTN
) IoWrite
->Port
, *(UINT32
*) &IoWrite
->Data
);
1896 Data64
= IoWrite64 ((UINTN
) IoWrite
->Port
, *(UINT64
*) &IoWrite
->Data
);
1899 Data64
= (UINT64
) -1;
1901 SendAckPacket (DEBUG_COMMAND_OK
);
1904 case DEBUG_COMMAND_READ_ALL_REGISTERS
:
1905 Status
= SendDataResponsePacket ((UINT8
*) CpuContext
, sizeof (*CpuContext
));
1908 case DEBUG_COMMAND_READ_REGISTER
:
1909 RegisterRead
= (DEBUG_DATA_READ_REGISTER
*) (DebugHeader
+ 1);
1911 if (RegisterRead
->Index
<= SOFT_DEBUGGER_REGISTER_MAX
) {
1912 RegisterBuffer
= ArchReadRegisterBuffer (CpuContext
, RegisterRead
->Index
, &Width
);
1913 Status
= SendDataResponsePacket (RegisterBuffer
, Width
);
1915 Status
= RETURN_UNSUPPORTED
;
1919 case DEBUG_COMMAND_WRITE_REGISTER
:
1920 RegisterWrite
= (DEBUG_DATA_WRITE_REGISTER
*) (DebugHeader
+ 1);
1921 if (RegisterWrite
->Index
<= SOFT_DEBUGGER_REGISTER_MAX
) {
1922 RegisterBuffer
= ArchReadRegisterBuffer (CpuContext
, RegisterWrite
->Index
, &Width
);
1923 ASSERT (Width
== RegisterWrite
->Length
);
1924 CopyMem (RegisterBuffer
, RegisterWrite
->Data
, Width
);
1925 SendAckPacket (DEBUG_COMMAND_OK
);
1927 Status
= RETURN_UNSUPPORTED
;
1931 case DEBUG_COMMAND_ARCH_MODE
:
1932 Data8
= DEBUG_ARCH_SYMBOL
;
1933 Status
= SendDataResponsePacket ((UINT8
*) &Data8
, (UINT16
) sizeof (UINT8
));
1936 case DEBUG_COMMAND_READ_MSR
:
1937 MsrRegisterRead
= (DEBUG_DATA_READ_MSR
*) (DebugHeader
+ 1);
1938 Data64
= AsmReadMsr64 (MsrRegisterRead
->Index
);
1939 Status
= SendDataResponsePacket ((UINT8
*) &Data64
, (UINT16
) sizeof (UINT64
));
1942 case DEBUG_COMMAND_WRITE_MSR
:
1943 MsrRegisterWrite
= (DEBUG_DATA_WRITE_MSR
*) (DebugHeader
+ 1);
1944 AsmWriteMsr64 (MsrRegisterWrite
->Index
, MsrRegisterWrite
->Value
);
1945 SendAckPacket (DEBUG_COMMAND_OK
);
1948 case DEBUG_COMMAND_SET_DEBUG_SETTING
:
1949 Status
= SetDebugSetting ((DEBUG_DATA_SET_DEBUG_SETTING
*)(DebugHeader
+ 1));
1950 if (Status
== RETURN_SUCCESS
) {
1951 SendAckPacket (DEBUG_COMMAND_OK
);
1955 case DEBUG_COMMAND_GET_REVISION
:
1956 DebugAgentRevision
.Revision
= DEBUG_AGENT_REVISION
;
1957 DebugAgentRevision
.Capabilities
= DEBUG_AGENT_CAPABILITIES
;
1958 Status
= SendDataResponsePacket ((UINT8
*) &DebugAgentRevision
, (UINT16
) sizeof (DEBUG_DATA_RESPONSE_GET_REVISION
));
1961 case DEBUG_COMMAND_GET_EXCEPTION
:
1962 Exception
.ExceptionNum
= (UINT8
) Vector
;
1963 Exception
.ExceptionData
= (UINT32
) CpuContext
->ExceptionData
;
1964 Status
= SendDataResponsePacket ((UINT8
*) &Exception
, (UINT16
) sizeof (DEBUG_DATA_RESPONSE_GET_EXCEPTION
));
1967 case DEBUG_COMMAND_SET_VIEWPOINT
:
1968 SetViewPoint
= (DEBUG_DATA_SET_VIEWPOINT
*) (DebugHeader
+ 1);
1969 if (MultiProcessorDebugSupport()) {
1970 if (IsCpuStopped (SetViewPoint
->ViewPoint
)) {
1971 SetDebugViewPoint (SetViewPoint
->ViewPoint
);
1972 SendAckPacket (DEBUG_COMMAND_OK
);
1975 // If CPU is not halted
1977 SendAckPacket (DEBUG_COMMAND_NOT_SUPPORTED
);
1979 } else if (SetViewPoint
->ViewPoint
== 0) {
1980 SendAckPacket (DEBUG_COMMAND_OK
);
1983 SendAckPacket (DEBUG_COMMAND_NOT_SUPPORTED
);
1988 case DEBUG_COMMAND_GET_VIEWPOINT
:
1989 Data32
= mDebugMpContext
.ViewPointIndex
;
1990 SendDataResponsePacket((UINT8
*) &Data32
, (UINT16
) sizeof (UINT32
));
1993 case DEBUG_COMMAND_MEMORY_READY
:
1994 Data8
= (UINT8
) GetDebugFlag (DEBUG_AGENT_FLAG_MEMORY_READY
);
1995 SendDataResponsePacket (&Data8
, (UINT16
) sizeof (UINT8
));
1998 case DEBUG_COMMAND_DETACH
:
1999 SetHostAttached (FALSE
);
2000 SendAckPacket (DEBUG_COMMAND_OK
);
2003 case DEBUG_COMMAND_CPUID
:
2004 Cpuid
= (DEBUG_DATA_CPUID
*) (DebugHeader
+ 1);
2006 Cpuid
->Eax
, Cpuid
->Ecx
,
2007 &CpuidResponse
.Eax
, &CpuidResponse
.Ebx
,
2008 &CpuidResponse
.Ecx
, &CpuidResponse
.Edx
2010 SendDataResponsePacket ((UINT8
*) &CpuidResponse
, (UINT16
) sizeof (CpuidResponse
));
2013 case DEBUG_COMMAND_SEARCH_SIGNATURE
:
2014 SearchSignature
= (DEBUG_DATA_SEARCH_SIGNATURE
*) (DebugHeader
+ 1);
2015 if ((SearchSignature
->Alignment
!= 0) &&
2016 (SearchSignature
->Alignment
== GetPowerOfTwo32 (SearchSignature
->Alignment
))
2018 if (SearchSignature
->Positive
) {
2020 Data64
= ALIGN_VALUE ((UINTN
) SearchSignature
->Start
, SearchSignature
->Alignment
);
2021 Data64
<= SearchSignature
->Start
+ SearchSignature
->Count
- SearchSignature
->DataLength
;
2022 Data64
+= SearchSignature
->Alignment
2024 if (CompareMem ((VOID
*) (UINTN
) Data64
, &SearchSignature
->Data
, SearchSignature
->DataLength
) == 0) {
2028 if (Data64
> SearchSignature
->Start
+ SearchSignature
->Count
- SearchSignature
->DataLength
) {
2029 Data64
= (UINT64
) -1;
2033 Data64
= ALIGN_VALUE ((UINTN
) SearchSignature
->Start
- SearchSignature
->Alignment
, SearchSignature
->Alignment
);
2034 Data64
>= SearchSignature
->Start
- SearchSignature
->Count
;
2035 Data64
-= SearchSignature
->Alignment
2037 if (CompareMem ((VOID
*) (UINTN
) Data64
, &SearchSignature
->Data
, SearchSignature
->DataLength
) == 0) {
2041 if (Data64
< SearchSignature
->Start
- SearchSignature
->Count
) {
2042 Data64
= (UINT64
) -1;
2045 SendDataResponsePacket ((UINT8
*) &Data64
, (UINT16
) sizeof (Data64
));
2047 Status
= RETURN_UNSUPPORTED
;
2052 SendAckPacket (DEBUG_COMMAND_NOT_SUPPORTED
);
2056 if (Status
== RETURN_UNSUPPORTED
) {
2057 SendAckPacket (DEBUG_COMMAND_NOT_SUPPORTED
);
2058 } else if (Status
!= RETURN_SUCCESS
) {
2059 SendAckPacket (DEBUG_COMMAND_ABORT
);
2062 ReleaseMpSpinLock (&mDebugMpContext
.DebugPortSpinLock
);
2068 C function called in interrupt handler.
2070 @param[in] Vector Vector value of exception or interrutp.
2071 @param[in] CpuContext Pointer to save CPU context.
2078 IN DEBUG_CPU_CONTEXT
*CpuContext
2081 UINT8 InputCharacter
;
2084 BOOLEAN BreakReceived
;
2085 UINT32 ProcessorIndex
;
2086 UINT32 CurrentDebugTimerInitCount
;
2087 DEBUG_PORT_HANDLE Handle
;
2090 UINT32 IssuedViewPoint
;
2091 DEBUG_AGENT_EXCEPTION_BUFFER
*ExceptionBuffer
;
2094 IssuedViewPoint
= 0;
2095 BreakReceived
= FALSE
;
2097 if (mSkipBreakpoint
) {
2099 // If Skip Breakpoint flag is set, means communication is disturbed by hardware SMI, we need to ignore the break points in SMM
2101 if ((Vector
== DEBUG_INT1_VECTOR
) || (Vector
== DEBUG_INT3_VECTOR
)) {
2102 DebugPortWriteBuffer (GetDebugPortHandle(), (UINT8
*) mWarningMsgIngoreBreakpoint
, AsciiStrLen (mWarningMsgIngoreBreakpoint
));
2107 if (MultiProcessorDebugSupport()) {
2108 ProcessorIndex
= GetProcessorIndex ();
2110 // If this processor has alreay halted before, need to check it later
2112 if (IsCpuStopped (ProcessorIndex
)) {
2113 IssuedViewPoint
= ProcessorIndex
;
2117 if (IssuedViewPoint
== ProcessorIndex
&& GetDebugFlag (DEBUG_AGENT_FLAG_STEPPING
) != 1) {
2119 // Check if this exception is issued by Debug Agent itself
2120 // If yes, fill the debug agent exception buffer and LongJump() back to
2121 // the saved CPU content in CommandCommunication()
2123 if (GetDebugFlag (DEBUG_AGENT_FLAG_AGENT_IN_PROGRESS
) == 1) {
2124 DebugAgentMsgPrint (DEBUG_AGENT_ERROR
, "Debug agent meet one Exception, ExceptionNum is %d, EIP = 0x%x.\n", Vector
, (UINTN
)CpuContext
->Eip
);
2125 ExceptionBuffer
= (DEBUG_AGENT_EXCEPTION_BUFFER
*) (UINTN
) GetMailboxPointer()->ExceptionBufferPointer
;
2126 ExceptionBuffer
->ExceptionContent
.ExceptionNum
= (UINT8
) Vector
;
2127 ExceptionBuffer
->ExceptionContent
.ExceptionData
= (UINT32
) CpuContext
->ExceptionData
;
2128 LongJump ((BASE_LIBRARY_JUMP_BUFFER
*)(UINTN
)(ExceptionBuffer
), 1);
2132 if (MultiProcessorDebugSupport()) {
2134 // If RUN commmand is executing, wait for it done.
2136 while (mDebugMpContext
.RunCommandSet
) {
2141 Handle
= GetDebugPortHandle();
2142 BreakCause
= GetBreakCause (Vector
, CpuContext
);
2144 case DEBUG_INT1_VECTOR
:
2145 case DEBUG_INT3_VECTOR
:
2146 switch (BreakCause
) {
2147 case DEBUG_DATA_BREAK_CAUSE_SYSTEM_RESET
:
2148 if (AttachHost (BreakCause
, READ_PACKET_TIMEOUT
, &BreakReceived
) != RETURN_SUCCESS
) {
2150 // Try to connect HOST, return if fails
2154 CommandCommunication (Vector
, CpuContext
, BreakReceived
);
2157 case DEBUG_DATA_BREAK_CAUSE_STEPPING
:
2159 // Stepping is finished, send Ack package.
2161 if (MultiProcessorDebugSupport()) {
2162 mDebugMpContext
.BreakAtCpuIndex
= ProcessorIndex
;
2164 SendAckPacket (DEBUG_COMMAND_OK
);
2165 CommandCommunication (Vector
, CpuContext
, BreakReceived
);
2168 case DEBUG_DATA_BREAK_CAUSE_MEMORY_READY
:
2172 SendCommandAndWaitForAckOK (DEBUG_COMMAND_MEMORY_READY
, READ_PACKET_TIMEOUT
, &BreakReceived
, NULL
);
2173 CommandCommunication (Vector
, CpuContext
, BreakReceived
);
2176 case DEBUG_DATA_BREAK_CAUSE_IMAGE_LOAD
:
2177 case DEBUG_DATA_BREAK_CAUSE_IMAGE_UNLOAD
:
2179 // Set AL to DEBUG_AGENT_IMAGE_CONTINUE
2181 Al
= ArchReadRegisterBuffer (CpuContext
, SOFT_DEBUGGER_REGISTER_AX
, &Data8
);
2182 *Al
= DEBUG_AGENT_IMAGE_CONTINUE
;
2184 if (!IsHostAttached ()) {
2186 // If HOST is not connected for image load/unload, return
2191 // Continue to run the following common code
2194 case DEBUG_DATA_BREAK_CAUSE_HW_BREAKPOINT
:
2195 case DEBUG_DATA_BREAK_CAUSE_SW_BREAKPOINT
:
2198 // Send Break packet to HOST
2200 AcquireMpSpinLock (&mDebugMpContext
.DebugPortSpinLock
);
2202 // Only the first breaking processor could send BREAK_POINT to HOST
2204 if (IsFirstBreakProcessor (ProcessorIndex
)) {
2205 SendBreakPacketToHost (BreakCause
, ProcessorIndex
, &BreakReceived
);
2207 ReleaseMpSpinLock (&mDebugMpContext
.DebugPortSpinLock
);
2209 if (Vector
== DEBUG_INT3_VECTOR
) {
2211 // go back address located "0xCC"
2214 SavedEip
= CpuContext
->Eip
;
2215 CommandCommunication (Vector
, CpuContext
, BreakReceived
);
2216 if ((SavedEip
== CpuContext
->Eip
) &&
2217 (*(UINT8
*) (UINTN
) CpuContext
->Eip
== DEBUG_SW_BREAKPOINT_SYMBOL
)) {
2219 // If this is not a software breakpoint set by HOST,
2225 CommandCommunication (Vector
, CpuContext
, BreakReceived
);
2232 case DEBUG_TIMER_VECTOR
:
2234 AcquireMpSpinLock (&mDebugMpContext
.DebugPortSpinLock
);
2236 if (MultiProcessorDebugSupport()) {
2237 if (IsBsp (ProcessorIndex
)) {
2239 // If current processor is BSP, check Apic timer's init count if changed,
2240 // it may be re-written when switching BSP.
2241 // If it changed, re-initialize debug timer
2243 CurrentDebugTimerInitCount
= GetApicTimerInitCount ();
2244 if (mDebugMpContext
.DebugTimerInitCount
!= CurrentDebugTimerInitCount
) {
2245 InitializeDebugTimer ();
2249 if (!IsBsp (ProcessorIndex
) || mDebugMpContext
.IpiSentByAp
) {
2250 ReleaseMpSpinLock (&mDebugMpContext
.DebugPortSpinLock
);
2252 // If current processor is not BSP or this is one IPI sent by AP
2254 if (mDebugMpContext
.BreakAtCpuIndex
!= (UINT32
) (-1)) {
2255 CommandCommunication (Vector
, CpuContext
, FALSE
);
2259 // Clear EOI before exiting interrupt process routine.
2267 // Only BSP could run here
2271 // If there is data in debug port, will check whether it is break(attach/break-in) symbol,
2272 // If yes, go into communication mode with HOST.
2273 // If no, exit interrupt process.
2275 if (DebugReadBreakSymbol (Handle
, &InputCharacter
) == EFI_NOT_FOUND
) {
2279 if ((!IsHostAttached () && (InputCharacter
== DEBUG_STARTING_SYMBOL_ATTACH
)) ||
2280 (IsHostAttached () && (InputCharacter
== DEBUG_COMMAND_HALT
)) ||
2281 (IsHostAttached () && (InputCharacter
== DEBUG_COMMAND_GO
))
2283 DebugAgentMsgPrint (DEBUG_AGENT_VERBOSE
, "Received data [%02x]\n", InputCharacter
);
2285 // Ack OK for break-in symbol
2287 SendAckPacket (DEBUG_COMMAND_OK
);
2290 // If receive GO command in Debug Timer, means HOST may lost ACK packet before.
2292 if (InputCharacter
== DEBUG_COMMAND_GO
) {
2296 if (!IsHostAttached ()) {
2298 // Try to attach HOST, if no ack received after 200ms, return
2300 if (AttachHost (BreakCause
, READ_PACKET_TIMEOUT
, &BreakReceived
) != RETURN_SUCCESS
) {
2305 if (MultiProcessorDebugSupport()) {
2306 if(FindNextPendingBreakCpu () != -1) {
2307 SetCpuBreakFlagByIndex (ProcessorIndex
, TRUE
);
2309 HaltOtherProcessors (ProcessorIndex
);
2312 ReleaseMpSpinLock (&mDebugMpContext
.DebugPortSpinLock
);
2313 CommandCommunication (Vector
, CpuContext
, BreakReceived
);
2314 AcquireMpSpinLock (&mDebugMpContext
.DebugPortSpinLock
);
2320 // Clear EOI before exiting interrupt process routine.
2324 ReleaseMpSpinLock (&mDebugMpContext
.DebugPortSpinLock
);
2329 if (Vector
<= DEBUG_EXCEPT_SIMD
) {
2330 if (BreakCause
== DEBUG_DATA_BREAK_CAUSE_STEPPING
) {
2332 // Stepping is finished, send Ack package.
2334 if (MultiProcessorDebugSupport()) {
2335 mDebugMpContext
.BreakAtCpuIndex
= ProcessorIndex
;
2337 SendAckPacket (DEBUG_COMMAND_OK
);
2340 // Exception occurs, send Break packet to HOST
2342 AcquireMpSpinLock (&mDebugMpContext
.DebugPortSpinLock
);
2344 // Only the first breaking processor could send BREAK_POINT to HOST
2346 if (IsFirstBreakProcessor (ProcessorIndex
)) {
2347 SendBreakPacketToHost (BreakCause
, ProcessorIndex
, &BreakReceived
);
2349 ReleaseMpSpinLock (&mDebugMpContext
.DebugPortSpinLock
);
2352 CommandCommunication (Vector
, CpuContext
, BreakReceived
);
2357 if (MultiProcessorDebugSupport()) {
2359 // Clear flag and wait for all processors run here
2361 SetIpiSentByApFlag (FALSE
);
2362 while (mDebugMpContext
.RunCommandSet
) {
2367 // Only current (view) processor could clean up AgentInProgress flag.
2369 if (mDebugMpContext
.ViewPointIndex
== ProcessorIndex
) {
2370 IssuedViewPoint
= mDebugMpContext
.ViewPointIndex
;
2374 if (IssuedViewPoint
== ProcessorIndex
&& GetDebugFlag (DEBUG_AGENT_FLAG_STEPPING
) != 1) {
2376 // If the command is not stepping, clean up AgentInProgress flag
2378 SetDebugFlag (DEBUG_AGENT_FLAG_AGENT_IN_PROGRESS
, 0);