diff options
Diffstat (limited to 'SourceLevelDebugPkg/Library/DebugAgent/SmmDebugAgent/SmmDebugAgentLib.c')
| -rw-r--r-- | SourceLevelDebugPkg/Library/DebugAgent/SmmDebugAgent/SmmDebugAgentLib.c | 828 |
1 files changed, 414 insertions, 414 deletions
diff --git a/SourceLevelDebugPkg/Library/DebugAgent/SmmDebugAgent/SmmDebugAgentLib.c b/SourceLevelDebugPkg/Library/DebugAgent/SmmDebugAgent/SmmDebugAgentLib.c index cc5bb957f7..1cbba43b20 100644 --- a/SourceLevelDebugPkg/Library/DebugAgent/SmmDebugAgent/SmmDebugAgentLib.c +++ b/SourceLevelDebugPkg/Library/DebugAgent/SmmDebugAgent/SmmDebugAgentLib.c @@ -1,414 +1,414 @@ -/** @file
- Debug Agent library implementation.
-
- Copyright (c) 2010 - 2018, Intel Corporation. All rights reserved.<BR>
- SPDX-License-Identifier: BSD-2-Clause-Patent
-
-**/
-
-#include "SmmDebugAgentLib.h"
-
-DEBUG_AGENT_MAILBOX *mMailboxPointer = NULL;
-DEBUG_AGENT_MAILBOX mLocalMailbox;
-UINTN mSavedDebugRegisters[6];
-IA32_IDT_GATE_DESCRIPTOR mIdtEntryTable[33];
-BOOLEAN mSkipBreakpoint = FALSE;
-BOOLEAN mSmmDebugIdtInitFlag = FALSE;
-BOOLEAN mApicTimerRestore = FALSE;
-BOOLEAN mPeriodicMode;
-UINT32 mTimerCycle;
-UINTN mApicTimerDivisor;
-UINT8 mVector;
-
-CHAR8 mWarningMsgIgnoreSmmEntryBreak[] = "Ignore smmentrybreak setting for SMI issued during DXE debugging!\r\n";
-
-/**
- Check if debug agent support multi-processor.
-
- @retval TRUE Multi-processor is supported.
- @retval FALSE Multi-processor is not supported.
-
-**/
-BOOLEAN
-MultiProcessorDebugSupport (
- VOID
- )
-{
- return FALSE;
-}
-
-/**
- Read the Attach/Break-in symbols from the debug port.
-
- @param[in] Handle Pointer to Debug Port handle.
- @param[out] BreakSymbol Returned break symbol.
-
- @retval EFI_SUCCESS Read the symbol in BreakSymbol.
- @retval EFI_NOT_FOUND No read the break symbol.
-
-**/
-EFI_STATUS
-DebugReadBreakSymbol (
- IN DEBUG_PORT_HANDLE Handle,
- OUT UINT8 *BreakSymbol
- )
-{
- //
- // Smm instance has no debug timer to poll break symbol.
- //
- return EFI_NOT_FOUND;
-}
-
-/**
- Get the pointer to Mailbox from the GUIDed HOB.
-
- @return Pointer to Mailbox.
-
-**/
-DEBUG_AGENT_MAILBOX *
-GetMailboxFromHob (
- VOID
- )
-{
- EFI_HOB_GUID_TYPE *GuidHob;
- UINT64 *MailboxLocation;
- DEBUG_AGENT_MAILBOX *Mailbox;
-
- GuidHob = GetFirstGuidHob (&gEfiDebugAgentGuid);
- if (GuidHob == NULL) {
- return NULL;
- }
-
- MailboxLocation = (UINT64 *)(GET_GUID_HOB_DATA (GuidHob));
- Mailbox = (DEBUG_AGENT_MAILBOX *)(UINTN)(*MailboxLocation);
- VerifyMailboxChecksum (Mailbox);
-
- return Mailbox;
-}
-
-/**
- Get Debug Agent Mailbox pointer.
-
- @return Mailbox pointer.
-
-**/
-DEBUG_AGENT_MAILBOX *
-GetMailboxPointer (
- VOID
- )
-{
- VerifyMailboxChecksum (mMailboxPointer);
- return mMailboxPointer;
-}
-
-/**
- Get debug port handle.
-
- @return Debug port handle.
-
-**/
-DEBUG_PORT_HANDLE
-GetDebugPortHandle (
- VOID
- )
-{
- return (DEBUG_PORT_HANDLE)(UINTN)(GetMailboxPointer ()->DebugPortHandle);
-}
-
-/**
- Store debug register when SMI exit.
-
-**/
-VOID
-SaveDebugRegister (
- VOID
- )
-{
- mSavedDebugRegisters[0] = AsmReadDr0 ();
- mSavedDebugRegisters[1] = AsmReadDr1 ();
- mSavedDebugRegisters[2] = AsmReadDr2 ();
- mSavedDebugRegisters[3] = AsmReadDr3 ();
- mSavedDebugRegisters[4] = AsmReadDr6 ();
- mSavedDebugRegisters[5] = AsmReadDr7 ();
-}
-
-/**
- Restore debug register when SMI exit.
-
-**/
-VOID
-RestoreDebugRegister (
- VOID
- )
-{
- AsmWriteDr7 (0);
- AsmWriteDr0 (mSavedDebugRegisters[0]);
- AsmWriteDr1 (mSavedDebugRegisters[1]);
- AsmWriteDr2 (mSavedDebugRegisters[2]);
- AsmWriteDr3 (mSavedDebugRegisters[3]);
- AsmWriteDr6 (mSavedDebugRegisters[4]);
- AsmWriteDr7 (mSavedDebugRegisters[5]);
-}
-
-/**
- Initialize debug agent.
-
- This function is used to set up debug environment for source level debug
- in SMM code.
-
- If InitFlag is DEBUG_AGENT_INIT_SMM, it will override IDT table entries
- and initialize debug port. It will get debug agent Mailbox from GUIDed HOB,
- it it exists, debug agent wiil copied it into the local Mailbox in SMM space.
- it will override IDT table entries and initialize debug port. Context must
- point to a BOOLEAN if it's not NULL, which indicates SMM Debug Agent supported
- or not.
- If InitFlag is DEBUG_AGENT_INIT_ENTER_SMI, debug agent will save Debug
- Registers and get local Mailbox in SMM space. Context will be NULL.
- If InitFlag is DEBUG_AGENT_INIT_EXIT_SMI, debug agent will restore Debug
- Registers. Context will be NULL.
-
- @param[in] InitFlag Init flag is used to decide initialize process.
- @param[in] Context Context needed according to InitFlag.
- @param[in] Function Continue function called by debug agent library; it was
- optional.
-
-**/
-VOID
-EFIAPI
-InitializeDebugAgent (
- IN UINT32 InitFlag,
- IN VOID *Context OPTIONAL,
- IN DEBUG_AGENT_CONTINUE Function OPTIONAL
- )
-{
- EFI_STATUS Status;
- UINT64 DebugPortHandle;
- IA32_IDT_GATE_DESCRIPTOR IdtEntry[33];
- IA32_DESCRIPTOR IdtDescriptor;
- IA32_DESCRIPTOR *Ia32Idtr;
- IA32_IDT_ENTRY *Ia32IdtEntry;
- IA32_DESCRIPTOR Idtr;
- UINT16 IdtEntryCount;
- DEBUG_AGENT_MAILBOX *Mailbox;
- UINT64 *MailboxLocation;
- UINT32 DebugTimerFrequency;
-
- switch (InitFlag) {
- case DEBUG_AGENT_INIT_SMM:
- //
- // Install configuration table for persisted vector handoff info
- //
- Status = gSmst->SmmInstallConfigurationTable (
- gSmst,
- &gEfiVectorHandoffTableGuid,
- (VOID *)&mVectorHandoffInfoDebugAgent[0],
- sizeof (EFI_VECTOR_HANDOFF_INFO) * mVectorHandoffInfoCount
- );
- if (EFI_ERROR (Status)) {
- DEBUG ((DEBUG_ERROR, "DebugAgent: Cannot install configuration table for persisted vector handoff info!\n"));
- if (Context != NULL) {
- *(BOOLEAN *)Context = FALSE;
- }
-
- CpuDeadLoop ();
- }
-
- //
- // Check if Debug Agent initialized in DXE phase
- //
- Status = EfiGetSystemConfigurationTable (&gEfiDebugAgentGuid, (VOID **)&Mailbox);
- if ((Status == EFI_SUCCESS) && (Mailbox != NULL)) {
- VerifyMailboxChecksum (Mailbox);
- mMailboxPointer = Mailbox;
- if (Context != NULL) {
- *(BOOLEAN *)Context = TRUE;
- }
-
- break;
- }
-
- //
- // Check if Debug Agent initialized in SEC/PEI phase
- //
- Mailbox = GetMailboxFromHob ();
- if (Mailbox != NULL) {
- mMailboxPointer = Mailbox;
- if (Context != NULL) {
- *(BOOLEAN *)Context = TRUE;
- }
-
- break;
- }
-
- //
- // Debug Agent was not initialized before, use the local mailbox.
- //
- ZeroMem (&mLocalMailbox, sizeof (DEBUG_AGENT_MAILBOX));
- Mailbox = &mLocalMailbox;
- //
- // Save original IDT entries
- //
- AsmReadIdtr (&IdtDescriptor);
- CopyMem (&IdtEntry, (VOID *)IdtDescriptor.Base, 33 * sizeof (IA32_IDT_GATE_DESCRIPTOR));
- //
- // Initialized Debug Agent
- //
- InitializeDebugIdt ();
- //
- // Initialize Debug Timer hardware and save its frequency
- //
- InitializeDebugTimer (&DebugTimerFrequency, TRUE);
- UpdateMailboxContent (Mailbox, DEBUG_MAILBOX_DEBUG_TIMER_FREQUENCY, DebugTimerFrequency);
-
- DebugPortHandle = (UINT64)(UINTN)DebugPortInitialize ((DEBUG_PORT_HANDLE)(UINTN)Mailbox->DebugPortHandle, NULL);
- UpdateMailboxContent (Mailbox, DEBUG_MAILBOX_DEBUG_PORT_HANDLE_INDEX, DebugPortHandle);
- mMailboxPointer = Mailbox;
- //
- // Trigger one software interrupt to inform HOST
- //
- TriggerSoftInterrupt (SYSTEM_RESET_SIGNATURE);
-
- SetDebugFlag (DEBUG_AGENT_FLAG_MEMORY_READY, 1);
- //
- // Memory has been ready
- //
- if (IsHostAttached ()) {
- //
- // Trigger one software interrupt to inform HOST
- //
- TriggerSoftInterrupt (MEMORY_READY_SIGNATURE);
- }
-
- //
- // Find and report PE/COFF image info to HOST
- //
- FindAndReportModuleImageInfo (SIZE_4KB);
- //
- // Restore saved IDT entries
- //
- CopyMem ((VOID *)IdtDescriptor.Base, &IdtEntry, 33 * sizeof (IA32_IDT_GATE_DESCRIPTOR));
-
- if (Context != NULL) {
- *(BOOLEAN *)Context = TRUE;
- }
-
- break;
-
- case DEBUG_AGENT_INIT_ENTER_SMI:
- SaveDebugRegister ();
- if (!mSmmDebugIdtInitFlag) {
- //
- // We only need to initialize Debug IDT table at first SMI entry
- // after SMM relocation.
- //
- InitializeDebugIdt ();
- mSmmDebugIdtInitFlag = TRUE;
- }
-
- //
- // Check if CPU APIC Timer is working, otherwise initialize it.
- //
- InitializeLocalApicSoftwareEnable (TRUE);
- GetApicTimerState (&mApicTimerDivisor, &mPeriodicMode, &mVector);
- mTimerCycle = GetApicTimerInitCount ();
- if (!mPeriodicMode || (mTimerCycle == 0)) {
- mApicTimerRestore = TRUE;
- InitializeDebugTimer (NULL, FALSE);
- }
-
- Mailbox = GetMailboxPointer ();
- if (GetDebugFlag (DEBUG_AGENT_FLAG_AGENT_IN_PROGRESS) == 1) {
- //
- // If Debug Agent has been communication state with HOST, we need skip
- // any break points set in SMM, set Skip Breakpoint flag
- //
- mSkipBreakpoint = TRUE;
- }
-
- if (GetDebugFlag (DEBUG_AGENT_FLAG_BREAK_ON_NEXT_SMI) == 1) {
- if (mSkipBreakpoint) {
- //
- // Print warning message if ignore smm entry break
- //
- DebugPortWriteBuffer (
- (DEBUG_PORT_HANDLE)(UINTN)Mailbox->DebugPortHandle,
- (UINT8 *)mWarningMsgIgnoreSmmEntryBreak,
- AsciiStrLen (mWarningMsgIgnoreSmmEntryBreak)
- );
- } else {
- //
- // If SMM entry break is set, SMM code will be break at here.
- //
- CpuBreakpoint ();
- }
- }
-
- break;
-
- case DEBUG_AGENT_INIT_EXIT_SMI:
- Mailbox = GetMailboxPointer ();
- //
- // Clear Skip Breakpoint flag
- //
- mSkipBreakpoint = FALSE;
- RestoreDebugRegister ();
- //
- // Restore APIC Timer
- //
- if (mApicTimerRestore) {
- InitializeApicTimer (mApicTimerDivisor, mTimerCycle, mPeriodicMode, mVector);
- mApicTimerRestore = FALSE;
- }
-
- break;
-
- case DEBUG_AGENT_INIT_THUNK_PEI_IA32TOX64:
- if (Context == NULL) {
- DEBUG ((DEBUG_ERROR, "DebugAgent: Input parameter Context cannot be NULL!\n"));
- CpuDeadLoop ();
- } else {
- Ia32Idtr = (IA32_DESCRIPTOR *)Context;
- Ia32IdtEntry = (IA32_IDT_ENTRY *)(Ia32Idtr->Base);
- MailboxLocation = (UINT64 *)((UINTN)Ia32IdtEntry[DEBUG_MAILBOX_VECTOR].Bits.OffsetLow +
- ((UINTN)Ia32IdtEntry[DEBUG_MAILBOX_VECTOR].Bits.OffsetHigh << 16));
- mMailboxPointer = (DEBUG_AGENT_MAILBOX *)(UINTN)(*MailboxLocation);
- VerifyMailboxChecksum (mMailboxPointer);
- //
- // Get original IDT address and size.
- //
- AsmReadIdtr ((IA32_DESCRIPTOR *)&Idtr);
- IdtEntryCount = (UINT16)((Idtr.Limit + 1) / sizeof (IA32_IDT_GATE_DESCRIPTOR));
- if (IdtEntryCount < 33) {
- Idtr.Limit = (UINT16)(sizeof (IA32_IDT_GATE_DESCRIPTOR) * 33 - 1);
- Idtr.Base = (UINTN)&mIdtEntryTable;
- ZeroMem (&mIdtEntryTable, Idtr.Limit + 1);
- AsmWriteIdtr ((IA32_DESCRIPTOR *)&Idtr);
- }
-
- InitializeDebugIdt ();
- //
- // Initialize Debug Timer hardware and save its frequency
- //
- InitializeDebugTimer (&DebugTimerFrequency, TRUE);
- UpdateMailboxContent (mMailboxPointer, DEBUG_MAILBOX_DEBUG_TIMER_FREQUENCY, DebugTimerFrequency);
- //
- // Enable Debug Timer interrupt and CPU interrupt
- //
- SaveAndSetDebugTimerInterrupt (TRUE);
- EnableInterrupts ();
-
- FindAndReportModuleImageInfo (SIZE_4KB);
- }
-
- break;
-
- default:
- //
- // Only DEBUG_AGENT_INIT_PREMEM_SEC and DEBUG_AGENT_INIT_POSTMEM_SEC are allowed for this
- // Debug Agent library instance.
- //
- DEBUG ((DEBUG_ERROR, "Debug Agent: The InitFlag value is not allowed!\n"));
- CpuDeadLoop ();
- break;
- }
-}
+/** @file + Debug Agent library implementation. + + Copyright (c) 2010 - 2018, Intel Corporation. All rights reserved.<BR> + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "SmmDebugAgentLib.h" + +DEBUG_AGENT_MAILBOX *mMailboxPointer = NULL; +DEBUG_AGENT_MAILBOX mLocalMailbox; +UINTN mSavedDebugRegisters[6]; +IA32_IDT_GATE_DESCRIPTOR mIdtEntryTable[33]; +BOOLEAN mSkipBreakpoint = FALSE; +BOOLEAN mSmmDebugIdtInitFlag = FALSE; +BOOLEAN mApicTimerRestore = FALSE; +BOOLEAN mPeriodicMode; +UINT32 mTimerCycle; +UINTN mApicTimerDivisor; +UINT8 mVector; + +CHAR8 mWarningMsgIgnoreSmmEntryBreak[] = "Ignore smmentrybreak setting for SMI issued during DXE debugging!\r\n"; + +/** + Check if debug agent support multi-processor. + + @retval TRUE Multi-processor is supported. + @retval FALSE Multi-processor is not supported. + +**/ +BOOLEAN +MultiProcessorDebugSupport ( + VOID + ) +{ + return FALSE; +} + +/** + Read the Attach/Break-in symbols from the debug port. + + @param[in] Handle Pointer to Debug Port handle. + @param[out] BreakSymbol Returned break symbol. + + @retval EFI_SUCCESS Read the symbol in BreakSymbol. + @retval EFI_NOT_FOUND No read the break symbol. + +**/ +EFI_STATUS +DebugReadBreakSymbol ( + IN DEBUG_PORT_HANDLE Handle, + OUT UINT8 *BreakSymbol + ) +{ + // + // Smm instance has no debug timer to poll break symbol. + // + return EFI_NOT_FOUND; +} + +/** + Get the pointer to Mailbox from the GUIDed HOB. + + @return Pointer to Mailbox. + +**/ +DEBUG_AGENT_MAILBOX * +GetMailboxFromHob ( + VOID + ) +{ + EFI_HOB_GUID_TYPE *GuidHob; + UINT64 *MailboxLocation; + DEBUG_AGENT_MAILBOX *Mailbox; + + GuidHob = GetFirstGuidHob (&gEfiDebugAgentGuid); + if (GuidHob == NULL) { + return NULL; + } + + MailboxLocation = (UINT64 *)(GET_GUID_HOB_DATA (GuidHob)); + Mailbox = (DEBUG_AGENT_MAILBOX *)(UINTN)(*MailboxLocation); + VerifyMailboxChecksum (Mailbox); + + return Mailbox; +} + +/** + Get Debug Agent Mailbox pointer. + + @return Mailbox pointer. + +**/ +DEBUG_AGENT_MAILBOX * +GetMailboxPointer ( + VOID + ) +{ + VerifyMailboxChecksum (mMailboxPointer); + return mMailboxPointer; +} + +/** + Get debug port handle. + + @return Debug port handle. + +**/ +DEBUG_PORT_HANDLE +GetDebugPortHandle ( + VOID + ) +{ + return (DEBUG_PORT_HANDLE)(UINTN)(GetMailboxPointer ()->DebugPortHandle); +} + +/** + Store debug register when SMI exit. + +**/ +VOID +SaveDebugRegister ( + VOID + ) +{ + mSavedDebugRegisters[0] = AsmReadDr0 (); + mSavedDebugRegisters[1] = AsmReadDr1 (); + mSavedDebugRegisters[2] = AsmReadDr2 (); + mSavedDebugRegisters[3] = AsmReadDr3 (); + mSavedDebugRegisters[4] = AsmReadDr6 (); + mSavedDebugRegisters[5] = AsmReadDr7 (); +} + +/** + Restore debug register when SMI exit. + +**/ +VOID +RestoreDebugRegister ( + VOID + ) +{ + AsmWriteDr7 (0); + AsmWriteDr0 (mSavedDebugRegisters[0]); + AsmWriteDr1 (mSavedDebugRegisters[1]); + AsmWriteDr2 (mSavedDebugRegisters[2]); + AsmWriteDr3 (mSavedDebugRegisters[3]); + AsmWriteDr6 (mSavedDebugRegisters[4]); + AsmWriteDr7 (mSavedDebugRegisters[5]); +} + +/** + Initialize debug agent. + + This function is used to set up debug environment for source level debug + in SMM code. + + If InitFlag is DEBUG_AGENT_INIT_SMM, it will override IDT table entries + and initialize debug port. It will get debug agent Mailbox from GUIDed HOB, + it it exists, debug agent wiil copied it into the local Mailbox in SMM space. + it will override IDT table entries and initialize debug port. Context must + point to a BOOLEAN if it's not NULL, which indicates SMM Debug Agent supported + or not. + If InitFlag is DEBUG_AGENT_INIT_ENTER_SMI, debug agent will save Debug + Registers and get local Mailbox in SMM space. Context will be NULL. + If InitFlag is DEBUG_AGENT_INIT_EXIT_SMI, debug agent will restore Debug + Registers. Context will be NULL. + + @param[in] InitFlag Init flag is used to decide initialize process. + @param[in] Context Context needed according to InitFlag. + @param[in] Function Continue function called by debug agent library; it was + optional. + +**/ +VOID +EFIAPI +InitializeDebugAgent ( + IN UINT32 InitFlag, + IN VOID *Context OPTIONAL, + IN DEBUG_AGENT_CONTINUE Function OPTIONAL + ) +{ + EFI_STATUS Status; + UINT64 DebugPortHandle; + IA32_IDT_GATE_DESCRIPTOR IdtEntry[33]; + IA32_DESCRIPTOR IdtDescriptor; + IA32_DESCRIPTOR *Ia32Idtr; + IA32_IDT_ENTRY *Ia32IdtEntry; + IA32_DESCRIPTOR Idtr; + UINT16 IdtEntryCount; + DEBUG_AGENT_MAILBOX *Mailbox; + UINT64 *MailboxLocation; + UINT32 DebugTimerFrequency; + + switch (InitFlag) { + case DEBUG_AGENT_INIT_SMM: + // + // Install configuration table for persisted vector handoff info + // + Status = gSmst->SmmInstallConfigurationTable ( + gSmst, + &gEfiVectorHandoffTableGuid, + (VOID *)&mVectorHandoffInfoDebugAgent[0], + sizeof (EFI_VECTOR_HANDOFF_INFO) * mVectorHandoffInfoCount + ); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "DebugAgent: Cannot install configuration table for persisted vector handoff info!\n")); + if (Context != NULL) { + *(BOOLEAN *)Context = FALSE; + } + + CpuDeadLoop (); + } + + // + // Check if Debug Agent initialized in DXE phase + // + Status = EfiGetSystemConfigurationTable (&gEfiDebugAgentGuid, (VOID **)&Mailbox); + if ((Status == EFI_SUCCESS) && (Mailbox != NULL)) { + VerifyMailboxChecksum (Mailbox); + mMailboxPointer = Mailbox; + if (Context != NULL) { + *(BOOLEAN *)Context = TRUE; + } + + break; + } + + // + // Check if Debug Agent initialized in SEC/PEI phase + // + Mailbox = GetMailboxFromHob (); + if (Mailbox != NULL) { + mMailboxPointer = Mailbox; + if (Context != NULL) { + *(BOOLEAN *)Context = TRUE; + } + + break; + } + + // + // Debug Agent was not initialized before, use the local mailbox. + // + ZeroMem (&mLocalMailbox, sizeof (DEBUG_AGENT_MAILBOX)); + Mailbox = &mLocalMailbox; + // + // Save original IDT entries + // + AsmReadIdtr (&IdtDescriptor); + CopyMem (&IdtEntry, (VOID *)IdtDescriptor.Base, 33 * sizeof (IA32_IDT_GATE_DESCRIPTOR)); + // + // Initialized Debug Agent + // + InitializeDebugIdt (); + // + // Initialize Debug Timer hardware and save its frequency + // + InitializeDebugTimer (&DebugTimerFrequency, TRUE); + UpdateMailboxContent (Mailbox, DEBUG_MAILBOX_DEBUG_TIMER_FREQUENCY, DebugTimerFrequency); + + DebugPortHandle = (UINT64)(UINTN)DebugPortInitialize ((DEBUG_PORT_HANDLE)(UINTN)Mailbox->DebugPortHandle, NULL); + UpdateMailboxContent (Mailbox, DEBUG_MAILBOX_DEBUG_PORT_HANDLE_INDEX, DebugPortHandle); + mMailboxPointer = Mailbox; + // + // Trigger one software interrupt to inform HOST + // + TriggerSoftInterrupt (SYSTEM_RESET_SIGNATURE); + + SetDebugFlag (DEBUG_AGENT_FLAG_MEMORY_READY, 1); + // + // Memory has been ready + // + if (IsHostAttached ()) { + // + // Trigger one software interrupt to inform HOST + // + TriggerSoftInterrupt (MEMORY_READY_SIGNATURE); + } + + // + // Find and report PE/COFF image info to HOST + // + FindAndReportModuleImageInfo (SIZE_4KB); + // + // Restore saved IDT entries + // + CopyMem ((VOID *)IdtDescriptor.Base, &IdtEntry, 33 * sizeof (IA32_IDT_GATE_DESCRIPTOR)); + + if (Context != NULL) { + *(BOOLEAN *)Context = TRUE; + } + + break; + + case DEBUG_AGENT_INIT_ENTER_SMI: + SaveDebugRegister (); + if (!mSmmDebugIdtInitFlag) { + // + // We only need to initialize Debug IDT table at first SMI entry + // after SMM relocation. + // + InitializeDebugIdt (); + mSmmDebugIdtInitFlag = TRUE; + } + + // + // Check if CPU APIC Timer is working, otherwise initialize it. + // + InitializeLocalApicSoftwareEnable (TRUE); + GetApicTimerState (&mApicTimerDivisor, &mPeriodicMode, &mVector); + mTimerCycle = GetApicTimerInitCount (); + if (!mPeriodicMode || (mTimerCycle == 0)) { + mApicTimerRestore = TRUE; + InitializeDebugTimer (NULL, FALSE); + } + + Mailbox = GetMailboxPointer (); + if (GetDebugFlag (DEBUG_AGENT_FLAG_AGENT_IN_PROGRESS) == 1) { + // + // If Debug Agent has been communication state with HOST, we need skip + // any break points set in SMM, set Skip Breakpoint flag + // + mSkipBreakpoint = TRUE; + } + + if (GetDebugFlag (DEBUG_AGENT_FLAG_BREAK_ON_NEXT_SMI) == 1) { + if (mSkipBreakpoint) { + // + // Print warning message if ignore smm entry break + // + DebugPortWriteBuffer ( + (DEBUG_PORT_HANDLE)(UINTN)Mailbox->DebugPortHandle, + (UINT8 *)mWarningMsgIgnoreSmmEntryBreak, + AsciiStrLen (mWarningMsgIgnoreSmmEntryBreak) + ); + } else { + // + // If SMM entry break is set, SMM code will be break at here. + // + CpuBreakpoint (); + } + } + + break; + + case DEBUG_AGENT_INIT_EXIT_SMI: + Mailbox = GetMailboxPointer (); + // + // Clear Skip Breakpoint flag + // + mSkipBreakpoint = FALSE; + RestoreDebugRegister (); + // + // Restore APIC Timer + // + if (mApicTimerRestore) { + InitializeApicTimer (mApicTimerDivisor, mTimerCycle, mPeriodicMode, mVector); + mApicTimerRestore = FALSE; + } + + break; + + case DEBUG_AGENT_INIT_THUNK_PEI_IA32TOX64: + if (Context == NULL) { + DEBUG ((DEBUG_ERROR, "DebugAgent: Input parameter Context cannot be NULL!\n")); + CpuDeadLoop (); + } else { + Ia32Idtr = (IA32_DESCRIPTOR *)Context; + Ia32IdtEntry = (IA32_IDT_ENTRY *)(Ia32Idtr->Base); + MailboxLocation = (UINT64 *)((UINTN)Ia32IdtEntry[DEBUG_MAILBOX_VECTOR].Bits.OffsetLow + + ((UINTN)Ia32IdtEntry[DEBUG_MAILBOX_VECTOR].Bits.OffsetHigh << 16)); + mMailboxPointer = (DEBUG_AGENT_MAILBOX *)(UINTN)(*MailboxLocation); + VerifyMailboxChecksum (mMailboxPointer); + // + // Get original IDT address and size. + // + AsmReadIdtr ((IA32_DESCRIPTOR *)&Idtr); + IdtEntryCount = (UINT16)((Idtr.Limit + 1) / sizeof (IA32_IDT_GATE_DESCRIPTOR)); + if (IdtEntryCount < 33) { + Idtr.Limit = (UINT16)(sizeof (IA32_IDT_GATE_DESCRIPTOR) * 33 - 1); + Idtr.Base = (UINTN)&mIdtEntryTable; + ZeroMem (&mIdtEntryTable, Idtr.Limit + 1); + AsmWriteIdtr ((IA32_DESCRIPTOR *)&Idtr); + } + + InitializeDebugIdt (); + // + // Initialize Debug Timer hardware and save its frequency + // + InitializeDebugTimer (&DebugTimerFrequency, TRUE); + UpdateMailboxContent (mMailboxPointer, DEBUG_MAILBOX_DEBUG_TIMER_FREQUENCY, DebugTimerFrequency); + // + // Enable Debug Timer interrupt and CPU interrupt + // + SaveAndSetDebugTimerInterrupt (TRUE); + EnableInterrupts (); + + FindAndReportModuleImageInfo (SIZE_4KB); + } + + break; + + default: + // + // Only DEBUG_AGENT_INIT_PREMEM_SEC and DEBUG_AGENT_INIT_POSTMEM_SEC are allowed for this + // Debug Agent library instance. + // + DEBUG ((DEBUG_ERROR, "Debug Agent: The InitFlag value is not allowed!\n")); + CpuDeadLoop (); + break; + } +} |
