This is the initial patch to make it boot to early DXE
phase without display (only debug message).

Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Ruiyu Ni <ruiyu...@intel.com>
Cc: Hao Wu <hao.a...@intel.com>
Cc: Andrew Fish <af...@apple.com>
---
 EmulatorPkg/EmulatorPkg.dsc                   |   7 +
 EmulatorPkg/Win/Host/WinHost.c                | 940 ++++++++++++++++++++++++++
 EmulatorPkg/Win/Host/WinHost.h                | 200 ++++++
 EmulatorPkg/Win/Host/WinHost.inf              |  88 +++
 EmulatorPkg/Win/Host/WinInclude.h             |  75 ++
 EmulatorPkg/Win/Host/WinMemoryAllocationLib.c | 178 +++++
 EmulatorPkg/Win/Host/WinThunk.c               | 228 +++++++
 7 files changed, 1716 insertions(+)
 create mode 100644 EmulatorPkg/Win/Host/WinHost.c
 create mode 100644 EmulatorPkg/Win/Host/WinHost.h
 create mode 100644 EmulatorPkg/Win/Host/WinHost.inf
 create mode 100644 EmulatorPkg/Win/Host/WinInclude.h
 create mode 100644 EmulatorPkg/Win/Host/WinMemoryAllocationLib.c
 create mode 100644 EmulatorPkg/Win/Host/WinThunk.c

diff --git a/EmulatorPkg/EmulatorPkg.dsc b/EmulatorPkg/EmulatorPkg.dsc
index ef56a86a32..8afeaf5fa3 100644
--- a/EmulatorPkg/EmulatorPkg.dsc
+++ b/EmulatorPkg/EmulatorPkg.dsc
@@ -251,6 +251,13 @@ [Components]
   EmulatorPkg/Unix/Host/Host.inf
 !endif
 
+!ifdef $(WIN_SEC_BUILD)
+  ##
+  #  Emulator, OS WIN application
+  ##
+  EmulatorPkg/Win/Host/WinHost.inf
+!endif
+
 !ifndef $(SKIP_MAIN_BUILD)
   #
   # Generic SEC
