]> git.proxmox.com Git - mirror_edk2.git/commitdiff
EmulatorPkg/Win: Add Windows host support
authorRuiyu Ni <ruiyu.ni@intel.com>
Thu, 23 Aug 2018 05:02:52 +0000 (13:02 +0800)
committerRuiyu Ni <ruiyu.ni@intel.com>
Mon, 27 Aug 2018 07:20:49 +0000 (15:20 +0800)
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>
EmulatorPkg/EmulatorPkg.dsc
EmulatorPkg/Win/Host/WinHost.c [new file with mode: 0644]
EmulatorPkg/Win/Host/WinHost.h [new file with mode: 0644]
EmulatorPkg/Win/Host/WinHost.inf [new file with mode: 0644]
EmulatorPkg/Win/Host/WinInclude.h [new file with mode: 0644]
EmulatorPkg/Win/Host/WinMemoryAllocationLib.c [new file with mode: 0644]
EmulatorPkg/Win/Host/WinThunk.c [new file with mode: 0644]

index ef56a86a322ca1c34fa2f5fec3613a3c8454ac5c..8afeaf5fa3f8c688808c02f14aa6708ad2ee9673 100644 (file)
   EmulatorPkg/Unix/Host/Host.inf\r
 !endif\r
 \r
+!ifdef $(WIN_SEC_BUILD)\r
+  ##\r
+  #  Emulator, OS WIN application\r
+  ##\r
+  EmulatorPkg/Win/Host/WinHost.inf\r
+!endif\r
+\r
 !ifndef $(SKIP_MAIN_BUILD)\r
   #\r
   # Generic SEC\r
