From 3c859dfebb436487928eab4644a33ce05b1905ac Mon Sep 17 00:00:00 2001 From: Ruiyu Ni Date: Thu, 23 Aug 2018 13:02:52 +0800 Subject: 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 Reviewed-by: Hao A Wu Cc: Andrew Fish --- EmulatorPkg/Win/Host/WinHost.c | 940 ++++++++++++++++++++++++++ EmulatorPkg/Win/Host/WinHost.h | 200 ++++++ EmulatorPkg/Win/Host/WinHost.inf | 88 +++ EmulatorPkg/Win/Host/WinInclude.h | 75 ++ EmulatorPkg/Win/Host/WinMemoryAllocationLib.c | 178 +++++ EmulatorPkg/Win/Host/WinThunk.c | 228 +++++++ 6 files changed, 1709 insertions(+) create mode 100644 EmulatorPkg/Win/Host/WinHost.c create mode 100644 EmulatorPkg/Win/Host/WinHost.h create mode 100644 EmulatorPkg/Win/Host/WinHost.inf create mode 100644 EmulatorPkg/Win/Host/WinInclude.h create mode 100644 EmulatorPkg/Win/Host/WinMemoryAllocationLib.c create mode 100644 EmulatorPkg/Win/Host/WinThunk.c (limited to 'EmulatorPkg/Win') 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.
+(C) Copyright 2016 Hewlett Packard Enterprise Development LP
+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.
+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 +#include +#include "WinInclude.h" + +#include +#include +#include +#include + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +#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.
+# Portions copyright (c) 2008 - 2011, Apple Inc. All rights reserved.
+# +# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# +## + +[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.
+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.
+ + 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 +#include +#include + +#include + +/** + 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.
+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) + -- cgit v1.2.3