diff --git a/EmulatorPkg/Win/Host/WinHost.c b/EmulatorPkg/Win/Host/WinHost.c
new file mode 100644
index 0000000000..22399f18b9
--- /dev/null
+++ b/EmulatorPkg/Win/Host/WinHost.c
@@ -0,0 +1,940 @@
+/**@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 Hewlett Packard Enterprise Development LP<BR>
+This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD 
License
+which accompanies this distribution.  The full text of the license may be 
found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+**/
+
+#include "WinHost.h"
+
+#ifndef SE_TIME_ZONE_NAME
+#define SE_TIME_ZONE_NAME                 TEXT("SeTimeZonePrivilege")
+#endif
+
+//
+// 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 seperate memory rantes.
+//  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 it's 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 occured 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  INTN  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;
+  UINT32                ProcessAffinityMask;
+  UINT32                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 ("\nEDK II WIN Host Emulation Environment from 
http://www.tianocore.org/edk2/\n";);
+
+  //
+  // Determine the first thread available to this process.
+  //
+  if (GetProcessAffinityMask (GetCurrentProcess (), &ProcessAffinityMask, 
&SystemAffinityMask)) {
+    LowBit = (INT32)LowBitSet32 (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);
+
+  //
+  // 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", 
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", 
FirmwareVolumesStr);
+    exit (1);
+  }
+  //
+  // Setup Boot Mode.
+  //
+  SecPrint ("  BootMode 0x%02x\n", 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");
+    exit (1);
+  }
+  SetMemN (TemporaryRam, TemporaryRamSize, PcdGet32 (PcdInitValueInTempStack));
+
+  SecPrint ("  OS Emulator passing in %u KB of temp RAM at 0x%08lx to SEC\n",
+    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", 
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");
+    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", FileName, Status);
+      exit (1);
+    }
+
+    SecPrint ("  FD loaded from %S\n", 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");
+  }
+  //
+  // 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 = _wtoi (MemorySizeStr) * 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");
+
+  //
+  // 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");
+  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 transfered 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)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;
+}
+
+
+VOID
+EFIAPI
+PeCoffLoaderRelocateImageExtraAction (
+  IN OUT PE_COFF_LOADER_IMAGE_CONTEXT         *ImageContext
+  )
+{
+  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 usw 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 bellow.
+  //
+
+  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)) {
+      ImageContext->EntryPoint  = (EFI_PHYSICAL_ADDRESS) (UINTN) DllEntryPoint;
+      SecPrint ("LoadLibraryEx (%S,\n               NULL, 
DONT_RESOLVE_DLL_REFERENCES)\n", DllFileName);
+    } else {
+      SecPrint ("WARNING: No source level debug %S. \n", DllFileName);
+    }
+
+    free (DllFileName);
+  }
+}
+
+VOID
+EFIAPI
+PeCoffLoaderUnloadImageExtraAction (
+  IN PE_COFF_LOADER_IMAGE_CONTEXT         *ImageContext
+)
+{
+  ASSERT (ImageContext != NULL);
+}
+
+
+VOID
+_ModuleEntryPoint (
+  VOID
+  )
+{
+}
diff --git a/EmulatorPkg/Win/Host/WinHost.h b/EmulatorPkg/Win/Host/WinHost.h
new file mode 100644
index 0000000000..c73ba17e74
--- /dev/null
+++ b/EmulatorPkg/Win/Host/WinHost.h
@@ -0,0 +1,200 @@
+/**@file
+
+Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD 
License
+which accompanies this distribution.  The full text of the license may be 
found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+
+Module Name:
+  WinHost.h
+
+Abstract:
+  Include file for Windows Host
+
+**/
+#ifndef _HOST_H_
+#define _HOST_H_
+
+#include <stdio.h>
+#include <time.h>
+#include "WinInclude.h"
+
+#include <PiPei.h>
+#include <IndustryStandard/PeImage.h>
+#include <Ppi/EmuThunk.h>
+#include <Protocol/EmuThunk.h>
+
+
+#include <Library/BaseLib.h>
+#include <Library/PeCoffLib.h>
+#include <Library/DebugLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/ThunkPpiList.h>
+#include <Library/ThunkProtocolList.h>
+#include <Library/PcdLib.h>
+#include <Library/PrintLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/PeiServicesLib.h>
+#include <Library/PeCoffExtraActionLib.h>
+
+
+#define TEMPORARY_RAM_SIZE                0x20000
+
+typedef struct {
+  VOID                  *Address;
+  UINTN                 Size;
+} NT_FD_INFO;
+
+typedef struct {
+  EFI_PHYSICAL_ADDRESS  Memory;
+  UINT64                Size;
+} NT_SYSTEM_MEMORY;
+
+RETURN_STATUS
+EFIAPI
+SecPeCoffGetEntryPoint (
+  IN     VOID  *Pe32Data,
+  IN OUT VOID  **EntryPoint
+);
+
+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 transfered and thus we should never return
+
+--*/
+;
+
+EFI_STATUS
+EFIAPI
+SecWinNtFdAddress (
+  IN     UINTN                 Index,
+  IN OUT EFI_PHYSICAL_ADDRESS  *FdBase,
+  IN OUT UINT64                *FdSize
+  )
+/*++
+
+Routine Description:
+
+  TODO: Add function description
+
+Arguments:
+
+  Index   - TODO: add argument description
+  FdBase  - TODO: add argument description
+  FdSize  - TODO: add argument description
+
+Returns:
+
+  TODO: add return values
+
+--*/
+;
+
+
+EFI_STATUS
+EFIAPI
+SecImageRead (
+  IN     VOID    *FileHandle,
+  IN     UINTN   FileOffset,
+  IN OUT UINTN   *ReadSize,
+  OUT    VOID    *Buffer
+  )
+/*++
+
+Routine Description:
+
+  TODO: Add function description
+
+Arguments:
+
+  FileHandle  - TODO: add argument description
+  FileOffset  - TODO: add argument description
+  ReadSize    - TODO: add argument description
+  Buffer      - TODO: add argument description
+
+Returns:
+
+  TODO: add return values
+
+--*/
+;
+
+CHAR16                            *
+AsciiToUnicode (
+  IN  CHAR8   *Ascii,
+  IN  UINTN   *StrLen OPTIONAL
+  )
+/*++
+
+Routine Description:
+
+  TODO: Add function description
+
+Arguments:
+
+  Ascii   - TODO: add argument description
+  StrLen  - TODO: add argument description
+
+Returns:
+
+  TODO: add return values
+
+--*/
+;
+
+UINTN
+CountSeparatorsInString (
+  IN  CONST CHAR16   *String,
+  IN  CHAR16   Separator
+  )
+/*++
+
+Routine Description:
+
+  TODO: Add function description
+
+Arguments:
+
+  String    - TODO: add argument description
+  Separator - TODO: add argument description
+
+Returns:
+
+  TODO: add return values
+
+--*/
+;
+
+BOOLEAN
+EfiSystemMemoryRange (
+  IN  VOID *MemoryAddress
+  );
+VOID
+SecInitializeThunk (
+  VOID
+);
+extern EMU_THUNK_PROTOCOL    gEmuThunkProtocol;
+#endif
\ No newline at end of file
diff --git a/EmulatorPkg/Win/Host/WinHost.inf b/EmulatorPkg/Win/Host/WinHost.inf
new file mode 100644
index 0000000000..544e775c49
--- /dev/null
+++ b/EmulatorPkg/Win/Host/WinHost.inf
@@ -0,0 +1,88 @@
+## @file
+# Entry Point of Win Emulator
+#
+# Main executable file of Win Emulator that loads Sec core after 
initialization finished.
+# Copyright (c) 2008 - 2018, Intel Corporation. All rights reserved.<BR>
+# Portions copyright (c) 2008 - 2011, Apple Inc. All rights reserved.<BR>
+#
+#  This program and the accompanying materials
+#  are licensed and made available under the terms and conditions of the BSD 
License
+#  which accompanies this distribution. The full text of the license may be 
found at
+#  http://opensource.org/licenses/bsd-license.php
+#  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+#  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR 
IMPLIED.
+#
+#
+##
+
+[Defines]
+  INF_VERSION                    = 0x00010005
+  BASE_NAME                      = WinHost
+  FILE_GUID                      = 62E8F833-2B0A-4C19-A966-63C180588BE7
+  MODULE_TYPE                    = USER_DEFINED
+  VERSION_STRING                 = 1.0
+
+#
+# The following information is for reference only and not required by the 
build tools.
+#
+#  VALID_ARCHITECTURES           = IA32 X64
+#
+
+[Sources]
+  WinMemoryAllocationLib.c
+  WinThunk.c
+  WinHost.h
+  WinHost.c
+  WinInclude.h
+
+[Packages]
+  MdePkg/MdePkg.dec
+  MdeModulePkg/MdeModulePkg.dec
+  EmulatorPkg/EmulatorPkg.dec
+
+[LibraryClasses]
+  DebugLib
+  PcdLib
+  PrintLib
+  BaseMemoryLib
+  BaseLib
+  PeCoffLib
+  ThunkPpiList
+  ThunkProtocolList
+  PpiListLib
+  PeiServicesLib
+
+[Ppis]
+  gEmuThunkPpiGuid
+
+[Pcd]
+  gEfiMdeModulePkgTokenSpaceGuid.PcdInitValueInTempStack
+
+  gEmulatorPkgTokenSpaceGuid.PcdEmuBootMode
+  gEmulatorPkgTokenSpaceGuid.PcdEmuFirmwareVolume
+  gEmulatorPkgTokenSpaceGuid.PcdEmuMemorySize
+  gEmulatorPkgTokenSpaceGuid.PcdEmuFdBaseAddress
+  gEmulatorPkgTokenSpaceGuid.PcdPeiServicesTablePage
+
+[BuildOptions]
+       *_*_*_DLINK_FLAGS            == /out:"$(BIN_DIR)\$(BASE_NAME).exe" 
/base:0x10000000 /pdb:"$(BIN_DIR)\$(BASE_NAME).pdb"
+      :*_*_*_CC_FLAGS               == /nologo /W4 /WX /Gy /c /D UNICODE /Od 
/Oy- /FIAutoGen.h /EHs-c- /GF /Gs8192 /Zi /Gm /D _CRT_SECURE_NO_WARNINGS /D 
_CRT_SECURE_NO_DEPRECATE
+       *_*_*_PP_FLAGS               == /nologo /E /TC /FIAutoGen.h
+
+  MSFT:*_*_IA32_DLINK_FLAGS          = /LIBPATH:"$(VCINSTALLDIR)\Lib" 
/LIBPATH:"$(VCINSTALLDIR)\PlatformSdk\Lib" 
/LIBPATH:"%UniversalCRTSdkDir%lib\%UCRTVersion%\ucrt\x86" 
/LIBPATH:"%WindowsSdkDir%lib\%WindowsSDKLibVersion%\um\x86" /NOLOGO 
/SUBSYSTEM:CONSOLE /NODEFAULTLIB /IGNORE:4086 /MAP /OPT:REF /DEBUG 
/MACHINE:I386 /LTCG Kernel32.lib MSVCRTD.lib Gdi32.lib User32.lib Winmm.lib 
Advapi32.lib
+  MSFT:*_VS2015_IA32_DLINK_FLAGS     = /LIBPATH:"$(VCINSTALLDIR)\Lib" 
/LIBPATH:"$(VCINSTALLDIR)\PlatformSdk\Lib" 
/LIBPATH:"%UniversalCRTSdkDir%lib\%UCRTVersion%\ucrt\x86" 
/LIBPATH:"%WindowsSdkDir%lib\%WindowsSDKLibVersion%\um\x86" /NOLOGO 
/SUBSYSTEM:CONSOLE /NODEFAULTLIB /IGNORE:4086 /MAP /OPT:REF /DEBUG 
/MACHINE:I386 /LTCG Kernel32.lib MSVCRTD.lib Gdi32.lib User32.lib Winmm.lib 
Advapi32.lib vcruntimed.lib ucrtd.lib
+  MSFT:*_VS2015x86_IA32_DLINK_FLAGS  = /LIBPATH:"$(VCINSTALLDIR)\Lib" 
/LIBPATH:"$(VCINSTALLDIR)\PlatformSdk\Lib" 
/LIBPATH:"%UniversalCRTSdkDir%lib\%UCRTVersion%\ucrt\x86" 
/LIBPATH:"%WindowsSdkDir%lib\%WindowsSDKLibVersion%\um\x86" /NOLOGO 
/SUBSYSTEM:CONSOLE /NODEFAULTLIB /IGNORE:4086 /MAP /OPT:REF /DEBUG 
/MACHINE:I386 /LTCG Kernel32.lib MSVCRTD.lib Gdi32.lib User32.lib Winmm.lib 
Advapi32.lib vcruntimed.lib ucrtd.lib
+  MSFT:*_VS2017_IA32_DLINK_FLAGS     = /LIBPATH:"%VCToolsInstallDir%lib\x86" 
/LIBPATH:"%UniversalCRTSdkDir%lib\%UCRTVersion%\ucrt\x86" 
/LIBPATH:"%WindowsSdkDir%lib\%WindowsSDKLibVersion%\um\x86" /NOLOGO 
/SUBSYSTEM:CONSOLE /NODEFAULTLIB /IGNORE:4086 /MAP /OPT:REF /DEBUG 
/MACHINE:I386 /LTCG Kernel32.lib MSVCRTD.lib vcruntimed.lib ucrtd.lib Gdi32.lib 
User32.lib Winmm.lib Advapi32.lib
+  MSFT:*_*_IA32_ASM_FLAGS           == /nologo /W3 /WX /c /coff /Cx /Zd /W0 /Zi
+  MSFT:*_*_IA32_ASMLINK_FLAGS       == /link /nologo /tiny
+
+  MSFT:*_*_X64_DLINK_FLAGS           = /LIBPATH:"$(VCINSTALLDIR)\Lib\AMD64" 
/LIBPATH:"%UniversalCRTSdkDir%lib\%UCRTVersion%\ucrt\x64" 
/LIBPATH:"%WindowsSdkDir%lib\%WindowsSDKLibVersion%\um\x64" /NOLOGO 
/SUBSYSTEM:CONSOLE /NODEFAULTLIB /IGNORE:4086 /MAP /OPT:REF /DEBUG 
/MACHINE:AMD64 /LTCG Kernel32.lib MSVCRTD.lib Gdi32.lib User32.lib Winmm.lib 
Advapi32.lib
+  MSFT:*_VS2015_X64_DLINK_FLAGS      = /LIBPATH:"$(VCINSTALLDIR)\Lib\AMD64" 
/LIBPATH:"%UniversalCRTSdkDir%lib\%UCRTVersion%\ucrt\x64" 
/LIBPATH:"%WindowsSdkDir%lib\%WindowsSDKLibVersion%\um\x64" /NOLOGO 
/SUBSYSTEM:CONSOLE /NODEFAULTLIB /IGNORE:4086 /MAP /OPT:REF /DEBUG 
/MACHINE:AMD64 /LTCG Kernel32.lib MSVCRTD.lib vcruntimed.lib ucrtd.lib 
Gdi32.lib User32.lib Winmm.lib Advapi32.lib
+  MSFT:*_VS2015x86_X64_DLINK_FLAGS   = /LIBPATH:"$(VCINSTALLDIR)\Lib\AMD64" 
/LIBPATH:"%UniversalCRTSdkDir%lib\%UCRTVersion%\ucrt\x64" 
/LIBPATH:"%WindowsSdkDir%lib\%WindowsSDKLibVersion%\um\x64" /NOLOGO 
/SUBSYSTEM:CONSOLE /NODEFAULTLIB /IGNORE:4086 /MAP /OPT:REF /DEBUG 
/MACHINE:AMD64 /LTCG Kernel32.lib MSVCRTD.lib vcruntimed.lib ucrtd.lib 
Gdi32.lib User32.lib Winmm.lib Advapi32.lib
+  MSFT:*_VS2017_X64_DLINK_FLAGS      = /LIBPATH:"%VCToolsInstallDir%lib\x64" 
/LIBPATH:"%UniversalCRTSdkDir%lib\%UCRTVersion%\ucrt\x64" 
/LIBPATH:"%WindowsSdkDir%lib\%WindowsSDKLibVersion%\um\x64" /NOLOGO 
/SUBSYSTEM:CONSOLE /NODEFAULTLIB /IGNORE:4086 /MAP /OPT:REF /DEBUG 
/MACHINE:AMD64 /LTCG Kernel32.lib MSVCRTD.lib vcruntimed.lib ucrtd.lib 
Gdi32.lib User32.lib Winmm.lib Advapi32.lib
+  MSFT:*_*_X64_ASM_FLAGS            == /nologo /W3 /WX /c /Cx /Zd /W0 /Zi
+  MSFT:*_*_X64_ASMLINK_FLAGS        == /link /nologo
+
+  INTEL:*_*_IA32_DLINK_FLAGS         = /LIBPATH:"C:\Program 
Files\Intel\Compiler\C++\9.1\IA32\Lib" /LIBPATH:"$(VCINSTALLDIR)\Lib" 
/LIBPATH:"$(VCINSTALLDIR)\PlatformSdk\Lib" /NOLOGO /SUBSYSTEM:CONSOLE 
/NODEFAULTLIB /IGNORE:4086 /MAP /OPT:REF /DEBUG /MACHINE:I386 /LTCG 
Kernel32.lib MSVCRTD.lib Gdi32.lib User32.lib Winmm.lib
+  INTEL:*_*_IA32_ASM_FLAGS          == /nologo /W3 /WX /c /coff /Cx /Zd /W0 /Zi
+  INTEL:*_*_IA32_ASMLINK_FLAGS      == /link /nologo /tiny
diff --git a/EmulatorPkg/Win/Host/WinInclude.h 
b/EmulatorPkg/Win/Host/WinInclude.h
new file mode 100644
index 0000000000..ae90b1ed30
--- /dev/null
+++ b/EmulatorPkg/Win/Host/WinInclude.h
@@ -0,0 +1,75 @@
+/**@file
+  Public include file for the WinNt Library
+
+Copyright (c) 2006 - 2014, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD 
License
+which accompanies this distribution.  The full text of the license may be 
found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+**/
+
+#ifndef __WIN_NT_INCLUDE_H__
+#define __WIN_NT_INCLUDE_H__
+
+//
+// Win32 include files do not compile clean with /W4, so we use the warning
+// pragma to suppress the warnings for Win32 only. This way our code can stil
+// compile at /W4 (highest warning level) with /WX (warnings cause build
+// errors).
+//
+#pragma warning(disable : 4115)
+#pragma warning(disable : 4201)
+#pragma warning(disable : 4028)
+#pragma warning(disable : 4133)
+
+#define GUID  _WINNT_DUP_GUID_____
+#define _LIST_ENTRY  _WINNT_DUP_LIST_ENTRY_FORWARD
+#define LIST_ENTRY   _WINNT_DUP_LIST_ENTRY
+#if defined (MDE_CPU_IA32) && (_MSC_VER < 1800)
+#define InterlockedIncrement _WINNT_DUP_InterlockedIncrement
+#define InterlockedDecrement _WINNT_DUP_InterlockedDecrement
+#define InterlockedCompareExchange64 _WINNT_DUP_InterlockedCompareExchange64
+#endif
+#undef UNALIGNED
+#undef CONST
+#undef VOID
+#undef DEBUG_EVENT
+
+// WQBugBug: This typedef is to make "windows.h" buildable.
+//                   It should be removed after the root cause why
+//                   size_t is undefined when go into the line below is found.
+#if defined (MDE_CPU_IA32)
+typedef UINT32 size_t ;
+#endif
+
+#include "windows.h"
+
+#undef GUID
+#undef _LIST_ENTRY
+#undef LIST_ENTRY
+#undef InterlockedIncrement
+#undef InterlockedDecrement
+#undef InterlockedCompareExchange64
+#undef InterlockedCompareExchangePointer
+#undef CreateEventEx
+
+#define VOID void
+
+//
+// Prevent collisions with Windows API name macros that deal with Unicode/Not 
issues
+//
+#undef LoadImage
+#undef CreateEvent
+#undef FAR
+
+//
+// Set the warnings back on as the EFI code must be /W4.
+//
+#pragma warning(default : 4115)
+#pragma warning(default : 4201)
+
+
+#endif
diff --git a/EmulatorPkg/Win/Host/WinMemoryAllocationLib.c 
b/EmulatorPkg/Win/Host/WinMemoryAllocationLib.c
new file mode 100644
index 0000000000..0c7e7ff508
--- /dev/null
+++ b/EmulatorPkg/Win/Host/WinMemoryAllocationLib.c
@@ -0,0 +1,178 @@
+/*++ @file
+
+  Copyright (c) 2011 - 2018, Intel Corporation. All rights reserved.<BR>
+
+  This program and the accompanying materials
+  are licensed and made available under the terms and conditions of the BSD 
License
+  which accompanies this distribution.  The full text of the license may be 
found at
+  http://opensource.org/licenses/bsd-license.php
+
+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include <Base.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/MemoryAllocationLib.h>
+
+#include <stdlib.h>
+
+/**
+  Allocates a buffer of type EfiBootServicesData.
+
+  Allocates the number bytes specified by AllocationSize of type 
EfiBootServicesData and returns a
+  pointer to the allocated buffer.  If AllocationSize is 0, then a valid 
buffer of 0 size is
+  returned.  If there is not enough memory remaining to satisfy the request, 
then NULL is returned.
+
+  @param  AllocationSize        The number of bytes to allocate.
+
+  @return A pointer to the allocated buffer or NULL if allocation fails.
+
+**/
+VOID *
+EFIAPI
+AllocatePool (
+  IN UINTN  AllocationSize
+  )
+{
+  return (VOID*) malloc (AllocationSize);
+}
+
+
+/**
+  Allocates and zeros a buffer of type EfiBootServicesData.
+
+  Allocates the number bytes specified by AllocationSize of type 
EfiBootServicesData, clears the
+  buffer with zeros, and returns a pointer to the allocated buffer.  If 
AllocationSize is 0, then a
+  valid buffer of 0 size is returned.  If there is not enough memory remaining 
to satisfy the
+  request, then NULL is returned.
+
+  @param  AllocationSize        The number of bytes to allocate and zero.
+
+  @return A pointer to the allocated buffer or NULL if allocation fails.
+
+**/
+VOID *
+EFIAPI
+AllocateZeroPool (
+  IN UINTN  AllocationSize
+  )
+{
+  VOID *Buffer;
+
+  Buffer = AllocatePool (AllocationSize);
+  if (Buffer == NULL) {
+    return NULL;
+  }
+
+  ZeroMem (Buffer, AllocationSize);
+
+  return Buffer;
+}
+
+
+/**
+  Reallocates a buffer of type EfiBootServicesData.
+
+  Allocates and zeros the number bytes specified by NewSize from memory of type
+  EfiBootServicesData.  If OldBuffer is not NULL, then the smaller of OldSize 
and
+  NewSize bytes are copied from OldBuffer to the newly allocated buffer, and
+  OldBuffer is freed.  A pointer to the newly allocated buffer is returned.
+  If NewSize is 0, then a valid buffer of 0 size is  returned.  If there is not
+  enough memory remaining to satisfy the request, then NULL is returned.
+
+  If the allocation of the new buffer is successful and the smaller of NewSize 
and OldSize
+  is greater than (MAX_ADDRESS - OldBuffer + 1), then ASSERT().
+
+  @param  OldSize        The size, in bytes, of OldBuffer.
+  @param  NewSize        The size, in bytes, of the buffer to reallocate.
+  @param  OldBuffer      The buffer to copy to the allocated buffer.  This is 
an optional
+                         parameter that may be NULL.
+
+  @return A pointer to the allocated buffer or NULL if allocation fails.
+
+**/
+VOID *
+EFIAPI
+ReallocatePool (
+  IN UINTN  OldSize,
+  IN UINTN  NewSize,
+  IN VOID   *OldBuffer  OPTIONAL
+  )
+{
+  VOID *NewBuffer;
+
+  NewBuffer = AllocatePool (NewSize);
+  if (NewBuffer == NULL) {
+    return NULL;
+  }
+
+  if (OldBuffer != NULL) {
+    if (OldSize > 0) {
+      CopyMem (NewBuffer, OldBuffer, OldSize);
+    }
+
+    FreePool (OldBuffer);
+  }
+
+  return NewBuffer;
+}
+
+/**
+  Copies a buffer to an allocated buffer of type EfiBootServicesData.
+
+  Allocates the number bytes specified by AllocationSize of type 
EfiBootServicesData, copies
+  AllocationSize bytes from Buffer to the newly allocated buffer, and returns 
a pointer to the
+  allocated buffer.  If AllocationSize is 0, then a valid buffer of 0 size is 
returned.  If there
+  is not enough memory remaining to satisfy the request, then NULL is returned.
+
+  If Buffer is NULL, then ASSERT().
+  If AllocationSize is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT().
+
+  @param  AllocationSize        The number of bytes to allocate and zero.
+  @param  Buffer                The buffer to copy to the allocated buffer.
+
+  @return A pointer to the allocated buffer or NULL if allocation fails.
+
+**/
+VOID *
+EFIAPI
+AllocateCopyPool (
+  IN UINTN       AllocationSize,
+  IN CONST VOID  *Buffer
+  )
+{
+  VOID  *Memory;
+
+  Memory = AllocatePool (AllocationSize);
+  if (Memory != NULL) {
+    Memory = CopyMem (Memory, Buffer, AllocationSize);
+  }
+  return Memory;
+}
+
+
+/**
+  Frees a buffer that was previously allocated with one of the pool allocation 
functions in the
+  Memory Allocation Library.
+
+  Frees the buffer specified by Buffer.  Buffer must have been allocated on a 
previous call to the
+  pool allocation services of the Memory Allocation Library.  If it is not 
possible to free pool
+  resources, then this function will perform no actions.
+
+  If Buffer was not allocated with a pool allocation function in the Memory 
Allocation Library,
+  then ASSERT().
+
+  @param  Buffer                Pointer to the buffer to free.
+
+**/
+VOID
+EFIAPI
+FreePool (
+  IN VOID   *Buffer
+  )
+{
+  free ((void *) Buffer);
+}
+
diff --git a/EmulatorPkg/Win/Host/WinThunk.c b/EmulatorPkg/Win/Host/WinThunk.c
new file mode 100644
index 0000000000..5ec5d439d4
--- /dev/null
+++ b/EmulatorPkg/Win/Host/WinThunk.c
@@ -0,0 +1,228 @@
+/**@file
+
+Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD 
License
+which accompanies this distribution.  The full text of the license may be 
found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+
+  WinNtThunk.c
+
+Abstract:
+
+  Since the SEC is the only windows program in our emulation we
+  must use a Tiano mechanism to export Win32 APIs to other modules.
+  This is the role of the EFI_WIN_NT_THUNK_PROTOCOL.
+
+  The mWinNtThunkTable exists so that a change to EFI_WIN_NT_THUNK_PROTOCOL
+  will cause an error in initializing the array if all the member functions
+  are not added. It looks like adding a element to end and not initializing
+  it may cause the table to be initaliized with the members at the end being
+  set to zero. This is bad as jumping to zero will case the NT32 to crash.
+
+  All the member functions in mWinNtThunkTable are Win32
+  API calls, so please reference Microsoft documentation.
+
+
+  gWinNt is a a public exported global that contains the initialized
+  data.
+
+**/
+
+#include "WinHost.h"
+
+UINTN
+SecWriteStdErr (
+  IN UINT8     *Buffer,
+  IN UINTN     NumberOfBytes
+  )
+{
+  return 0;
+}
+
+
+EFI_STATUS
+SecConfigStdIn (
+  VOID
+  )
+{
+  return EFI_SUCCESS;
+}
+
+UINTN
+SecWriteStdOut (
+  IN UINT8     *Buffer,
+  IN UINTN     NumberOfBytes
+  )
+{
+  return 0;
+}
+
+BOOLEAN
+SecPollStdIn (
+  VOID
+  )
+{
+  return FALSE;
+}
+
+UINTN
+SecReadStdIn (
+  IN UINT8     *Buffer,
+  IN UINTN     NumberOfBytes
+  )
+{
+  return 0;
+}
+
+
+VOID *
+SecAlloc (
+  IN  UINTN Size
+  )
+{
+  return malloc ((size_t)Size);
+}
+
+BOOLEAN
+SecFree (
+  IN  VOID *Ptr
+  )
+{
+  if (EfiSystemMemoryRange (Ptr)) {
+    // If an address range is in the EFI memory map it was alloced via EFI.
+    // So don't free those ranges and let the caller know.
+    return FALSE;
+  }
+
+  free (Ptr);
+  return TRUE;
+}
+
+VOID
+SecSetTimer (
+  IN  UINT64                  TimerPeriod,
+  IN  EMU_SET_TIMER_CALLBACK  Callback
+)
+{
+}
+
+VOID
+SecInitializeThunk (
+  VOID
+)
+{
+}
+
+VOID
+SecEnableInterrupt (
+  VOID
+  )
+{
+}
+
+
+VOID
+SecDisableInterrupt (
+  VOID
+  )
+{
+}
+
+
+UINT64
+SecQueryPerformanceFrequency (
+  VOID
+  )
+{
+  // Hard code to nanoseconds
+  return 1000000000ULL;
+}
+
+UINT64
+SecQueryPerformanceCounter (
+  VOID
+  )
+{
+  return 0;
+}
+
+
+
+VOID
+SecSleep (
+  IN  UINT64 Nanoseconds
+  )
+{
+  Sleep ((DWORD)DivU64x32 (Nanoseconds, 1000000));
+}
+
+
+VOID
+SecCpuSleep (
+  VOID
+  )
+{
+  Sleep (1);
+}
+
+
+VOID
+SecExit (
+  UINTN   Status
+  )
+{
+  exit ((int)Status);
+}
+
+
+VOID
+SecGetTime (
+  OUT  EFI_TIME               *Time,
+  OUT EFI_TIME_CAPABILITIES   *Capabilities OPTIONAL
+  )
+{
+}
+
+EFI_STATUS
+SecSetTime (
+  IN  EFI_TIME               *Time
+)
+{
+  return EFI_SUCCESS;
+}
+
+EMU_THUNK_PROTOCOL gEmuThunkProtocol = {
+  SecWriteStdErr,
+  SecConfigStdIn,
+  SecWriteStdOut,
+  SecReadStdIn,
+  SecPollStdIn,
+  SecAlloc,
+  NULL,
+  SecFree,
+  SecPeCoffGetEntryPoint,
+  PeCoffLoaderRelocateImageExtraAction,
+  PeCoffLoaderUnloadImageExtraAction,
+  SecEnableInterrupt,
+  SecDisableInterrupt,
+  SecQueryPerformanceFrequency,
+  SecQueryPerformanceCounter,
+  SecSleep,
+  SecCpuSleep,
+  SecExit,
+  SecGetTime,
+  SecSetTime,
+  SecSetTimer,
+  GetNextThunkProtocol
+};
+
+
+#pragma warning(default : 4996)
+#pragma warning(default : 4232)
+
-- 
2.16.1.windows.1

_______________________________________________
edk2-devel mailing list
edk2-devel@lists.01.org
https://lists.01.org/mailman/listinfo/edk2-devel

Reply via email to