There are cases that the operands of an expression are all with rank less
than UINT64/INT64 and the result of the expression is explicitly cast to
UINT64/INT64 to fit the target size.
An example will be:
UINT32 a,b;
// a and b can be any unsigned int type with rank less than UINT64, like
// UINT8, UINT16, etc.
UINT64 c;
c = (UINT64) (a + b);
Some static code checkers may warn that the expression result might
overflow within the rank of "int" (integer promotions) and the result is
then cast to a bigger size.
The commit refines codes by the following rules:
1). When the expression is possible to overflow the range of unsigned int/
int:
c = (UINT64)a + b;
2). When the expression will not overflow within the rank of "int", remove
the explicit type casts:
c = a + b;
3). When the expression will be cast to pointer of possible greater size:
UINT32 a,b;
VOID *c;
c = (VOID *)(UINTN)(a + b); --> c = (VOID *)((UINTN)a + b);
4). When one side of a comparison expression contains only operands with
rank less than UINT32:
UINT8 a;
UINT16 b;
UINTN c;
if ((UINTN)(a + b) > c) {...} --> if (((UINT32)a + b) > c) {...}
For rule 4), if we remove the 'UINTN' type cast like:
if (a + b > c) {...}
The VS compiler will complain with warning C4018 (signed/unsigned
mismatch, level 3 warning) due to promoting 'a + b' to type 'int'.
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Hao Wu <hao.a.wu@intel.com>
Reviewed-by: Jeff Fan <jeff.fan@intel.com>
		
	
		
			
				
	
	
		
			551 lines
		
	
	
		
			16 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			551 lines
		
	
	
		
			16 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/** @file
 | 
						|
  Debug Agent library implementition for Dxe Core and Dxr modules.
 | 
						|
 | 
						|
  Copyright (c) 2010 - 2017, Intel Corporation. All rights reserved.<BR>
 | 
						|
  This program and the accompanying materials
 | 
						|
  are licensed and made available under the terms and conditions of the BSD License
 | 
						|
  which accompanies this distribution.  The full text of the license may be found at
 | 
						|
  http://opensource.org/licenses/bsd-license.php.
 | 
						|
 | 
						|
  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
 | 
						|
  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 | 
						|
 | 
						|
**/
 | 
						|
 | 
						|
#include "DxeDebugAgentLib.h"
 | 
						|
 | 
						|
DEBUG_AGENT_MAILBOX          mMailbox;
 | 
						|
DEBUG_AGENT_MAILBOX          *mMailboxPointer = NULL;
 | 
						|
IA32_IDT_GATE_DESCRIPTOR     mIdtEntryTable[33];
 | 
						|
BOOLEAN                      mDxeCoreFlag                = FALSE;
 | 
						|
BOOLEAN                      mMultiProcessorDebugSupport = FALSE;
 | 
						|
VOID                         *mSavedIdtTable             = NULL;
 | 
						|
UINTN                        mSaveIdtTableSize           = 0;
 | 
						|
BOOLEAN                      mDebugAgentInitialized      = FALSE;
 | 
						|
BOOLEAN                      mSkipBreakpoint             = FALSE;
 | 
						|
 | 
						|
/**
 | 
						|
  Check if debug agent support multi-processor.
 | 
						|
 | 
						|
  @retval TRUE    Multi-processor is supported.
 | 
						|
  @retval FALSE   Multi-processor is not supported.
 | 
						|
 | 
						|
**/
 | 
						|
BOOLEAN
 | 
						|
