git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@3 6f19259b-4bc3-4df7-8a09-765794883524
		
			
				
	
	
		
			499 lines
		
	
	
		
			17 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			499 lines
		
	
	
		
			17 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/*++
 | 
						|
 | 
						|
Copyright (c) 2006, Intel Corporation                                                         
 | 
						|
All rights reserved. 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.             
 | 
						|
 | 
						|
Module Name:
 | 
						|
  
 | 
						|
  MemoryStatusCode.c
 | 
						|
   
 | 
						|
Abstract:
 | 
						|
 | 
						|
  Lib to provide memory journal status code reporting Routines.
 | 
						|
 | 
						|
--*/
 | 
						|
#include "MemoryStatusCode.h"
 | 
						|
 | 
						|
//
 | 
						|
// Global variable.  Not accessible while running from flash.
 | 
						|
// After we relocate ourselves into memory, we update this
 | 
						|
// and use it to determine if we are running from flash or memory.
 | 
						|
//
 | 
						|
 | 
						|
//
 | 
						|
// Global variable used to replace the PPI once we start running from memory.
 | 
						|
//
 | 
						|
PEI_STATUS_CODE_MEMORY_PPI    mStatusCodeMemoryPpi = { 0, 0, 0, 0 };
 | 
						|
 | 
						|
//
 | 
						|
// PPI descriptor for the MonoStatusCode PEIM, see MonoStatusCode.c
 | 
						|
//
 | 
						|
extern EFI_PEI_PPI_DESCRIPTOR mPpiListStatusCode;
 | 
						|
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
MemoryStatusCodeInitialize (
 | 
						|
  IN EFI_FFS_FILE_HEADER       *FfsHeader,
 | 
						|
  IN EFI_PEI_SERVICES          **PeiServices
 | 
						|
  )
 | 
						|
