REF: https://bugzilla.tianocore.org/show_bug.cgi?id=3737 Apply uncrustify changes to .c/.h files in the EmulatorPkg 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: Ray Ni <ray.ni@intel.com>
		
			
				
	
	
		
			1115 lines
		
	
	
		
			31 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			1115 lines
		
	
	
		
			31 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/**@file
 | 
						|
  WinNt emulator of pre-SEC phase. It's really a Win32 application, but this is
 | 
						|
  Ok since all the other modules for NT32 are NOT Win32 applications.
 | 
						|
 | 
						|
  This program gets NT32 PCD setting and figures out what the memory layout
 | 
						|
  will be, how may FD's will be loaded and also what the boot mode is.
 | 
						|
 | 
						|
  This code produces 128 K of temporary memory for the SEC stack by directly
 | 
						|
  allocate memory space with ReadWrite and Execute attribute.
 | 
						|
 | 
						|
Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
 | 
						|
(C) Copyright 2016-2020 Hewlett Packard Enterprise Development LP<BR>
 | 
						|
SPDX-License-Identifier: BSD-2-Clause-Patent
 | 
						|
**/
 | 
						|
 | 
						|
#include "WinHost.h"
 | 
						|
 | 
						|
#ifndef SE_TIME_ZONE_NAME
 | 
						|
#define SE_TIME_ZONE_NAME  TEXT("SeTimeZonePrivilege")
 | 
						|
#endif
 | 
						|
 | 
						|
//
 | 
						|
// The growth size for array of module handle entries
 | 
						|
//
 | 
						|
#define MAX_PDB_NAME_TO_MOD_HANDLE_ARRAY_SIZE  0x100
 | 
						|
 | 
						|
//
 | 
						|
// Module handle entry structure
 | 
						|
//
 | 
						|
typedef struct {
 | 
						|
  CHAR8    *PdbPointer;
 | 
						|
  VOID     *ModHandle;
 | 
						|
} PDB_NAME_TO_MOD_HANDLE;
 | 
						|
 | 
						|
//
 | 
						|
// An Array to hold the module handles
 | 
						|
//
 | 
						|
PDB_NAME_TO_MOD_HANDLE  *mPdbNameModHandleArray    = NULL;
 | 
						|
UINTN                   mPdbNameModHandleArraySize = 0;
 | 
						|
 | 
						|
//
 | 
						|
// Default information about where the FD is located.
 | 
						|
//  This array gets filled in with information from PcdWinNtFirmwareVolume
 | 
						|
//  The number of array elements is allocated base on parsing
 | 
						|
//  PcdWinNtFirmwareVolume and the memory is never freed.
 | 
						|
//
 | 
						|
UINTN       gFdInfoCount = 0;
 | 
						|
NT_FD_INFO  *gFdInfo;
 | 
						|
 | 
						|
//
 | 
						|
// Array that supports separate memory ranges.
 | 
						|
//  The memory ranges are set by PcdWinNtMemorySizeForSecMain.
 | 
						|
//  The number of array elements is allocated base on parsing
 | 
						|
//  PcdWinNtMemorySizeForSecMain value and the memory is never freed.
 | 
						|
//
 | 
						|
UINTN             gSystemMemoryCount = 0;
 | 
						|
NT_SYSTEM_MEMORY  *gSystemMemory;
 | 
						|
 | 
						|
/*++
 | 
						|
 | 
						|
Routine Description:
 | 
						|
  This service is called from Index == 0 until it returns EFI_UNSUPPORTED.
 | 
						|
  It allows discontinuous memory regions to be supported by the emulator.
 | 
						|
  It uses gSystemMemory[] and gSystemMemoryCount that were created by
 | 
						|
  parsing the host environment variable EFI_MEMORY_SIZE.
 | 
						|
  The size comes from the varaible and the address comes from the call to
 | 
						|
  UnixOpenFile.
 | 
						|
 | 
						|
Arguments:
 | 
						|
  Index      - Which memory region to use
 | 
						|
  MemoryBase - Return Base address of memory region
 | 
						|
  MemorySize - Return size in bytes of the memory region
 | 
						|
 | 
						|
Returns:
 | 
						|
  EFI_SUCCESS - If memory region was mapped
 | 
						|
  EFI_UNSUPPORTED - If Index is not supported
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
WinPeiAutoScan (
 | 
						|
  IN  UINTN                 Index,
 | 
						|
  OUT EFI_PHYSICAL_ADDRESS  *MemoryBase,
 | 
						|
  OUT UINT64                *MemorySize
 | 
						|
  )
 | 
						|
{
 | 
						|
  if (Index >= gSystemMemoryCount) {
 | 
						|
    return EFI_UNSUPPORTED;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Allocate enough memory space for emulator
 | 
						|
  //
 | 
						|
  gSystemMemory[Index].Memory = (EFI_PHYSICAL_ADDRESS)(UINTN)VirtualAlloc (NULL, (SIZE_T)(gSystemMemory[Index].Size), MEM_COMMIT, PAGE_EXECUTE_READWRITE);
 | 
						|
  if (gSystemMemory[Index].Memory == 0) {
 | 
						|
    return EFI_OUT_OF_RESOURCES;
 | 
						|
  }
 | 
						|
 | 
						|
  *MemoryBase = gSystemMemory[Index].Memory;
 | 
						|
  *MemorySize = gSystemMemory[Index].Size;
 | 
						|
 | 
						|
  return EFI_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
/*++
 | 
						|
 | 
						|
Routine Description:
 | 
						|
  Return the FD Size and base address. Since the FD is loaded from a
 | 
						|
  file into host memory only the SEC will know its address.
 | 
						|
 | 
						|
Arguments:
 | 
						|
  Index  - Which FD, starts at zero.
 | 
						|
  FdSize - Size of the FD in bytes
 | 
						|
  FdBase - Start address of the FD. Assume it points to an FV Header
 | 
						|
  FixUp  - Difference between actual FD address and build address
 | 
						|
 | 
						|
Returns:
 | 
						|
  EFI_SUCCESS     - Return the Base address and size of the FV
 | 
						|
  EFI_UNSUPPORTED - Index does nto map to an FD in the system
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
WinFdAddress (
 | 
						|
  IN     UINTN                 Index,
 | 
						|
  IN OUT EFI_PHYSICAL_ADDRESS  *FdBase,
 | 
						|
  IN OUT UINT64                *FdSize,
 | 
						|
  IN OUT EFI_PHYSICAL_ADDRESS  *FixUp
 | 
						|
  )
 | 
						|
{
 | 
						|
  if (Index >= gFdInfoCount) {
 | 
						|
    return EFI_UNSUPPORTED;
 | 
						|
  }
 | 
						|
 | 
						|
  *FdBase = (EFI_PHYSICAL_ADDRESS)(UINTN)gFdInfo[Index].Address;
 | 
						|
  *FdSize = (UINT64)gFdInfo[Index].Size;
 | 
						|
  *FixUp  = 0;
 | 
						|
 | 
						|
  if ((*FdBase == 0) && (*FdSize == 0)) {
 | 
						|
    return EFI_UNSUPPORTED;
 | 
						|
  }
 | 
						|
 | 
						|
  if (Index == 0) {
 | 
						|
    //
 | 
						|
    // FD 0 has XIP code and well known PCD values
 | 
						|
    // If the memory buffer could not be allocated at the FD build address
 | 
						|
    // the Fixup is the difference.
 | 
						|
    //
 | 
						|
    *FixUp = *FdBase - PcdGet64 (PcdEmuFdBaseAddress);
 | 
						|
  }
 | 
						|
 | 
						|
  return EFI_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
/*++
 | 
						|
 | 
						|
Routine Description:
 | 
						|
  Since the SEC is the only Unix program in stack it must export
 | 
						|
  an interface to do POSIX calls.  gUnix is initialized in UnixThunk.c.
 | 
						|
 | 
						|
Arguments:
 | 
						|
  InterfaceSize - sizeof (EFI_WIN_NT_THUNK_PROTOCOL);
 | 
						|
  InterfaceBase - Address of the gUnix global
 | 
						|
 | 
						|
Returns:
 | 
						|
  EFI_SUCCESS - Data returned
 | 
						|
 | 
						|
**/
 | 
						|