MultiProcessorDebugSupport (
 | 
						|
  VOID
 | 
						|
  )
 | 
						|
{
 | 
						|
  return mMultiProcessorDebugSupport;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Internal constructor worker function.
 | 
						|
 | 
						|
  It will register one callback function on EFI PCD Protocol.
 | 
						|
  It will allocate the NVS memory to store Mailbox and install configuration table
 | 
						|
  in system table to store its pointer.
 | 
						|
 | 
						|
**/
 | 
						|
VOID
 | 
						|
InternalConstructorWorker (
 | 
						|
  VOID
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS                  Status;
 | 
						|
  EFI_PHYSICAL_ADDRESS        Address;
 | 
						|
  BOOLEAN                     DebugTimerInterruptState;
 | 
						|
  DEBUG_AGENT_MAILBOX         *Mailbox;
 | 
						|
  DEBUG_AGENT_MAILBOX         *NewMailbox;
 | 
						|
  EFI_HOB_GUID_TYPE           *GuidHob;
 | 
						|
  EFI_VECTOR_HANDOFF_INFO     *VectorHandoffInfo;
 | 
						|
 | 
						|
  //
 | 
						|
  // Check persisted vector handoff info
 | 
						|
  //
 | 
						|
  Status = EFI_SUCCESS;
 | 
						|
  GuidHob = GetFirstGuidHob (&gEfiVectorHandoffInfoPpiGuid);
 | 
						|
  if (GuidHob != NULL && !mDxeCoreFlag) {
 | 
						|
    //
 | 
						|
    // Check if configuration table is installed or not if GUIDed HOB existed,
 | 
						|
    // only when Debug Agent is not linked by DXE Core
 | 
						|
    //
 | 
						|
    Status = EfiGetSystemConfigurationTable (&gEfiVectorHandoffTableGuid, (VOID **) &VectorHandoffInfo);
 | 
						|
  }
 | 
						|
  if (GuidHob == NULL || Status != EFI_SUCCESS) {
 | 
						|
    //
 | 
						|
    // Install configuration table for persisted vector handoff info if GUIDed HOB cannot be found or
 | 
						|
    // configuration table does not exist
 | 
						|
    //
 | 
						|
    Status = gBS->InstallConfigurationTable (&gEfiVectorHandoffTableGuid, (VOID *) &mVectorHandoffInfoDebugAgent[0]);
 | 
						|
    if (EFI_ERROR (Status)) {
 | 
						|
      DEBUG ((EFI_D_ERROR, "DebugAgent: Cannot install configuration table for persisted vector handoff info!\n"));
 | 
						|
      CpuDeadLoop ();
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Install EFI Serial IO protocol on debug port
 | 
						|
  //
 | 
						|
  InstallSerialIo ();
 | 
						|
 | 
						|
  Address = 0;
 | 
						|
  Status = gBS->AllocatePages (
 | 
						|
                  AllocateAnyPages,
 | 
						|
                  EfiACPIMemoryNVS,
 | 
						|
                  EFI_SIZE_TO_PAGES (sizeof(DEBUG_AGENT_MAILBOX) + PcdGet16(PcdDebugPortHandleBufferSize)),
 | 
						|
                  &Address
 | 
						|
                  );
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    DEBUG ((EFI_D_ERROR, "DebugAgent: Cannot install configuration table for mailbox!\n"));
 | 
						|
    CpuDeadLoop ();
 | 
						|
  }
 | 
						|
 | 
						|
  DebugTimerInterruptState = SaveAndSetDebugTimerInterrupt (FALSE);
 | 
						|
 | 
						|
  NewMailbox = (DEBUG_AGENT_MAILBOX *) (UINTN) Address;
 | 
						|
  //
 | 
						|
  // Copy Mailbox and Debug Port Handle buffer to new location in ACPI NVS memory, because original Mailbox
 | 
						|
  // and Debug Port Handle buffer may be free at runtime, SMM debug agent needs to access them
 | 
						|
  //
 | 
						|
  Mailbox = GetMailboxPointer ();
 | 
						|
  CopyMem (NewMailbox, Mailbox, sizeof (DEBUG_AGENT_MAILBOX));
 | 
						|
  CopyMem (NewMailbox + 1, (VOID *)(UINTN)Mailbox->DebugPortHandle, PcdGet16(PcdDebugPortHandleBufferSize));
 | 
						|
  //
 | 
						|
  // Update Debug Port Handle in new Mailbox
 | 
						|
  //
 | 
						|
  UpdateMailboxContent (NewMailbox, DEBUG_MAILBOX_DEBUG_PORT_HANDLE_INDEX, (UINT64)(UINTN)(NewMailbox + 1));
 | 
						|
  mMailboxPointer = NewMailbox;
 | 
						|
 | 
						|
  DebugTimerInterruptState = SaveAndSetDebugTimerInterrupt (DebugTimerInterruptState);
 | 
						|
 | 
						|
  Status = gBS->InstallConfigurationTable (&gEfiDebugAgentGuid, (VOID *) mMailboxPointer);
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    DEBUG ((EFI_D_ERROR, "DebugAgent: Failed to install configuration for mailbox!\n"));
 | 
						|
    CpuDeadLoop ();
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Debug Agent constructor function.
 | 
						|
 | 
						|
  @param[in]  ImageHandle   The firmware allocated handle for the EFI image.
 | 
						|
  @param[in]  SystemTable   A pointer to the EFI System Table.
 | 
						|
 | 
						|
  @retval  RETURN_SUCCESS  When this function completed.
 | 
						|
 | 
						|
**/
 | 
						|
RETURN_STATUS
 | 
						|
EFIAPI
 | 
						|
DxeDebugAgentLibConstructor (
 | 
						|
  IN EFI_HANDLE        ImageHandle,
 | 
						|
  IN EFI_SYSTEM_TABLE  *SystemTable
 | 
						|
  )
 | 
						|
{
 | 
						|
  if (mDxeCoreFlag) {
 | 
						|
    //
 | 
						|
    // Invoke internal constructor function only when DXE core links this library instance
 | 
						|
    //
 | 
						|
    InternalConstructorWorker ();
 | 
						|
  }
 | 
						|
 | 
						|
  return RETURN_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Get the pointer to Mailbox from the configuration table.
 | 
						|
 | 
						|
  @return Pointer to Mailbox.
 | 
						|
 | 
						|
**/
 | 
						|
DEBUG_AGENT_MAILBOX *
 | 
						|
GetMailboxFromConfigurationTable (
 | 
						|
  VOID
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS               Status;
 | 
						|
  DEBUG_AGENT_MAILBOX      *Mailbox;
 | 
						|
 | 
						|
  Status = EfiGetSystemConfigurationTable (&gEfiDebugAgentGuid, (VOID **) &Mailbox);
 | 
						|
  if (Status == EFI_SUCCESS && Mailbox != NULL) {
 | 
						|
    VerifyMailboxChecksum (Mailbox);
 | 
						|
    return Mailbox;
 | 
						|
  } else {
 | 
						|
    return NULL;
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Get the pointer to Mailbox from the GUIDed HOB.
 | 
						|
 | 
						|
  @param[in]  HobStart      The starting HOB pointer to search from.
 | 
						|
 | 
						|
  @return Pointer to Mailbox.
 | 
						|
 | 
						|
**/
 | 
						|
DEBUG_AGENT_MAILBOX *
 | 
						|
GetMailboxFromHob (
 | 
						|
  IN VOID                  *HobStart
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_HOB_GUID_TYPE        *GuidHob;
 | 
						|
  UINT64                   *MailboxLocation;
 | 
						|
  DEBUG_AGENT_MAILBOX      *Mailbox;
 | 
						|
 | 
						|
  GuidHob = GetNextGuidHob (&gEfiDebugAgentGuid, HobStart);
 | 
						|
  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
 | 
						|
  )
 | 
						|
{
 | 
						|
  AcquireMpSpinLock (&mDebugMpContext.MailboxSpinLock);
 | 
						|
  VerifyMailboxChecksum (mMailboxPointer);
 | 
						|
  ReleaseMpSpinLock (&mDebugMpContext.MailboxSpinLock);
 | 
						|
  return mMailboxPointer;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Get debug port handle.
 | 
						|
 | 
						|
  @return Debug port handle.
 | 
						|
 | 
						|
**/
 | 
						|
DEBUG_PORT_HANDLE
 | 
						|
GetDebugPortHandle (
 | 
						|
  VOID
 | 
						|
  )
 | 
						|
{
 | 
						|
  return (DEBUG_PORT_HANDLE) (UINTN)(GetMailboxPointer ()->DebugPortHandle);
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Worker function to set up Debug Agent environment.
 | 
						|
 | 
						|
  This function will set up IDT table and initialize the IDT entries and 
 | 
						|
  initialize CPU LOCAL APIC timer.
 | 
						|
  It also tries to connect HOST if Debug Agent was not initialized before.
 | 
						|
 | 
						|
  @param[in] Mailbox        Pointer to Mailbox.
 | 
						|
 | 
						|
**/
 | 
						|
VOID
 | 
						|
SetupDebugAgentEnvironment (
 | 
						|
  IN DEBUG_AGENT_MAILBOX       *Mailbox
 | 
						|
  )
 | 
						|
{
 | 
						|
  IA32_DESCRIPTOR              Idtr;
 | 
						|
  UINT16                       IdtEntryCount;
 | 
						|
  UINT64                       DebugPortHandle;
 | 
						|
  UINT32                       DebugTimerFrequency;
 | 
						|
 | 
						|
  if (mMultiProcessorDebugSupport) {
 | 
						|
    InitializeSpinLock (&mDebugMpContext.MpContextSpinLock);
 | 
						|
    InitializeSpinLock (&mDebugMpContext.DebugPortSpinLock);
 | 
						|
    InitializeSpinLock (&mDebugMpContext.MailboxSpinLock);
 | 
						|
    //
 | 
						|
    // Clear Break CPU index value
 | 
						|
    //
 | 
						|
    mDebugMpContext.BreakAtCpuIndex = (UINT32) -1;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Get original IDT address and size.
 | 
						|
  //
 | 
						|
  AsmReadIdtr ((IA32_DESCRIPTOR *) &Idtr);
 | 
						|
  IdtEntryCount = (UINT16) ((Idtr.Limit + 1) / sizeof (IA32_IDT_GATE_DESCRIPTOR));
 | 
						|
  if (IdtEntryCount < 33) {
 | 
						|
    ZeroMem (&mIdtEntryTable, sizeof (IA32_IDT_GATE_DESCRIPTOR) * 33);
 | 
						|
    //
 | 
						|
    // Copy original IDT table into new one
 | 
						|
    //
 | 
						|
    CopyMem (&mIdtEntryTable, (VOID *) Idtr.Base, Idtr.Limit + 1);
 | 
						|
    //
 | 
						|
    // Load new IDT table
 | 
						|
    //
 | 
						|
    Idtr.Limit = (UINT16) (sizeof (IA32_IDT_GATE_DESCRIPTOR) * 33 - 1);
 | 
						|
    Idtr.Base  = (UINTN) &mIdtEntryTable;
 | 
						|
    AsmWriteIdtr ((IA32_DESCRIPTOR *) &Idtr);
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Initialize the IDT table entries to support source level debug.
 | 
						|
  //
 | 
						|
  InitializeDebugIdt ();
 | 
						|
 | 
						|
  //
 | 
						|
  // If mMailboxPointer is not set before, set it
 | 
						|
  //
 | 
						|
  if (mMailboxPointer == NULL) {
 | 
						|
    if (Mailbox != NULL) {
 | 
						|
      //
 | 
						|
      // If Mailbox exists, copy it into one global variable
 | 
						|
      //
 | 
						|
      CopyMem (&mMailbox, Mailbox, sizeof (DEBUG_AGENT_MAILBOX));
 | 
						|
    } else {
 | 
						|
      ZeroMem (&mMailbox, sizeof (DEBUG_AGENT_MAILBOX));
 | 
						|
    }
 | 
						|
    mMailboxPointer = &mMailbox;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Initialize Debug Timer hardware and save its initial count and frequency
 | 
						|
  //
 | 
						|
  mDebugMpContext.DebugTimerInitCount = InitializeDebugTimer (&DebugTimerFrequency, TRUE);
 | 
						|
  UpdateMailboxContent (mMailboxPointer, DEBUG_MAILBOX_DEBUG_TIMER_FREQUENCY, DebugTimerFrequency);
 | 
						|
  //
 | 
						|
  // Initialize debug communication port
 | 
						|
  //
 | 
						|
  DebugPortHandle = (UINT64) (UINTN)DebugPortInitialize ((VOID *)(UINTN)mMailboxPointer->DebugPortHandle, NULL);
 | 
						|
  UpdateMailboxContent (mMailboxPointer, DEBUG_MAILBOX_DEBUG_PORT_HANDLE_INDEX, DebugPortHandle);
 | 
						|
 | 
						|
  if (Mailbox == NULL) {
 | 
						|
    //
 | 
						|
    // 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);
 | 
						|
    }
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
/**
 | 
						|
  Initialize debug agent.
 | 
						|
 | 
						|
  This function is used to set up debug environment for DXE phase.
 | 
						|
 | 
						|
  If this function is called by DXE Core, Context must be the pointer
 | 
						|
  to HOB list which will be used to get GUIDed HOB. It will enable
 | 
						|
  interrupt to support break-in feature.
 | 
						|
  If this function is called by DXE module, Context must be NULL. It
 | 
						|
  will enable interrupt to support break-in feature.
 | 
						|
 | 
						|
  @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
 | 
						|
  )
 | 
						|
{
 | 
						|
  UINT64                       *MailboxLocation;
 | 
						|
  DEBUG_AGENT_MAILBOX          *Mailbox;
 | 
						|
  BOOLEAN                      InterruptStatus;
 | 
						|
  VOID                         *HobList;
 | 
						|
  IA32_DESCRIPTOR              IdtDescriptor;
 | 
						|
  IA32_DESCRIPTOR              *Ia32Idtr;
 | 
						|
  IA32_IDT_ENTRY               *Ia32IdtEntry;
 | 
						|
  BOOLEAN                      PeriodicMode;
 | 
						|
  UINTN                        TimerCycle;
 | 
						|
 | 
						|
  if (InitFlag == DEBUG_AGENT_INIT_DXE_AP) {
 | 
						|
    //
 | 
						|
    // Check if CPU APIC Timer is working, otherwise initialize it.
 | 
						|
    //
 | 
						|
    InitializeLocalApicSoftwareEnable (TRUE);
 | 
						|
    GetApicTimerState (NULL, &PeriodicMode, NULL);
 | 
						|
    TimerCycle = GetApicTimerInitCount ();
 | 
						|
    if (!PeriodicMode || TimerCycle == 0) {
 | 
						|
      InitializeDebugTimer (NULL, FALSE);
 | 
						|
    }
 | 
						|
    //
 | 
						|
    // Invoked by AP, enable interrupt to let AP could receive IPI from other processors
 | 
						|
    //
 | 
						|
    EnableInterrupts ();
 | 
						|
    return ;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Disable Debug Timer interrupt
 | 
						|
  //
 | 
						|
  SaveAndSetDebugTimerInterrupt (FALSE);
 | 
						|
  //
 | 
						|
  // Save and disable original interrupt status
 | 
						|
  //
 | 
						|
  InterruptStatus = SaveAndDisableInterrupts ();
 | 
						|
 | 
						|
  //
 | 
						|
  // Try to get mailbox firstly
 | 
						|
  //
 | 
						|
  HobList         = NULL;
 | 
						|
  Mailbox         = NULL;
 | 
						|
  MailboxLocation = NULL;
 | 
						|
 | 
						|
  switch (InitFlag) {
 | 
						|
 | 
						|
  case DEBUG_AGENT_INIT_DXE_LOAD:
 | 
						|
    //
 | 
						|
    // Check if Debug Agent has been initialized before
 | 
						|
    //
 | 
						|
    if (IsDebugAgentInitialzed ()) {
 | 
						|
      DEBUG ((EFI_D_INFO, "Debug Agent: The former agent will be overwritten by the new one!\n"));
 | 
						|
    }
 | 
						|
 | 
						|
    mMultiProcessorDebugSupport = TRUE;
 | 
						|
    //
 | 
						|
    // Save original IDT table
 | 
						|
    //
 | 
						|
    AsmReadIdtr (&IdtDescriptor);
 | 
						|
    mSaveIdtTableSize = IdtDescriptor.Limit + 1;
 | 
						|
    mSavedIdtTable    = AllocateCopyPool (mSaveIdtTableSize, (VOID *) IdtDescriptor.Base);
 | 
						|
    //
 | 
						|
    // Check if Debug Agent initialized in DXE phase
 | 
						|
    //
 | 
						|
    Mailbox = GetMailboxFromConfigurationTable ();
 | 
						|
    if (Mailbox == NULL) {
 | 
						|
      //
 | 
						|
      // Try to get mailbox from GUIDed HOB build in PEI
 | 
						|
      //
 | 
						|
      HobList = GetHobList ();
 | 
						|
      Mailbox = GetMailboxFromHob (HobList);
 | 
						|
    }
 | 
						|
    //
 | 
						|
    // Set up Debug Agent Environment and try to connect HOST if required
 | 
						|
    //
 | 
						|
    SetupDebugAgentEnvironment (Mailbox);
 | 
						|
    //
 | 
						|
    // For DEBUG_AGENT_INIT_S3, needn't to install configuration table and EFI Serial IO protocol
 | 
						|
    // For DEBUG_AGENT_INIT_DXE_CORE, InternalConstructorWorker() will invoked in Constructor()
 | 
						|
    //
 | 
						|
    InternalConstructorWorker ();
 | 
						|
    //
 | 
						|
    // Enable Debug Timer interrupt
 | 
						|
    //
 | 
						|
    SaveAndSetDebugTimerInterrupt (TRUE);
 | 
						|
    //
 | 
						|
    // Enable interrupt to receive Debug Timer interrupt
 | 
						|
    //
 | 
						|
    EnableInterrupts ();
 | 
						|
 | 
						|
    mDebugAgentInitialized = TRUE;
 | 
						|
    FindAndReportModuleImageInfo (SIZE_4KB);
 | 
						|
 | 
						|
    *(EFI_STATUS *)Context = EFI_SUCCESS;
 | 
						|
 | 
						|
    break;
 | 
						|
 | 
						|
  case DEBUG_AGENT_INIT_DXE_UNLOAD:
 | 
						|
    if (mDebugAgentInitialized) {
 | 
						|
      if (IsHostAttached ()) {
 | 
						|
        *(EFI_STATUS *)Context = EFI_ACCESS_DENIED;
 | 
						|
        //
 | 
						|
        // Enable Debug Timer interrupt again
 | 
						|
        //
 | 
						|
        SaveAndSetDebugTimerInterrupt (TRUE);
 | 
						|
      } else {
 | 
						|
        //
 | 
						|
        // Restore original IDT table
 | 
						|
        //
 | 
						|
        AsmReadIdtr (&IdtDescriptor);
 | 
						|
        IdtDescriptor.Limit = (UINT16) (mSaveIdtTableSize - 1);
 | 
						|
        CopyMem ((VOID *) IdtDescriptor.Base, mSavedIdtTable, mSaveIdtTableSize);
 | 
						|
        AsmWriteIdtr (&IdtDescriptor);
 | 
						|
        FreePool (mSavedIdtTable);
 | 
						|
        mDebugAgentInitialized = FALSE;
 | 
						|
        *(EFI_STATUS *)Context = EFI_SUCCESS;
 | 
						|
      }
 | 
						|
    } else {
 | 
						|
      *(EFI_STATUS *)Context = EFI_NOT_STARTED;
 | 
						|
    }
 | 
						|
 | 
						|
    //
 | 
						|
    // Restore interrupt state.
 | 
						|
    //
 | 
						|
    SetInterruptState (InterruptStatus);
 | 
						|
    break;
 | 
						|
 | 
						|
  case DEBUG_AGENT_INIT_DXE_CORE:
 | 
						|
    mDxeCoreFlag                = TRUE;
 | 
						|
    mMultiProcessorDebugSupport = TRUE;
 | 
						|
    //
 | 
						|
    // Try to get mailbox from GUIDed HOB build in PEI
 | 
						|
    //
 | 
						|
    HobList = Context;
 | 
						|
    Mailbox = GetMailboxFromHob (HobList);
 | 
						|
    //
 | 
						|
    // Set up Debug Agent Environment and try to connect HOST if required
 | 
						|
    //
 | 
						|
    SetupDebugAgentEnvironment (Mailbox);
 | 
						|
    //
 | 
						|
    // Enable Debug Timer interrupt
 | 
						|
    //
 | 
						|
    SaveAndSetDebugTimerInterrupt (TRUE);
 | 
						|
    //
 | 
						|
    // Enable interrupt to receive Debug Timer interrupt
 | 
						|
    //
 | 
						|
    EnableInterrupts ();
 | 
						|
 | 
						|
    break;
 | 
						|
 | 
						|
  case DEBUG_AGENT_INIT_S3:
 | 
						|
 | 
						|
    if (Context != NULL) {
 | 
						|
      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));
 | 
						|
      Mailbox = (DEBUG_AGENT_MAILBOX *)(UINTN)(*MailboxLocation);
 | 
						|
      VerifyMailboxChecksum (Mailbox);
 | 
						|
    }
 | 
						|
    //
 | 
						|
    // Save Mailbox pointer in global variable
 | 
						|
    //
 | 
						|
    mMailboxPointer = Mailbox;
 | 
						|
    //
 | 
						|
    // Set up Debug Agent Environment and try to connect HOST if required
 | 
						|
    //
 | 
						|
    SetupDebugAgentEnvironment (Mailbox);
 | 
						|
    //
 | 
						|
    // Disable interrupt
 | 
						|
    //
 | 
						|
    DisableInterrupts ();
 | 
						|
    FindAndReportModuleImageInfo (SIZE_4KB);
 | 
						|
    if (GetDebugFlag (DEBUG_AGENT_FLAG_BREAK_BOOT_SCRIPT) == 1) {
 | 
						|
      //
 | 
						|
      // If Boot Script entry break is set, code will be break at here.
 | 
						|
      //
 | 
						|
      CpuBreakpoint ();
 | 
						|
    }
 | 
						|
    break;
 | 
						|
 | 
						|
  default:
 | 
						|
    //
 | 
						|
    // Only DEBUG_AGENT_INIT_PREMEM_SEC and DEBUG_AGENT_INIT_POSTMEM_SEC are allowed for this
 | 
						|
    // Debug Agent library instance.
 | 
						|
    //
 | 
						|
    DEBUG ((EFI_D_ERROR, "Debug Agent: The InitFlag value is not allowed!\n"));
 | 
						|
    CpuDeadLoop ();
 | 
						|
    break;
 | 
						|
  }
 | 
						|
}
 |