REF: https://bugzilla.tianocore.org/show_bug.cgi?id=3737 Apply uncrustify changes to .c/.h files in the SourceLevelDebugPkg package Cc: Andrew Fish <afish@apple.com> Cc: Leif Lindholm <leif@nuviainc.com> Cc: Michael D Kinney <michael.d.kinney@intel.com> Signed-off-by: Michael Kubacki <michael.kubacki@microsoft.com> Reviewed-by: Hao A Wu <hao.a.wu@intel.com> Reviewed-by: Ray Ni <ray.ni@intel.com>
		
			
				
	
	
		
			722 lines
		
	
	
		
			24 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			722 lines
		
	
	
		
			24 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/** @file
 | 
						|
  SEC Core Debug Agent Library instance implementation.
 | 
						|
 | 
						|
  Copyright (c) 2010 - 2017, Intel Corporation. All rights reserved.<BR>
 | 
						|
  SPDX-License-Identifier: BSD-2-Clause-Patent
 | 
						|
 | 
						|
**/
 | 
						|
 | 
						|
#include "SecPeiDebugAgentLib.h"
 | 
						|
 | 
						|
GLOBAL_REMOVE_IF_UNREFERENCED BOOLEAN  mSkipBreakpoint = FALSE;
 | 
						|
 | 
						|
GLOBAL_REMOVE_IF_UNREFERENCED EFI_PEI_VECTOR_HANDOFF_INFO_PPI  mVectorHandoffInfoPpi = {
 | 
						|
  &mVectorHandoffInfoDebugAgent[0]
 | 
						|
};
 | 
						|
 | 
						|
//
 | 
						|
// Ppis to be installed
 | 
						|
//
 | 
						|