/*++
 | 
						|
 | 
						|
Routine Description:
 | 
						|
 | 
						|
  Initialization routine.
 | 
						|
  Allocates heap space for storing Status Codes.
 | 
						|
  Installs a PPI to point to that heap space.
 | 
						|
  Installs a callback to switch to memory.
 | 
						|
  Installs a callback to 
 | 
						|
 | 
						|
Arguments: 
 | 
						|
 | 
						|
  FfsHeader   - FV this PEIM was loaded from.
 | 
						|
  PeiServices - General purpose services available to every PEIM.
 | 
						|
 | 
						|
Returns: 
 | 
						|
 | 
						|
  None
 | 
						|
 | 
						|
--*/
 | 
						|
{
 | 
						|
  EFI_STATUS                  Status;
 | 
						|
  MEMORY_STATUS_CODE_INSTANCE *PrivateData;
 | 
						|
  PEI_STATUS_CODE_MEMORY_PPI  *StatusCodeMemoryPpi;
 | 
						|
  EFI_PEI_PROGRESS_CODE_PPI   *ReportStatusCodePpi;
 | 
						|
  EFI_PHYSICAL_ADDRESS        Buffer;
 | 
						|
  VOID                        *StartPointer;
 | 
						|
  UINTN                       Length;
 | 
						|
  UINTN                       LastEntry;
 | 
						|
  EFI_PEI_PPI_DESCRIPTOR      *ReportStatusCodeDescriptor;
 | 
						|
  EFI_PEI_PPI_DESCRIPTOR      *StatusCodeMemoryDescriptor;
 | 
						|
 | 
						|
  //
 | 
						|
  // Determine if we are being called after relocation into memory.
 | 
						|
  //
 | 
						|
  if (!gRunningFromMemory) {
 | 
						|
    //
 | 
						|
    // If we are not running from memory, we need to allocate some heap and
 | 
						|
    // install the PPI
 | 
						|
    //
 | 
						|
    //
 | 
						|
    // Allocate heap storage for the journal
 | 
						|
    //
 | 
						|
    Status = (*PeiServices)->AllocatePool (
 | 
						|
                              PeiServices,
 | 
						|
                              PEI_STATUS_CODE_HEAP_LENGTH,
 | 
						|
                              &StartPointer
 | 
						|
                              );
 | 
						|
 | 
						|
    //
 | 
						|
    // This is not a required feature to boot.
 | 
						|
    //
 | 
						|
    if (EFI_ERROR (Status)) {
 | 
						|
      return Status;
 | 
						|
    }
 | 
						|
    //
 | 
						|
    // Allocate heap storage for private data
 | 
						|
    // The private data contains the FFS header for this PEIM,
 | 
						|
    // a PPI containing information about the status code journal, and
 | 
						|
    // a notification for the LoadFile service, to relocate the PEIM into
 | 
						|
    // memory.
 | 
						|
    //
 | 
						|
    Status = (*PeiServices)->AllocatePool (
 | 
						|
                              PeiServices,
 | 
						|
                              sizeof (MEMORY_STATUS_CODE_INSTANCE),
 | 
						|
                              (VOID **) &PrivateData
 | 
						|
                              );
 | 
						|
 | 
						|
    //
 | 
						|
    // This is not a required feature to boot.
 | 
						|
    //
 | 
						|
    if (EFI_ERROR (Status)) {
 | 
						|
      return Status;
 | 
						|
    }
 | 
						|
    //
 | 
						|
    // Update the contents of the private data.
 | 
						|
    //
 | 
						|
    PrivateData->Signature                      = MEMORY_STATUS_CODE_SIGNATURE;
 | 
						|
    PrivateData->This = PrivateData;
 | 
						|
    PrivateData->FfsHeader = FfsHeader;
 | 
						|
    PrivateData->PpiDescriptor.Flags = (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST);
 | 
						|
    PrivateData->PpiDescriptor.Guid = &gPeiStatusCodeMemoryPpiGuid;
 | 
						|
    PrivateData->PpiDescriptor.Ppi = &PrivateData->StatusCodeMemoryPpi;
 | 
						|
    PrivateData->StatusCodeMemoryPpi.FirstEntry = 0;
 | 
						|
    PrivateData->StatusCodeMemoryPpi.LastEntry = 0;
 | 
						|
    PrivateData->StatusCodeMemoryPpi.Address = (EFI_PHYSICAL_ADDRESS) (UINTN) StartPointer;
 | 
						|
    PrivateData->StatusCodeMemoryPpi.Length = PEI_STATUS_CODE_HEAP_LENGTH;
 | 
						|
    PrivateData->NotifyDescriptor.Flags =
 | 
						|
      (
 | 
						|
        EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK |
 | 
						|
        EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST
 | 
						|
      );
 | 
						|
    PrivateData->NotifyDescriptor.Guid    = &gEfiPeiFvFileLoaderPpiGuid;
 | 
						|
    PrivateData->NotifyDescriptor.Notify  = LoadImageCallback;
 | 
						|
 | 
						|
    //
 | 
						|
    // Publish the PPI
 | 
						|
    //
 | 
						|
    Status = (*PeiServices)->InstallPpi (PeiServices, &PrivateData->PpiDescriptor);
 | 
						|
    if (EFI_ERROR (Status)) {
 | 
						|
      return Status;
 | 
						|
    }
 | 
						|
    //
 | 
						|
    // Post a callback to relocate to memory
 | 
						|
    //
 | 
						|
    Status = (**PeiServices).NotifyPpi (PeiServices, &PrivateData->NotifyDescriptor);
 | 
						|
    if (EFI_ERROR (Status)) {
 | 
						|
      return Status;
 | 
						|
    }
 | 
						|
  } else {
 | 
						|
    //
 | 
						|
    // If we are running from memory, we need to copy from the heap to a RT
 | 
						|
    // memory buffer.
 | 
						|
    //
 | 
						|
    //
 | 
						|
    // Locate Journal
 | 
						|
    //
 | 
						|
    Status = (*PeiServices)->LocatePpi (
 | 
						|
                              PeiServices,
 | 
						|
                              &gPeiStatusCodeMemoryPpiGuid,
 | 
						|
                              0,
 | 
						|
                              &StatusCodeMemoryDescriptor,
 | 
						|
                              (VOID **) &StatusCodeMemoryPpi
 | 
						|
                              );
 | 
						|
    if (EFI_ERROR (Status)) {
 | 
						|
      return Status;
 | 
						|
    }
 | 
						|
    //
 | 
						|
    // Get private data
 | 
						|
    //
 | 
						|
    PrivateData = _CR (StatusCodeMemoryDescriptor, MEMORY_STATUS_CODE_INSTANCE, PpiDescriptor);
 | 
						|
    //
 | 
						|
    // At this point, we need to fix up any addresses that we have as the heap
 | 
						|
    // has moved.
 | 
						|
    //
 | 
						|
    PrivateData->PpiDescriptor.Ppi  = &PrivateData->StatusCodeMemoryPpi;
 | 
						|
    PrivateData->PpiDescriptor.Guid = &gPeiStatusCodeMemoryPpiGuid;
 | 
						|
    PrivateData->StatusCodeMemoryPpi.Address = PrivateData->StatusCodeMemoryPpi.Address +
 | 
						|
      (UINTN) PrivateData - (UINTN) PrivateData->This;
 | 
						|
    PrivateData->NotifyDescriptor.Guid    = &gEfiPeiFvFileLoaderPpiGuid;
 | 
						|
    PrivateData->NotifyDescriptor.Notify  = LoadImageCallback;
 | 
						|
    PrivateData->This                     = PrivateData;
 | 
						|
 | 
						|
    //
 | 
						|
    // Allocate RT memory.
 | 
						|
    //
 | 
						|
    Status = (*PeiServices)->AllocatePages (
 | 
						|
                              PeiServices,
 | 
						|
                              EfiRuntimeServicesData,
 | 
						|
                              PEI_STATUS_CODE_RT_PAGES,
 | 
						|
                              &Buffer
 | 
						|
                              );
 | 
						|
    if (EFI_ERROR (Status)) {
 | 
						|
      return Status;
 | 
						|
    }
 | 
						|
 | 
						|
    DEBUG_CODE (
 | 
						|
      ZeroMem ((VOID *) (UINTN) Buffer, PEI_STATUS_CODE_RT_LENGTH);
 | 
						|
    );
 | 
						|
 | 
						|
    //
 | 
						|
    // Copy the heap to the allocated memory.
 | 
						|
    // Unwind the rolling queue to start at 0 in the new space.  We need to do
 | 
						|
    // this because the new queue is much bigger than the heap allocation.
 | 
						|
    //
 | 
						|
    if (PEI_STATUS_CODE_RT_LENGTH <= PEI_STATUS_CODE_HEAP_LENGTH) {
 | 
						|
      return Status;
 | 
						|
    }
 | 
						|
 | 
						|
    if (StatusCodeMemoryPpi->LastEntry >= StatusCodeMemoryPpi->FirstEntry) {
 | 
						|
      LastEntry = StatusCodeMemoryPpi->LastEntry - StatusCodeMemoryPpi->FirstEntry;
 | 
						|
      StartPointer = (VOID *) ((UINTN) StatusCodeMemoryPpi->Address + (StatusCodeMemoryPpi->FirstEntry * sizeof (EFI_STATUS_CODE_ENTRY)));
 | 
						|
      Length = (StatusCodeMemoryPpi->LastEntry - StatusCodeMemoryPpi->FirstEntry) * sizeof (EFI_STATUS_CODE_ENTRY);
 | 
						|
      (*PeiServices)->CopyMem ((VOID *) (UINTN) Buffer, StartPointer, Length);
 | 
						|
    } else {
 | 
						|
      //
 | 
						|
      // The last entry will be the new last entry after moving heap to buffer
 | 
						|
      //
 | 
						|
      LastEntry = (PEI_STATUS_CODE_MAX_HEAP_ENTRY - StatusCodeMemoryPpi->FirstEntry) + StatusCodeMemoryPpi->LastEntry;
 | 
						|
      //
 | 
						|
      // Copy from the first entry to the end of the heap
 | 
						|
      //
 | 
						|
      StartPointer = (VOID *) ((UINTN) StatusCodeMemoryPpi->Address + (StatusCodeMemoryPpi->FirstEntry * sizeof (EFI_STATUS_CODE_ENTRY)));
 | 
						|
      Length = PEI_STATUS_CODE_HEAP_LENGTH - (StatusCodeMemoryPpi->FirstEntry * sizeof (EFI_STATUS_CODE_ENTRY));
 | 
						|
      (*PeiServices)->CopyMem ((VOID *) (UINTN) Buffer, StartPointer, Length);
 | 
						|
      //
 | 
						|
      // Copy from the start to the heap to the last entry
 | 
						|
      //
 | 
						|
      StartPointer = (VOID *) (UINTN) StatusCodeMemoryPpi->Address;
 | 
						|
      (*PeiServices)->CopyMem (
 | 
						|
                        (VOID *) (UINTN) (Buffer + Length),
 | 
						|
                        StartPointer,
 | 
						|
                        (StatusCodeMemoryPpi->LastEntry * sizeof (EFI_STATUS_CODE_ENTRY))
 | 
						|
                        );
 | 
						|
    };
 | 
						|
 | 
						|
    //
 | 
						|
    // Update the PPI to NULL, so it will not be used.
 | 
						|
    //
 | 
						|
    StatusCodeMemoryPpi->FirstEntry = 0;
 | 
						|
    StatusCodeMemoryPpi->LastEntry  = 0;
 | 
						|
    StatusCodeMemoryPpi->Address    = 0;
 | 
						|
    StatusCodeMemoryPpi->Length     = 0;
 | 
						|
 | 
						|
    //
 | 
						|
    // Update in memory version of PPI that will be used.
 | 
						|
    //
 | 
						|
    mStatusCodeMemoryPpi.FirstEntry = 0;
 | 
						|
    mStatusCodeMemoryPpi.LastEntry  = LastEntry;
 | 
						|
    mStatusCodeMemoryPpi.Address    = (EFI_PHYSICAL_ADDRESS) (UINTN) Buffer;
 | 
						|
    mStatusCodeMemoryPpi.Length     = PEI_STATUS_CODE_RT_LENGTH;
 | 
						|
 | 
						|
    //
 | 
						|
    // Reinstall the report status code function
 | 
						|
    //
 | 
						|
    //
 | 
						|
    // Locate status code PPI
 | 
						|
    //
 | 
						|
    Status = (*PeiServices)->LocatePpi (
 | 
						|
                              PeiServices,
 | 
						|
                              &gEfiPeiStatusCodePpiGuid,
 | 
						|
                              0,
 | 
						|
                              &ReportStatusCodeDescriptor,
 | 
						|
                              (VOID **) &ReportStatusCodePpi
 | 
						|
                              );
 | 
						|
    if (EFI_ERROR (Status)) {
 | 
						|
      return Status;
 | 
						|
    }
 | 
						|
    //
 | 
						|
    // Reinstall the ReportStatusCode interface using the memory-based
 | 
						|
    // descriptor
 | 
						|
    //
 | 
						|
    Status = (*PeiServices)->ReInstallPpi (
 | 
						|
                              PeiServices,
 | 
						|
                              ReportStatusCodeDescriptor,
 | 
						|
                              &mPpiListStatusCode
 | 
						|
                              );
 | 
						|
    if (EFI_ERROR (Status)) {
 | 
						|
      CpuBreakpoint ();
 | 
						|
      return Status;
 | 
						|
    }
 | 
						|
    //
 | 
						|
    // Publish a GUIDed HOB that contains a pointer to the status code PPI
 | 
						|
    // structure.  This is a bit of a short cut as I just used the PPI GUID to
 | 
						|
    // identify the HOB.  This HOB is caught by the DXE status code memory
 | 
						|
    // listener and used to find the journal.
 | 
						|
    //
 | 
						|
    StatusCodeMemoryPpi = &mStatusCodeMemoryPpi;
 | 
						|
 | 
						|
    BuildGuidDataHob (
 | 
						|
      &gPeiStatusCodeMemoryPpiGuid,
 | 
						|
      &StatusCodeMemoryPpi,
 | 
						|
      sizeof (VOID *)
 | 
						|
      );
 | 
						|
  }
 | 
						|
  return EFI_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
EFI_STATUS
 | 
						|
MemoryReportStatusCode (
 | 
						|
  IN EFI_STATUS_CODE_TYPE     CodeType,
 | 
						|
  IN EFI_STATUS_CODE_VALUE    Value,
 | 
						|
  IN UINT32                   Instance,
 | 
						|
  IN EFI_GUID                 * CallerId,
 | 
						|
  IN EFI_STATUS_CODE_DATA     * Data OPTIONAL
 | 
						|
  )
 | 
						|
/*++
 | 
						|
 | 
						|
Routine Description:
 | 
						|
 | 
						|
  Provide a memory status code
 | 
						|
 | 
						|
Arguments:
 | 
						|
 | 
						|
  Same as ReportStatusCode PPI
 | 
						|
    
 | 
						|
Returns:
 | 
						|
 | 
						|
  EFI_SUCCESS   This function always returns success
 | 
						|
 | 
						|
--*/
 | 
						|
{
 | 
						|
  EFI_STATUS                  Status;
 | 
						|
  PEI_STATUS_CODE_MEMORY_PPI  *StatusCodeMemoryPpi;
 | 
						|
  EFI_STATUS_CODE_ENTRY       *CurrentEntry;
 | 
						|
  UINTN                       LastEntry;
 | 
						|
  MEMORY_STATUS_CODE_INSTANCE *PrivateData;
 | 
						|
  EFI_PEI_PPI_DESCRIPTOR      *StatusCodeMemoryDescriptor;
 | 
						|
  EFI_PEI_SERVICES            **PeiServices;
 | 
						|
 | 
						|
  PeiServices = GetPeiServicesTablePointer ();
 | 
						|
  //
 | 
						|
  // We don't care to log debug codes.
 | 
						|
  //
 | 
						|
  if ((CodeType & EFI_STATUS_CODE_TYPE_MASK) == EFI_DEBUG_CODE) {
 | 
						|
    return EFI_SUCCESS;
 | 
						|
  }
 | 
						|
 | 
						|
  if (!gRunningFromMemory) {
 | 
						|
    //
 | 
						|
    // If we are called from DXE and have not been reinstalled into memory, we
 | 
						|
    // can no longer locate the journal, so we can no longer log status codes.
 | 
						|
    //
 | 
						|
    if (!PeiServices) {
 | 
						|
      return EFI_SUCCESS;
 | 
						|
    }
 | 
						|
    //
 | 
						|
    // Locate Journal
 | 
						|
    //
 | 
						|
    Status = (*PeiServices)->LocatePpi (
 | 
						|
                              PeiServices,
 | 
						|
                              &gPeiStatusCodeMemoryPpiGuid,
 | 
						|
                              0,
 | 
						|
                              &StatusCodeMemoryDescriptor,
 | 
						|
                              (VOID **) &StatusCodeMemoryPpi
 | 
						|
                              );
 | 
						|
    if (EFI_ERROR (Status)) {
 | 
						|
      return EFI_SUCCESS;
 | 
						|
    }
 | 
						|
    //
 | 
						|
    // Determine the last entry in the journal.
 | 
						|
    // This is needed to properly implement the rolling queue.
 | 
						|
    //
 | 
						|
    LastEntry = PEI_STATUS_CODE_MAX_HEAP_ENTRY;
 | 
						|
 | 
						|
    //
 | 
						|
    // Get private data
 | 
						|
    //
 | 
						|
    PrivateData = _CR (StatusCodeMemoryDescriptor, MEMORY_STATUS_CODE_INSTANCE, PpiDescriptor);
 | 
						|
 | 
						|
    //
 | 
						|
    // Once memory gets installed, heap gets moved to real memory.
 | 
						|
    // We need to fix up the pointers to match the move.
 | 
						|
    //
 | 
						|
    PrivateData->PpiDescriptor.Ppi  = &PrivateData->StatusCodeMemoryPpi;
 | 
						|
    PrivateData->PpiDescriptor.Guid = &gPeiStatusCodeMemoryPpiGuid;
 | 
						|
    PrivateData->StatusCodeMemoryPpi.Address = PrivateData->StatusCodeMemoryPpi.Address +
 | 
						|
      (UINTN) PrivateData - (UINTN) PrivateData->This;
 | 
						|
    PrivateData->NotifyDescriptor.Guid    = &gEfiPeiFvFileLoaderPpiGuid;
 | 
						|
    PrivateData->NotifyDescriptor.Notify  = LoadImageCallback;
 | 
						|
    PrivateData->This                     = PrivateData;
 | 
						|
 | 
						|
    StatusCodeMemoryPpi                   = PrivateData->PpiDescriptor.Ppi;
 | 
						|
  } else {
 | 
						|
    //
 | 
						|
    // Use global/memory copy of the PPI
 | 
						|
    //
 | 
						|
    StatusCodeMemoryPpi = &mStatusCodeMemoryPpi;
 | 
						|
 | 
						|
    //
 | 
						|
    // Determine the last entry in the journal.
 | 
						|
    // This is needed to properly implement the rolling queue.
 | 
						|
    //
 | 
						|
    LastEntry = PEI_STATUS_CODE_MAX_RT_ENTRY;
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // Return if we are using a cleared PPI somehow
 | 
						|
  //
 | 
						|
  if (!StatusCodeMemoryPpi->Address || !StatusCodeMemoryPpi->Length) {
 | 
						|
    return EFI_SUCCESS;
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // Update the latest entry in the journal (may actually be first due to rolling
 | 
						|
  // queue).
 | 
						|
  //
 | 
						|
  CurrentEntry = (EFI_STATUS_CODE_ENTRY *) (UINTN) (StatusCodeMemoryPpi->Address + (StatusCodeMemoryPpi->LastEntry * sizeof (EFI_STATUS_CODE_ENTRY)));
 | 
						|
 | 
						|
  StatusCodeMemoryPpi->LastEntry = (StatusCodeMemoryPpi->LastEntry + 1) % LastEntry;
 | 
						|
  if (StatusCodeMemoryPpi->LastEntry == StatusCodeMemoryPpi->FirstEntry) {
 | 
						|
    StatusCodeMemoryPpi->FirstEntry = (StatusCodeMemoryPpi->FirstEntry + 1) % LastEntry;
 | 
						|
  }
 | 
						|
 | 
						|
  CurrentEntry->Type      = CodeType;
 | 
						|
  CurrentEntry->Value     = Value;
 | 
						|
  CurrentEntry->Instance  = Instance;
 | 
						|
 | 
						|
  return EFI_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
LoadImageCallback (
 | 
						|
  IN EFI_PEI_SERVICES           **PeiServices,
 | 
						|
  IN EFI_PEI_NOTIFY_DESCRIPTOR  *NotifyDescriptor,
 | 
						|
  IN VOID                       *Ppi
 | 
						|
  )
 | 
						|
/*++
 | 
						|
 | 
						|
Routine Description:
 | 
						|
 | 
						|
  Relocate the PEIM into memory.
 | 
						|
 | 
						|
  Once load protocol becomes available, relocate our PEIM into memory.
 | 
						|
  The primary benefit is to eliminate the blackout window that we would have in
 | 
						|
  the memory log between the end of PEI and the status code DXE driver taking
 | 
						|
  control.  If we don't do this, we cannot determine where our memory journal
 | 
						|
  is located and cannot function.
 | 
						|
 | 
						|
  A second benefit is speed optimization throughout DXE.
 | 
						|
 | 
						|
Arguments:
 | 
						|
 | 
						|
  PeiServices      - General purpose services available to every PEIM.
 | 
						|
  NotifyDescriptor - Information about the notify event.
 | 
						|
  Ppi              - Context
 | 
						|
    
 | 
						|
Returns:
 | 
						|
 | 
						|
  EFI_SUCCESS   This function always returns success.
 | 
						|
 | 
						|
--*/
 | 
						|
{
 | 
						|
  EFI_STATUS                  Status;
 | 
						|
  EFI_PHYSICAL_ADDRESS        ImageAddress;
 | 
						|
  EFI_PHYSICAL_ADDRESS        EntryPoint;
 | 
						|
  UINT64                      ImageSize;
 | 
						|
  MEMORY_STATUS_CODE_INSTANCE *PrivateData;
 | 
						|
 | 
						|
  //
 | 
						|
  // Relocate to memory
 | 
						|
  //
 | 
						|
  if (!gRunningFromMemory) {
 | 
						|
    //
 | 
						|
    // Use the callback descriptor to get the FfsHeader
 | 
						|
    //
 | 
						|
    PrivateData = _CR (NotifyDescriptor, MEMORY_STATUS_CODE_INSTANCE, NotifyDescriptor);
 | 
						|
 | 
						|
    Status = ((EFI_PEI_FV_FILE_LOADER_PPI *) Ppi)->FvLoadFile (
 | 
						|
                                                    Ppi,
 | 
						|
                                                    PrivateData->FfsHeader,
 | 
						|
                                                    &ImageAddress,
 | 
						|
                                                    &ImageSize,
 | 
						|
                                                    &EntryPoint
 | 
						|
                                                    );
 | 
						|
    if (EFI_ERROR (Status)) {
 | 
						|
      return EFI_SUCCESS;
 | 
						|
    }
 | 
						|
    //
 | 
						|
    // Set the flag in the loaded image that indicates the PEIM is executing
 | 
						|
    // from memory.
 | 
						|
    //
 | 
						|
#ifdef EFI_NT_EMULATOR
 | 
						|
    gRunningFromMemory = TRUE;
 | 
						|
#else
 | 
						|
    * (BOOLEAN *) ((UINTN) &gRunningFromMemory + (UINTN) EntryPoint - (UINTN) InstallMonoStatusCode) = TRUE;
 | 
						|
#endif
 | 
						|
    Status = ((EFI_PEIM_ENTRY_POINT )(UINTN) EntryPoint) (PrivateData->FfsHeader, PeiServices);
 | 
						|
    if (EFI_ERROR (Status)) {
 | 
						|
      return EFI_SUCCESS;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  return EFI_SUCCESS;
 | 
						|
}
 |