summaryrefslogtreecommitdiffstats
path: root/EmulatorPkg/Win
diff options
context:
space:
mode:
authorRuiyu Ni <ruiyu.ni@intel.com>2018-08-23 13:02:52 +0800
committerRuiyu Ni <ruiyu.ni@intel.com>2018-08-27 15:20:49 +0800
commit3c859dfebb436487928eab4644a33ce05b1905ac (patch)
tree7cbe852174ce1196ef42204912de2282c9ee612a /EmulatorPkg/Win
parent47c04c382eb5c024173f8b8d37536ca25f9f93c4 (diff)
downloadedk2-3c859dfebb436487928eab4644a33ce05b1905ac.tar.gz
edk2-3c859dfebb436487928eab4644a33ce05b1905ac.tar.bz2
edk2-3c859dfebb436487928eab4644a33ce05b1905ac.zip
EmulatorPkg/Win: Add Windows host support
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.ni@intel.com> Reviewed-by: Hao A Wu <hao.a.wu@intel.com> Cc: Andrew Fish <afish@apple.com>
Diffstat (limited to 'EmulatorPkg/Win')
-rw-r--r--EmulatorPkg/Win/Host/WinHost.c940
-rw-r--r--EmulatorPkg/Win/Host/WinHost.h200
-rw-r--r--EmulatorPkg/Win/Host/WinHost.inf88
-rw-r--r--EmulatorPkg/Win/Host/WinInclude.h75
-rw-r--r--EmulatorPkg/Win/Host/WinMemoryAllocationLib.c178
-rw-r--r--EmulatorPkg/Win/Host/WinThunk.c228
6 files changed, 1709 insertions, 0 deletions
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)
+