diff --git a/EmulatorPkg/Win/Host/WinHost.c b/EmulatorPkg/Win/Host/WinHost.c
new file mode 100644 (file)
index 0000000..22399f1
--- /dev/null
@@ -0,0 +1,940 @@
+/**@file\r
+  WinNt emulator of pre-SEC phase. It's really a Win32 application, but this is\r
+  Ok since all the other modules for NT32 are NOT Win32 applications.\r
+\r
+  This program gets NT32 PCD setting and figures out what the memory layout\r
+  will be, how may FD's will be loaded and also what the boot mode is.\r
+\r
+  This code produces 128 K of temporary memory for the SEC stack by directly\r
+  allocate memory space with ReadWrite and Execute attribute.\r
+\r
+Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>\r
+(C) Copyright 2016 Hewlett Packard Enterprise Development LP<BR>\r
+This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution.  The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+**/\r
+\r
+#include "WinHost.h"\r
+\r
+#ifndef SE_TIME_ZONE_NAME\r
+#define SE_TIME_ZONE_NAME                 TEXT("SeTimeZonePrivilege")\r
+#endif\r
+\r
+//\r
+// Default information about where the FD is located.\r
+//  This array gets filled in with information from PcdWinNtFirmwareVolume\r
+//  The number of array elements is allocated base on parsing\r
+//  PcdWinNtFirmwareVolume and the memory is never freed.\r
+//\r
+UINTN                                     gFdInfoCount = 0;\r
+NT_FD_INFO                                *gFdInfo;\r
+\r
+//\r
+// Array that supports seperate memory rantes.\r
+//  The memory ranges are set by PcdWinNtMemorySizeForSecMain.\r
+//  The number of array elements is allocated base on parsing\r
+//  PcdWinNtMemorySizeForSecMain value and the memory is never freed.\r
+//\r
+UINTN                                     gSystemMemoryCount = 0;\r
+NT_SYSTEM_MEMORY                          *gSystemMemory;\r
+\r
+/*++\r
+\r
+Routine Description:\r
+  This service is called from Index == 0 until it returns EFI_UNSUPPORTED.\r
+  It allows discontinuous memory regions to be supported by the emulator.\r
+  It uses gSystemMemory[] and gSystemMemoryCount that were created by\r
+  parsing the host environment variable EFI_MEMORY_SIZE.\r
+  The size comes from the varaible and the address comes from the call to\r
+  UnixOpenFile.\r
+\r
+Arguments:\r
+  Index      - Which memory region to use\r
+  MemoryBase - Return Base address of memory region\r
+  MemorySize - Return size in bytes of the memory region\r
+\r
+Returns:\r
+  EFI_SUCCESS - If memory region was mapped\r
+  EFI_UNSUPPORTED - If Index is not supported\r
+\r
+**/\r
+EFI_STATUS\r
+WinPeiAutoScan (\r
+  IN  UINTN                 Index,\r
+  OUT EFI_PHYSICAL_ADDRESS  *MemoryBase,\r
+  OUT UINT64                *MemorySize\r
+  )\r
+{\r
+  if (Index >= gSystemMemoryCount) {\r
+    return EFI_UNSUPPORTED;\r
+  }\r
+\r
+  //\r
+  // Allocate enough memory space for emulator\r
+  //\r
+  gSystemMemory[Index].Memory = (EFI_PHYSICAL_ADDRESS) (UINTN) VirtualAlloc (NULL, (SIZE_T) (gSystemMemory[Index].Size), MEM_COMMIT, PAGE_EXECUTE_READWRITE);\r
+  if (gSystemMemory[Index].Memory == 0) {\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+\r
+  *MemoryBase = gSystemMemory[Index].Memory;\r
+  *MemorySize = gSystemMemory[Index].Size;\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/*++\r
+\r
+Routine Description:\r
+  Return the FD Size and base address. Since the FD is loaded from a\r
+  file into host memory only the SEC will know it's address.\r
+\r
+Arguments:\r
+  Index  - Which FD, starts at zero.\r
+  FdSize - Size of the FD in bytes\r
+  FdBase - Start address of the FD. Assume it points to an FV Header\r
+  FixUp  - Difference between actual FD address and build address\r
+\r
+Returns:\r
+  EFI_SUCCESS     - Return the Base address and size of the FV\r
+  EFI_UNSUPPORTED - Index does nto map to an FD in the system\r
+\r
+**/\r
+EFI_STATUS\r
+WinFdAddress (\r
+  IN     UINTN                 Index,\r
+  IN OUT EFI_PHYSICAL_ADDRESS  *FdBase,\r
+  IN OUT UINT64                *FdSize,\r
+  IN OUT EFI_PHYSICAL_ADDRESS  *FixUp\r
+  )\r
+{\r
+  if (Index >= gFdInfoCount) {\r
+    return EFI_UNSUPPORTED;\r
+  }\r
+\r
+\r
+  *FdBase = (EFI_PHYSICAL_ADDRESS)(UINTN)gFdInfo[Index].Address;\r
+  *FdSize = (UINT64)gFdInfo[Index].Size;\r
+  *FixUp  = 0;\r
+\r
+  if (*FdBase == 0 && *FdSize == 0) {\r
+    return EFI_UNSUPPORTED;\r
+  }\r
+\r
+  if (Index == 0) {\r
+    //\r
+    // FD 0 has XIP code and well known PCD values\r
+    // If the memory buffer could not be allocated at the FD build address\r
+    // the Fixup is the difference.\r
+    //\r
+    *FixUp = *FdBase - PcdGet64 (PcdEmuFdBaseAddress);\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/*++\r
+\r
+Routine Description:\r
+  Since the SEC is the only Unix program in stack it must export\r
+  an interface to do POSIX calls.  gUnix is initialized in UnixThunk.c.\r
+\r
+Arguments:\r
+  InterfaceSize - sizeof (EFI_WIN_NT_THUNK_PROTOCOL);\r
+  InterfaceBase - Address of the gUnix global\r
+\r
+Returns:\r
+  EFI_SUCCESS - Data returned\r
+\r
+**/\r
+VOID *\r
+WinThunk (\r
+  VOID\r
+  )\r
+{\r
+  return &gEmuThunkProtocol;\r
+}\r
+\r
+\r
+EMU_THUNK_PPI mSecEmuThunkPpi = {\r
+  WinPeiAutoScan,\r
+  WinFdAddress,\r
+  WinThunk\r
+};\r
+\r
+VOID\r
+SecPrint (\r
+  CHAR8  *Format,\r
+  ...\r
+  )\r
+{\r
+  va_list  Marker;\r
+  UINTN    CharCount;\r
+  CHAR8    Buffer[0x1000];\r
+\r
+  va_start (Marker, Format);\r
+\r
+  _vsnprintf (Buffer, sizeof (Buffer), Format, Marker);\r
+\r
+  va_end (Marker);\r
+\r
+  CharCount = strlen (Buffer);\r
+  WriteFile (\r
+    GetStdHandle (STD_OUTPUT_HANDLE),\r
+    Buffer,\r
+    (DWORD)CharCount,\r
+    (LPDWORD)&CharCount,\r
+    NULL\r
+    );\r
+}\r
+\r
+/*++\r
+\r
+Routine Description:\r
+ Check to see if an address range is in the EFI GCD memory map.\r
+\r
+ This is all of GCD for system memory passed to DXE Core. FV\r
+ mapping and other device mapped into system memory are not\r
+ inlcuded in the check.\r
+\r
+Arguments:\r
+  Index      - Which memory region to use\r
+  MemoryBase - Return Base address of memory region\r
+  MemorySize - Return size in bytes of the memory region\r
+\r
+Returns:\r
+  TRUE -  Address is in the EFI GCD memory map\r
+  FALSE - Address is NOT in memory map\r
+\r
+**/\r
+BOOLEAN\r
+EfiSystemMemoryRange (\r
+  IN  VOID *MemoryAddress\r
+  )\r
+{\r
+  UINTN                 Index;\r
+  EFI_PHYSICAL_ADDRESS  MemoryBase;\r
+\r
+  MemoryBase = (EFI_PHYSICAL_ADDRESS)(UINTN)MemoryAddress;\r
+  for (Index = 0; Index < gSystemMemoryCount; Index++) {\r
+    if ((MemoryBase >= gSystemMemory[Index].Memory) &&\r
+        (MemoryBase < (gSystemMemory[Index].Memory + gSystemMemory[Index].Size)) ) {\r
+      return TRUE;\r
+    }\r
+  }\r
+\r
+  return FALSE;\r
+}\r
+\r
+\r
+EFI_STATUS\r
+WinNtOpenFile (\r
+  IN  CHAR16                    *FileName,            OPTIONAL\r
+  IN  UINT32                    MapSize,\r
+  IN  DWORD                     CreationDisposition,\r
+  IN OUT  VOID                  **BaseAddress,\r
+  OUT UINTN                     *Length\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+  Opens and memory maps a file using WinNt services. If *BaseAddress is non zero\r
+  the process will try and allocate the memory starting at BaseAddress.\r
+\r
+Arguments:\r
+  FileName            - The name of the file to open and map\r
+  MapSize             - The amount of the file to map in bytes\r
+  CreationDisposition - The flags to pass to CreateFile().  Use to create new files for\r
+                        memory emulation, and exiting files for firmware volume emulation\r
+  BaseAddress         - The base address of the mapped file in the user address space.\r
+                         If *BaseAddress is 0, the new memory region is used.\r
+                         If *BaseAddress is not 0, the request memory region is used for\r
+                          the mapping of the file into the process space.\r
+  Length              - The size of the mapped region in bytes\r
+\r
+Returns:\r
+  EFI_SUCCESS      - The file was opened and mapped.\r
+  EFI_NOT_FOUND    - FileName was not found in the current directory\r
+  EFI_DEVICE_ERROR - An error occured attempting to map the opened file\r
+\r
+--*/\r
+{\r
+  HANDLE  NtFileHandle;\r
+  HANDLE  NtMapHandle;\r
+  VOID    *VirtualAddress;\r
+  UINTN   FileSize;\r
+\r
+  //\r
+  // Use Win API to open/create a file\r
+  //\r
+  NtFileHandle = INVALID_HANDLE_VALUE;\r
+  if (FileName != NULL) {\r
+    NtFileHandle = CreateFile (\r
+                     FileName,\r
+                     GENERIC_READ | GENERIC_WRITE | GENERIC_EXECUTE,\r
+                     FILE_SHARE_READ,\r
+                     NULL,\r
+                     CreationDisposition,\r
+                     FILE_ATTRIBUTE_NORMAL,\r
+                     NULL\r
+                     );\r
+    if (NtFileHandle == INVALID_HANDLE_VALUE) {\r
+      return EFI_NOT_FOUND;\r
+    }\r
+  }\r
+  //\r
+  // Map the open file into a memory range\r
+  //\r
+  NtMapHandle = CreateFileMapping (\r
+                  NtFileHandle,\r
+                  NULL,\r
+                  PAGE_EXECUTE_READWRITE,\r
+                  0,\r
+                  MapSize,\r
+                  NULL\r
+                  );\r
+  if (NtMapHandle == NULL) {\r
+    return EFI_DEVICE_ERROR;\r
+  }\r
+  //\r
+  // Get the virtual address (address in the emulator) of the mapped file\r
+  //\r
+  VirtualAddress = MapViewOfFileEx (\r
+                    NtMapHandle,\r
+                    FILE_MAP_EXECUTE | FILE_MAP_ALL_ACCESS,\r
+                    0,\r
+                    0,\r
+                    MapSize,\r
+                    *BaseAddress\r
+                    );\r
+  if (VirtualAddress == NULL) {\r
+    return EFI_DEVICE_ERROR;\r
+  }\r
+\r
+  if (MapSize == 0) {\r
+    //\r
+    // Seek to the end of the file to figure out the true file size.\r
+    //\r
+    FileSize = SetFilePointer (\r
+                NtFileHandle,\r
+                0,\r
+                NULL,\r
+                FILE_END\r
+                );\r
+    if (FileSize == -1) {\r
+      return EFI_DEVICE_ERROR;\r
+    }\r
+\r
+    *Length = FileSize;\r
+  } else {\r
+    *Length = MapSize;\r
+  }\r
+\r
+  *BaseAddress = VirtualAddress;\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+INTN\r
+EFIAPI\r
+main (\r
+  IN  INTN  Argc,\r
+  IN  CHAR8 **Argv,\r
+  IN  CHAR8 **Envp\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+  Main entry point to SEC for WinNt. This is a Windows program\r
+\r
+Arguments:\r
+  Argc - Number of command line arguments\r
+  Argv - Array of command line argument strings\r
+  Envp - Array of environment variable strings\r
+\r
+Returns:\r
+  0 - Normal exit\r
+  1 - Abnormal exit\r
+\r
+--*/\r
+{\r
+  EFI_STATUS            Status;\r
+  HANDLE                Token;\r
+  TOKEN_PRIVILEGES      TokenPrivileges;\r
+  VOID                  *TemporaryRam;\r
+  UINT32                TemporaryRamSize;\r
+  VOID                  *EmuMagicPage;\r
+  UINTN                 Index;\r
+  UINTN                 Index1;\r
+  CHAR16                *FileName;\r
+  CHAR16                *FileNamePtr;\r
+  BOOLEAN               Done;\r
+  EFI_PEI_FILE_HANDLE   FileHandle;\r
+  VOID                  *SecFile;\r
+  CHAR16                *MemorySizeStr;\r
+  CHAR16                *FirmwareVolumesStr;\r
+  UINT32                ProcessAffinityMask;\r
+  UINT32                SystemAffinityMask;\r
+  INT32                 LowBit;\r
+\r
+  //\r
+  // Enable the privilege so that RTC driver can successfully run SetTime()\r
+  //\r
+  OpenProcessToken (GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES|TOKEN_QUERY, &Token);\r
+  if (LookupPrivilegeValue(NULL, SE_TIME_ZONE_NAME, &TokenPrivileges.Privileges[0].Luid)) {\r
+    TokenPrivileges.PrivilegeCount = 1;\r
+    TokenPrivileges.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;\r
+    AdjustTokenPrivileges(Token, FALSE, &TokenPrivileges, 0, (PTOKEN_PRIVILEGES) NULL, 0);\r
+  }\r
+\r
+  MemorySizeStr      = (CHAR16 *) PcdGetPtr (PcdEmuMemorySize);\r
+  FirmwareVolumesStr = (CHAR16 *) PcdGetPtr (PcdEmuFirmwareVolume);\r
+\r
+  SecPrint ("\nEDK II WIN Host Emulation Environment from http://www.tianocore.org/edk2/\n");\r
+\r
+  //\r
+  // Determine the first thread available to this process.\r
+  //\r
+  if (GetProcessAffinityMask (GetCurrentProcess (), &ProcessAffinityMask, &SystemAffinityMask)) {\r
+    LowBit = (INT32)LowBitSet32 (ProcessAffinityMask);\r
+    if (LowBit != -1) {\r
+      //\r
+      // Force the system to bind the process to a single thread to work\r
+      // around odd semaphore type crashes.\r
+      //\r
+      SetProcessAffinityMask (GetCurrentProcess (), (INTN)(BIT0 << LowBit));\r
+    }\r
+  }\r
+\r
+  //\r
+  // Make some Windows calls to Set the process to the highest priority in the\r
+  //  idle class. We need this to have good performance.\r
+  //\r
+  SetPriorityClass (GetCurrentProcess (), IDLE_PRIORITY_CLASS);\r
+  SetThreadPriority (GetCurrentThread (), THREAD_PRIORITY_HIGHEST);\r
+\r
+  SecInitializeThunk ();\r
+  //\r
+  // PPIs pased into PEI_CORE\r
+  //\r
+  AddThunkPpi (EFI_PEI_PPI_DESCRIPTOR_PPI, &gEmuThunkPpiGuid, &mSecEmuThunkPpi);\r
+\r
+  //\r
+  // Allocate space for gSystemMemory Array\r
+  //\r
+  gSystemMemoryCount  = CountSeparatorsInString (MemorySizeStr, '!') + 1;\r
+  gSystemMemory       = calloc (gSystemMemoryCount, sizeof (NT_SYSTEM_MEMORY));\r
+  if (gSystemMemory == NULL) {\r
+    SecPrint ("ERROR : Can not allocate memory for %S.  Exiting.\n", MemorySizeStr);\r
+    exit (1);\r
+  }\r
+\r
+  //\r
+  // Allocate space for gSystemMemory Array\r
+  //\r
+  gFdInfoCount  = CountSeparatorsInString (FirmwareVolumesStr, '!') + 1;\r
+  gFdInfo       = calloc (gFdInfoCount, sizeof (NT_FD_INFO));\r
+  if (gFdInfo == NULL) {\r
+    SecPrint ("ERROR : Can not allocate memory for %S.  Exiting.\n", FirmwareVolumesStr);\r
+    exit (1);\r
+  }\r
+  //\r
+  // Setup Boot Mode.\r
+  //\r
+  SecPrint ("  BootMode 0x%02x\n", PcdGet32 (PcdEmuBootMode));\r
+\r
+  //\r
+  //  Allocate 128K memory to emulate temp memory for PEI.\r
+  //  on a real platform this would be SRAM, or using the cache as RAM.\r
+  //  Set TemporaryRam to zero so WinNtOpenFile will allocate a new mapping\r
+  //\r
+  TemporaryRamSize = TEMPORARY_RAM_SIZE;\r
+  TemporaryRam     = VirtualAlloc (NULL, (SIZE_T) (TemporaryRamSize), MEM_COMMIT, PAGE_EXECUTE_READWRITE);\r
+  if (TemporaryRam == NULL) {\r
+    SecPrint ("ERROR : Can not allocate enough space for SecStack\n");\r
+    exit (1);\r
+  }\r
+  SetMemN (TemporaryRam, TemporaryRamSize, PcdGet32 (PcdInitValueInTempStack));\r
+\r
+  SecPrint ("  OS Emulator passing in %u KB of temp RAM at 0x%08lx to SEC\n",\r
+    TemporaryRamSize / SIZE_1KB,\r
+    TemporaryRam\r
+    );\r
+\r
+  //\r
+  // If enabled use the magic page to communicate between modules\r
+  // This replaces the PI PeiServicesTable pointer mechanism that\r
+  // deos not work in the emulator. It also allows the removal of\r
+  // writable globals from SEC, PEI_CORE (libraries), PEIMs\r
+  //\r
+  EmuMagicPage = (VOID *)(UINTN)(FixedPcdGet64 (PcdPeiServicesTablePage) & MAX_UINTN);\r
+  if (EmuMagicPage != NULL) {\r
+    UINT64  Size;\r
+    Status = WinNtOpenFile (\r
+              NULL,\r
+              SIZE_4KB,\r
+              0,\r
+              &EmuMagicPage,\r
+              &Size\r
+              );\r
+    if (EFI_ERROR (Status)) {\r
+      SecPrint ("ERROR : Could not allocate PeiServicesTablePage @ %p\n", EmuMagicPage);\r
+      return EFI_DEVICE_ERROR;\r
+    }\r
+  }\r
+\r
+  //\r
+  // Open All the firmware volumes and remember the info in the gFdInfo global\r
+  // Meanwhile, find the SEC Core.\r
+  //\r
+  FileNamePtr = AllocateCopyPool (StrSize (FirmwareVolumesStr), FirmwareVolumesStr);\r
+  if (FileNamePtr == NULL) {\r
+    SecPrint ("ERROR : Can not allocate memory for firmware volume string\n");\r
+    exit (1);\r
+  }\r
+\r
+  for (Done = FALSE, Index = 0, SecFile = NULL; !Done; Index++) {\r
+    FileName = FileNamePtr;\r
+    for (Index1 = 0; (FileNamePtr[Index1] != '!') && (FileNamePtr[Index1] != 0); Index1++)\r
+      ;\r
+    if (FileNamePtr[Index1] == 0) {\r
+      Done = TRUE;\r
+    } else {\r
+      FileNamePtr[Index1]  = '\0';\r
+      FileNamePtr = &FileNamePtr[Index1 + 1];\r
+    }\r
+\r
+    //\r
+    // Open the FD and remember where it got mapped into our processes address space\r
+    //\r
+    Status = WinNtOpenFile (\r
+              FileName,\r
+              0,\r
+              OPEN_EXISTING,\r
+              &gFdInfo[Index].Address,\r
+              &gFdInfo[Index].Size\r
+              );\r
+    if (EFI_ERROR (Status)) {\r
+      SecPrint ("ERROR : Can not open Firmware Device File %S (0x%X).  Exiting.\n", FileName, Status);\r
+      exit (1);\r
+    }\r
+\r
+    SecPrint ("  FD loaded from %S\n", FileName);\r
+\r
+    if (SecFile == NULL) {\r
+      //\r
+      // Assume the beginning of the FD is an FV and look for the SEC Core.\r
+      // Load the first one we find.\r
+      //\r
+      FileHandle = NULL;\r
+      Status = PeiServicesFfsFindNextFile (\r
+                  EFI_FV_FILETYPE_SECURITY_CORE,\r
+                  (EFI_PEI_FV_HANDLE)gFdInfo[Index].Address,\r
+                  &FileHandle\r
+                  );\r
+      if (!EFI_ERROR (Status)) {\r
+        Status = PeiServicesFfsFindSectionData (EFI_SECTION_PE32, FileHandle, &SecFile);\r
+        if (!EFI_ERROR (Status)) {\r
+          SecPrint (" contains SEC Core");\r
+        }\r
+      }\r
+    }\r
+\r
+    SecPrint ("\n");\r
+  }\r
+  //\r
+  // Calculate memory regions and store the information in the gSystemMemory\r
+  //  global for later use. The autosizing code will use this data to\r
+  //  map this memory into the SEC process memory space.\r
+  //\r
+  for (Index = 0, Done = FALSE; !Done; Index++) {\r
+    //\r
+    // Save the size of the memory and make a Unicode filename SystemMemory00, ...\r
+    //\r
+    gSystemMemory[Index].Size = _wtoi (MemorySizeStr) * SIZE_1MB;\r
+\r
+    //\r
+    // Find the next region\r
+    //\r
+    for (Index1 = 0; MemorySizeStr[Index1] != '!' && MemorySizeStr[Index1] != 0; Index1++)\r
+      ;\r
+    if (MemorySizeStr[Index1] == 0) {\r
+      Done = TRUE;\r
+    }\r
+\r
+    MemorySizeStr = MemorySizeStr + Index1 + 1;\r
+  }\r
+\r
+  SecPrint ("\n");\r
+\r
+  //\r
+  // Hand off to SEC Core\r
+  //\r
+  SecLoadSecCore ((UINTN)TemporaryRam, TemporaryRamSize, gFdInfo[0].Address, gFdInfo[0].Size, SecFile);\r
+\r
+  //\r
+  // If we get here, then the SEC Core returned. This is an error as SEC should\r
+  //  always hand off to PEI Core and then on to DXE Core.\r
+  //\r
+  SecPrint ("ERROR : SEC returned\n");\r
+  exit (1);\r
+}\r
+\r
+VOID\r
+SecLoadSecCore (\r
+  IN  UINTN   TemporaryRam,\r
+  IN  UINTN   TemporaryRamSize,\r
+  IN  VOID    *BootFirmwareVolumeBase,\r
+  IN  UINTN   BootFirmwareVolumeSize,\r
+  IN  VOID    *SecCorePe32File\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+  This is the service to load the SEC Core from the Firmware Volume\r
+\r
+Arguments:\r
+  TemporaryRam            - Memory to use for SEC.\r
+  TemporaryRamSize        - Size of Memory to use for SEC\r
+  BootFirmwareVolumeBase  - Start of the Boot FV\r
+  SecCorePe32File         - SEC Core PE32\r
+\r
+Returns:\r
+  Success means control is transfered and thus we should never return\r
+\r
+--*/\r
+{\r
+  EFI_STATUS                  Status;\r
+  VOID                        *TopOfStack;\r
+  VOID                        *SecCoreEntryPoint;\r
+  EFI_SEC_PEI_HAND_OFF        *SecCoreData;\r
+  UINTN                       SecStackSize;\r
+\r
+  //\r
+  // Compute Top Of Memory for Stack and PEI Core Allocations\r
+  //\r
+  SecStackSize = TemporaryRamSize >> 1;\r
+\r
+  //\r
+  // |-----------| <---- TemporaryRamBase + TemporaryRamSize\r
+  // |   Heap    |\r
+  // |           |\r
+  // |-----------| <---- StackBase / PeiTemporaryMemoryBase\r
+  // |           |\r
+  // |  Stack    |\r
+  // |-----------| <---- TemporaryRamBase\r
+  //\r
+  TopOfStack  = (VOID *)(TemporaryRam + SecStackSize);\r
+\r
+  //\r
+  // Reservet space for storing PeiCore's parament in stack.\r
+  //\r
+  TopOfStack  = (VOID *)((UINTN)TopOfStack - sizeof (EFI_SEC_PEI_HAND_OFF) - CPU_STACK_ALIGNMENT);\r
+  TopOfStack  = ALIGN_POINTER (TopOfStack, CPU_STACK_ALIGNMENT);\r
+\r
+  //\r
+  // Bind this information into the SEC hand-off state\r
+  //\r
+  SecCoreData                         = (EFI_SEC_PEI_HAND_OFF*)(UINTN)TopOfStack;\r
+  SecCoreData->DataSize               = sizeof (EFI_SEC_PEI_HAND_OFF);\r
+  SecCoreData->BootFirmwareVolumeBase = BootFirmwareVolumeBase;\r
+  SecCoreData->BootFirmwareVolumeSize = BootFirmwareVolumeSize;\r
+  SecCoreData->TemporaryRamBase       = (VOID*)TemporaryRam;\r
+  SecCoreData->TemporaryRamSize       = TemporaryRamSize;\r
+  SecCoreData->StackBase              = SecCoreData->TemporaryRamBase;\r
+  SecCoreData->StackSize              = SecStackSize;\r
+  SecCoreData->PeiTemporaryRamBase    = (VOID*) ((UINTN) SecCoreData->TemporaryRamBase + SecStackSize);\r
+  SecCoreData->PeiTemporaryRamSize    = TemporaryRamSize - SecStackSize;\r
+\r
+  //\r
+  // Load the PEI Core from a Firmware Volume\r
+  //\r
+  Status = SecPeCoffGetEntryPoint (\r
+            SecCorePe32File,\r
+            &SecCoreEntryPoint\r
+            );\r
+  if (EFI_ERROR (Status)) {\r
+    return ;\r
+  }\r
+\r
+  //\r
+  // Transfer control to the SEC Core\r
+  //\r
+  SwitchStack (\r
+    (SWITCH_STACK_ENTRY_POINT)SecCoreEntryPoint,\r
+    SecCoreData,\r
+    GetThunkPpiList (),\r
+    TopOfStack\r
+    );\r
+  //\r
+  // If we get here, then the SEC Core returned.  This is an error\r
+  //\r
+  return ;\r
+}\r
+\r
+RETURN_STATUS\r
+EFIAPI\r
+SecPeCoffGetEntryPoint (\r
+  IN     VOID  *Pe32Data,\r
+  IN OUT VOID  **EntryPoint\r
+  )\r
+{\r
+  EFI_STATUS                            Status;\r
+  PE_COFF_LOADER_IMAGE_CONTEXT          ImageContext;\r
+\r
+  ZeroMem (&ImageContext, sizeof (ImageContext));\r
+  ImageContext.Handle     = Pe32Data;\r
+\r
+  ImageContext.ImageRead  = (PE_COFF_LOADER_READ_FILE) SecImageRead;\r
+\r
+  Status                  = PeCoffLoaderGetImageInfo (&ImageContext);\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+  //\r
+  // Allocate space in NT (not emulator) memory with ReadWrite and Execute attribute.\r
+  // Extra space is for alignment\r
+  //\r
+  ImageContext.ImageAddress = (EFI_PHYSICAL_ADDRESS) (UINTN) VirtualAlloc (NULL, (SIZE_T) (ImageContext.ImageSize + (ImageContext.SectionAlignment * 2)), MEM_COMMIT, PAGE_EXECUTE_READWRITE);\r
+  if (ImageContext.ImageAddress == 0) {\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+  //\r
+  // Align buffer on section boundary\r
+  //\r
+  ImageContext.ImageAddress += ImageContext.SectionAlignment - 1;\r
+  ImageContext.ImageAddress &= ~((EFI_PHYSICAL_ADDRESS)ImageContext.SectionAlignment - 1);\r
+\r
+  Status = PeCoffLoaderLoadImage (&ImageContext);\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  Status = PeCoffLoaderRelocateImage (&ImageContext);\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  *EntryPoint   = (VOID *)(UINTN)ImageContext.EntryPoint;\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+SecImageRead (\r
+  IN     VOID    *FileHandle,\r
+  IN     UINTN   FileOffset,\r
+  IN OUT UINTN   *ReadSize,\r
+  OUT    VOID    *Buffer\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+  Support routine for the PE/COFF Loader that reads a buffer from a PE/COFF file\r
+\r
+Arguments:\r
+  FileHandle - The handle to the PE/COFF file\r
+  FileOffset - The offset, in bytes, into the file to read\r
+  ReadSize   - The number of bytes to read from the file starting at FileOffset\r
+  Buffer     - A pointer to the buffer to read the data into.\r
+\r
+Returns:\r
+  EFI_SUCCESS - ReadSize bytes of data were read into Buffer from the PE/COFF file starting at FileOffset\r
+\r
+--*/\r
+{\r
+  CHAR8 *Destination8;\r
+  CHAR8 *Source8;\r
+  UINTN Length;\r
+\r
+  Destination8  = Buffer;\r
+  Source8       = (CHAR8 *) ((UINTN) FileHandle + FileOffset);\r
+  Length        = *ReadSize;\r
+  while (Length--) {\r
+    *(Destination8++) = *(Source8++);\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+CHAR16 *\r
+AsciiToUnicode (\r
+  IN  CHAR8   *Ascii,\r
+  IN  UINTN   *StrLen OPTIONAL\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+  Convert the passed in Ascii string to Unicode.\r
+  Optionally return the length of the strings.\r
+\r
+Arguments:\r
+  Ascii   - Ascii string to convert\r
+  StrLen  - Length of string\r
+\r
+Returns:\r
+  Pointer to malloc'ed Unicode version of Ascii\r
+\r
+--*/\r
+{\r
+  UINTN   Index;\r
+  CHAR16  *Unicode;\r
+\r
+  //\r
+  // Allocate a buffer for unicode string\r
+  //\r
+  for (Index = 0; Ascii[Index] != '\0'; Index++)\r
+    ;\r
+  Unicode = malloc ((Index + 1) * sizeof (CHAR16));\r
+  if (Unicode == NULL) {\r
+    return NULL;\r
+  }\r
+\r
+  for (Index = 0; Ascii[Index] != '\0'; Index++) {\r
+    Unicode[Index] = (CHAR16) Ascii[Index];\r
+  }\r
+\r
+  Unicode[Index] = '\0';\r
+\r
+  if (StrLen != NULL) {\r
+    *StrLen = Index;\r
+  }\r
+\r
+  return Unicode;\r
+}\r
+\r
+UINTN\r
+CountSeparatorsInString (\r
+  IN  CONST CHAR16   *String,\r
+  IN  CHAR16         Separator\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+  Count the number of separators in String\r
+\r
+Arguments:\r
+  String    - String to process\r
+  Separator - Item to count\r
+\r
+Returns:\r
+  Number of Separator in String\r
+\r
+--*/\r
+{\r
+  UINTN Count;\r
+\r
+  for (Count = 0; *String != '\0'; String++) {\r
+    if (*String == Separator) {\r
+      Count++;\r
+    }\r
+  }\r
+\r
+  return Count;\r
+}\r
+\r
+\r
+VOID\r
+EFIAPI\r
+PeCoffLoaderRelocateImageExtraAction (\r
+  IN OUT PE_COFF_LOADER_IMAGE_CONTEXT         *ImageContext\r
+  )\r
+{\r
+  VOID              *DllEntryPoint;\r
+  CHAR16            *DllFileName;\r
+  HMODULE           Library;\r
+  UINTN             Index;\r
+\r
+  ASSERT (ImageContext != NULL);\r
+  //\r
+  // If we load our own PE COFF images the Windows debugger can not source\r
+  //  level debug our code. If a valid PDB pointer exists usw it to load\r
+  //  the *.dll file as a library using Windows* APIs. This allows\r
+  //  source level debug. The image is still loaded and relocated\r
+  //  in the Framework memory space like on a real system (by the code above),\r
+  //  but the entry point points into the DLL loaded by the code bellow.\r
+  //\r
+\r
+  DllEntryPoint = NULL;\r
+\r
+  //\r
+  // Load the DLL if it's not an EBC image.\r
+  //\r
+  if ((ImageContext->PdbPointer != NULL) &&\r
+      (ImageContext->Machine != EFI_IMAGE_MACHINE_EBC)) {\r
+    //\r
+    // Convert filename from ASCII to Unicode\r
+    //\r
+    DllFileName = AsciiToUnicode (ImageContext->PdbPointer, &Index);\r
+\r
+    //\r
+    // Check that we have a valid filename\r
+    //\r
+    if (Index < 5 || DllFileName[Index - 4] != '.') {\r
+      free (DllFileName);\r
+\r
+      //\r
+      // Never return an error if PeCoffLoaderRelocateImage() succeeded.\r
+      // The image will run, but we just can't source level debug. If we\r
+      // return an error the image will not run.\r
+      //\r
+      return;\r
+    }\r
+    //\r
+    // Replace .PDB with .DLL on the filename\r
+    //\r
+    DllFileName[Index - 3]  = 'D';\r
+    DllFileName[Index - 2]  = 'L';\r
+    DllFileName[Index - 1]  = 'L';\r
+\r
+    //\r
+    // Load the .DLL file into the user process's address space for source\r
+    // level debug\r
+    //\r
+    Library = LoadLibraryEx (DllFileName, NULL, DONT_RESOLVE_DLL_REFERENCES);\r
+    if (Library != NULL) {\r
+      //\r
+      // InitializeDriver is the entry point we put in all our EFI DLL's. The\r
+      // DONT_RESOLVE_DLL_REFERENCES argument to LoadLIbraryEx() suppresses the\r
+      // normal DLL entry point of DllMain, and prevents other modules that are\r
+      // referenced in side the DllFileName from being loaded. There is no error\r
+      // checking as the we can point to the PE32 image loaded by Tiano. This\r
+      // step is only needed for source level debugging\r
+      //\r
+      DllEntryPoint = (VOID *) (UINTN) GetProcAddress (Library, "InitializeDriver");\r
+\r
+    }\r
+\r
+    if ((Library != NULL) && (DllEntryPoint != NULL)) {\r
+      ImageContext->EntryPoint  = (EFI_PHYSICAL_ADDRESS) (UINTN) DllEntryPoint;\r
+      SecPrint ("LoadLibraryEx (%S,\n               NULL, DONT_RESOLVE_DLL_REFERENCES)\n", DllFileName);\r
+    } else {\r
+      SecPrint ("WARNING: No source level debug %S. \n", DllFileName);\r
+    }\r
+\r
+    free (DllFileName);\r
+  }\r
+}\r
+\r
+VOID\r
+EFIAPI\r
+PeCoffLoaderUnloadImageExtraAction (\r
+  IN PE_COFF_LOADER_IMAGE_CONTEXT         *ImageContext\r
+)\r
+{\r
+  ASSERT (ImageContext != NULL);\r
+}\r
+\r
+\r
+VOID\r
+_ModuleEntryPoint (\r
+  VOID\r
+  )\r
+{\r
+}\r
diff --git a/EmulatorPkg/Win/Host/WinHost.h b/EmulatorPkg/Win/Host/WinHost.h
new file mode 100644 (file)
index 0000000..c73ba17
--- /dev/null
@@ -0,0 +1,200 @@
+/**@file\r
+\r
+Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>\r
+This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution.  The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+\r
+Module Name:\r
+  WinHost.h\r
+\r
+Abstract:\r
+  Include file for Windows Host\r
+\r
+**/\r
+#ifndef _HOST_H_\r
+#define _HOST_H_\r
+\r
+#include <stdio.h>\r
+#include <time.h>\r
+#include "WinInclude.h"\r
+\r
+#include <PiPei.h>\r
+#include <IndustryStandard/PeImage.h>\r
+#include <Ppi/EmuThunk.h>\r
+#include <Protocol/EmuThunk.h>\r
+\r
+\r
+#include <Library/BaseLib.h>\r
+#include <Library/PeCoffLib.h>\r
+#include <Library/DebugLib.h>\r
+#include <Library/MemoryAllocationLib.h>\r
+#include <Library/ThunkPpiList.h>\r
+#include <Library/ThunkProtocolList.h>\r
+#include <Library/PcdLib.h>\r
+#include <Library/PrintLib.h>\r
+#include <Library/BaseMemoryLib.h>\r
+#include <Library/PeiServicesLib.h>\r
+#include <Library/PeCoffExtraActionLib.h>\r
+\r
+\r
+#define TEMPORARY_RAM_SIZE                0x20000\r
+\r
+typedef struct {\r
+  VOID                  *Address;\r
+  UINTN                 Size;\r
+} NT_FD_INFO;\r
+\r
+typedef struct {\r
+  EFI_PHYSICAL_ADDRESS  Memory;\r
+  UINT64                Size;\r
+} NT_SYSTEM_MEMORY;\r
+\r
+RETURN_STATUS\r
+EFIAPI\r
+SecPeCoffGetEntryPoint (\r
+  IN     VOID  *Pe32Data,\r
+  IN OUT VOID  **EntryPoint\r
+);\r
+\r
+VOID\r
+SecLoadSecCore (\r
+  IN  UINTN   TemporaryRam,\r
+  IN  UINTN   TemporaryRamSize,\r
+  IN  VOID    *BootFirmwareVolumeBase,\r
+  IN  UINTN   BootFirmwareVolumeSize,\r
+  IN  VOID    *SecCorePe32File\r
+)\r
+/*++\r
+\r
+Routine Description:\r
+  This is the service to load the SEC Core from the Firmware Volume\r
+\r
+Arguments:\r
+  TemporaryRam            - Memory to use for SEC.\r
+  TemporaryRamSize        - Size of Memory to use for SEC\r
+  BootFirmwareVolumeBase  - Start of the Boot FV\r
+  SecCorePe32File         - SEC Core PE32\r
+\r
+Returns:\r
+  Success means control is transfered and thus we should never return\r
+\r
+--*/\r
+;\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+SecWinNtFdAddress (\r
+  IN     UINTN                 Index,\r
+  IN OUT EFI_PHYSICAL_ADDRESS  *FdBase,\r
+  IN OUT UINT64                *FdSize\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  TODO: Add function description\r
+\r
+Arguments:\r
+\r
+  Index   - TODO: add argument description\r
+  FdBase  - TODO: add argument description\r
+  FdSize  - TODO: add argument description\r
+\r
+Returns:\r
+\r
+  TODO: add return values\r
+\r
+--*/\r
+;\r
+\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+SecImageRead (\r
+  IN     VOID    *FileHandle,\r
+  IN     UINTN   FileOffset,\r
+  IN OUT UINTN   *ReadSize,\r
+  OUT    VOID    *Buffer\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  TODO: Add function description\r
+\r
+Arguments:\r
+\r
+  FileHandle  - TODO: add argument description\r
+  FileOffset  - TODO: add argument description\r
+  ReadSize    - TODO: add argument description\r
+  Buffer      - TODO: add argument description\r
+\r
+Returns:\r
+\r
+  TODO: add return values\r
+\r
+--*/\r
+;\r
+\r
+CHAR16                            *\r
+AsciiToUnicode (\r
+  IN  CHAR8   *Ascii,\r
+  IN  UINTN   *StrLen OPTIONAL\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  TODO: Add function description\r
+\r
+Arguments:\r
+\r
+  Ascii   - TODO: add argument description\r
+  StrLen  - TODO: add argument description\r
+\r
+Returns:\r
+\r
+  TODO: add return values\r
+\r
+--*/\r
+;\r
+\r
+UINTN\r
+CountSeparatorsInString (\r
+  IN  CONST CHAR16   *String,\r
+  IN  CHAR16   Separator\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  TODO: Add function description\r
+\r
+Arguments:\r
+\r
+  String    - TODO: add argument description\r
+  Separator - TODO: add argument description\r
+\r
+Returns:\r
+\r
+  TODO: add return values\r
+\r
+--*/\r
+;\r
+\r
+BOOLEAN\r
+EfiSystemMemoryRange (\r
+  IN  VOID *MemoryAddress\r
+  );\r
+VOID\r
+SecInitializeThunk (\r
+  VOID\r
+);\r
+extern EMU_THUNK_PROTOCOL    gEmuThunkProtocol;\r
+#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 (file)
index 0000000..544e775
--- /dev/null
@@ -0,0 +1,88 @@
+## @file\r
+# Entry Point of Win Emulator\r
+#\r
+# Main executable file of Win Emulator that loads Sec core after initialization finished.\r
+# Copyright (c) 2008 - 2018, Intel Corporation. All rights reserved.<BR>\r
+# Portions copyright (c) 2008 - 2011, Apple Inc. All rights reserved.<BR>\r
+#\r
+#  This program and the accompanying materials\r
+#  are licensed and made available under the terms and conditions of the BSD License\r
+#  which accompanies this distribution. The full text of the license may be found at\r
+#  http://opensource.org/licenses/bsd-license.php\r
+#  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+#  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+#\r
+#\r
+##\r
+\r
+[Defines]\r
+  INF_VERSION                    = 0x00010005\r
+  BASE_NAME                      = WinHost\r
+  FILE_GUID                      = 62E8F833-2B0A-4C19-A966-63C180588BE7\r
+  MODULE_TYPE                    = USER_DEFINED\r
+  VERSION_STRING                 = 1.0\r
+\r
+#\r
+# The following information is for reference only and not required by the build tools.\r
+#\r
+#  VALID_ARCHITECTURES           = IA32 X64\r
+#\r
+\r
+[Sources]\r
+  WinMemoryAllocationLib.c\r
+  WinThunk.c\r
+  WinHost.h\r
+  WinHost.c\r
+  WinInclude.h\r
+\r
+[Packages]\r
+  MdePkg/MdePkg.dec\r
+  MdeModulePkg/MdeModulePkg.dec\r
+  EmulatorPkg/EmulatorPkg.dec\r
+\r
+[LibraryClasses]\r
+  DebugLib\r
+  PcdLib\r
+  PrintLib\r
+  BaseMemoryLib\r
+  BaseLib\r
+  PeCoffLib\r
+  ThunkPpiList\r
+  ThunkProtocolList\r
+  PpiListLib\r
+  PeiServicesLib\r
+\r
+[Ppis]\r
+  gEmuThunkPpiGuid\r
+\r
+[Pcd]\r
+  gEfiMdeModulePkgTokenSpaceGuid.PcdInitValueInTempStack\r
+\r
+  gEmulatorPkgTokenSpaceGuid.PcdEmuBootMode\r
+  gEmulatorPkgTokenSpaceGuid.PcdEmuFirmwareVolume\r
+  gEmulatorPkgTokenSpaceGuid.PcdEmuMemorySize\r
+  gEmulatorPkgTokenSpaceGuid.PcdEmuFdBaseAddress\r
+  gEmulatorPkgTokenSpaceGuid.PcdPeiServicesTablePage\r
+\r
+[BuildOptions]\r
+       *_*_*_DLINK_FLAGS            == /out:"$(BIN_DIR)\$(BASE_NAME).exe" /base:0x10000000 /pdb:"$(BIN_DIR)\$(BASE_NAME).pdb"\r
+      :*_*_*_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\r
+       *_*_*_PP_FLAGS               == /nologo /E /TC /FIAutoGen.h\r
+\r
+  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\r
+  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\r
+  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\r
+  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\r
+  MSFT:*_*_IA32_ASM_FLAGS           == /nologo /W3 /WX /c /coff /Cx /Zd /W0 /Zi\r
+  MSFT:*_*_IA32_ASMLINK_FLAGS       == /link /nologo /tiny\r
+\r
+  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\r
+  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\r
+  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\r
+  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\r
+  MSFT:*_*_X64_ASM_FLAGS            == /nologo /W3 /WX /c /Cx /Zd /W0 /Zi\r
+  MSFT:*_*_X64_ASMLINK_FLAGS        == /link /nologo\r
+\r
+  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\r
+  INTEL:*_*_IA32_ASM_FLAGS          == /nologo /W3 /WX /c /coff /Cx /Zd /W0 /Zi\r
+  INTEL:*_*_IA32_ASMLINK_FLAGS      == /link /nologo /tiny\r
diff --git a/EmulatorPkg/Win/Host/WinInclude.h b/EmulatorPkg/Win/Host/WinInclude.h
new file mode 100644 (file)
index 0000000..ae90b1e
--- /dev/null
@@ -0,0 +1,75 @@
+/**@file\r
+  Public include file for the WinNt Library\r
+\r
+Copyright (c) 2006 - 2014, Intel Corporation. All rights reserved.<BR>\r
+This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution.  The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+**/\r
+\r
+#ifndef __WIN_NT_INCLUDE_H__\r
+#define __WIN_NT_INCLUDE_H__\r
+\r
+//\r
+// Win32 include files do not compile clean with /W4, so we use the warning\r
+// pragma to suppress the warnings for Win32 only. This way our code can stil\r
+// compile at /W4 (highest warning level) with /WX (warnings cause build\r
+// errors).\r
+//\r
+#pragma warning(disable : 4115)\r
+#pragma warning(disable : 4201)\r
+#pragma warning(disable : 4028)\r
+#pragma warning(disable : 4133)\r
+\r
+#define GUID  _WINNT_DUP_GUID_____\r
+#define _LIST_ENTRY  _WINNT_DUP_LIST_ENTRY_FORWARD\r
+#define LIST_ENTRY   _WINNT_DUP_LIST_ENTRY\r
+#if defined (MDE_CPU_IA32) && (_MSC_VER < 1800)\r
+#define InterlockedIncrement _WINNT_DUP_InterlockedIncrement\r
+#define InterlockedDecrement _WINNT_DUP_InterlockedDecrement\r
+#define InterlockedCompareExchange64 _WINNT_DUP_InterlockedCompareExchange64\r
+#endif\r
+#undef UNALIGNED\r
+#undef CONST\r
+#undef VOID\r
+#undef DEBUG_EVENT\r
+\r
+// WQBugBug: This typedef is to make "windows.h" buildable.\r
+//                   It should be removed after the root cause why\r
+//                   size_t is undefined when go into the line below is found.\r
+#if defined (MDE_CPU_IA32)\r
+typedef UINT32 size_t ;\r
+#endif\r
+\r
+#include "windows.h"\r
+\r
+#undef GUID\r
+#undef _LIST_ENTRY\r
+#undef LIST_ENTRY\r
+#undef InterlockedIncrement\r
+#undef InterlockedDecrement\r
+#undef InterlockedCompareExchange64\r
+#undef InterlockedCompareExchangePointer\r
+#undef CreateEventEx\r
+\r
+#define VOID void\r
+\r
+//\r
+// Prevent collisions with Windows API name macros that deal with Unicode/Not issues\r
+//\r
+#undef LoadImage\r
+#undef CreateEvent\r
+#undef FAR\r
+\r
+//\r
+// Set the warnings back on as the EFI code must be /W4.\r
+//\r
+#pragma warning(default : 4115)\r
+#pragma warning(default : 4201)\r
+\r
+\r
+#endif\r
diff --git a/EmulatorPkg/Win/Host/WinMemoryAllocationLib.c b/EmulatorPkg/Win/Host/WinMemoryAllocationLib.c
new file mode 100644 (file)
index 0000000..0c7e7ff
--- /dev/null
@@ -0,0 +1,178 @@
+/*++ @file\r
+\r
+  Copyright (c) 2011 - 2018, Intel Corporation. All rights reserved.<BR>\r
+\r
+  This program and the accompanying materials\r
+  are licensed and made available under the terms and conditions of the BSD License\r
+  which accompanies this distribution.  The full text of the license may be found at\r
+  http://opensource.org/licenses/bsd-license.php\r
+\r
+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#include <Base.h>\r
+#include <Library/BaseMemoryLib.h>\r
+#include <Library/MemoryAllocationLib.h>\r
+\r
+#include <stdlib.h>\r
+\r
+/**\r
+  Allocates a buffer of type EfiBootServicesData.\r
+\r
+  Allocates the number bytes specified by AllocationSize of type EfiBootServicesData and returns a\r
+  pointer to the allocated buffer.  If AllocationSize is 0, then a valid buffer of 0 size is\r
+  returned.  If there is not enough memory remaining to satisfy the request, then NULL is returned.\r
+\r
+  @param  AllocationSize        The number of bytes to allocate.\r
+\r
+  @return A pointer to the allocated buffer or NULL if allocation fails.\r
+\r
+**/\r
+VOID *\r
+EFIAPI\r
+AllocatePool (\r
+  IN UINTN  AllocationSize\r
+  )\r
+{\r
+  return (VOID*) malloc (AllocationSize);\r
+}\r
+\r
+\r
+/**\r
+  Allocates and zeros a buffer of type EfiBootServicesData.\r
+\r
+  Allocates the number bytes specified by AllocationSize of type EfiBootServicesData, clears the\r
+  buffer with zeros, and returns a pointer to the allocated buffer.  If AllocationSize is 0, then a\r
+  valid buffer of 0 size is returned.  If there is not enough memory remaining to satisfy the\r
+  request, then NULL is returned.\r
+\r
+  @param  AllocationSize        The number of bytes to allocate and zero.\r
+\r
+  @return A pointer to the allocated buffer or NULL if allocation fails.\r
+\r
+**/\r
+VOID *\r
+EFIAPI\r
+AllocateZeroPool (\r
+  IN UINTN  AllocationSize\r
+  )\r
+{\r
+  VOID *Buffer;\r
+\r
+  Buffer = AllocatePool (AllocationSize);\r
+  if (Buffer == NULL) {\r
+    return NULL;\r
+  }\r
+\r
+  ZeroMem (Buffer, AllocationSize);\r
+\r
+  return Buffer;\r
+}\r
+\r
+\r
+/**\r
+  Reallocates a buffer of type EfiBootServicesData.\r
+\r
+  Allocates and zeros the number bytes specified by NewSize from memory of type\r
+  EfiBootServicesData.  If OldBuffer is not NULL, then the smaller of OldSize and\r
+  NewSize bytes are copied from OldBuffer to the newly allocated buffer, and\r
+  OldBuffer is freed.  A pointer to the newly allocated buffer is returned.\r
+  If NewSize is 0, then a valid buffer of 0 size is  returned.  If there is not\r
+  enough memory remaining to satisfy the request, then NULL is returned.\r
+\r
+  If the allocation of the new buffer is successful and the smaller of NewSize and OldSize\r
+  is greater than (MAX_ADDRESS - OldBuffer + 1), then ASSERT().\r
+\r
+  @param  OldSize        The size, in bytes, of OldBuffer.\r
+  @param  NewSize        The size, in bytes, of the buffer to reallocate.\r
+  @param  OldBuffer      The buffer to copy to the allocated buffer.  This is an optional\r
+                         parameter that may be NULL.\r
+\r
+  @return A pointer to the allocated buffer or NULL if allocation fails.\r
+\r
+**/\r
+VOID *\r
+EFIAPI\r
+ReallocatePool (\r
+  IN UINTN  OldSize,\r
+  IN UINTN  NewSize,\r
+  IN VOID   *OldBuffer  OPTIONAL\r
+  )\r
+{\r
+  VOID *NewBuffer;\r
+\r
+  NewBuffer = AllocatePool (NewSize);\r
+  if (NewBuffer == NULL) {\r
+    return NULL;\r
+  }\r
+\r
+  if (OldBuffer != NULL) {\r
+    if (OldSize > 0) {\r
+      CopyMem (NewBuffer, OldBuffer, OldSize);\r
+    }\r
+\r
+    FreePool (OldBuffer);\r
+  }\r
+\r
+  return NewBuffer;\r
+}\r
+\r
+/**\r
+  Copies a buffer to an allocated buffer of type EfiBootServicesData.\r
+\r
+  Allocates the number bytes specified by AllocationSize of type EfiBootServicesData, copies\r
+  AllocationSize bytes from Buffer to the newly allocated buffer, and returns a pointer to the\r
+  allocated buffer.  If AllocationSize is 0, then a valid buffer of 0 size is returned.  If there\r
+  is not enough memory remaining to satisfy the request, then NULL is returned.\r
+\r
+  If Buffer is NULL, then ASSERT().\r
+  If AllocationSize is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT().\r
+\r
+  @param  AllocationSize        The number of bytes to allocate and zero.\r
+  @param  Buffer                The buffer to copy to the allocated buffer.\r
+\r
+  @return A pointer to the allocated buffer or NULL if allocation fails.\r
+\r
+**/\r
+VOID *\r
+EFIAPI\r
+AllocateCopyPool (\r
+  IN UINTN       AllocationSize,\r
+  IN CONST VOID  *Buffer\r
+  )\r
+{\r
+  VOID  *Memory;\r
+\r
+  Memory = AllocatePool (AllocationSize);\r
+  if (Memory != NULL) {\r
+    Memory = CopyMem (Memory, Buffer, AllocationSize);\r
+  }\r
+  return Memory;\r
+}\r
+\r
+\r
+/**\r
+  Frees a buffer that was previously allocated with one of the pool allocation functions in the\r
+  Memory Allocation Library.\r
+\r
+  Frees the buffer specified by Buffer.  Buffer must have been allocated on a previous call to the\r
+  pool allocation services of the Memory Allocation Library.  If it is not possible to free pool\r
+  resources, then this function will perform no actions.\r
+\r
+  If Buffer was not allocated with a pool allocation function in the Memory Allocation Library,\r
+  then ASSERT().\r
+\r
+  @param  Buffer                Pointer to the buffer to free.\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+FreePool (\r
+  IN VOID   *Buffer\r
+  )\r
+{\r
+  free ((void *) Buffer);\r
+}\r
+\r
diff --git a/EmulatorPkg/Win/Host/WinThunk.c b/EmulatorPkg/Win/Host/WinThunk.c
new file mode 100644 (file)
index 0000000..5ec5d43
--- /dev/null
@@ -0,0 +1,228 @@
+/**@file\r
+\r
+Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>\r
+This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution.  The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+Module Name:\r
+\r
+  WinNtThunk.c\r
+\r
+Abstract:\r
+\r
+  Since the SEC is the only windows program in our emulation we\r
+  must use a Tiano mechanism to export Win32 APIs to other modules.\r
+  This is the role of the EFI_WIN_NT_THUNK_PROTOCOL.\r
+\r
+  The mWinNtThunkTable exists so that a change to EFI_WIN_NT_THUNK_PROTOCOL\r
+  will cause an error in initializing the array if all the member functions\r
+  are not added. It looks like adding a element to end and not initializing\r
+  it may cause the table to be initaliized with the members at the end being\r
+  set to zero. This is bad as jumping to zero will case the NT32 to crash.\r
+\r
+  All the member functions in mWinNtThunkTable are Win32\r
+  API calls, so please reference Microsoft documentation.\r
+\r
+\r
+  gWinNt is a a public exported global that contains the initialized\r
+  data.\r
+\r
+**/\r
+\r
+#include "WinHost.h"\r
+\r
+UINTN\r
+SecWriteStdErr (\r
+  IN UINT8     *Buffer,\r
+  IN UINTN     NumberOfBytes\r
+  )\r
+{\r
+  return 0;\r
+}\r
+\r
+\r
+EFI_STATUS\r
+SecConfigStdIn (\r
+  VOID\r
+  )\r
+{\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+UINTN\r
+SecWriteStdOut (\r
+  IN UINT8     *Buffer,\r
+  IN UINTN     NumberOfBytes\r
+  )\r
+{\r
+  return 0;\r
+}\r
+\r
+BOOLEAN\r
+SecPollStdIn (\r
+  VOID\r
+  )\r
+{\r
+  return FALSE;\r
+}\r
+\r
+UINTN\r
+SecReadStdIn (\r
+  IN UINT8     *Buffer,\r
+  IN UINTN     NumberOfBytes\r
+  )\r
+{\r
+  return 0;\r
+}\r
+\r
+\r
+VOID *\r
+SecAlloc (\r
+  IN  UINTN Size\r
+  )\r
+{\r
+  return malloc ((size_t)Size);\r
+}\r
+\r
+BOOLEAN\r
+SecFree (\r
+  IN  VOID *Ptr\r
+  )\r
+{\r
+  if (EfiSystemMemoryRange (Ptr)) {\r
+    // If an address range is in the EFI memory map it was alloced via EFI.\r
+    // So don't free those ranges and let the caller know.\r
+    return FALSE;\r
+  }\r
+\r
+  free (Ptr);\r
+  return TRUE;\r
+}\r
+\r
+VOID\r
+SecSetTimer (\r
+  IN  UINT64                  TimerPeriod,\r
+  IN  EMU_SET_TIMER_CALLBACK  Callback\r
+)\r
+{\r
+}\r
+\r
+VOID\r
+SecInitializeThunk (\r
+  VOID\r
+)\r
+{\r
+}\r
+\r
+VOID\r
+SecEnableInterrupt (\r
+  VOID\r
+  )\r
+{\r
+}\r
+\r
+\r
+VOID\r
+SecDisableInterrupt (\r
+  VOID\r
+  )\r
+{\r
+}\r
+\r
+\r
+UINT64\r
+SecQueryPerformanceFrequency (\r
+  VOID\r
+  )\r
+{\r
+  // Hard code to nanoseconds\r
+  return 1000000000ULL;\r
+}\r
+\r
+UINT64\r
+SecQueryPerformanceCounter (\r
+  VOID\r
+  )\r
+{\r
+  return 0;\r
+}\r
+\r
+\r
+\r
+VOID\r
+SecSleep (\r
+  IN  UINT64 Nanoseconds\r
+  )\r
+{\r
+  Sleep ((DWORD)DivU64x32 (Nanoseconds, 1000000));\r
+}\r
+\r
+\r
+VOID\r
+SecCpuSleep (\r
+  VOID\r
+  )\r
+{\r
+  Sleep (1);\r
+}\r
+\r
+\r
+VOID\r
+SecExit (\r
+  UINTN   Status\r
+  )\r
+{\r
+  exit ((int)Status);\r
+}\r
+\r
+\r
+VOID\r
+SecGetTime (\r
+  OUT  EFI_TIME               *Time,\r
+  OUT EFI_TIME_CAPABILITIES   *Capabilities OPTIONAL\r
+  )\r
+{\r
+}\r
+\r
+EFI_STATUS\r
+SecSetTime (\r
+  IN  EFI_TIME               *Time\r
+)\r
+{\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+EMU_THUNK_PROTOCOL gEmuThunkProtocol = {\r
+  SecWriteStdErr,\r
+  SecConfigStdIn,\r
+  SecWriteStdOut,\r
+  SecReadStdIn,\r
+  SecPollStdIn,\r
+  SecAlloc,\r
+  NULL,\r
+  SecFree,\r
+  SecPeCoffGetEntryPoint,\r
+  PeCoffLoaderRelocateImageExtraAction,\r
+  PeCoffLoaderUnloadImageExtraAction,\r
+  SecEnableInterrupt,\r
+  SecDisableInterrupt,\r
+  SecQueryPerformanceFrequency,\r
+  SecQueryPerformanceCounter,\r
+  SecSleep,\r
+  SecCpuSleep,\r
+  SecExit,\r
+  SecGetTime,\r
+  SecSetTime,\r
+  SecSetTimer,\r
+  GetNextThunkProtocol\r
+};\r
+\r
+\r
+#pragma warning(default : 4996)\r
+#pragma warning(default : 4232)\r
+\r