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 DebugAgentMsgPrint (DEBUG_AGENT_INFO
, "Update HostSequenceNo to %x\n", Value
);
378 Mailbox
->ToBeCheckSum
= Mailbox
->CheckSum
+ CalculateSum8 ((UINT8
*)&Mailbox
->HostSequenceNo
, sizeof(UINT8
))
379 - CalculateSum8 ((UINT8
*)&Value
, sizeof(UINT8
));
380 Mailbox
->HostSequenceNo
= (UINT8
) Value
;
383 UpdateMailboxChecksum (Mailbox
);
384 ReleaseMpSpinLock (&mDebugMpContext
.MailboxSpinLock
);
387 Set debug flag in mailbox.
389 @param[in] FlagMask Debug flag mask value.
390 @param[in] FlagValue Debug flag value.
399 DEBUG_AGENT_MAILBOX
*Mailbox
;
402 Mailbox
= GetMailboxPointer ();
403 Data64
= (Mailbox
->DebugFlag
.Uint64
& ~FlagMask
) |
404 (LShiftU64 ((UINT64
)FlagValue
, LowBitSet64 (FlagMask
)) & FlagMask
);
405 UpdateMailboxContent (Mailbox
, DEBUG_MAILBOX_DEBUG_FLAG_INDEX
, Data64
);
409 Get debug flag in mailbox.
411 @param[in] FlagMask Debug flag mask value.
413 @return Debug flag value.
421 DEBUG_AGENT_MAILBOX
*Mailbox
;
424 Mailbox
= GetMailboxPointer ();
425 DebugFlag
= (UINT32
) RShiftU64 (Mailbox
->DebugFlag
.Uint64
& FlagMask
, LowBitSet64 (FlagMask
));
431 Send a debug message packet to the debug port.
433 @param[in] Buffer The debug message.
434 @param[in] Length The length of debug message.
443 DEBUG_PACKET_HEADER DebugHeader
;
444 DEBUG_PORT_HANDLE Handle
;
446 Handle
= GetDebugPortHandle();
448 DebugHeader
.StartSymbol
= DEBUG_STARTING_SYMBOL_NORMAL
;
449 DebugHeader
.Command
= DEBUG_COMMAND_PRINT_MESSAGE
;
450 DebugHeader
.Length
= sizeof (DEBUG_PACKET_HEADER
) + (UINT8
) Length
;
451 DebugHeader
.SequenceNo
= 0xEE;
453 DebugHeader
.Crc
= CalculateCrc16 (
454 (UINT8
*)Buffer
, Length
,
455 CalculateCrc16 ((UINT8
*)&DebugHeader
, sizeof (DEBUG_PACKET_HEADER
), 0)
458 DebugPortWriteBuffer (Handle
, (UINT8
*)&DebugHeader
, sizeof (DEBUG_PACKET_HEADER
));
459 DebugPortWriteBuffer (Handle
, (UINT8
*)Buffer
, Length
);
463 Prints a debug message to the debug port if the specified error level is enabled.
465 If any bit in ErrorLevel is also set in Mainbox, then print the message specified
466 by Format and the associated variable argument list to the debug port.
468 @param[in] ErrorLevel The error level of the debug message.
469 @param[in] Format Format string for the debug message to print.
470 @param[in] ... Variable argument list whose contents are accessed
471 based on the format string specified by Format.
482 CHAR8 Buffer
[DEBUG_DATA_MAXIMUM_REAL_DATA
];
486 // Check driver debug mask value and global mask
488 if ((ErrorLevel
& GetDebugFlag (DEBUG_AGENT_FLAG_PRINT_ERROR_LEVEL
)) == 0) {
493 // Convert the DEBUG() message to an ASCII String
495 VA_START (Marker
, Format
);
496 AsciiVSPrint (Buffer
, sizeof (Buffer
), Format
, Marker
);
499 SendDebugMsgPacket (Buffer
, AsciiStrLen (Buffer
));
503 Prints a debug message to the debug output device if the specified error level is enabled.
505 If any bit in ErrorLevel is also set in DebugPrintErrorLevelLib function
506 GetDebugPrintErrorLevel (), then print the message specified by Format and the
507 associated variable argument list to the debug output device.
509 If Format is NULL, then ASSERT().
511 @param[in] ErrorLevel The error level of the debug message.
512 @param[in] IsSend Flag of debug message to declare that the data is being sent or being received.
513 @param[in] Data Variable argument list whose contents are accessed
514 @param[in] Length based on the format string specified by Format.
519 DebugAgentDataMsgPrint (
526 CHAR8 Buffer
[DEBUG_DATA_MAXIMUM_REAL_DATA
];
531 // Check driver debug mask value and global mask
533 if ((ErrorLevel
& GetDebugFlag (DEBUG_AGENT_FLAG_PRINT_ERROR_LEVEL
)) == 0) {
539 DestBuffer
+= AsciiSPrint (DestBuffer
, DEBUG_DATA_MAXIMUM_REAL_DATA
, "Sent data [ ");
541 DestBuffer
+= AsciiSPrint (DestBuffer
, DEBUG_DATA_MAXIMUM_REAL_DATA
, "Received data [ ");
546 if (DestBuffer
- Buffer
> DEBUG_DATA_MAXIMUM_REAL_DATA
- 6) {
548 // If there was no enough space in buffer, send out the debug message,
549 // reserving 6 bytes is for the last data and end characters "]\n".
551 SendDebugMsgPacket (Buffer
, DestBuffer
- Buffer
);
554 DestBuffer
+= AsciiSPrint (DestBuffer
, DEBUG_DATA_MAXIMUM_REAL_DATA
- (DestBuffer
- Buffer
), "%02x ", Data
[Index
]);
556 if (Index
>= Length
) {
558 // The last character of debug message has been foramtted in buffer
560 DestBuffer
+= AsciiSPrint(DestBuffer
, DEBUG_DATA_MAXIMUM_REAL_DATA
- (DestBuffer
- Buffer
), "]\n");
561 SendDebugMsgPacket (Buffer
, DestBuffer
- Buffer
);
568 Read remaing debug packet except for the start symbol
570 @param[in] Handle Pointer to Debug Port handle.
571 @param[in, out] DebugHeader Debug header buffer including start symbol.
573 @retval EFI_SUCCESS Read the symbol in BreakSymbol.
574 @retval EFI_CRC_ERROR CRC check fail.
575 @retval EFI_TIMEOUT Timeout occurs when reading debug packet.
576 @retval EFI_DEVICE_ERROR Receive the old or responsed packet.
580 ReadRemainingBreakPacket (
581 IN DEBUG_PORT_HANDLE Handle
,
582 IN OUT DEBUG_PACKET_HEADER
*DebugHeader
586 DEBUG_AGENT_MAILBOX
*Mailbox
;
589 // Has received start symbol, try to read the rest part
591 if (DebugPortReadBuffer (Handle
, &DebugHeader
->Command
, sizeof (DEBUG_PACKET_HEADER
) - 1, READ_PACKET_TIMEOUT
) == 0) {
593 // Timeout occur, exit
595 DebugAgentMsgPrint (DEBUG_AGENT_WARNING
, "Timeout in Debug Timer interrupt\n");
599 Crc
= DebugHeader
->Crc
;
600 DebugHeader
->Crc
= 0;
601 if (CalculateCrc16 ((UINT8
*)DebugHeader
, DebugHeader
->Length
, 0) != Crc
) {
602 DebugAgentMsgPrint (DEBUG_AGENT_WARNING
, "Debug Timer CRC (%x) against (%x)\n", Crc
, CalculateCrc16 ((UINT8
*) &DebugHeader
, DebugHeader
->Length
, 0));
603 DebugAgentDataMsgPrint (DEBUG_AGENT_VERBOSE
, FALSE
, (UINT8
*)DebugHeader
, DebugHeader
->Length
);
604 return EFI_CRC_ERROR
;
606 Mailbox
= GetMailboxPointer();
607 if (((DebugHeader
->Command
& DEBUG_COMMAND_RESPONSE
) != 0) &&
608 (DebugHeader
->SequenceNo
== (UINT8
) (Mailbox
->HostSequenceNo
+ 1))) {
610 // Only updagte HostSequenceNo for new command packet
612 UpdateMailboxContent (Mailbox
, DEBUG_MAILBOX_HOST_SEQUENCE_NO_INDEX
, DebugHeader
->SequenceNo
);
616 // If one old command or response packet received, skip it
618 return EFI_DEVICE_ERROR
;
623 Check if HOST is attached based on Mailbox.
625 @retval TRUE HOST is attached.
626 @retval FALSE HOST is not attached.
634 return (BOOLEAN
) (GetDebugFlag (DEBUG_AGENT_FLAG_HOST_ATTACHED
) == 1);
638 Set HOST connect flag in Mailbox.
640 @param[in] Attached Attach status.
648 DebugAgentMsgPrint (DEBUG_AGENT_INFO
, "Attach status is %d\n", Attached
);
649 SetDebugFlag (DEBUG_AGENT_FLAG_HOST_ATTACHED
, (UINT32
)Attached
);
653 Set debug setting of Debug Agent in Mailbox.
655 @param DebugSetting Pointer to Debug Setting defined by transfer protocol.
657 @retval RETURN_SUCCESS The setting is set successfully.
658 @retval RETURN_UNSUPPORTED The Key value is not supported.
663 IN DEBUG_DATA_SET_DEBUG_SETTING
*DebugSetting
666 RETURN_STATUS Status
;
668 Status
= RETURN_SUCCESS
;
669 switch (DebugSetting
->Key
) {
670 case DEBUG_AGENT_SETTING_SMM_ENTRY_BREAK
:
671 SetDebugFlag (DEBUG_AGENT_FLAG_BREAK_ON_NEXT_SMI
, DebugSetting
->Value
);
673 case DEBUG_AGENT_SETTING_PRINT_ERROR_LEVEL
:
674 SetDebugFlag (DEBUG_AGENT_FLAG_PRINT_ERROR_LEVEL
, DebugSetting
->Value
);
676 case DEBUG_AGENT_SETTING_BOOT_SCRIPT_ENTRY_BREAK
:
677 SetDebugFlag (DEBUG_AGENT_FLAG_BREAK_BOOT_SCRIPT
, DebugSetting
->Value
);
680 Status
= RETURN_UNSUPPORTED
;
688 @param[in] CpuContext Pointer to saved CPU context.
693 IN DEBUG_CPU_CONTEXT
*CpuContext
696 IA32_EFLAGS32
*Eflags
;
698 Eflags
= (IA32_EFLAGS32
*) &CpuContext
->Eflags
;
704 Exectue Stepping command.
706 @param[in] CpuContext Pointer to saved CPU context.
711 IN DEBUG_CPU_CONTEXT
*CpuContext
714 IA32_EFLAGS32
*Eflags
;
716 Eflags
= (IA32_EFLAGS32
*) &CpuContext
->Eflags
;
722 Set debug register for hardware breakpoint.
724 @param[in] CpuContext Pointer to saved CPU context.
725 @param[in] SetHwBreakpoint Hardware breakpoint to be set.
730 IN DEBUG_CPU_CONTEXT
*CpuContext
,
731 IN DEBUG_DATA_SET_HW_BREAKPOINT
*SetHwBreakpoint
737 RegisterIndex
= SetHwBreakpoint
->Type
.Index
;
742 * ((UINTN
*) &CpuContext
->Dr0
+ RegisterIndex
) = (UINTN
) SetHwBreakpoint
->Address
;
744 Dr7Value
= CpuContext
->Dr7
;
749 Dr7Value
|= 0x3 << (RegisterIndex
* 2);
753 Dr7Value
&= ~(0xf << (16 + RegisterIndex
* 4));
754 Dr7Value
|= (UINTN
) ((SetHwBreakpoint
->Type
.Length
<< 2) | SetHwBreakpoint
->Type
.Access
) << (16 + RegisterIndex
* 4);
760 CpuContext
->Dr7
= Dr7Value
;
764 Clear debug register for hardware breakpoint.
766 @param[in] CpuContext Pointer to saved CPU context.
767 @param[in] ClearHwBreakpoint Hardware breakpoint to be cleared.
772 IN DEBUG_CPU_CONTEXT
*CpuContext
,
773 IN DEBUG_DATA_CLEAR_HW_BREAKPOINT
*ClearHwBreakpoint
776 if ((ClearHwBreakpoint
->IndexMask
& BIT0
) != 0) {
778 CpuContext
->Dr7
&= ~(0x3 << 0);
780 if ((ClearHwBreakpoint
->IndexMask
& BIT1
) != 0) {
782 CpuContext
->Dr7
&= ~(0x3 << 2);
784 if ((ClearHwBreakpoint
->IndexMask
& BIT2
) != 0) {
786 CpuContext
->Dr7
&= ~(0x3 << 4);
788 if ((ClearHwBreakpoint
->IndexMask
& BIT3
) != 0) {
790 CpuContext
->Dr7
&= ~(0x3 << 6);
796 Return the offset of FP / MMX / XMM registers in the FPU saved state by register index.
798 @param[in] Index Register index.
799 @param[out] Width Register width returned.
801 @return Offset in the FPU Save State.
805 ArchReadFxStatOffset (
810 if (Index
< SOFT_DEBUGGER_REGISTER_ST0
) {
812 case SOFT_DEBUGGER_REGISTER_FP_FCW
:
813 *Width
= (UINT8
) sizeof (UINT16
);
814 return OFFSET_OF(DEBUG_DATA_FX_SAVE_STATE
, Fcw
);
816 case SOFT_DEBUGGER_REGISTER_FP_FSW
:
817 *Width
= (UINT8
) sizeof (UINT16
);
818 return OFFSET_OF(DEBUG_DATA_FX_SAVE_STATE
, Fsw
);
820 case SOFT_DEBUGGER_REGISTER_FP_FTW
:
821 *Width
= (UINT8
) sizeof (UINT16
);
822 return OFFSET_OF(DEBUG_DATA_FX_SAVE_STATE
, Ftw
);
824 case SOFT_DEBUGGER_REGISTER_FP_OPCODE
:
825 *Width
= (UINT8
) sizeof (UINT16
);
826 return OFFSET_OF(DEBUG_DATA_FX_SAVE_STATE
, Opcode
);
828 case SOFT_DEBUGGER_REGISTER_FP_EIP
:
829 *Width
= (UINT8
) sizeof (UINT32
);
830 return OFFSET_OF(DEBUG_DATA_FX_SAVE_STATE
, Eip
);
832 case SOFT_DEBUGGER_REGISTER_FP_CS
:
833 *Width
= (UINT8
) sizeof (UINT16
);
834 return OFFSET_OF(DEBUG_DATA_FX_SAVE_STATE
, Cs
);
836 case SOFT_DEBUGGER_REGISTER_FP_DATAOFFSET
:
837 *Width
= (UINT8
) sizeof (UINT32
);
838 return OFFSET_OF(DEBUG_DATA_FX_SAVE_STATE
, DataOffset
);
840 case SOFT_DEBUGGER_REGISTER_FP_DS
:
841 *Width
= (UINT8
) sizeof (UINT16
);
842 return OFFSET_OF(DEBUG_DATA_FX_SAVE_STATE
, Ds
);
844 case SOFT_DEBUGGER_REGISTER_FP_MXCSR
:
845 *Width
= (UINT8
) sizeof (UINT32
);
846 return OFFSET_OF(DEBUG_DATA_FX_SAVE_STATE
, Mxcsr
);
848 case SOFT_DEBUGGER_REGISTER_FP_MXCSR_MASK
:
849 *Width
= (UINT8
) sizeof (UINT32
);
850 return OFFSET_OF(DEBUG_DATA_FX_SAVE_STATE
, Mxcsr_Mask
);
854 if (Index
<= SOFT_DEBUGGER_REGISTER_ST7
) {
856 } else if (Index
<= SOFT_DEBUGGER_REGISTER_XMM15
) {
863 Index
-= SOFT_DEBUGGER_REGISTER_MM0
- SOFT_DEBUGGER_REGISTER_ST0
;
866 return OFFSET_OF (DEBUG_DATA_FX_SAVE_STATE
, St0Mm0
) + (Index
- SOFT_DEBUGGER_REGISTER_ST0
) * 16;
870 Return the pointer of the register value in the CPU saved context.
872 @param[in] CpuContext Pointer to saved CPU context.
873 @param[in] Index Register index value.
874 @param[out] Width Data width to read.
876 @return The pointer in the CPU saved context.
880 ArchReadRegisterBuffer (
881 IN DEBUG_CPU_CONTEXT
*CpuContext
,
888 if (Index
< SOFT_DEBUGGER_REGISTER_FP_BASE
) {
889 Buffer
= (UINT8
*) CpuContext
+ OFFSET_OF (DEBUG_CPU_CONTEXT
, Dr0
) + Index
* sizeof (UINTN
);
890 *Width
= (UINT8
) sizeof (UINTN
);
893 // FPU/MMX/XMM registers
895 Buffer
= (UINT8
*) CpuContext
+ OFFSET_OF (DEBUG_CPU_CONTEXT
, FxSaveState
) + ArchReadFxStatOffset (Index
, Width
);
902 Send the packet without data to HOST.
904 @param[in] CommandType Type of Command.
905 @param[in] SequenceNo Sequence number.
909 SendPacketWithoutData (
910 IN UINT8 CommandType
,
914 DEBUG_PACKET_HEADER DebugHeader
;
915 DEBUG_PORT_HANDLE Handle
;
917 Handle
= GetDebugPortHandle();
919 DebugHeader
.StartSymbol
= DEBUG_STARTING_SYMBOL_NORMAL
;
920 DebugHeader
.Command
= CommandType
;
921 DebugHeader
.Length
= sizeof (DEBUG_PACKET_HEADER
);
922 DebugHeader
.SequenceNo
= SequenceNo
;
924 DebugHeader
.Crc
= CalculateCrc16 ((UINT8
*)&DebugHeader
, sizeof (DEBUG_PACKET_HEADER
), 0);
926 DebugAgentDataMsgPrint (DEBUG_AGENT_VERBOSE
, TRUE
, (UINT8
*) &DebugHeader
, DebugHeader
.Length
);
927 DebugPortWriteBuffer (Handle
, (UINT8
*) &DebugHeader
, DebugHeader
.Length
);
931 Send acknowledge packet to HOST.
933 @param[in] AckCommand Type of Acknowledge packet.
942 DEBUG_AGENT_MAILBOX
*Mailbox
;
944 if (AckCommand
!= DEBUG_COMMAND_OK
) {
946 // This is not ACK OK packet
948 DebugAgentMsgPrint (DEBUG_AGENT_ERROR
, "Send ACK(%d)\n", AckCommand
);
950 Mailbox
= GetMailboxPointer();
951 SequenceNo
= Mailbox
->HostSequenceNo
;
952 DebugAgentMsgPrint (DEBUG_AGENT_INFO
, "SendAckPacket: SequenceNo = %x\n", SequenceNo
);
953 SendPacketWithoutData (AckCommand
, SequenceNo
);
954 UpdateMailboxContent (Mailbox
, DEBUG_MAILBOX_LAST_ACK
, AckCommand
);
958 Receive valid packet from HOST.
960 @param[out] InputPacket Buffer to receive packet.
961 @param[out] BreakReceived TRUE means break-in symbol received.
962 FALSE means break-in symbol not received.
963 @param[out] IncompatibilityFlag If IncompatibilityFlag is not NULL, return
964 TRUE: Compatible packet received.
965 FALSE: Incompatible packet received.
966 @param[in] Timeout Time out value to wait for acknowlege from HOST.
967 The unit is microsecond.
968 @param[in] SkipStartSymbol TRUE: Skip time out when reading start symbol.
969 FALSE: Does not Skip time out when reading start symbol.
971 @retval RETURN_SUCCESS A valid package was reveived in InputPacket.
972 @retval RETURN_TIMEOUT Timeout occurs.
977 OUT UINT8
*InputPacket
,
978 OUT BOOLEAN
*BreakReceived
,
979 OUT BOOLEAN
*IncompatibilityFlag
, OPTIONAL
981 IN BOOLEAN SkipStartSymbol
984 DEBUG_PACKET_HEADER
*DebugHeader
;
986 DEBUG_PORT_HANDLE Handle
;
988 UINTN TimeoutForStartSymbol
;
990 Handle
= GetDebugPortHandle();
991 if (SkipStartSymbol
) {
992 TimeoutForStartSymbol
= 0;
994 TimeoutForStartSymbol
= Timeout
;
997 DebugHeader
= (DEBUG_PACKET_HEADER
*) InputPacket
;
1000 // Find the valid start symbol
1002 Received
= DebugPortReadBuffer (Handle
, &DebugHeader
->StartSymbol
, sizeof (DebugHeader
->StartSymbol
), TimeoutForStartSymbol
);
1003 if (Received
< sizeof (DebugHeader
->StartSymbol
)) {
1004 DebugAgentMsgPrint (DEBUG_AGENT_WARNING
, "DebugPortReadBuffer(StartSymbol) timeout\n");
1005 return RETURN_TIMEOUT
;
1008 if (DebugHeader
->StartSymbol
!= DEBUG_STARTING_SYMBOL_NORMAL
) {
1009 DebugAgentMsgPrint (DEBUG_AGENT_WARNING
, "Invalid start symbol received [%02x]\n", DebugHeader
->StartSymbol
);
1014 // Read Package header till field Length
1016 Received
= DebugPortReadBuffer (
1018 &DebugHeader
->Command
,
1019 OFFSET_OF (DEBUG_PACKET_HEADER
, Length
) + sizeof (DebugHeader
->Length
) - sizeof (DebugHeader
->StartSymbol
),
1022 if (Received
== 0) {
1023 DebugAgentMsgPrint (DEBUG_AGENT_ERROR
, "DebugPortReadBuffer(Command) timeout\n");
1024 return RETURN_TIMEOUT
;
1026 if (DebugHeader
->Length
< sizeof (DEBUG_PACKET_HEADER
)) {
1027 if (IncompatibilityFlag
!= NULL
) {
1029 // This is one old version debug packet format, set Incompatibility flag
1031 *IncompatibilityFlag
= TRUE
;
1034 // Skip the bad small packet
1040 // Read the payload data include the CRC field
1042 Received
= DebugPortReadBuffer (Handle
, &DebugHeader
->SequenceNo
, (UINT8
) (DebugHeader
->Length
- OFFSET_OF (DEBUG_PACKET_HEADER
, SequenceNo
)), Timeout
);
1043 if (Received
== 0) {
1044 DebugAgentMsgPrint (DEBUG_AGENT_ERROR
, "DebugPortReadBuffer(SequenceNo) timeout\n");
1045 return RETURN_TIMEOUT
;
1048 // Calculate the CRC of Debug Packet
1050 Crc
= DebugHeader
->Crc
;
1051 DebugHeader
->Crc
= 0;
1052 if (Crc
== CalculateCrc16 ((UINT8
*) DebugHeader
, DebugHeader
->Length
, 0)) {
1055 DebugAgentMsgPrint (DEBUG_AGENT_WARNING
, "CRC Error (received CRC is %x)\n", Crc
);
1056 DebugAgentDataMsgPrint (DEBUG_AGENT_VERBOSE
, FALSE
, (UINT8
*) DebugHeader
, DebugHeader
->Length
);
1060 DebugAgentDataMsgPrint (DEBUG_AGENT_VERBOSE
, FALSE
, (UINT8
*) DebugHeader
, DebugHeader
->Length
);
1062 return RETURN_SUCCESS
;
1066 Receive acknowledge packet OK from HOST in specified time.
1068 @param[in] Command The command type issued by TARGET.
1069 @param[in] Timeout Time out value to wait for acknowlege from HOST.
1070 The unit is microsecond.
1071 @param[out] BreakReceived If BreakReceived is not NULL,
1072 TRUE is retured if break-in symbol received.
1073 FALSE is retured if break-in symbol not received.
1074 @param[out] IncompatibilityFlag If IncompatibilityFlag is not NULL, return
1075 TRUE: Compatible packet received.
1076 FALSE: Incompatible packet received.
1078 @retval RETRUEN_SUCCESS Succeed to receive acknowlege packet from HOST,
1079 the type of acknowlege packet saved in Ack.
1080 @retval RETURN_TIMEOUT Specified timeout value was up.
1084 SendCommandAndWaitForAckOK (
1087 OUT BOOLEAN
*BreakReceived
, OPTIONAL
1088 OUT BOOLEAN
*IncompatibilityFlag OPTIONAL
1091 RETURN_STATUS Status
;
1092 UINT8 InputPacketBuffer
[DEBUG_DATA_UPPER_LIMIT
];
1093 DEBUG_PACKET_HEADER
*DebugHeader
;
1095 UINT8 HostSequenceNo
;
1099 DebugHeader
= (DEBUG_PACKET_HEADER
*) InputPacketBuffer
;
1100 Status
= RETURN_TIMEOUT
;
1101 while (RetryCount
> 0) {
1102 SequenceNo
= GetMailboxPointer()->SequenceNo
;
1103 HostSequenceNo
= GetMailboxPointer()->HostSequenceNo
;
1104 SendPacketWithoutData (Command
, SequenceNo
);
1105 Status
= ReceivePacket ((UINT8
*) DebugHeader
, BreakReceived
, IncompatibilityFlag
, Timeout
, FALSE
);
1106 if (Status
== RETURN_TIMEOUT
) {
1107 if (Command
== DEBUG_COMMAND_INIT_BREAK
) {
1110 DebugAgentMsgPrint (DEBUG_AGENT_WARNING
, "TARGET: Timeout when waiting for ACK packet.\n");
1114 ASSERT_EFI_ERROR (Status
);
1116 // Status == RETURN_SUCCESS
1118 if (DebugHeader
->Command
== DEBUG_COMMAND_OK
&& DebugHeader
->SequenceNo
== SequenceNo
) {
1122 UpdateMailboxContent (GetMailboxPointer(), DEBUG_MAILBOX_SEQUENCE_NO_INDEX
, ++SequenceNo
);
1125 if (DebugHeader
->Command
== DEBUG_COMMAND_GO
&& (DebugHeader
->SequenceNo
== HostSequenceNo
|| Command
== DEBUG_COMMAND_INIT_BREAK
)) {
1129 if (Command
== DEBUG_COMMAND_INIT_BREAK
) {
1130 DebugAgentMsgPrint (DEBUG_AGENT_WARNING
, "TARGET: Receive GO() in last boot\n");
1132 SendPacketWithoutData (DEBUG_COMMAND_OK
, DebugHeader
->SequenceNo
);
1136 ASSERT (Command
== DEBUG_COMMAND_INIT_BREAK
);
1141 Get current break cause.
1143 @param[in] Vector Vector value of exception or interrupt.
1144 @param[in] CpuContext Pointer to save CPU context.
1146 @return The type of break cause defined by XXXX
1152 IN DEBUG_CPU_CONTEXT
*CpuContext
1157 Cause
= DEBUG_DATA_BREAK_CAUSE_UNKNOWN
;
1160 case DEBUG_INT1_VECTOR
:
1161 case DEBUG_INT3_VECTOR
:
1163 if (Vector
== DEBUG_INT1_VECTOR
) {
1167 if ((CpuContext
->Dr6
& BIT14
) != 0) {
1168 Cause
= DEBUG_DATA_BREAK_CAUSE_STEPPING
;
1170 // If it's single step, no need to check DR0, to ensure single step work in PeCoffExtraActionLib
1171 // (right after triggering a breakpoint to report image load/unload).
1176 Cause
= DEBUG_DATA_BREAK_CAUSE_HW_BREAKPOINT
;
1182 Cause
= DEBUG_DATA_BREAK_CAUSE_SW_BREAKPOINT
;
1185 switch (CpuContext
->Dr0
) {
1186 case IMAGE_LOAD_SIGNATURE
:
1187 case IMAGE_UNLOAD_SIGNATURE
:
1189 if (CpuContext
->Dr3
== IO_PORT_BREAKPOINT_ADDRESS
) {
1191 Cause
= (UINT8
) ((CpuContext
->Dr0
== IMAGE_LOAD_SIGNATURE
) ?
1192 DEBUG_DATA_BREAK_CAUSE_IMAGE_LOAD
: DEBUG_DATA_BREAK_CAUSE_IMAGE_UNLOAD
);
1196 case SOFT_INTERRUPT_SIGNATURE
:
1198 if (CpuContext
->Dr1
== MEMORY_READY_SIGNATURE
) {
1199 Cause
= DEBUG_DATA_BREAK_CAUSE_MEMORY_READY
;
1200 CpuContext
->Dr0
= 0;
1201 } else if (CpuContext
->Dr1
== SYSTEM_RESET_SIGNATURE
) {
1202 Cause
= DEBUG_DATA_BREAK_CAUSE_SYSTEM_RESET
;
1203 CpuContext
->Dr0
= 0;
1214 case DEBUG_TIMER_VECTOR
:
1215 Cause
= DEBUG_DATA_BREAK_CAUSE_USER_HALT
;
1220 if (GetDebugFlag (DEBUG_AGENT_FLAG_STEPPING
) == 1) {
1222 // If stepping command is executing
1224 Cause
= DEBUG_DATA_BREAK_CAUSE_STEPPING
;
1226 Cause
= DEBUG_DATA_BREAK_CAUSE_EXCEPTION
;
1236 Copy memory from source to destination with specified width.
1238 @param[out] Dest A pointer to the destination buffer of the memory copy.
1239 @param[in] Src A pointer to the source buffer of the memory copy.
1240 @param[in] Count The number of data with specified width to copy from source to destination.
1241 @param[in] Width Data width in byte.
1262 // Copy memory from tail to avoid memory overlap
1264 Destination
= Dest
+ (Count
- 1) * Width
;
1265 Source
= Src
+ (Count
- 1) * Width
;
1269 while (Count
-- != 0) {
1272 *(UINT8
*) Destination
= MmioRead8 ((UINTN
) Source
);
1275 *(UINT16
*) Destination
= MmioRead16 ((UINTN
) Source
);
1278 *(UINT32
*) Destination
= MmioRead32 ((UINTN
) Source
);
1281 *(UINT64
*) Destination
= MmioRead64 ((UINTN
) Source
);
1287 Destination
+= Step
;
1292 Read memory with speicifed width and send packet with response data to HOST.
1294 @param[in] Data Pointer to response data buffer.
1295 @param[in] Count The number of data with specified Width.
1296 @param[in] Width Data width in byte.
1298 @retval RETURN_SUCCESS Response data was sent successfully.
1302 ReadMemoryAndSendResponsePacket (
1308 RETURN_STATUS Status
;
1309 DEBUG_PACKET_HEADER
*DebugHeader
;
1311 DEBUG_PACKET_HEADER
*AckDebugHeader
;
1312 UINT8 DebugPacket
[DEBUG_DATA_UPPER_LIMIT
+ sizeof (UINT64
) - 1];
1313 UINT8 InputPacketBuffer
[DEBUG_DATA_UPPER_LIMIT
];
1314 DEBUG_PORT_HANDLE Handle
;
1316 UINTN RemainingDataSize
;
1317 UINTN CurrentDataSize
;
1319 Handle
= GetDebugPortHandle();
1322 // Data is appended end of Debug Packet header, make sure data address
1323 // in Debug Packet 8-byte alignment always
1325 DebugHeader
= (DEBUG_PACKET_HEADER
*) (ALIGN_VALUE ((UINTN
)&DebugPacket
+ sizeof (DEBUG_PACKET_HEADER
), sizeof (UINT64
))
1326 - sizeof (DEBUG_PACKET_HEADER
));
1327 DebugHeader
->StartSymbol
= DEBUG_STARTING_SYMBOL_NORMAL
;
1329 RemainingDataSize
= Count
* Width
;
1331 SequenceNo
= GetMailboxPointer()->HostSequenceNo
;
1332 if (RemainingDataSize
<= DEBUG_DATA_MAXIMUM_REAL_DATA
) {
1334 // If the remaining data is less one real packet size, this is the last data packet
1336 CurrentDataSize
= RemainingDataSize
;
1338 DebugHeader
->Command
= DEBUG_COMMAND_OK
;
1341 // Data is too larger to be sent in one packet, calculate the actual data size could
1342 // be sent in one Maximum data packet
1344 CurrentDataSize
= (DEBUG_DATA_MAXIMUM_REAL_DATA
/ Width
) * Width
;
1346 DebugHeader
->Command
= DEBUG_COMMAND_IN_PROGRESS
;
1349 // Construct the rest Debug header
1351 DebugHeader
->Length
= (UINT8
)(CurrentDataSize
+ sizeof (DEBUG_PACKET_HEADER
));
1352 DebugHeader
->SequenceNo
= SequenceNo
;
1353 DebugHeader
->Crc
= 0;
1354 CopyMemByWidth ((UINT8
*)(DebugHeader
+ 1), Data
, (UINT16
) CurrentDataSize
/ Width
, Width
);
1356 // Calculate and fill the checksum, DebugHeader->Crc should be 0 before invoking CalculateCrc16 ()
1358 DebugHeader
->Crc
= CalculateCrc16 ((UINT8
*) DebugHeader
, DebugHeader
->Length
, 0);
1360 DebugAgentDataMsgPrint (DEBUG_AGENT_VERBOSE
, TRUE
, (UINT8
*) DebugHeader
, DebugHeader
->Length
);
1362 DebugPortWriteBuffer (Handle
, (UINT8
*) DebugHeader
, DebugHeader
->Length
);
1365 Status
= ReceivePacket (InputPacketBuffer
, NULL
, NULL
, READ_PACKET_TIMEOUT
, FALSE
);
1366 if (Status
== RETURN_TIMEOUT
) {
1367 DebugAgentMsgPrint (DEBUG_AGENT_WARNING
, "TARGET: Timeout in SendDataResponsePacket()\n");
1370 AckDebugHeader
= (DEBUG_PACKET_HEADER
*) InputPacketBuffer
;
1371 SequenceNo
= AckDebugHeader
->SequenceNo
;
1372 if (AckDebugHeader
->Command
== DEBUG_COMMAND_OK
&&
1373 SequenceNo
== DebugHeader
->SequenceNo
&&
1376 // If this is the last packet, return RETURN_SUCCESS.
1378 return RETURN_SUCCESS
;
1380 if ((SequenceNo
== (UINT8
) (DebugHeader
->SequenceNo
+ 1)) && (AckDebugHeader
->Command
== DEBUG_COMMAND_CONTINUE
)) {
1382 // Calculate the rest data size
1384 Data
+= CurrentDataSize
;
1385 RemainingDataSize
-= CurrentDataSize
;
1386 UpdateMailboxContent (GetMailboxPointer(), DEBUG_MAILBOX_HOST_SEQUENCE_NO_INDEX
, (UINT8
) SequenceNo
);
1389 if (SequenceNo
>= DebugHeader
->SequenceNo
) {
1390 DebugAgentMsgPrint (DEBUG_AGENT_WARNING
, "TARGET: Received one old or new command(SequenceNo is %x, last SequenceNo is %x)\n", SequenceNo
, DebugHeader
->SequenceNo
);
1398 Send packet with response data to HOST.
1400 @param[in] Data Pointer to response data buffer.
1401 @param[in] DataSize Size of response data in byte.
1403 @retval RETURN_SUCCESS Response data was sent successfully.
1407 SendDataResponsePacket (
1412 return ReadMemoryAndSendResponsePacket (Data
, DataSize
, 1);
1416 Send break cause packet to HOST.
1418 @param[in] Vector Vector value of exception or interrutp.
1419 @param[in] CpuContext Pointer to save CPU context.
1421 @retval RETURN_SUCCESS Response data was sent successfully.
1422 @retval RETURN_DEVICE_ERROR Cannot receive DEBUG_COMMAND_OK from HOST.
1426 SendBreakCausePacket (
1428 IN DEBUG_CPU_CONTEXT
*CpuContext
1431 DEBUG_DATA_RESPONSE_BREAK_CAUSE DebugDataBreakCause
;
1433 DebugDataBreakCause
.StopAddress
= CpuContext
->Eip
;
1434 DebugDataBreakCause
.Cause
= GetBreakCause (Vector
, CpuContext
);
1436 return SendDataResponsePacket ((UINT8
*) &DebugDataBreakCause
, (UINT16
) sizeof (DEBUG_DATA_RESPONSE_BREAK_CAUSE
));
1440 Try to attach the HOST.
1442 Send init break packet to HOST:
1443 If no acknowlege received in specified Timeout, return RETURN_TIMEOUT.
1444 If received acknowlege, check the revision of HOST.
1445 Set Attach Flag if attach successfully.
1447 @param[in] BreakCause Break cause of this break event.
1448 @param[in] Timeout Time out value to wait for acknowlege from HOST.
1449 The unit is microsecond.
1450 @param[out] BreakReceived If BreakReceived is not NULL,
1451 TRUE is retured if break-in symbol received.
1452 FALSE is retured if break-in symbol not received.
1456 IN UINT8 BreakCause
,
1458 OUT BOOLEAN
*BreakReceived
1461 RETURN_STATUS Status
;
1462 DEBUG_PORT_HANDLE Handle
;
1463 BOOLEAN IncompatibilityFlag
;
1465 IncompatibilityFlag
= FALSE
;
1466 Handle
= GetDebugPortHandle();
1469 // Send init break and wait ack in Timeout
1471 DebugPortWriteBuffer (Handle
, (UINT8
*) mErrorMsgSendInitPacket
, AsciiStrLen (mErrorMsgSendInitPacket
));
1472 if (BreakCause
== DEBUG_DATA_BREAK_CAUSE_SYSTEM_RESET
) {
1473 Status
= SendCommandAndWaitForAckOK (DEBUG_COMMAND_INIT_BREAK
, Timeout
, BreakReceived
, &IncompatibilityFlag
);
1475 Status
= SendCommandAndWaitForAckOK (DEBUG_COMMAND_ATTACH_BREAK
, Timeout
, BreakReceived
, &IncompatibilityFlag
);
1477 if (IncompatibilityFlag
) {
1479 // If the incompatible Debug Packet received, the HOST should be running transfer protocol before DEBUG_AGENT_REVISION.
1480 // It could be UDK Debugger for Windows v1.1/v1.2 or for Linux v0.8/v1.2.
1482 DebugPortWriteBuffer (Handle
, (UINT8
*) mErrorMsgVersionAlert
, AsciiStrLen (mErrorMsgVersionAlert
));
1486 if (RETURN_ERROR (Status
)) {
1487 DebugPortWriteBuffer (Handle
, (UINT8
*) mErrorMsgConnectFail
, AsciiStrLen (mErrorMsgConnectFail
));
1489 DebugPortWriteBuffer (Handle
, (UINT8
*) mErrorMsgConnectOK
, AsciiStrLen (mErrorMsgConnectOK
));
1493 SetHostAttached (TRUE
);
1499 Send Break point packet to HOST.
1501 Only the first breaking processor could sent BREAK_POINT packet.
1503 @param[in] BreakCause Break cause of this break event.
1504 @param[in] ProcessorIndex Processor index value.
1505 @param[out] BreakReceived If BreakReceived is not NULL,
1506 TRUE is retured if break-in symbol received.
1507 FALSE is retured if break-in symbol not received.
1511 SendBreakPacketToHost (
1512 IN UINT8 BreakCause
,
1513 IN UINT32 ProcessorIndex
,
1514 OUT BOOLEAN
*BreakReceived
1517 UINT8 InputCharacter
;
1518 DEBUG_PORT_HANDLE Handle
;
1520 Handle
= GetDebugPortHandle();
1522 if (IsHostAttached ()) {
1523 DebugAgentMsgPrint (DEBUG_AGENT_INFO
, "processor[%x]:Send Break Packet to HOST.\n", ProcessorIndex
);
1524 SendCommandAndWaitForAckOK (DEBUG_COMMAND_BREAK_POINT
, READ_PACKET_TIMEOUT
, BreakReceived
, NULL
);
1526 DebugAgentMsgPrint (DEBUG_AGENT_INFO
, "processor[%x]:Try to attach HOST.\n", ProcessorIndex
);
1528 // If HOST is not attached, try to attach it firstly.
1531 // Poll Attach symbols from HOST and ack OK
1534 DebugPortReadBuffer (Handle
, &InputCharacter
, 1, 0);
1535 } while (InputCharacter
!= DEBUG_STARTING_SYMBOL_ATTACH
);
1536 SendAckPacket (DEBUG_COMMAND_OK
);
1539 // Try to attach HOST
1541 while (AttachHost (BreakCause
, 0, NULL
) != RETURN_SUCCESS
);
1547 The main function to process communication with HOST.
1549 It received the command packet from HOST, and sent response data packet to HOST.
1551 @param[in] Vector Vector value of exception or interrutp.
1552 @param[in, out] CpuContext Pointer to saved CPU context.
1553 @param[in] BreakReceived TRUE means break-in symbol received.
1554 FALSE means break-in symbol not received.
1558 CommandCommunication (
1560 IN OUT DEBUG_CPU_CONTEXT
*CpuContext
,
1561 IN BOOLEAN BreakReceived
1564 RETURN_STATUS Status
;
1565 UINT8 InputPacketBuffer
[DEBUG_DATA_UPPER_LIMIT
+ sizeof (UINT64
) - 1];
1566 DEBUG_PACKET_HEADER
*DebugHeader
;
1571 DEBUG_DATA_READ_MEMORY
*MemoryRead
;
1572 DEBUG_DATA_WRITE_MEMORY
*MemoryWrite
;
1573 DEBUG_DATA_READ_IO
*IoRead
;
1574 DEBUG_DATA_WRITE_IO
*IoWrite
;
1575 DEBUG_DATA_READ_REGISTER
*RegisterRead
;
1576 DEBUG_DATA_WRITE_REGISTER
*RegisterWrite
;
1577 UINT8
*RegisterBuffer
;
1578 DEBUG_DATA_READ_MSR
*MsrRegisterRead
;
1579 DEBUG_DATA_WRITE_MSR
*MsrRegisterWrite
;
1580 DEBUG_DATA_CPUID
*Cpuid
;
1581 DEBUG_DATA_RESPONSE_CPUID CpuidResponse
;
1582 DEBUG_DATA_SEARCH_SIGNATURE
*SearchSignature
;
1583 DEBUG_DATA_RESPONSE_GET_EXCEPTION Exception
;
1584 DEBUG_DATA_RESPONSE_GET_REVISION DebugAgentRevision
;
1585 DEBUG_DATA_SET_VIEWPOINT
*SetViewPoint
;
1586 BOOLEAN HaltDeferred
;
1587 UINT32 ProcessorIndex
;
1588 DEBUG_PORT_HANDLE Handle
;
1589 DEBUG_AGENT_EXCEPTION_BUFFER AgentExceptionBuffer
;
1590 UINT32 IssuedViewPoint
;
1591 DEBUG_AGENT_MAILBOX
*Mailbox
;
1592 UINT8
*AlignedDataPtr
;
1595 IssuedViewPoint
= 0;
1596 HaltDeferred
= BreakReceived
;
1598 if (MultiProcessorDebugSupport()) {
1599 ProcessorIndex
= GetProcessorIndex ();
1600 SetCpuStopFlagByIndex (ProcessorIndex
, TRUE
);
1601 if (mDebugMpContext
.ViewPointIndex
== ProcessorIndex
) {
1603 // Only the current view processor could set AgentInProgress Flag.
1605 IssuedViewPoint
= ProcessorIndex
;
1609 if (IssuedViewPoint
== ProcessorIndex
) {
1611 // Set AgentInProgress Flag.
1613 SetDebugFlag (DEBUG_AGENT_FLAG_AGENT_IN_PROGRESS
, 1);
1616 Handle
= GetDebugPortHandle();
1620 if (MultiProcessorDebugSupport()) {
1622 // Check if the current processor is HOST view point
1624 if (mDebugMpContext
.ViewPointIndex
!= ProcessorIndex
) {
1625 if (mDebugMpContext
.RunCommandSet
) {
1627 // If HOST view point sets RUN flag, run GO command to leave
1629 SetCpuStopFlagByIndex (ProcessorIndex
, FALSE
);
1630 CommandGo (CpuContext
);
1634 // Run into loop again
1642 AcquireMpSpinLock (&mDebugMpContext
.DebugPortSpinLock
);
1644 DebugHeader
=(DEBUG_PACKET_HEADER
*) InputPacketBuffer
;
1646 DebugAgentMsgPrint (DEBUG_AGENT_INFO
, "TARGET: Try to get command from HOST...\n");
1647 Status
= ReceivePacket ((UINT8
*)DebugHeader
, &BreakReceived
, NULL
, READ_PACKET_TIMEOUT
, TRUE
);
1648 if (Status
!= RETURN_SUCCESS
|| (DebugHeader
->Command
& DEBUG_COMMAND_RESPONSE
) != 0) {
1649 DebugAgentMsgPrint (DEBUG_AGENT_WARNING
, "TARGET: Get command[%x] sequenceno[%x] returned status is [%x] \n", DebugHeader
->Command
, DebugHeader
->SequenceNo
, Status
);
1650 DebugAgentMsgPrint (DEBUG_AGENT_WARNING
, "TARGET: Get command failed or it's response packet not expected! \n");
1651 ReleaseMpSpinLock (&mDebugMpContext
.DebugPortSpinLock
);
1655 Mailbox
= GetMailboxPointer ();
1656 if (DebugHeader
->SequenceNo
== Mailbox
->HostSequenceNo
) {
1657 DebugAgentMsgPrint (DEBUG_AGENT_WARNING
, "TARGET: Receive one old command[%x] agaist command[%x]\n", DebugHeader
->SequenceNo
, Mailbox
->HostSequenceNo
);
1658 SendAckPacket (Mailbox
->LastAck
);
1659 ReleaseMpSpinLock (&mDebugMpContext
.DebugPortSpinLock
);
1661 } else if (DebugHeader
->SequenceNo
== (UINT8
) (Mailbox
->HostSequenceNo
+ 1)) {
1662 UpdateMailboxContent (Mailbox
, DEBUG_MAILBOX_HOST_SEQUENCE_NO_INDEX
, (UINT8
) DebugHeader
->SequenceNo
);
1664 DebugAgentMsgPrint (DEBUG_AGENT_WARNING
, "Receive one invalid comamnd[%x] agaist command[%x]\n", DebugHeader
->SequenceNo
, Mailbox
->HostSequenceNo
);
1665 ReleaseMpSpinLock (&mDebugMpContext
.DebugPortSpinLock
);
1670 // Save CPU content before executing HOST commond
1672 UpdateMailboxContent (Mailbox
, DEBUG_MAILBOX_EXCEPTION_BUFFER_POINTER_INDEX
, (UINT64
)(UINTN
) &AgentExceptionBuffer
.JumpBuffer
);
1673 if (SetJump (&AgentExceptionBuffer
.JumpBuffer
) != 0) {
1675 // If HOST command failed, continue to wait for HOST's next command
1676 // If needed, agent could send exception info to HOST.
1678 SendAckPacket (DEBUG_COMMAND_ABORT
);
1679 ReleaseMpSpinLock (&mDebugMpContext
.DebugPortSpinLock
);
1683 DebugAgentMsgPrint (DEBUG_AGENT_INFO
, "Processor[%x]:Received one command(%x)\n", mDebugMpContext
.ViewPointIndex
, DebugHeader
->Command
);
1685 switch (DebugHeader
->Command
) {
1687 case DEBUG_COMMAND_HALT
:
1688 SendAckPacket (DEBUG_COMMAND_HALT_DEFERRED
);
1689 HaltDeferred
= TRUE
;
1690 BreakReceived
= FALSE
;
1691 Status
= RETURN_SUCCESS
;
1694 case DEBUG_COMMAND_RESET
:
1695 SendAckPacket (DEBUG_COMMAND_OK
);
1696 SendAckPacket (DEBUG_COMMAND_OK
);
1697 SendAckPacket (DEBUG_COMMAND_OK
);
1698 ReleaseMpSpinLock (&mDebugMpContext
.DebugPortSpinLock
);
1702 // Assume system resets in 2 seconds, otherwise send TIMEOUT packet.
1703 // PCD can be used if 2 seconds isn't long enough for some platforms.
1705 MicroSecondDelay (2000000);
1706 UpdateMailboxContent (Mailbox
, DEBUG_MAILBOX_HOST_SEQUENCE_NO_INDEX
, Mailbox
->HostSequenceNo
+ 1);
1707 SendAckPacket (DEBUG_COMMAND_TIMEOUT
);
1708 SendAckPacket (DEBUG_COMMAND_TIMEOUT
);
1709 SendAckPacket (DEBUG_COMMAND_TIMEOUT
);
1712 case DEBUG_COMMAND_GO
:
1713 CommandGo (CpuContext
);
1715 // Clear Dr0 to avoid to be recognized as IMAGE_LOAD/_UNLOAD again when hitting a breakpoint after GO
1716 // If HOST changed Dr0 before GO, we will not change Dr0 here
1718 Data8
= GetBreakCause (Vector
, CpuContext
);
1719 if (Data8
== DEBUG_DATA_BREAK_CAUSE_IMAGE_LOAD
|| Data8
== DEBUG_DATA_BREAK_CAUSE_IMAGE_UNLOAD
) {
1720 CpuContext
->Dr0
= 0;
1723 // Clear Stepping Flag
1725 SetDebugFlag (DEBUG_AGENT_FLAG_STEPPING
, 0);
1727 if (!HaltDeferred
) {
1729 // If no HALT command received when being in-active mode
1731 if (MultiProcessorDebugSupport()) {
1732 Data32
= FindNextPendingBreakCpu ();
1735 // If there are still others processors being in break state,
1736 // send OK packet to HOST to finish this go command
1738 SendAckPacket (DEBUG_COMMAND_OK
);
1741 // Set current view to the next breaking processor
1743 mDebugMpContext
.ViewPointIndex
= Data32
;
1744 mDebugMpContext
.BreakAtCpuIndex
= mDebugMpContext
.ViewPointIndex
;
1745 SetCpuBreakFlagByIndex (mDebugMpContext
.ViewPointIndex
, FALSE
);
1747 // Send break packet to HOST to let HOST break again
1749 SendBreakPacketToHost (DEBUG_DATA_BREAK_CAUSE_UNKNOWN
, mDebugMpContext
.BreakAtCpuIndex
, &BreakReceived
);
1751 // Continue to run into loop to read command packet from HOST
1753 ReleaseMpSpinLock (&mDebugMpContext
.DebugPortSpinLock
);
1758 // If no else processor break, set stop bitmask,
1759 // and set Running flag for all processors.
1761 SetCpuStopFlagByIndex (ProcessorIndex
, FALSE
);
1762 SetCpuRunningFlag (TRUE
);
1765 // Wait for all processors are in running state
1768 if (IsAllCpuRunning ()) {
1773 // Set BSP to be current view point.
1775 SetDebugViewPoint (mDebugMpContext
.BspIndex
);
1778 // Clear breaking processor index and running flag
1780 mDebugMpContext
.BreakAtCpuIndex
= (UINT32
) (-1);
1781 SetCpuRunningFlag (FALSE
);
1785 // Send OK packet to HOST to finish this go command
1787 SendAckPacket (DEBUG_COMMAND_OK
);
1789 ReleaseMpSpinLock (&mDebugMpContext
.DebugPortSpinLock
);
1791 if (!IsHostAttached()) {
1792 UpdateMailboxContent (Mailbox
, DEBUG_MAILBOX_SEQUENCE_NO_INDEX
, 0);
1793 UpdateMailboxContent (Mailbox
, DEBUG_MAILBOX_HOST_SEQUENCE_NO_INDEX
, 0);
1799 // If reveived HALT command, need to defer the GO command
1801 SendAckPacket (DEBUG_COMMAND_HALT_PROCESSED
);
1802 HaltDeferred
= FALSE
;
1804 Vector
= DEBUG_TIMER_VECTOR
;
1808 case DEBUG_COMMAND_BREAK_CAUSE
:
1810 if (MultiProcessorDebugSupport() && ProcessorIndex
!= mDebugMpContext
.BreakAtCpuIndex
) {
1811 Status
= SendBreakCausePacket (DEBUG_TIMER_VECTOR
, CpuContext
);
1814 Status
= SendBreakCausePacket (Vector
, CpuContext
);
1819 case DEBUG_COMMAND_SET_HW_BREAKPOINT
:
1820 SetDebugRegister (CpuContext
, (DEBUG_DATA_SET_HW_BREAKPOINT
*) (DebugHeader
+ 1));
1821 SendAckPacket (DEBUG_COMMAND_OK
);
1824 case DEBUG_COMMAND_CLEAR_HW_BREAKPOINT
:
1825 ClearDebugRegister (CpuContext
, (DEBUG_DATA_CLEAR_HW_BREAKPOINT
*) (DebugHeader
+ 1));
1826 SendAckPacket (DEBUG_COMMAND_OK
);
1829 case DEBUG_COMMAND_SINGLE_STEPPING
:
1830 CommandStepping (CpuContext
);
1832 // Clear Dr0 to avoid to be recognized as IMAGE_LOAD/_UNLOAD again when hitting a breakpoint after GO
1833 // If HOST changed Dr0 before GO, we will not change Dr0 here
1835 Data8
= GetBreakCause (Vector
, CpuContext
);
1836 if (Data8
== DEBUG_DATA_BREAK_CAUSE_IMAGE_LOAD
|| Data8
== DEBUG_DATA_BREAK_CAUSE_IMAGE_UNLOAD
) {
1837 CpuContext
->Dr0
= 0;
1840 mDebugMpContext
.BreakAtCpuIndex
= (UINT32
) (-1);
1842 // Set Stepping Flag
1844 SetDebugFlag (DEBUG_AGENT_FLAG_STEPPING
, 1);
1845 ReleaseMpSpinLock (&mDebugMpContext
.DebugPortSpinLock
);
1847 // Executing stepping command directly without sending ACK packet,
1848 // ACK packet will be sent after stepping done.
1852 case DEBUG_COMMAND_SET_SW_BREAKPOINT
:
1853 Data64
= (UINTN
) (((DEBUG_DATA_SET_SW_BREAKPOINT
*) (DebugHeader
+ 1))->Address
);
1854 Data8
= *(UINT8
*) (UINTN
) Data64
;
1855 *(UINT8
*) (UINTN
) Data64
= DEBUG_SW_BREAKPOINT_SYMBOL
;
1856 Status
= SendDataResponsePacket ((UINT8
*) &Data8
, (UINT16
) sizeof (UINT8
));
1859 case DEBUG_COMMAND_READ_MEMORY
:
1860 MemoryRead
= (DEBUG_DATA_READ_MEMORY
*) (DebugHeader
+ 1);
1861 Status
= ReadMemoryAndSendResponsePacket ((UINT8
*) (UINTN
) MemoryRead
->Address
, MemoryRead
->Count
, MemoryRead
->Width
);
1864 case DEBUG_COMMAND_WRITE_MEMORY
:
1865 MemoryWrite
= (DEBUG_DATA_WRITE_MEMORY
*) (DebugHeader
+ 1);
1867 // Copy data into one memory with 8-byte alignment address
1869 AlignedDataPtr
= ALIGN_POINTER ((UINT8
*) &MemoryWrite
->Data
, sizeof (UINT64
));
1870 if (AlignedDataPtr
!= (UINT8
*) &MemoryWrite
->Data
) {
1871 CopyMem (AlignedDataPtr
, (UINT8
*) &MemoryWrite
->Data
, MemoryWrite
->Count
* MemoryWrite
->Width
);
1873 CopyMemByWidth ((UINT8
*) (UINTN
) MemoryWrite
->Address
, AlignedDataPtr
, MemoryWrite
->Count
, MemoryWrite
->Width
);
1874 SendAckPacket (DEBUG_COMMAND_OK
);
1877 case DEBUG_COMMAND_READ_IO
:
1878 IoRead
= (DEBUG_DATA_READ_IO
*) (DebugHeader
+ 1);
1879 switch (IoRead
->Width
) {
1881 Data64
= IoRead8 ((UINTN
) IoRead
->Port
);
1884 Data64
= IoRead16 ((UINTN
) IoRead
->Port
);
1887 Data64
= IoRead32 ((UINTN
) IoRead
->Port
);
1890 Data64
= IoRead64 ((UINTN
) IoRead
->Port
);
1893 Data64
= (UINT64
) -1;
1895 Status
= SendDataResponsePacket ((UINT8
*) &Data64
, IoRead
->Width
);
1898 case DEBUG_COMMAND_WRITE_IO
:
1899 IoWrite
= (DEBUG_DATA_WRITE_IO
*) (DebugHeader
+ 1);
1900 switch (IoWrite
->Width
) {
1902 Data64
= IoWrite8 ((UINTN
) IoWrite
->Port
, *(UINT8
*) &IoWrite
->Data
);
1905 Data64
= IoWrite16 ((UINTN
) IoWrite
->Port
, *(UINT16
*) &IoWrite
->Data
);
1908 Data64
= IoWrite32 ((UINTN
) IoWrite
->Port
, *(UINT32
*) &IoWrite
->Data
);
1911 Data64
= IoWrite64 ((UINTN
) IoWrite
->Port
, *(UINT64
*) &IoWrite
->Data
);
1914 Data64
= (UINT64
) -1;
1916 SendAckPacket (DEBUG_COMMAND_OK
);
1919 case DEBUG_COMMAND_READ_ALL_REGISTERS
:
1920 Status
= SendDataResponsePacket ((UINT8
*) CpuContext
, sizeof (*CpuContext
));
1923 case DEBUG_COMMAND_READ_REGISTER
:
1924 RegisterRead
= (DEBUG_DATA_READ_REGISTER
*) (DebugHeader
+ 1);
1926 if (RegisterRead
->Index
<= SOFT_DEBUGGER_REGISTER_MAX
) {
1927 RegisterBuffer
= ArchReadRegisterBuffer (CpuContext
, RegisterRead
->Index
, &Width
);
1928 Status
= SendDataResponsePacket (RegisterBuffer
, Width
);
1930 Status
= RETURN_UNSUPPORTED
;
1934 case DEBUG_COMMAND_WRITE_REGISTER
:
1935 RegisterWrite
= (DEBUG_DATA_WRITE_REGISTER
*) (DebugHeader
+ 1);
1936 if (RegisterWrite
->Index
<= SOFT_DEBUGGER_REGISTER_MAX
) {
1937 RegisterBuffer
= ArchReadRegisterBuffer (CpuContext
, RegisterWrite
->Index
, &Width
);
1938 ASSERT (Width
== RegisterWrite
->Length
);
1939 CopyMem (RegisterBuffer
, RegisterWrite
->Data
, Width
);
1940 SendAckPacket (DEBUG_COMMAND_OK
);
1942 Status
= RETURN_UNSUPPORTED
;
1946 case DEBUG_COMMAND_ARCH_MODE
:
1947 Data8
= DEBUG_ARCH_SYMBOL
;
1948 Status
= SendDataResponsePacket ((UINT8
*) &Data8
, (UINT16
) sizeof (UINT8
));
1951 case DEBUG_COMMAND_READ_MSR
:
1952 MsrRegisterRead
= (DEBUG_DATA_READ_MSR
*) (DebugHeader
+ 1);
1953 Data64
= AsmReadMsr64 (MsrRegisterRead
->Index
);
1954 Status
= SendDataResponsePacket ((UINT8
*) &Data64
, (UINT16
) sizeof (UINT64
));
1957 case DEBUG_COMMAND_WRITE_MSR
:
1958 MsrRegisterWrite
= (DEBUG_DATA_WRITE_MSR
*) (DebugHeader
+ 1);
1959 AsmWriteMsr64 (MsrRegisterWrite
->Index
, MsrRegisterWrite
->Value
);
1960 SendAckPacket (DEBUG_COMMAND_OK
);
1963 case DEBUG_COMMAND_SET_DEBUG_SETTING
:
1964 Status
= SetDebugSetting ((DEBUG_DATA_SET_DEBUG_SETTING
*)(DebugHeader
+ 1));
1965 if (Status
== RETURN_SUCCESS
) {
1966 SendAckPacket (DEBUG_COMMAND_OK
);
1970 case DEBUG_COMMAND_GET_REVISION
:
1971 DebugAgentRevision
.Revision
= DEBUG_AGENT_REVISION
;
1972 DebugAgentRevision
.Capabilities
= DEBUG_AGENT_CAPABILITIES
;
1973 Status
= SendDataResponsePacket ((UINT8
*) &DebugAgentRevision
, (UINT16
) sizeof (DEBUG_DATA_RESPONSE_GET_REVISION
));
1976 case DEBUG_COMMAND_GET_EXCEPTION
:
1977 Exception
.ExceptionNum
= (UINT8
) Vector
;
1978 Exception
.ExceptionData
= (UINT32
) CpuContext
->ExceptionData
;
1979 Status
= SendDataResponsePacket ((UINT8
*) &Exception
, (UINT16
) sizeof (DEBUG_DATA_RESPONSE_GET_EXCEPTION
));
1982 case DEBUG_COMMAND_SET_VIEWPOINT
:
1983 SetViewPoint
= (DEBUG_DATA_SET_VIEWPOINT
*) (DebugHeader
+ 1);
1984 if (MultiProcessorDebugSupport()) {
1985 if (IsCpuStopped (SetViewPoint
->ViewPoint
)) {
1986 SetDebugViewPoint (SetViewPoint
->ViewPoint
);
1987 SendAckPacket (DEBUG_COMMAND_OK
);
1990 // If CPU is not halted
1992 SendAckPacket (DEBUG_COMMAND_NOT_SUPPORTED
);
1994 } else if (SetViewPoint
->ViewPoint
== 0) {
1995 SendAckPacket (DEBUG_COMMAND_OK
);
1998 SendAckPacket (DEBUG_COMMAND_NOT_SUPPORTED
);
2003 case DEBUG_COMMAND_GET_VIEWPOINT
:
2004 Data32
= mDebugMpContext
.ViewPointIndex
;
2005 SendDataResponsePacket((UINT8
*) &Data32
, (UINT16
) sizeof (UINT32
));
2008 case DEBUG_COMMAND_MEMORY_READY
:
2009 Data8
= (UINT8
) GetDebugFlag (DEBUG_AGENT_FLAG_MEMORY_READY
);
2010 SendDataResponsePacket (&Data8
, (UINT16
) sizeof (UINT8
));
2013 case DEBUG_COMMAND_DETACH
:
2014 SetHostAttached (FALSE
);
2015 SendAckPacket (DEBUG_COMMAND_OK
);
2018 case DEBUG_COMMAND_CPUID
:
2019 Cpuid
= (DEBUG_DATA_CPUID
*) (DebugHeader
+ 1);
2021 Cpuid
->Eax
, Cpuid
->Ecx
,
2022 &CpuidResponse
.Eax
, &CpuidResponse
.Ebx
,
2023 &CpuidResponse
.Ecx
, &CpuidResponse
.Edx
2025 SendDataResponsePacket ((UINT8
*) &CpuidResponse
, (UINT16
) sizeof (CpuidResponse
));
2028 case DEBUG_COMMAND_SEARCH_SIGNATURE
:
2029 SearchSignature
= (DEBUG_DATA_SEARCH_SIGNATURE
*) (DebugHeader
+ 1);
2030 if ((SearchSignature
->Alignment
!= 0) &&
2031 (SearchSignature
->Alignment
== GetPowerOfTwo32 (SearchSignature
->Alignment
))
2033 if (SearchSignature
->Positive
) {
2035 Data64
= ALIGN_VALUE ((UINTN
) SearchSignature
->Start
, SearchSignature
->Alignment
);
2036 Data64
<= SearchSignature
->Start
+ SearchSignature
->Count
- SearchSignature
->DataLength
;
2037 Data64
+= SearchSignature
->Alignment
2039 if (CompareMem ((VOID
*) (UINTN
) Data64
, &SearchSignature
->Data
, SearchSignature
->DataLength
) == 0) {
2043 if (Data64
> SearchSignature
->Start
+ SearchSignature
->Count
- SearchSignature
->DataLength
) {
2044 Data64
= (UINT64
) -1;
2048 Data64
= ALIGN_VALUE ((UINTN
) SearchSignature
->Start
- SearchSignature
->Alignment
, SearchSignature
->Alignment
);
2049 Data64
>= SearchSignature
->Start
- SearchSignature
->Count
;
2050 Data64
-= SearchSignature
->Alignment
2052 if (CompareMem ((VOID
*) (UINTN
) Data64
, &SearchSignature
->Data
, SearchSignature
->DataLength
) == 0) {
2056 if (Data64
< SearchSignature
->Start
- SearchSignature
->Count
) {
2057 Data64
= (UINT64
) -1;
2060 SendDataResponsePacket ((UINT8
*) &Data64
, (UINT16
) sizeof (Data64
));
2062 Status
= RETURN_UNSUPPORTED
;
2067 SendAckPacket (DEBUG_COMMAND_NOT_SUPPORTED
);
2071 if (Status
== RETURN_UNSUPPORTED
) {
2072 SendAckPacket (DEBUG_COMMAND_NOT_SUPPORTED
);
2073 } else if (Status
!= RETURN_SUCCESS
) {
2074 SendAckPacket (DEBUG_COMMAND_ABORT
);
2077 ReleaseMpSpinLock (&mDebugMpContext
.DebugPortSpinLock
);
2083 C function called in interrupt handler.
2085 @param[in] Vector Vector value of exception or interrutp.
2086 @param[in] CpuContext Pointer to save CPU context.
2093 IN DEBUG_CPU_CONTEXT
*CpuContext
2096 UINT8 InputCharacter
;
2099 BOOLEAN BreakReceived
;
2100 UINT32 ProcessorIndex
;
2101 UINT32 CurrentDebugTimerInitCount
;
2102 DEBUG_PORT_HANDLE Handle
;
2105 UINT32 IssuedViewPoint
;
2106 DEBUG_AGENT_EXCEPTION_BUFFER
*ExceptionBuffer
;
2109 IssuedViewPoint
= 0;
2110 BreakReceived
= FALSE
;
2112 if (mSkipBreakpoint
) {
2114 // If Skip Breakpoint flag is set, means communication is disturbed by hardware SMI, we need to ignore the break points in SMM
2116 if ((Vector
== DEBUG_INT1_VECTOR
) || (Vector
== DEBUG_INT3_VECTOR
)) {
2117 DebugPortWriteBuffer (GetDebugPortHandle(), (UINT8
*) mWarningMsgIngoreBreakpoint
, AsciiStrLen (mWarningMsgIngoreBreakpoint
));
2122 if (MultiProcessorDebugSupport()) {
2123 ProcessorIndex
= GetProcessorIndex ();
2125 // If this processor has alreay halted before, need to check it later
2127 if (IsCpuStopped (ProcessorIndex
)) {
2128 IssuedViewPoint
= ProcessorIndex
;
2132 if (IssuedViewPoint
== ProcessorIndex
&& GetDebugFlag (DEBUG_AGENT_FLAG_STEPPING
) != 1) {
2134 // Check if this exception is issued by Debug Agent itself
2135 // If yes, fill the debug agent exception buffer and LongJump() back to
2136 // the saved CPU content in CommandCommunication()
2138 if (GetDebugFlag (DEBUG_AGENT_FLAG_AGENT_IN_PROGRESS
) == 1) {
2139 DebugAgentMsgPrint (DEBUG_AGENT_ERROR
, "Debug agent meet one Exception, ExceptionNum is %d, EIP = 0x%x.\n", Vector
, (UINTN
)CpuContext
->Eip
);
2140 ExceptionBuffer
= (DEBUG_AGENT_EXCEPTION_BUFFER
*) (UINTN
) GetMailboxPointer()->ExceptionBufferPointer
;
2141 ExceptionBuffer
->ExceptionContent
.ExceptionNum
= (UINT8
) Vector
;
2142 ExceptionBuffer
->ExceptionContent
.ExceptionData
= (UINT32
) CpuContext
->ExceptionData
;
2143 LongJump ((BASE_LIBRARY_JUMP_BUFFER
*)(UINTN
)(ExceptionBuffer
), 1);
2147 if (MultiProcessorDebugSupport()) {
2149 // If RUN commmand is executing, wait for it done.
2151 while (mDebugMpContext
.RunCommandSet
) {
2156 Handle
= GetDebugPortHandle();
2157 BreakCause
= GetBreakCause (Vector
, CpuContext
);
2159 case DEBUG_INT1_VECTOR
:
2160 case DEBUG_INT3_VECTOR
:
2161 switch (BreakCause
) {
2162 case DEBUG_DATA_BREAK_CAUSE_SYSTEM_RESET
:
2163 if (AttachHost (BreakCause
, READ_PACKET_TIMEOUT
, &BreakReceived
) != RETURN_SUCCESS
) {
2165 // Try to connect HOST, return if fails
2169 CommandCommunication (Vector
, CpuContext
, BreakReceived
);
2172 case DEBUG_DATA_BREAK_CAUSE_STEPPING
:
2174 // Stepping is finished, send Ack package.
2176 if (MultiProcessorDebugSupport()) {
2177 mDebugMpContext
.BreakAtCpuIndex
= ProcessorIndex
;
2179 SendAckPacket (DEBUG_COMMAND_OK
);
2180 CommandCommunication (Vector
, CpuContext
, BreakReceived
);
2183 case DEBUG_DATA_BREAK_CAUSE_MEMORY_READY
:
2187 SendCommandAndWaitForAckOK (DEBUG_COMMAND_MEMORY_READY
, READ_PACKET_TIMEOUT
, &BreakReceived
, NULL
);
2188 CommandCommunication (Vector
, CpuContext
, BreakReceived
);
2191 case DEBUG_DATA_BREAK_CAUSE_IMAGE_LOAD
:
2192 case DEBUG_DATA_BREAK_CAUSE_IMAGE_UNLOAD
:
2194 // Set AL to DEBUG_AGENT_IMAGE_CONTINUE
2196 Al
= ArchReadRegisterBuffer (CpuContext
, SOFT_DEBUGGER_REGISTER_AX
, &Data8
);
2197 *Al
= DEBUG_AGENT_IMAGE_CONTINUE
;
2199 if (!IsHostAttached ()) {
2201 // If HOST is not connected for image load/unload, return
2206 // Continue to run the following common code
2209 case DEBUG_DATA_BREAK_CAUSE_HW_BREAKPOINT
:
2210 case DEBUG_DATA_BREAK_CAUSE_SW_BREAKPOINT
:
2213 // Send Break packet to HOST
2215 AcquireMpSpinLock (&mDebugMpContext
.DebugPortSpinLock
);
2217 // Only the first breaking processor could send BREAK_POINT to HOST
2219 if (IsFirstBreakProcessor (ProcessorIndex
)) {
2220 SendBreakPacketToHost (BreakCause
, ProcessorIndex
, &BreakReceived
);
2222 ReleaseMpSpinLock (&mDebugMpContext
.DebugPortSpinLock
);
2224 if (Vector
== DEBUG_INT3_VECTOR
) {
2226 // go back address located "0xCC"
2229 SavedEip
= CpuContext
->Eip
;
2230 CommandCommunication (Vector
, CpuContext
, BreakReceived
);
2231 if ((SavedEip
== CpuContext
->Eip
) &&
2232 (*(UINT8
*) (UINTN
) CpuContext
->Eip
== DEBUG_SW_BREAKPOINT_SYMBOL
)) {
2234 // If this is not a software breakpoint set by HOST,
2240 CommandCommunication (Vector
, CpuContext
, BreakReceived
);
2247 case DEBUG_TIMER_VECTOR
:
2249 AcquireMpSpinLock (&mDebugMpContext
.DebugPortSpinLock
);
2251 if (MultiProcessorDebugSupport()) {
2252 if (IsBsp (ProcessorIndex
)) {
2254 // If current processor is BSP, check Apic timer's init count if changed,
2255 // it may be re-written when switching BSP.
2256 // If it changed, re-initialize debug timer
2258 CurrentDebugTimerInitCount
= GetApicTimerInitCount ();
2259 if (mDebugMpContext
.DebugTimerInitCount
!= CurrentDebugTimerInitCount
) {
2260 InitializeDebugTimer ();
2264 if (!IsBsp (ProcessorIndex
) || mDebugMpContext
.IpiSentByAp
) {
2265 ReleaseMpSpinLock (&mDebugMpContext
.DebugPortSpinLock
);
2267 // If current processor is not BSP or this is one IPI sent by AP
2269 if (mDebugMpContext
.BreakAtCpuIndex
!= (UINT32
) (-1)) {
2270 CommandCommunication (Vector
, CpuContext
, FALSE
);
2274 // Clear EOI before exiting interrupt process routine.
2282 // Only BSP could run here
2286 // If there is data in debug port, will check whether it is break(attach/break-in) symbol,
2287 // If yes, go into communication mode with HOST.
2288 // If no, exit interrupt process.
2290 if (DebugReadBreakSymbol (Handle
, &InputCharacter
) == EFI_NOT_FOUND
) {
2294 if ((!IsHostAttached () && (InputCharacter
== DEBUG_STARTING_SYMBOL_ATTACH
)) ||
2295 (IsHostAttached () && (InputCharacter
== DEBUG_COMMAND_HALT
)) ||
2296 (IsHostAttached () && (InputCharacter
== DEBUG_COMMAND_GO
))
2298 DebugAgentMsgPrint (DEBUG_AGENT_VERBOSE
, "Received data [%02x]\n", InputCharacter
);
2300 // Ack OK for break-in symbol
2302 SendAckPacket (DEBUG_COMMAND_OK
);
2305 // If receive GO command in Debug Timer, means HOST may lost ACK packet before.
2307 if (InputCharacter
== DEBUG_COMMAND_GO
) {
2311 if (!IsHostAttached ()) {
2313 // Try to attach HOST, if no ack received after 200ms, return
2315 if (AttachHost (BreakCause
, READ_PACKET_TIMEOUT
, &BreakReceived
) != RETURN_SUCCESS
) {
2320 if (MultiProcessorDebugSupport()) {
2321 if(FindNextPendingBreakCpu () != -1) {
2322 SetCpuBreakFlagByIndex (ProcessorIndex
, TRUE
);
2324 HaltOtherProcessors (ProcessorIndex
);
2327 ReleaseMpSpinLock (&mDebugMpContext
.DebugPortSpinLock
);
2328 CommandCommunication (Vector
, CpuContext
, BreakReceived
);
2329 AcquireMpSpinLock (&mDebugMpContext
.DebugPortSpinLock
);
2335 // Clear EOI before exiting interrupt process routine.
2339 ReleaseMpSpinLock (&mDebugMpContext
.DebugPortSpinLock
);
2344 if (Vector
<= DEBUG_EXCEPT_SIMD
) {
2345 if (BreakCause
== DEBUG_DATA_BREAK_CAUSE_STEPPING
) {
2347 // Stepping is finished, send Ack package.
2349 if (MultiProcessorDebugSupport()) {
2350 mDebugMpContext
.BreakAtCpuIndex
= ProcessorIndex
;
2352 SendAckPacket (DEBUG_COMMAND_OK
);
2355 // Exception occurs, send Break packet to HOST
2357 AcquireMpSpinLock (&mDebugMpContext
.DebugPortSpinLock
);
2359 // Only the first breaking processor could send BREAK_POINT to HOST
2361 if (IsFirstBreakProcessor (ProcessorIndex
)) {
2362 SendBreakPacketToHost (BreakCause
, ProcessorIndex
, &BreakReceived
);
2364 ReleaseMpSpinLock (&mDebugMpContext
.DebugPortSpinLock
);
2367 CommandCommunication (Vector
, CpuContext
, BreakReceived
);
2372 if (MultiProcessorDebugSupport()) {
2374 // Clear flag and wait for all processors run here
2376 SetIpiSentByApFlag (FALSE
);
2377 while (mDebugMpContext
.RunCommandSet
) {
2382 // Only current (view) processor could clean up AgentInProgress flag.
2384 if (mDebugMpContext
.ViewPointIndex
== ProcessorIndex
) {
2385 IssuedViewPoint
= mDebugMpContext
.ViewPointIndex
;
2389 if (IssuedViewPoint
== ProcessorIndex
&& GetDebugFlag (DEBUG_AGENT_FLAG_STEPPING
) != 1) {
2391 // If the command is not stepping, clean up AgentInProgress flag
2393 SetDebugFlag (DEBUG_AGENT_FLAG_AGENT_IN_PROGRESS
, 0);