diff options
Diffstat (limited to 'SourceLevelDebugPkg/Library/DebugAgent/SecPeiDebugAgent/SecPeiDebugAgentLib.c')
| -rw-r--r-- | SourceLevelDebugPkg/Library/DebugAgent/SecPeiDebugAgent/SecPeiDebugAgentLib.c | 1442 |
1 files changed, 721 insertions, 721 deletions
diff --git a/SourceLevelDebugPkg/Library/DebugAgent/SecPeiDebugAgent/SecPeiDebugAgentLib.c b/SourceLevelDebugPkg/Library/DebugAgent/SecPeiDebugAgent/SecPeiDebugAgentLib.c index b32754fc2a..17bc21309c 100644 --- a/SourceLevelDebugPkg/Library/DebugAgent/SecPeiDebugAgent/SecPeiDebugAgentLib.c +++ b/SourceLevelDebugPkg/Library/DebugAgent/SecPeiDebugAgent/SecPeiDebugAgentLib.c @@ -1,721 +1,721 @@ -/** @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);
- }
-}
+/** @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); + } +} |
