2 Commond Debug Agent library implementition. It mainly includes
3 the first C function called by exception/interrupt handlers,
4 read/write debug packet to communication with HOST based on transfer
7 Copyright (c) 2010 - 2015, Intel Corporation. All rights reserved.<BR>
8 This program and the accompanying materials
9 are licensed and made available under the terms and conditions of the BSD License
10 which accompanies this distribution. The full text of the license may be found at
11 http://opensource.org/licenses/bsd-license.php.
13 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
14 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
18 #include "DebugAgent.h"
19 #include "Ia32/DebugException.h"
21 GLOBAL_REMOVE_IF_UNREFERENCED CHAR8 mErrorMsgVersionAlert
[] = "\rThe SourceLevelDebugPkg you are using requires a newer version of the Intel(R) UDK Debugger Tool.\r\n";
22 GLOBAL_REMOVE_IF_UNREFERENCED CHAR8 mErrorMsgSendInitPacket
[] = "\rSend INIT break packet and try to connect the HOST (Intel(R) UDK Debugger Tool v1.4) ...\r\n";
23 GLOBAL_REMOVE_IF_UNREFERENCED CHAR8 mErrorMsgConnectOK
[] = "HOST connection is successful!\r\n";
24 GLOBAL_REMOVE_IF_UNREFERENCED CHAR8 mErrorMsgConnectFail
[] = "HOST connection is failed!\r\n";
25 GLOBAL_REMOVE_IF_UNREFERENCED CHAR8 mWarningMsgIngoreBreakpoint
[] = "Ignore break point in SMM for SMI issued during DXE debugging!\r\n";
28 // Vector Handoff Info list used by Debug Agent for persist
30 GLOBAL_REMOVE_IF_UNREFERENCED EFI_VECTOR_HANDOFF_INFO mVectorHandoffInfoDebugAgent
[] = {
32 DEBUG_EXCEPT_DIVIDE_ERROR
, // Vector 0
33 EFI_VECTOR_HANDOFF_HOOK_BEFORE
,
37 DEBUG_EXCEPT_DEBUG
, // Vector 1
38 EFI_VECTOR_HANDOFF_DO_NOT_HOOK
,
42 DEBUG_EXCEPT_NMI
, // Vector 2
43 EFI_VECTOR_HANDOFF_HOOK_BEFORE
,
47 DEBUG_EXCEPT_BREAKPOINT
, // Vector 3
48 EFI_VECTOR_HANDOFF_DO_NOT_HOOK
,
52 DEBUG_EXCEPT_OVERFLOW
, // Vector 4
53 EFI_VECTOR_HANDOFF_HOOK_BEFORE
,
57 DEBUG_EXCEPT_BOUND
, // Vector 5
58 EFI_VECTOR_HANDOFF_HOOK_BEFORE
,
62 DEBUG_EXCEPT_INVALID_OPCODE
, // Vector 6
63 EFI_VECTOR_HANDOFF_HOOK_BEFORE
,
67 DEBUG_EXCEPT_DOUBLE_FAULT
, // Vector 8
68 EFI_VECTOR_HANDOFF_HOOK_BEFORE
,
72 DEBUG_EXCEPT_INVALID_TSS
, // Vector 10
73 EFI_VECTOR_HANDOFF_HOOK_BEFORE
,
77 DEBUG_EXCEPT_SEG_NOT_PRESENT
, // Vector 11
78 EFI_VECTOR_HANDOFF_HOOK_BEFORE
,
82 DEBUG_EXCEPT_STACK_FAULT
, // Vector 12
83 EFI_VECTOR_HANDOFF_HOOK_BEFORE
,
87 DEBUG_EXCEPT_GP_FAULT
, // Vector 13
88 EFI_VECTOR_HANDOFF_HOOK_BEFORE
,
92 DEBUG_EXCEPT_PAGE_FAULT
, // Vector 14
93 EFI_VECTOR_HANDOFF_HOOK_BEFORE
,
97 DEBUG_EXCEPT_FP_ERROR
, // Vector 16
98 EFI_VECTOR_HANDOFF_HOOK_BEFORE
,
102 DEBUG_EXCEPT_ALIGNMENT_CHECK
, // Vector 17
103 EFI_VECTOR_HANDOFF_HOOK_BEFORE
,
107 DEBUG_EXCEPT_MACHINE_CHECK
, // Vector 18
108 EFI_VECTOR_HANDOFF_HOOK_BEFORE
,
112 DEBUG_EXCEPT_SIMD
, // Vector 19
113 EFI_VECTOR_HANDOFF_HOOK_BEFORE
,
117 DEBUG_TIMER_VECTOR
, // Vector 32
118 EFI_VECTOR_HANDOFF_DO_NOT_HOOK
,
122 DEBUG_MAILBOX_VECTOR
, // Vector 33
123 EFI_VECTOR_HANDOFF_DO_NOT_HOOK
,
128 EFI_VECTOR_HANDOFF_LAST_ENTRY
,
133 GLOBAL_REMOVE_IF_UNREFERENCED UINTN mVectorHandoffInfoCount
= sizeof (mVectorHandoffInfoDebugAgent
) / sizeof (EFI_VECTOR_HANDOFF_INFO
);
136 Calculate CRC16 for target data.
138 @param[in] Data The target data.
139 @param[in] DataSize The target data size.
140 @param[in] Crc Initial CRC.
142 @return UINT16 The CRC16 value.
155 for (Index
= 0; Index
< DataSize
; Index
++) {
156 Crc
^= (UINT16
)Data
[Index
];
157 for (BitIndex
= 0; BitIndex
< 8; BitIndex
++) {
158 if ((Crc
& 0x8000) != 0) {
171 Read IDT entry to check if IDT entries are setup by Debug Agent.
173 @retval TRUE IDT entries were setup by Debug Agent.
174 @retval FALSE IDT entries were not setup by Debug Agent.
178 IsDebugAgentInitialzed (
182 UINTN InterruptHandler
;
184 InterruptHandler
= (UINTN
) GetExceptionHandlerInIdtEntry (0);
185 if (InterruptHandler
>= 4 && *(UINT32
*)(InterruptHandler
- 4) == AGENT_HANDLER_SIGNATURE
) {
193 Find and report module image info to HOST.
195 @param[in] AlignSize Image aligned size.
199 FindAndReportModuleImageInfo (
204 EFI_IMAGE_DOS_HEADER
*DosHdr
;
205 EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION Hdr
;
206 PE_COFF_LOADER_IMAGE_CONTEXT ImageContext
;
211 Pe32Data
= ((UINTN
)mErrorMsgVersionAlert
) & ~(AlignSize
- 1);
212 while (Pe32Data
!= 0) {
213 DosHdr
= (EFI_IMAGE_DOS_HEADER
*) Pe32Data
;
214 if (DosHdr
->e_magic
== EFI_IMAGE_DOS_SIGNATURE
) {
216 // DOS image header is present, so read the PE header after the DOS image header.
218 Hdr
.Pe32
= (EFI_IMAGE_NT_HEADERS32
*)(Pe32Data
+ (UINTN
) ((DosHdr
->e_lfanew
) & 0x0ffff));
220 // Make sure PE header address does not overflow and is less than the initial address.
222 if (((UINTN
)Hdr
.Pe32
> Pe32Data
) && ((UINTN
)Hdr
.Pe32
< (UINTN
)mErrorMsgVersionAlert
)) {
223 if (Hdr
.Pe32
->Signature
== EFI_IMAGE_NT_SIGNATURE
) {
232 // DOS image header is not present, TE header is at the image base.
234 Hdr
.Pe32
= (EFI_IMAGE_NT_HEADERS32
*)Pe32Data
;
235 if ((Hdr
.Te
->Signature
== EFI_TE_IMAGE_HEADER_SIGNATURE
) &&
236 ((Hdr
.Te
->Machine
== IMAGE_FILE_MACHINE_I386
) || Hdr
.Te
->Machine
== IMAGE_FILE_MACHINE_X64
)) {
238 // It's TE image, it TE header and Machine type match
245 // Not found the image base, check the previous aligned address
247 Pe32Data
-= AlignSize
;
250 ImageContext
.ImageAddress
= Pe32Data
;
251 ImageContext
.PdbPointer
= PeCoffLoaderGetPdbPointer ((VOID
*) (UINTN
) ImageContext
.ImageAddress
);
252 PeCoffLoaderRelocateImageExtraAction (&ImageContext
);
256 Trigger one software interrupt to debug agent to handle it.
258 @param[in] Signature Software interrupt signature.
262 TriggerSoftInterrupt (
270 // Save Debug Register State
278 AsmWriteDr0 (SOFT_INTERRUPT_SIGNATURE
);
279 AsmWriteDr1 (Signature
);
282 // Do INT3 to communicate with HOST side
287 // Restore Debug Register State only when Host didn't change it inside exception handler.
288 // Dr registers can only be changed by setting the HW breakpoint.
296 Calculate Mailbox checksum and update the checksum field.
298 @param[in] Mailbox Debug Agent Mailbox pointer.
302 UpdateMailboxChecksum (
303 IN DEBUG_AGENT_MAILBOX
*Mailbox
306 Mailbox
->CheckSum
= CalculateCheckSum8 ((UINT8
*)Mailbox
, sizeof (DEBUG_AGENT_MAILBOX
) - 2);
310 Verify Mailbox checksum.
312 If checksum error, print debug message and run init dead loop.
314 @param[in] Mailbox Debug Agent Mailbox pointer.
318 VerifyMailboxChecksum (
319 IN DEBUG_AGENT_MAILBOX
*Mailbox
324 CheckSum
= CalculateCheckSum8 ((UINT8
*) Mailbox
, sizeof (DEBUG_AGENT_MAILBOX
) - 2);
326 // The checksum updating process may be disturbed by hardware SMI, we need to check CheckSum field
327 // and ToBeCheckSum field to validate the mail box.
329 if (CheckSum
!= Mailbox
->CheckSum
&& CheckSum
!= Mailbox
->ToBeCheckSum
) {
330 DEBUG ((EFI_D_ERROR
, "DebugAgent: Mailbox checksum error, stack or heap crashed!\n"));
331 DEBUG ((EFI_D_ERROR
, "DebugAgent: CheckSum = %x, Mailbox->CheckSum = %x, Mailbox->ToBeCheckSum = %x\n", CheckSum
, Mailbox
->CheckSum
, Mailbox
->ToBeCheckSum
));
337 Update Mailbox content by index.
339 @param[in] Mailbox Debug Agent Mailbox pointer.
340 @param[in] Index Mailbox content index.
341 @param[in] Value Value to be set into Mailbox.
345 UpdateMailboxContent (
346 IN DEBUG_AGENT_MAILBOX
*Mailbox
,
351 AcquireMpSpinLock (&mDebugMpContext
.MailboxSpinLock
);
353 case DEBUG_MAILBOX_DEBUG_FLAG_INDEX
:
354 Mailbox
->ToBeCheckSum
= Mailbox
->CheckSum
+ CalculateSum8 ((UINT8
*)&Mailbox
->DebugFlag
.Uint64
, sizeof(UINT64
))
355 - CalculateSum8 ((UINT8
*)&Value
, sizeof(UINT64
));
356 Mailbox
->DebugFlag
.Uint64
= Value
;
358 case DEBUG_MAILBOX_DEBUG_PORT_HANDLE_INDEX
:
359 Mailbox
->ToBeCheckSum
= Mailbox
->CheckSum
+ CalculateSum8 ((UINT8
*)&Mailbox
->DebugPortHandle
, sizeof(UINTN
))
360 - CalculateSum8 ((UINT8
*)&Value
, sizeof(UINTN
));
361 Mailbox
->DebugPortHandle
= (UINTN
) Value
;
363 case DEBUG_MAILBOX_EXCEPTION_BUFFER_POINTER_INDEX
:
364 Mailbox
->ToBeCheckSum
= Mailbox
->CheckSum
+ CalculateSum8 ((UINT8
*)&Mailbox
->ExceptionBufferPointer
, sizeof(UINTN
))
365 - CalculateSum8 ((UINT8
*)&Value
, sizeof(UINTN
));
366 Mailbox
->ExceptionBufferPointer
= (UINTN
) Value
;
368 case DEBUG_MAILBOX_LAST_ACK
:
369 Mailbox
->ToBeCheckSum
= Mailbox
->CheckSum
+ CalculateSum8 ((UINT8
*)&Mailbox
->LastAck
, sizeof(UINT8
))
370 - CalculateSum8 ((UINT8
*)&Value
, sizeof(UINT8
));
371 Mailbox
->LastAck
= (UINT8
) Value
;
373 case DEBUG_MAILBOX_SEQUENCE_NO_INDEX
:
374 Mailbox
->ToBeCheckSum
= Mailbox
->CheckSum
+ CalculateSum8 ((UINT8
*)&Mailbox
->SequenceNo
, sizeof(UINT8
))
375 - CalculateSum8 ((UINT8
*)&Value
, sizeof(UINT8
));
376 Mailbox
->SequenceNo
= (UINT8
) Value
;
378 case DEBUG_MAILBOX_HOST_SEQUENCE_NO_INDEX
:
379 Mailbox
->ToBeCheckSum
= Mailbox
->CheckSum
+ CalculateSum8 ((UINT8
*)&Mailbox
->HostSequenceNo
, sizeof(UINT8
))
380 - CalculateSum8 ((UINT8
*)&Value
, sizeof(UINT8
));
381 Mailbox
->HostSequenceNo
= (UINT8
) Value
;
383 case DEBUG_MAILBOX_DEBUG_TIMER_FREQUENCY
:
384 Mailbox
->ToBeCheckSum
= Mailbox
->CheckSum
+ CalculateSum8 ((UINT8
*)&Mailbox
->DebugTimerFrequency
, sizeof(UINT32
))
385 - CalculateSum8 ((UINT8
*)&Value
, sizeof(UINT32
));
386 Mailbox
->DebugTimerFrequency
= (UINT32
) Value
;
389 UpdateMailboxChecksum (Mailbox
);
390 ReleaseMpSpinLock (&mDebugMpContext
.MailboxSpinLock
);
394 Read data from debug device and save the data in buffer.
396 Reads NumberOfBytes data bytes from a debug device into the buffer
397 specified by Buffer. The number of bytes actually read is returned.
398 If the return value is less than NumberOfBytes, then the rest operation failed.
399 If NumberOfBytes is zero, then return 0.
401 @param Handle Debug port handle.
402 @param Buffer Pointer to the data buffer to store the data read from the debug device.
403 @param NumberOfBytes Number of bytes which will be read.
404 @param Timeout Timeout value for reading from debug device. It unit is Microsecond.
406 @retval 0 Read data failed, no data is to be read.
407 @retval >0 Actual number of bytes read from debug device.
411 DebugAgentReadBuffer (
412 IN DEBUG_PORT_HANDLE Handle
,
414 IN UINTN NumberOfBytes
,
420 UINT32 TimeoutTicker
;
422 UINT32 TimerFrequency
;
428 TimerFrequency
= GetMailboxPointer()->DebugTimerFrequency
;
429 TimerCycle
= GetApicTimerInitCount ();
432 Begin
= GetApicTimerCurrentCount ();
433 TimeoutTicker
= (UINT32
) DivU64x32 (
440 TimerRound
= (UINT32
) DivU64x32Remainder (TimeoutTicker
, TimerCycle
/ 2, &TimeoutTicker
);
443 while (Index
< NumberOfBytes
) {
444 if (DebugPortPollBuffer (Handle
)) {
445 DebugPortReadBuffer (Handle
, Buffer
+ Index
, 1, 0);
450 if (TimerRound
== 0) {
451 if (IsDebugTimerTimeout (TimerCycle
, Begin
, TimeoutTicker
)) {
453 // If time out occurs.
458 if (IsDebugTimerTimeout (TimerCycle
, Begin
, TimerCycle
/ 2)) {
460 Begin
= GetApicTimerCurrentCount ();
470 Set debug flag in mailbox.
472 @param[in] FlagMask Debug flag mask value.
473 @param[in] FlagValue Debug flag value.
482 DEBUG_AGENT_MAILBOX
*Mailbox
;
485 Mailbox
= GetMailboxPointer ();
486 Data64
= (Mailbox
->DebugFlag
.Uint64
& ~FlagMask
) |
487 (LShiftU64 ((UINT64
)FlagValue
, LowBitSet64 (FlagMask
)) & FlagMask
);
488 UpdateMailboxContent (Mailbox
, DEBUG_MAILBOX_DEBUG_FLAG_INDEX
, Data64
);
492 Get debug flag in mailbox.
494 @param[in] FlagMask Debug flag mask value.
496 @return Debug flag value.
504 DEBUG_AGENT_MAILBOX
*Mailbox
;
507 Mailbox
= GetMailboxPointer ();
508 DebugFlag
= (UINT32
) RShiftU64 (Mailbox
->DebugFlag
.Uint64
& FlagMask
, LowBitSet64 (FlagMask
));
514 Send a debug message packet to the debug port.
516 @param[in] Buffer The debug message.
517 @param[in] Length The length of debug message.
526 DEBUG_PACKET_HEADER DebugHeader
;
527 DEBUG_PORT_HANDLE Handle
;
529 Handle
= GetDebugPortHandle();
531 DebugHeader
.StartSymbol
= DEBUG_STARTING_SYMBOL_NORMAL
;
532 DebugHeader
.Command
= DEBUG_COMMAND_PRINT_MESSAGE
;
533 DebugHeader
.Length
= sizeof (DEBUG_PACKET_HEADER
) + (UINT8
) Length
;
534 DebugHeader
.SequenceNo
= 0xEE;
536 DebugHeader
.Crc
= CalculateCrc16 (
537 (UINT8
*)Buffer
, Length
,
538 CalculateCrc16 ((UINT8
*)&DebugHeader
, sizeof (DEBUG_PACKET_HEADER
), 0)
541 DebugPortWriteBuffer (Handle
, (UINT8
*)&DebugHeader
, sizeof (DEBUG_PACKET_HEADER
));
542 DebugPortWriteBuffer (Handle
, (UINT8
*)Buffer
, Length
);
546 Prints a debug message to the debug port if the specified error level is enabled.
548 If any bit in ErrorLevel is also set in Mainbox, then print the message specified
549 by Format and the associated variable argument list to the debug port.
551 @param[in] ErrorLevel The error level of the debug message.
552 @param[in] Format Format string for the debug message to print.
553 @param[in] ... Variable argument list whose contents are accessed
554 based on the format string specified by Format.
565 CHAR8 Buffer
[DEBUG_DATA_MAXIMUM_REAL_DATA
];
569 // Check driver debug mask value and global mask
571 if ((ErrorLevel
& GetDebugFlag (DEBUG_AGENT_FLAG_PRINT_ERROR_LEVEL
)) == 0) {
576 // Convert the DEBUG() message to an ASCII String
578 VA_START (Marker
, Format
);
579 AsciiVSPrint (Buffer
, sizeof (Buffer
), Format
, Marker
);
582 SendDebugMsgPacket (Buffer
, AsciiStrLen (Buffer
));
586 Prints a debug message to the debug output device if the specified error level is enabled.
588 If any bit in ErrorLevel is also set in DebugPrintErrorLevelLib function
589 GetDebugPrintErrorLevel (), then print the message specified by Format and the
590 associated variable argument list to the debug output device.
592 If Format is NULL, then ASSERT().
594 @param[in] ErrorLevel The error level of the debug message.
595 @param[in] IsSend Flag of debug message to declare that the data is being sent or being received.
596 @param[in] Data Variable argument list whose contents are accessed
597 @param[in] Length based on the format string specified by Format.
602 DebugAgentDataMsgPrint (
609 CHAR8 Buffer
[DEBUG_DATA_MAXIMUM_REAL_DATA
];
614 // Check driver debug mask value and global mask
616 if ((ErrorLevel
& GetDebugFlag (DEBUG_AGENT_FLAG_PRINT_ERROR_LEVEL
)) == 0) {
622 DestBuffer
+= AsciiSPrint (DestBuffer
, DEBUG_DATA_MAXIMUM_REAL_DATA
, "Sent data [ ");
624 DestBuffer
+= AsciiSPrint (DestBuffer
, DEBUG_DATA_MAXIMUM_REAL_DATA
, "Received data [ ");
629 if (DestBuffer
- Buffer
> DEBUG_DATA_MAXIMUM_REAL_DATA
- 6) {
631 // If there was no enough space in buffer, send out the debug message,
632 // reserving 6 bytes is for the last data and end characters "]\n".
634 SendDebugMsgPacket (Buffer
, DestBuffer
- Buffer
);
637 DestBuffer
+= AsciiSPrint (DestBuffer
, DEBUG_DATA_MAXIMUM_REAL_DATA
- (DestBuffer
- Buffer
), "%02x ", Data
[Index
]);
639 if (Index
>= Length
) {
641 // The last character of debug message has been foramtted in buffer
643 DestBuffer
+= AsciiSPrint(DestBuffer
, DEBUG_DATA_MAXIMUM_REAL_DATA
- (DestBuffer
- Buffer
), "]\n");
644 SendDebugMsgPacket (Buffer
, DestBuffer
- Buffer
);
651 Read remaing debug packet except for the start symbol
653 @param[in] Handle Pointer to Debug Port handle.
654 @param[in, out] DebugHeader Debug header buffer including start symbol.
656 @retval EFI_SUCCESS Read the symbol in BreakSymbol.
657 @retval EFI_CRC_ERROR CRC check fail.
658 @retval EFI_TIMEOUT Timeout occurs when reading debug packet.
659 @retval EFI_DEVICE_ERROR Receive the old or responsed packet.
663 ReadRemainingBreakPacket (
664 IN DEBUG_PORT_HANDLE Handle
,
665 IN OUT DEBUG_PACKET_HEADER
*DebugHeader
669 DEBUG_AGENT_MAILBOX
*Mailbox
;
672 // Has received start symbol, try to read the rest part
674 if (DebugAgentReadBuffer (Handle
, (UINT8
*)DebugHeader
+ OFFSET_OF (DEBUG_PACKET_HEADER
, Command
), sizeof (DEBUG_PACKET_HEADER
) - OFFSET_OF (DEBUG_PACKET_HEADER
, Command
), READ_PACKET_TIMEOUT
) == 0) {
676 // Timeout occur, exit
678 DebugAgentMsgPrint (DEBUG_AGENT_WARNING
, "Timeout in Debug Timer interrupt\n");
682 Crc
= DebugHeader
->Crc
;
683 DebugHeader
->Crc
= 0;
684 if (CalculateCrc16 ((UINT8
*)DebugHeader
, DebugHeader
->Length
, 0) != Crc
) {
685 DebugAgentMsgPrint (DEBUG_AGENT_WARNING
, "Debug Timer CRC (%x) against (%x)\n", Crc
, CalculateCrc16 ((UINT8
*) &DebugHeader
, DebugHeader
->Length
, 0));
686 DebugAgentDataMsgPrint (DEBUG_AGENT_VERBOSE
, FALSE
, (UINT8
*)DebugHeader
, DebugHeader
->Length
);
687 return EFI_CRC_ERROR
;
689 Mailbox
= GetMailboxPointer();
690 if (IS_REQUEST (DebugHeader
)) {
691 if (DebugHeader
->SequenceNo
== (UINT8
) (Mailbox
->HostSequenceNo
+ 1)) {
693 // Only updagte HostSequenceNo for new command packet
695 UpdateMailboxContent (Mailbox
, DEBUG_MAILBOX_HOST_SEQUENCE_NO_INDEX
, DebugHeader
->SequenceNo
);
698 if (DebugHeader
->SequenceNo
== Mailbox
->HostSequenceNo
) {
703 return EFI_DEVICE_ERROR
;
707 Check if HOST is attached based on Mailbox.
709 @retval TRUE HOST is attached.
710 @retval FALSE HOST is not attached.
718 return (BOOLEAN
) (GetDebugFlag (DEBUG_AGENT_FLAG_HOST_ATTACHED
) == 1);
722 Set HOST connect flag in Mailbox.
724 @param[in] Attached Attach status.
732 DebugAgentMsgPrint (DEBUG_AGENT_INFO
, "Attach status is %d\n", Attached
);
733 SetDebugFlag (DEBUG_AGENT_FLAG_HOST_ATTACHED
, (UINT32
)Attached
);
737 Set debug setting of Debug Agent in Mailbox.
739 @param DebugSetting Pointer to Debug Setting defined by transfer protocol.
741 @retval RETURN_SUCCESS The setting is set successfully.
742 @retval RETURN_UNSUPPORTED The Key value is not supported.
747 IN DEBUG_DATA_SET_DEBUG_SETTING
*DebugSetting
750 RETURN_STATUS Status
;
752 Status
= RETURN_SUCCESS
;
753 switch (DebugSetting
->Key
) {
754 case DEBUG_AGENT_SETTING_SMM_ENTRY_BREAK
:
755 SetDebugFlag (DEBUG_AGENT_FLAG_BREAK_ON_NEXT_SMI
, DebugSetting
->Value
);
757 case DEBUG_AGENT_SETTING_PRINT_ERROR_LEVEL
:
758 SetDebugFlag (DEBUG_AGENT_FLAG_PRINT_ERROR_LEVEL
, DebugSetting
->Value
);
760 case DEBUG_AGENT_SETTING_BOOT_SCRIPT_ENTRY_BREAK
:
761 SetDebugFlag (DEBUG_AGENT_FLAG_BREAK_BOOT_SCRIPT
, DebugSetting
->Value
);
764 Status
= RETURN_UNSUPPORTED
;
772 @param[in] CpuContext Pointer to saved CPU context.
777 IN DEBUG_CPU_CONTEXT
*CpuContext
780 IA32_EFLAGS32
*Eflags
;
782 Eflags
= (IA32_EFLAGS32
*) &CpuContext
->Eflags
;
788 Execute Stepping command.
790 @param[in] CpuContext Pointer to saved CPU context.
795 IN DEBUG_CPU_CONTEXT
*CpuContext
798 IA32_EFLAGS32
*Eflags
;
800 Eflags
= (IA32_EFLAGS32
*) &CpuContext
->Eflags
;
804 // Save and clear EFLAGS.IF to avoid interrupt happen when executing Stepping
806 SetDebugFlag (DEBUG_AGENT_FLAG_INTERRUPT_FLAG
, Eflags
->Bits
.IF
);
811 SetDebugFlag (DEBUG_AGENT_FLAG_STEPPING
, 1);
815 Do some cleanup after Stepping command done.
817 @param[in] CpuContext Pointer to saved CPU context.
821 CommandSteppingCleanup (
822 IN DEBUG_CPU_CONTEXT
*CpuContext
825 IA32_EFLAGS32
*Eflags
;
827 Eflags
= (IA32_EFLAGS32
*) &CpuContext
->Eflags
;
831 Eflags
->Bits
.IF
= GetDebugFlag (DEBUG_AGENT_FLAG_INTERRUPT_FLAG
);
833 // Clear Stepping flag
835 SetDebugFlag (DEBUG_AGENT_FLAG_STEPPING
, 0);
839 Set debug register for hardware breakpoint.
841 @param[in] CpuContext Pointer to saved CPU context.
842 @param[in] SetHwBreakpoint Hardware breakpoint to be set.
847 IN DEBUG_CPU_CONTEXT
*CpuContext
,
848 IN DEBUG_DATA_SET_HW_BREAKPOINT
*SetHwBreakpoint
854 RegisterIndex
= SetHwBreakpoint
->Type
.Index
;
859 * ((UINTN
*) &CpuContext
->Dr0
+ RegisterIndex
) = (UINTN
) SetHwBreakpoint
->Address
;
861 Dr7Value
= CpuContext
->Dr7
;
866 Dr7Value
|= (UINTN
) (0x3 << (RegisterIndex
* 2));
870 Dr7Value
&= (UINTN
) (~(0xf << (16 + RegisterIndex
* 4)));
871 Dr7Value
|= (UINTN
) ((SetHwBreakpoint
->Type
.Length
<< 2) | SetHwBreakpoint
->Type
.Access
) << (16 + RegisterIndex
* 4);
877 CpuContext
->Dr7
= Dr7Value
;
881 Clear debug register for hardware breakpoint.
883 @param[in] CpuContext Pointer to saved CPU context.
884 @param[in] ClearHwBreakpoint Hardware breakpoint to be cleared.
889 IN DEBUG_CPU_CONTEXT
*CpuContext
,
890 IN DEBUG_DATA_CLEAR_HW_BREAKPOINT
*ClearHwBreakpoint
893 if ((ClearHwBreakpoint
->IndexMask
& BIT0
) != 0) {
895 CpuContext
->Dr7
&= (UINTN
)(~(0x3 << 0));
897 if ((ClearHwBreakpoint
->IndexMask
& BIT1
) != 0) {
899 CpuContext
->Dr7
&= (UINTN
)(~(0x3 << 2));
901 if ((ClearHwBreakpoint
->IndexMask
& BIT2
) != 0) {
903 CpuContext
->Dr7
&= (UINTN
)(~(0x3 << 4));
905 if ((ClearHwBreakpoint
->IndexMask
& BIT3
) != 0) {
907 CpuContext
->Dr7
&= (UINTN
)(~(0x3 << 6));
913 Return the offset of FP / MMX / XMM registers in the FPU saved state by register index.
915 @param[in] Index Register index.
916 @param[out] Width Register width returned.
918 @return Offset in the FPU Save State.
922 ArchReadFxStatOffset (
927 if (Index
< SOFT_DEBUGGER_REGISTER_ST0
) {
929 case SOFT_DEBUGGER_REGISTER_FP_FCW
:
930 *Width
= (UINT8
) sizeof (UINT16
);
931 return OFFSET_OF(DEBUG_DATA_FX_SAVE_STATE
, Fcw
);
933 case SOFT_DEBUGGER_REGISTER_FP_FSW
:
934 *Width
= (UINT8
) sizeof (UINT16
);
935 return OFFSET_OF(DEBUG_DATA_FX_SAVE_STATE
, Fsw
);
937 case SOFT_DEBUGGER_REGISTER_FP_FTW
:
938 *Width
= (UINT8
) sizeof (UINT16
);
939 return OFFSET_OF(DEBUG_DATA_FX_SAVE_STATE
, Ftw
);
941 case SOFT_DEBUGGER_REGISTER_FP_OPCODE
:
942 *Width
= (UINT8
) sizeof (UINT16
);
943 return OFFSET_OF(DEBUG_DATA_FX_SAVE_STATE
, Opcode
);
945 case SOFT_DEBUGGER_REGISTER_FP_EIP
:
946 *Width
= (UINT8
) sizeof (UINT32
);
947 return OFFSET_OF(DEBUG_DATA_FX_SAVE_STATE
, Eip
);
949 case SOFT_DEBUGGER_REGISTER_FP_CS
:
950 *Width
= (UINT8
) sizeof (UINT16
);
951 return OFFSET_OF(DEBUG_DATA_FX_SAVE_STATE
, Cs
);
953 case SOFT_DEBUGGER_REGISTER_FP_DATAOFFSET
:
954 *Width
= (UINT8
) sizeof (UINT32
);
955 return OFFSET_OF(DEBUG_DATA_FX_SAVE_STATE
, DataOffset
);
957 case SOFT_DEBUGGER_REGISTER_FP_DS
:
958 *Width
= (UINT8
) sizeof (UINT16
);
959 return OFFSET_OF(DEBUG_DATA_FX_SAVE_STATE
, Ds
);
961 case SOFT_DEBUGGER_REGISTER_FP_MXCSR
:
962 *Width
= (UINT8
) sizeof (UINT32
);
963 return OFFSET_OF(DEBUG_DATA_FX_SAVE_STATE
, Mxcsr
);
965 case SOFT_DEBUGGER_REGISTER_FP_MXCSR_MASK
:
966 *Width
= (UINT8
) sizeof (UINT32
);
967 return OFFSET_OF(DEBUG_DATA_FX_SAVE_STATE
, Mxcsr_Mask
);
971 if (Index
<= SOFT_DEBUGGER_REGISTER_ST7
) {
973 } else if (Index
<= SOFT_DEBUGGER_REGISTER_XMM15
) {
980 Index
-= SOFT_DEBUGGER_REGISTER_MM0
- SOFT_DEBUGGER_REGISTER_ST0
;
983 return OFFSET_OF (DEBUG_DATA_FX_SAVE_STATE
, St0Mm0
) + (Index
- SOFT_DEBUGGER_REGISTER_ST0
) * 16;
987 Return the pointer of the register value in the CPU saved context.
989 @param[in] CpuContext Pointer to saved CPU context.
990 @param[in] Index Register index value.
991 @param[out] Width Data width to read.
993 @return The pointer in the CPU saved context.
997 ArchReadRegisterBuffer (
998 IN DEBUG_CPU_CONTEXT
*CpuContext
,
1005 if (Index
< SOFT_DEBUGGER_REGISTER_FP_BASE
) {
1006 Buffer
= (UINT8
*) CpuContext
+ OFFSET_OF (DEBUG_CPU_CONTEXT
, Dr0
) + Index
* sizeof (UINTN
);
1007 *Width
= (UINT8
) sizeof (UINTN
);
1010 // FPU/MMX/XMM registers
1012 Buffer
= (UINT8
*) CpuContext
+ OFFSET_OF (DEBUG_CPU_CONTEXT
, FxSaveState
) + ArchReadFxStatOffset (Index
, Width
);
1019 Send the packet without data to HOST.
1021 @param[in] CommandType Type of Command.
1022 @param[in] SequenceNo Sequence number.
1026 SendPacketWithoutData (
1027 IN UINT8 CommandType
,
1031 DEBUG_PACKET_HEADER DebugHeader
;
1032 DEBUG_PORT_HANDLE Handle
;
1034 Handle
= GetDebugPortHandle();
1036 DebugHeader
.StartSymbol
= DEBUG_STARTING_SYMBOL_NORMAL
;
1037 DebugHeader
.Command
= CommandType
;
1038 DebugHeader
.Length
= sizeof (DEBUG_PACKET_HEADER
);
1039 DebugHeader
.SequenceNo
= SequenceNo
;
1040 DebugHeader
.Crc
= 0;
1041 DebugHeader
.Crc
= CalculateCrc16 ((UINT8
*)&DebugHeader
, sizeof (DEBUG_PACKET_HEADER
), 0);
1043 DebugAgentDataMsgPrint (DEBUG_AGENT_VERBOSE
, TRUE
, (UINT8
*) &DebugHeader
, DebugHeader
.Length
);
1044 DebugPortWriteBuffer (Handle
, (UINT8
*) &DebugHeader
, DebugHeader
.Length
);
1048 Send acknowledge packet to HOST.
1050 @param[in] AckCommand Type of Acknowledge packet.
1059 DEBUG_AGENT_MAILBOX
*Mailbox
;
1061 if (AckCommand
!= DEBUG_COMMAND_OK
) {
1063 // This is not ACK OK packet
1065 DebugAgentMsgPrint (DEBUG_AGENT_ERROR
, "Send ACK(%d)\n", AckCommand
);
1067 Mailbox
= GetMailboxPointer();
1068 SequenceNo
= Mailbox
->HostSequenceNo
;
1069 DebugAgentMsgPrint (DEBUG_AGENT_INFO
, "SendAckPacket: SequenceNo = %x\n", SequenceNo
);
1070 SendPacketWithoutData (AckCommand
, SequenceNo
);
1071 UpdateMailboxContent (Mailbox
, DEBUG_MAILBOX_LAST_ACK
, AckCommand
);
1075 Decompress the Data in place.
1077 @param[in, out] Data The compressed data buffer.
1078 The buffer is assumed large enough to hold the uncompressed data.
1079 @param[in] Length The length of the compressed data buffer.
1081 @return The length of the uncompressed data buffer.
1084 DecompressDataInPlace (
1091 UINTN LastCharCount
;
1094 LastChar
= (UINT16
) -1;
1096 for (Index
= 0; Index
< Length
; Index
++) {
1097 CurrentChar
= Data
[Index
];
1098 if (LastCharCount
== 2) {
1100 CopyMem (&Data
[Index
+ CurrentChar
], &Data
[Index
+ 1], Length
- Index
- 1);
1101 SetMem (&Data
[Index
], CurrentChar
, (UINT8
) LastChar
);
1102 LastChar
= (UINT16
) -1;
1103 Index
+= CurrentChar
- 1;
1104 Length
+= CurrentChar
- 1;
1106 if (LastChar
!= CurrentChar
) {
1110 LastChar
= CurrentChar
;
1114 ASSERT (Length
<= DEBUG_DATA_MAXIMUM_REAL_DATA
);
1116 return (UINT8
) Length
;
1120 Receive valid packet from HOST.
1122 @param[out] InputPacket Buffer to receive packet.
1123 @param[out] BreakReceived TRUE means break-in symbol received.
1124 FALSE means break-in symbol not received.
1125 @param[out] IncompatibilityFlag If IncompatibilityFlag is not NULL, return
1126 TRUE: Compatible packet received.
1127 FALSE: Incompatible packet received.
1128 @param[in] Timeout Time out value to wait for acknowlege from HOST.
1129 The unit is microsecond.
1130 @param[in] SkipStartSymbol TRUE: Skip time out when reading start symbol.
1131 FALSE: Does not Skip time out when reading start symbol.
1133 @retval RETURN_SUCCESS A valid package was reveived in InputPacket.
1134 @retval RETURN_TIMEOUT Timeout occurs.
1139 OUT UINT8
*InputPacket
,
1140 OUT BOOLEAN
*BreakReceived
,
1141 OUT BOOLEAN
*IncompatibilityFlag
, OPTIONAL
1143 IN BOOLEAN SkipStartSymbol
1146 DEBUG_PACKET_HEADER
*DebugHeader
;
1148 DEBUG_PORT_HANDLE Handle
;
1150 UINTN TimeoutForStartSymbol
;
1152 Handle
= GetDebugPortHandle();
1153 if (SkipStartSymbol
) {
1154 TimeoutForStartSymbol
= 0;
1156 TimeoutForStartSymbol
= Timeout
;
1159 DebugHeader
= (DEBUG_PACKET_HEADER
*) InputPacket
;
1162 // Find the valid start symbol
1164 Received
= DebugAgentReadBuffer (Handle
, &DebugHeader
->StartSymbol
, sizeof (DebugHeader
->StartSymbol
), TimeoutForStartSymbol
);
1165 if (Received
< sizeof (DebugHeader
->StartSymbol
)) {
1166 DebugAgentMsgPrint (DEBUG_AGENT_WARNING
, "DebugAgentReadBuffer(StartSymbol) timeout\n");
1167 return RETURN_TIMEOUT
;
1170 if ((DebugHeader
->StartSymbol
!= DEBUG_STARTING_SYMBOL_NORMAL
) && (DebugHeader
->StartSymbol
!= DEBUG_STARTING_SYMBOL_COMPRESS
)) {
1171 DebugAgentMsgPrint (DEBUG_AGENT_WARNING
, "Invalid start symbol received [%02x]\n", DebugHeader
->StartSymbol
);
1176 // Read Package header till field Length
1178 Received
= DebugAgentReadBuffer (
1180 (UINT8
*) DebugHeader
+ OFFSET_OF (DEBUG_PACKET_HEADER
, Command
),
1181 OFFSET_OF (DEBUG_PACKET_HEADER
, Length
) + sizeof (DebugHeader
->Length
) - sizeof (DebugHeader
->StartSymbol
),
1184 if (Received
== 0) {
1185 DebugAgentMsgPrint (DEBUG_AGENT_ERROR
, "DebugAgentReadBuffer(Command) timeout\n");
1186 return RETURN_TIMEOUT
;
1188 if (DebugHeader
->Length
< sizeof (DEBUG_PACKET_HEADER
)) {
1189 if (IncompatibilityFlag
!= NULL
) {
1191 // This is one old version debug packet format, set Incompatibility flag
1193 *IncompatibilityFlag
= TRUE
;
1196 // Skip the bad small packet
1202 // Read the payload data include the CRC field
1204 Received
= DebugAgentReadBuffer (Handle
, &DebugHeader
->SequenceNo
, (UINT8
) (DebugHeader
->Length
- OFFSET_OF (DEBUG_PACKET_HEADER
, SequenceNo
)), Timeout
);
1205 if (Received
== 0) {
1206 DebugAgentMsgPrint (DEBUG_AGENT_ERROR
, "DebugAgentReadBuffer(SequenceNo) timeout\n");
1207 return RETURN_TIMEOUT
;
1210 // Calculate the CRC of Debug Packet
1212 Crc
= DebugHeader
->Crc
;
1213 DebugHeader
->Crc
= 0;
1214 if (Crc
== CalculateCrc16 ((UINT8
*) DebugHeader
, DebugHeader
->Length
, 0)) {
1217 DebugAgentMsgPrint (DEBUG_AGENT_WARNING
, "CRC Error (received CRC is %x)\n", Crc
);
1218 DebugAgentDataMsgPrint (DEBUG_AGENT_VERBOSE
, FALSE
, (UINT8
*) DebugHeader
, DebugHeader
->Length
);
1222 DebugAgentDataMsgPrint (DEBUG_AGENT_VERBOSE
, FALSE
, (UINT8
*) DebugHeader
, DebugHeader
->Length
);
1224 if (DebugHeader
->StartSymbol
== DEBUG_STARTING_SYMBOL_COMPRESS
) {
1225 DebugHeader
->StartSymbol
= DEBUG_STARTING_SYMBOL_NORMAL
;
1226 DebugHeader
->Length
= DecompressDataInPlace (
1227 (UINT8
*) (DebugHeader
+ 1), DebugHeader
->Length
- sizeof (DEBUG_PACKET_HEADER
)
1228 ) + sizeof (DEBUG_PACKET_HEADER
);
1230 return RETURN_SUCCESS
;
1234 Receive acknowledge packet OK from HOST in specified time.
1236 @param[in] Command The command type issued by TARGET.
1237 @param[in] Timeout Time out value to wait for acknowlege from HOST.
1238 The unit is microsecond.
1239 @param[out] BreakReceived If BreakReceived is not NULL,
1240 TRUE is retured if break-in symbol received.
1241 FALSE is retured if break-in symbol not received.
1242 @param[out] IncompatibilityFlag If IncompatibilityFlag is not NULL, return
1243 TRUE: Compatible packet received.
1244 FALSE: Incompatible packet received.
1246 @retval RETRUEN_SUCCESS Succeed to receive acknowlege packet from HOST,
1247 the type of acknowlege packet saved in Ack.
1248 @retval RETURN_TIMEOUT Specified timeout value was up.
1252 SendCommandAndWaitForAckOK (
1255 OUT BOOLEAN
*BreakReceived
, OPTIONAL
1256 OUT BOOLEAN
*IncompatibilityFlag OPTIONAL
1259 RETURN_STATUS Status
;
1260 UINT8 InputPacketBuffer
[DEBUG_DATA_UPPER_LIMIT
];
1261 DEBUG_PACKET_HEADER
*DebugHeader
;
1263 UINT8 HostSequenceNo
;
1267 DebugHeader
= (DEBUG_PACKET_HEADER
*) InputPacketBuffer
;
1268 Status
= RETURN_TIMEOUT
;
1269 while (RetryCount
> 0) {
1270 SequenceNo
= GetMailboxPointer()->SequenceNo
;
1271 HostSequenceNo
= GetMailboxPointer()->HostSequenceNo
;
1272 SendPacketWithoutData (Command
, SequenceNo
);
1273 Status
= ReceivePacket ((UINT8
*) DebugHeader
, BreakReceived
, IncompatibilityFlag
, Timeout
, FALSE
);
1274 if (Status
== RETURN_TIMEOUT
) {
1275 if (Command
== DEBUG_COMMAND_INIT_BREAK
) {
1278 DebugAgentMsgPrint (DEBUG_AGENT_WARNING
, "TARGET: Timeout when waiting for ACK packet.\n");
1282 ASSERT_EFI_ERROR (Status
);
1284 // Status == RETURN_SUCCESS
1286 if (DebugHeader
->Command
== DEBUG_COMMAND_OK
&& DebugHeader
->SequenceNo
== SequenceNo
) {
1290 UpdateMailboxContent (GetMailboxPointer(), DEBUG_MAILBOX_SEQUENCE_NO_INDEX
, ++SequenceNo
);
1293 if (DebugHeader
->Command
== DEBUG_COMMAND_GO
&& (DebugHeader
->SequenceNo
== HostSequenceNo
|| Command
== DEBUG_COMMAND_INIT_BREAK
)) {
1297 if (Command
== DEBUG_COMMAND_INIT_BREAK
) {
1298 DebugAgentMsgPrint (DEBUG_AGENT_WARNING
, "TARGET: Receive GO() in last boot\n");
1300 SendPacketWithoutData (DEBUG_COMMAND_OK
, DebugHeader
->SequenceNo
);
1304 ASSERT (Command
== DEBUG_COMMAND_INIT_BREAK
);
1309 Get current break cause.
1311 @param[in] Vector Vector value of exception or interrupt.
1312 @param[in] CpuContext Pointer to save CPU context.
1314 @return The type of break cause defined by XXXX
1320 IN DEBUG_CPU_CONTEXT
*CpuContext
1325 Cause
= DEBUG_DATA_BREAK_CAUSE_UNKNOWN
;
1328 case DEBUG_INT1_VECTOR
:
1329 case DEBUG_INT3_VECTOR
:
1331 if (Vector
== DEBUG_INT1_VECTOR
) {
1335 if ((CpuContext
->Dr6
& BIT14
) != 0) {
1336 Cause
= DEBUG_DATA_BREAK_CAUSE_STEPPING
;
1338 // DR6.BIT14 Indicates (when set) that the debug exception was
1339 // triggered by the single step execution mode.
1340 // The single-step mode is the highest priority debug exception.
1341 // This is single step, no need to check DR0, to ensure single step
1342 // work in PeCoffExtraActionLib (right after triggering a breakpoint
1343 // to report image load/unload).
1348 Cause
= DEBUG_DATA_BREAK_CAUSE_HW_BREAKPOINT
;
1354 Cause
= DEBUG_DATA_BREAK_CAUSE_SW_BREAKPOINT
;
1357 switch (CpuContext
->Dr0
) {
1358 case IMAGE_LOAD_SIGNATURE
:
1359 case IMAGE_UNLOAD_SIGNATURE
:
1361 if (CpuContext
->Dr3
== IO_PORT_BREAKPOINT_ADDRESS
) {
1363 Cause
= (UINT8
) ((CpuContext
->Dr0
== IMAGE_LOAD_SIGNATURE
) ?
1364 DEBUG_DATA_BREAK_CAUSE_IMAGE_LOAD
: DEBUG_DATA_BREAK_CAUSE_IMAGE_UNLOAD
);
1368 case SOFT_INTERRUPT_SIGNATURE
:
1370 if (CpuContext
->Dr1
== MEMORY_READY_SIGNATURE
) {
1371 Cause
= DEBUG_DATA_BREAK_CAUSE_MEMORY_READY
;
1372 CpuContext
->Dr0
= 0;
1373 } else if (CpuContext
->Dr1
== SYSTEM_RESET_SIGNATURE
) {
1374 Cause
= DEBUG_DATA_BREAK_CAUSE_SYSTEM_RESET
;
1375 CpuContext
->Dr0
= 0;
1386 case DEBUG_TIMER_VECTOR
:
1387 Cause
= DEBUG_DATA_BREAK_CAUSE_USER_HALT
;
1392 if (GetDebugFlag (DEBUG_AGENT_FLAG_STEPPING
) == 1) {
1394 // If stepping command is executing
1396 Cause
= DEBUG_DATA_BREAK_CAUSE_STEPPING
;
1398 Cause
= DEBUG_DATA_BREAK_CAUSE_EXCEPTION
;
1408 Copy memory from source to destination with specified width.
1410 @param[out] Dest A pointer to the destination buffer of the memory copy.
1411 @param[in] Src A pointer to the source buffer of the memory copy.
1412 @param[in] Count The number of data with specified width to copy from source to destination.
1413 @param[in] Width Data width in byte.
1434 // Copy memory from tail to avoid memory overlap
1436 Destination
= Dest
+ (Count
- 1) * Width
;
1437 Source
= Src
+ (Count
- 1) * Width
;
1441 while (Count
-- != 0) {
1444 *(UINT8
*) Destination
= MmioRead8 ((UINTN
) Source
);
1447 *(UINT16
*) Destination
= MmioRead16 ((UINTN
) Source
);
1450 *(UINT32
*) Destination
= MmioRead32 ((UINTN
) Source
);
1453 *(UINT64
*) Destination
= MmioRead64 ((UINTN
) Source
);
1459 Destination
+= Step
;
1464 Compress the data buffer but do not modify the original buffer.
1466 The compressed data is directly send to the debug channel.
1467 Compressing in place doesn't work because the data may become larger
1468 during compressing phase. ("3 3 ..." --> "3 3 0 ...")
1469 The routine is expected to be called three times:
1470 1. Compute the length of the compressed data buffer;
1471 2. Compute the CRC of the compressed data buffer;
1472 3. Compress the data and send to the debug channel.
1474 @param[in] Data The data buffer.
1475 @param[in] Length The length of the data buffer.
1476 @param[out] CompressedLength Return the length of the compressed data buffer.
1477 It may be larger than the Length in some cases.
1478 @param[out] CompressedCrc Return the CRC of the compressed data buffer.
1479 @param[in] Handle The debug channel handle to send the compressed data buffer.
1482 CompressDataThenSend (
1485 OUT UINTN
*CompressedLength
, OPTIONAL
1486 OUT UINT16
*CompressedCrc
, OPTIONAL
1487 IN DEBUG_PORT_HANDLE Handle OPTIONAL
1492 UINT8 LastCharCount
;
1494 UINTN CompressedIndex
;
1496 ASSERT (Length
> 0);
1498 LastChar
= Data
[0] + 1; // Just ensure it's different from the first byte.
1501 for (Index
= 0, CompressedIndex
= 0; Index
<= Length
; Index
++) {
1502 if (Index
< Length
) {
1503 CurrentChar
= Data
[Index
];
1505 CurrentChar
= (UINT8
) LastChar
+ 1; // just ensure it's different from LastChar
1507 if (LastChar
!= CurrentChar
) {
1508 if (LastCharCount
== 1) {
1510 if (CompressedCrc
!= NULL
) {
1511 *CompressedCrc
= CalculateCrc16 (&LastChar
, 1, *CompressedCrc
);
1513 if (Handle
!= NULL
) {
1514 DebugPortWriteBuffer (Handle
, &LastChar
, 1);
1517 } else if (LastCharCount
>= 2) {
1518 CompressedIndex
+= 3;
1520 if (CompressedCrc
!= NULL
) {
1521 *CompressedCrc
= CalculateCrc16 (&LastChar
, 1, *CompressedCrc
);
1522 *CompressedCrc
= CalculateCrc16 (&LastChar
, 1, *CompressedCrc
);
1523 *CompressedCrc
= CalculateCrc16 (&LastCharCount
, 1, *CompressedCrc
);
1525 if (Handle
!= NULL
) {
1526 DebugPortWriteBuffer (Handle
, &LastChar
, 1);
1527 DebugPortWriteBuffer (Handle
, &LastChar
, 1);
1528 DebugPortWriteBuffer (Handle
, &LastCharCount
, 1);
1534 LastChar
= CurrentChar
;
1537 if (CompressedLength
!= NULL
) {
1538 *CompressedLength
= CompressedIndex
;
1543 Read memory with speicifed width and send packet with response data to HOST.
1545 @param[in] Data Pointer to response data buffer.
1546 @param[in] Count The number of data with specified Width.
1547 @param[in] Width Data width in byte.
1548 @param[in] DebugHeader Pointer to a buffer for creating response packet and receiving ACK packet,
1549 to minimize the stack usage.
1551 @retval RETURN_SUCCESS Response data was sent successfully.
1555 ReadMemoryAndSendResponsePacket (
1559 IN DEBUG_PACKET_HEADER
*DebugHeader
1562 RETURN_STATUS Status
;
1564 DEBUG_PORT_HANDLE Handle
;
1566 UINTN RemainingDataSize
;
1567 UINT8 CurrentDataSize
;
1568 UINTN CompressedDataSize
;
1570 Handle
= GetDebugPortHandle();
1572 RemainingDataSize
= Count
* Width
;
1574 SequenceNo
= GetMailboxPointer()->HostSequenceNo
;
1575 if (RemainingDataSize
<= DEBUG_DATA_MAXIMUM_REAL_DATA
) {
1577 // If the remaining data is less one real packet size, this is the last data packet
1579 CurrentDataSize
= (UINT8
) RemainingDataSize
;
1581 DebugHeader
->Command
= DEBUG_COMMAND_OK
;
1584 // Data is too larger to be sent in one packet, calculate the actual data size could
1585 // be sent in one Maximum data packet
1587 CurrentDataSize
= (DEBUG_DATA_MAXIMUM_REAL_DATA
/ Width
) * Width
;
1589 DebugHeader
->Command
= DEBUG_COMMAND_IN_PROGRESS
;
1592 // Construct the rest Debug header
1594 DebugHeader
->StartSymbol
= DEBUG_STARTING_SYMBOL_NORMAL
;
1595 DebugHeader
->Length
= CurrentDataSize
+ sizeof (DEBUG_PACKET_HEADER
);
1596 DebugHeader
->SequenceNo
= SequenceNo
;
1597 DebugHeader
->Crc
= 0;
1598 CopyMemByWidth ((UINT8
*) (DebugHeader
+ 1), Data
, CurrentDataSize
/ Width
, Width
);
1601 // Compression/decompression support was added since revision 0.4.
1602 // Revision 0.3 shouldn't compress the packet.
1604 if (DEBUG_AGENT_REVISION
>= DEBUG_AGENT_REVISION_04
) {
1606 // Get the compressed data size without modifying the packet.
1608 CompressDataThenSend (
1609 (UINT8
*) (DebugHeader
+ 1),
1611 &CompressedDataSize
,
1616 CompressedDataSize
= CurrentDataSize
;
1618 if (CompressedDataSize
< CurrentDataSize
) {
1619 DebugHeader
->Length
= (UINT8
) CompressedDataSize
+ sizeof (DEBUG_PACKET_HEADER
);
1620 DebugHeader
->StartSymbol
= DEBUG_STARTING_SYMBOL_COMPRESS
;
1622 // Compute the CRC of the packet head without modifying the packet.
1624 DebugHeader
->Crc
= CalculateCrc16 ((UINT8
*) DebugHeader
, sizeof (DEBUG_PACKET_HEADER
), 0);
1625 CompressDataThenSend (
1626 (UINT8
*) (DebugHeader
+ 1),
1633 // Send out the packet head.
1635 DebugPortWriteBuffer (Handle
, (UINT8
*) DebugHeader
, sizeof (DEBUG_PACKET_HEADER
));
1637 // Compress and send out the packet data.
1639 CompressDataThenSend (
1640 (UINT8
*) (DebugHeader
+ 1),
1649 // Calculate and fill the checksum, DebugHeader->Crc should be 0 before invoking CalculateCrc16 ()
1651 DebugHeader
->Crc
= CalculateCrc16 ((UINT8
*) DebugHeader
, DebugHeader
->Length
, 0);
1653 DebugAgentDataMsgPrint (DEBUG_AGENT_VERBOSE
, TRUE
, (UINT8
*) DebugHeader
, DebugHeader
->Length
);
1655 DebugPortWriteBuffer (Handle
, (UINT8
*) DebugHeader
, DebugHeader
->Length
);
1659 Status
= ReceivePacket ((UINT8
*) DebugHeader
, NULL
, NULL
, READ_PACKET_TIMEOUT
, FALSE
);
1660 if (Status
== RETURN_TIMEOUT
) {
1661 DebugAgentMsgPrint (DEBUG_AGENT_WARNING
, "TARGET: Timeout in SendDataResponsePacket()\n");
1664 if ((DebugHeader
->Command
== DEBUG_COMMAND_OK
) && (DebugHeader
->SequenceNo
== SequenceNo
) && LastPacket
) {
1666 // If this is the last packet, return RETURN_SUCCESS.
1668 return RETURN_SUCCESS
;
1670 if ((DebugHeader
->Command
== DEBUG_COMMAND_CONTINUE
) && (DebugHeader
->SequenceNo
== (UINT8
) (SequenceNo
+ 1))) {
1672 // Calculate the rest data size
1674 Data
+= CurrentDataSize
;
1675 RemainingDataSize
-= CurrentDataSize
;
1676 UpdateMailboxContent (GetMailboxPointer(), DEBUG_MAILBOX_HOST_SEQUENCE_NO_INDEX
, DebugHeader
->SequenceNo
);
1679 if (DebugHeader
->SequenceNo
>= SequenceNo
) {
1680 DebugAgentMsgPrint (DEBUG_AGENT_WARNING
, "TARGET: Received one old or new command(SequenceNo is %x, last SequenceNo is %x)\n", SequenceNo
, DebugHeader
->SequenceNo
);
1688 Send packet with response data to HOST.
1690 @param[in] Data Pointer to response data buffer.
1691 @param[in] DataSize Size of response data in byte.
1692 @param[in, out] DebugHeader Pointer to a buffer for creating response packet and receiving ACK packet,
1693 to minimize the stack usage.
1695 @retval RETURN_SUCCESS Response data was sent successfully.
1699 SendDataResponsePacket (
1702 IN OUT DEBUG_PACKET_HEADER
*DebugHeader
1705 return ReadMemoryAndSendResponsePacket (Data
, DataSize
, 1, DebugHeader
);
1709 Try to attach the HOST.
1711 Send init break packet to HOST:
1712 If no acknowlege received in specified Timeout, return RETURN_TIMEOUT.
1713 If received acknowlege, check the revision of HOST.
1714 Set Attach Flag if attach successfully.
1716 @param[in] BreakCause Break cause of this break event.
1717 @param[in] Timeout Time out value to wait for acknowlege from HOST.
1718 The unit is microsecond.
1719 @param[out] BreakReceived If BreakReceived is not NULL,
1720 TRUE is retured if break-in symbol received.
1721 FALSE is retured if break-in symbol not received.
1725 IN UINT8 BreakCause
,
1727 OUT BOOLEAN
*BreakReceived
1730 RETURN_STATUS Status
;
1731 DEBUG_PORT_HANDLE Handle
;
1732 BOOLEAN IncompatibilityFlag
;
1734 IncompatibilityFlag
= FALSE
;
1735 Handle
= GetDebugPortHandle();
1738 // Send init break and wait ack in Timeout
1740 DebugPortWriteBuffer (Handle
, (UINT8
*) mErrorMsgSendInitPacket
, AsciiStrLen (mErrorMsgSendInitPacket
));
1741 if (BreakCause
== DEBUG_DATA_BREAK_CAUSE_SYSTEM_RESET
) {
1742 Status
= SendCommandAndWaitForAckOK (DEBUG_COMMAND_INIT_BREAK
, Timeout
, BreakReceived
, &IncompatibilityFlag
);
1744 Status
= SendCommandAndWaitForAckOK (DEBUG_COMMAND_ATTACH_BREAK
, Timeout
, BreakReceived
, &IncompatibilityFlag
);
1746 if (IncompatibilityFlag
) {
1748 // If the incompatible Debug Packet received, the HOST should be running transfer protocol before DEBUG_AGENT_REVISION.
1749 // It could be UDK Debugger for Windows v1.1/v1.2 or for Linux v0.8/v1.2.
1751 DebugPortWriteBuffer (Handle
, (UINT8
*) mErrorMsgVersionAlert
, AsciiStrLen (mErrorMsgVersionAlert
));
1755 if (RETURN_ERROR (Status
)) {
1756 DebugPortWriteBuffer (Handle
, (UINT8
*) mErrorMsgConnectFail
, AsciiStrLen (mErrorMsgConnectFail
));
1758 DebugPortWriteBuffer (Handle
, (UINT8
*) mErrorMsgConnectOK
, AsciiStrLen (mErrorMsgConnectOK
));
1762 SetHostAttached (TRUE
);
1768 Send Break point packet to HOST.
1770 Only the first breaking processor could sent BREAK_POINT packet.
1772 @param[in] BreakCause Break cause of this break event.
1773 @param[in] ProcessorIndex Processor index value.
1774 @param[out] BreakReceived If BreakReceived is not NULL,
1775 TRUE is retured if break-in symbol received.
1776 FALSE is retured if break-in symbol not received.
1780 SendBreakPacketToHost (
1781 IN UINT8 BreakCause
,
1782 IN UINT32 ProcessorIndex
,
1783 OUT BOOLEAN
*BreakReceived
1786 UINT8 InputCharacter
;
1787 DEBUG_PORT_HANDLE Handle
;
1789 Handle
= GetDebugPortHandle();
1791 if (IsHostAttached ()) {
1792 DebugAgentMsgPrint (DEBUG_AGENT_INFO
, "processor[%x]:Send Break Packet to HOST.\n", ProcessorIndex
);
1793 SendCommandAndWaitForAckOK (DEBUG_COMMAND_BREAK_POINT
, READ_PACKET_TIMEOUT
, BreakReceived
, NULL
);
1795 DebugAgentMsgPrint (DEBUG_AGENT_INFO
, "processor[%x]:Try to attach HOST.\n", ProcessorIndex
);
1797 // If HOST is not attached, try to attach it firstly.
1800 // Poll Attach symbols from HOST and ack OK
1803 DebugAgentReadBuffer (Handle
, &InputCharacter
, 1, 0);
1804 } while (InputCharacter
!= DEBUG_STARTING_SYMBOL_ATTACH
);
1805 SendAckPacket (DEBUG_COMMAND_OK
);
1808 // Try to attach HOST
1810 while (AttachHost (BreakCause
, 0, NULL
) != RETURN_SUCCESS
);
1816 The main function to process communication with HOST.
1818 It received the command packet from HOST, and sent response data packet to HOST.
1820 @param[in] Vector Vector value of exception or interrutp.
1821 @param[in, out] CpuContext Pointer to saved CPU context.
1822 @param[in] BreakReceived TRUE means break-in symbol received.
1823 FALSE means break-in symbol not received.
1827 CommandCommunication (
1829 IN OUT DEBUG_CPU_CONTEXT
*CpuContext
,
1830 IN BOOLEAN BreakReceived
1833 RETURN_STATUS Status
;
1834 UINT8 InputPacketBuffer
[DEBUG_DATA_UPPER_LIMIT
+ sizeof (UINT64
) - 1];
1835 DEBUG_PACKET_HEADER
*DebugHeader
;
1840 DEBUG_DATA_READ_MEMORY
*MemoryRead
;
1841 DEBUG_DATA_WRITE_MEMORY
*MemoryWrite
;
1842 DEBUG_DATA_READ_IO
*IoRead
;
1843 DEBUG_DATA_WRITE_IO
*IoWrite
;
1844 DEBUG_DATA_READ_REGISTER
*RegisterRead
;
1845 DEBUG_DATA_WRITE_REGISTER
*RegisterWrite
;
1846 UINT8
*RegisterBuffer
;
1847 DEBUG_DATA_READ_MSR
*MsrRegisterRead
;
1848 DEBUG_DATA_WRITE_MSR
*MsrRegisterWrite
;
1849 DEBUG_DATA_CPUID
*Cpuid
;
1850 DEBUG_DATA_RESPONSE_BREAK_CAUSE BreakCause
;
1851 DEBUG_DATA_RESPONSE_CPUID CpuidResponse
;
1852 DEBUG_DATA_SEARCH_SIGNATURE
*SearchSignature
;
1853 DEBUG_DATA_RESPONSE_GET_EXCEPTION Exception
;
1854 DEBUG_DATA_RESPONSE_GET_REVISION DebugAgentRevision
;
1855 DEBUG_DATA_SET_VIEWPOINT
*SetViewPoint
;
1856 BOOLEAN HaltDeferred
;
1857 UINT32 ProcessorIndex
;
1858 DEBUG_PORT_HANDLE Handle
;
1859 DEBUG_AGENT_EXCEPTION_BUFFER AgentExceptionBuffer
;
1860 UINT32 IssuedViewPoint
;
1861 DEBUG_AGENT_MAILBOX
*Mailbox
;
1862 UINT8
*AlignedDataPtr
;
1865 IssuedViewPoint
= 0;
1866 HaltDeferred
= BreakReceived
;
1868 if (MultiProcessorDebugSupport()) {
1869 ProcessorIndex
= GetProcessorIndex ();
1870 SetCpuStopFlagByIndex (ProcessorIndex
, TRUE
);
1871 if (mDebugMpContext
.ViewPointIndex
== ProcessorIndex
) {
1873 // Only the current view processor could set AgentInProgress Flag.
1875 IssuedViewPoint
= ProcessorIndex
;
1879 if (IssuedViewPoint
== ProcessorIndex
) {
1881 // Set AgentInProgress Flag.
1883 SetDebugFlag (DEBUG_AGENT_FLAG_AGENT_IN_PROGRESS
, 1);
1886 Handle
= GetDebugPortHandle();
1890 if (MultiProcessorDebugSupport()) {
1892 // Check if the current processor is HOST view point
1894 if (mDebugMpContext
.ViewPointIndex
!= ProcessorIndex
) {
1895 if (mDebugMpContext
.RunCommandSet
) {
1897 // If HOST view point sets RUN flag, run GO command to leave
1899 SetCpuStopFlagByIndex (ProcessorIndex
, FALSE
);
1900 CommandGo (CpuContext
);
1904 // Run into loop again
1912 AcquireMpSpinLock (&mDebugMpContext
.DebugPortSpinLock
);
1914 DebugHeader
=(DEBUG_PACKET_HEADER
*) InputPacketBuffer
;
1916 DebugAgentMsgPrint (DEBUG_AGENT_INFO
, "TARGET: Try to get command from HOST...\n");
1917 Status
= ReceivePacket ((UINT8
*) DebugHeader
, &BreakReceived
, NULL
, READ_PACKET_TIMEOUT
, TRUE
);
1918 if (Status
!= RETURN_SUCCESS
|| !IS_REQUEST (DebugHeader
)) {
1919 DebugAgentMsgPrint (DEBUG_AGENT_WARNING
, "TARGET: Get command[%x] sequenceno[%x] returned status is [%x] \n", DebugHeader
->Command
, DebugHeader
->SequenceNo
, Status
);
1920 DebugAgentMsgPrint (DEBUG_AGENT_WARNING
, "TARGET: Get command failed or it's response packet not expected! \n");
1921 ReleaseMpSpinLock (&mDebugMpContext
.DebugPortSpinLock
);
1925 Mailbox
= GetMailboxPointer ();
1926 if (DebugHeader
->SequenceNo
== Mailbox
->HostSequenceNo
) {
1927 DebugAgentMsgPrint (DEBUG_AGENT_WARNING
, "TARGET: Receive one old command[%x] agaist command[%x]\n", DebugHeader
->SequenceNo
, Mailbox
->HostSequenceNo
);
1928 SendAckPacket (Mailbox
->LastAck
);
1929 ReleaseMpSpinLock (&mDebugMpContext
.DebugPortSpinLock
);
1931 } else if (DebugHeader
->SequenceNo
== (UINT8
) (Mailbox
->HostSequenceNo
+ 1)) {
1932 UpdateMailboxContent (Mailbox
, DEBUG_MAILBOX_HOST_SEQUENCE_NO_INDEX
, (UINT8
) DebugHeader
->SequenceNo
);
1934 DebugAgentMsgPrint (DEBUG_AGENT_WARNING
, "Receive one invalid comamnd[%x] agaist command[%x]\n", DebugHeader
->SequenceNo
, Mailbox
->HostSequenceNo
);
1935 ReleaseMpSpinLock (&mDebugMpContext
.DebugPortSpinLock
);
1940 // Save CPU content before executing HOST commond
1942 UpdateMailboxContent (Mailbox
, DEBUG_MAILBOX_EXCEPTION_BUFFER_POINTER_INDEX
, (UINT64
)(UINTN
) &AgentExceptionBuffer
.JumpBuffer
);
1943 if (SetJump (&AgentExceptionBuffer
.JumpBuffer
) != 0) {
1945 // If HOST command failed, continue to wait for HOST's next command
1946 // If needed, agent could send exception info to HOST.
1948 SendAckPacket (DEBUG_COMMAND_ABORT
);
1949 ReleaseMpSpinLock (&mDebugMpContext
.DebugPortSpinLock
);
1953 DebugAgentMsgPrint (DEBUG_AGENT_INFO
, "Processor[%x]:Received one command(%x)\n", mDebugMpContext
.ViewPointIndex
, DebugHeader
->Command
);
1955 switch (DebugHeader
->Command
) {
1957 case DEBUG_COMMAND_HALT
:
1958 SendAckPacket (DEBUG_COMMAND_HALT_DEFERRED
);
1959 HaltDeferred
= TRUE
;
1960 BreakReceived
= FALSE
;
1961 Status
= RETURN_SUCCESS
;
1964 case DEBUG_COMMAND_RESET
:
1965 SendAckPacket (DEBUG_COMMAND_OK
);
1966 SendAckPacket (DEBUG_COMMAND_OK
);
1967 SendAckPacket (DEBUG_COMMAND_OK
);
1968 ReleaseMpSpinLock (&mDebugMpContext
.DebugPortSpinLock
);
1972 // Assume system resets in 2 seconds, otherwise send TIMEOUT packet.
1973 // PCD can be used if 2 seconds isn't long enough for some platforms.
1975 MicroSecondDelay (2000000);
1976 UpdateMailboxContent (Mailbox
, DEBUG_MAILBOX_HOST_SEQUENCE_NO_INDEX
, Mailbox
->HostSequenceNo
+ 1);
1977 SendAckPacket (DEBUG_COMMAND_TIMEOUT
);
1978 SendAckPacket (DEBUG_COMMAND_TIMEOUT
);
1979 SendAckPacket (DEBUG_COMMAND_TIMEOUT
);
1982 case DEBUG_COMMAND_GO
:
1983 CommandGo (CpuContext
);
1985 // Clear Dr0 to avoid to be recognized as IMAGE_LOAD/_UNLOAD again when hitting a breakpoint after GO
1986 // If HOST changed Dr0 before GO, we will not change Dr0 here
1988 Data8
= GetBreakCause (Vector
, CpuContext
);
1989 if (Data8
== DEBUG_DATA_BREAK_CAUSE_IMAGE_LOAD
|| Data8
== DEBUG_DATA_BREAK_CAUSE_IMAGE_UNLOAD
) {
1990 CpuContext
->Dr0
= 0;
1993 if (!HaltDeferred
) {
1995 // If no HALT command received when being in-active mode
1997 if (MultiProcessorDebugSupport()) {
1998 Data32
= FindNextPendingBreakCpu ();
2001 // If there are still others processors being in break state,
2002 // send OK packet to HOST to finish this go command
2004 SendAckPacket (DEBUG_COMMAND_OK
);
2007 // Set current view to the next breaking processor
2009 mDebugMpContext
.ViewPointIndex
= Data32
;
2010 mDebugMpContext
.BreakAtCpuIndex
= mDebugMpContext
.ViewPointIndex
;
2011 SetCpuBreakFlagByIndex (mDebugMpContext
.ViewPointIndex
, FALSE
);
2013 // Send break packet to HOST to let HOST break again
2015 SendBreakPacketToHost (DEBUG_DATA_BREAK_CAUSE_UNKNOWN
, mDebugMpContext
.BreakAtCpuIndex
, &BreakReceived
);
2017 // Continue to run into loop to read command packet from HOST
2019 ReleaseMpSpinLock (&mDebugMpContext
.DebugPortSpinLock
);
2024 // If no else processor break, set stop bitmask,
2025 // and set Running flag for all processors.
2027 SetCpuStopFlagByIndex (ProcessorIndex
, FALSE
);
2028 SetCpuRunningFlag (TRUE
);
2031 // Wait for all processors are in running state
2034 if (IsAllCpuRunning ()) {
2039 // Set BSP to be current view point.
2041 SetDebugViewPoint (mDebugMpContext
.BspIndex
);
2044 // Clear breaking processor index and running flag
2046 mDebugMpContext
.BreakAtCpuIndex
= (UINT32
) (-1);
2047 SetCpuRunningFlag (FALSE
);
2051 // Send OK packet to HOST to finish this go command
2053 SendAckPacket (DEBUG_COMMAND_OK
);
2055 ReleaseMpSpinLock (&mDebugMpContext
.DebugPortSpinLock
);
2057 if (!IsHostAttached()) {
2058 UpdateMailboxContent (Mailbox
, DEBUG_MAILBOX_SEQUENCE_NO_INDEX
, 0);
2059 UpdateMailboxContent (Mailbox
, DEBUG_MAILBOX_HOST_SEQUENCE_NO_INDEX
, 0);
2065 // If reveived HALT command, need to defer the GO command
2067 SendAckPacket (DEBUG_COMMAND_HALT_PROCESSED
);
2068 HaltDeferred
= FALSE
;
2070 Vector
= DEBUG_TIMER_VECTOR
;
2074 case DEBUG_COMMAND_BREAK_CAUSE
:
2075 BreakCause
.StopAddress
= CpuContext
->Eip
;
2076 if (MultiProcessorDebugSupport() && ProcessorIndex
!= mDebugMpContext
.BreakAtCpuIndex
) {
2077 BreakCause
.Cause
= GetBreakCause (DEBUG_TIMER_VECTOR
, CpuContext
);
2079 BreakCause
.Cause
= GetBreakCause (Vector
, CpuContext
);
2081 SendDataResponsePacket ((UINT8
*) &BreakCause
, (UINT16
) sizeof (DEBUG_DATA_RESPONSE_BREAK_CAUSE
), DebugHeader
);
2084 case DEBUG_COMMAND_SET_HW_BREAKPOINT
:
2085 SetDebugRegister (CpuContext
, (DEBUG_DATA_SET_HW_BREAKPOINT
*) (DebugHeader
+ 1));
2086 SendAckPacket (DEBUG_COMMAND_OK
);
2089 case DEBUG_COMMAND_CLEAR_HW_BREAKPOINT
:
2090 ClearDebugRegister (CpuContext
, (DEBUG_DATA_CLEAR_HW_BREAKPOINT
*) (DebugHeader
+ 1));
2091 SendAckPacket (DEBUG_COMMAND_OK
);
2094 case DEBUG_COMMAND_SINGLE_STEPPING
:
2095 CommandStepping (CpuContext
);
2097 // Clear Dr0 to avoid to be recognized as IMAGE_LOAD/_UNLOAD again when hitting a breakpoint after GO
2098 // If HOST changed Dr0 before GO, we will not change Dr0 here
2100 Data8
= GetBreakCause (Vector
, CpuContext
);
2101 if (Data8
== DEBUG_DATA_BREAK_CAUSE_IMAGE_LOAD
|| Data8
== DEBUG_DATA_BREAK_CAUSE_IMAGE_UNLOAD
) {
2102 CpuContext
->Dr0
= 0;
2105 mDebugMpContext
.BreakAtCpuIndex
= (UINT32
) (-1);
2106 ReleaseMpSpinLock (&mDebugMpContext
.DebugPortSpinLock
);
2108 // Executing stepping command directly without sending ACK packet,
2109 // ACK packet will be sent after stepping done.
2113 case DEBUG_COMMAND_SET_SW_BREAKPOINT
:
2114 Data64
= (UINTN
) (((DEBUG_DATA_SET_SW_BREAKPOINT
*) (DebugHeader
+ 1))->Address
);
2115 Data8
= *(UINT8
*) (UINTN
) Data64
;
2116 *(UINT8
*) (UINTN
) Data64
= DEBUG_SW_BREAKPOINT_SYMBOL
;
2117 Status
= SendDataResponsePacket ((UINT8
*) &Data8
, (UINT16
) sizeof (UINT8
), DebugHeader
);
2120 case DEBUG_COMMAND_READ_MEMORY
:
2121 MemoryRead
= (DEBUG_DATA_READ_MEMORY
*) (DebugHeader
+ 1);
2122 Status
= ReadMemoryAndSendResponsePacket ((UINT8
*) (UINTN
) MemoryRead
->Address
, MemoryRead
->Count
, MemoryRead
->Width
, DebugHeader
);
2125 case DEBUG_COMMAND_WRITE_MEMORY
:
2126 MemoryWrite
= (DEBUG_DATA_WRITE_MEMORY
*) (DebugHeader
+ 1);
2128 // Copy data into one memory with 8-byte alignment address
2130 AlignedDataPtr
= ALIGN_POINTER ((UINT8
*) &MemoryWrite
->Data
, sizeof (UINT64
));
2131 if (AlignedDataPtr
!= (UINT8
*) &MemoryWrite
->Data
) {
2132 CopyMem (AlignedDataPtr
, (UINT8
*) &MemoryWrite
->Data
, MemoryWrite
->Count
* MemoryWrite
->Width
);
2134 CopyMemByWidth ((UINT8
*) (UINTN
) MemoryWrite
->Address
, AlignedDataPtr
, MemoryWrite
->Count
, MemoryWrite
->Width
);
2135 SendAckPacket (DEBUG_COMMAND_OK
);
2138 case DEBUG_COMMAND_READ_IO
:
2139 IoRead
= (DEBUG_DATA_READ_IO
*) (DebugHeader
+ 1);
2140 switch (IoRead
->Width
) {
2142 Data64
= IoRead8 ((UINTN
) IoRead
->Port
);
2145 Data64
= IoRead16 ((UINTN
) IoRead
->Port
);
2148 Data64
= IoRead32 ((UINTN
) IoRead
->Port
);
2151 Data64
= IoRead64 ((UINTN
) IoRead
->Port
);
2154 Data64
= (UINT64
) -1;
2156 Status
= SendDataResponsePacket ((UINT8
*) &Data64
, IoRead
->Width
, DebugHeader
);
2159 case DEBUG_COMMAND_WRITE_IO
:
2160 IoWrite
= (DEBUG_DATA_WRITE_IO
*) (DebugHeader
+ 1);
2161 switch (IoWrite
->Width
) {
2163 Data64
= IoWrite8 ((UINTN
) IoWrite
->Port
, *(UINT8
*) &IoWrite
->Data
);
2166 Data64
= IoWrite16 ((UINTN
) IoWrite
->Port
, *(UINT16
*) &IoWrite
->Data
);
2169 Data64
= IoWrite32 ((UINTN
) IoWrite
->Port
, *(UINT32
*) &IoWrite
->Data
);
2172 Data64
= IoWrite64 ((UINTN
) IoWrite
->Port
, *(UINT64
*) &IoWrite
->Data
);
2175 Data64
= (UINT64
) -1;
2177 SendAckPacket (DEBUG_COMMAND_OK
);
2180 case DEBUG_COMMAND_READ_ALL_REGISTERS
:
2181 Status
= SendDataResponsePacket ((UINT8
*) CpuContext
, sizeof (*CpuContext
), DebugHeader
);
2184 case DEBUG_COMMAND_READ_REGISTER
:
2185 RegisterRead
= (DEBUG_DATA_READ_REGISTER
*) (DebugHeader
+ 1);
2187 if (RegisterRead
->Index
<= SOFT_DEBUGGER_REGISTER_MAX
) {
2188 RegisterBuffer
= ArchReadRegisterBuffer (CpuContext
, RegisterRead
->Index
, &Width
);
2189 Status
= SendDataResponsePacket (RegisterBuffer
, Width
, DebugHeader
);
2191 Status
= RETURN_UNSUPPORTED
;
2195 case DEBUG_COMMAND_WRITE_REGISTER
:
2196 RegisterWrite
= (DEBUG_DATA_WRITE_REGISTER
*) (DebugHeader
+ 1);
2197 if (RegisterWrite
->Index
<= SOFT_DEBUGGER_REGISTER_MAX
) {
2198 RegisterBuffer
= ArchReadRegisterBuffer (CpuContext
, RegisterWrite
->Index
, &Width
);
2199 ASSERT (Width
== RegisterWrite
->Length
);
2200 CopyMem (RegisterBuffer
, RegisterWrite
->Data
, Width
);
2201 SendAckPacket (DEBUG_COMMAND_OK
);
2203 Status
= RETURN_UNSUPPORTED
;
2207 case DEBUG_COMMAND_ARCH_MODE
:
2208 Data8
= DEBUG_ARCH_SYMBOL
;
2209 Status
= SendDataResponsePacket ((UINT8
*) &Data8
, (UINT16
) sizeof (UINT8
), DebugHeader
);
2212 case DEBUG_COMMAND_READ_MSR
:
2213 MsrRegisterRead
= (DEBUG_DATA_READ_MSR
*) (DebugHeader
+ 1);
2214 Data64
= AsmReadMsr64 (MsrRegisterRead
->Index
);
2215 Status
= SendDataResponsePacket ((UINT8
*) &Data64
, (UINT16
) sizeof (UINT64
), DebugHeader
);
2218 case DEBUG_COMMAND_WRITE_MSR
:
2219 MsrRegisterWrite
= (DEBUG_DATA_WRITE_MSR
*) (DebugHeader
+ 1);
2220 AsmWriteMsr64 (MsrRegisterWrite
->Index
, MsrRegisterWrite
->Value
);
2221 SendAckPacket (DEBUG_COMMAND_OK
);
2224 case DEBUG_COMMAND_SET_DEBUG_SETTING
:
2225 Status
= SetDebugSetting ((DEBUG_DATA_SET_DEBUG_SETTING
*)(DebugHeader
+ 1));
2226 if (Status
== RETURN_SUCCESS
) {
2227 SendAckPacket (DEBUG_COMMAND_OK
);
2231 case DEBUG_COMMAND_GET_REVISION
:
2232 DebugAgentRevision
.Revision
= DEBUG_AGENT_REVISION
;
2233 DebugAgentRevision
.Capabilities
= DEBUG_AGENT_CAPABILITIES
;
2234 Status
= SendDataResponsePacket ((UINT8
*) &DebugAgentRevision
, (UINT16
) sizeof (DEBUG_DATA_RESPONSE_GET_REVISION
), DebugHeader
);
2237 case DEBUG_COMMAND_GET_EXCEPTION
:
2238 Exception
.ExceptionNum
= (UINT8
) Vector
;
2239 Exception
.ExceptionData
= (UINT32
) CpuContext
->ExceptionData
;
2240 Status
= SendDataResponsePacket ((UINT8
*) &Exception
, (UINT16
) sizeof (DEBUG_DATA_RESPONSE_GET_EXCEPTION
), DebugHeader
);
2243 case DEBUG_COMMAND_SET_VIEWPOINT
:
2244 SetViewPoint
= (DEBUG_DATA_SET_VIEWPOINT
*) (DebugHeader
+ 1);
2245 if (MultiProcessorDebugSupport()) {
2246 if (IsCpuStopped (SetViewPoint
->ViewPoint
)) {
2247 SetDebugViewPoint (SetViewPoint
->ViewPoint
);
2248 SendAckPacket (DEBUG_COMMAND_OK
);
2251 // If CPU is not halted
2253 SendAckPacket (DEBUG_COMMAND_NOT_SUPPORTED
);
2255 } else if (SetViewPoint
->ViewPoint
== 0) {
2256 SendAckPacket (DEBUG_COMMAND_OK
);
2259 SendAckPacket (DEBUG_COMMAND_NOT_SUPPORTED
);
2264 case DEBUG_COMMAND_GET_VIEWPOINT
:
2265 Data32
= mDebugMpContext
.ViewPointIndex
;
2266 SendDataResponsePacket((UINT8
*) &Data32
, (UINT16
) sizeof (UINT32
), DebugHeader
);
2269 case DEBUG_COMMAND_MEMORY_READY
:
2270 Data8
= (UINT8
) GetDebugFlag (DEBUG_AGENT_FLAG_MEMORY_READY
);
2271 SendDataResponsePacket (&Data8
, (UINT16
) sizeof (UINT8
), DebugHeader
);
2274 case DEBUG_COMMAND_DETACH
:
2275 SetHostAttached (FALSE
);
2276 SendAckPacket (DEBUG_COMMAND_OK
);
2279 case DEBUG_COMMAND_CPUID
:
2280 Cpuid
= (DEBUG_DATA_CPUID
*) (DebugHeader
+ 1);
2282 Cpuid
->Eax
, Cpuid
->Ecx
,
2283 &CpuidResponse
.Eax
, &CpuidResponse
.Ebx
,
2284 &CpuidResponse
.Ecx
, &CpuidResponse
.Edx
2286 SendDataResponsePacket ((UINT8
*) &CpuidResponse
, (UINT16
) sizeof (CpuidResponse
), DebugHeader
);
2289 case DEBUG_COMMAND_SEARCH_SIGNATURE
:
2290 SearchSignature
= (DEBUG_DATA_SEARCH_SIGNATURE
*) (DebugHeader
+ 1);
2291 if ((SearchSignature
->Alignment
!= 0) &&
2292 (SearchSignature
->Alignment
== GetPowerOfTwo32 (SearchSignature
->Alignment
))
2294 if (SearchSignature
->Positive
) {
2296 Data64
= ALIGN_VALUE ((UINTN
) SearchSignature
->Start
, SearchSignature
->Alignment
);
2297 Data64
<= SearchSignature
->Start
+ SearchSignature
->Count
- SearchSignature
->DataLength
;
2298 Data64
+= SearchSignature
->Alignment
2300 if (CompareMem ((VOID
*) (UINTN
) Data64
, &SearchSignature
->Data
, SearchSignature
->DataLength
) == 0) {
2304 if (Data64
> SearchSignature
->Start
+ SearchSignature
->Count
- SearchSignature
->DataLength
) {
2305 Data64
= (UINT64
) -1;
2309 Data64
= ALIGN_VALUE ((UINTN
) SearchSignature
->Start
- SearchSignature
->Alignment
, SearchSignature
->Alignment
);
2310 Data64
>= SearchSignature
->Start
- SearchSignature
->Count
;
2311 Data64
-= SearchSignature
->Alignment
2313 if (CompareMem ((VOID
*) (UINTN
) Data64
, &SearchSignature
->Data
, SearchSignature
->DataLength
) == 0) {
2317 if (Data64
< SearchSignature
->Start
- SearchSignature
->Count
) {
2318 Data64
= (UINT64
) -1;
2321 SendDataResponsePacket ((UINT8
*) &Data64
, (UINT16
) sizeof (Data64
), DebugHeader
);
2323 Status
= RETURN_UNSUPPORTED
;
2328 SendAckPacket (DEBUG_COMMAND_NOT_SUPPORTED
);
2332 if (Status
== RETURN_UNSUPPORTED
) {
2333 SendAckPacket (DEBUG_COMMAND_NOT_SUPPORTED
);
2334 } else if (Status
!= RETURN_SUCCESS
) {
2335 SendAckPacket (DEBUG_COMMAND_ABORT
);
2338 ReleaseMpSpinLock (&mDebugMpContext
.DebugPortSpinLock
);
2344 C function called in interrupt handler.
2346 @param[in] Vector Vector value of exception or interrutp.
2347 @param[in] CpuContext Pointer to save CPU context.
2354 IN DEBUG_CPU_CONTEXT
*CpuContext
2357 UINT8 InputCharacter
;
2360 BOOLEAN BreakReceived
;
2361 UINT32 ProcessorIndex
;
2362 UINT32 CurrentDebugTimerInitCount
;
2363 DEBUG_PORT_HANDLE Handle
;
2366 UINT32 IssuedViewPoint
;
2367 DEBUG_AGENT_EXCEPTION_BUFFER
*ExceptionBuffer
;
2371 IssuedViewPoint
= 0;
2372 BreakReceived
= FALSE
;
2374 if (mSkipBreakpoint
) {
2376 // If Skip Breakpoint flag is set, means communication is disturbed by hardware SMI, we need to ignore the break points in SMM
2378 if ((Vector
== DEBUG_INT1_VECTOR
) || (Vector
== DEBUG_INT3_VECTOR
)) {
2379 DebugPortWriteBuffer (GetDebugPortHandle(), (UINT8
*) mWarningMsgIngoreBreakpoint
, AsciiStrLen (mWarningMsgIngoreBreakpoint
));
2384 if (MultiProcessorDebugSupport()) {
2385 ProcessorIndex
= GetProcessorIndex ();
2387 // If this processor has alreay halted before, need to check it later
2389 if (IsCpuStopped (ProcessorIndex
)) {
2390 IssuedViewPoint
= ProcessorIndex
;
2394 if (IssuedViewPoint
== ProcessorIndex
&& GetDebugFlag (DEBUG_AGENT_FLAG_STEPPING
) != 1) {
2396 // Check if this exception is issued by Debug Agent itself
2397 // If yes, fill the debug agent exception buffer and LongJump() back to
2398 // the saved CPU content in CommandCommunication()
2399 // If exception is issued when executing Stepping, will be handled in
2400 // exception handle procedure.
2402 if (GetDebugFlag (DEBUG_AGENT_FLAG_AGENT_IN_PROGRESS
) == 1) {
2403 DebugAgentMsgPrint (
2405 "Debug agent meet one Exception, ExceptionNum is %d, EIP = 0x%x.\n",
2407 (UINTN
)CpuContext
->Eip
2409 ExceptionBuffer
= (DEBUG_AGENT_EXCEPTION_BUFFER
*) (UINTN
) GetMailboxPointer()->ExceptionBufferPointer
;
2410 ExceptionBuffer
->ExceptionContent
.ExceptionNum
= (UINT8
) Vector
;
2411 ExceptionBuffer
->ExceptionContent
.ExceptionData
= (UINT32
) CpuContext
->ExceptionData
;
2412 LongJump ((BASE_LIBRARY_JUMP_BUFFER
*)(UINTN
)(ExceptionBuffer
), 1);
2416 if (MultiProcessorDebugSupport()) {
2418 // If RUN commmand is executing, wait for it done.
2420 while (mDebugMpContext
.RunCommandSet
) {
2425 Handle
= GetDebugPortHandle();
2426 BreakCause
= GetBreakCause (Vector
, CpuContext
);
2428 case DEBUG_INT1_VECTOR
:
2429 case DEBUG_INT3_VECTOR
:
2430 switch (BreakCause
) {
2431 case DEBUG_DATA_BREAK_CAUSE_SYSTEM_RESET
:
2432 if (AttachHost (BreakCause
, READ_PACKET_TIMEOUT
, &BreakReceived
) != RETURN_SUCCESS
) {
2434 // Try to connect HOST, return if fails
2438 CommandCommunication (Vector
, CpuContext
, BreakReceived
);
2441 case DEBUG_DATA_BREAK_CAUSE_STEPPING
:
2443 // Stepping is finished, send Ack package.
2445 if (MultiProcessorDebugSupport()) {
2446 mDebugMpContext
.BreakAtCpuIndex
= ProcessorIndex
;
2449 // Clear Stepping Flag and restore EFLAGS.IF
2451 CommandSteppingCleanup (CpuContext
);
2452 SendAckPacket (DEBUG_COMMAND_OK
);
2453 CommandCommunication (Vector
, CpuContext
, BreakReceived
);
2456 case DEBUG_DATA_BREAK_CAUSE_MEMORY_READY
:
2460 SendCommandAndWaitForAckOK (DEBUG_COMMAND_MEMORY_READY
, READ_PACKET_TIMEOUT
, &BreakReceived
, NULL
);
2461 CommandCommunication (Vector
, CpuContext
, BreakReceived
);
2464 case DEBUG_DATA_BREAK_CAUSE_IMAGE_LOAD
:
2465 case DEBUG_DATA_BREAK_CAUSE_IMAGE_UNLOAD
:
2467 // Set AL to DEBUG_AGENT_IMAGE_CONTINUE
2469 Al
= ArchReadRegisterBuffer (CpuContext
, SOFT_DEBUGGER_REGISTER_AX
, &Data8
);
2470 *Al
= DEBUG_AGENT_IMAGE_CONTINUE
;
2472 if (!IsHostAttached ()) {
2474 // If HOST is not connected for image load/unload, return
2479 // Continue to run the following common code
2482 case DEBUG_DATA_BREAK_CAUSE_HW_BREAKPOINT
:
2483 case DEBUG_DATA_BREAK_CAUSE_SW_BREAKPOINT
:
2486 // Send Break packet to HOST
2488 AcquireMpSpinLock (&mDebugMpContext
.DebugPortSpinLock
);
2490 // Only the first breaking processor could send BREAK_POINT to HOST
2492 if (IsFirstBreakProcessor (ProcessorIndex
)) {
2493 SendBreakPacketToHost (BreakCause
, ProcessorIndex
, &BreakReceived
);
2495 ReleaseMpSpinLock (&mDebugMpContext
.DebugPortSpinLock
);
2497 if (Vector
== DEBUG_INT3_VECTOR
) {
2499 // go back address located "0xCC"
2502 SavedEip
= CpuContext
->Eip
;
2503 CommandCommunication (Vector
, CpuContext
, BreakReceived
);
2504 if ((SavedEip
== CpuContext
->Eip
) &&
2505 (*(UINT8
*) (UINTN
) CpuContext
->Eip
== DEBUG_SW_BREAKPOINT_SYMBOL
)) {
2507 // If this is not a software breakpoint set by HOST,
2513 CommandCommunication (Vector
, CpuContext
, BreakReceived
);
2520 case DEBUG_TIMER_VECTOR
:
2522 AcquireMpSpinLock (&mDebugMpContext
.DebugPortSpinLock
);
2524 if (MultiProcessorDebugSupport()) {
2525 if (IsBsp (ProcessorIndex
)) {
2527 // If current processor is BSP, check Apic timer's init count if changed,
2528 // it may be re-written when switching BSP.
2529 // If it changed, re-initialize debug timer
2531 CurrentDebugTimerInitCount
= GetApicTimerInitCount ();
2532 if (mDebugMpContext
.DebugTimerInitCount
!= CurrentDebugTimerInitCount
) {
2533 InitializeDebugTimer (NULL
);
2537 if (!IsBsp (ProcessorIndex
) || mDebugMpContext
.IpiSentByAp
) {
2538 ReleaseMpSpinLock (&mDebugMpContext
.DebugPortSpinLock
);
2540 // If current processor is not BSP or this is one IPI sent by AP
2542 if (mDebugMpContext
.BreakAtCpuIndex
!= (UINT32
) (-1)) {
2543 CommandCommunication (Vector
, CpuContext
, FALSE
);
2547 // Clear EOI before exiting interrupt process routine.
2555 // Only BSP could run here
2559 // If there is data in debug port, will check whether it is break(attach/break-in) symbol,
2560 // If yes, go into communication mode with HOST.
2561 // If no, exit interrupt process.
2563 if (DebugReadBreakSymbol (Handle
, &InputCharacter
) == EFI_NOT_FOUND
) {
2567 if ((!IsHostAttached () && (InputCharacter
== DEBUG_STARTING_SYMBOL_ATTACH
)) ||
2568 (IsHostAttached () && (InputCharacter
== DEBUG_COMMAND_HALT
)) ||
2569 (IsHostAttached () && (InputCharacter
== DEBUG_COMMAND_GO
))
2571 DebugAgentMsgPrint (DEBUG_AGENT_VERBOSE
, "Received data [%02x]\n", InputCharacter
);
2573 // Ack OK for break-in symbol
2575 SendAckPacket (DEBUG_COMMAND_OK
);
2578 // If receive GO command in Debug Timer, means HOST may lost ACK packet before.
2580 if (InputCharacter
== DEBUG_COMMAND_GO
) {
2584 if (!IsHostAttached ()) {
2586 // Try to attach HOST, if no ack received after 200ms, return
2588 if (AttachHost (BreakCause
, READ_PACKET_TIMEOUT
, &BreakReceived
) != RETURN_SUCCESS
) {
2593 if (MultiProcessorDebugSupport()) {
2594 if(FindNextPendingBreakCpu () != -1) {
2595 SetCpuBreakFlagByIndex (ProcessorIndex
, TRUE
);
2597 HaltOtherProcessors (ProcessorIndex
);
2600 ReleaseMpSpinLock (&mDebugMpContext
.DebugPortSpinLock
);
2601 CommandCommunication (Vector
, CpuContext
, BreakReceived
);
2602 AcquireMpSpinLock (&mDebugMpContext
.DebugPortSpinLock
);
2608 // Clear EOI before exiting interrupt process routine.
2612 ReleaseMpSpinLock (&mDebugMpContext
.DebugPortSpinLock
);
2617 if (Vector
<= DEBUG_EXCEPT_SIMD
) {
2618 DebugAgentMsgPrint (
2620 "Exception happened, ExceptionNum is %d, EIP = 0x%x.\n",
2622 (UINTN
) CpuContext
->Eip
2624 if (BreakCause
== DEBUG_DATA_BREAK_CAUSE_STEPPING
) {
2626 // If exception happened when executing Stepping, send Ack package.
2627 // HOST consider Stepping command was finished.
2629 if (MultiProcessorDebugSupport()) {
2630 mDebugMpContext
.BreakAtCpuIndex
= ProcessorIndex
;
2633 // Clear Stepping flag and restore EFLAGS.IF
2635 CommandSteppingCleanup (CpuContext
);
2636 SendAckPacket (DEBUG_COMMAND_OK
);
2639 // Exception occurs, send Break packet to HOST
2641 AcquireMpSpinLock (&mDebugMpContext
.DebugPortSpinLock
);
2643 // Only the first breaking processor could send BREAK_POINT to HOST
2645 if (IsFirstBreakProcessor (ProcessorIndex
)) {
2646 SendBreakPacketToHost (BreakCause
, ProcessorIndex
, &BreakReceived
);
2648 ReleaseMpSpinLock (&mDebugMpContext
.DebugPortSpinLock
);
2651 CommandCommunication (Vector
, CpuContext
, BreakReceived
);
2656 if (MultiProcessorDebugSupport()) {
2658 // Clear flag and wait for all processors run here
2660 SetIpiSentByApFlag (FALSE
);
2661 while (mDebugMpContext
.RunCommandSet
) {
2666 // Only current (view) processor could clean up AgentInProgress flag.
2668 if (mDebugMpContext
.ViewPointIndex
== ProcessorIndex
) {
2669 IssuedViewPoint
= mDebugMpContext
.ViewPointIndex
;
2673 if (IssuedViewPoint
== ProcessorIndex
&& GetDebugFlag (DEBUG_AGENT_FLAG_STEPPING
) != 1) {
2675 // If the command is not stepping, clean up AgentInProgress flag
2677 SetDebugFlag (DEBUG_AGENT_FLAG_AGENT_IN_PROGRESS
, 0);