GLOBAL_REMOVE_IF_UNREFERENCED EFI_PEI_PPI_DESCRIPTOR  mVectorHandoffInfoPpiList[] = {
 | 
						|
  {
 | 
						|
    (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
 | 
						|
    &gEfiVectorHandoffInfoPpiGuid,
 | 
						|
    &mVectorHandoffInfoPpi
 | 
						|
  }
 | 
						|
};
 | 
						|
 | 
						|
GLOBAL_REMOVE_IF_UNREFERENCED EFI_PEI_NOTIFY_DESCRIPTOR  mDebugAgentMemoryDiscoveredNotifyList[1] = {
 | 
						|
  {
 | 
						|
    (EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
 | 
						|
    &gEfiPeiMemoryDiscoveredPpiGuid,
 | 
						|
    DebugAgentCallbackMemoryDiscoveredPpi
 | 
						|
  }
 | 
						|
};
 | 
						|
 | 
						|
/**
 | 
						|
  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
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS           Status;
 | 
						|
  DEBUG_PACKET_HEADER  DebugHeader;
 | 
						|
  UINT8                *Data8;
 | 
						|
 | 
						|
  *BreakSymbol = 0;
 | 
						|
  //
 | 
						|
  // If Debug Port buffer has data, read it till it was break symbol or Debug Port buffer empty.
 | 
						|
  //
 | 
						|
  Data8 = (UINT8 *)&DebugHeader;
 | 
						|
  while (TRUE) {
 | 
						|
    //
 | 
						|
    // If start symbol is not received
 | 
						|
    //
 | 
						|
    if (!DebugPortPollBuffer (Handle)) {
 | 
						|
      //
 | 
						|
      // If no data in Debug Port, exit
 | 
						|
      //
 | 
						|
      break;
 | 
						|
    }
 | 
						|
 | 
						|
    //
 | 
						|
    // Try to read the start symbol
 | 
						|
    //
 | 
						|
    DebugAgentReadBuffer (Handle, Data8, 1, 0);
 | 
						|
    if (*Data8 == DEBUG_STARTING_SYMBOL_ATTACH) {
 | 
						|
      *BreakSymbol = *Data8;
 | 
						|
      DebugAgentMsgPrint (DEBUG_AGENT_INFO, "Debug Timer attach symbol received %x", *BreakSymbol);
 | 
						|
      return EFI_SUCCESS;
 | 
						|
    }
 | 
						|
 | 
						|
    if (*Data8 == DEBUG_STARTING_SYMBOL_NORMAL) {
 | 
						|
      Status = ReadRemainingBreakPacket (Handle, &DebugHeader);
 | 
						|
      if (Status == EFI_SUCCESS) {
 | 
						|
        *BreakSymbol = DebugHeader.Command;
 | 
						|
        DebugAgentMsgPrint (DEBUG_AGENT_INFO, "Debug Timer break symbol received %x", *BreakSymbol);
 | 
						|
        return EFI_SUCCESS;
 | 
						|
      }
 | 
						|
 | 
						|
      if (Status == EFI_TIMEOUT) {
 | 
						|
        break;
 | 
						|
      }
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  return EFI_NOT_FOUND;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Get the pointer to location saved Mailbox pointer from IDT entry.
 | 
						|
 | 
						|
**/
 | 
						|
VOID *
 | 
						|
GetLocationSavedMailboxPointerInIdtEntry (
 | 
						|
  VOID
 | 
						|
  )
 | 
						|
{
 | 
						|
  UINTN  *MailboxLocation;
 | 
						|
 | 
						|
  MailboxLocation = (UINTN *)GetExceptionHandlerInIdtEntry (DEBUG_MAILBOX_VECTOR);
 | 
						|
  //
 | 
						|
  // *MailboxLocation is the pointer to Mailbox
 | 
						|
  //
 | 
						|
  VerifyMailboxChecksum ((DEBUG_AGENT_MAILBOX *)(*MailboxLocation));
 | 
						|
  return MailboxLocation;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Set the pointer of Mailbox into IDT entry before memory is ready.
 | 
						|
 | 
						|
  @param[in]  MailboxLocation    Pointer to location saved Mailbox pointer.
 | 
						|
 | 
						|
**/
 | 
						|
VOID
 | 
						|
SetLocationSavedMailboxPointerInIdtEntry (
 | 
						|
  IN VOID  *MailboxLocation
 | 
						|
  )
 | 
						|
{
 | 
						|
  SetExceptionHandlerInIdtEntry (DEBUG_MAILBOX_VECTOR, MailboxLocation);
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Get the location of Mailbox pointer from the GUIDed HOB.
 | 
						|
 | 
						|
  @return Pointer to the location saved Mailbox pointer.
 | 
						|
 | 
						|
**/
 | 
						|
UINT64 *
 | 
						|
GetMailboxLocationFromHob (
 | 
						|
  VOID
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_HOB_GUID_TYPE  *GuidHob;
 | 
						|
 | 
						|
  GuidHob = GetFirstGuidHob (&gEfiDebugAgentGuid);
 | 
						|
  if (GuidHob == NULL) {
 | 
						|
    return NULL;
 | 
						|
  }
 | 
						|
 | 
						|
  return (UINT64 *)(GET_GUID_HOB_DATA (GuidHob));
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Get Debug Agent Mailbox pointer.
 | 
						|
 | 
						|
  @return Mailbox pointer.
 | 
						|
 | 
						|
**/
 | 
						|
DEBUG_AGENT_MAILBOX *
 | 
						|
GetMailboxPointer (
 | 
						|
  VOID
 | 
						|
  )
 | 
						|
{
 | 
						|
  UINT64               DebugPortHandle;
 | 
						|
  UINT64               *MailboxLocationInIdt;
 | 
						|
  UINT64               *MailboxLocationInHob;
 | 
						|
  DEBUG_AGENT_MAILBOX  *Mailbox;
 | 
						|
 | 
						|
  //
 | 
						|
  // Get mailbox from IDT entry firstly
 | 
						|
  //
 | 
						|
  MailboxLocationInIdt = GetLocationSavedMailboxPointerInIdtEntry ();
 | 
						|
  Mailbox              = (DEBUG_AGENT_MAILBOX *)(UINTN)(*MailboxLocationInIdt);
 | 
						|
  //
 | 
						|
  // Cannot used GetDebugFlag() to get Debug Flag to avoid GetMailboxPointer() nested
 | 
						|
  //
 | 
						|
  if ((Mailbox->DebugFlag.Bits.CheckMailboxInHob != 1) ||
 | 
						|
      (Mailbox->DebugFlag.Bits.InitArch != DEBUG_ARCH_SYMBOL))
 | 
						|
  {
 | 
						|
    //
 | 
						|
    // If mailbox was setup in SEC or the current CPU arch is different from the init arch
 | 
						|
    // Debug Agent initialized, return the mailbox from IDT entry directly.
 | 
						|
    // Otherwise, we need to check the mailbox location saved in GUIDed HOB further.
 | 
						|
    //
 | 
						|
    return Mailbox;
 | 
						|
  }
 | 
						|
 | 
						|
  MailboxLocationInHob = GetMailboxLocationFromHob ();
 | 
						|
  //
 | 
						|
  // Compare mailbox in IDT entry with mailbox in HOB,
 | 
						|
  // need to fix mailbox location if HOB moved by PEI CORE
 | 
						|
  //
 | 
						|
  if ((MailboxLocationInHob != MailboxLocationInIdt) && (MailboxLocationInHob != NULL)) {
 | 
						|
    Mailbox = (DEBUG_AGENT_MAILBOX *)(UINTN)(*MailboxLocationInHob);
 | 
						|
    //
 | 
						|
    // Fix up Debug Port handler and save new mailbox in IDT entry
 | 
						|
    //
 | 
						|
    Mailbox         = (DEBUG_AGENT_MAILBOX *)((UINTN)Mailbox + ((UINTN)(MailboxLocationInHob) - (UINTN)MailboxLocationInIdt));
 | 
						|
    DebugPortHandle = (UINTN)Mailbox->DebugPortHandle + ((UINTN)(MailboxLocationInHob) - (UINTN)MailboxLocationInIdt);
 | 
						|
    UpdateMailboxContent (Mailbox, DEBUG_MAILBOX_DEBUG_PORT_HANDLE_INDEX, DebugPortHandle);
 | 
						|
    *MailboxLocationInHob = (UINT64)(UINTN)Mailbox;
 | 
						|
    SetLocationSavedMailboxPointerInIdtEntry (MailboxLocationInHob);
 | 
						|
    //
 | 
						|
    // Clean CheckMailboxInHob flag
 | 
						|
    //
 | 
						|
    Mailbox->DebugFlag.Bits.CheckMailboxInHob = 0;
 | 
						|
    UpdateMailboxChecksum (Mailbox);
 | 
						|
  }
 | 
						|
 | 
						|
  return Mailbox;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Get debug port handle.
 | 
						|
 | 
						|
  @return Debug port handle.
 | 
						|
 | 
						|
**/
 | 
						|
DEBUG_PORT_HANDLE
 | 
						|
GetDebugPortHandle (
 | 
						|
  VOID
 | 
						|
  )
 | 
						|
{
 | 
						|
  DEBUG_AGENT_MAILBOX  *DebugAgentMailbox;
 | 
						|
 | 
						|
  DebugAgentMailbox = GetMailboxPointer ();
 | 
						|
 | 
						|
  return (DEBUG_PORT_HANDLE)(UINTN)(DebugAgentMailbox->DebugPortHandle);
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Debug Agent provided notify callback function on Memory Discovered PPI.
 | 
						|
 | 
						|
  @param[in] PeiServices      Indirect reference to the PEI Services Table.
 | 
						|
  @param[in] NotifyDescriptor Address of the notification descriptor data structure.
 | 
						|
  @param[in] Ppi              Address of the PPI that was installed.
 | 
						|
 | 
						|
  @retval EFI_SUCCESS If the function completed successfully.
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
DebugAgentCallbackMemoryDiscoveredPpi (
 | 
						|
  IN EFI_PEI_SERVICES           **PeiServices,
 | 
						|
  IN EFI_PEI_NOTIFY_DESCRIPTOR  *NotifyDescriptor,
 | 
						|
  IN VOID                       *Ppi
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS            Status;
 | 
						|
  DEBUG_AGENT_MAILBOX   *Mailbox;
 | 
						|
  BOOLEAN               InterruptStatus;
 | 
						|
  EFI_PHYSICAL_ADDRESS  Address;
 | 
						|
  DEBUG_AGENT_MAILBOX   *NewMailbox;
 | 
						|
  UINT64                *MailboxLocationInHob;
 | 
						|
 | 
						|
  //
 | 
						|
  // Save and disable original interrupt status
 | 
						|
  //
 | 
						|
  InterruptStatus = SaveAndDisableInterrupts ();
 | 
						|
 | 
						|
  //
 | 
						|
  // Allocate ACPI NVS memory for new Mailbox and Debug Port Handle buffer
 | 
						|
  //
 | 
						|
  Status = PeiServicesAllocatePages (
 | 
						|
             EfiACPIMemoryNVS,
 | 
						|
             EFI_SIZE_TO_PAGES (sizeof (DEBUG_AGENT_MAILBOX) + PcdGet16 (PcdDebugPortHandleBufferSize)),
 | 
						|
             &Address
 | 
						|
             );
 | 
						|
  ASSERT_EFI_ERROR (Status);
 | 
						|
  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 in the allocated pool that may be marked as free by DXE Core after DXE Core
 | 
						|
  // reallocates the HOB.
 | 
						|
  //
 | 
						|
  Mailbox = GetMailboxPointer ();
 | 
						|
  CopyMem (NewMailbox, Mailbox, sizeof (DEBUG_AGENT_MAILBOX));
 | 
						|
  CopyMem (NewMailbox + 1, (VOID *)(UINTN)Mailbox->DebugPortHandle, PcdGet16 (PcdDebugPortHandleBufferSize));
 | 
						|
  //
 | 
						|
  // Update Mailbox Location pointer in GUIDed HOB and IDT entry with new one
 | 
						|
  //
 | 
						|
  MailboxLocationInHob = GetMailboxLocationFromHob ();
 | 
						|
  ASSERT (MailboxLocationInHob != NULL);
 | 
						|
  *MailboxLocationInHob = (UINT64)(UINTN)NewMailbox;
 | 
						|
  SetLocationSavedMailboxPointerInIdtEntry (MailboxLocationInHob);
 | 
						|
  //
 | 
						|
  // Update Debug Port Handle in new Mailbox
 | 
						|
  //
 | 
						|
  UpdateMailboxContent (NewMailbox, DEBUG_MAILBOX_DEBUG_PORT_HANDLE_INDEX, (UINT64)(UINTN)(NewMailbox + 1));
 | 
						|
  //
 | 
						|
  // Set physical memory ready flag
 | 
						|
  //
 | 
						|
  SetDebugFlag (DEBUG_AGENT_FLAG_MEMORY_READY, 1);
 | 
						|
 | 
						|
  if (IsHostAttached ()) {
 | 
						|
    //
 | 
						|
    // Trigger one software interrupt to inform HOST
 | 
						|
    //
 | 
						|
    TriggerSoftInterrupt (MEMORY_READY_SIGNATURE);
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Restore interrupt state.
 | 
						|
  //
 | 
						|
  SetInterruptState (InterruptStatus);
 | 
						|
 | 
						|
  return EFI_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Initialize debug agent.
 | 
						|
 | 
						|
  This function is used to set up debug environment for SEC and PEI phase.
 | 
						|
 | 
						|
  If InitFlag is DEBUG_AGENT_INIT_PREMEM_SEC, it will override IDT table entries
 | 
						|
  and initialize debug port. It will enable interrupt to support break-in feature.
 | 
						|
  It will set up debug agent Mailbox in cache-as-ramfrom. It will be called before
 | 
						|
  physical memory is ready.
 | 
						|
  If InitFlag is DEBUG_AGENT_INIT_POSTMEM_SEC, debug agent will build one GUIDed
 | 
						|
  HOB to copy debug agent Mailbox. It will be called after physical memory is ready.
 | 
						|
 | 
						|
  This function is used to set up debug environment to support source level debugging.
 | 
						|
  If certain Debug Agent Library instance has to save some private data in the stack,
 | 
						|
  this function must work on the mode that doesn't return to the caller, then
 | 
						|
  the caller needs to wrap up all rest of logic after InitializeDebugAgent() into one
 | 
						|
  function and pass it into InitializeDebugAgent(). InitializeDebugAgent() is
 | 
						|
  responsible to invoke the passing-in function at the end of InitializeDebugAgent().
 | 
						|
 | 
						|
  If the parameter Function is not NULL, Debug Agent Library instance will invoke it by
 | 
						|
  passing in the Context to be its parameter.
 | 
						|
 | 
						|
  If Function() is NULL, Debug Agent Library instance will return after setup debug
 | 
						|
  environment.
 | 
						|
 | 
						|
  @param[in] InitFlag     Init flag is used to decide the initialize process.
 | 
						|
  @param[in] Context      Context needed according to InitFlag; it was optional.
 | 
						|
  @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
 | 
						|
  )
 | 
						|
{
 | 
						|
  DEBUG_AGENT_MAILBOX              *Mailbox;
 | 
						|
  DEBUG_AGENT_MAILBOX              *NewMailbox;
 | 
						|
  DEBUG_AGENT_MAILBOX              MailboxInStack;
 | 
						|
  DEBUG_AGENT_PHASE2_CONTEXT       Phase2Context;
 | 
						|
  DEBUG_AGENT_CONTEXT_POSTMEM_SEC  *DebugAgentContext;
 | 
						|
  EFI_STATUS                       Status;
 | 
						|
  IA32_DESCRIPTOR                  *Ia32Idtr;
 | 
						|
  IA32_IDT_ENTRY                   *Ia32IdtEntry;
 | 
						|
  UINT64                           DebugPortHandle;
 | 
						|
  UINT64                           MailboxLocation;
 | 
						|
  UINT64                           *MailboxLocationPointer;
 | 
						|
  EFI_PHYSICAL_ADDRESS             Address;
 | 
						|
  UINT32                           DebugTimerFrequency;
 | 
						|
  BOOLEAN                          CpuInterruptState;
 | 
						|
 | 
						|
  //
 | 
						|
  // Disable interrupts and save current interrupt state
 | 
						|
  //
 | 
						|
  CpuInterruptState = SaveAndDisableInterrupts ();
 | 
						|
 | 
						|
  switch (InitFlag) {
 | 
						|
    case DEBUG_AGENT_INIT_PREMEM_SEC:
 | 
						|
 | 
						|
      InitializeDebugIdt ();
 | 
						|
 | 
						|
      MailboxLocation = (UINT64)(UINTN)&MailboxInStack;
 | 
						|
      Mailbox         = &MailboxInStack;
 | 
						|
      ZeroMem ((VOID *)Mailbox, sizeof (DEBUG_AGENT_MAILBOX));
 | 
						|
      //
 | 
						|
      // Get and save debug port handle and set the length of memory block.
 | 
						|
      //
 | 
						|
      SetLocationSavedMailboxPointerInIdtEntry (&MailboxLocation);
 | 
						|
      //
 | 
						|
      // Force error message could be printed during the first shakehand between Target/HOST.
 | 
						|
      //
 | 
						|
      SetDebugFlag (DEBUG_AGENT_FLAG_PRINT_ERROR_LEVEL, DEBUG_AGENT_ERROR);
 | 
						|
      //
 | 
						|
      // Save init arch type when debug agent initialized
 | 
						|
      //
 | 
						|
      SetDebugFlag (DEBUG_AGENT_FLAG_INIT_ARCH, DEBUG_ARCH_SYMBOL);
 | 
						|
      //
 | 
						|
      // Initialize Debug Timer hardware and save its frequency
 | 
						|
      //
 | 
						|
      InitializeDebugTimer (&DebugTimerFrequency, TRUE);
 | 
						|
      UpdateMailboxContent (Mailbox, DEBUG_MAILBOX_DEBUG_TIMER_FREQUENCY, DebugTimerFrequency);
 | 
						|
 | 
						|
      Phase2Context.InitFlag = InitFlag;
 | 
						|
      Phase2Context.Context  = Context;
 | 
						|
      Phase2Context.Function = Function;
 | 
						|
      DebugPortInitialize ((VOID *)&Phase2Context, InitializeDebugAgentPhase2);
 | 
						|
      //
 | 
						|
      // If reaches here, it means Debug Port initialization failed.
 | 
						|
      //
 | 
						|
      DEBUG ((DEBUG_ERROR, "Debug Agent: Debug port initialization failed.\n"));
 | 
						|
 | 
						|
      break;
 | 
						|
 | 
						|
    case DEBUG_AGENT_INIT_POSTMEM_SEC:
 | 
						|
      Mailbox = GetMailboxPointer ();
 | 
						|
      //
 | 
						|
      // Memory has been ready
 | 
						|
      //
 | 
						|
      SetDebugFlag (DEBUG_AGENT_FLAG_MEMORY_READY, 1);
 | 
						|
      if (IsHostAttached ()) {
 | 
						|
        //
 | 
						|
        // Trigger one software interrupt to inform HOST
 | 
						|
        //
 | 
						|
        TriggerSoftInterrupt (MEMORY_READY_SIGNATURE);
 | 
						|
      }
 | 
						|
 | 
						|
      //
 | 
						|
      // Install Vector Handoff Info PPI to persist vectors used by Debug Agent
 | 
						|
      //
 | 
						|
      Status = PeiServicesInstallPpi (&mVectorHandoffInfoPpiList[0]);
 | 
						|
      if (EFI_ERROR (Status)) {
 | 
						|
        DEBUG ((DEBUG_ERROR, "DebugAgent: Failed to install Vector Handoff Info PPI!\n"));
 | 
						|
        CpuDeadLoop ();
 | 
						|
      }
 | 
						|
 | 
						|
      //
 | 
						|
      // Fix up Debug Port handle address and mailbox address
 | 
						|
      //
 | 
						|
      DebugAgentContext = (DEBUG_AGENT_CONTEXT_POSTMEM_SEC *)Context;
 | 
						|
      if (DebugAgentContext != NULL) {
 | 
						|
        DebugPortHandle = (UINT64)(UINT32)(Mailbox->DebugPortHandle + DebugAgentContext->StackMigrateOffset);
 | 
						|
        UpdateMailboxContent (Mailbox, DEBUG_MAILBOX_DEBUG_PORT_HANDLE_INDEX, DebugPortHandle);
 | 
						|
        Mailbox         = (DEBUG_AGENT_MAILBOX *)((UINTN)Mailbox + DebugAgentContext->StackMigrateOffset);
 | 
						|
        MailboxLocation = (UINT64)(UINTN)Mailbox;
 | 
						|
        //
 | 
						|
        // Build mailbox location in HOB and fix-up its address
 | 
						|
        //
 | 
						|
        MailboxLocationPointer = BuildGuidDataHob (
 | 
						|
                                   &gEfiDebugAgentGuid,
 | 
						|
                                   &MailboxLocation,
 | 
						|
                                   sizeof (UINT64)
 | 
						|
                                   );
 | 
						|
        MailboxLocationPointer = (UINT64 *)((UINTN)MailboxLocationPointer + DebugAgentContext->HeapMigrateOffset);
 | 
						|
      } else {
 | 
						|
        //
 | 
						|
        // DebugAgentContext is NULL. Then, Mailbox can directly be copied into memory.
 | 
						|
        // Allocate ACPI NVS memory for new Mailbox and Debug Port Handle buffer
 | 
						|
        //
 | 
						|
        Status = PeiServicesAllocatePages (
 | 
						|
                   EfiACPIMemoryNVS,
 | 
						|
                   EFI_SIZE_TO_PAGES (sizeof (DEBUG_AGENT_MAILBOX) + PcdGet16 (PcdDebugPortHandleBufferSize)),
 | 
						|
                   &Address
 | 
						|
                   );
 | 
						|
        if (EFI_ERROR (Status)) {
 | 
						|
          DEBUG ((DEBUG_ERROR, "DebugAgent: Failed to allocate pages!\n"));
 | 
						|
          CpuDeadLoop ();
 | 
						|
        }
 | 
						|
 | 
						|
        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 in the allocated pool that may be marked as free by DXE Core after DXE Core
 | 
						|
        // reallocates the HOB.
 | 
						|
        //
 | 
						|
        CopyMem (NewMailbox, Mailbox, sizeof (DEBUG_AGENT_MAILBOX));
 | 
						|
        CopyMem (NewMailbox + 1, (VOID *)(UINTN)Mailbox->DebugPortHandle, PcdGet16 (PcdDebugPortHandleBufferSize));
 | 
						|
        UpdateMailboxContent (NewMailbox, DEBUG_MAILBOX_DEBUG_PORT_HANDLE_INDEX, (UINT64)(UINTN)(NewMailbox + 1));
 | 
						|
        MailboxLocation = (UINT64)(UINTN)NewMailbox;
 | 
						|
        //
 | 
						|
        // Build mailbox location in HOB
 | 
						|
        //
 | 
						|
        MailboxLocationPointer = BuildGuidDataHob (
 | 
						|
                                   &gEfiDebugAgentGuid,
 | 
						|
                                   &MailboxLocation,
 | 
						|
                                   sizeof (UINT64)
 | 
						|
                                   );
 | 
						|
      }
 | 
						|
 | 
						|
      //
 | 
						|
      // Update IDT entry to save the location saved mailbox pointer
 | 
						|
      //
 | 
						|
      SetLocationSavedMailboxPointerInIdtEntry (MailboxLocationPointer);
 | 
						|
      break;
 | 
						|
 | 
						|
    case DEBUG_AGENT_INIT_PEI:
 | 
						|
      if (Context == NULL) {
 | 
						|
        DEBUG ((DEBUG_ERROR, "DebugAgent: Input parameter Context cannot be NULL!\n"));
 | 
						|
        CpuDeadLoop ();
 | 
						|
      }
 | 
						|
 | 
						|
      //
 | 
						|
      // Check if Debug Agent has initialized before
 | 
						|
      //
 | 
						|
      if (IsDebugAgentInitialzed ()) {
 | 
						|
        DEBUG ((DEBUG_WARN, "Debug Agent: It has already initialized in SEC Core!\n"));
 | 
						|
        break;
 | 
						|
      }
 | 
						|
 | 
						|
      //
 | 
						|
      // Install Vector Handoff Info PPI to persist vectors used by Debug Agent
 | 
						|
      //
 | 
						|
      Status = PeiServicesInstallPpi (&mVectorHandoffInfoPpiList[0]);
 | 
						|
      if (EFI_ERROR (Status)) {
 | 
						|
        DEBUG ((DEBUG_ERROR, "DebugAgent: Failed to install Vector Handoff Info PPI!\n"));
 | 
						|
        CpuDeadLoop ();
 | 
						|
      }
 | 
						|
 | 
						|
      //
 | 
						|
      // Set up IDT entries
 | 
						|
      //
 | 
						|
      InitializeDebugIdt ();
 | 
						|
      //
 | 
						|
      // Build mailbox in HOB and setup Mailbox Set In Pei flag
 | 
						|
      //
 | 
						|
      Mailbox = AllocateZeroPool (sizeof (DEBUG_AGENT_MAILBOX));
 | 
						|
      if (Mailbox == NULL) {
 | 
						|
        DEBUG ((DEBUG_ERROR, "DebugAgent: Failed to allocate memory!\n"));
 | 
						|
        CpuDeadLoop ();
 | 
						|
      } else {
 | 
						|
        MailboxLocation        = (UINT64)(UINTN)Mailbox;
 | 
						|
        MailboxLocationPointer = BuildGuidDataHob (
 | 
						|
                                   &gEfiDebugAgentGuid,
 | 
						|
                                   &MailboxLocation,
 | 
						|
                                   sizeof (UINT64)
 | 
						|
                                   );
 | 
						|
        //
 | 
						|
        // Initialize Debug Timer hardware and save its frequency
 | 
						|
        //
 | 
						|
        InitializeDebugTimer (&DebugTimerFrequency, TRUE);
 | 
						|
        UpdateMailboxContent (Mailbox, DEBUG_MAILBOX_DEBUG_TIMER_FREQUENCY, DebugTimerFrequency);
 | 
						|
        //
 | 
						|
        // Update IDT entry to save the location pointer saved mailbox pointer
 | 
						|
        //
 | 
						|
        SetLocationSavedMailboxPointerInIdtEntry (MailboxLocationPointer);
 | 
						|
      }
 | 
						|
 | 
						|
      //
 | 
						|
      // Save init arch type when debug agent initialized
 | 
						|
      //
 | 
						|
      SetDebugFlag (DEBUG_AGENT_FLAG_INIT_ARCH, DEBUG_ARCH_SYMBOL);
 | 
						|
      //
 | 
						|
      // Register for a callback once memory has been initialized.
 | 
						|
      // If memory has been ready, the callback function will be invoked immediately
 | 
						|
      //
 | 
						|
      Status = PeiServicesNotifyPpi (&mDebugAgentMemoryDiscoveredNotifyList[0]);
 | 
						|
      if (EFI_ERROR (Status)) {
 | 
						|
        DEBUG ((DEBUG_ERROR, "DebugAgent: Failed to register memory discovered callback function!\n"));
 | 
						|
        CpuDeadLoop ();
 | 
						|
      }
 | 
						|
 | 
						|
      //
 | 
						|
      // Set HOB check flag if memory has not been ready yet
 | 
						|
      //
 | 
						|
      if (GetDebugFlag (DEBUG_AGENT_FLAG_MEMORY_READY) == 0) {
 | 
						|
        SetDebugFlag (DEBUG_AGENT_FLAG_CHECK_MAILBOX_IN_HOB, 1);
 | 
						|
      }
 | 
						|
 | 
						|
      Phase2Context.InitFlag = InitFlag;
 | 
						|
      Phase2Context.Context  = Context;
 | 
						|
      Phase2Context.Function = Function;
 | 
						|
      DebugPortInitialize ((VOID *)&Phase2Context, InitializeDebugAgentPhase2);
 | 
						|
 | 
						|
      FindAndReportModuleImageInfo (4);
 | 
						|
 | 
						|
      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);
 | 
						|
        MailboxLocationPointer = (UINT64 *)((UINTN)Ia32IdtEntry[DEBUG_MAILBOX_VECTOR].Bits.OffsetLow +
 | 
						|
                                            ((UINTN)Ia32IdtEntry[DEBUG_MAILBOX_VECTOR].Bits.OffsetHigh << 16));
 | 
						|
        Mailbox = (DEBUG_AGENT_MAILBOX *)(UINTN)(*MailboxLocationPointer);
 | 
						|
        //
 | 
						|
        // Mailbox should valid and setup before executing thunk code
 | 
						|
        //
 | 
						|
        VerifyMailboxChecksum (Mailbox);
 | 
						|
 | 
						|
        DebugPortHandle = (UINT64)(UINTN)DebugPortInitialize ((VOID *)(UINTN)Mailbox->DebugPortHandle, NULL);
 | 
						|
        UpdateMailboxContent (Mailbox, DEBUG_MAILBOX_DEBUG_PORT_HANDLE_INDEX, DebugPortHandle);
 | 
						|
        //
 | 
						|
        // Set up IDT entries
 | 
						|
        //
 | 
						|
        InitializeDebugIdt ();
 | 
						|
        //
 | 
						|
        // Update IDT entry to save location pointer saved the mailbox pointer
 | 
						|
        //
 | 
						|
        SetLocationSavedMailboxPointerInIdtEntry (MailboxLocationPointer);
 | 
						|
 | 
						|
        FindAndReportModuleImageInfo (4);
 | 
						|
      }
 | 
						|
 | 
						|
      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;
 | 
						|
  }
 | 
						|
 | 
						|
  if (InitFlag == DEBUG_AGENT_INIT_POSTMEM_SEC) {
 | 
						|
    //
 | 
						|
    // Restore CPU Interrupt state and keep debug timer interrupt state as is
 | 
						|
    // in DEBUG_AGENT_INIT_POSTMEM_SEC case
 | 
						|
    //
 | 
						|
    SetInterruptState (CpuInterruptState);
 | 
						|
  } else {
 | 
						|
    //
 | 
						|
    // Enable Debug Timer interrupt
 | 
						|
    //
 | 
						|
    SaveAndSetDebugTimerInterrupt (TRUE);
 | 
						|
    //
 | 
						|
    // Enable CPU interrupts so debug timer interrupts can be delivered
 | 
						|
    //
 | 
						|
    EnableInterrupts ();
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // If Function is not NULL, invoke it always whatever debug agent was initialized successfully or not.
 | 
						|
  //
 | 
						|
  if (Function != NULL) {
 | 
						|
    Function (Context);
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Set return status for DEBUG_AGENT_INIT_PEI
 | 
						|
  //
 | 
						|
  if ((InitFlag == DEBUG_AGENT_INIT_PEI) && (Context != NULL)) {
 | 
						|
    *(EFI_STATUS *)Context = EFI_SUCCESS;
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Caller provided function to be invoked at the end of DebugPortInitialize().
 | 
						|
 | 
						|
  Refer to the description for DebugPortInitialize() for more details.
 | 
						|
 | 
						|
  @param[in] Context           The first input argument of DebugPortInitialize().
 | 
						|
  @param[in] DebugPortHandle   Debug port handle created by Debug Communication Library.
 | 
						|
 | 
						|
**/
 | 
						|
VOID
 | 
						|
EFIAPI
 | 
						|
InitializeDebugAgentPhase2 (
 | 
						|
  IN VOID               *Context,
 | 
						|
  IN DEBUG_PORT_HANDLE  DebugPortHandle
 | 
						|
  )
 | 
						|
{
 | 
						|
  DEBUG_AGENT_PHASE2_CONTEXT  *Phase2Context;
 | 
						|
  UINT64                      *MailboxLocation;
 | 
						|
  DEBUG_AGENT_MAILBOX         *Mailbox;
 | 
						|
  EFI_SEC_PEI_HAND_OFF        *SecCoreData;
 | 
						|
  UINT16                      BufferSize;
 | 
						|
  UINT64                      NewDebugPortHandle;
 | 
						|
 | 
						|
  Phase2Context   = (DEBUG_AGENT_PHASE2_CONTEXT *)Context;
 | 
						|
  MailboxLocation = GetLocationSavedMailboxPointerInIdtEntry ();
 | 
						|
  Mailbox         = (DEBUG_AGENT_MAILBOX *)(UINTN)(*MailboxLocation);
 | 
						|
  BufferSize      = PcdGet16 (PcdDebugPortHandleBufferSize);
 | 
						|
  if ((Phase2Context->InitFlag == DEBUG_AGENT_INIT_PEI) && (BufferSize != 0)) {
 | 
						|
    NewDebugPortHandle = (UINT64)(UINTN)AllocateCopyPool (BufferSize, DebugPortHandle);
 | 
						|
  } else {
 | 
						|
    NewDebugPortHandle = (UINT64)(UINTN)DebugPortHandle;
 | 
						|
  }
 | 
						|
 | 
						|
  UpdateMailboxContent (Mailbox, DEBUG_MAILBOX_DEBUG_PORT_HANDLE_INDEX, NewDebugPortHandle);
 | 
						|
 | 
						|
  //
 | 
						|
  // Trigger one software interrupt to inform HOST
 | 
						|
  //
 | 
						|
  TriggerSoftInterrupt (SYSTEM_RESET_SIGNATURE);
 | 
						|
 | 
						|
  if (Phase2Context->InitFlag == DEBUG_AGENT_INIT_PREMEM_SEC) {
 | 
						|
    //
 | 
						|
    // If Temporary RAM region is below 128 MB, then send message to
 | 
						|
    // host to disable low memory filtering.
 | 
						|
    //
 | 
						|
    SecCoreData = (EFI_SEC_PEI_HAND_OFF *)Phase2Context->Context;
 | 
						|
    if (((UINTN)SecCoreData->TemporaryRamBase < BASE_128MB) && IsHostAttached ()) {
 | 
						|
      SetDebugFlag (DEBUG_AGENT_FLAG_MEMORY_READY, 1);
 | 
						|
      TriggerSoftInterrupt (MEMORY_READY_SIGNATURE);
 | 
						|
    }
 | 
						|
 | 
						|
    //
 | 
						|
    // Enable Debug Timer interrupt
 | 
						|
    //
 | 
						|
    SaveAndSetDebugTimerInterrupt (TRUE);
 | 
						|
    //
 | 
						|
    // Enable CPU interrupts so debug timer interrupts can be delivered
 | 
						|
    //
 | 
						|
    EnableInterrupts ();
 | 
						|
    //
 | 
						|
    // Call continuation function if it is not NULL.
 | 
						|
    //
 | 
						|
    Phase2Context->Function (Phase2Context->Context);
 | 
						|
  }
 | 
						|
}
 |