VOID *
 | 
						|
WinThunk (
 | 
						|
  VOID
 | 
						|
  )
 | 
						|
{
 | 
						|
  return &gEmuThunkProtocol;
 | 
						|
}
 | 
						|
 | 
						|
EMU_THUNK_PPI  mSecEmuThunkPpi = {
 | 
						|
  WinPeiAutoScan,
 | 
						|
  WinFdAddress,
 | 
						|
  WinThunk
 | 
						|
};
 | 
						|
 | 
						|
VOID
 | 
						|
SecPrint (
 | 
						|
  CHAR8  *Format,
 | 
						|
  ...
 | 
						|
  )
 | 
						|
{
 | 
						|
  va_list  Marker;
 | 
						|
  UINTN    CharCount;
 | 
						|
  CHAR8    Buffer[0x1000];
 | 
						|
 | 
						|
  va_start (Marker, Format);
 | 
						|
 | 
						|
  _vsnprintf (Buffer, sizeof (Buffer), Format, Marker);
 | 
						|
 | 
						|
  va_end (Marker);
 | 
						|
 | 
						|
  CharCount = strlen (Buffer);
 | 
						|
  WriteFile (
 | 
						|
    GetStdHandle (STD_OUTPUT_HANDLE),
 | 
						|
    Buffer,
 | 
						|
    (DWORD)CharCount,
 | 
						|
    (LPDWORD)&CharCount,
 | 
						|
    NULL
 | 
						|
    );
 | 
						|
}
 | 
						|
 | 
						|
/*++
 | 
						|
 | 
						|
Routine Description:
 | 
						|
 Check to see if an address range is in the EFI GCD memory map.
 | 
						|
 | 
						|
 This is all of GCD for system memory passed to DXE Core. FV
 | 
						|
 mapping and other device mapped into system memory are not
 | 
						|
 inlcuded in the check.
 | 
						|
 | 
						|
Arguments:
 | 
						|
  Index      - Which memory region to use
 | 
						|
  MemoryBase - Return Base address of memory region
 | 
						|
  MemorySize - Return size in bytes of the memory region
 | 
						|
 | 
						|
Returns:
 | 
						|
  TRUE -  Address is in the EFI GCD memory map
 | 
						|
  FALSE - Address is NOT in memory map
 | 
						|
 | 
						|
**/
 | 
						|
BOOLEAN
 | 
						|
EfiSystemMemoryRange (
 | 
						|
  IN  VOID  *MemoryAddress
 | 
						|
  )
 | 
						|
{
 | 
						|
  UINTN                 Index;
 | 
						|
  EFI_PHYSICAL_ADDRESS  MemoryBase;
 | 
						|
 | 
						|
  MemoryBase = (EFI_PHYSICAL_ADDRESS)(UINTN)MemoryAddress;
 | 
						|
  for (Index = 0; Index < gSystemMemoryCount; Index++) {
 | 
						|
    if ((MemoryBase >= gSystemMemory[Index].Memory) &&
 | 
						|
        (MemoryBase < (gSystemMemory[Index].Memory + gSystemMemory[Index].Size)))
 | 
						|
    {
 | 
						|
      return TRUE;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  return FALSE;
 | 
						|
}
 | 
						|
 | 
						|
EFI_STATUS
 | 
						|
WinNtOpenFile (
 | 
						|
  IN  CHAR16    *FileName             OPTIONAL,
 | 
						|
  IN  UINT32    MapSize,
 | 
						|
  IN  DWORD     CreationDisposition,
 | 
						|
  IN OUT  VOID  **BaseAddress,
 | 
						|
  OUT UINTN     *Length
 | 
						|
  )
 | 
						|
 | 
						|
/*++
 | 
						|
 | 
						|
Routine Description:
 | 
						|
  Opens and memory maps a file using WinNt services. If *BaseAddress is non zero
 | 
						|
  the process will try and allocate the memory starting at BaseAddress.
 | 
						|
 | 
						|
Arguments:
 | 
						|
  FileName            - The name of the file to open and map
 | 
						|
  MapSize             - The amount of the file to map in bytes
 | 
						|
  CreationDisposition - The flags to pass to CreateFile().  Use to create new files for
 | 
						|
                        memory emulation, and exiting files for firmware volume emulation
 | 
						|
  BaseAddress         - The base address of the mapped file in the user address space.
 | 
						|
                         If *BaseAddress is 0, the new memory region is used.
 | 
						|
                         If *BaseAddress is not 0, the request memory region is used for
 | 
						|
                          the mapping of the file into the process space.
 | 
						|
  Length              - The size of the mapped region in bytes
 | 
						|
 | 
						|
Returns:
 | 
						|
  EFI_SUCCESS      - The file was opened and mapped.
 | 
						|
  EFI_NOT_FOUND    - FileName was not found in the current directory
 | 
						|
  EFI_DEVICE_ERROR - An error occurred attempting to map the opened file
 | 
						|
 | 
						|
--*/
 | 
						|
{
 | 
						|
  HANDLE  NtFileHandle;
 | 
						|
  HANDLE  NtMapHandle;
 | 
						|
  VOID    *VirtualAddress;
 | 
						|
  UINTN   FileSize;
 | 
						|
 | 
						|
  //
 | 
						|
  // Use Win API to open/create a file
 | 
						|
  //
 | 
						|
  NtFileHandle = INVALID_HANDLE_VALUE;
 | 
						|
  if (FileName != NULL) {
 | 
						|
    NtFileHandle = CreateFile (
 | 
						|
                     FileName,
 | 
						|
                     GENERIC_READ | GENERIC_WRITE | GENERIC_EXECUTE,
 | 
						|
                     FILE_SHARE_READ,
 | 
						|
                     NULL,
 | 
						|
                     CreationDisposition,
 | 
						|
                     FILE_ATTRIBUTE_NORMAL,
 | 
						|
                     NULL
 | 
						|
                     );
 | 
						|
    if (NtFileHandle == INVALID_HANDLE_VALUE) {
 | 
						|
      return EFI_NOT_FOUND;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Map the open file into a memory range
 | 
						|
  //
 | 
						|
  NtMapHandle = CreateFileMapping (
 | 
						|
                  NtFileHandle,
 | 
						|
                  NULL,
 | 
						|
                  PAGE_EXECUTE_READWRITE,
 | 
						|
                  0,
 | 
						|
                  MapSize,
 | 
						|
                  NULL
 | 
						|
                  );
 | 
						|
  if (NtMapHandle == NULL) {
 | 
						|
    return EFI_DEVICE_ERROR;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Get the virtual address (address in the emulator) of the mapped file
 | 
						|
  //
 | 
						|
  VirtualAddress = MapViewOfFileEx (
 | 
						|
                     NtMapHandle,
 | 
						|
                     FILE_MAP_EXECUTE | FILE_MAP_ALL_ACCESS,
 | 
						|
                     0,
 | 
						|
                     0,
 | 
						|
                     MapSize,
 | 
						|
                     *BaseAddress
 | 
						|
                     );
 | 
						|
  if (VirtualAddress == NULL) {
 | 
						|
    return EFI_DEVICE_ERROR;
 | 
						|
  }
 | 
						|
 | 
						|
  if (MapSize == 0) {
 | 
						|
    //
 | 
						|
    // Seek to the end of the file to figure out the true file size.
 | 
						|
    //
 | 
						|
    FileSize = SetFilePointer (
 | 
						|
                 NtFileHandle,
 | 
						|
                 0,
 | 
						|
                 NULL,
 | 
						|
                 FILE_END
 | 
						|
                 );
 | 
						|
    if (FileSize == -1) {
 | 
						|
      return EFI_DEVICE_ERROR;
 | 
						|
    }
 | 
						|
 | 
						|
    *Length = FileSize;
 | 
						|
  } else {
 | 
						|
    *Length = MapSize;
 | 
						|
  }
 | 
						|
 | 
						|
  *BaseAddress = VirtualAddress;
 | 
						|
 | 
						|
  return EFI_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
INTN
 | 
						|
EFIAPI
 | 
						|
main (
 | 
						|
  IN  INT    Argc,
 | 
						|
  IN  CHAR8  **Argv,
 | 
						|
  IN  CHAR8  **Envp
 | 
						|
  )
 | 
						|
 | 
						|
/*++
 | 
						|
 | 
						|
Routine Description:
 | 
						|
  Main entry point to SEC for WinNt. This is a Windows program
 | 
						|
 | 
						|
Arguments:
 | 
						|
  Argc - Number of command line arguments
 | 
						|
  Argv - Array of command line argument strings
 | 
						|
  Envp - Array of environment variable strings
 | 
						|
 | 
						|
Returns:
 | 
						|
  0 - Normal exit
 | 
						|
  1 - Abnormal exit
 | 
						|
 | 
						|
--*/
 | 
						|
{
 | 
						|
  EFI_STATUS           Status;
 | 
						|
  HANDLE               Token;
 | 
						|
  TOKEN_PRIVILEGES     TokenPrivileges;
 | 
						|
  VOID                 *TemporaryRam;
 | 
						|
  UINT32               TemporaryRamSize;
 | 
						|
  VOID                 *EmuMagicPage;
 | 
						|
  UINTN                Index;
 | 
						|
  UINTN                Index1;
 | 
						|
  CHAR16               *FileName;
 | 
						|
  CHAR16               *FileNamePtr;
 | 
						|
  BOOLEAN              Done;
 | 
						|
  EFI_PEI_FILE_HANDLE  FileHandle;
 | 
						|
  VOID                 *SecFile;
 | 
						|
  CHAR16               *MemorySizeStr;
 | 
						|
  CHAR16               *FirmwareVolumesStr;
 | 
						|
  UINTN                ProcessAffinityMask;
 | 
						|
  UINTN                SystemAffinityMask;
 | 
						|
  INT32                LowBit;
 | 
						|
 | 
						|
  //
 | 
						|
  // Enable the privilege so that RTC driver can successfully run SetTime()
 | 
						|
  //
 | 
						|
  OpenProcessToken (GetCurrentProcess (), TOKEN_ADJUST_PRIVILEGES|TOKEN_QUERY, &Token);
 | 
						|
  if (LookupPrivilegeValue (NULL, SE_TIME_ZONE_NAME, &TokenPrivileges.Privileges[0].Luid)) {
 | 
						|
    TokenPrivileges.PrivilegeCount           = 1;
 | 
						|
    TokenPrivileges.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
 | 
						|
    AdjustTokenPrivileges (Token, FALSE, &TokenPrivileges, 0, (PTOKEN_PRIVILEGES)NULL, 0);
 | 
						|
  }
 | 
						|
 | 
						|
  MemorySizeStr      = (CHAR16 *)PcdGetPtr (PcdEmuMemorySize);
 | 
						|
  FirmwareVolumesStr = (CHAR16 *)PcdGetPtr (PcdEmuFirmwareVolume);
 | 
						|
 | 
						|
  SecPrint ("\n\rEDK II WIN Host Emulation Environment from http://www.tianocore.org/edk2/\n\r");
 | 
						|
 | 
						|
  //
 | 
						|
  // Determine the first thread available to this process.
 | 
						|
  //
 | 
						|
  if (GetProcessAffinityMask (GetCurrentProcess (), &ProcessAffinityMask, &SystemAffinityMask)) {
 | 
						|
    LowBit = (INT32)LowBitSet32 ((UINT32)ProcessAffinityMask);
 | 
						|
    if (LowBit != -1) {
 | 
						|
      //
 | 
						|
      // Force the system to bind the process to a single thread to work
 | 
						|
      // around odd semaphore type crashes.
 | 
						|
      //
 | 
						|
      SetProcessAffinityMask (GetCurrentProcess (), (INTN)(BIT0 << LowBit));
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Make some Windows calls to Set the process to the highest priority in the
 | 
						|
  //  idle class. We need this to have good performance.
 | 
						|
  //
 | 
						|
  SetPriorityClass (GetCurrentProcess (), IDLE_PRIORITY_CLASS);
 | 
						|
  SetThreadPriority (GetCurrentThread (), THREAD_PRIORITY_HIGHEST);
 | 
						|
 | 
						|
  SecInitializeThunk ();
 | 
						|
  //
 | 
						|
  // PPIs pased into PEI_CORE
 | 
						|
  //
 | 
						|
  AddThunkPpi (EFI_PEI_PPI_DESCRIPTOR_PPI, &gEmuThunkPpiGuid, &mSecEmuThunkPpi);
 | 
						|
 | 
						|
  //
 | 
						|
  // Emulator Bus Driver Thunks
 | 
						|
  //
 | 
						|
  AddThunkProtocol (&mWinNtWndThunkIo, (CHAR16 *)PcdGetPtr (PcdEmuGop), TRUE);
 | 
						|
  AddThunkProtocol (&mWinNtFileSystemThunkIo, (CHAR16 *)PcdGetPtr (PcdEmuFileSystem), TRUE);
 | 
						|
  AddThunkProtocol (&mWinNtBlockIoThunkIo, (CHAR16 *)PcdGetPtr (PcdEmuVirtualDisk), TRUE);
 | 
						|
  AddThunkProtocol (&mWinNtSnpThunkIo, (CHAR16 *)PcdGetPtr (PcdEmuNetworkInterface), TRUE);
 | 
						|
 | 
						|
  //
 | 
						|
  // Allocate space for gSystemMemory Array
 | 
						|
  //
 | 
						|
  gSystemMemoryCount = CountSeparatorsInString (MemorySizeStr, '!') + 1;
 | 
						|
  gSystemMemory      = calloc (gSystemMemoryCount, sizeof (NT_SYSTEM_MEMORY));
 | 
						|
  if (gSystemMemory == NULL) {
 | 
						|
    SecPrint ("ERROR : Can not allocate memory for %S.  Exiting.\n\r", MemorySizeStr);
 | 
						|
    exit (1);
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Allocate space for gSystemMemory Array
 | 
						|
  //
 | 
						|
  gFdInfoCount = CountSeparatorsInString (FirmwareVolumesStr, '!') + 1;
 | 
						|
  gFdInfo      = calloc (gFdInfoCount, sizeof (NT_FD_INFO));
 | 
						|
  if (gFdInfo == NULL) {
 | 
						|
    SecPrint ("ERROR : Can not allocate memory for %S.  Exiting.\n\r", FirmwareVolumesStr);
 | 
						|
    exit (1);
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Setup Boot Mode.
 | 
						|
  //
 | 
						|
  SecPrint ("  BootMode 0x%02x\n\r", PcdGet32 (PcdEmuBootMode));
 | 
						|
 | 
						|
  //
 | 
						|
  //  Allocate 128K memory to emulate temp memory for PEI.
 | 
						|
  //  on a real platform this would be SRAM, or using the cache as RAM.
 | 
						|
  //  Set TemporaryRam to zero so WinNtOpenFile will allocate a new mapping
 | 
						|
  //
 | 
						|
  TemporaryRamSize = TEMPORARY_RAM_SIZE;
 | 
						|
  TemporaryRam     = VirtualAlloc (NULL, (SIZE_T)(TemporaryRamSize), MEM_COMMIT, PAGE_EXECUTE_READWRITE);
 | 
						|
  if (TemporaryRam == NULL) {
 | 
						|
    SecPrint ("ERROR : Can not allocate enough space for SecStack\n\r");
 | 
						|
    exit (1);
 | 
						|
  }
 | 
						|
 | 
						|
  SetMem32 (TemporaryRam, TemporaryRamSize, PcdGet32 (PcdInitValueInTempStack));
 | 
						|
 | 
						|
  SecPrint (
 | 
						|
    "  OS Emulator passing in %u KB of temp RAM at 0x%08lx to SEC\n\r",
 | 
						|
    TemporaryRamSize / SIZE_1KB,
 | 
						|
    TemporaryRam
 | 
						|
    );
 | 
						|
 | 
						|
  //
 | 
						|
  // If enabled use the magic page to communicate between modules
 | 
						|
  // This replaces the PI PeiServicesTable pointer mechanism that
 | 
						|
  // deos not work in the emulator. It also allows the removal of
 | 
						|
  // writable globals from SEC, PEI_CORE (libraries), PEIMs
 | 
						|
  //
 | 
						|
  EmuMagicPage = (VOID *)(UINTN)(FixedPcdGet64 (PcdPeiServicesTablePage) & MAX_UINTN);
 | 
						|
  if (EmuMagicPage != NULL) {
 | 
						|
    UINT64  Size;
 | 
						|
    Status = WinNtOpenFile (
 | 
						|
               NULL,
 | 
						|
               SIZE_4KB,
 | 
						|
               0,
 | 
						|
               &EmuMagicPage,
 | 
						|
               &Size
 | 
						|
               );
 | 
						|
    if (EFI_ERROR (Status)) {
 | 
						|
      SecPrint ("ERROR : Could not allocate PeiServicesTablePage @ %p\n\r", EmuMagicPage);
 | 
						|
      return EFI_DEVICE_ERROR;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Open All the firmware volumes and remember the info in the gFdInfo global
 | 
						|
  // Meanwhile, find the SEC Core.
 | 
						|
  //
 | 
						|
  FileNamePtr = AllocateCopyPool (StrSize (FirmwareVolumesStr), FirmwareVolumesStr);
 | 
						|
  if (FileNamePtr == NULL) {
 | 
						|
    SecPrint ("ERROR : Can not allocate memory for firmware volume string\n\r");
 | 
						|
    exit (1);
 | 
						|
  }
 | 
						|
 | 
						|
  for (Done = FALSE, Index = 0, SecFile = NULL; !Done; Index++) {
 | 
						|
    FileName = FileNamePtr;
 | 
						|
    for (Index1 = 0; (FileNamePtr[Index1] != '!') && (FileNamePtr[Index1] != 0); Index1++) {
 | 
						|
    }
 | 
						|
 | 
						|
    if (FileNamePtr[Index1] == 0) {
 | 
						|
      Done = TRUE;
 | 
						|
    } else {
 | 
						|
      FileNamePtr[Index1] = '\0';
 | 
						|
      FileNamePtr         = &FileNamePtr[Index1 + 1];
 | 
						|
    }
 | 
						|
 | 
						|
    //
 | 
						|
    // Open the FD and remember where it got mapped into our processes address space
 | 
						|
    //
 | 
						|
    Status = WinNtOpenFile (
 | 
						|
               FileName,
 | 
						|
               0,
 | 
						|
               OPEN_EXISTING,
 | 
						|
               &gFdInfo[Index].Address,
 | 
						|
               &gFdInfo[Index].Size
 | 
						|
               );
 | 
						|
    if (EFI_ERROR (Status)) {
 | 
						|
      SecPrint ("ERROR : Can not open Firmware Device File %S (0x%X).  Exiting.\n\r", FileName, Status);
 | 
						|
      exit (1);
 | 
						|
    }
 | 
						|
 | 
						|
    SecPrint ("  FD loaded from %S", FileName);
 | 
						|
 | 
						|
    if (SecFile == NULL) {
 | 
						|
      //
 | 
						|
      // Assume the beginning of the FD is an FV and look for the SEC Core.
 | 
						|
      // Load the first one we find.
 | 
						|
      //
 | 
						|
      FileHandle = NULL;
 | 
						|
      Status     = PeiServicesFfsFindNextFile (
 | 
						|
                     EFI_FV_FILETYPE_SECURITY_CORE,
 | 
						|
                     (EFI_PEI_FV_HANDLE)gFdInfo[Index].Address,
 | 
						|
                     &FileHandle
 | 
						|
                     );
 | 
						|
      if (!EFI_ERROR (Status)) {
 | 
						|
        Status = PeiServicesFfsFindSectionData (EFI_SECTION_PE32, FileHandle, &SecFile);
 | 
						|
        if (!EFI_ERROR (Status)) {
 | 
						|
          SecPrint (" contains SEC Core");
 | 
						|
        }
 | 
						|
      }
 | 
						|
    }
 | 
						|
 | 
						|
    SecPrint ("\n\r");
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Calculate memory regions and store the information in the gSystemMemory
 | 
						|
  //  global for later use. The autosizing code will use this data to
 | 
						|
  //  map this memory into the SEC process memory space.
 | 
						|
  //
 | 
						|
  for (Index = 0, Done = FALSE; !Done; Index++) {
 | 
						|
    //
 | 
						|
    // Save the size of the memory and make a Unicode filename SystemMemory00, ...
 | 
						|
    //
 | 
						|
    gSystemMemory[Index].Size = ((UINT64)_wtoi (MemorySizeStr)) * ((UINT64)SIZE_1MB);
 | 
						|
 | 
						|
    //
 | 
						|
    // Find the next region
 | 
						|
    //
 | 
						|
    for (Index1 = 0; MemorySizeStr[Index1] != '!' && MemorySizeStr[Index1] != 0; Index1++) {
 | 
						|
    }
 | 
						|
 | 
						|
    if (MemorySizeStr[Index1] == 0) {
 | 
						|
      Done = TRUE;
 | 
						|
    }
 | 
						|
 | 
						|
    MemorySizeStr = MemorySizeStr + Index1 + 1;
 | 
						|
  }
 | 
						|
 | 
						|
  SecPrint ("\n\r");
 | 
						|
 | 
						|
  //
 | 
						|
  // Hand off to SEC Core
 | 
						|
  //
 | 
						|
  SecLoadSecCore ((UINTN)TemporaryRam, TemporaryRamSize, gFdInfo[0].Address, gFdInfo[0].Size, SecFile);
 | 
						|
 | 
						|
  //
 | 
						|
  // If we get here, then the SEC Core returned. This is an error as SEC should
 | 
						|
  //  always hand off to PEI Core and then on to DXE Core.
 | 
						|
  //
 | 
						|
  SecPrint ("ERROR : SEC returned\n\r");
 | 
						|
  exit (1);
 | 
						|
}
 | 
						|
 | 
						|
VOID
 | 
						|
SecLoadSecCore (
 | 
						|
  IN  UINTN  TemporaryRam,
 | 
						|
  IN  UINTN  TemporaryRamSize,
 | 
						|
  IN  VOID   *BootFirmwareVolumeBase,
 | 
						|
  IN  UINTN  BootFirmwareVolumeSize,
 | 
						|
  IN  VOID   *SecCorePe32File
 | 
						|
  )
 | 
						|
 | 
						|
/*++
 | 
						|
 | 
						|
Routine Description:
 | 
						|
  This is the service to load the SEC Core from the Firmware Volume
 | 
						|
 | 
						|
Arguments:
 | 
						|
  TemporaryRam            - Memory to use for SEC.
 | 
						|
  TemporaryRamSize        - Size of Memory to use for SEC
 | 
						|
  BootFirmwareVolumeBase  - Start of the Boot FV
 | 
						|
  SecCorePe32File         - SEC Core PE32
 | 
						|
 | 
						|
Returns:
 | 
						|
  Success means control is transferred and thus we should never return
 | 
						|
 | 
						|
--*/
 | 
						|
{
 | 
						|
  EFI_STATUS            Status;
 | 
						|
  VOID                  *TopOfStack;
 | 
						|
  VOID                  *SecCoreEntryPoint;
 | 
						|
  EFI_SEC_PEI_HAND_OFF  *SecCoreData;
 | 
						|
  UINTN                 SecStackSize;
 | 
						|
 | 
						|
  //
 | 
						|
  // Compute Top Of Memory for Stack and PEI Core Allocations
 | 
						|
  //
 | 
						|
  SecStackSize = TemporaryRamSize >> 1;
 | 
						|
 | 
						|
  //
 | 
						|
  // |-----------| <---- TemporaryRamBase + TemporaryRamSize
 | 
						|
  // |   Heap    |
 | 
						|
  // |           |
 | 
						|
  // |-----------| <---- StackBase / PeiTemporaryMemoryBase
 | 
						|
  // |           |
 | 
						|
  // |  Stack    |
 | 
						|
  // |-----------| <---- TemporaryRamBase
 | 
						|
  //
 | 
						|
  TopOfStack = (VOID *)(TemporaryRam + SecStackSize);
 | 
						|
 | 
						|
  //
 | 
						|
  // Reservet space for storing PeiCore's parament in stack.
 | 
						|
  //
 | 
						|
  TopOfStack = (VOID *)((UINTN)TopOfStack - sizeof (EFI_SEC_PEI_HAND_OFF) - CPU_STACK_ALIGNMENT);
 | 
						|
  TopOfStack = ALIGN_POINTER (TopOfStack, CPU_STACK_ALIGNMENT);
 | 
						|
 | 
						|
  //
 | 
						|
  // Bind this information into the SEC hand-off state
 | 
						|
  //
 | 
						|
  SecCoreData                         = (EFI_SEC_PEI_HAND_OFF *)(UINTN)TopOfStack;
 | 
						|
  SecCoreData->DataSize               = sizeof (EFI_SEC_PEI_HAND_OFF);
 | 
						|
  SecCoreData->BootFirmwareVolumeBase = BootFirmwareVolumeBase;
 | 
						|
  SecCoreData->BootFirmwareVolumeSize = BootFirmwareVolumeSize;
 | 
						|
  SecCoreData->TemporaryRamBase       = (VOID *)TemporaryRam;
 | 
						|
  SecCoreData->TemporaryRamSize       = TemporaryRamSize;
 | 
						|
  SecCoreData->StackBase              = SecCoreData->TemporaryRamBase;
 | 
						|
  SecCoreData->StackSize              = SecStackSize;
 | 
						|
  SecCoreData->PeiTemporaryRamBase    = (VOID *)((UINTN)SecCoreData->TemporaryRamBase + SecStackSize);
 | 
						|
  SecCoreData->PeiTemporaryRamSize    = TemporaryRamSize - SecStackSize;
 | 
						|
 | 
						|
  //
 | 
						|
  // Load the PEI Core from a Firmware Volume
 | 
						|
  //
 | 
						|
  Status = SecPeCoffGetEntryPoint (
 | 
						|
             SecCorePe32File,
 | 
						|
             &SecCoreEntryPoint
 | 
						|
             );
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    return;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Transfer control to the SEC Core
 | 
						|
  //
 | 
						|
  SwitchStack (
 | 
						|
    (SWITCH_STACK_ENTRY_POINT)(UINTN)SecCoreEntryPoint,
 | 
						|
    SecCoreData,
 | 
						|
    GetThunkPpiList (),
 | 
						|
    TopOfStack
 | 
						|
    );
 | 
						|
  //
 | 
						|
  // If we get here, then the SEC Core returned.  This is an error
 | 
						|
  //
 | 
						|
  return;
 | 
						|
}
 | 
						|
 | 
						|
RETURN_STATUS
 | 
						|
EFIAPI
 | 
						|
SecPeCoffGetEntryPoint (
 | 
						|
  IN     VOID  *Pe32Data,
 | 
						|
  IN OUT VOID  **EntryPoint
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS                    Status;
 | 
						|
  PE_COFF_LOADER_IMAGE_CONTEXT  ImageContext;
 | 
						|
 | 
						|
  ZeroMem (&ImageContext, sizeof (ImageContext));
 | 
						|
  ImageContext.Handle = Pe32Data;
 | 
						|
 | 
						|
  ImageContext.ImageRead = (PE_COFF_LOADER_READ_FILE)SecImageRead;
 | 
						|
 | 
						|
  Status = PeCoffLoaderGetImageInfo (&ImageContext);
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    return Status;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Allocate space in NT (not emulator) memory with ReadWrite and Execute attribute.
 | 
						|
  // Extra space is for alignment
 | 
						|
  //
 | 
						|
  ImageContext.ImageAddress = (EFI_PHYSICAL_ADDRESS)(UINTN)VirtualAlloc (NULL, (SIZE_T)(ImageContext.ImageSize + (ImageContext.SectionAlignment * 2)), MEM_COMMIT, PAGE_EXECUTE_READWRITE);
 | 
						|
  if (ImageContext.ImageAddress == 0) {
 | 
						|
    return EFI_OUT_OF_RESOURCES;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Align buffer on section boundary
 | 
						|
  //
 | 
						|
  ImageContext.ImageAddress += ImageContext.SectionAlignment - 1;
 | 
						|
  ImageContext.ImageAddress &= ~((EFI_PHYSICAL_ADDRESS)ImageContext.SectionAlignment - 1);
 | 
						|
 | 
						|
  Status = PeCoffLoaderLoadImage (&ImageContext);
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    return Status;
 | 
						|
  }
 | 
						|
 | 
						|
  Status = PeCoffLoaderRelocateImage (&ImageContext);
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    return Status;
 | 
						|
  }
 | 
						|
 | 
						|
  *EntryPoint = (VOID *)(UINTN)ImageContext.EntryPoint;
 | 
						|
 | 
						|
  return EFI_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
SecImageRead (
 | 
						|
  IN     VOID   *FileHandle,
 | 
						|
  IN     UINTN  FileOffset,
 | 
						|
  IN OUT UINTN  *ReadSize,
 | 
						|
  OUT    VOID   *Buffer
 | 
						|
  )
 | 
						|
 | 
						|
/*++
 | 
						|
 | 
						|
Routine Description:
 | 
						|
  Support routine for the PE/COFF Loader that reads a buffer from a PE/COFF file
 | 
						|
 | 
						|
Arguments:
 | 
						|
  FileHandle - The handle to the PE/COFF file
 | 
						|
  FileOffset - The offset, in bytes, into the file to read
 | 
						|
  ReadSize   - The number of bytes to read from the file starting at FileOffset
 | 
						|
  Buffer     - A pointer to the buffer to read the data into.
 | 
						|
 | 
						|
Returns:
 | 
						|
  EFI_SUCCESS - ReadSize bytes of data were read into Buffer from the PE/COFF file starting at FileOffset
 | 
						|
 | 
						|
--*/
 | 
						|
{
 | 
						|
  CHAR8  *Destination8;
 | 
						|
  CHAR8  *Source8;
 | 
						|
  UINTN  Length;
 | 
						|
 | 
						|
  Destination8 = Buffer;
 | 
						|
  Source8      = (CHAR8 *)((UINTN)FileHandle + FileOffset);
 | 
						|
  Length       = *ReadSize;
 | 
						|
  while (Length--) {
 | 
						|
    *(Destination8++) = *(Source8++);
 | 
						|
  }
 | 
						|
 | 
						|
  return EFI_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
CHAR16 *
 | 
						|
AsciiToUnicode (
 | 
						|
  IN  CHAR8  *Ascii,
 | 
						|
  IN  UINTN  *StrLen OPTIONAL
 | 
						|
  )
 | 
						|
 | 
						|
/*++
 | 
						|
 | 
						|
Routine Description:
 | 
						|
  Convert the passed in Ascii string to Unicode.
 | 
						|
  Optionally return the length of the strings.
 | 
						|
 | 
						|
Arguments:
 | 
						|
  Ascii   - Ascii string to convert
 | 
						|
  StrLen  - Length of string
 | 
						|
 | 
						|
Returns:
 | 
						|
  Pointer to malloc'ed Unicode version of Ascii
 | 
						|
 | 
						|
--*/
 | 
						|
{
 | 
						|
  UINTN   Index;
 | 
						|
  CHAR16  *Unicode;
 | 
						|
 | 
						|
  //
 | 
						|
  // Allocate a buffer for unicode string
 | 
						|
  //
 | 
						|
  for (Index = 0; Ascii[Index] != '\0'; Index++) {
 | 
						|
  }
 | 
						|
 | 
						|
  Unicode = malloc ((Index + 1) * sizeof (CHAR16));
 | 
						|
  if (Unicode == NULL) {
 | 
						|
    return NULL;
 | 
						|
  }
 | 
						|
 | 
						|
  for (Index = 0; Ascii[Index] != '\0'; Index++) {
 | 
						|
    Unicode[Index] = (CHAR16)Ascii[Index];
 | 
						|
  }
 | 
						|
 | 
						|
  Unicode[Index] = '\0';
 | 
						|
 | 
						|
  if (StrLen != NULL) {
 | 
						|
    *StrLen = Index;
 | 
						|
  }
 | 
						|
 | 
						|
  return Unicode;
 | 
						|
}
 | 
						|
 | 
						|
UINTN
 | 
						|
CountSeparatorsInString (
 | 
						|
  IN  CONST CHAR16  *String,
 | 
						|
  IN  CHAR16        Separator
 | 
						|
  )
 | 
						|
 | 
						|
/*++
 | 
						|
 | 
						|
Routine Description:
 | 
						|
  Count the number of separators in String
 | 
						|
 | 
						|
Arguments:
 | 
						|
  String    - String to process
 | 
						|
  Separator - Item to count
 | 
						|
 | 
						|
Returns:
 | 
						|
  Number of Separator in String
 | 
						|
 | 
						|
--*/
 | 
						|
{
 | 
						|
  UINTN  Count;
 | 
						|
 | 
						|
  for (Count = 0; *String != '\0'; String++) {
 | 
						|
    if (*String == Separator) {
 | 
						|
      Count++;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  return Count;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Store the ModHandle in an array indexed by the Pdb File name.
 | 
						|
  The ModHandle is needed to unload the image.
 | 
						|
  @param ImageContext - Input data returned from PE Laoder Library. Used to find the
 | 
						|
                 .PDB file name of the PE Image.
 | 
						|
  @param ModHandle    - Returned from LoadLibraryEx() and stored for call to
 | 
						|
                 FreeLibrary().
 | 
						|
  @return   return EFI_SUCCESS when ModHandle was stored.
 | 
						|
--*/
 | 
						|
EFI_STATUS
 | 
						|
AddModHandle (
 | 
						|
  IN  PE_COFF_LOADER_IMAGE_CONTEXT  *ImageContext,
 | 
						|
  IN  VOID                          *ModHandle
 | 
						|
  )
 | 
						|
 | 
						|
{
 | 
						|
  UINTN                   Index;
 | 
						|
  PDB_NAME_TO_MOD_HANDLE  *Array;
 | 
						|
  UINTN                   PreviousSize;
 | 
						|
  PDB_NAME_TO_MOD_HANDLE  *TempArray;
 | 
						|
  HANDLE                  Handle;
 | 
						|
  UINTN                   Size;
 | 
						|
 | 
						|
  //
 | 
						|
  // Return EFI_ALREADY_STARTED if this DLL has already been loaded
 | 
						|
  //
 | 
						|
  Array = mPdbNameModHandleArray;
 | 
						|
  for (Index = 0; Index < mPdbNameModHandleArraySize; Index++, Array++) {
 | 
						|
    if ((Array->PdbPointer != NULL) && (Array->ModHandle == ModHandle)) {
 | 
						|
      return EFI_ALREADY_STARTED;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  Array = mPdbNameModHandleArray;
 | 
						|
  for (Index = 0; Index < mPdbNameModHandleArraySize; Index++, Array++) {
 | 
						|
    if (Array->PdbPointer == NULL) {
 | 
						|
      //
 | 
						|
      // Make a copy of the stirng and store the ModHandle
 | 
						|
      //
 | 
						|
      Handle            = GetProcessHeap ();
 | 
						|
      Size              = AsciiStrLen (ImageContext->PdbPointer) + 1;
 | 
						|
      Array->PdbPointer = HeapAlloc (Handle, HEAP_ZERO_MEMORY, Size);
 | 
						|
      ASSERT (Array->PdbPointer != NULL);
 | 
						|
 | 
						|
      AsciiStrCpyS (Array->PdbPointer, Size, ImageContext->PdbPointer);
 | 
						|
      Array->ModHandle = ModHandle;
 | 
						|
      return EFI_SUCCESS;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // No free space in mPdbNameModHandleArray so grow it by
 | 
						|
  // MAX_PDB_NAME_TO_MOD_HANDLE_ARRAY_SIZE entires.
 | 
						|
  //
 | 
						|
  PreviousSize                = mPdbNameModHandleArraySize * sizeof (PDB_NAME_TO_MOD_HANDLE);
 | 
						|
  mPdbNameModHandleArraySize += MAX_PDB_NAME_TO_MOD_HANDLE_ARRAY_SIZE;
 | 
						|
  //
 | 
						|
  // re-allocate a new buffer and copy the old values to the new locaiton.
 | 
						|
  //
 | 
						|
  TempArray = HeapAlloc (
 | 
						|
                GetProcessHeap (),
 | 
						|
                HEAP_ZERO_MEMORY,
 | 
						|
                mPdbNameModHandleArraySize * sizeof (PDB_NAME_TO_MOD_HANDLE)
 | 
						|
                );
 | 
						|
 | 
						|
  CopyMem ((VOID *)(UINTN)TempArray, (VOID *)(UINTN)mPdbNameModHandleArray, PreviousSize);
 | 
						|
 | 
						|
  HeapFree (GetProcessHeap (), 0, mPdbNameModHandleArray);
 | 
						|
 | 
						|
  mPdbNameModHandleArray = TempArray;
 | 
						|
  if (mPdbNameModHandleArray == NULL) {
 | 
						|
    ASSERT (FALSE);
 | 
						|
    return EFI_OUT_OF_RESOURCES;
 | 
						|
  }
 | 
						|
 | 
						|
  return AddModHandle (ImageContext, ModHandle);
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Return the ModHandle and delete the entry in the array.
 | 
						|
   @param  ImageContext - Input data returned from PE Laoder Library. Used to find the
 | 
						|
                 .PDB file name of the PE Image.
 | 
						|
  @return
 | 
						|
    ModHandle - ModHandle assoicated with ImageContext is returned
 | 
						|
    NULL      - No ModHandle associated with ImageContext
 | 
						|
**/
 | 
						|
VOID *
 | 
						|
RemoveModHandle (
 | 
						|
  IN  PE_COFF_LOADER_IMAGE_CONTEXT  *ImageContext
 | 
						|
  )
 | 
						|
{
 | 
						|
  UINTN                   Index;
 | 
						|
  PDB_NAME_TO_MOD_HANDLE  *Array;
 | 
						|
 | 
						|
  if (ImageContext->PdbPointer == NULL) {
 | 
						|
    //
 | 
						|
    // If no PDB pointer there is no ModHandle so return NULL
 | 
						|
    //
 | 
						|
    return NULL;
 | 
						|
  }
 | 
						|
 | 
						|
  Array = mPdbNameModHandleArray;
 | 
						|
  for (Index = 0; Index < mPdbNameModHandleArraySize; Index++, Array++) {
 | 
						|
    if ((Array->PdbPointer != NULL) && (AsciiStrCmp (Array->PdbPointer, ImageContext->PdbPointer) == 0)) {
 | 
						|
      //
 | 
						|
      // If you find a match return it and delete the entry
 | 
						|
      //
 | 
						|
      HeapFree (GetProcessHeap (), 0, Array->PdbPointer);
 | 
						|
      Array->PdbPointer = NULL;
 | 
						|
      return Array->ModHandle;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  return NULL;
 | 
						|
}
 | 
						|
 | 
						|
VOID
 | 
						|
EFIAPI
 | 
						|
PeCoffLoaderRelocateImageExtraAction (
 | 
						|
  IN OUT PE_COFF_LOADER_IMAGE_CONTEXT  *ImageContext
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS  Status;
 | 
						|
  VOID        *DllEntryPoint;
 | 
						|
  CHAR16      *DllFileName;
 | 
						|
  HMODULE     Library;
 | 
						|
  UINTN       Index;
 | 
						|
 | 
						|
  ASSERT (ImageContext != NULL);
 | 
						|
  //
 | 
						|
  // If we load our own PE COFF images the Windows debugger can not source
 | 
						|
  //  level debug our code. If a valid PDB pointer exists use it to load
 | 
						|
  //  the *.dll file as a library using Windows* APIs. This allows
 | 
						|
  //  source level debug. The image is still loaded and relocated
 | 
						|
  //  in the Framework memory space like on a real system (by the code above),
 | 
						|
  //  but the entry point points into the DLL loaded by the code below.
 | 
						|
  //
 | 
						|
 | 
						|
  DllEntryPoint = NULL;
 | 
						|
 | 
						|
  //
 | 
						|
  // Load the DLL if it's not an EBC image.
 | 
						|
  //
 | 
						|
  if ((ImageContext->PdbPointer != NULL) &&
 | 
						|
      (ImageContext->Machine != EFI_IMAGE_MACHINE_EBC))
 | 
						|
  {
 | 
						|
    //
 | 
						|
    // Convert filename from ASCII to Unicode
 | 
						|
    //
 | 
						|
    DllFileName = AsciiToUnicode (ImageContext->PdbPointer, &Index);
 | 
						|
 | 
						|
    //
 | 
						|
    // Check that we have a valid filename
 | 
						|
    //
 | 
						|
    if ((Index < 5) || (DllFileName[Index - 4] != '.')) {
 | 
						|
      free (DllFileName);
 | 
						|
 | 
						|
      //
 | 
						|
      // Never return an error if PeCoffLoaderRelocateImage() succeeded.
 | 
						|
      // The image will run, but we just can't source level debug. If we
 | 
						|
      // return an error the image will not run.
 | 
						|
      //
 | 
						|
      return;
 | 
						|
    }
 | 
						|
 | 
						|
    //
 | 
						|
    // Replace .PDB with .DLL on the filename
 | 
						|
    //
 | 
						|
    DllFileName[Index - 3] = 'D';
 | 
						|
    DllFileName[Index - 2] = 'L';
 | 
						|
    DllFileName[Index - 1] = 'L';
 | 
						|
 | 
						|
    //
 | 
						|
    // Load the .DLL file into the user process's address space for source
 | 
						|
    // level debug
 | 
						|
    //
 | 
						|
    Library = LoadLibraryEx (DllFileName, NULL, DONT_RESOLVE_DLL_REFERENCES);
 | 
						|
    if (Library != NULL) {
 | 
						|
      //
 | 
						|
      // InitializeDriver is the entry point we put in all our EFI DLL's. The
 | 
						|
      // DONT_RESOLVE_DLL_REFERENCES argument to LoadLIbraryEx() suppresses the
 | 
						|
      // normal DLL entry point of DllMain, and prevents other modules that are
 | 
						|
      // referenced in side the DllFileName from being loaded. There is no error
 | 
						|
      // checking as the we can point to the PE32 image loaded by Tiano. This
 | 
						|
      // step is only needed for source level debugging
 | 
						|
      //
 | 
						|
      DllEntryPoint = (VOID *)(UINTN)GetProcAddress (Library, "InitializeDriver");
 | 
						|
    }
 | 
						|
 | 
						|
    if ((Library != NULL) && (DllEntryPoint != NULL)) {
 | 
						|
      Status = AddModHandle (ImageContext, Library);
 | 
						|
      if (Status == EFI_ALREADY_STARTED) {
 | 
						|
        //
 | 
						|
        // If the DLL has already been loaded before, then this instance of the DLL can not be debugged.
 | 
						|
        //
 | 
						|
        ImageContext->PdbPointer = NULL;
 | 
						|
        SecPrint ("WARNING: DLL already loaded.  No source level debug %S.\n\r", DllFileName);
 | 
						|
      } else {
 | 
						|
        //
 | 
						|
        // This DLL is not already loaded, so source level debugging is supported.
 | 
						|
        //
 | 
						|
        ImageContext->EntryPoint = (EFI_PHYSICAL_ADDRESS)(UINTN)DllEntryPoint;
 | 
						|
        SecPrint ("LoadLibraryEx (\n\r  %S,\n\r  NULL, DONT_RESOLVE_DLL_REFERENCES)\n\r", DllFileName);
 | 
						|
      }
 | 
						|
    } else {
 | 
						|
      SecPrint ("WARNING: No source level debug %S. \n\r", DllFileName);
 | 
						|
    }
 | 
						|
 | 
						|
    free (DllFileName);
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
VOID
 | 
						|
EFIAPI
 | 
						|
PeCoffLoaderUnloadImageExtraAction (
 | 
						|
  IN PE_COFF_LOADER_IMAGE_CONTEXT  *ImageContext
 | 
						|
  )
 | 
						|
{
 | 
						|
  VOID  *ModHandle;
 | 
						|
 | 
						|
  ASSERT (ImageContext != NULL);
 | 
						|
 | 
						|
  ModHandle = RemoveModHandle (ImageContext);
 | 
						|
  if (ModHandle != NULL) {
 | 
						|
    FreeLibrary (ModHandle);
 | 
						|
    SecPrint ("FreeLibrary (\n\r  %s)\n\r", ImageContext->PdbPointer);
 | 
						|
  } else {
 | 
						|
    SecPrint ("WARNING: Unload image without source level debug\n\r");
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
VOID
 | 
						|
_ModuleEntryPoint (
 | 
						|
  VOID
 | 
						|
  )
 | 
						|
{
 | 
						|
}
 |