* [PATCH 01/12] EmulatorPkg/ThunkProtocolList: Fix VS build failure
2018-08-23 9:52 [PATCH 00/12] Add WinHost support in EmulatorPkg Ruiyu Ni
@ 2018-08-23 9:52 ` Ruiyu Ni
2018-08-23 9:52 ` [PATCH 02/12] EmulatorPkg/Win: Add Windows host support Ruiyu Ni
` (11 subsequent siblings)
12 siblings, 0 replies; 14+ messages in thread
From: Ruiyu Ni @ 2018-08-23 9:52 UTC (permalink / raw)
To: edk2-devel; +Cc: Andrdw Fish, Hao A Wu
VS compiler complains converting UINTN to UINT16 causes data lost.
Add typecast to fix the build failure.
Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Ruiyu Ni <ruiyu.ni@intel.com>
Cc: Andrdw Fish <afish@apple.com>
Cc: Hao A Wu <hao.a.wu@intel.com>
---
EmulatorPkg/Library/ThunkProtocolList/ThunkProtocolList.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/EmulatorPkg/Library/ThunkProtocolList/ThunkProtocolList.c b/EmulatorPkg/Library/ThunkProtocolList/ThunkProtocolList.c
index b2daa2bef5..9fa9e25e94 100644
--- a/EmulatorPkg/Library/ThunkProtocolList/ThunkProtocolList.c
+++ b/EmulatorPkg/Library/ThunkProtocolList/ThunkProtocolList.c
@@ -2,7 +2,7 @@
Emulator Thunk to abstract OS services from pure EFI code
Copyright (c) 2008 - 2011, Apple Inc. All rights reserved.<BR>
- Copyright (c) 2011, Intel Corporation. All rights reserved.<BR>
+ Copyright (c) 2011 - 2018, Intel Corporation. All rights reserved.<BR>
This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
@@ -82,7 +82,7 @@ AddThunkProtocol (
Private->EmuBusDriver = EmuBusDriver;
CopyMem (&Private->Data, ThunkIo, sizeof (EMU_IO_THUNK_PROTOCOL));
- Private->Data.Instance = Instance++;
+ Private->Data.Instance = (UINT16)Instance++;
Private->Data.ConfigString = StartString;
InsertTailList (&mThunkList, &Private->Link);
--
2.16.1.windows.1
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [PATCH 02/12] EmulatorPkg/Win: Add Windows host support
2018-08-23 9:52 [PATCH 00/12] Add WinHost support in EmulatorPkg Ruiyu Ni
2018-08-23 9:52 ` [PATCH 01/12] EmulatorPkg/ThunkProtocolList: Fix VS build failure Ruiyu Ni
@ 2018-08-23 9:52 ` Ruiyu Ni
2018-08-23 9:52 ` [PATCH 03/12] EmulatorPkg/Win: Enable source level debugging Ruiyu Ni
` (10 subsequent siblings)
12 siblings, 0 replies; 14+ messages in thread
From: Ruiyu Ni @ 2018-08-23 9:52 UTC (permalink / raw)
To: edk2-devel; +Cc: Hao Wu, Andrew Fish
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>
Cc: Hao Wu <hao.a.wu@intel.com>
Cc: Andrew Fish <afish@apple.com>
---
EmulatorPkg/EmulatorPkg.dsc | 7 +
EmulatorPkg/Win/Host/WinHost.c | 940 ++++++++++++++++++++++++++
EmulatorPkg/Win/Host/WinHost.h | 200 ++++++
EmulatorPkg/Win/Host/WinHost.inf | 88 +++
EmulatorPkg/Win/Host/WinInclude.h | 75 ++
EmulatorPkg/Win/Host/WinMemoryAllocationLib.c | 178 +++++
EmulatorPkg/Win/Host/WinThunk.c | 228 +++++++
7 files changed, 1716 insertions(+)
create mode 100644 EmulatorPkg/Win/Host/WinHost.c
create mode 100644 EmulatorPkg/Win/Host/WinHost.h
create mode 100644 EmulatorPkg/Win/Host/WinHost.inf
create mode 100644 EmulatorPkg/Win/Host/WinInclude.h
create mode 100644 EmulatorPkg/Win/Host/WinMemoryAllocationLib.c
create mode 100644 EmulatorPkg/Win/Host/WinThunk.c
diff --git a/EmulatorPkg/EmulatorPkg.dsc b/EmulatorPkg/EmulatorPkg.dsc
index ef56a86a32..8afeaf5fa3 100644
--- a/EmulatorPkg/EmulatorPkg.dsc
+++ b/EmulatorPkg/EmulatorPkg.dsc
@@ -251,6 +251,13 @@ [Components]
EmulatorPkg/Unix/Host/Host.inf
!endif
+!ifdef $(WIN_SEC_BUILD)
+ ##
+ # Emulator, OS WIN application
+ ##
+ EmulatorPkg/Win/Host/WinHost.inf
+!endif
+
!ifndef $(SKIP_MAIN_BUILD)
#
# Generic SEC
diff --git a/EmulatorPkg/Win/Host/WinHost.c b/EmulatorPkg/Win/Host/WinHost.c
new file mode 100644
index 0000000000..22399f18b9
--- /dev/null
+++ b/EmulatorPkg/Win/Host/WinHost.c
@@ -0,0 +1,940 @@
+/**@file
+ WinNt emulator of pre-SEC phase. It's really a Win32 application, but this is
+ Ok since all the other modules for NT32 are NOT Win32 applications.
+
+ This program gets NT32 PCD setting and figures out what the memory layout
+ will be, how may FD's will be loaded and also what the boot mode is.
+
+ This code produces 128 K of temporary memory for the SEC stack by directly
+ allocate memory space with ReadWrite and Execute attribute.
+
+Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
+(C) Copyright 2016 Hewlett Packard Enterprise Development LP<BR>
+This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+**/
+
+#include "WinHost.h"
+
+#ifndef SE_TIME_ZONE_NAME
+#define SE_TIME_ZONE_NAME TEXT("SeTimeZonePrivilege")
+#endif
+
+//
+// Default information about where the FD is located.
+// This array gets filled in with information from PcdWinNtFirmwareVolume
+// The number of array elements is allocated base on parsing
+// PcdWinNtFirmwareVolume and the memory is never freed.
+//
+UINTN gFdInfoCount = 0;
+NT_FD_INFO *gFdInfo;
+
+//
+// Array that supports seperate memory rantes.
+// The memory ranges are set by PcdWinNtMemorySizeForSecMain.
+// The number of array elements is allocated base on parsing
+// PcdWinNtMemorySizeForSecMain value and the memory is never freed.
+//
+UINTN gSystemMemoryCount = 0;
+NT_SYSTEM_MEMORY *gSystemMemory;
+
+/*++
+
+Routine Description:
+ This service is called from Index == 0 until it returns EFI_UNSUPPORTED.
+ It allows discontinuous memory regions to be supported by the emulator.
+ It uses gSystemMemory[] and gSystemMemoryCount that were created by
+ parsing the host environment variable EFI_MEMORY_SIZE.
+ The size comes from the varaible and the address comes from the call to
+ UnixOpenFile.
+
+Arguments:
+ Index - Which memory region to use
+ MemoryBase - Return Base address of memory region
+ MemorySize - Return size in bytes of the memory region
+
+Returns:
+ EFI_SUCCESS - If memory region was mapped
+ EFI_UNSUPPORTED - If Index is not supported
+
+**/
+EFI_STATUS
+WinPeiAutoScan (
+ IN UINTN Index,
+ OUT EFI_PHYSICAL_ADDRESS *MemoryBase,
+ OUT UINT64 *MemorySize
+ )
+{
+ if (Index >= gSystemMemoryCount) {
+ return EFI_UNSUPPORTED;
+ }
+
+ //
+ // Allocate enough memory space for emulator
+ //
+ gSystemMemory[Index].Memory = (EFI_PHYSICAL_ADDRESS) (UINTN) VirtualAlloc (NULL, (SIZE_T) (gSystemMemory[Index].Size), MEM_COMMIT, PAGE_EXECUTE_READWRITE);
+ if (gSystemMemory[Index].Memory == 0) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ *MemoryBase = gSystemMemory[Index].Memory;
+ *MemorySize = gSystemMemory[Index].Size;
+
+ return EFI_SUCCESS;
+}
+
+/*++
+
+Routine Description:
+ Return the FD Size and base address. Since the FD is loaded from a
+ file into host memory only the SEC will know it's address.
+
+Arguments:
+ Index - Which FD, starts at zero.
+ FdSize - Size of the FD in bytes
+ FdBase - Start address of the FD. Assume it points to an FV Header
+ FixUp - Difference between actual FD address and build address
+
+Returns:
+ EFI_SUCCESS - Return the Base address and size of the FV
+ EFI_UNSUPPORTED - Index does nto map to an FD in the system
+
+**/
+EFI_STATUS
+WinFdAddress (
+ IN UINTN Index,
+ IN OUT EFI_PHYSICAL_ADDRESS *FdBase,
+ IN OUT UINT64 *FdSize,
+ IN OUT EFI_PHYSICAL_ADDRESS *FixUp
+ )
+{
+ if (Index >= gFdInfoCount) {
+ return EFI_UNSUPPORTED;
+ }
+
+
+ *FdBase = (EFI_PHYSICAL_ADDRESS)(UINTN)gFdInfo[Index].Address;
+ *FdSize = (UINT64)gFdInfo[Index].Size;
+ *FixUp = 0;
+
+ if (*FdBase == 0 && *FdSize == 0) {
+ return EFI_UNSUPPORTED;
+ }
+
+ if (Index == 0) {
+ //
+ // FD 0 has XIP code and well known PCD values
+ // If the memory buffer could not be allocated at the FD build address
+ // the Fixup is the difference.
+ //
+ *FixUp = *FdBase - PcdGet64 (PcdEmuFdBaseAddress);
+ }
+
+ return EFI_SUCCESS;
+}
+
+/*++
+
+Routine Description:
+ Since the SEC is the only Unix program in stack it must export
+ an interface to do POSIX calls. gUnix is initialized in UnixThunk.c.
+
+Arguments:
+ InterfaceSize - sizeof (EFI_WIN_NT_THUNK_PROTOCOL);
+ InterfaceBase - Address of the gUnix global
+
+Returns:
+ EFI_SUCCESS - Data returned
+
+**/
+VOID *
+WinThunk (
+ VOID
+ )
+{
+ return &gEmuThunkProtocol;
+}
+
+
+EMU_THUNK_PPI mSecEmuThunkPpi = {
+ WinPeiAutoScan,
+ WinFdAddress,
+ WinThunk
+};
+
+VOID
+SecPrint (
+ CHAR8 *Format,
+ ...
+ )
+{
+ va_list Marker;
+ UINTN CharCount;
+ CHAR8 Buffer[0x1000];
+
+ va_start (Marker, Format);
+
+ _vsnprintf (Buffer, sizeof (Buffer), Format, Marker);
+
+ va_end (Marker);
+
+ CharCount = strlen (Buffer);
+ WriteFile (
+ GetStdHandle (STD_OUTPUT_HANDLE),
+ Buffer,
+ (DWORD)CharCount,
+ (LPDWORD)&CharCount,
+ NULL
+ );
+}
+
+/*++
+
+Routine Description:
+ Check to see if an address range is in the EFI GCD memory map.
+
+ This is all of GCD for system memory passed to DXE Core. FV
+ mapping and other device mapped into system memory are not
+ inlcuded in the check.
+
+Arguments:
+ Index - Which memory region to use
+ MemoryBase - Return Base address of memory region
+ MemorySize - Return size in bytes of the memory region
+
+Returns:
+ TRUE - Address is in the EFI GCD memory map
+ FALSE - Address is NOT in memory map
+
+**/
+BOOLEAN
+EfiSystemMemoryRange (
+ IN VOID *MemoryAddress
+ )
+{
+ UINTN Index;
+ EFI_PHYSICAL_ADDRESS MemoryBase;
+
+ MemoryBase = (EFI_PHYSICAL_ADDRESS)(UINTN)MemoryAddress;
+ for (Index = 0; Index < gSystemMemoryCount; Index++) {
+ if ((MemoryBase >= gSystemMemory[Index].Memory) &&
+ (MemoryBase < (gSystemMemory[Index].Memory + gSystemMemory[Index].Size)) ) {
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
+
+
+EFI_STATUS
+WinNtOpenFile (
+ IN CHAR16 *FileName, OPTIONAL
+ IN UINT32 MapSize,
+ IN DWORD CreationDisposition,
+ IN OUT VOID **BaseAddress,
+ OUT UINTN *Length
+ )
+/*++
+
+Routine Description:
+ Opens and memory maps a file using WinNt services. If *BaseAddress is non zero
+ the process will try and allocate the memory starting at BaseAddress.
+
+Arguments:
+ FileName - The name of the file to open and map
+ MapSize - The amount of the file to map in bytes
+ CreationDisposition - The flags to pass to CreateFile(). Use to create new files for
+ memory emulation, and exiting files for firmware volume emulation
+ BaseAddress - The base address of the mapped file in the user address space.
+ If *BaseAddress is 0, the new memory region is used.
+ If *BaseAddress is not 0, the request memory region is used for
+ the mapping of the file into the process space.
+ Length - The size of the mapped region in bytes
+
+Returns:
+ EFI_SUCCESS - The file was opened and mapped.
+ EFI_NOT_FOUND - FileName was not found in the current directory
+ EFI_DEVICE_ERROR - An error occured attempting to map the opened file
+
+--*/
+{
+ HANDLE NtFileHandle;
+ HANDLE NtMapHandle;
+ VOID *VirtualAddress;
+ UINTN FileSize;
+
+ //
+ // Use Win API to open/create a file
+ //
+ NtFileHandle = INVALID_HANDLE_VALUE;
+ if (FileName != NULL) {
+ NtFileHandle = CreateFile (
+ FileName,
+ GENERIC_READ | GENERIC_WRITE | GENERIC_EXECUTE,
+ FILE_SHARE_READ,
+ NULL,
+ CreationDisposition,
+ FILE_ATTRIBUTE_NORMAL,
+ NULL
+ );
+ if (NtFileHandle == INVALID_HANDLE_VALUE) {
+ return EFI_NOT_FOUND;
+ }
+ }
+ //
+ // Map the open file into a memory range
+ //
+ NtMapHandle = CreateFileMapping (
+ NtFileHandle,
+ NULL,
+ PAGE_EXECUTE_READWRITE,
+ 0,
+ MapSize,
+ NULL
+ );
+ if (NtMapHandle == NULL) {
+ return EFI_DEVICE_ERROR;
+ }
+ //
+ // Get the virtual address (address in the emulator) of the mapped file
+ //
+ VirtualAddress = MapViewOfFileEx (
+ NtMapHandle,
+ FILE_MAP_EXECUTE | FILE_MAP_ALL_ACCESS,
+ 0,
+ 0,
+ MapSize,
+ *BaseAddress
+ );
+ if (VirtualAddress == NULL) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ if (MapSize == 0) {
+ //
+ // Seek to the end of the file to figure out the true file size.
+ //
+ FileSize = SetFilePointer (
+ NtFileHandle,
+ 0,
+ NULL,
+ FILE_END
+ );
+ if (FileSize == -1) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ *Length = FileSize;
+ } else {
+ *Length = MapSize;
+ }
+
+ *BaseAddress = VirtualAddress;
+
+ return EFI_SUCCESS;
+}
+
+INTN
+EFIAPI
+main (
+ IN INTN Argc,
+ IN CHAR8 **Argv,
+ IN CHAR8 **Envp
+ )
+/*++
+
+Routine Description:
+ Main entry point to SEC for WinNt. This is a Windows program
+
+Arguments:
+ Argc - Number of command line arguments
+ Argv - Array of command line argument strings
+ Envp - Array of environment variable strings
+
+Returns:
+ 0 - Normal exit
+ 1 - Abnormal exit
+
+--*/
+{
+ EFI_STATUS Status;
+ HANDLE Token;
+ TOKEN_PRIVILEGES TokenPrivileges;
+ VOID *TemporaryRam;
+ UINT32 TemporaryRamSize;
+ VOID *EmuMagicPage;
+ UINTN Index;
+ UINTN Index1;
+ CHAR16 *FileName;
+ CHAR16 *FileNamePtr;
+ BOOLEAN Done;
+ EFI_PEI_FILE_HANDLE FileHandle;
+ VOID *SecFile;
+ CHAR16 *MemorySizeStr;
+ CHAR16 *FirmwareVolumesStr;
+ UINT32 ProcessAffinityMask;
+ UINT32 SystemAffinityMask;
+ INT32 LowBit;
+
+ //
+ // Enable the privilege so that RTC driver can successfully run SetTime()
+ //
+ OpenProcessToken (GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES|TOKEN_QUERY, &Token);
+ if (LookupPrivilegeValue(NULL, SE_TIME_ZONE_NAME, &TokenPrivileges.Privileges[0].Luid)) {
+ TokenPrivileges.PrivilegeCount = 1;
+ TokenPrivileges.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
+ AdjustTokenPrivileges(Token, FALSE, &TokenPrivileges, 0, (PTOKEN_PRIVILEGES) NULL, 0);
+ }
+
+ MemorySizeStr = (CHAR16 *) PcdGetPtr (PcdEmuMemorySize);
+ FirmwareVolumesStr = (CHAR16 *) PcdGetPtr (PcdEmuFirmwareVolume);
+
+ SecPrint ("\nEDK II WIN Host Emulation Environment from http://www.tianocore.org/edk2/\n");
+
+ //
+ // Determine the first thread available to this process.
+ //
+ if (GetProcessAffinityMask (GetCurrentProcess (), &ProcessAffinityMask, &SystemAffinityMask)) {
+ LowBit = (INT32)LowBitSet32 (ProcessAffinityMask);
+ if (LowBit != -1) {
+ //
+ // Force the system to bind the process to a single thread to work
+ // around odd semaphore type crashes.
+ //
+ SetProcessAffinityMask (GetCurrentProcess (), (INTN)(BIT0 << LowBit));
+ }
+ }
+
+ //
+ // Make some Windows calls to Set the process to the highest priority in the
+ // idle class. We need this to have good performance.
+ //
+ SetPriorityClass (GetCurrentProcess (), IDLE_PRIORITY_CLASS);
+ SetThreadPriority (GetCurrentThread (), THREAD_PRIORITY_HIGHEST);
+
+ SecInitializeThunk ();
+ //
+ // PPIs pased into PEI_CORE
+ //
+ AddThunkPpi (EFI_PEI_PPI_DESCRIPTOR_PPI, &gEmuThunkPpiGuid, &mSecEmuThunkPpi);
+
+ //
+ // Allocate space for gSystemMemory Array
+ //
+ gSystemMemoryCount = CountSeparatorsInString (MemorySizeStr, '!') + 1;
+ gSystemMemory = calloc (gSystemMemoryCount, sizeof (NT_SYSTEM_MEMORY));
+ if (gSystemMemory == NULL) {
+ SecPrint ("ERROR : Can not allocate memory for %S. Exiting.\n", MemorySizeStr);
+ exit (1);
+ }
+
+ //
+ // Allocate space for gSystemMemory Array
+ //
+ gFdInfoCount = CountSeparatorsInString (FirmwareVolumesStr, '!') + 1;
+ gFdInfo = calloc (gFdInfoCount, sizeof (NT_FD_INFO));
+ if (gFdInfo == NULL) {
+ SecPrint ("ERROR : Can not allocate memory for %S. Exiting.\n", FirmwareVolumesStr);
+ exit (1);
+ }
+ //
+ // Setup Boot Mode.
+ //
+ SecPrint (" BootMode 0x%02x\n", PcdGet32 (PcdEmuBootMode));
+
+ //
+ // Allocate 128K memory to emulate temp memory for PEI.
+ // on a real platform this would be SRAM, or using the cache as RAM.
+ // Set TemporaryRam to zero so WinNtOpenFile will allocate a new mapping
+ //
+ TemporaryRamSize = TEMPORARY_RAM_SIZE;
+ TemporaryRam = VirtualAlloc (NULL, (SIZE_T) (TemporaryRamSize), MEM_COMMIT, PAGE_EXECUTE_READWRITE);
+ if (TemporaryRam == NULL) {
+ SecPrint ("ERROR : Can not allocate enough space for SecStack\n");
+ exit (1);
+ }
+ SetMemN (TemporaryRam, TemporaryRamSize, PcdGet32 (PcdInitValueInTempStack));
+
+ SecPrint (" OS Emulator passing in %u KB of temp RAM at 0x%08lx to SEC\n",
+ TemporaryRamSize / SIZE_1KB,
+ TemporaryRam
+ );
+
+ //
+ // If enabled use the magic page to communicate between modules
+ // This replaces the PI PeiServicesTable pointer mechanism that
+ // deos not work in the emulator. It also allows the removal of
+ // writable globals from SEC, PEI_CORE (libraries), PEIMs
+ //
+ EmuMagicPage = (VOID *)(UINTN)(FixedPcdGet64 (PcdPeiServicesTablePage) & MAX_UINTN);
+ if (EmuMagicPage != NULL) {
+ UINT64 Size;
+ Status = WinNtOpenFile (
+ NULL,
+ SIZE_4KB,
+ 0,
+ &EmuMagicPage,
+ &Size
+ );
+ if (EFI_ERROR (Status)) {
+ SecPrint ("ERROR : Could not allocate PeiServicesTablePage @ %p\n", EmuMagicPage);
+ return EFI_DEVICE_ERROR;
+ }
+ }
+
+ //
+ // Open All the firmware volumes and remember the info in the gFdInfo global
+ // Meanwhile, find the SEC Core.
+ //
+ FileNamePtr = AllocateCopyPool (StrSize (FirmwareVolumesStr), FirmwareVolumesStr);
+ if (FileNamePtr == NULL) {
+ SecPrint ("ERROR : Can not allocate memory for firmware volume string\n");
+ exit (1);
+ }
+
+ for (Done = FALSE, Index = 0, SecFile = NULL; !Done; Index++) {
+ FileName = FileNamePtr;
+ for (Index1 = 0; (FileNamePtr[Index1] != '!') && (FileNamePtr[Index1] != 0); Index1++)
+ ;
+ if (FileNamePtr[Index1] == 0) {
+ Done = TRUE;
+ } else {
+ FileNamePtr[Index1] = '\0';
+ FileNamePtr = &FileNamePtr[Index1 + 1];
+ }
+
+ //
+ // Open the FD and remember where it got mapped into our processes address space
+ //
+ Status = WinNtOpenFile (
+ FileName,
+ 0,
+ OPEN_EXISTING,
+ &gFdInfo[Index].Address,
+ &gFdInfo[Index].Size
+ );
+ if (EFI_ERROR (Status)) {
+ SecPrint ("ERROR : Can not open Firmware Device File %S (0x%X). Exiting.\n", FileName, Status);
+ exit (1);
+ }
+
+ SecPrint (" FD loaded from %S\n", FileName);
+
+ if (SecFile == NULL) {
+ //
+ // Assume the beginning of the FD is an FV and look for the SEC Core.
+ // Load the first one we find.
+ //
+ FileHandle = NULL;
+ Status = PeiServicesFfsFindNextFile (
+ EFI_FV_FILETYPE_SECURITY_CORE,
+ (EFI_PEI_FV_HANDLE)gFdInfo[Index].Address,
+ &FileHandle
+ );
+ if (!EFI_ERROR (Status)) {
+ Status = PeiServicesFfsFindSectionData (EFI_SECTION_PE32, FileHandle, &SecFile);
+ if (!EFI_ERROR (Status)) {
+ SecPrint (" contains SEC Core");
+ }
+ }
+ }
+
+ SecPrint ("\n");
+ }
+ //
+ // Calculate memory regions and store the information in the gSystemMemory
+ // global for later use. The autosizing code will use this data to
+ // map this memory into the SEC process memory space.
+ //
+ for (Index = 0, Done = FALSE; !Done; Index++) {
+ //
+ // Save the size of the memory and make a Unicode filename SystemMemory00, ...
+ //
+ gSystemMemory[Index].Size = _wtoi (MemorySizeStr) * SIZE_1MB;
+
+ //
+ // Find the next region
+ //
+ for (Index1 = 0; MemorySizeStr[Index1] != '!' && MemorySizeStr[Index1] != 0; Index1++)
+ ;
+ if (MemorySizeStr[Index1] == 0) {
+ Done = TRUE;
+ }
+
+ MemorySizeStr = MemorySizeStr + Index1 + 1;
+ }
+
+ SecPrint ("\n");
+
+ //
+ // Hand off to SEC Core
+ //
+ SecLoadSecCore ((UINTN)TemporaryRam, TemporaryRamSize, gFdInfo[0].Address, gFdInfo[0].Size, SecFile);
+
+ //
+ // If we get here, then the SEC Core returned. This is an error as SEC should
+ // always hand off to PEI Core and then on to DXE Core.
+ //
+ SecPrint ("ERROR : SEC returned\n");
+ exit (1);
+}
+
+VOID
+SecLoadSecCore (
+ IN UINTN TemporaryRam,
+ IN UINTN TemporaryRamSize,
+ IN VOID *BootFirmwareVolumeBase,
+ IN UINTN BootFirmwareVolumeSize,
+ IN VOID *SecCorePe32File
+ )
+/*++
+
+Routine Description:
+ This is the service to load the SEC Core from the Firmware Volume
+
+Arguments:
+ TemporaryRam - Memory to use for SEC.
+ TemporaryRamSize - Size of Memory to use for SEC
+ BootFirmwareVolumeBase - Start of the Boot FV
+ SecCorePe32File - SEC Core PE32
+
+Returns:
+ Success means control is transfered and thus we should never return
+
+--*/
+{
+ EFI_STATUS Status;
+ VOID *TopOfStack;
+ VOID *SecCoreEntryPoint;
+ EFI_SEC_PEI_HAND_OFF *SecCoreData;
+ UINTN SecStackSize;
+
+ //
+ // Compute Top Of Memory for Stack and PEI Core Allocations
+ //
+ SecStackSize = TemporaryRamSize >> 1;
+
+ //
+ // |-----------| <---- TemporaryRamBase + TemporaryRamSize
+ // | Heap |
+ // | |
+ // |-----------| <---- StackBase / PeiTemporaryMemoryBase
+ // | |
+ // | Stack |
+ // |-----------| <---- TemporaryRamBase
+ //
+ TopOfStack = (VOID *)(TemporaryRam + SecStackSize);
+
+ //
+ // Reservet space for storing PeiCore's parament in stack.
+ //
+ TopOfStack = (VOID *)((UINTN)TopOfStack - sizeof (EFI_SEC_PEI_HAND_OFF) - CPU_STACK_ALIGNMENT);
+ TopOfStack = ALIGN_POINTER (TopOfStack, CPU_STACK_ALIGNMENT);
+
+ //
+ // Bind this information into the SEC hand-off state
+ //
+ SecCoreData = (EFI_SEC_PEI_HAND_OFF*)(UINTN)TopOfStack;
+ SecCoreData->DataSize = sizeof (EFI_SEC_PEI_HAND_OFF);
+ SecCoreData->BootFirmwareVolumeBase = BootFirmwareVolumeBase;
+ SecCoreData->BootFirmwareVolumeSize = BootFirmwareVolumeSize;
+ SecCoreData->TemporaryRamBase = (VOID*)TemporaryRam;
+ SecCoreData->TemporaryRamSize = TemporaryRamSize;
+ SecCoreData->StackBase = SecCoreData->TemporaryRamBase;
+ SecCoreData->StackSize = SecStackSize;
+ SecCoreData->PeiTemporaryRamBase = (VOID*) ((UINTN) SecCoreData->TemporaryRamBase + SecStackSize);
+ SecCoreData->PeiTemporaryRamSize = TemporaryRamSize - SecStackSize;
+
+ //
+ // Load the PEI Core from a Firmware Volume
+ //
+ Status = SecPeCoffGetEntryPoint (
+ SecCorePe32File,
+ &SecCoreEntryPoint
+ );
+ if (EFI_ERROR (Status)) {
+ return ;
+ }
+
+ //
+ // Transfer control to the SEC Core
+ //
+ SwitchStack (
+ (SWITCH_STACK_ENTRY_POINT)SecCoreEntryPoint,
+ SecCoreData,
+ GetThunkPpiList (),
+ TopOfStack
+ );
+ //
+ // If we get here, then the SEC Core returned. This is an error
+ //
+ return ;
+}
+
+RETURN_STATUS
+EFIAPI
+SecPeCoffGetEntryPoint (
+ IN VOID *Pe32Data,
+ IN OUT VOID **EntryPoint
+ )
+{
+ EFI_STATUS Status;
+ PE_COFF_LOADER_IMAGE_CONTEXT ImageContext;
+
+ ZeroMem (&ImageContext, sizeof (ImageContext));
+ ImageContext.Handle = Pe32Data;
+
+ ImageContext.ImageRead = (PE_COFF_LOADER_READ_FILE) SecImageRead;
+
+ Status = PeCoffLoaderGetImageInfo (&ImageContext);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ //
+ // Allocate space in NT (not emulator) memory with ReadWrite and Execute attribute.
+ // Extra space is for alignment
+ //
+ ImageContext.ImageAddress = (EFI_PHYSICAL_ADDRESS) (UINTN) VirtualAlloc (NULL, (SIZE_T) (ImageContext.ImageSize + (ImageContext.SectionAlignment * 2)), MEM_COMMIT, PAGE_EXECUTE_READWRITE);
+ if (ImageContext.ImageAddress == 0) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ //
+ // Align buffer on section boundary
+ //
+ ImageContext.ImageAddress += ImageContext.SectionAlignment - 1;
+ ImageContext.ImageAddress &= ~((EFI_PHYSICAL_ADDRESS)ImageContext.SectionAlignment - 1);
+
+ Status = PeCoffLoaderLoadImage (&ImageContext);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Status = PeCoffLoaderRelocateImage (&ImageContext);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ *EntryPoint = (VOID *)(UINTN)ImageContext.EntryPoint;
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+EFIAPI
+SecImageRead (
+ IN VOID *FileHandle,
+ IN UINTN FileOffset,
+ IN OUT UINTN *ReadSize,
+ OUT VOID *Buffer
+ )
+/*++
+
+Routine Description:
+ Support routine for the PE/COFF Loader that reads a buffer from a PE/COFF file
+
+Arguments:
+ FileHandle - The handle to the PE/COFF file
+ FileOffset - The offset, in bytes, into the file to read
+ ReadSize - The number of bytes to read from the file starting at FileOffset
+ Buffer - A pointer to the buffer to read the data into.
+
+Returns:
+ EFI_SUCCESS - ReadSize bytes of data were read into Buffer from the PE/COFF file starting at FileOffset
+
+--*/
+{
+ CHAR8 *Destination8;
+ CHAR8 *Source8;
+ UINTN Length;
+
+ Destination8 = Buffer;
+ Source8 = (CHAR8 *) ((UINTN) FileHandle + FileOffset);
+ Length = *ReadSize;
+ while (Length--) {
+ *(Destination8++) = *(Source8++);
+ }
+
+ return EFI_SUCCESS;
+}
+
+CHAR16 *
+AsciiToUnicode (
+ IN CHAR8 *Ascii,
+ IN UINTN *StrLen OPTIONAL
+ )
+/*++
+
+Routine Description:
+ Convert the passed in Ascii string to Unicode.
+ Optionally return the length of the strings.
+
+Arguments:
+ Ascii - Ascii string to convert
+ StrLen - Length of string
+
+Returns:
+ Pointer to malloc'ed Unicode version of Ascii
+
+--*/
+{
+ UINTN Index;
+ CHAR16 *Unicode;
+
+ //
+ // Allocate a buffer for unicode string
+ //
+ for (Index = 0; Ascii[Index] != '\0'; Index++)
+ ;
+ Unicode = malloc ((Index + 1) * sizeof (CHAR16));
+ if (Unicode == NULL) {
+ return NULL;
+ }
+
+ for (Index = 0; Ascii[Index] != '\0'; Index++) {
+ Unicode[Index] = (CHAR16) Ascii[Index];
+ }
+
+ Unicode[Index] = '\0';
+
+ if (StrLen != NULL) {
+ *StrLen = Index;
+ }
+
+ return Unicode;
+}
+
+UINTN
+CountSeparatorsInString (
+ IN CONST CHAR16 *String,
+ IN CHAR16 Separator
+ )
+/*++
+
+Routine Description:
+ Count the number of separators in String
+
+Arguments:
+ String - String to process
+ Separator - Item to count
+
+Returns:
+ Number of Separator in String
+
+--*/
+{
+ UINTN Count;
+
+ for (Count = 0; *String != '\0'; String++) {
+ if (*String == Separator) {
+ Count++;
+ }
+ }
+
+ return Count;
+}
+
+
+VOID
+EFIAPI
+PeCoffLoaderRelocateImageExtraAction (
+ IN OUT PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext
+ )
+{
+ VOID *DllEntryPoint;
+ CHAR16 *DllFileName;
+ HMODULE Library;
+ UINTN Index;
+
+ ASSERT (ImageContext != NULL);
+ //
+ // If we load our own PE COFF images the Windows debugger can not source
+ // level debug our code. If a valid PDB pointer exists usw it to load
+ // the *.dll file as a library using Windows* APIs. This allows
+ // source level debug. The image is still loaded and relocated
+ // in the Framework memory space like on a real system (by the code above),
+ // but the entry point points into the DLL loaded by the code bellow.
+ //
+
+ DllEntryPoint = NULL;
+
+ //
+ // Load the DLL if it's not an EBC image.
+ //
+ if ((ImageContext->PdbPointer != NULL) &&
+ (ImageContext->Machine != EFI_IMAGE_MACHINE_EBC)) {
+ //
+ // Convert filename from ASCII to Unicode
+ //
+ DllFileName = AsciiToUnicode (ImageContext->PdbPointer, &Index);
+
+ //
+ // Check that we have a valid filename
+ //
+ if (Index < 5 || DllFileName[Index - 4] != '.') {
+ free (DllFileName);
+
+ //
+ // Never return an error if PeCoffLoaderRelocateImage() succeeded.
+ // The image will run, but we just can't source level debug. If we
+ // return an error the image will not run.
+ //
+ return;
+ }
+ //
+ // Replace .PDB with .DLL on the filename
+ //
+ DllFileName[Index - 3] = 'D';
+ DllFileName[Index - 2] = 'L';
+ DllFileName[Index - 1] = 'L';
+
+ //
+ // Load the .DLL file into the user process's address space for source
+ // level debug
+ //
+ Library = LoadLibraryEx (DllFileName, NULL, DONT_RESOLVE_DLL_REFERENCES);
+ if (Library != NULL) {
+ //
+ // InitializeDriver is the entry point we put in all our EFI DLL's. The
+ // DONT_RESOLVE_DLL_REFERENCES argument to LoadLIbraryEx() suppresses the
+ // normal DLL entry point of DllMain, and prevents other modules that are
+ // referenced in side the DllFileName from being loaded. There is no error
+ // checking as the we can point to the PE32 image loaded by Tiano. This
+ // step is only needed for source level debugging
+ //
+ DllEntryPoint = (VOID *) (UINTN) GetProcAddress (Library, "InitializeDriver");
+
+ }
+
+ if ((Library != NULL) && (DllEntryPoint != NULL)) {
+ ImageContext->EntryPoint = (EFI_PHYSICAL_ADDRESS) (UINTN) DllEntryPoint;
+ SecPrint ("LoadLibraryEx (%S,\n NULL, DONT_RESOLVE_DLL_REFERENCES)\n", DllFileName);
+ } else {
+ SecPrint ("WARNING: No source level debug %S. \n", DllFileName);
+ }
+
+ free (DllFileName);
+ }
+}
+
+VOID
+EFIAPI
+PeCoffLoaderUnloadImageExtraAction (
+ IN PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext
+)
+{
+ ASSERT (ImageContext != NULL);
+}
+
+
+VOID
+_ModuleEntryPoint (
+ VOID
+ )
+{
+}
diff --git a/EmulatorPkg/Win/Host/WinHost.h b/EmulatorPkg/Win/Host/WinHost.h
new file mode 100644
index 0000000000..c73ba17e74
--- /dev/null
+++ b/EmulatorPkg/Win/Host/WinHost.h
@@ -0,0 +1,200 @@
+/**@file
+
+Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+
+Module Name:
+ WinHost.h
+
+Abstract:
+ Include file for Windows Host
+
+**/
+#ifndef _HOST_H_
+#define _HOST_H_
+
+#include <stdio.h>
+#include <time.h>
+#include "WinInclude.h"
+
+#include <PiPei.h>
+#include <IndustryStandard/PeImage.h>
+#include <Ppi/EmuThunk.h>
+#include <Protocol/EmuThunk.h>
+
+
+#include <Library/BaseLib.h>
+#include <Library/PeCoffLib.h>
+#include <Library/DebugLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/ThunkPpiList.h>
+#include <Library/ThunkProtocolList.h>
+#include <Library/PcdLib.h>
+#include <Library/PrintLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/PeiServicesLib.h>
+#include <Library/PeCoffExtraActionLib.h>
+
+
+#define TEMPORARY_RAM_SIZE 0x20000
+
+typedef struct {
+ VOID *Address;
+ UINTN Size;
+} NT_FD_INFO;
+
+typedef struct {
+ EFI_PHYSICAL_ADDRESS Memory;
+ UINT64 Size;
+} NT_SYSTEM_MEMORY;
+
+RETURN_STATUS
+EFIAPI
+SecPeCoffGetEntryPoint (
+ IN VOID *Pe32Data,
+ IN OUT VOID **EntryPoint
+);
+
+VOID
+SecLoadSecCore (
+ IN UINTN TemporaryRam,
+ IN UINTN TemporaryRamSize,
+ IN VOID *BootFirmwareVolumeBase,
+ IN UINTN BootFirmwareVolumeSize,
+ IN VOID *SecCorePe32File
+)
+/*++
+
+Routine Description:
+ This is the service to load the SEC Core from the Firmware Volume
+
+Arguments:
+ TemporaryRam - Memory to use for SEC.
+ TemporaryRamSize - Size of Memory to use for SEC
+ BootFirmwareVolumeBase - Start of the Boot FV
+ SecCorePe32File - SEC Core PE32
+
+Returns:
+ Success means control is transfered and thus we should never return
+
+--*/
+;
+
+EFI_STATUS
+EFIAPI
+SecWinNtFdAddress (
+ IN UINTN Index,
+ IN OUT EFI_PHYSICAL_ADDRESS *FdBase,
+ IN OUT UINT64 *FdSize
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ Index - TODO: add argument description
+ FdBase - TODO: add argument description
+ FdSize - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+
+EFI_STATUS
+EFIAPI
+SecImageRead (
+ IN VOID *FileHandle,
+ IN UINTN FileOffset,
+ IN OUT UINTN *ReadSize,
+ OUT VOID *Buffer
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ FileHandle - TODO: add argument description
+ FileOffset - TODO: add argument description
+ ReadSize - TODO: add argument description
+ Buffer - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+CHAR16 *
+AsciiToUnicode (
+ IN CHAR8 *Ascii,
+ IN UINTN *StrLen OPTIONAL
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ Ascii - TODO: add argument description
+ StrLen - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+UINTN
+CountSeparatorsInString (
+ IN CONST CHAR16 *String,
+ IN CHAR16 Separator
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ String - TODO: add argument description
+ Separator - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+BOOLEAN
+EfiSystemMemoryRange (
+ IN VOID *MemoryAddress
+ );
+VOID
+SecInitializeThunk (
+ VOID
+);
+extern EMU_THUNK_PROTOCOL gEmuThunkProtocol;
+#endif
\ No newline at end of file
diff --git a/EmulatorPkg/Win/Host/WinHost.inf b/EmulatorPkg/Win/Host/WinHost.inf
new file mode 100644
index 0000000000..544e775c49
--- /dev/null
+++ b/EmulatorPkg/Win/Host/WinHost.inf
@@ -0,0 +1,88 @@
+## @file
+# Entry Point of Win Emulator
+#
+# Main executable file of Win Emulator that loads Sec core after initialization finished.
+# Copyright (c) 2008 - 2018, Intel Corporation. All rights reserved.<BR>
+# Portions copyright (c) 2008 - 2011, Apple Inc. All rights reserved.<BR>
+#
+# This program and the accompanying materials
+# are licensed and made available under the terms and conditions of the BSD License
+# which accompanies this distribution. The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = WinHost
+ FILE_GUID = 62E8F833-2B0A-4C19-A966-63C180588BE7
+ MODULE_TYPE = USER_DEFINED
+ VERSION_STRING = 1.0
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64
+#
+
+[Sources]
+ WinMemoryAllocationLib.c
+ WinThunk.c
+ WinHost.h
+ WinHost.c
+ WinInclude.h
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ EmulatorPkg/EmulatorPkg.dec
+
+[LibraryClasses]
+ DebugLib
+ PcdLib
+ PrintLib
+ BaseMemoryLib
+ BaseLib
+ PeCoffLib
+ ThunkPpiList
+ ThunkProtocolList
+ PpiListLib
+ PeiServicesLib
+
+[Ppis]
+ gEmuThunkPpiGuid
+
+[Pcd]
+ gEfiMdeModulePkgTokenSpaceGuid.PcdInitValueInTempStack
+
+ gEmulatorPkgTokenSpaceGuid.PcdEmuBootMode
+ gEmulatorPkgTokenSpaceGuid.PcdEmuFirmwareVolume
+ gEmulatorPkgTokenSpaceGuid.PcdEmuMemorySize
+ gEmulatorPkgTokenSpaceGuid.PcdEmuFdBaseAddress
+ gEmulatorPkgTokenSpaceGuid.PcdPeiServicesTablePage
+
+[BuildOptions]
+ *_*_*_DLINK_FLAGS == /out:"$(BIN_DIR)\$(BASE_NAME).exe" /base:0x10000000 /pdb:"$(BIN_DIR)\$(BASE_NAME).pdb"
+ :*_*_*_CC_FLAGS == /nologo /W4 /WX /Gy /c /D UNICODE /Od /Oy- /FIAutoGen.h /EHs-c- /GF /Gs8192 /Zi /Gm /D _CRT_SECURE_NO_WARNINGS /D _CRT_SECURE_NO_DEPRECATE
+ *_*_*_PP_FLAGS == /nologo /E /TC /FIAutoGen.h
+
+ MSFT:*_*_IA32_DLINK_FLAGS = /LIBPATH:"$(VCINSTALLDIR)\Lib" /LIBPATH:"$(VCINSTALLDIR)\PlatformSdk\Lib" /LIBPATH:"%UniversalCRTSdkDir%lib\%UCRTVersion%\ucrt\x86" /LIBPATH:"%WindowsSdkDir%lib\%WindowsSDKLibVersion%\um\x86" /NOLOGO /SUBSYSTEM:CONSOLE /NODEFAULTLIB /IGNORE:4086 /MAP /OPT:REF /DEBUG /MACHINE:I386 /LTCG Kernel32.lib MSVCRTD.lib Gdi32.lib User32.lib Winmm.lib Advapi32.lib
+ MSFT:*_VS2015_IA32_DLINK_FLAGS = /LIBPATH:"$(VCINSTALLDIR)\Lib" /LIBPATH:"$(VCINSTALLDIR)\PlatformSdk\Lib" /LIBPATH:"%UniversalCRTSdkDir%lib\%UCRTVersion%\ucrt\x86" /LIBPATH:"%WindowsSdkDir%lib\%WindowsSDKLibVersion%\um\x86" /NOLOGO /SUBSYSTEM:CONSOLE /NODEFAULTLIB /IGNORE:4086 /MAP /OPT:REF /DEBUG /MACHINE:I386 /LTCG Kernel32.lib MSVCRTD.lib Gdi32.lib User32.lib Winmm.lib Advapi32.lib vcruntimed.lib ucrtd.lib
+ MSFT:*_VS2015x86_IA32_DLINK_FLAGS = /LIBPATH:"$(VCINSTALLDIR)\Lib" /LIBPATH:"$(VCINSTALLDIR)\PlatformSdk\Lib" /LIBPATH:"%UniversalCRTSdkDir%lib\%UCRTVersion%\ucrt\x86" /LIBPATH:"%WindowsSdkDir%lib\%WindowsSDKLibVersion%\um\x86" /NOLOGO /SUBSYSTEM:CONSOLE /NODEFAULTLIB /IGNORE:4086 /MAP /OPT:REF /DEBUG /MACHINE:I386 /LTCG Kernel32.lib MSVCRTD.lib Gdi32.lib User32.lib Winmm.lib Advapi32.lib vcruntimed.lib ucrtd.lib
+ MSFT:*_VS2017_IA32_DLINK_FLAGS = /LIBPATH:"%VCToolsInstallDir%lib\x86" /LIBPATH:"%UniversalCRTSdkDir%lib\%UCRTVersion%\ucrt\x86" /LIBPATH:"%WindowsSdkDir%lib\%WindowsSDKLibVersion%\um\x86" /NOLOGO /SUBSYSTEM:CONSOLE /NODEFAULTLIB /IGNORE:4086 /MAP /OPT:REF /DEBUG /MACHINE:I386 /LTCG Kernel32.lib MSVCRTD.lib vcruntimed.lib ucrtd.lib Gdi32.lib User32.lib Winmm.lib Advapi32.lib
+ MSFT:*_*_IA32_ASM_FLAGS == /nologo /W3 /WX /c /coff /Cx /Zd /W0 /Zi
+ MSFT:*_*_IA32_ASMLINK_FLAGS == /link /nologo /tiny
+
+ MSFT:*_*_X64_DLINK_FLAGS = /LIBPATH:"$(VCINSTALLDIR)\Lib\AMD64" /LIBPATH:"%UniversalCRTSdkDir%lib\%UCRTVersion%\ucrt\x64" /LIBPATH:"%WindowsSdkDir%lib\%WindowsSDKLibVersion%\um\x64" /NOLOGO /SUBSYSTEM:CONSOLE /NODEFAULTLIB /IGNORE:4086 /MAP /OPT:REF /DEBUG /MACHINE:AMD64 /LTCG Kernel32.lib MSVCRTD.lib Gdi32.lib User32.lib Winmm.lib Advapi32.lib
+ MSFT:*_VS2015_X64_DLINK_FLAGS = /LIBPATH:"$(VCINSTALLDIR)\Lib\AMD64" /LIBPATH:"%UniversalCRTSdkDir%lib\%UCRTVersion%\ucrt\x64" /LIBPATH:"%WindowsSdkDir%lib\%WindowsSDKLibVersion%\um\x64" /NOLOGO /SUBSYSTEM:CONSOLE /NODEFAULTLIB /IGNORE:4086 /MAP /OPT:REF /DEBUG /MACHINE:AMD64 /LTCG Kernel32.lib MSVCRTD.lib vcruntimed.lib ucrtd.lib Gdi32.lib User32.lib Winmm.lib Advapi32.lib
+ MSFT:*_VS2015x86_X64_DLINK_FLAGS = /LIBPATH:"$(VCINSTALLDIR)\Lib\AMD64" /LIBPATH:"%UniversalCRTSdkDir%lib\%UCRTVersion%\ucrt\x64" /LIBPATH:"%WindowsSdkDir%lib\%WindowsSDKLibVersion%\um\x64" /NOLOGO /SUBSYSTEM:CONSOLE /NODEFAULTLIB /IGNORE:4086 /MAP /OPT:REF /DEBUG /MACHINE:AMD64 /LTCG Kernel32.lib MSVCRTD.lib vcruntimed.lib ucrtd.lib Gdi32.lib User32.lib Winmm.lib Advapi32.lib
+ MSFT:*_VS2017_X64_DLINK_FLAGS = /LIBPATH:"%VCToolsInstallDir%lib\x64" /LIBPATH:"%UniversalCRTSdkDir%lib\%UCRTVersion%\ucrt\x64" /LIBPATH:"%WindowsSdkDir%lib\%WindowsSDKLibVersion%\um\x64" /NOLOGO /SUBSYSTEM:CONSOLE /NODEFAULTLIB /IGNORE:4086 /MAP /OPT:REF /DEBUG /MACHINE:AMD64 /LTCG Kernel32.lib MSVCRTD.lib vcruntimed.lib ucrtd.lib Gdi32.lib User32.lib Winmm.lib Advapi32.lib
+ MSFT:*_*_X64_ASM_FLAGS == /nologo /W3 /WX /c /Cx /Zd /W0 /Zi
+ MSFT:*_*_X64_ASMLINK_FLAGS == /link /nologo
+
+ INTEL:*_*_IA32_DLINK_FLAGS = /LIBPATH:"C:\Program Files\Intel\Compiler\C++\9.1\IA32\Lib" /LIBPATH:"$(VCINSTALLDIR)\Lib" /LIBPATH:"$(VCINSTALLDIR)\PlatformSdk\Lib" /NOLOGO /SUBSYSTEM:CONSOLE /NODEFAULTLIB /IGNORE:4086 /MAP /OPT:REF /DEBUG /MACHINE:I386 /LTCG Kernel32.lib MSVCRTD.lib Gdi32.lib User32.lib Winmm.lib
+ INTEL:*_*_IA32_ASM_FLAGS == /nologo /W3 /WX /c /coff /Cx /Zd /W0 /Zi
+ INTEL:*_*_IA32_ASMLINK_FLAGS == /link /nologo /tiny
diff --git a/EmulatorPkg/Win/Host/WinInclude.h b/EmulatorPkg/Win/Host/WinInclude.h
new file mode 100644
index 0000000000..ae90b1ed30
--- /dev/null
+++ b/EmulatorPkg/Win/Host/WinInclude.h
@@ -0,0 +1,75 @@
+/**@file
+ Public include file for the WinNt Library
+
+Copyright (c) 2006 - 2014, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+**/
+
+#ifndef __WIN_NT_INCLUDE_H__
+#define __WIN_NT_INCLUDE_H__
+
+//
+// Win32 include files do not compile clean with /W4, so we use the warning
+// pragma to suppress the warnings for Win32 only. This way our code can stil
+// compile at /W4 (highest warning level) with /WX (warnings cause build
+// errors).
+//
+#pragma warning(disable : 4115)
+#pragma warning(disable : 4201)
+#pragma warning(disable : 4028)
+#pragma warning(disable : 4133)
+
+#define GUID _WINNT_DUP_GUID_____
+#define _LIST_ENTRY _WINNT_DUP_LIST_ENTRY_FORWARD
+#define LIST_ENTRY _WINNT_DUP_LIST_ENTRY
+#if defined (MDE_CPU_IA32) && (_MSC_VER < 1800)
+#define InterlockedIncrement _WINNT_DUP_InterlockedIncrement
+#define InterlockedDecrement _WINNT_DUP_InterlockedDecrement
+#define InterlockedCompareExchange64 _WINNT_DUP_InterlockedCompareExchange64
+#endif
+#undef UNALIGNED
+#undef CONST
+#undef VOID
+#undef DEBUG_EVENT
+
+// WQBugBug: This typedef is to make "windows.h" buildable.
+// It should be removed after the root cause why
+// size_t is undefined when go into the line below is found.
+#if defined (MDE_CPU_IA32)
+typedef UINT32 size_t ;
+#endif
+
+#include "windows.h"
+
+#undef GUID
+#undef _LIST_ENTRY
+#undef LIST_ENTRY
+#undef InterlockedIncrement
+#undef InterlockedDecrement
+#undef InterlockedCompareExchange64
+#undef InterlockedCompareExchangePointer
+#undef CreateEventEx
+
+#define VOID void
+
+//
+// Prevent collisions with Windows API name macros that deal with Unicode/Not issues
+//
+#undef LoadImage
+#undef CreateEvent
+#undef FAR
+
+//
+// Set the warnings back on as the EFI code must be /W4.
+//
+#pragma warning(default : 4115)
+#pragma warning(default : 4201)
+
+
+#endif
diff --git a/EmulatorPkg/Win/Host/WinMemoryAllocationLib.c b/EmulatorPkg/Win/Host/WinMemoryAllocationLib.c
new file mode 100644
index 0000000000..0c7e7ff508
--- /dev/null
+++ b/EmulatorPkg/Win/Host/WinMemoryAllocationLib.c
@@ -0,0 +1,178 @@
+/*++ @file
+
+ Copyright (c) 2011 - 2018, Intel Corporation. All rights reserved.<BR>
+
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include <Base.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/MemoryAllocationLib.h>
+
+#include <stdlib.h>
+
+/**
+ Allocates a buffer of type EfiBootServicesData.
+
+ Allocates the number bytes specified by AllocationSize of type EfiBootServicesData and returns a
+ pointer to the allocated buffer. If AllocationSize is 0, then a valid buffer of 0 size is
+ returned. If there is not enough memory remaining to satisfy the request, then NULL is returned.
+
+ @param AllocationSize The number of bytes to allocate.
+
+ @return A pointer to the allocated buffer or NULL if allocation fails.
+
+**/
+VOID *
+EFIAPI
+AllocatePool (
+ IN UINTN AllocationSize
+ )
+{
+ return (VOID*) malloc (AllocationSize);
+}
+
+
+/**
+ Allocates and zeros a buffer of type EfiBootServicesData.
+
+ Allocates the number bytes specified by AllocationSize of type EfiBootServicesData, clears the
+ buffer with zeros, and returns a pointer to the allocated buffer. If AllocationSize is 0, then a
+ valid buffer of 0 size is returned. If there is not enough memory remaining to satisfy the
+ request, then NULL is returned.
+
+ @param AllocationSize The number of bytes to allocate and zero.
+
+ @return A pointer to the allocated buffer or NULL if allocation fails.
+
+**/
+VOID *
+EFIAPI
+AllocateZeroPool (
+ IN UINTN AllocationSize
+ )
+{
+ VOID *Buffer;
+
+ Buffer = AllocatePool (AllocationSize);
+ if (Buffer == NULL) {
+ return NULL;
+ }
+
+ ZeroMem (Buffer, AllocationSize);
+
+ return Buffer;
+}
+
+
+/**
+ Reallocates a buffer of type EfiBootServicesData.
+
+ Allocates and zeros the number bytes specified by NewSize from memory of type
+ EfiBootServicesData. If OldBuffer is not NULL, then the smaller of OldSize and
+ NewSize bytes are copied from OldBuffer to the newly allocated buffer, and
+ OldBuffer is freed. A pointer to the newly allocated buffer is returned.
+ If NewSize is 0, then a valid buffer of 0 size is returned. If there is not
+ enough memory remaining to satisfy the request, then NULL is returned.
+
+ If the allocation of the new buffer is successful and the smaller of NewSize and OldSize
+ is greater than (MAX_ADDRESS - OldBuffer + 1), then ASSERT().
+
+ @param OldSize The size, in bytes, of OldBuffer.
+ @param NewSize The size, in bytes, of the buffer to reallocate.
+ @param OldBuffer The buffer to copy to the allocated buffer. This is an optional
+ parameter that may be NULL.
+
+ @return A pointer to the allocated buffer or NULL if allocation fails.
+
+**/
+VOID *
+EFIAPI
+ReallocatePool (
+ IN UINTN OldSize,
+ IN UINTN NewSize,
+ IN VOID *OldBuffer OPTIONAL
+ )
+{
+ VOID *NewBuffer;
+
+ NewBuffer = AllocatePool (NewSize);
+ if (NewBuffer == NULL) {
+ return NULL;
+ }
+
+ if (OldBuffer != NULL) {
+ if (OldSize > 0) {
+ CopyMem (NewBuffer, OldBuffer, OldSize);
+ }
+
+ FreePool (OldBuffer);
+ }
+
+ return NewBuffer;
+}
+
+/**
+ Copies a buffer to an allocated buffer of type EfiBootServicesData.
+
+ Allocates the number bytes specified by AllocationSize of type EfiBootServicesData, copies
+ AllocationSize bytes from Buffer to the newly allocated buffer, and returns a pointer to the
+ allocated buffer. If AllocationSize is 0, then a valid buffer of 0 size is returned. If there
+ is not enough memory remaining to satisfy the request, then NULL is returned.
+
+ If Buffer is NULL, then ASSERT().
+ If AllocationSize is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT().
+
+ @param AllocationSize The number of bytes to allocate and zero.
+ @param Buffer The buffer to copy to the allocated buffer.
+
+ @return A pointer to the allocated buffer or NULL if allocation fails.
+
+**/
+VOID *
+EFIAPI
+AllocateCopyPool (
+ IN UINTN AllocationSize,
+ IN CONST VOID *Buffer
+ )
+{
+ VOID *Memory;
+
+ Memory = AllocatePool (AllocationSize);
+ if (Memory != NULL) {
+ Memory = CopyMem (Memory, Buffer, AllocationSize);
+ }
+ return Memory;
+}
+
+
+/**
+ Frees a buffer that was previously allocated with one of the pool allocation functions in the
+ Memory Allocation Library.
+
+ Frees the buffer specified by Buffer. Buffer must have been allocated on a previous call to the
+ pool allocation services of the Memory Allocation Library. If it is not possible to free pool
+ resources, then this function will perform no actions.
+
+ If Buffer was not allocated with a pool allocation function in the Memory Allocation Library,
+ then ASSERT().
+
+ @param Buffer Pointer to the buffer to free.
+
+**/
+VOID
+EFIAPI
+FreePool (
+ IN VOID *Buffer
+ )
+{
+ free ((void *) Buffer);
+}
+
diff --git a/EmulatorPkg/Win/Host/WinThunk.c b/EmulatorPkg/Win/Host/WinThunk.c
new file mode 100644
index 0000000000..5ec5d439d4
--- /dev/null
+++ b/EmulatorPkg/Win/Host/WinThunk.c
@@ -0,0 +1,228 @@
+/**@file
+
+Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+
+ WinNtThunk.c
+
+Abstract:
+
+ Since the SEC is the only windows program in our emulation we
+ must use a Tiano mechanism to export Win32 APIs to other modules.
+ This is the role of the EFI_WIN_NT_THUNK_PROTOCOL.
+
+ The mWinNtThunkTable exists so that a change to EFI_WIN_NT_THUNK_PROTOCOL
+ will cause an error in initializing the array if all the member functions
+ are not added. It looks like adding a element to end and not initializing
+ it may cause the table to be initaliized with the members at the end being
+ set to zero. This is bad as jumping to zero will case the NT32 to crash.
+
+ All the member functions in mWinNtThunkTable are Win32
+ API calls, so please reference Microsoft documentation.
+
+
+ gWinNt is a a public exported global that contains the initialized
+ data.
+
+**/
+
+#include "WinHost.h"
+
+UINTN
+SecWriteStdErr (
+ IN UINT8 *Buffer,
+ IN UINTN NumberOfBytes
+ )
+{
+ return 0;
+}
+
+
+EFI_STATUS
+SecConfigStdIn (
+ VOID
+ )
+{
+ return EFI_SUCCESS;
+}
+
+UINTN
+SecWriteStdOut (
+ IN UINT8 *Buffer,
+ IN UINTN NumberOfBytes
+ )
+{
+ return 0;
+}
+
+BOOLEAN
+SecPollStdIn (
+ VOID
+ )
+{
+ return FALSE;
+}
+
+UINTN
+SecReadStdIn (
+ IN UINT8 *Buffer,
+ IN UINTN NumberOfBytes
+ )
+{
+ return 0;
+}
+
+
+VOID *
+SecAlloc (
+ IN UINTN Size
+ )
+{
+ return malloc ((size_t)Size);
+}
+
+BOOLEAN
+SecFree (
+ IN VOID *Ptr
+ )
+{
+ if (EfiSystemMemoryRange (Ptr)) {
+ // If an address range is in the EFI memory map it was alloced via EFI.
+ // So don't free those ranges and let the caller know.
+ return FALSE;
+ }
+
+ free (Ptr);
+ return TRUE;
+}
+
+VOID
+SecSetTimer (
+ IN UINT64 TimerPeriod,
+ IN EMU_SET_TIMER_CALLBACK Callback
+)
+{
+}
+
+VOID
+SecInitializeThunk (
+ VOID
+)
+{
+}
+
+VOID
+SecEnableInterrupt (
+ VOID
+ )
+{
+}
+
+
+VOID
+SecDisableInterrupt (
+ VOID
+ )
+{
+}
+
+
+UINT64
+SecQueryPerformanceFrequency (
+ VOID
+ )
+{
+ // Hard code to nanoseconds
+ return 1000000000ULL;
+}
+
+UINT64
+SecQueryPerformanceCounter (
+ VOID
+ )
+{
+ return 0;
+}
+
+
+
+VOID
+SecSleep (
+ IN UINT64 Nanoseconds
+ )
+{
+ Sleep ((DWORD)DivU64x32 (Nanoseconds, 1000000));
+}
+
+
+VOID
+SecCpuSleep (
+ VOID
+ )
+{
+ Sleep (1);
+}
+
+
+VOID
+SecExit (
+ UINTN Status
+ )
+{
+ exit ((int)Status);
+}
+
+
+VOID
+SecGetTime (
+ OUT EFI_TIME *Time,
+ OUT EFI_TIME_CAPABILITIES *Capabilities OPTIONAL
+ )
+{
+}
+
+EFI_STATUS
+SecSetTime (
+ IN EFI_TIME *Time
+)
+{
+ return EFI_SUCCESS;
+}
+
+EMU_THUNK_PROTOCOL gEmuThunkProtocol = {
+ SecWriteStdErr,
+ SecConfigStdIn,
+ SecWriteStdOut,
+ SecReadStdIn,
+ SecPollStdIn,
+ SecAlloc,
+ NULL,
+ SecFree,
+ SecPeCoffGetEntryPoint,
+ PeCoffLoaderRelocateImageExtraAction,
+ PeCoffLoaderUnloadImageExtraAction,
+ SecEnableInterrupt,
+ SecDisableInterrupt,
+ SecQueryPerformanceFrequency,
+ SecQueryPerformanceCounter,
+ SecSleep,
+ SecCpuSleep,
+ SecExit,
+ SecGetTime,
+ SecSetTime,
+ SecSetTimer,
+ GetNextThunkProtocol
+};
+
+
+#pragma warning(default : 4996)
+#pragma warning(default : 4232)
+
--
2.16.1.windows.1
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [PATCH 03/12] EmulatorPkg/Win: Enable source level debugging
2018-08-23 9:52 [PATCH 00/12] Add WinHost support in EmulatorPkg Ruiyu Ni
2018-08-23 9:52 ` [PATCH 01/12] EmulatorPkg/ThunkProtocolList: Fix VS build failure Ruiyu Ni
2018-08-23 9:52 ` [PATCH 02/12] EmulatorPkg/Win: Add Windows host support Ruiyu Ni
@ 2018-08-23 9:52 ` Ruiyu Ni
2018-08-23 9:52 ` [PATCH 04/12] EmulatorPkg/Win: Enable native OS console as firmware console Ruiyu Ni
` (9 subsequent siblings)
12 siblings, 0 replies; 14+ messages in thread
From: Ruiyu Ni @ 2018-08-23 9:52 UTC (permalink / raw)
To: edk2-devel; +Cc: Andrew Fish, Hao A Wu
Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Ruiyu Ni <ruiyu.ni@intel.com>
Cc: Andrew Fish <afish@apple.com>
Cc: Hao A Wu <hao.a.wu@intel.com>
---
EmulatorPkg/EmulatorPkg.dsc | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/EmulatorPkg/EmulatorPkg.dsc b/EmulatorPkg/EmulatorPkg.dsc
index 8afeaf5fa3..67812f754b 100644
--- a/EmulatorPkg/EmulatorPkg.dsc
+++ b/EmulatorPkg/EmulatorPkg.dsc
@@ -420,3 +420,11 @@ [Components]
!endif
+[BuildOptions]
+ MSFT:DEBUG_*_*_CC_FLAGS = /Od /Oy-
+ MSFT:NOOPT_*_*_CC_FLAGS = /Od /Oy-
+
+ MSFT:*_*_*_DLINK_FLAGS = /ALIGN:4096 /FILEALIGN:4096 /SUBSYSTEM:CONSOLE
+ MSFT:DEBUG_*_*_DLINK_FLAGS = /EXPORT:InitializeDriver=$(IMAGE_ENTRY_POINT) /BASE:0x10000
+ MSFT:NOOPT_*_*_DLINK_FLAGS = /EXPORT:InitializeDriver=$(IMAGE_ENTRY_POINT) /BASE:0x10000
+
--
2.16.1.windows.1
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [PATCH 04/12] EmulatorPkg/Win: Enable native OS console as firmware console
2018-08-23 9:52 [PATCH 00/12] Add WinHost support in EmulatorPkg Ruiyu Ni
` (2 preceding siblings ...)
2018-08-23 9:52 ` [PATCH 03/12] EmulatorPkg/Win: Enable source level debugging Ruiyu Ni
@ 2018-08-23 9:52 ` Ruiyu Ni
2018-08-23 9:52 ` [PATCH 05/12] EmulatorPkg/Win: Add input/output support Ruiyu Ni
` (8 subsequent siblings)
12 siblings, 0 replies; 14+ messages in thread
From: Ruiyu Ni @ 2018-08-23 9:52 UTC (permalink / raw)
To: edk2-devel; +Cc: Hao A Wu, Andrew Fish
The patch implements Stdin/Stdout/Stderr access so that
the native OS console (cmd.exe) can be used as the firmware
console and debug message can also be routed to it.
Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Ruiyu Ni <ruiyu.ni@intel.com>
Cc: Hao A Wu <hao.a.wu@intel.com>
Cc: Andrew Fish <afish@apple.com>
---
EmulatorPkg/Win/Host/WinThunk.c | 109 ++++++++++++++++++++++++++++++++++++++--
1 file changed, 105 insertions(+), 4 deletions(-)
diff --git a/EmulatorPkg/Win/Host/WinThunk.c b/EmulatorPkg/Win/Host/WinThunk.c
index 5ec5d439d4..69a61258f3 100644
--- a/EmulatorPkg/Win/Host/WinThunk.c
+++ b/EmulatorPkg/Win/Host/WinThunk.c
@@ -42,7 +42,19 @@ SecWriteStdErr (
IN UINTN NumberOfBytes
)
{
- return 0;
+ BOOL Success;
+ DWORD CharCount;
+
+ CharCount = (DWORD)NumberOfBytes;
+ Success = WriteFile (
+ GetStdHandle (STD_ERROR_HANDLE),
+ Buffer,
+ CharCount,
+ &CharCount,
+ NULL
+ );
+
+ return Success ? CharCount : 0;
}
@@ -51,7 +63,32 @@ SecConfigStdIn (
VOID
)
{
- return EFI_SUCCESS;
+ BOOL Success;
+ DWORD Mode;
+
+ Success = GetConsoleMode (GetStdHandle (STD_INPUT_HANDLE), &Mode);
+ if (Success) {
+ //
+ // Disable buffer (line input), echo, mouse, window
+ //
+ Success = SetConsoleMode (
+ GetStdHandle (STD_INPUT_HANDLE),
+ Mode | ENABLE_VIRTUAL_TERMINAL_INPUT & ~(ENABLE_LINE_INPUT | ENABLE_ECHO_INPUT | ENABLE_MOUSE_INPUT | ENABLE_WINDOW_INPUT)
+ );
+ }
+ if (Success) {
+ //
+ // Enable terminal mode
+ //
+ Success = GetConsoleMode (GetStdHandle (STD_OUTPUT_HANDLE), &Mode);
+ if (Success) {
+ Success = SetConsoleMode (
+ GetStdHandle (STD_OUTPUT_HANDLE),
+ Mode | ENABLE_VIRTUAL_TERMINAL_PROCESSING | DISABLE_NEWLINE_AUTO_RETURN
+ );
+ }
+ }
+ return Success ? EFI_SUCCESS : EFI_DEVICE_ERROR;
}
UINTN
@@ -60,7 +97,19 @@ SecWriteStdOut (
IN UINTN NumberOfBytes
)
{
- return 0;
+ BOOL Success;
+ DWORD CharCount;
+
+ CharCount = (DWORD)NumberOfBytes;
+ Success = WriteFile (
+ GetStdHandle (STD_OUTPUT_HANDLE),
+ Buffer,
+ CharCount,
+ &CharCount,
+ NULL
+ );
+
+ return Success ? CharCount : 0;
}
BOOLEAN
@@ -68,6 +117,38 @@ SecPollStdIn (
VOID
)
{
+ BOOL Success;
+ INPUT_RECORD Record;
+ DWORD RecordNum;
+
+ do {
+ Success = GetNumberOfConsoleInputEvents (GetStdHandle (STD_INPUT_HANDLE), &RecordNum);
+ if (!Success || (RecordNum == 0)) {
+ break;
+ }
+ Success = PeekConsoleInput (
+ GetStdHandle (STD_INPUT_HANDLE),
+ &Record,
+ 1,
+ &RecordNum
+ );
+ if (Success && (RecordNum == 1)) {
+ if (Record.EventType == KEY_EVENT && Record.Event.KeyEvent.bKeyDown) {
+ return TRUE;
+ } else {
+ //
+ // Consume the non-key event.
+ //
+ Success = ReadConsoleInput (
+ GetStdHandle (STD_INPUT_HANDLE),
+ &Record,
+ 1,
+ &RecordNum
+ );
+ }
+ }
+ } while (Success);
+
return FALSE;
}
@@ -77,7 +158,27 @@ SecReadStdIn (
IN UINTN NumberOfBytes
)
{
- return 0;
+ BOOL Success;
+ INPUT_RECORD Record;
+ DWORD RecordNum;
+ UINTN BytesReturn;
+
+ if (!SecPollStdIn ()) {
+ return 0;
+ }
+ Success = ReadConsoleInput (
+ GetStdHandle (STD_INPUT_HANDLE),
+ &Record,
+ 1,
+ &RecordNum
+ );
+ ASSERT (Success && (RecordNum == 1) && (Record.EventType == KEY_EVENT) && (Record.Event.KeyEvent.bKeyDown));
+ NumberOfBytes = MIN (Record.Event.KeyEvent.wRepeatCount, NumberOfBytes);
+ BytesReturn = NumberOfBytes;
+ while (NumberOfBytes-- != 0) {
+ Buffer[NumberOfBytes] = Record.Event.KeyEvent.uChar.AsciiChar;
+ }
+ return BytesReturn;
}
--
2.16.1.windows.1
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [PATCH 05/12] EmulatorPkg/Win: Add input/output support
2018-08-23 9:52 [PATCH 00/12] Add WinHost support in EmulatorPkg Ruiyu Ni
` (3 preceding siblings ...)
2018-08-23 9:52 ` [PATCH 04/12] EmulatorPkg/Win: Enable native OS console as firmware console Ruiyu Ni
@ 2018-08-23 9:52 ` Ruiyu Ni
2018-08-23 9:52 ` [PATCH 06/12] EmulatorPkg/Win: Add timer and interrupt support Ruiyu Ni
` (7 subsequent siblings)
12 siblings, 0 replies; 14+ messages in thread
From: Ruiyu Ni @ 2018-08-23 9:52 UTC (permalink / raw)
To: edk2-devel; +Cc: Andrew Fish, Hao A Wu
The patch adds GOP and SimpleTextIn[Ex] support.
Now firmware can boot to UI and Shell but timer doesn't work.
Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Ruiyu Ni <ruiyu.ni@intel.com>
Cc: Andrew Fish <afish@intel.com>
Cc: Hao A Wu <hao.a.wu@intel.com>
---
EmulatorPkg/Win/Host/WinGop.h | 204 +++++++++
EmulatorPkg/Win/Host/WinGopInput.c | 417 +++++++++++++++++
EmulatorPkg/Win/Host/WinGopScreen.c | 872 ++++++++++++++++++++++++++++++++++++
EmulatorPkg/Win/Host/WinHost.c | 5 +
EmulatorPkg/Win/Host/WinHost.h | 1 +
EmulatorPkg/Win/Host/WinHost.inf | 7 +
6 files changed, 1506 insertions(+)
create mode 100644 EmulatorPkg/Win/Host/WinGop.h
create mode 100644 EmulatorPkg/Win/Host/WinGopInput.c
create mode 100644 EmulatorPkg/Win/Host/WinGopScreen.c
diff --git a/EmulatorPkg/Win/Host/WinGop.h b/EmulatorPkg/Win/Host/WinGop.h
new file mode 100644
index 0000000000..32ae6b03af
--- /dev/null
+++ b/EmulatorPkg/Win/Host/WinGop.h
@@ -0,0 +1,204 @@
+/** @file
+
+Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+
+ WinGop.h
+
+Abstract:
+
+ Private data for the Gop driver that is bound to the WinNt Thunk protocol
+
+
+**/
+
+#ifndef _WIN_GOP_H_
+#define _WIN_GOP_H_
+
+
+#include "WinHost.h"
+
+#include <Protocol/EmuIoThunk.h>
+#include <Protocol/EmuGraphicsWindow.h>
+#include <Protocol/SimpleTextIn.h>
+#include <Protocol/SimpleTextInEx.h>
+#include <Protocol/GraphicsOutput.h>
+
+//
+// WM_SYSKEYDOWN/WM_SYSKEYUP Notification
+// lParam
+// bit 24: Specifies whether the key is an extended key,
+// such as the right-hand ALT and CTRL keys that appear on
+// an enhanced 101- or 102-key keyboard.
+// The value is 1 if it is an extended key; otherwise, it is 0.
+// bit 29:Specifies the context code.
+// The value is 1 if the ALT key is down while the key is pressed/released;
+// it is 0 if the WM_SYSKEYDOWN message is posted to the active window
+// because no window has the keyboard focus.
+#define GOP_EXTENDED_KEY (0x1 << 24)
+#define GOP_ALT_KEY_PRESSED (0x1 << 29)
+
+#define KEYBOARD_TIMER_INTERVAL 200000 // 0.02s
+
+#define MAX_Q 256
+
+typedef struct {
+ UINTN Front;
+ UINTN Rear;
+ EFI_KEY_DATA Q[MAX_Q];
+ CRITICAL_SECTION Cs;
+} GOP_QUEUE_FIXED;
+
+#define WIN_NT_GOP_CLASS_NAME L"WinNtGopWindow"
+
+
+typedef struct {
+ UINT64 Signature;
+ EMU_GRAPHICS_WINDOW_PROTOCOL GraphicsWindowIo;
+
+ //
+ // GOP Private Data knowing when to start hardware
+ //
+ BOOLEAN HardwareNeedsStarting;
+
+ CHAR16 *WindowName;
+ CHAR16 Buffer[160];
+
+ HANDLE ThreadInited; // Semaphore
+ HANDLE ThreadHandle; // Thread
+ DWORD ThreadId;
+
+ HWND WindowHandle;
+ WNDCLASSEX WindowsClass;
+
+ UINT32 Width;
+ UINT32 Height;
+ //
+ // This screen is used to redraw the scree when windows events happen. It's
+ // updated in the main thread and displayed in the windows thread.
+ //
+ BITMAPV4HEADER *VirtualScreenInfo;
+ RGBQUAD *VirtualScreen;
+
+ EFI_GRAPHICS_OUTPUT_BLT_PIXEL *FillLine;
+
+ //
+ // Keyboard Queue used by Simple Text In.
+ // QueueForRead: WinProc thread adds, and main thread removes.
+ //
+ GOP_QUEUE_FIXED QueueForRead;
+
+ EMU_GRAPHICS_WINDOW_REGISTER_KEY_NOTIFY_CALLBACK MakeRegisterdKeyCallback;
+ EMU_GRAPHICS_WINDOW_REGISTER_KEY_NOTIFY_CALLBACK BreakRegisterdKeyCallback;
+ VOID *RegisterdKeyCallbackContext;
+
+ EFI_KEY_STATE KeyState;
+ BOOLEAN LeftShift;
+ BOOLEAN RightShift;
+ BOOLEAN LeftAlt;
+ BOOLEAN RightAlt;
+ BOOLEAN LeftCtrl;
+ BOOLEAN RightCtrl;
+ BOOLEAN LeftLogo;
+ BOOLEAN RightLogo;
+ BOOLEAN Menu;
+ BOOLEAN SysReq;
+ BOOLEAN NumLock;
+ BOOLEAN ScrollLock;
+ BOOLEAN CapsLock;
+ BOOLEAN IsPartialKeySupport;
+} GRAPHICS_PRIVATE_DATA;
+#define GRAPHICS_PRIVATE_DATA_SIGNATURE SIGNATURE_32 ('g', 'f', 'x', 'd')
+#define GRAPHICS_PRIVATE_DATA_FROM_THIS(a) \
+ CR(a, GRAPHICS_PRIVATE_DATA, GraphicsWindowIo, GRAPHICS_PRIVATE_DATA_SIGNATURE)
+
+
+//
+// Gop Hardware abstraction internal worker functions
+//
+
+/**
+ TODO: Add function description
+
+ @param Private TODO: add argument description
+ @param Key TODO: add argument description
+
+ @return TODO: add return values
+
+**/
+EFI_STATUS
+GopPrivateAddKey (
+ IN GRAPHICS_PRIVATE_DATA *Private,
+ IN EFI_INPUT_KEY Key
+ );
+
+EFI_STATUS
+EFIAPI
+WinNtWndGetKey (
+ IN EMU_GRAPHICS_WINDOW_PROTOCOL *GraphicsIo,
+ IN EFI_KEY_DATA *KeyData
+ );
+
+EFI_STATUS
+EFIAPI
+WinNtWndCheckKey (
+ IN EMU_GRAPHICS_WINDOW_PROTOCOL *GraphicsIo
+ );
+
+EFI_STATUS
+EFIAPI
+WinNtWndKeySetState (
+ IN EMU_GRAPHICS_WINDOW_PROTOCOL *GraphicsIo,
+ IN EFI_KEY_TOGGLE_STATE *KeyToggleState
+ );
+
+EFI_STATUS
+EFIAPI
+WinNtWndRegisterKeyNotify (
+ IN EMU_GRAPHICS_WINDOW_PROTOCOL *GraphicsIo,
+ IN EMU_GRAPHICS_WINDOW_REGISTER_KEY_NOTIFY_CALLBACK MakeCallBack,
+ IN EMU_GRAPHICS_WINDOW_REGISTER_KEY_NOTIFY_CALLBACK BreakCallBack,
+ IN VOID *Context
+ );
+
+EFI_STATUS
+EFIAPI
+WinNtWndCheckPointer (
+ IN EMU_GRAPHICS_WINDOW_PROTOCOL *GraphicsIo
+ );
+
+EFI_STATUS
+EFIAPI
+WinNtWndGetPointerState (
+ IN EMU_GRAPHICS_WINDOW_PROTOCOL *GraphicsIo,
+ IN EFI_SIMPLE_POINTER_STATE *State
+ );
+EFI_STATUS
+GopPrivateCreateQ (
+ IN GRAPHICS_PRIVATE_DATA *Private,
+ IN GOP_QUEUE_FIXED *Queue
+ );
+
+
+/**
+ TODO: Add function description
+
+ @param Private TODO: add argument description
+
+ @retval EFI_SUCCESS TODO: Add description for return value
+
+**/
+EFI_STATUS
+GopPrivateDestroyQ (
+ IN GRAPHICS_PRIVATE_DATA *Private,
+ IN GOP_QUEUE_FIXED *Queue
+ );
+#endif
\ No newline at end of file
diff --git a/EmulatorPkg/Win/Host/WinGopInput.c b/EmulatorPkg/Win/Host/WinGopInput.c
new file mode 100644
index 0000000000..7223f6a185
--- /dev/null
+++ b/EmulatorPkg/Win/Host/WinGopInput.c
@@ -0,0 +1,417 @@
+/** @file
+
+Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+
+ WinGopInput.c
+
+Abstract:
+
+ This file produces the Simple Text In for an Gop window.
+
+ This stuff is linked at the hip to the Window, since the window
+ processing is done in a thread kicked off in WinNtGopImplementation.c
+
+ Since the window information is processed in an other thread we need
+ a keyboard Queue to pass data about. The Simple Text In code just
+ takes data off the Queue. The WinProc message loop takes keyboard input
+ and places it in the Queue.
+
+
+**/
+
+
+#include "WinGop.h"
+
+
+/**
+ TODO: Add function description
+
+ @param Private TODO: add argument description
+
+ @retval EFI_SUCCESS TODO: Add description for return value
+
+**/
+EFI_STATUS
+GopPrivateCreateQ (
+ IN GRAPHICS_PRIVATE_DATA *Private,
+ IN GOP_QUEUE_FIXED *Queue
+ )
+{
+ InitializeCriticalSection (&Queue->Cs);
+ Queue->Front = 0;
+ Queue->Rear = 0;
+ return EFI_SUCCESS;
+}
+
+
+/**
+ TODO: Add function description
+
+ @param Private TODO: add argument description
+
+ @retval EFI_SUCCESS TODO: Add description for return value
+
+**/
+EFI_STATUS
+GopPrivateDestroyQ (
+ IN GRAPHICS_PRIVATE_DATA *Private,
+ IN GOP_QUEUE_FIXED *Queue
+ )
+{
+ Queue->Front = 0;
+ Queue->Rear = 0;
+ DeleteCriticalSection (&Queue->Cs);
+ return EFI_SUCCESS;
+}
+
+
+/**
+ TODO: Add function description
+
+ @param Private TODO: add argument description
+ @param Key TODO: add argument description
+
+ @retval EFI_NOT_READY TODO: Add description for return value
+ @retval EFI_SUCCESS TODO: Add description for return value
+
+**/
+EFI_STATUS
+GopPrivateAddQ (
+ IN GRAPHICS_PRIVATE_DATA *Private,
+ IN GOP_QUEUE_FIXED *Queue,
+ IN EFI_KEY_DATA *KeyData
+ )
+{
+ EnterCriticalSection (&Queue->Cs);
+
+ if ((Queue->Rear + 1) % MAX_Q == Queue->Front) {
+ LeaveCriticalSection (&Queue->Cs);
+ return EFI_NOT_READY;
+ }
+
+ CopyMem (&Queue->Q[Queue->Rear], KeyData, sizeof (EFI_KEY_DATA));
+ Queue->Rear = (Queue->Rear + 1) % MAX_Q;
+
+ LeaveCriticalSection (&Queue->Cs);
+ return EFI_SUCCESS;
+}
+
+
+/**
+ TODO: Add function description
+
+ @param Private TODO: add argument description
+ @param Key TODO: add argument description
+
+ @retval EFI_NOT_READY TODO: Add description for return value
+ @retval EFI_SUCCESS TODO: Add description for return value
+
+**/
+EFI_STATUS
+GopPrivateDeleteQ (
+ IN GRAPHICS_PRIVATE_DATA *Private,
+ IN GOP_QUEUE_FIXED *Queue,
+ OUT EFI_KEY_DATA *Key
+ )
+{
+ EnterCriticalSection (&Queue->Cs);
+
+ if (Queue->Front == Queue->Rear) {
+ LeaveCriticalSection (&Queue->Cs);
+ return EFI_NOT_READY;
+ }
+
+ CopyMem (Key, &Queue->Q[Queue->Front], sizeof (EFI_KEY_DATA));
+ Queue->Front = (Queue->Front + 1) % MAX_Q;
+
+ if (Key->Key.ScanCode == SCAN_NULL && Key->Key.UnicodeChar == CHAR_NULL) {
+ if (!Private->IsPartialKeySupport) {
+ //
+ // If partial keystrok is not enabled, don't return the partial keystroke.
+ //
+ LeaveCriticalSection (&Queue->Cs);
+ ZeroMem (Key, sizeof (EFI_KEY_DATA));
+ return EFI_NOT_READY;
+ }
+ }
+ LeaveCriticalSection (&Queue->Cs);
+ return EFI_SUCCESS;
+}
+
+
+/**
+ TODO: Add function description
+
+ @param Private TODO: add argument description
+
+ @retval EFI_NOT_READY TODO: Add description for return value
+ @retval EFI_SUCCESS TODO: Add description for return value
+
+**/
+EFI_STATUS
+GopPrivateCheckQ (
+ IN GOP_QUEUE_FIXED *Queue
+ )
+{
+ if (Queue->Front == Queue->Rear) {
+ return EFI_NOT_READY;
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Initialize the key state.
+
+ @param Private The GOP_PRIVATE_DATA instance.
+ @param KeyState A pointer to receive the key state information.
+**/
+VOID
+InitializeKeyState (
+ IN GRAPHICS_PRIVATE_DATA *Private,
+ IN EFI_KEY_STATE *KeyState
+ )
+{
+ KeyState->KeyShiftState = EFI_SHIFT_STATE_VALID;
+ KeyState->KeyToggleState = EFI_TOGGLE_STATE_VALID;
+
+ //
+ // Record Key shift state and toggle state
+ //
+ if (Private->LeftCtrl) {
+ KeyState->KeyShiftState |= EFI_LEFT_CONTROL_PRESSED;
+ }
+ if (Private->RightCtrl) {
+ KeyState->KeyShiftState |= EFI_RIGHT_CONTROL_PRESSED;
+ }
+ if (Private->LeftAlt) {
+ KeyState->KeyShiftState |= EFI_LEFT_ALT_PRESSED;
+ }
+ if (Private->RightAlt) {
+ KeyState->KeyShiftState |= EFI_RIGHT_ALT_PRESSED;
+ }
+ if (Private->LeftShift) {
+ KeyState->KeyShiftState |= EFI_LEFT_SHIFT_PRESSED;
+ }
+ if (Private->RightShift) {
+ KeyState->KeyShiftState |= EFI_RIGHT_SHIFT_PRESSED;
+ }
+ if (Private->LeftLogo) {
+ KeyState->KeyShiftState |= EFI_LEFT_LOGO_PRESSED;
+ }
+ if (Private->RightLogo) {
+ KeyState->KeyShiftState |= EFI_RIGHT_LOGO_PRESSED;
+ }
+ if (Private->Menu) {
+ KeyState->KeyShiftState |= EFI_MENU_KEY_PRESSED;
+ }
+ if (Private->SysReq) {
+ KeyState->KeyShiftState |= EFI_SYS_REQ_PRESSED;
+ }
+ if (Private->CapsLock) {
+ KeyState->KeyToggleState |= EFI_CAPS_LOCK_ACTIVE;
+ }
+ if (Private->NumLock) {
+ KeyState->KeyToggleState |= EFI_NUM_LOCK_ACTIVE;
+ }
+ if (Private->ScrollLock) {
+ KeyState->KeyToggleState |= EFI_SCROLL_LOCK_ACTIVE;
+ }
+ if (Private->IsPartialKeySupport) {
+ KeyState->KeyToggleState |= EFI_KEY_STATE_EXPOSED;
+ }
+}
+
+/**
+ TODO: Add function description
+
+ @param Private TODO: add argument description
+ @param Key TODO: add argument description
+
+ @retval EFI_NOT_READY TODO: Add description for return value
+ @retval EFI_SUCCESS TODO: Add description for return value
+
+**/
+EFI_STATUS
+GopPrivateAddKey (
+ IN GRAPHICS_PRIVATE_DATA *Private,
+ IN EFI_INPUT_KEY Key
+ )
+{
+ EFI_KEY_DATA KeyData;
+
+ KeyData.Key = Key;
+ InitializeKeyState (Private, &KeyData.KeyState);
+
+ //
+ // Convert Ctrl+[1-26] to Ctrl+[A-Z]
+ //
+ if ((Private->LeftCtrl || Private->RightCtrl) &&
+ (KeyData.Key.UnicodeChar >= 1) && (KeyData.Key.UnicodeChar <= 26)
+ ) {
+ if ((Private->LeftShift || Private->RightShift) == Private->CapsLock) {
+ KeyData.Key.UnicodeChar = (CHAR16)(KeyData.Key.UnicodeChar + L'a' - 1);
+ } else {
+ KeyData.Key.UnicodeChar = (CHAR16)(KeyData.Key.UnicodeChar + L'A' - 1);
+ }
+ }
+
+ //
+ // Unmask the Shift bit for printable char
+ //
+ if (((KeyData.Key.UnicodeChar >= L'a') && (KeyData.Key.UnicodeChar <= L'z')) ||
+ ((KeyData.Key.UnicodeChar >= L'A') && (KeyData.Key.UnicodeChar <= L'Z'))
+ ) {
+ KeyData.KeyState.KeyShiftState &= ~(EFI_LEFT_SHIFT_PRESSED | EFI_RIGHT_SHIFT_PRESSED);
+ }
+
+ GopPrivateAddQ (Private, &Private->QueueForRead, &KeyData);
+ if (Private->MakeRegisterdKeyCallback != NULL) {
+ Private->MakeRegisterdKeyCallback (Private->RegisterdKeyCallbackContext, &KeyData);
+ }
+
+ return EFI_SUCCESS;
+}
+
+
+EFI_STATUS
+EFIAPI
+WinNtWndCheckKey (
+ IN EMU_GRAPHICS_WINDOW_PROTOCOL *GraphicsIo
+ )
+{
+ GRAPHICS_PRIVATE_DATA *Private;
+
+ Private = GRAPHICS_PRIVATE_DATA_FROM_THIS (GraphicsIo);
+
+ return GopPrivateCheckQ (&Private->QueueForRead);
+
+}
+EFI_STATUS
+EFIAPI
+WinNtWndGetKey (
+ IN EMU_GRAPHICS_WINDOW_PROTOCOL *GraphicsIo,
+ IN EFI_KEY_DATA *KeyData
+ )
+/*++
+
+ Routine Description:
+ Reads the next keystroke from the input device. The WaitForKey Event can
+ be used to test for existance of a keystroke via WaitForEvent () call.
+
+ Arguments:
+ Private - The private structure of WinNt Gop device.
+ KeyData - A pointer to a buffer that is filled in with the keystroke
+ state data for the key that was pressed.
+
+ Returns:
+ EFI_SUCCESS - The keystroke information was returned.
+ EFI_NOT_READY - There was no keystroke data availiable.
+ EFI_DEVICE_ERROR - The keystroke information was not returned due to
+ hardware errors.
+ EFI_INVALID_PARAMETER - KeyData is NULL.
+
+--*/
+{
+ EFI_STATUS Status;
+ GRAPHICS_PRIVATE_DATA *Private;
+
+ Private = GRAPHICS_PRIVATE_DATA_FROM_THIS (GraphicsIo);
+
+ ZeroMem (&KeyData->Key, sizeof (KeyData->Key));
+ InitializeKeyState (Private, &KeyData->KeyState);
+
+ Status = GopPrivateCheckQ (&Private->QueueForRead);
+ if (!EFI_ERROR (Status)) {
+ //
+ // If a Key press exists try and read it.
+ //
+ Status = GopPrivateDeleteQ (Private, &Private->QueueForRead, KeyData);
+ if (!EFI_ERROR (Status)) {
+ //
+ // If partial keystroke is not enabled, check whether it is value key. If not return
+ // EFI_NOT_READY.
+ //
+ if (!Private->IsPartialKeySupport) {
+ if (KeyData->Key.ScanCode == SCAN_NULL && KeyData->Key.UnicodeChar == CHAR_NULL) {
+ Status = EFI_NOT_READY;
+ }
+ }
+ }
+ }
+
+ return Status;
+
+}
+
+EFI_STATUS
+EFIAPI
+WinNtWndKeySetState (
+ IN EMU_GRAPHICS_WINDOW_PROTOCOL *GraphicsIo,
+ IN EFI_KEY_TOGGLE_STATE *KeyToggleState
+ )
+{
+ GRAPHICS_PRIVATE_DATA *Private;
+
+ Private = GRAPHICS_PRIVATE_DATA_FROM_THIS (GraphicsIo);
+ Private->KeyState.KeyToggleState = *KeyToggleState;
+ return EFI_SUCCESS;
+}
+
+
+EFI_STATUS
+EFIAPI
+WinNtWndRegisterKeyNotify (
+ IN EMU_GRAPHICS_WINDOW_PROTOCOL *GraphicsIo,
+ IN EMU_GRAPHICS_WINDOW_REGISTER_KEY_NOTIFY_CALLBACK MakeCallBack,
+ IN EMU_GRAPHICS_WINDOW_REGISTER_KEY_NOTIFY_CALLBACK BreakCallBack,
+ IN VOID *Context
+ )
+{
+ GRAPHICS_PRIVATE_DATA *Private;
+
+ Private = GRAPHICS_PRIVATE_DATA_FROM_THIS (GraphicsIo);
+
+ Private->MakeRegisterdKeyCallback = MakeCallBack;
+ Private->BreakRegisterdKeyCallback = BreakCallBack;
+ Private->RegisterdKeyCallbackContext = Context;
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+EFIAPI
+WinNtWndCheckPointer (
+ IN EMU_GRAPHICS_WINDOW_PROTOCOL *GraphicsIo
+ )
+{
+ GRAPHICS_PRIVATE_DATA *Private;
+
+ Private = GRAPHICS_PRIVATE_DATA_FROM_THIS (GraphicsIo);
+
+ return EFI_NOT_READY;
+}
+
+
+EFI_STATUS
+EFIAPI
+WinNtWndGetPointerState (
+ IN EMU_GRAPHICS_WINDOW_PROTOCOL *GraphicsIo,
+ IN EFI_SIMPLE_POINTER_STATE *State
+ )
+{
+ GRAPHICS_PRIVATE_DATA *Private;
+
+ Private = GRAPHICS_PRIVATE_DATA_FROM_THIS (GraphicsIo);
+
+ return EFI_NOT_READY;
+}
\ No newline at end of file
diff --git a/EmulatorPkg/Win/Host/WinGopScreen.c b/EmulatorPkg/Win/Host/WinGopScreen.c
new file mode 100644
index 0000000000..2ca51d23d0
--- /dev/null
+++ b/EmulatorPkg/Win/Host/WinGopScreen.c
@@ -0,0 +1,872 @@
+/** @file
+
+Copyright (c) 2006 - 2013, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+
+ WinGopScreen.c
+
+Abstract:
+
+ This file produces the graphics abstration of GOP. It is called by
+ WinNtGopDriver.c file which deals with the UEFI 2.0 driver model.
+ This file just does graphics.
+
+
+**/
+
+#include "WinGop.h"
+
+DWORD mTlsIndex = TLS_OUT_OF_INDEXES;
+DWORD mTlsIndexUseCount = 0; // lets us know when we can free mTlsIndex.
+
+BOOLEAN
+WinNtGopConvertParamToEfiKeyShiftState (
+ IN GRAPHICS_PRIVATE_DATA *Private,
+ IN WPARAM *wParam,
+ IN LPARAM *lParam,
+ IN BOOLEAN Flag
+ )
+{
+ switch (*wParam) {
+ //
+ // BUGBUG: Only GetAsyncKeyState() and GetKeyState() can distinguish
+ // left and right Ctrl, and Shift key.
+ // Neither of the two is defined in EFI_WIN_NT_THUNK_PROTOCOL.
+ // Therefor, we can not set the correct Shift state here.
+ //
+ case VK_SHIFT:
+ if ((*lParam & GOP_EXTENDED_KEY) == GOP_EXTENDED_KEY) {
+ Private->RightShift = Flag;
+ } else {
+ Private->LeftShift = Flag;
+ }
+ return TRUE;
+
+ case VK_LSHIFT:
+ Private->LeftShift = Flag;
+ return TRUE;
+
+ case VK_RSHIFT:
+ Private->RightShift = Flag;
+ return TRUE;
+
+ case VK_CONTROL:
+ if ((*lParam & GOP_EXTENDED_KEY) == GOP_EXTENDED_KEY) {
+ Private->RightCtrl= Flag;
+ } else {
+ Private->LeftCtrl = Flag;
+ }
+ return TRUE;
+
+ case VK_LCONTROL:
+ Private->LeftCtrl = Flag;
+ return TRUE;
+
+ case VK_RCONTROL:
+ Private->RightCtrl = Flag;
+ return TRUE;
+
+ case VK_LWIN:
+ Private->LeftLogo = Flag;
+ return TRUE;
+
+ case VK_RWIN:
+ Private->RightLogo = Flag;
+ return TRUE;
+
+ case VK_APPS:
+ Private->Menu = Flag;
+ return TRUE;
+ //
+ // BUGBUG: PrintScreen/SysRq can not trigger WM_KEYDOWN message,
+ // so SySReq shift state is not supported here.
+ //
+ case VK_PRINT:
+ Private->SysReq = Flag;
+ return TRUE;
+ //
+ // For Alt Keystroke.
+ //
+ case VK_MENU:
+ if ((*lParam & GOP_EXTENDED_KEY) == GOP_EXTENDED_KEY) {
+ Private->RightAlt = Flag;
+ } else {
+ Private->LeftAlt = Flag;
+ }
+ return TRUE;
+
+ default:
+ return FALSE;
+ }
+}
+
+BOOLEAN
+WinNtGopConvertParamToEfiKey (
+ IN GRAPHICS_PRIVATE_DATA *Private,
+ IN WPARAM *wParam,
+ IN LPARAM *lParam,
+ IN EFI_INPUT_KEY *Key
+ )
+{
+ BOOLEAN Flag;
+ Flag = FALSE;
+ switch (*wParam) {
+ case VK_HOME: Key->ScanCode = SCAN_HOME; Flag = TRUE; break;
+ case VK_END: Key->ScanCode = SCAN_END; Flag = TRUE; break;
+ case VK_LEFT: Key->ScanCode = SCAN_LEFT; Flag = TRUE; break;
+ case VK_RIGHT: Key->ScanCode = SCAN_RIGHT; Flag = TRUE; break;
+ case VK_UP: Key->ScanCode = SCAN_UP; Flag = TRUE; break;
+ case VK_DOWN: Key->ScanCode = SCAN_DOWN; Flag = TRUE; break;
+ case VK_DELETE: Key->ScanCode = SCAN_DELETE; Flag = TRUE; break;
+ case VK_INSERT: Key->ScanCode = SCAN_INSERT; Flag = TRUE; break;
+ case VK_PRIOR: Key->ScanCode = SCAN_PAGE_UP; Flag = TRUE; break;
+ case VK_NEXT: Key->ScanCode = SCAN_PAGE_DOWN; Flag = TRUE; break;
+ case VK_ESCAPE: Key->ScanCode = SCAN_ESC; Flag = TRUE; break;
+
+ case VK_F1: Key->ScanCode = SCAN_F1; Flag = TRUE; break;
+ case VK_F2: Key->ScanCode = SCAN_F2; Flag = TRUE; break;
+ case VK_F3: Key->ScanCode = SCAN_F3; Flag = TRUE; break;
+ case VK_F4: Key->ScanCode = SCAN_F4; Flag = TRUE; break;
+ case VK_F5: Key->ScanCode = SCAN_F5; Flag = TRUE; break;
+ case VK_F6: Key->ScanCode = SCAN_F6; Flag = TRUE; break;
+ case VK_F7: Key->ScanCode = SCAN_F7; Flag = TRUE; break;
+ case VK_F8: Key->ScanCode = SCAN_F8; Flag = TRUE; break;
+ case VK_F9: Key->ScanCode = SCAN_F9; Flag = TRUE; break;
+ case VK_F11: Key->ScanCode = SCAN_F11; Flag = TRUE; break;
+ case VK_F12: Key->ScanCode = SCAN_F12; Flag = TRUE; break;
+
+ case VK_F13: Key->ScanCode = SCAN_F13; Flag = TRUE; break;
+ case VK_F14: Key->ScanCode = SCAN_F14; Flag = TRUE; break;
+ case VK_F15: Key->ScanCode = SCAN_F15; Flag = TRUE; break;
+ case VK_F16: Key->ScanCode = SCAN_F16; Flag = TRUE; break;
+ case VK_F17: Key->ScanCode = SCAN_F17; Flag = TRUE; break;
+ case VK_F18: Key->ScanCode = SCAN_F18; Flag = TRUE; break;
+ case VK_F19: Key->ScanCode = SCAN_F19; Flag = TRUE; break;
+ case VK_F20: Key->ScanCode = SCAN_F20; Flag = TRUE; break;
+ case VK_F21: Key->ScanCode = SCAN_F21; Flag = TRUE; break;
+ case VK_F22: Key->ScanCode = SCAN_F22; Flag = TRUE; break;
+ case VK_F23: Key->ScanCode = SCAN_F23; Flag = TRUE; break;
+ case VK_F24: Key->ScanCode = SCAN_F24; Flag = TRUE; break;
+ case VK_PAUSE: Key->ScanCode = SCAN_PAUSE; Flag = TRUE; break;
+
+ //
+ // Set toggle state
+ //
+ case VK_NUMLOCK:
+ Private->NumLock = (BOOLEAN)(!Private->NumLock);
+ Flag = TRUE;
+ break;
+ case VK_SCROLL:
+ Private->ScrollLock = (BOOLEAN)(!Private->ScrollLock);
+ Flag = TRUE;
+ break;
+ case VK_CAPITAL:
+ Private->CapsLock = (BOOLEAN)(!Private->CapsLock);
+ Flag = TRUE;
+ break;
+ }
+
+ return (WinNtGopConvertParamToEfiKeyShiftState (Private, wParam, lParam, TRUE)) == TRUE ? TRUE : Flag;
+}
+
+
+//
+// GOP Protocol Member Functions
+//
+
+/**
+ Change the resolution and resize of the window
+**/
+EFI_STATUS
+EFIAPI
+WinNtWndSize (
+ IN EMU_GRAPHICS_WINDOW_PROTOCOL *GraphicsIo,
+ IN UINT32 Width,
+ IN UINT32 Height
+)
+{
+ UINT32 Size;
+ GRAPHICS_PRIVATE_DATA *Private;
+ RECT Rect;
+ EFI_GRAPHICS_OUTPUT_BLT_PIXEL *NewFillLine;
+
+ Private = GRAPHICS_PRIVATE_DATA_FROM_THIS (GraphicsIo);
+ Private->Width = Width;
+ Private->Height = Height;
+
+
+ //
+ // Free the old buffer. We do not save the content of the old buffer since the
+ // screen is to be cleared anyway. Clearing the screen is required by the EFI spec.
+ // See UEFI spec -EFI_GRAPHICS_OUTPUT_PROTOCOL.SetMode()
+ //
+ if (Private->VirtualScreenInfo != NULL) {
+ HeapFree (GetProcessHeap (), 0, Private->VirtualScreenInfo);
+ }
+
+ //
+ // Allocate DIB frame buffer directly from NT for performance enhancement
+ // This buffer is the virtual screen/frame buffer. This buffer is not the
+ // same a a frame buffer. The first row of this buffer will be the bottom
+ // line of the image. This is an artifact of the way we draw to the screen.
+ //
+ Size = Private->Width * Private->Height * sizeof (RGBQUAD) + sizeof (BITMAPV4HEADER);
+ Private->VirtualScreenInfo = HeapAlloc (
+ GetProcessHeap (),
+ HEAP_ZERO_MEMORY,
+ Size
+ );
+
+ //
+ // Update the virtual screen info data structure
+ //
+ Private->VirtualScreenInfo->bV4Size = sizeof (BITMAPV4HEADER);
+ Private->VirtualScreenInfo->bV4Width = Private->Width;
+ Private->VirtualScreenInfo->bV4Height = Private->Height;
+ Private->VirtualScreenInfo->bV4Planes = 1;
+ Private->VirtualScreenInfo->bV4BitCount = 32;
+ //
+ // uncompressed
+ //
+ Private->VirtualScreenInfo->bV4V4Compression = BI_RGB;
+
+ //
+ // The rest of the allocated memory block is the virtual screen buffer
+ //
+ Private->VirtualScreen = (RGBQUAD *)(Private->VirtualScreenInfo + 1);
+
+ //
+ // Use the AdjuctWindowRect fuction to calculate the real width and height
+ // of the new window including the border and caption
+ //
+ Rect.left = 0;
+ Rect.top = 0;
+ Rect.right = Private->Width;
+ Rect.bottom = Private->Height;
+
+ AdjustWindowRect (&Rect, WS_OVERLAPPEDWINDOW, 0);
+
+ Width = Rect.right - Rect.left;
+ Height = Rect.bottom - Rect.top;
+
+ //
+ // Retrieve the original window position information
+ //
+ GetWindowRect (Private->WindowHandle, &Rect);
+
+ //
+ // Adjust the window size
+ //
+ MoveWindow (Private->WindowHandle, Rect.left, Rect.top, (INT32)Width, (INT32)Height, TRUE);
+
+ NewFillLine = AllocatePool (sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL) * Private->Width);
+ if (NewFillLine == NULL) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ if (Private->FillLine != NULL) {
+ FreePool (Private->FillLine);
+ }
+
+ Private->FillLine = NewFillLine;
+ return EFI_SUCCESS;
+}
+
+/**
+ Blt pixels from the rectangle (Width X Height) formed by the BltBuffer
+ onto the graphics screen starting a location (X, Y). (0, 0) is defined as
+ the upper left hand side of the screen. (X, Y) can be outside of the
+ current screen geometry and the BltBuffer will be cliped when it is
+ displayed. X and Y can be negative or positive. If Width or Height is
+ bigger than the current video screen the image will be clipped.
+
+ @param This Protocol instance pointer.
+ @param X X location on graphics screen.
+ @param Y Y location on the graphics screen.
+ @param Width Width of BltBuffer.
+ @param Height Hight of BltBuffer
+ @param BltOperation Operation to perform on BltBuffer and video memory
+ @param BltBuffer Buffer containing data to blt into video buffer.
+ This buffer has a size of
+ Width*Height*sizeof(EFI_GRAPHICS_OUTPUT_BLT_PIXEL)
+ @param SourceX If the BltOperation is a EfiCopyBlt this is the
+ source of the copy. For other BLT operations this
+ argument is not used.
+ @param SourceX If the BltOperation is a EfiCopyBlt this is the
+ source of the copy. For other BLT operations this
+ argument is not used.
+
+ @retval EFI_SUCCESS The palette is updated with PaletteArray.
+ @retval EFI_INVALID_PARAMETER BltOperation is not valid.
+ @retval EFI_DEVICE_ERROR A hardware error occured writting to the video
+ buffer.
+
+**/
+// TODO: SourceY - add argument and description to function comment
+// TODO: DestinationX - add argument and description to function comment
+// TODO: DestinationY - add argument and description to function comment
+// TODO: Delta - add argument and description to function comment
+EFI_STATUS
+WinNtWndBlt (
+ IN EMU_GRAPHICS_WINDOW_PROTOCOL *GraphicsIo,
+ IN EFI_UGA_PIXEL *BltBuffer OPTIONAL,
+ IN EFI_UGA_BLT_OPERATION BltOperation,
+ IN EMU_GRAPHICS_WINDOWS__BLT_ARGS *Args
+)
+{
+ GRAPHICS_PRIVATE_DATA *Private;
+ UINTN DstY;
+ UINTN SrcY;
+ RGBQUAD *VScreen;
+ RGBQUAD *VScreenSrc;
+ EFI_GRAPHICS_OUTPUT_BLT_PIXEL *Blt;
+ UINTN Index;
+ RECT Rect;
+ EFI_GRAPHICS_OUTPUT_BLT_PIXEL *FillPixel;
+ UINT32 VerticalResolution;
+ UINT32 HorizontalResolution;
+
+ Private = GRAPHICS_PRIVATE_DATA_FROM_THIS (GraphicsIo);
+
+ //
+ // We need to fill the Virtual Screen buffer with the blt data.
+ // The virtual screen is upside down, as the first row is the bootom row of
+ // the image.
+ //
+ VerticalResolution = Private->VirtualScreenInfo->bV4Height;
+ HorizontalResolution = Private->VirtualScreenInfo->bV4Width;
+ if (BltOperation == EfiBltVideoToBltBuffer) {
+
+ for (SrcY = Args->SourceY, DstY = Args->DestinationY; DstY < (Args->Height + Args->DestinationY); SrcY++, DstY++) {
+ Blt = (EFI_GRAPHICS_OUTPUT_BLT_PIXEL *) ((UINT8 *) BltBuffer + (DstY * Args->Delta) + Args->DestinationX * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL));
+ VScreen = &Private->VirtualScreen[(VerticalResolution - SrcY - 1) * HorizontalResolution + Args->SourceX];
+ CopyMem (Blt, VScreen, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL) * Args->Width);
+ }
+ } else {
+ if (BltOperation == EfiBltVideoFill) {
+ FillPixel = BltBuffer;
+ for (Index = 0; Index < Args->Width; Index++) {
+ Private->FillLine[Index] = *FillPixel;
+ }
+ }
+
+ for (Index = 0; Index < Args->Height; Index++) {
+ if (Args->DestinationY <= Args->SourceY) {
+ SrcY = Args->SourceY + Index;
+ DstY = Args->DestinationY + Index;
+ } else {
+ SrcY = Args->SourceY + Args->Height - Index - 1;
+ DstY = Args->DestinationY + Args->Height - Index - 1;
+ }
+
+ VScreen = &Private->VirtualScreen[(VerticalResolution - DstY - 1) * HorizontalResolution + Args->DestinationX];
+ switch (BltOperation) {
+ case EfiBltBufferToVideo:
+ Blt = (EFI_GRAPHICS_OUTPUT_BLT_PIXEL *) ((UINT8 *) BltBuffer + (SrcY * Args->Delta) + Args->SourceX * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL));
+ CopyMem (VScreen, Blt, Args->Width * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL));
+ break;
+
+ case EfiBltVideoToVideo:
+ VScreenSrc = &Private->VirtualScreen[(VerticalResolution - SrcY - 1) * HorizontalResolution + Args->SourceX];
+ CopyMem (VScreen, VScreenSrc, Args->Width * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL));
+ break;
+
+ case EfiBltVideoFill:
+ CopyMem (VScreen, Private->FillLine, Args->Width * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL));
+ break;
+ }
+ }
+ }
+
+ if (BltOperation != EfiBltVideoToBltBuffer) {
+ //
+ // Mark the area we just blted as Invalid so WM_PAINT will update.
+ //
+ Rect.left = (LONG)Args->DestinationX;
+ Rect.top = (LONG)Args->DestinationY;
+ Rect.right = (LONG)(Args->DestinationX + Args->Width);
+ Rect.bottom = (LONG)(Args->DestinationY + Args->Height);
+ InvalidateRect (Private->WindowHandle, &Rect, FALSE);
+
+ //
+ // Send the WM_PAINT message to the thread that is drawing the window. We
+ // are in the main thread and the window drawing is in a child thread.
+ // There is a child thread per window. We have no CriticalSection or Mutex
+ // since we write the data and the other thread displays the data. While
+ // we may miss some data for a short period of time this is no different than
+ // a write combining on writes to a frame buffer.
+ //
+
+ UpdateWindow (Private->WindowHandle);
+ }
+
+ return EFI_SUCCESS;
+}
+
+
+
+/**
+ Win32 Windows event handler.
+
+ See Win32 Book
+
+ @return See Win32 Book
+
+**/
+// TODO: hwnd - add argument and description to function comment
+// TODO: iMsg - add argument and description to function comment
+// TODO: wParam - add argument and description to function comment
+// TODO: lParam - add argument and description to function comment
+LRESULT
+CALLBACK
+WinNtGopThreadWindowProc (
+ IN HWND hwnd,
+ IN UINT iMsg,
+ IN WPARAM wParam,
+ IN LPARAM lParam
+ )
+{
+ GRAPHICS_PRIVATE_DATA *Private;
+ UINTN Size;
+ HDC Handle;
+ PAINTSTRUCT PaintStruct;
+ LPARAM Index;
+ EFI_INPUT_KEY Key;
+ BOOLEAN AltIsPress;
+
+ //
+ // BugBug - if there are two instances of this DLL in memory (such as is
+ // the case for ERM), the correct instance of this function may not be called.
+ // This also means that the address of the mTlsIndex value will be wrong, and
+ // the value may be wrong too.
+ //
+
+
+ //
+ // Use mTlsIndex global to get a Thread Local Storage version of Private.
+ // This works since each Gop protocol has a unique Private data instance and
+ // a unique thread.
+ //
+ AltIsPress = FALSE;
+ Private = TlsGetValue (mTlsIndex);
+ ASSERT (NULL != Private);
+
+ switch (iMsg) {
+ case WM_CREATE:
+ Size = Private->Width * Private->Height * sizeof (RGBQUAD);
+
+ //
+ // Allocate DIB frame buffer directly from NT for performance enhancement
+ // This buffer is the virtual screen/frame buffer. This buffer is not the
+ // same a a frame buffer. The first fow of this buffer will be the bottom
+ // line of the image. This is an artifact of the way we draw to the screen.
+ //
+ Private->VirtualScreenInfo = HeapAlloc (
+ GetProcessHeap (),
+ HEAP_ZERO_MEMORY,
+ Size
+ );
+
+ Private->VirtualScreenInfo->bV4Size = sizeof (BITMAPV4HEADER);
+ Private->VirtualScreenInfo->bV4Width = Private->Width;
+ Private->VirtualScreenInfo->bV4Height = Private->Height;
+ Private->VirtualScreenInfo->bV4Planes = 1;
+ Private->VirtualScreenInfo->bV4BitCount = 32;
+ //
+ // uncompressed
+ //
+ Private->VirtualScreenInfo->bV4V4Compression = BI_RGB;
+ Private->VirtualScreen = (RGBQUAD *) (Private->VirtualScreenInfo + 1);
+ return 0;
+
+ case WM_PAINT:
+ //
+ // I have not found a way to convert hwnd into a Private context. So for
+ // now we use this API to convert hwnd to Private data.
+ //
+
+ Handle = BeginPaint (hwnd, &PaintStruct);
+
+ SetDIBitsToDevice (
+ Handle, // Destination Device Context
+ 0, // Destination X - 0
+ 0, // Destination Y - 0
+ Private->Width, // Width
+ Private->Height, // Height
+ 0, // Source X
+ 0, // Source Y
+ 0, // DIB Start Scan Line
+ Private->Height, // Number of scan lines
+ Private->VirtualScreen, // Address of array of DIB bits
+ (BITMAPINFO *) Private->VirtualScreenInfo, // Address of structure with bitmap info
+ DIB_RGB_COLORS // RGB or palette indexes
+ );
+
+ EndPaint (hwnd, &PaintStruct);
+ return 0;
+
+ //
+ // F10 and the ALT key do not create a WM_KEYDOWN message, thus this special case
+ // WM_SYSKEYDOWN is posted when F10 is pressed or
+ // holds down ALT key and then presses another key.
+ //
+ case WM_SYSKEYDOWN:
+
+ Key.ScanCode = 0;
+ Key.UnicodeChar = CHAR_NULL;
+ switch (wParam) {
+ case VK_F10:
+ Key.ScanCode = SCAN_F10;
+ Key.UnicodeChar = CHAR_NULL;
+ GopPrivateAddKey (Private, Key);
+ return 0;
+ }
+
+ //
+ // If ALT or ALT + modifier key is pressed.
+ //
+ if (WinNtGopConvertParamToEfiKey (Private, &wParam, &lParam, &Key)) {
+ if (Key.ScanCode != 0){
+ //
+ // If ALT is pressed with other ScanCode.
+ // Always revers the left Alt for simple.
+ //
+ Private->LeftAlt = TRUE;
+ }
+ GopPrivateAddKey (Private, Key);
+ //
+ // When Alt is released there is no windoes message, so
+ // clean it after using it.
+ //
+ Private->RightAlt = FALSE;
+ Private->LeftAlt = FALSE;
+ return 0;
+ }
+ AltIsPress = TRUE;
+
+ case WM_CHAR:
+ //
+ // The ESC key also generate WM_CHAR.
+ //
+ if (wParam == 0x1B) {
+ return 0;
+ }
+
+ if (AltIsPress == TRUE) {
+ //
+ // If AltIsPress is true that means the Alt key is pressed.
+ //
+ Private->LeftAlt = TRUE;
+ }
+ for (Index = 0; Index < (lParam & 0xffff); Index++) {
+ if (wParam != 0) {
+ Key.UnicodeChar = (CHAR16) wParam;
+ Key.ScanCode = SCAN_NULL;
+ GopPrivateAddKey (Private, Key);
+ }
+ }
+ if (AltIsPress == TRUE) {
+ //
+ // When Alt is released there is no windoes message, so
+ // clean it after using it.
+ //
+ Private->LeftAlt = FALSE;
+ Private->RightAlt = FALSE;
+ }
+ return 0;
+
+ case WM_SYSKEYUP:
+ //
+ // ALT is pressed with another key released
+ //
+ WinNtGopConvertParamToEfiKeyShiftState (Private, &wParam, &lParam, FALSE);
+ return 0;
+
+ case WM_KEYDOWN:
+ Key.ScanCode = SCAN_NULL;
+ Key.UnicodeChar = CHAR_NULL;
+ //
+ // A value key press will cause a WM_KEYDOWN first, then cause a WM_CHAR
+ // So if there is no modifier key updated, skip the WM_KEYDOWN even.
+ //
+ if (WinNtGopConvertParamToEfiKey (Private, &wParam, &lParam, &Key)) {
+ //
+ // Support the partial keystroke, add all keydown event into the queue.
+ //
+ GopPrivateAddKey (Private, Key);
+ }
+ return 0;
+
+ case WM_KEYUP:
+ WinNtGopConvertParamToEfiKeyShiftState (Private, &wParam, &lParam, FALSE);
+ return 0;
+
+ case WM_CLOSE:
+ //
+ // This close message is issued by user, core is not aware of this,
+ // so don't release the window display resource, just hide the window.
+ //
+ ShowWindow (Private->WindowHandle, SW_HIDE);
+ return 0;
+
+ case WM_DESTROY:
+ DestroyWindow (hwnd);
+ PostQuitMessage (0);
+
+ HeapFree (GetProcessHeap (), 0, Private->VirtualScreenInfo);
+
+ ExitThread (0);
+
+ default:
+ break;
+ };
+
+ return DefWindowProc (hwnd, iMsg, wParam, lParam);
+}
+
+
+/**
+ This thread simulates the end of WinMain () aplication. Each Winow nededs
+ to process it's events. The messages are dispatched to
+ WinNtGopThreadWindowProc ().
+ Be very careful sine WinNtGopThreadWinMain () and WinNtGopThreadWindowProc ()
+ are running in a seperate thread. We have to do this to process the events.
+
+ @param lpParameter Handle of window to manage.
+
+ @return if a WM_QUIT message is returned exit.
+
+**/
+DWORD
+WINAPI
+WinNtGopThreadWinMain (
+ LPVOID lpParameter
+ )
+{
+ MSG Message;
+ GRAPHICS_PRIVATE_DATA *Private;
+ RECT Rect;
+
+ Private = (GRAPHICS_PRIVATE_DATA *) lpParameter;
+ ASSERT (NULL != Private);
+
+ //
+ // Since each thread has unique private data, save the private data in Thread
+ // Local Storage slot. Then the shared global mTlsIndex can be used to get
+ // thread specific context.
+ //
+ TlsSetValue (mTlsIndex, Private);
+
+ Private->ThreadId = GetCurrentThreadId ();
+
+ Private->WindowsClass.cbSize = sizeof (WNDCLASSEX);
+ Private->WindowsClass.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
+ Private->WindowsClass.lpfnWndProc = WinNtGopThreadWindowProc;
+ Private->WindowsClass.cbClsExtra = 0;
+ Private->WindowsClass.cbWndExtra = 0;
+ Private->WindowsClass.hInstance = NULL;
+ Private->WindowsClass.hIcon = LoadIcon (NULL, IDI_APPLICATION);
+ Private->WindowsClass.hCursor = LoadCursor (NULL, IDC_ARROW);
+ Private->WindowsClass.hbrBackground = (HBRUSH)(UINTN)COLOR_WINDOW;
+ Private->WindowsClass.lpszMenuName = NULL;
+ Private->WindowsClass.lpszClassName = WIN_NT_GOP_CLASS_NAME;
+ Private->WindowsClass.hIconSm = LoadIcon (NULL, IDI_APPLICATION);
+
+ //
+ // Use 100 x 100 as initial Window size.
+ //
+ Private->Width = 100;
+ Private->Height = 100;
+
+
+ //
+ // This call will fail after the first time, but thats O.K. since we only need
+ // WIN_NT_GOP_CLASS_NAME to exist to create the window.
+ //
+ // Note: Multiple instances of this DLL will use the same instance of this
+ // Class, including the callback function, unless the Class is unregistered and
+ // successfully registered again.
+ //
+ RegisterClassEx (&Private->WindowsClass);
+
+ //
+ // Setting Rect values to allow for the AdjustWindowRect to provide
+ // us the correct sizes for the client area when doing the CreateWindowEx
+ //
+ Rect.top = 0;
+ Rect.bottom = Private->Height;
+ Rect.left = 0;
+ Rect.right = Private->Width;
+
+ AdjustWindowRect (&Rect, WS_OVERLAPPEDWINDOW, 0);
+
+ Private->WindowHandle = CreateWindowEx (
+ 0,
+ WIN_NT_GOP_CLASS_NAME,
+ Private->WindowName,
+ WS_OVERLAPPEDWINDOW,
+ CW_USEDEFAULT,
+ CW_USEDEFAULT,
+ Rect.right - Rect.left,
+ Rect.bottom - Rect.top,
+ NULL,
+ NULL,
+ NULL,
+ (VOID **)&Private
+ );
+
+ //
+ // The reset of this thread is the standard winows program. We need a sperate
+ // thread since we must process the message loop to make windows act like
+ // windows.
+ //
+
+ ShowWindow (Private->WindowHandle, SW_SHOW);
+ UpdateWindow (Private->WindowHandle);
+
+ //
+ // Let the main thread get some work done
+ //
+ ReleaseSemaphore (Private->ThreadInited, 1, NULL);
+
+ //
+ // This is the message loop that all Windows programs need.
+ //
+ while (GetMessage (&Message, Private->WindowHandle, 0, 0)) {
+ TranslateMessage (&Message);
+ DispatchMessage (&Message);
+ }
+
+ return (DWORD)Message.wParam;
+}
+
+
+/**
+ TODO: Add function description
+
+ @param Private TODO: add argument description
+ @param HorizontalResolution TODO: add argument description
+ @param VerticalResolution TODO: add argument description
+ @param ColorDepth TODO: add argument description
+ @param RefreshRate TODO: add argument description
+
+ @return TODO: add return values
+
+**/
+EFI_STATUS
+EFIAPI
+WinNtGraphicsWindowOpen (
+ IN EMU_IO_THUNK_PROTOCOL *This
+ )
+{
+ DWORD NewThreadId;
+ GRAPHICS_PRIVATE_DATA *Private;
+
+ Private = AllocateZeroPool (sizeof (*Private));
+
+ GopPrivateCreateQ (Private, &Private->QueueForRead);
+
+ Private->GraphicsWindowIo.Size = WinNtWndSize;
+ Private->GraphicsWindowIo.CheckKey = WinNtWndCheckKey;
+ Private->GraphicsWindowIo.GetKey = WinNtWndGetKey;
+ Private->GraphicsWindowIo.KeySetState = WinNtWndKeySetState;
+ Private->GraphicsWindowIo.RegisterKeyNotify = WinNtWndRegisterKeyNotify;
+ Private->GraphicsWindowIo.Blt = WinNtWndBlt;
+ Private->GraphicsWindowIo.CheckPointer = WinNtWndCheckPointer;
+ Private->GraphicsWindowIo.GetPointerState = WinNtWndGetPointerState;
+
+ Private->WindowName = This->ConfigString;
+ //
+ // Initialize a Thread Local Storge variable slot. We use TLS to get the
+ // correct Private data instance into the windows thread.
+ //
+ if (mTlsIndex == TLS_OUT_OF_INDEXES) {
+ ASSERT (0 == mTlsIndexUseCount);
+ mTlsIndex = TlsAlloc ();
+ }
+
+ //
+ // always increase the use count!
+ //
+ mTlsIndexUseCount++;
+
+ Private->ThreadInited = CreateSemaphore (NULL, 0, 1, NULL);
+ Private->ThreadHandle = CreateThread (
+ NULL,
+ 0,
+ WinNtGopThreadWinMain,
+ (VOID *) Private,
+ 0,
+ &NewThreadId
+ );
+
+ //
+ // The other thread has entered the windows message loop so we can
+ // continue our initialization.
+ //
+ WaitForSingleObject (Private->ThreadInited, INFINITE);
+ CloseHandle (Private->ThreadInited);
+
+ This->Private = Private;
+ This->Interface = &Private->GraphicsWindowIo;
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+EFIAPI
+WinNtGraphicsWindowClose (
+ IN EMU_IO_THUNK_PROTOCOL *This
+)
+{
+ GRAPHICS_PRIVATE_DATA *Private;
+
+ Private = (GRAPHICS_PRIVATE_DATA *)This->Private;
+
+ //
+ // BugBug: Shutdown GOP Hardware and any child devices.
+ //
+ SendMessage (Private->WindowHandle, WM_DESTROY, 0, 0);
+ CloseHandle (Private->ThreadHandle);
+
+ mTlsIndexUseCount--;
+
+ //
+ // The callback function for another window could still be called,
+ // so we need to make sure there are no more users of mTlsIndex.
+ //
+ if (0 == mTlsIndexUseCount) {
+ ASSERT (TLS_OUT_OF_INDEXES != mTlsIndex);
+
+ TlsFree (mTlsIndex);
+ mTlsIndex = TLS_OUT_OF_INDEXES;
+
+ UnregisterClass (
+ Private->WindowsClass.lpszClassName,
+ Private->WindowsClass.hInstance
+ );
+ }
+
+
+ GopPrivateDestroyQ (Private, &Private->QueueForRead);
+ return EFI_SUCCESS;
+}
+
+
+EMU_IO_THUNK_PROTOCOL mWinNtWndThunkIo = {
+ &gEmuGraphicsWindowProtocolGuid,
+ NULL,
+ NULL,
+ 0,
+ WinNtGraphicsWindowOpen,
+ WinNtGraphicsWindowClose,
+ NULL
+};
diff --git a/EmulatorPkg/Win/Host/WinHost.c b/EmulatorPkg/Win/Host/WinHost.c
index 22399f18b9..f8d21d26d9 100644
--- a/EmulatorPkg/Win/Host/WinHost.c
+++ b/EmulatorPkg/Win/Host/WinHost.c
@@ -424,6 +424,11 @@ Returns:
//
AddThunkPpi (EFI_PEI_PPI_DESCRIPTOR_PPI, &gEmuThunkPpiGuid, &mSecEmuThunkPpi);
+ //
+ // Emulator Bus Driver Thunks
+ //
+ AddThunkProtocol (&mWinNtWndThunkIo, (CHAR16 *)PcdGetPtr (PcdEmuGop), TRUE);
+
//
// Allocate space for gSystemMemory Array
//
diff --git a/EmulatorPkg/Win/Host/WinHost.h b/EmulatorPkg/Win/Host/WinHost.h
index c73ba17e74..3dc6a7e641 100644
--- a/EmulatorPkg/Win/Host/WinHost.h
+++ b/EmulatorPkg/Win/Host/WinHost.h
@@ -197,4 +197,5 @@ SecInitializeThunk (
VOID
);
extern EMU_THUNK_PROTOCOL gEmuThunkProtocol;
+extern EMU_IO_THUNK_PROTOCOL mWinNtWndThunkIo;
#endif
\ No newline at end of file
diff --git a/EmulatorPkg/Win/Host/WinHost.inf b/EmulatorPkg/Win/Host/WinHost.inf
index 544e775c49..b62791bcfa 100644
--- a/EmulatorPkg/Win/Host/WinHost.inf
+++ b/EmulatorPkg/Win/Host/WinHost.inf
@@ -30,6 +30,9 @@ [Defines]
[Sources]
WinMemoryAllocationLib.c
+ WinGopInput.c
+ WinGopScreen.c
+ WinGop.h
WinThunk.c
WinHost.h
WinHost.c
@@ -55,6 +58,9 @@ [LibraryClasses]
[Ppis]
gEmuThunkPpiGuid
+[Protocols]
+ gEmuIoThunkProtocolGuid
+ gEmuGraphicsWindowProtocolGuid
[Pcd]
gEfiMdeModulePkgTokenSpaceGuid.PcdInitValueInTempStack
@@ -62,6 +68,7 @@ [Pcd]
gEmulatorPkgTokenSpaceGuid.PcdEmuFirmwareVolume
gEmulatorPkgTokenSpaceGuid.PcdEmuMemorySize
gEmulatorPkgTokenSpaceGuid.PcdEmuFdBaseAddress
+ gEmulatorPkgTokenSpaceGuid.PcdEmuGop|L"GOP Window"
gEmulatorPkgTokenSpaceGuid.PcdPeiServicesTablePage
[BuildOptions]
--
2.16.1.windows.1
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [PATCH 06/12] EmulatorPkg/Win: Add timer and interrupt support
2018-08-23 9:52 [PATCH 00/12] Add WinHost support in EmulatorPkg Ruiyu Ni
` (4 preceding siblings ...)
2018-08-23 9:52 ` [PATCH 05/12] EmulatorPkg/Win: Add input/output support Ruiyu Ni
@ 2018-08-23 9:52 ` Ruiyu Ni
2018-08-23 9:52 ` [PATCH 07/12] EmulatorPkg/Win: Add RTC support Ruiyu Ni
` (6 subsequent siblings)
12 siblings, 0 replies; 14+ messages in thread
From: Ruiyu Ni @ 2018-08-23 9:52 UTC (permalink / raw)
To: edk2-devel; +Cc: Hao Wu, Andrew Fish
Now the firmware can boot to Shell and count down 5 seconds to
command prompt.
Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Ruiyu Ni <ruiyu.ni@intel.com>
Cc: Hao Wu <hao.a.wu@intel.com>
Cc: Andrew Fish <afish@intel.com>
---
EmulatorPkg/Win/Host/WinThunk.c | 194 ++++++++++++++++++++++++++++++++++++++++
1 file changed, 194 insertions(+)
diff --git a/EmulatorPkg/Win/Host/WinThunk.c b/EmulatorPkg/Win/Host/WinThunk.c
index 69a61258f3..ffe71aef9a 100644
--- a/EmulatorPkg/Win/Host/WinThunk.c
+++ b/EmulatorPkg/Win/Host/WinThunk.c
@@ -205,12 +205,193 @@ SecFree (
return TRUE;
}
+
+
+//
+// Define a global that we can use to shut down the NT timer thread when
+// the timer is canceled.
+//
+BOOLEAN mCancelTimerThread = FALSE;
+
+//
+// The notification function to call on every timer interrupt
+//
+EMU_SET_TIMER_CALLBACK *mTimerNotifyFunction = NULL;
+
+//
+// The thread handle for this driver
+//
+HANDLE mNtMainThreadHandle;
+
+//
+// The timer value from the last timer interrupt
+//
+UINT32 mNtLastTick;
+
+//
+// Critical section used to update varibles shared between the main thread and
+// the timer interrupt thread.
+//
+CRITICAL_SECTION mNtCriticalSection;
+
+//
+// Worker Functions
+//
+UINT mMMTimerThreadID = 0;
+
+volatile BOOLEAN mInterruptEnabled = FALSE;
+
+VOID
+CALLBACK
+MMTimerThread (
+ UINT wTimerID,
+ UINT msg,
+ DWORD dwUser,
+ DWORD dw1,
+ DWORD dw2
+)
+{
+ UINT32 CurrentTick;
+ UINT32 Delta;
+
+ if (!mCancelTimerThread) {
+
+ //
+ // Suspend the main thread until we are done.
+ // Enter the critical section before suspending
+ // and leave the critical section after resuming
+ // to avoid deadlock between main and timer thread.
+ //
+ EnterCriticalSection (&mNtCriticalSection);
+ SuspendThread (mNtMainThreadHandle);
+
+ //
+ // If the timer thread is being canceled, then bail immediately.
+ // We check again here because there's a small window of time from when
+ // this thread was kicked off and when we suspended the main thread above.
+ //
+ if (mCancelTimerThread) {
+ ResumeThread (mNtMainThreadHandle);
+ LeaveCriticalSection (&mNtCriticalSection);
+ timeKillEvent (wTimerID);
+ mMMTimerThreadID = 0;
+ return;
+ }
+
+ while (!mInterruptEnabled) {
+ //
+ // Resume the main thread
+ //
+ ResumeThread (mNtMainThreadHandle);
+ LeaveCriticalSection (&mNtCriticalSection);
+
+ //
+ // Wait for interrupts to be enabled.
+ //
+ while (!mInterruptEnabled) {
+ Sleep (1);
+ }
+
+ //
+ // Suspend the main thread until we are done
+ //
+ EnterCriticalSection (&mNtCriticalSection);
+ SuspendThread (mNtMainThreadHandle);
+ }
+
+ //
+ // Get the current system tick
+ //
+ CurrentTick = GetTickCount ();
+ Delta = CurrentTick - mNtLastTick;
+ mNtLastTick = CurrentTick;
+
+ //
+ // If delay was more then 1 second, ignore it (probably debugging case)
+ //
+ if (Delta < 1000) {
+
+ //
+ // Only invoke the callback function if a Non-NULL handler has been
+ // registered. Assume all other handlers are legal.
+ //
+ if (mTimerNotifyFunction != NULL) {
+ mTimerNotifyFunction (Delta);
+ }
+ }
+
+ //
+ // Resume the main thread
+ //
+ ResumeThread (mNtMainThreadHandle);
+ LeaveCriticalSection (&mNtCriticalSection);
+ } else {
+ timeKillEvent (wTimerID);
+ mMMTimerThreadID = 0;
+ }
+
+}
+
VOID
SecSetTimer (
IN UINT64 TimerPeriod,
IN EMU_SET_TIMER_CALLBACK Callback
)
{
+ //
+// If TimerPeriod is 0, then the timer thread should be canceled
+//
+ if (TimerPeriod == 0) {
+ //
+ // Cancel the timer thread
+ //
+ EnterCriticalSection (&mNtCriticalSection);
+
+ mCancelTimerThread = TRUE;
+
+ LeaveCriticalSection (&mNtCriticalSection);
+
+ //
+ // Wait for the timer thread to exit
+ //
+
+ if (mMMTimerThreadID != 0) {
+ timeKillEvent (mMMTimerThreadID);
+ mMMTimerThreadID = 0;
+ }
+ } else {
+ //
+ // If the TimerPeriod is valid, then create and/or adjust the period of the timer thread
+ //
+ EnterCriticalSection (&mNtCriticalSection);
+
+ mCancelTimerThread = FALSE;
+
+ LeaveCriticalSection (&mNtCriticalSection);
+
+ //
+ // Get the starting tick location if we are just starting the timer thread
+ //
+ mNtLastTick = GetTickCount ();
+
+ if (mMMTimerThreadID) {
+ timeKillEvent (mMMTimerThreadID);
+ }
+
+ SetThreadPriority (
+ GetCurrentThread (),
+ THREAD_PRIORITY_HIGHEST
+ );
+
+ mMMTimerThreadID = timeSetEvent (
+ (UINT)TimerPeriod,
+ 0,
+ MMTimerThread,
+ (DWORD_PTR)NULL,
+ TIME_PERIODIC | TIME_KILL_SYNCHRONOUS | TIME_CALLBACK_FUNCTION
+ );
+ }
+ mTimerNotifyFunction = Callback;
}
VOID
@@ -218,6 +399,17 @@ SecInitializeThunk (
VOID
)
{
+ InitializeCriticalSection (&mNtCriticalSection);
+
+ DuplicateHandle (
+ GetCurrentProcess (),
+ GetCurrentThread (),
+ GetCurrentProcess (),
+ &mNtMainThreadHandle,
+ 0,
+ FALSE,
+ DUPLICATE_SAME_ACCESS
+ );
}
VOID
@@ -225,6 +417,7 @@ SecEnableInterrupt (
VOID
)
{
+ mInterruptEnabled = TRUE;
}
@@ -233,6 +426,7 @@ SecDisableInterrupt (
VOID
)
{
+ mInterruptEnabled = FALSE;
}
--
2.16.1.windows.1
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [PATCH 07/12] EmulatorPkg/Win: Add RTC support
2018-08-23 9:52 [PATCH 00/12] Add WinHost support in EmulatorPkg Ruiyu Ni
` (5 preceding siblings ...)
2018-08-23 9:52 ` [PATCH 06/12] EmulatorPkg/Win: Add timer and interrupt support Ruiyu Ni
@ 2018-08-23 9:52 ` Ruiyu Ni
2018-08-23 9:52 ` [PATCH 08/12] EmulatorPkg/Win: Add SimpleFileSystem support Ruiyu Ni
` (5 subsequent siblings)
12 siblings, 0 replies; 14+ messages in thread
From: Ruiyu Ni @ 2018-08-23 9:52 UTC (permalink / raw)
To: edk2-devel; +Cc: Hao Wu, Andrew Fish
Now firmware can display the time correctly.
Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Ruiyu Ni <ruiyu.ni@intel.com>
Cc: Hao Wu <hao.a.wu@intel.com>
Cc: Andrew Fish <afish@intel.com>
---
EmulatorPkg/Win/Host/WinThunk.c | 58 +++++++++++++++++++++++++++++++++++++++--
1 file changed, 56 insertions(+), 2 deletions(-)
diff --git a/EmulatorPkg/Win/Host/WinThunk.c b/EmulatorPkg/Win/Host/WinThunk.c
index ffe71aef9a..306fe75ecd 100644
--- a/EmulatorPkg/Win/Host/WinThunk.c
+++ b/EmulatorPkg/Win/Host/WinThunk.c
@@ -482,14 +482,68 @@ SecGetTime (
OUT EFI_TIME_CAPABILITIES *Capabilities OPTIONAL
)
{
+ SYSTEMTIME SystemTime;
+ TIME_ZONE_INFORMATION TimeZone;
+
+ GetLocalTime (&SystemTime);
+ GetTimeZoneInformation (&TimeZone);
+
+ Time->Year = (UINT16)SystemTime.wYear;
+ Time->Month = (UINT8)SystemTime.wMonth;
+ Time->Day = (UINT8)SystemTime.wDay;
+ Time->Hour = (UINT8)SystemTime.wHour;
+ Time->Minute = (UINT8)SystemTime.wMinute;
+ Time->Second = (UINT8)SystemTime.wSecond;
+ Time->Nanosecond = (UINT32)(SystemTime.wMilliseconds * 1000000);
+ Time->TimeZone = (INT16)TimeZone.Bias;
+
+ if (Capabilities != NULL) {
+ Capabilities->Resolution = 1;
+ Capabilities->Accuracy = 50000000;
+ Capabilities->SetsToZero = FALSE;
+ }
+
+ Time->Daylight = 0;
+ if (TimeZone.StandardDate.wMonth) {
+ Time->Daylight = (UINT8)TimeZone.StandardDate.wMonth;
+ }
}
EFI_STATUS
SecSetTime (
IN EFI_TIME *Time
-)
+ )
{
- return EFI_SUCCESS;
+ TIME_ZONE_INFORMATION TimeZone;
+ SYSTEMTIME SystemTime;
+ BOOL Flag;
+
+ //
+ // Set Daylight savings time information and Time Zone
+ //
+ GetTimeZoneInformation (&TimeZone);
+ TimeZone.StandardDate.wMonth = Time->Daylight;
+ TimeZone.Bias = Time->TimeZone;
+ Flag = SetTimeZoneInformation (&TimeZone);
+ if (!Flag) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ SystemTime.wYear = Time->Year;
+ SystemTime.wMonth = Time->Month;
+ SystemTime.wDay = Time->Day;
+ SystemTime.wHour = Time->Hour;
+ SystemTime.wMinute = Time->Minute;
+ SystemTime.wSecond = Time->Second;
+ SystemTime.wMilliseconds = (INT16)(Time->Nanosecond / 1000000);
+
+ Flag = SetLocalTime (&SystemTime);
+
+ if (!Flag) {
+ return EFI_DEVICE_ERROR;
+ } else {
+ return EFI_SUCCESS;
+ }
}
EMU_THUNK_PROTOCOL gEmuThunkProtocol = {
--
2.16.1.windows.1
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [PATCH 08/12] EmulatorPkg/Win: Add SimpleFileSystem support
2018-08-23 9:52 [PATCH 00/12] Add WinHost support in EmulatorPkg Ruiyu Ni
` (6 preceding siblings ...)
2018-08-23 9:52 ` [PATCH 07/12] EmulatorPkg/Win: Add RTC support Ruiyu Ni
@ 2018-08-23 9:52 ` Ruiyu Ni
2018-08-23 9:52 ` [PATCH 09/12] EmulatorPkg/Win: Add BlockIo support Ruiyu Ni
` (4 subsequent siblings)
12 siblings, 0 replies; 14+ messages in thread
From: Ruiyu Ni @ 2018-08-23 9:52 UTC (permalink / raw)
To: edk2-devel; +Cc: Hao Wu, Andrew Fish
Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Ruiyu Ni <ruiyu.ni@intel.com>
Cc: Hao Wu <hao.a.wu@intel.com>
Cc: Andrew Fish <afish@intel.com>
---
EmulatorPkg/Win/Host/WinFileSystem.c | 2409 ++++++++++++++++++++++++++++++++++
EmulatorPkg/Win/Host/WinHost.c | 1 +
EmulatorPkg/Win/Host/WinHost.h | 5 +
EmulatorPkg/Win/Host/WinHost.inf | 9 +
4 files changed, 2424 insertions(+)
create mode 100644 EmulatorPkg/Win/Host/WinFileSystem.c
diff --git a/EmulatorPkg/Win/Host/WinFileSystem.c b/EmulatorPkg/Win/Host/WinFileSystem.c
new file mode 100644
index 0000000000..0d43ddaae3
--- /dev/null
+++ b/EmulatorPkg/Win/Host/WinFileSystem.c
@@ -0,0 +1,2409 @@
+/*++ @file
+ Support OS native directory access.
+
+Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+
+**/
+
+#include "WinHost.h"
+
+
+#define WIN_NT_SIMPLE_FILE_SYSTEM_PRIVATE_SIGNATURE SIGNATURE_32 ('N', 'T', 'f', 's')
+
+typedef struct {
+ UINTN Signature;
+ EMU_IO_THUNK_PROTOCOL *Thunk;
+ EFI_SIMPLE_FILE_SYSTEM_PROTOCOL SimpleFileSystem;
+ CHAR16 *FilePath;
+ CHAR16 *VolumeLabel;
+} WIN_NT_SIMPLE_FILE_SYSTEM_PRIVATE;
+
+#define WIN_NT_SIMPLE_FILE_SYSTEM_PRIVATE_DATA_FROM_THIS(a) \
+ CR (a, \
+ WIN_NT_SIMPLE_FILE_SYSTEM_PRIVATE, \
+ SimpleFileSystem, \
+ WIN_NT_SIMPLE_FILE_SYSTEM_PRIVATE_SIGNATURE \
+ )
+
+
+#define WIN_NT_EFI_FILE_PRIVATE_SIGNATURE SIGNATURE_32 ('l', 'o', 'f', 's')
+
+typedef struct {
+ UINTN Signature;
+ EMU_IO_THUNK_PROTOCOL *Thunk;
+ EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *SimpleFileSystem;
+ EFI_FILE_PROTOCOL EfiFile;
+ HANDLE LHandle;
+ HANDLE DirHandle;
+ BOOLEAN IsRootDirectory;
+ BOOLEAN IsDirectoryPath;
+ BOOLEAN IsOpenedByRead;
+ CHAR16 *FilePath;
+ WCHAR *FileName;
+ BOOLEAN IsValidFindBuf;
+ WIN32_FIND_DATA FindBuf;
+} WIN_NT_EFI_FILE_PRIVATE;
+
+#define WIN_NT_EFI_FILE_PRIVATE_DATA_FROM_THIS(a) \
+ CR (a, \
+ WIN_NT_EFI_FILE_PRIVATE, \
+ EfiFile, \
+ WIN_NT_EFI_FILE_PRIVATE_SIGNATURE \
+ )
+
+extern EFI_FILE_PROTOCOL gWinNtFileProtocol;
+extern EFI_SIMPLE_FILE_SYSTEM_PROTOCOL gWinNtFileSystemProtocol;
+
+EFI_STATUS
+WinNtFileGetInfo (
+ IN EFI_FILE_PROTOCOL *This,
+ IN EFI_GUID *InformationType,
+ IN OUT UINTN *BufferSize,
+ OUT VOID *Buffer
+ );
+
+EFI_STATUS
+WinNtFileSetInfo (
+ IN EFI_FILE_PROTOCOL *This,
+ IN EFI_GUID *InformationType,
+ IN UINTN BufferSize,
+ IN VOID *Buffer
+ );
+
+
+
+CHAR16 *
+EfiStrChr (
+ IN CHAR16 *Str,
+ IN CHAR16 Chr
+)
+/*++
+
+Routine Description:
+
+ Locate the first occurance of a character in a string.
+
+Arguments:
+
+ Str - Pointer to NULL terminated unicode string.
+ Chr - Character to locate.
+
+Returns:
+
+ If Str is NULL, then NULL is returned.
+ If Chr is not contained in Str, then NULL is returned.
+ If Chr is contained in Str, then a pointer to the first occurance of Chr in Str is returned.
+
+--*/
+{
+ if (Str == NULL) {
+ return Str;
+ }
+
+ while (*Str != '\0' && *Str != Chr) {
+ ++Str;
+ }
+
+ return (*Str == Chr) ? Str : NULL;
+}
+
+
+
+BOOLEAN
+IsZero (
+ IN VOID *Buffer,
+ IN UINTN Length
+ )
+{
+ if (Buffer == NULL || Length == 0) {
+ return FALSE;
+ }
+
+ if (*(UINT8 *) Buffer != 0) {
+ return FALSE;
+ }
+
+ if (Length > 1) {
+ if (!CompareMem (Buffer, (UINT8 *) Buffer + 1, Length - 1)) {
+ return FALSE;
+ }
+ }
+
+ return TRUE;
+}
+
+VOID
+CutPrefix (
+ IN CHAR16 *Str,
+ IN UINTN Count
+ )
+{
+ CHAR16 *Pointer;
+
+ if (StrLen (Str) < Count) {
+ ASSERT (0);
+ }
+
+ if (Count != 0) {
+ for (Pointer = Str; *(Pointer + Count); Pointer++) {
+ *Pointer = *(Pointer + Count);
+ }
+
+ *Pointer = *(Pointer + Count);
+ }
+}
+/**
+ Open the root directory on a volume.
+
+ @param This Protocol instance pointer.
+ @param Root Returns an Open file handle for the root directory
+
+ @retval EFI_SUCCESS The device was opened.
+ @retval EFI_UNSUPPORTED This volume does not support the file system.
+ @retval EFI_NO_MEDIA The device has no media.
+ @retval EFI_DEVICE_ERROR The device reported an error.
+ @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.
+ @retval EFI_ACCESS_DENIED The service denied access to the file.
+ @retval EFI_OUT_OF_RESOURCES The volume was not opened due to lack of resources.
+
+**/
+EFI_STATUS
+WinNtOpenVolume (
+ IN EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *This,
+ OUT EFI_FILE_PROTOCOL **Root
+ )
+{
+ EFI_STATUS Status;
+ WIN_NT_SIMPLE_FILE_SYSTEM_PRIVATE *Private;
+ WIN_NT_EFI_FILE_PRIVATE *PrivateFile;
+ CHAR16 *TempFileName;
+ UINTN Size;
+
+ if (This == NULL || Root == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Private = WIN_NT_SIMPLE_FILE_SYSTEM_PRIVATE_DATA_FROM_THIS (This);
+
+ PrivateFile = AllocatePool (sizeof (WIN_NT_EFI_FILE_PRIVATE));
+ if (PrivateFile == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto Done;
+ }
+
+ PrivateFile->FileName = AllocatePool (StrSize (Private->FilePath));
+ if (PrivateFile->FileName == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto Done;
+ }
+
+ PrivateFile->FilePath = AllocatePool (StrSize (Private->FilePath));
+ if (PrivateFile->FilePath == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto Done;
+ }
+
+ StrCpy (PrivateFile->FilePath, Private->FilePath);
+ StrCpy (PrivateFile->FileName, PrivateFile->FilePath);
+ PrivateFile->Signature = WIN_NT_EFI_FILE_PRIVATE_SIGNATURE;
+ PrivateFile->Thunk = Private->Thunk;
+ PrivateFile->SimpleFileSystem = This;
+ PrivateFile->IsRootDirectory = TRUE;
+ PrivateFile->IsDirectoryPath = TRUE;
+ PrivateFile->IsOpenedByRead = TRUE;
+ CopyMem (&PrivateFile->EfiFile, &gWinNtFileProtocol, sizeof (gWinNtFileProtocol));
+ PrivateFile->IsValidFindBuf = FALSE;
+
+ //
+ // Set DirHandle
+ //
+ PrivateFile->DirHandle = CreateFile (
+ PrivateFile->FilePath,
+ GENERIC_READ,
+ FILE_SHARE_READ | FILE_SHARE_WRITE,
+ NULL,
+ OPEN_EXISTING,
+ FILE_FLAG_BACKUP_SEMANTICS,
+ NULL
+ );
+
+ if (PrivateFile->DirHandle == INVALID_HANDLE_VALUE) {
+ Status = EFI_NOT_FOUND;
+ goto Done;
+ }
+
+ //
+ // Find the first file under it
+ //
+ Size = StrSize (PrivateFile->FilePath);
+ Size += StrSize (L"\\*");
+ TempFileName = AllocatePool (Size);
+ if (TempFileName == NULL) {
+ goto Done;
+ }
+ StrCpy (TempFileName, PrivateFile->FilePath);
+ StrCat (TempFileName, L"\\*");
+
+ PrivateFile->LHandle = FindFirstFile (TempFileName, &PrivateFile->FindBuf);
+ FreePool (TempFileName);
+
+ if (PrivateFile->LHandle == INVALID_HANDLE_VALUE) {
+ PrivateFile->IsValidFindBuf = FALSE;
+ } else {
+ PrivateFile->IsValidFindBuf = TRUE;
+ }
+ *Root = &PrivateFile->EfiFile;
+
+ Status = EFI_SUCCESS;
+
+Done:
+ if (EFI_ERROR (Status)) {
+ if (PrivateFile) {
+ if (PrivateFile->FileName) {
+ FreePool (PrivateFile->FileName);
+ }
+
+ if (PrivateFile->FilePath) {
+ FreePool (PrivateFile->FilePath);
+ }
+
+ FreePool (PrivateFile);
+ }
+ }
+
+ return Status;
+}
+
+/**
+ Count the number of Leading Dot in FileNameToken.
+
+ @param FileNameToken A string representing a token in the path name.
+
+ @return UINTN The number of leading dot in the name.
+
+**/
+UINTN
+CountLeadingDots (
+ IN CONST CHAR16 * FileNameToken
+)
+{
+ UINTN Num;
+
+ Num = 0;
+ while (*FileNameToken == L'.') {
+ Num++;
+ FileNameToken++;
+ }
+
+ return Num;
+}
+
+
+BOOLEAN
+IsFileNameTokenValid (
+ IN CONST CHAR16 * FileNameToken
+)
+{
+ UINTN Num;
+ if (StrStr (FileNameToken, L"/") != NULL) {
+ //
+ // No L'/' in file name.
+ //
+ return FALSE;
+ } else {
+ //
+ // If Token has all dot, the number should not exceed 2
+ //
+ Num = CountLeadingDots (FileNameToken);
+
+ if (Num == StrLen (FileNameToken)) {
+ //
+ // If the FileNameToken only contains a number of L'.'.
+ //
+ if (Num > 2) {
+ return FALSE;
+ }
+ }
+ }
+
+ return TRUE;
+}
+
+
+/**
+ Return the first string token found in the indirect pointer a String named by FileName.
+
+ On input, FileName is a indirect pointer pointing to a String.
+ On output, FileName is a updated to point to the next character after the first
+ found L"\" or NULL if there is no L"\" found.
+
+ @param FileName A indirect pointer pointing to a FileName.
+
+ @return Token The first string token found before a L"\".
+
+**/
+CHAR16 *
+GetNextFileNameToken (
+ IN OUT CONST CHAR16 ** FileName
+)
+{
+ CHAR16 *SlashPos;
+ CHAR16 *Token;
+ UINTN Offset;
+ ASSERT (**FileName != L'\\');
+ ASSERT (**FileName != L'\0');
+
+ SlashPos = StrStr (*FileName, L"\\");
+ if (SlashPos == NULL) {
+ Token = AllocateCopyPool (StrSize (*FileName), *FileName);
+ *FileName = NULL;
+ } else {
+ Offset = SlashPos - *FileName;
+ Token = AllocateZeroPool ((Offset + 1) * sizeof (CHAR16));
+ StrnCpy (Token, *FileName, Offset);
+ //
+ // Point *FileName to the next character after L'\'.
+ //
+ *FileName = *FileName + Offset + 1;
+ //
+ // If *FileName is an empty string, then set *FileName to NULL
+ //
+ if (**FileName == L'\0') {
+ *FileName = NULL;
+ }
+ }
+
+ return Token;
+}
+
+
+/**
+ Check if a FileName contains only Valid Characters.
+
+ If FileName contains only a single L'\', return TRUE.
+ If FileName contains two adjacent L'\', return FALSE.
+ If FileName conatins L'/' , return FALSE.
+ If FielName contains more than two dots seperated with other FileName characters
+ by L'\', return FALSE. For example, L'.\...\filename.txt' is invalid path name. But L'..TwoDots\filename.txt' is valid path name.
+
+ @param FileName The File Name String to check.
+
+ @return TRUE FileName only contains valid characters.
+ @return FALSE FileName contains at least one invalid character.
+
+**/
+
+BOOLEAN
+IsFileNameValid (
+ IN CONST CHAR16 *FileName
+ )
+{
+ CHAR16 *Token;
+ BOOLEAN Valid;
+
+ //
+ // If FileName is just L'\', then it is a valid pathname.
+ //
+ if (StrCmp (FileName, L"\\") == 0) {
+ return TRUE;
+ }
+ //
+ // We don't support two or more adjacent L'\'.
+ //
+ if (StrStr (FileName, L"\\\\") != NULL) {
+ return FALSE;
+ }
+
+ //
+ // Is FileName has a leading L"\", skip to next character.
+ //
+ if (FileName [0] == L'\\') {
+ FileName++;
+ }
+
+ do {
+ Token = GetNextFileNameToken (&FileName);
+ Valid = IsFileNameTokenValid (Token);
+ FreePool (Token);
+
+ if (!Valid)
+ return FALSE;
+ } while (FileName != NULL);
+
+ return TRUE;
+}
+
+
+/**
+ Opens a new file relative to the source file's location.
+
+ @param This The protocol instance pointer.
+ @param NewHandle Returns File Handle for FileName.
+ @param FileName Null terminated string. "\", ".", and ".." are supported.
+ @param OpenMode Open mode for file.
+ @param Attributes Only used for EFI_FILE_MODE_CREATE.
+
+ @retval EFI_SUCCESS The device was opened.
+ @retval EFI_NOT_FOUND The specified file could not be found on the device.
+ @retval EFI_NO_MEDIA The device has no media.
+ @retval EFI_MEDIA_CHANGED The media has changed.
+ @retval EFI_DEVICE_ERROR The device reported an error.
+ @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.
+ @retval EFI_ACCESS_DENIED The service denied access to the file.
+ @retval EFI_OUT_OF_RESOURCES The volume was not opened due to lack of resources.
+ @retval EFI_VOLUME_FULL The volume is full.
+
+**/
+EFI_STATUS
+WinNtFileOpen (
+ IN EFI_FILE_PROTOCOL *This,
+ OUT EFI_FILE_PROTOCOL **NewHandle,
+ IN CHAR16 *FileName,
+ IN UINT64 OpenMode,
+ IN UINT64 Attributes
+ )
+{
+ WIN_NT_EFI_FILE_PRIVATE *PrivateFile;
+ WIN_NT_EFI_FILE_PRIVATE *NewPrivateFile;
+ WIN_NT_SIMPLE_FILE_SYSTEM_PRIVATE *PrivateRoot;
+ EFI_STATUS Status;
+ CHAR16 *RealFileName;
+ CHAR16 *TempFileName;
+ CHAR16 *ParseFileName;
+ CHAR16 *GuardPointer;
+ CHAR16 TempChar;
+ DWORD LastError;
+ UINTN Count;
+ BOOLEAN LoopFinish;
+ UINTN InfoSize;
+ EFI_FILE_INFO *Info;
+ UINTN Size;
+
+
+ //
+ // Init local variables
+ //
+ PrivateFile = WIN_NT_EFI_FILE_PRIVATE_DATA_FROM_THIS (This);
+ PrivateRoot = WIN_NT_SIMPLE_FILE_SYSTEM_PRIVATE_DATA_FROM_THIS (PrivateFile->SimpleFileSystem);
+ NewPrivateFile = NULL;
+
+ //
+ // Allocate buffer for FileName as the passed in FileName may be read only
+ //
+ TempFileName = AllocatePool (StrSize (FileName));
+ if (TempFileName == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ StrCpy (TempFileName, FileName);
+ FileName = TempFileName;
+
+ if (FileName[StrLen (FileName) - 1] == L'\\') {
+ FileName[StrLen (FileName) - 1] = 0;
+ }
+
+ //
+ // If file name does not equal to "." or ".." and not trailed with "\..",
+ // then we trim the leading/trailing blanks and trailing dots
+ //
+ if (StrCmp (FileName, L".") != 0 && StrCmp (FileName, L"..") != 0 &&
+ ((StrLen (FileName) >= 3) ? (StrCmp (&FileName[StrLen (FileName) - 3], L"\\..") != 0) : TRUE)) {
+ //
+ // Trim leading blanks
+ //
+ Count = 0;
+ for (TempFileName = FileName;
+ *TempFileName != 0 && *TempFileName == L' ';
+ TempFileName++) {
+ Count++;
+ }
+ CutPrefix (FileName, Count);
+ //
+ // Trim trailing blanks
+ //
+ for (TempFileName = FileName + StrLen (FileName) - 1;
+ TempFileName >= FileName && (*TempFileName == L' ');
+ TempFileName--) {
+ ;
+ }
+ *(TempFileName + 1) = 0;
+ }
+
+ //
+ // Attempt to open the file
+ //
+ NewPrivateFile = AllocatePool (sizeof (WIN_NT_EFI_FILE_PRIVATE));
+ if (NewPrivateFile == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto Done;
+ }
+
+ CopyMem (NewPrivateFile, PrivateFile, sizeof (WIN_NT_EFI_FILE_PRIVATE));
+
+ NewPrivateFile->FilePath = AllocatePool (StrSize (PrivateFile->FileName));
+ if (NewPrivateFile->FilePath == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto Done;
+ }
+
+ if (PrivateFile->IsDirectoryPath) {
+ StrCpy (NewPrivateFile->FilePath, PrivateFile->FileName);
+ } else {
+ StrCpy (NewPrivateFile->FilePath, PrivateFile->FilePath);
+ }
+
+ Size = StrSize (NewPrivateFile->FilePath);
+ Size += StrSize (L"\\");
+ Size += StrSize (FileName);
+ NewPrivateFile->FileName = AllocatePool (Size);
+ if (NewPrivateFile->FileName == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto Done;
+ }
+
+ if (*FileName == L'\\') {
+ StrCpy (NewPrivateFile->FileName, PrivateRoot->FilePath);
+ StrCat (NewPrivateFile->FileName, L"\\");
+ StrCat (NewPrivateFile->FileName, FileName + 1);
+ } else {
+ StrCpy (NewPrivateFile->FileName, NewPrivateFile->FilePath);
+ if (StrCmp (FileName, L"") != 0) {
+ //
+ // In case the filename becomes empty, especially after trimming dots and blanks
+ //
+ StrCat (NewPrivateFile->FileName, L"\\");
+ StrCat (NewPrivateFile->FileName, FileName);
+ }
+ }
+
+ if (!IsFileNameValid (NewPrivateFile->FileName)) {
+ Status = EFI_NOT_FOUND;
+ goto Done;
+ }
+
+ //
+ // Get rid of . and .., except leading . or ..
+ //
+
+ //
+ // GuardPointer protect simplefilesystem root path not be destroyed
+ //
+ GuardPointer = NewPrivateFile->FileName + StrLen (PrivateRoot->FilePath);
+
+ LoopFinish = FALSE;
+
+ while (!LoopFinish) {
+
+ LoopFinish = TRUE;
+
+ for (ParseFileName = GuardPointer; *ParseFileName; ParseFileName++) {
+ if (*ParseFileName == L'.' &&
+ (*(ParseFileName + 1) == 0 || *(ParseFileName + 1) == L'\\') &&
+ *(ParseFileName - 1) == L'\\'
+ ) {
+
+ //
+ // cut \.
+ //
+ CutPrefix (ParseFileName - 1, 2);
+ LoopFinish = FALSE;
+ break;
+ }
+
+ if (*ParseFileName == L'.' &&
+ *(ParseFileName + 1) == L'.' &&
+ (*(ParseFileName + 2) == 0 || *(ParseFileName + 2) == L'\\') &&
+ *(ParseFileName - 1) == L'\\'
+ ) {
+
+ ParseFileName--;
+ Count = 3;
+
+ while (ParseFileName != GuardPointer) {
+ ParseFileName--;
+ Count++;
+ if (*ParseFileName == L'\\') {
+ break;
+ }
+ }
+
+ //
+ // cut \.. and its left directory
+ //
+ CutPrefix (ParseFileName, Count);
+ LoopFinish = FALSE;
+ break;
+ }
+ }
+ }
+
+ RealFileName = NewPrivateFile->FileName;
+ while (EfiStrChr (RealFileName, L'\\') != NULL) {
+ RealFileName = EfiStrChr (RealFileName, L'\\') + 1;
+ }
+
+ TempChar = 0;
+ if (RealFileName != NewPrivateFile->FileName) {
+ TempChar = *(RealFileName - 1);
+ *(RealFileName - 1) = 0;
+ }
+
+ FreePool (NewPrivateFile->FilePath);
+ NewPrivateFile->FilePath = NULL;
+ NewPrivateFile->FilePath = AllocatePool (StrSize (NewPrivateFile->FileName));
+ if (NewPrivateFile->FilePath == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto Done;
+ }
+
+ StrCpy (NewPrivateFile->FilePath, NewPrivateFile->FileName);
+ if (TempChar != 0) {
+ *(RealFileName - 1) = TempChar;
+ }
+
+ NewPrivateFile->IsRootDirectory = FALSE;
+
+ //
+ // Test whether file or directory
+ //
+ if (OpenMode & EFI_FILE_MODE_CREATE) {
+ if (Attributes & EFI_FILE_DIRECTORY) {
+ NewPrivateFile->IsDirectoryPath = TRUE;
+ } else {
+ NewPrivateFile->IsDirectoryPath = FALSE;
+ }
+ } else {
+ NewPrivateFile->LHandle = CreateFile (
+ NewPrivateFile->FileName,
+ GENERIC_READ,
+ FILE_SHARE_READ | FILE_SHARE_WRITE,
+ NULL,
+ OPEN_EXISTING,
+ 0,
+ NULL
+ );
+
+ if (NewPrivateFile->LHandle != INVALID_HANDLE_VALUE) {
+ NewPrivateFile->IsDirectoryPath = FALSE;
+ CloseHandle (NewPrivateFile->LHandle);
+ } else {
+ NewPrivateFile->IsDirectoryPath = TRUE;
+ }
+
+ NewPrivateFile->LHandle = INVALID_HANDLE_VALUE;
+ }
+
+ if (OpenMode & EFI_FILE_MODE_WRITE) {
+ NewPrivateFile->IsOpenedByRead = FALSE;
+ } else {
+ NewPrivateFile->IsOpenedByRead = TRUE;
+ }
+
+ Status = EFI_SUCCESS;
+
+ //
+ // deal with directory
+ //
+ if (NewPrivateFile->IsDirectoryPath) {
+
+ Size = StrSize (NewPrivateFile->FileName);
+ Size += StrSize (L"\\*");
+ TempFileName = AllocatePool (Size);
+ if (TempFileName == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto Done;
+ }
+
+ StrCpy (TempFileName, NewPrivateFile->FileName);
+
+ if ((OpenMode & EFI_FILE_MODE_CREATE)) {
+ //
+ // Create a directory
+ //
+ if (!CreateDirectory (TempFileName, NULL)) {
+
+ LastError = GetLastError ();
+ if (LastError != ERROR_ALREADY_EXISTS) {
+ FreePool (TempFileName);
+ Status = EFI_ACCESS_DENIED;
+ goto Done;
+ }
+ }
+ }
+
+ NewPrivateFile->DirHandle = CreateFile (
+ TempFileName,
+ NewPrivateFile->IsOpenedByRead ? GENERIC_READ : (GENERIC_READ | GENERIC_WRITE),
+ FILE_SHARE_READ | FILE_SHARE_WRITE,
+ NULL,
+ OPEN_EXISTING,
+ FILE_FLAG_BACKUP_SEMANTICS,
+ NULL
+ );
+
+ if (NewPrivateFile->DirHandle == INVALID_HANDLE_VALUE) {
+
+ NewPrivateFile->DirHandle = CreateFile (
+ TempFileName,
+ GENERIC_READ,
+ FILE_SHARE_READ | FILE_SHARE_WRITE,
+ NULL,
+ OPEN_EXISTING,
+ FILE_FLAG_BACKUP_SEMANTICS,
+ NULL
+ );
+
+ if (NewPrivateFile->DirHandle != INVALID_HANDLE_VALUE) {
+ CloseHandle (NewPrivateFile->DirHandle);
+ NewPrivateFile->DirHandle = INVALID_HANDLE_VALUE;
+ Status = EFI_ACCESS_DENIED;
+ } else {
+ Status = EFI_NOT_FOUND;
+ }
+
+ FreePool (TempFileName);
+ goto Done;
+ }
+
+ //
+ // Find the first file under it
+ //
+ StrCat (TempFileName, L"\\*");
+ NewPrivateFile->LHandle = FindFirstFile (TempFileName, &NewPrivateFile->FindBuf);
+ FreePool (TempFileName);
+
+ if (NewPrivateFile->LHandle == INVALID_HANDLE_VALUE) {
+ NewPrivateFile->IsValidFindBuf = FALSE;
+ } else {
+ NewPrivateFile->IsValidFindBuf = TRUE;
+ }
+ } else {
+ //
+ // deal with file
+ //
+ if (!NewPrivateFile->IsOpenedByRead) {
+ NewPrivateFile->LHandle = CreateFile (
+ NewPrivateFile->FileName,
+ GENERIC_READ | GENERIC_WRITE,
+ FILE_SHARE_READ | FILE_SHARE_WRITE,
+ NULL,
+ (OpenMode & EFI_FILE_MODE_CREATE) ? OPEN_ALWAYS : OPEN_EXISTING,
+ 0,
+ NULL
+ );
+
+ if (NewPrivateFile->LHandle == INVALID_HANDLE_VALUE) {
+ NewPrivateFile->LHandle = CreateFile (
+ NewPrivateFile->FileName,
+ GENERIC_READ,
+ FILE_SHARE_READ | FILE_SHARE_WRITE,
+ NULL,
+ OPEN_EXISTING,
+ 0,
+ NULL
+ );
+
+ if (NewPrivateFile->LHandle == INVALID_HANDLE_VALUE) {
+ Status = EFI_NOT_FOUND;
+ } else {
+ Status = EFI_ACCESS_DENIED;
+ CloseHandle (NewPrivateFile->LHandle);
+ NewPrivateFile->LHandle = INVALID_HANDLE_VALUE;
+ }
+ }
+ } else {
+ NewPrivateFile->LHandle = CreateFile (
+ NewPrivateFile->FileName,
+ GENERIC_READ,
+ FILE_SHARE_READ | FILE_SHARE_WRITE,
+ NULL,
+ OPEN_EXISTING,
+ 0,
+ NULL
+ );
+
+ if (NewPrivateFile->LHandle == INVALID_HANDLE_VALUE) {
+ Status = EFI_NOT_FOUND;
+ }
+ }
+ }
+
+ if ((OpenMode & EFI_FILE_MODE_CREATE) && Status == EFI_SUCCESS) {
+ //
+ // Set the attribute
+ //
+ InfoSize = 0;
+ Info = NULL;
+
+ Status = WinNtFileGetInfo (&NewPrivateFile->EfiFile, &gEfiFileInfoGuid, &InfoSize, Info);
+
+ if (Status != EFI_BUFFER_TOO_SMALL) {
+ Status = EFI_DEVICE_ERROR;
+ goto Done;
+ }
+
+ Info = AllocatePool (InfoSize);
+ if (Info == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto Done;
+ }
+
+ Status = WinNtFileGetInfo (&NewPrivateFile->EfiFile, &gEfiFileInfoGuid, &InfoSize, Info);
+
+ if (EFI_ERROR (Status)) {
+ FreePool (Info);
+ goto Done;
+ }
+
+ Info->Attribute = Attributes;
+
+ WinNtFileSetInfo (&NewPrivateFile->EfiFile, &gEfiFileInfoGuid, InfoSize, Info);
+ FreePool (Info);
+ }
+
+Done:
+ FreePool (FileName);
+
+ if (EFI_ERROR (Status)) {
+ if (NewPrivateFile) {
+ if (NewPrivateFile->FileName) {
+ FreePool (NewPrivateFile->FileName);
+ }
+
+ if (NewPrivateFile->FilePath) {
+ FreePool (NewPrivateFile->FilePath);
+ }
+
+ FreePool (NewPrivateFile);
+ }
+ } else {
+ *NewHandle = &NewPrivateFile->EfiFile;
+ if (StrCmp (NewPrivateFile->FileName, PrivateRoot->FilePath) == 0) {
+ NewPrivateFile->IsRootDirectory = TRUE;
+ }
+ }
+
+ return Status;
+}
+
+
+
+/**
+ Close the file handle
+
+ @param This Protocol instance pointer.
+
+ @retval EFI_SUCCESS The device was opened.
+
+**/
+EFI_STATUS
+WinNtFileClose (
+ IN EFI_FILE_PROTOCOL *This
+ )
+{
+ WIN_NT_EFI_FILE_PRIVATE *PrivateFile;
+
+ PrivateFile = WIN_NT_EFI_FILE_PRIVATE_DATA_FROM_THIS (This);
+
+ if (PrivateFile->LHandle != INVALID_HANDLE_VALUE) {
+ if (PrivateFile->IsDirectoryPath) {
+ FindClose (PrivateFile->LHandle);
+ } else {
+ CloseHandle (PrivateFile->LHandle);
+ }
+
+ PrivateFile->LHandle = INVALID_HANDLE_VALUE;
+ }
+
+ if (PrivateFile->IsDirectoryPath && PrivateFile->DirHandle != INVALID_HANDLE_VALUE) {
+ CloseHandle (PrivateFile->DirHandle);
+ PrivateFile->DirHandle = INVALID_HANDLE_VALUE;
+ }
+
+ if (PrivateFile->FileName) {
+ FreePool (PrivateFile->FileName);
+ }
+
+ if (PrivateFile->FilePath) {
+ FreePool (PrivateFile->FilePath);
+ }
+
+ FreePool (PrivateFile);
+
+ return EFI_SUCCESS;
+
+}
+
+
+/**
+ Close and delete the file handle.
+
+ @param This Protocol instance pointer.
+
+ @retval EFI_SUCCESS The device was opened.
+ @retval EFI_WARN_DELETE_FAILURE The handle was closed but the file was not deleted.
+
+**/
+EFI_STATUS
+WinNtFileDelete (
+ IN EFI_FILE_PROTOCOL *This
+ )
+{
+ EFI_STATUS Status;
+ WIN_NT_EFI_FILE_PRIVATE *PrivateFile;
+
+ PrivateFile = WIN_NT_EFI_FILE_PRIVATE_DATA_FROM_THIS (This);
+
+ Status = EFI_WARN_DELETE_FAILURE;
+
+ if (PrivateFile->IsDirectoryPath) {
+ if (PrivateFile->LHandle != INVALID_HANDLE_VALUE) {
+ FindClose (PrivateFile->LHandle);
+ }
+
+ if (PrivateFile->DirHandle != INVALID_HANDLE_VALUE) {
+ CloseHandle (PrivateFile->DirHandle);
+ PrivateFile->DirHandle = INVALID_HANDLE_VALUE;
+ }
+
+ if (RemoveDirectory (PrivateFile->FileName)) {
+ Status = EFI_SUCCESS;
+ }
+ } else {
+ CloseHandle (PrivateFile->LHandle);
+ PrivateFile->LHandle = INVALID_HANDLE_VALUE;
+
+ if (!PrivateFile->IsOpenedByRead) {
+ if (DeleteFile (PrivateFile->FileName)) {
+ Status = EFI_SUCCESS;
+ }
+ }
+ }
+
+ FreePool (PrivateFile->FileName);
+ FreePool (PrivateFile->FilePath);
+ FreePool (PrivateFile);
+
+ return Status;
+}
+
+VOID
+WinNtSystemTimeToEfiTime (
+ IN SYSTEMTIME *SystemTime,
+ IN TIME_ZONE_INFORMATION *TimeZone,
+ OUT EFI_TIME *Time
+)
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ SystemTime - TODO: add argument description
+ TimeZone - TODO: add argument description
+ Time - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+{
+ Time->Year = (UINT16)SystemTime->wYear;
+ Time->Month = (UINT8)SystemTime->wMonth;
+ Time->Day = (UINT8)SystemTime->wDay;
+ Time->Hour = (UINT8)SystemTime->wHour;
+ Time->Minute = (UINT8)SystemTime->wMinute;
+ Time->Second = (UINT8)SystemTime->wSecond;
+ Time->Nanosecond = (UINT32)SystemTime->wMilliseconds * 1000000;
+ Time->TimeZone = (INT16)TimeZone->Bias;
+
+ if (TimeZone->StandardDate.wMonth) {
+ Time->Daylight = EFI_TIME_ADJUST_DAYLIGHT;
+ }
+}
+
+/**
+ Convert the FileTime to EfiTime.
+
+ @param PrivateFile Pointer to WIN_NT_EFI_FILE_PRIVATE.
+ @param TimeZone Pointer to the current time zone.
+ @param FileTime Pointer to file time.
+ @param EfiTime Pointer to EFI time.
+**/
+VOID
+WinNtFileTimeToEfiTime (
+ IN CONST WIN_NT_EFI_FILE_PRIVATE *PrivateFile,
+ IN TIME_ZONE_INFORMATION *TimeZone,
+ IN CONST FILETIME *FileTime,
+ OUT EFI_TIME *EfiTime
+)
+{
+ FILETIME TempFileTime;
+ SYSTEMTIME SystemTime;
+
+ FileTimeToLocalFileTime (FileTime, &TempFileTime);
+ FileTimeToSystemTime (&TempFileTime, &SystemTime);
+ WinNtSystemTimeToEfiTime (&SystemTime, TimeZone, EfiTime);
+}
+
+
+/**
+ Read data from the file.
+
+ @param This Protocol instance pointer.
+ @param BufferSize On input size of buffer, on output amount of data in buffer.
+ @param Buffer The buffer in which data is read.
+
+ @retval EFI_SUCCESS Data was read.
+ @retval EFI_NO_MEDIA The device has no media.
+ @retval EFI_DEVICE_ERROR The device reported an error.
+ @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.
+ @retval EFI_BUFFER_TO_SMALL BufferSize is too small. BufferSize contains required size.
+
+**/
+EFI_STATUS
+WinNtFileRead (
+ IN EFI_FILE_PROTOCOL *This,
+ IN OUT UINTN *BufferSize,
+ OUT VOID *Buffer
+ )
+{
+ WIN_NT_EFI_FILE_PRIVATE *PrivateFile;
+ EFI_STATUS Status;
+ UINTN Size;
+ UINTN NameSize;
+ UINTN ResultSize;
+ UINTN Index;
+ EFI_FILE_INFO *Info;
+ WCHAR *pw;
+ TIME_ZONE_INFORMATION TimeZone;
+ EFI_FILE_INFO *FileInfo;
+ UINT64 Pos;
+ UINT64 FileSize;
+ UINTN FileInfoSize;
+
+ PrivateFile = WIN_NT_EFI_FILE_PRIVATE_DATA_FROM_THIS (This);
+
+ if (PrivateFile->LHandle == INVALID_HANDLE_VALUE) {
+ Status = EFI_DEVICE_ERROR;
+ goto Done;
+ }
+
+ if (!PrivateFile->IsDirectoryPath) {
+
+ if (This->GetPosition (This, &Pos) != EFI_SUCCESS) {
+ Status = EFI_DEVICE_ERROR;
+ goto Done;
+ }
+
+ FileInfoSize = SIZE_OF_EFI_FILE_SYSTEM_INFO;
+ FileInfo = AllocatePool (FileInfoSize);
+
+ Status = This->GetInfo (
+ This,
+ &gEfiFileInfoGuid,
+ &FileInfoSize,
+ FileInfo
+ );
+
+ if (Status == EFI_BUFFER_TOO_SMALL) {
+ FreePool (FileInfo);
+ FileInfo = AllocatePool (FileInfoSize);
+ Status = This->GetInfo (
+ This,
+ &gEfiFileInfoGuid,
+ &FileInfoSize,
+ FileInfo
+ );
+ }
+
+ if (EFI_ERROR (Status)) {
+ Status = EFI_DEVICE_ERROR;
+ goto Done;
+ }
+
+ FileSize = FileInfo->FileSize;
+
+ FreePool (FileInfo);
+
+ if (Pos >= FileSize) {
+ *BufferSize = 0;
+ if (Pos == FileSize) {
+ Status = EFI_SUCCESS;
+ goto Done;
+ } else {
+ Status = EFI_DEVICE_ERROR;
+ goto Done;
+ }
+ }
+
+ Status = ReadFile (
+ PrivateFile->LHandle,
+ Buffer,
+ (DWORD)*BufferSize,
+ (LPDWORD)BufferSize,
+ NULL
+ ) ? EFI_SUCCESS : EFI_DEVICE_ERROR;
+ goto Done;
+ }
+
+ //
+ // Read on a directory. Perform a find next
+ //
+ if (!PrivateFile->IsValidFindBuf) {
+ *BufferSize = 0;
+ Status = EFI_SUCCESS;
+ goto Done;
+ }
+
+ Size = SIZE_OF_EFI_FILE_INFO;
+
+ NameSize = StrSize (PrivateFile->FindBuf.cFileName);
+
+ ResultSize = Size + NameSize;
+
+ Status = EFI_BUFFER_TOO_SMALL;
+
+ if (*BufferSize >= ResultSize) {
+ Status = EFI_SUCCESS;
+
+ Info = Buffer;
+ ZeroMem (Info, ResultSize);
+
+ Info->Size = ResultSize;
+
+ GetTimeZoneInformation (&TimeZone);
+ WinNtFileTimeToEfiTime (PrivateFile, &TimeZone, &PrivateFile->FindBuf.ftCreationTime, &Info->CreateTime);
+ WinNtFileTimeToEfiTime (PrivateFile, &TimeZone, &PrivateFile->FindBuf.ftLastAccessTime, &Info->LastAccessTime);
+ WinNtFileTimeToEfiTime (PrivateFile, &TimeZone, &PrivateFile->FindBuf.ftLastWriteTime, &Info->ModificationTime);
+
+ Info->FileSize = PrivateFile->FindBuf.nFileSizeLow;
+
+ Info->PhysicalSize = PrivateFile->FindBuf.nFileSizeLow;
+
+ if (PrivateFile->FindBuf.dwFileAttributes & FILE_ATTRIBUTE_ARCHIVE) {
+ Info->Attribute |= EFI_FILE_ARCHIVE;
+ }
+
+ if (PrivateFile->FindBuf.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN) {
+ Info->Attribute |= EFI_FILE_HIDDEN;
+ }
+
+ if (PrivateFile->FindBuf.dwFileAttributes & FILE_ATTRIBUTE_SYSTEM) {
+ Info->Attribute |= EFI_FILE_SYSTEM;
+ }
+
+ if (PrivateFile->FindBuf.dwFileAttributes & FILE_ATTRIBUTE_READONLY) {
+ Info->Attribute |= EFI_FILE_READ_ONLY;
+ }
+
+ if (PrivateFile->FindBuf.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
+ Info->Attribute |= EFI_FILE_DIRECTORY;
+ }
+
+ NameSize = NameSize / sizeof (WCHAR);
+
+ pw = (WCHAR *)(((CHAR8 *)Buffer) + Size);
+
+ for (Index = 0; Index < NameSize; Index++) {
+ pw[Index] = PrivateFile->FindBuf.cFileName[Index];
+ }
+
+ if (FindNextFile (PrivateFile->LHandle, &PrivateFile->FindBuf)) {
+ PrivateFile->IsValidFindBuf = TRUE;
+ } else {
+ PrivateFile->IsValidFindBuf = FALSE;
+ }
+ }
+
+ *BufferSize = ResultSize;
+
+Done:
+ return Status;
+}
+
+
+
+/**
+ Write data to a file.
+
+ @param This Protocol instance pointer.
+ @param BufferSize On input size of buffer, on output amount of data in buffer.
+ @param Buffer The buffer in which data to write.
+
+ @retval EFI_SUCCESS Data was written.
+ @retval EFI_UNSUPPORTED Writes to Open directory are not supported.
+ @retval EFI_NO_MEDIA The device has no media.
+ @retval EFI_DEVICE_ERROR The device reported an error.
+ @retval EFI_DEVICE_ERROR An attempt was made to write to a deleted file.
+ @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.
+ @retval EFI_WRITE_PROTECTED The device is write protected.
+ @retval EFI_ACCESS_DENIED The file was open for read only.
+ @retval EFI_VOLUME_FULL The volume is full.
+
+**/
+EFI_STATUS
+WinNtFileWrite (
+ IN EFI_FILE_PROTOCOL *This,
+ IN OUT UINTN *BufferSize,
+ IN VOID *Buffer
+ )
+{
+ WIN_NT_EFI_FILE_PRIVATE *PrivateFile;
+ EFI_STATUS Status;
+
+ PrivateFile = WIN_NT_EFI_FILE_PRIVATE_DATA_FROM_THIS (This);
+
+ if (PrivateFile->LHandle == INVALID_HANDLE_VALUE) {
+ Status = EFI_DEVICE_ERROR;
+ goto Done;
+ }
+
+ if (PrivateFile->IsDirectoryPath) {
+ Status = EFI_UNSUPPORTED;
+ goto Done;
+ }
+
+ if (PrivateFile->IsOpenedByRead) {
+ Status = EFI_ACCESS_DENIED;
+ goto Done;
+ }
+
+ Status = WriteFile (
+ PrivateFile->LHandle,
+ Buffer,
+ (DWORD)*BufferSize,
+ (LPDWORD)BufferSize,
+ NULL
+ ) ? EFI_SUCCESS : EFI_DEVICE_ERROR;
+
+Done:
+ return Status;
+
+ //
+ // bugbug: need to access windows error reporting
+ //
+}
+
+
+
+/**
+ Set a files current position
+
+ @param This Protocol instance pointer.
+ @param Position Byte position from the start of the file.
+
+ @retval EFI_SUCCESS Data was written.
+ @retval EFI_UNSUPPORTED Seek request for non-zero is not valid on open.
+
+**/
+EFI_STATUS
+WinNtFileSetPossition (
+ IN EFI_FILE_PROTOCOL *This,
+ IN UINT64 Position
+ )
+{
+ EFI_STATUS Status;
+ WIN_NT_EFI_FILE_PRIVATE *PrivateFile;
+ UINT32 PosLow;
+ UINT32 PosHigh;
+ CHAR16 *FileName;
+ UINTN Size;
+
+ PrivateFile = WIN_NT_EFI_FILE_PRIVATE_DATA_FROM_THIS (This);
+
+ if (PrivateFile->IsDirectoryPath) {
+ if (Position != 0) {
+ Status = EFI_UNSUPPORTED;
+ goto Done;
+ }
+
+ Size = StrSize (PrivateFile->FileName);
+ Size += StrSize (L"\\*");
+ FileName = AllocatePool (Size);
+ if (FileName == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto Done;
+ }
+
+ StrCpy (FileName, PrivateFile->FileName);
+ StrCat (FileName, L"\\*");
+
+ if (PrivateFile->LHandle != INVALID_HANDLE_VALUE) {
+ FindClose (PrivateFile->LHandle);
+ }
+
+ PrivateFile->LHandle = FindFirstFile (FileName, &PrivateFile->FindBuf);
+
+ if (PrivateFile->LHandle == INVALID_HANDLE_VALUE) {
+ PrivateFile->IsValidFindBuf = FALSE;
+ } else {
+ PrivateFile->IsValidFindBuf = TRUE;
+ }
+
+ FreePool (FileName);
+
+ Status = (PrivateFile->LHandle == INVALID_HANDLE_VALUE) ? EFI_DEVICE_ERROR : EFI_SUCCESS;
+ } else {
+ if (Position == (UINT64)-1) {
+ PosLow = SetFilePointer (PrivateFile->LHandle, (ULONG)0, NULL, FILE_END);
+ } else {
+ PosHigh = (UINT32)RShiftU64 (Position, 32);
+
+ PosLow = SetFilePointer (PrivateFile->LHandle, (ULONG)Position, (PLONG)&PosHigh, FILE_BEGIN);
+ }
+
+ Status = (PosLow == 0xFFFFFFFF) ? EFI_DEVICE_ERROR : EFI_SUCCESS;
+ }
+
+Done:
+ return Status;
+}
+
+
+
+/**
+ Get a file's current position
+
+ @param This Protocol instance pointer.
+ @param Position Byte position from the start of the file.
+
+ @retval EFI_SUCCESS Data was written.
+ @retval EFI_UNSUPPORTED Seek request for non-zero is not valid on open..
+
+**/
+EFI_STATUS
+WinNtFileGetPossition (
+ IN EFI_FILE_PROTOCOL *This,
+ OUT UINT64 *Position
+ )
+{
+ EFI_STATUS Status;
+ WIN_NT_EFI_FILE_PRIVATE *PrivateFile;
+ INT32 PositionHigh;
+ UINT64 PosHigh64;
+
+ PrivateFile = WIN_NT_EFI_FILE_PRIVATE_DATA_FROM_THIS (This);
+
+ PositionHigh = 0;
+ PosHigh64 = 0;
+
+ if (PrivateFile->IsDirectoryPath) {
+
+ Status = EFI_UNSUPPORTED;
+ goto Done;
+
+ } else {
+
+ PositionHigh = 0;
+ *Position = SetFilePointer (
+ PrivateFile->LHandle,
+ 0,
+ (PLONG)&PositionHigh,
+ FILE_CURRENT
+ );
+
+ Status = *Position == 0xffffffff ? EFI_DEVICE_ERROR : EFI_SUCCESS;
+ if (EFI_ERROR (Status)) {
+ goto Done;
+ }
+
+ PosHigh64 = PositionHigh;
+ *Position += LShiftU64 (PosHigh64, 32);
+ }
+
+Done:
+ return Status;
+}
+
+
+EFI_STATUS
+WinNtSimpleFileSystemFileInfo (
+ IN WIN_NT_EFI_FILE_PRIVATE *PrivateFile,
+ IN OUT UINTN *BufferSize,
+ OUT VOID *Buffer
+)
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ PrivateFile - TODO: add argument description
+ BufferSize - TODO: add argument description
+ Buffer - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+{
+ EFI_STATUS Status;
+ UINTN Size;
+ UINTN NameSize;
+ UINTN ResultSize;
+ EFI_FILE_INFO *Info;
+ BY_HANDLE_FILE_INFORMATION FileInfo;
+ CHAR16 *RealFileName;
+ CHAR16 *TempPointer;
+ TIME_ZONE_INFORMATION TimeZone;
+
+ Size = SIZE_OF_EFI_FILE_INFO;
+
+ RealFileName = PrivateFile->FileName;
+ TempPointer = RealFileName;
+ while (*TempPointer) {
+ if (*TempPointer == '\\') {
+ RealFileName = TempPointer + 1;
+ }
+
+ TempPointer++;
+ }
+ NameSize = StrSize (RealFileName);
+
+ ResultSize = Size + NameSize;
+
+ Status = EFI_BUFFER_TOO_SMALL;
+ if (*BufferSize >= ResultSize) {
+ Status = EFI_SUCCESS;
+
+ Info = Buffer;
+ ZeroMem (Info, ResultSize);
+
+ Info->Size = ResultSize;
+ GetFileInformationByHandle (
+ PrivateFile->IsDirectoryPath ? PrivateFile->DirHandle : PrivateFile->LHandle,
+ &FileInfo
+ );
+ Info->FileSize = FileInfo.nFileSizeLow;
+ Info->PhysicalSize = Info->FileSize;
+
+ GetTimeZoneInformation (&TimeZone);
+ WinNtFileTimeToEfiTime (PrivateFile, &TimeZone, &FileInfo.ftCreationTime, &Info->CreateTime);
+ WinNtFileTimeToEfiTime (PrivateFile, &TimeZone, &FileInfo.ftLastAccessTime, &Info->LastAccessTime);
+ WinNtFileTimeToEfiTime (PrivateFile, &TimeZone, &FileInfo.ftLastWriteTime, &Info->ModificationTime);
+
+ if (FileInfo.dwFileAttributes & FILE_ATTRIBUTE_ARCHIVE) {
+ Info->Attribute |= EFI_FILE_ARCHIVE;
+ }
+
+ if (FileInfo.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN) {
+ Info->Attribute |= EFI_FILE_HIDDEN;
+ }
+
+ if (FileInfo.dwFileAttributes & FILE_ATTRIBUTE_READONLY) {
+ Info->Attribute |= EFI_FILE_READ_ONLY;
+ }
+
+ if (FileInfo.dwFileAttributes & FILE_ATTRIBUTE_SYSTEM) {
+ Info->Attribute |= EFI_FILE_SYSTEM;
+ }
+
+ if (FileInfo.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
+ Info->Attribute |= EFI_FILE_DIRECTORY;
+ }
+
+ if (PrivateFile->IsDirectoryPath) {
+ Info->Attribute |= EFI_FILE_DIRECTORY;
+ }
+
+ if (PrivateFile->IsRootDirectory) {
+ *((CHAR8 *)Buffer + Size) = 0;
+ } else {
+ CopyMem ((CHAR8 *)Buffer + Size, RealFileName, NameSize);
+ }
+ }
+
+ *BufferSize = ResultSize;
+ return Status;
+}
+
+/**
+ Get information about a file.
+
+ @param This Protocol instance pointer.
+ @param InformationType Type of information to return in Buffer.
+ @param BufferSize On input size of buffer, on output amount of data in buffer.
+ @param Buffer The buffer to return data.
+
+ @retval EFI_SUCCESS Data was returned.
+ @retval EFI_UNSUPPORTED InformationType is not supported.
+ @retval EFI_NO_MEDIA The device has no media.
+ @retval EFI_DEVICE_ERROR The device reported an error.
+ @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.
+ @retval EFI_WRITE_PROTECTED The device is write protected.
+ @retval EFI_ACCESS_DENIED The file was open for read only.
+ @retval EFI_BUFFER_TOO_SMALL Buffer was too small; required size returned in BufferSize.
+
+**/
+EFI_STATUS
+WinNtFileGetInfo (
+ IN EFI_FILE_PROTOCOL *This,
+ IN EFI_GUID *InformationType,
+ IN OUT UINTN *BufferSize,
+ OUT VOID *Buffer
+ )
+{
+ EFI_STATUS Status;
+ WIN_NT_EFI_FILE_PRIVATE *PrivateFile;
+ EFI_FILE_SYSTEM_INFO *FileSystemInfoBuffer;
+ UINT32 SectorsPerCluster;
+ UINT32 BytesPerSector;
+ UINT32 FreeClusters;
+ UINT32 TotalClusters;
+ UINT32 BytesPerCluster;
+ CHAR16 *DriveName;
+ BOOLEAN DriveNameFound;
+ BOOL NtStatus;
+ UINTN Index;
+ WIN_NT_SIMPLE_FILE_SYSTEM_PRIVATE *PrivateRoot;
+
+ if (This == NULL || InformationType == NULL || BufferSize == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ PrivateFile = WIN_NT_EFI_FILE_PRIVATE_DATA_FROM_THIS (This);
+ PrivateRoot = WIN_NT_SIMPLE_FILE_SYSTEM_PRIVATE_DATA_FROM_THIS (PrivateFile->SimpleFileSystem);
+
+ Status = EFI_UNSUPPORTED;
+
+ if (CompareGuid (InformationType, &gEfiFileInfoGuid)) {
+ Status = WinNtSimpleFileSystemFileInfo (PrivateFile, BufferSize, Buffer);
+ }
+
+ if (CompareGuid (InformationType, &gEfiFileSystemInfoGuid)) {
+ if (*BufferSize < SIZE_OF_EFI_FILE_SYSTEM_INFO + StrSize (PrivateRoot->VolumeLabel)) {
+ *BufferSize = SIZE_OF_EFI_FILE_SYSTEM_INFO + StrSize (PrivateRoot->VolumeLabel);
+ Status = EFI_BUFFER_TOO_SMALL;
+ goto Done;
+ }
+
+ FileSystemInfoBuffer = (EFI_FILE_SYSTEM_INFO *)Buffer;
+ FileSystemInfoBuffer->Size = SIZE_OF_EFI_FILE_SYSTEM_INFO + StrSize (PrivateRoot->VolumeLabel);
+ FileSystemInfoBuffer->ReadOnly = FALSE;
+
+ //
+ // Try to get the drive name
+ //
+ DriveNameFound = FALSE;
+ DriveName = AllocatePool (StrSize (PrivateFile->FilePath) + 1);
+ if (DriveName == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto Done;
+ }
+
+ StrCpy (DriveName, PrivateFile->FilePath);
+ for (Index = 0; DriveName[Index] != 0 && DriveName[Index] != ':'; Index++) {
+ ;
+ }
+
+ if (DriveName[Index] == ':') {
+ DriveName[Index + 1] = '\\';
+ DriveName[Index + 2] = 0;
+ DriveNameFound = TRUE;
+ } else if (DriveName[0] == '\\' && DriveName[1] == '\\') {
+ for (Index = 2; DriveName[Index] != 0 && DriveName[Index] != '\\'; Index++) {
+ ;
+ }
+
+ if (DriveName[Index] == '\\') {
+ DriveNameFound = TRUE;
+ for (Index++; DriveName[Index] != 0 && DriveName[Index] != '\\'; Index++) {
+ ;
+ }
+
+ DriveName[Index] = '\\';
+ DriveName[Index + 1] = 0;
+ }
+ }
+
+ //
+ // Try GetDiskFreeSpace first
+ //
+ NtStatus = GetDiskFreeSpace (
+ DriveNameFound ? DriveName : NULL,
+ (LPDWORD)&SectorsPerCluster,
+ (LPDWORD)&BytesPerSector,
+ (LPDWORD)&FreeClusters,
+ (LPDWORD)&TotalClusters
+ );
+ if (DriveName) {
+ FreePool (DriveName);
+ }
+
+ if (NtStatus) {
+ //
+ // Succeeded
+ //
+ BytesPerCluster = BytesPerSector * SectorsPerCluster;
+ FileSystemInfoBuffer->VolumeSize = MultU64x32 (TotalClusters, BytesPerCluster);
+ FileSystemInfoBuffer->FreeSpace = MultU64x32 (FreeClusters, BytesPerCluster);
+ FileSystemInfoBuffer->BlockSize = BytesPerCluster;
+
+ } else {
+ //
+ // try GetDiskFreeSpaceEx then
+ //
+ FileSystemInfoBuffer->BlockSize = 0;
+ NtStatus = GetDiskFreeSpaceEx (
+ PrivateFile->FilePath,
+ (PULARGE_INTEGER)(&FileSystemInfoBuffer->FreeSpace),
+ (PULARGE_INTEGER)(&FileSystemInfoBuffer->VolumeSize),
+ NULL
+ );
+ if (!NtStatus) {
+ Status = EFI_DEVICE_ERROR;
+ goto Done;
+ }
+ }
+
+ StrCpy ((CHAR16 *)FileSystemInfoBuffer->VolumeLabel, PrivateRoot->VolumeLabel);
+ *BufferSize = SIZE_OF_EFI_FILE_SYSTEM_INFO + StrSize (PrivateRoot->VolumeLabel);
+ Status = EFI_SUCCESS;
+ }
+
+ if (CompareGuid (InformationType, &gEfiFileSystemVolumeLabelInfoIdGuid)) {
+ if (*BufferSize < StrSize (PrivateRoot->VolumeLabel)) {
+ *BufferSize = StrSize (PrivateRoot->VolumeLabel);
+ Status = EFI_BUFFER_TOO_SMALL;
+ goto Done;
+ }
+
+ StrCpy ((CHAR16 *)Buffer, PrivateRoot->VolumeLabel);
+ *BufferSize = StrSize (PrivateRoot->VolumeLabel);
+ Status = EFI_SUCCESS;
+ }
+
+Done:
+ return Status;
+}
+
+
+/**
+ Set information about a file
+
+ @param File Protocol instance pointer.
+ @param InformationType Type of information in Buffer.
+ @param BufferSize Size of buffer.
+ @param Buffer The data to write.
+
+ @retval EFI_SUCCESS Data was returned.
+ @retval EFI_UNSUPPORTED InformationType is not supported.
+ @retval EFI_NO_MEDIA The device has no media.
+ @retval EFI_DEVICE_ERROR The device reported an error.
+ @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.
+ @retval EFI_WRITE_PROTECTED The device is write protected.
+ @retval EFI_ACCESS_DENIED The file was open for read only.
+
+**/
+EFI_STATUS
+WinNtFileSetInfo (
+ IN EFI_FILE_PROTOCOL *This,
+ IN EFI_GUID *InformationType,
+ IN UINTN BufferSize,
+ IN VOID *Buffer
+ )
+{
+ WIN_NT_SIMPLE_FILE_SYSTEM_PRIVATE *PrivateRoot;
+ WIN_NT_EFI_FILE_PRIVATE *PrivateFile;
+ EFI_FILE_INFO *OldFileInfo;
+ EFI_FILE_INFO *NewFileInfo;
+ EFI_STATUS Status;
+ UINTN OldInfoSize;
+ INTN NtStatus;
+ UINT32 NewAttr;
+ UINT32 OldAttr;
+ CHAR16 *OldFileName;
+ CHAR16 *NewFileName;
+ CHAR16 *TempFileName;
+ CHAR16 *CharPointer;
+ BOOLEAN AttrChangeFlag;
+ BOOLEAN NameChangeFlag;
+ BOOLEAN SizeChangeFlag;
+ BOOLEAN TimeChangeFlag;
+ UINT64 CurPos;
+ SYSTEMTIME NewCreationSystemTime;
+ SYSTEMTIME NewLastAccessSystemTime;
+ SYSTEMTIME NewLastWriteSystemTime;
+ FILETIME NewCreationFileTime;
+ FILETIME NewLastAccessFileTime;
+ FILETIME NewLastWriteFileTime;
+ WIN32_FIND_DATA FindBuf;
+ EFI_FILE_SYSTEM_INFO *NewFileSystemInfo;
+ UINTN Size;
+
+ //
+ // Initialise locals.
+ //
+ PrivateFile = WIN_NT_EFI_FILE_PRIVATE_DATA_FROM_THIS (This);
+ PrivateRoot = WIN_NT_SIMPLE_FILE_SYSTEM_PRIVATE_DATA_FROM_THIS (PrivateFile->SimpleFileSystem);
+
+ Status = EFI_UNSUPPORTED;
+ OldFileInfo = NewFileInfo = NULL;
+ OldFileName = NewFileName = NULL;
+ AttrChangeFlag = NameChangeFlag = SizeChangeFlag = TimeChangeFlag = FALSE;
+
+ //
+ // Set file system information.
+ //
+ if (CompareGuid (InformationType, &gEfiFileSystemInfoGuid)) {
+ NewFileSystemInfo = (EFI_FILE_SYSTEM_INFO *)Buffer;
+ if (BufferSize < SIZE_OF_EFI_FILE_SYSTEM_INFO + StrSize (NewFileSystemInfo->VolumeLabel)) {
+ Status = EFI_BAD_BUFFER_SIZE;
+ goto Done;
+ }
+
+
+ FreePool (PrivateRoot->VolumeLabel);
+ PrivateRoot->VolumeLabel = AllocatePool (StrSize (NewFileSystemInfo->VolumeLabel));
+ if (PrivateRoot->VolumeLabel == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto Done;
+ }
+
+ StrCpy (PrivateRoot->VolumeLabel, NewFileSystemInfo->VolumeLabel);
+
+ Status = EFI_SUCCESS;
+ goto Done;
+ }
+
+ //
+ // Set volume label information.
+ //
+ if (CompareGuid (InformationType, &gEfiFileSystemVolumeLabelInfoIdGuid)) {
+ if (BufferSize < StrSize (PrivateRoot->VolumeLabel)) {
+ Status = EFI_BAD_BUFFER_SIZE;
+ goto Done;
+ }
+
+ StrCpy (PrivateRoot->VolumeLabel, (CHAR16 *)Buffer);
+
+ Status = EFI_SUCCESS;
+ goto Done;
+ }
+
+ if (!CompareGuid (InformationType, &gEfiFileInfoGuid)) {
+ Status = EFI_UNSUPPORTED;
+ goto Done;
+ }
+
+ if (BufferSize < SIZE_OF_EFI_FILE_INFO) {
+ Status = EFI_BAD_BUFFER_SIZE;
+ goto Done;
+ }
+
+ //
+ // Set file/directory information.
+ //
+
+ //
+ // Check for invalid set file information parameters.
+ //
+ NewFileInfo = (EFI_FILE_INFO *)Buffer;
+
+ if ((NewFileInfo->Size <= SIZE_OF_EFI_FILE_INFO) ||
+ (NewFileInfo->Attribute &~(EFI_FILE_VALID_ATTR)) ||
+ (sizeof (UINTN) == 4 && NewFileInfo->Size > 0xFFFFFFFF)
+ ) {
+ Status = EFI_INVALID_PARAMETER;
+ goto Done;
+ }
+
+ //
+ // bugbug: - This is not safe. We need something like EfiStrMaxSize()
+ // that would have an additional parameter that would be the size
+ // of the string array just in case there are no NULL characters in
+ // the string array.
+ //
+ //
+ // Get current file information so we can determine what kind
+ // of change request this is.
+ //
+ OldInfoSize = 0;
+ Status = WinNtSimpleFileSystemFileInfo (PrivateFile, &OldInfoSize, NULL);
+
+ if (Status != EFI_BUFFER_TOO_SMALL) {
+ Status = EFI_DEVICE_ERROR;
+ goto Done;
+ }
+
+ OldFileInfo = AllocatePool (OldInfoSize);
+ if (OldFileInfo == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto Done;
+ }
+
+ Status = WinNtSimpleFileSystemFileInfo (PrivateFile, &OldInfoSize, OldFileInfo);
+
+ if (EFI_ERROR (Status)) {
+ goto Done;
+ }
+
+ OldFileName = AllocatePool (StrSize (PrivateFile->FileName));
+ if (OldFileName == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto Done;
+ }
+
+ StrCpy (OldFileName, PrivateFile->FileName);
+
+ //
+ // Make full pathname from new filename and rootpath.
+ //
+ if (NewFileInfo->FileName[0] == '\\') {
+ Size = StrSize (PrivateRoot->FilePath);
+ Size += StrSize (L"\\");
+ Size += StrSize (NewFileInfo->FileName);
+ NewFileName = AllocatePool (Size);
+ if (NewFileName == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto Done;
+ }
+
+ StrCpy (NewFileName, PrivateRoot->FilePath);
+ StrCat (NewFileName, L"\\");
+ StrCat (NewFileName, NewFileInfo->FileName + 1);
+ } else {
+ Size = StrSize (PrivateFile->FilePath);
+ Size += StrSize (L"\\");
+ Size += StrSize (NewFileInfo->FileName);
+ NewFileName = AllocatePool (Size);
+ if (NewFileName == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto Done;
+ }
+
+ StrCpy (NewFileName, PrivateFile->FilePath);
+ StrCat (NewFileName, L"\\");
+ StrCat (NewFileName, NewFileInfo->FileName);
+ }
+
+ //
+ // Is there an attribute change request?
+ //
+ if (NewFileInfo->Attribute != OldFileInfo->Attribute) {
+ if ((NewFileInfo->Attribute & EFI_FILE_DIRECTORY) != (OldFileInfo->Attribute & EFI_FILE_DIRECTORY)) {
+ Status = EFI_INVALID_PARAMETER;
+ goto Done;
+ }
+
+ AttrChangeFlag = TRUE;
+ }
+
+ //
+ // Is there a name change request?
+ // bugbug: - Need EfiStrCaseCmp()
+ //
+ if (StrCmp (NewFileInfo->FileName, OldFileInfo->FileName)) {
+ NameChangeFlag = TRUE;
+ }
+
+ //
+ // Is there a size change request?
+ //
+ if (NewFileInfo->FileSize != OldFileInfo->FileSize) {
+ SizeChangeFlag = TRUE;
+ }
+
+ //
+ // Is there a time stamp change request?
+ //
+ if (!IsZero (&NewFileInfo->CreateTime, sizeof (EFI_TIME)) &&
+ CompareMem (&NewFileInfo->CreateTime, &OldFileInfo->CreateTime, sizeof (EFI_TIME))
+ ) {
+ TimeChangeFlag = TRUE;
+ } else if (!IsZero (&NewFileInfo->LastAccessTime, sizeof (EFI_TIME)) &&
+ CompareMem (&NewFileInfo->LastAccessTime, &OldFileInfo->LastAccessTime, sizeof (EFI_TIME))
+ ) {
+ TimeChangeFlag = TRUE;
+ } else if (!IsZero (&NewFileInfo->ModificationTime, sizeof (EFI_TIME)) &&
+ CompareMem (&NewFileInfo->ModificationTime, &OldFileInfo->ModificationTime, sizeof (EFI_TIME))
+ ) {
+ TimeChangeFlag = TRUE;
+ }
+
+ //
+ // All done if there are no change requests being made.
+ //
+ if (!(AttrChangeFlag || NameChangeFlag || SizeChangeFlag || TimeChangeFlag)) {
+ Status = EFI_SUCCESS;
+ goto Done;
+ }
+
+ //
+ // Set file or directory information.
+ //
+ OldAttr = GetFileAttributes (OldFileName);
+
+ //
+ // Name change.
+ //
+ if (NameChangeFlag) {
+ //
+ // Close the handles first
+ //
+ if (PrivateFile->IsOpenedByRead) {
+ Status = EFI_ACCESS_DENIED;
+ goto Done;
+ }
+
+ for (CharPointer = NewFileName; *CharPointer != 0 && *CharPointer != L'/'; CharPointer++) {
+ }
+
+ if (*CharPointer != 0) {
+ Status = EFI_ACCESS_DENIED;
+ goto Done;
+ }
+
+ if (PrivateFile->LHandle != INVALID_HANDLE_VALUE) {
+ if (PrivateFile->IsDirectoryPath) {
+ FindClose (PrivateFile->LHandle);
+ } else {
+ CloseHandle (PrivateFile->LHandle);
+ PrivateFile->LHandle = INVALID_HANDLE_VALUE;
+ }
+ }
+
+ if (PrivateFile->IsDirectoryPath && PrivateFile->DirHandle != INVALID_HANDLE_VALUE) {
+ CloseHandle (PrivateFile->DirHandle);
+ PrivateFile->DirHandle = INVALID_HANDLE_VALUE;
+ }
+
+ NtStatus = MoveFile (OldFileName, NewFileName);
+
+ if (NtStatus) {
+ //
+ // modify file name
+ //
+ FreePool (PrivateFile->FileName);
+
+ PrivateFile->FileName = AllocatePool (StrSize (NewFileName));
+ if (PrivateFile->FileName == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto Done;
+ }
+
+ StrCpy (PrivateFile->FileName, NewFileName);
+
+ Size = StrSize (NewFileName);
+ Size += StrSize (L"\\*");
+ TempFileName = AllocatePool (Size);
+
+ StrCpy (TempFileName, NewFileName);
+
+ if (!PrivateFile->IsDirectoryPath) {
+ PrivateFile->LHandle = CreateFile (
+ TempFileName,
+ PrivateFile->IsOpenedByRead ? GENERIC_READ : GENERIC_READ | GENERIC_WRITE,
+ FILE_SHARE_READ | FILE_SHARE_WRITE,
+ NULL,
+ OPEN_EXISTING,
+ 0,
+ NULL
+ );
+
+ FreePool (TempFileName);
+
+ //
+ // Flush buffers just in case
+ //
+ if (FlushFileBuffers (PrivateFile->LHandle) == 0) {
+ Status = EFI_DEVICE_ERROR;
+ goto Done;
+ }
+ } else {
+ PrivateFile->DirHandle = CreateFile (
+ TempFileName,
+ PrivateFile->IsOpenedByRead ? GENERIC_READ : GENERIC_READ | GENERIC_WRITE,
+ FILE_SHARE_READ | FILE_SHARE_WRITE,
+ NULL,
+ OPEN_EXISTING,
+ FILE_FLAG_BACKUP_SEMANTICS,
+ NULL
+ );
+
+ StrCat (TempFileName, L"\\*");
+ PrivateFile->LHandle = FindFirstFile (TempFileName, &FindBuf);
+
+ FreePool (TempFileName);
+ }
+ } else {
+ Status = EFI_ACCESS_DENIED;
+ Reopen:;
+
+ NtStatus = SetFileAttributes (OldFileName, OldAttr);
+
+ if (!NtStatus) {
+ goto Done;
+ }
+
+ Size = StrSize (OldFileName);
+ Size += StrSize (L"\\*");
+ TempFileName = AllocatePool (Size);
+
+ StrCpy (TempFileName, OldFileName);
+
+ if (!PrivateFile->IsDirectoryPath) {
+ PrivateFile->LHandle = CreateFile (
+ TempFileName,
+ PrivateFile->IsOpenedByRead ? GENERIC_READ : GENERIC_READ | GENERIC_WRITE,
+ FILE_SHARE_READ | FILE_SHARE_WRITE,
+ NULL,
+ OPEN_EXISTING,
+ 0,
+ NULL
+ );
+ } else {
+ PrivateFile->DirHandle = CreateFile (
+ TempFileName,
+ PrivateFile->IsOpenedByRead ? GENERIC_READ : GENERIC_READ | GENERIC_WRITE,
+ FILE_SHARE_READ | FILE_SHARE_WRITE,
+ NULL,
+ OPEN_EXISTING,
+ FILE_FLAG_BACKUP_SEMANTICS,
+ NULL
+ );
+
+ StrCat (TempFileName, L"\\*");
+ PrivateFile->LHandle = FindFirstFile (TempFileName, &FindBuf);
+ }
+
+ FreePool (TempFileName);
+
+ goto Done;
+
+ }
+ }
+
+ //
+ // Size change
+ //
+ if (SizeChangeFlag) {
+ if (PrivateFile->IsDirectoryPath) {
+ Status = EFI_UNSUPPORTED;
+ goto Done;
+ }
+
+ if (PrivateFile->IsOpenedByRead || OldFileInfo->Attribute & EFI_FILE_READ_ONLY) {
+ Status = EFI_ACCESS_DENIED;
+ goto Done;
+ }
+
+ Status = This->GetPosition (This, &CurPos);
+ if (EFI_ERROR (Status)) {
+ goto Done;
+ }
+
+ Status = This->SetPosition (This, NewFileInfo->FileSize);
+ if (EFI_ERROR (Status)) {
+ goto Done;
+ }
+
+ if (SetEndOfFile (PrivateFile->LHandle) == 0) {
+ Status = EFI_DEVICE_ERROR;
+ goto Done;
+ }
+
+ Status = This->SetPosition (This, CurPos);
+ if (EFI_ERROR (Status)) {
+ goto Done;
+ }
+ }
+
+ //
+ // Time change
+ //
+ if (TimeChangeFlag) {
+
+ NewCreationSystemTime.wYear = NewFileInfo->CreateTime.Year;
+ NewCreationSystemTime.wMonth = NewFileInfo->CreateTime.Month;
+ NewCreationSystemTime.wDay = NewFileInfo->CreateTime.Day;
+ NewCreationSystemTime.wHour = NewFileInfo->CreateTime.Hour;
+ NewCreationSystemTime.wMinute = NewFileInfo->CreateTime.Minute;
+ NewCreationSystemTime.wSecond = NewFileInfo->CreateTime.Second;
+ NewCreationSystemTime.wMilliseconds = 0;
+
+ if (!SystemTimeToFileTime (
+ &NewCreationSystemTime,
+ &NewCreationFileTime
+ )) {
+ goto Done;
+ }
+
+ if (!LocalFileTimeToFileTime (
+ &NewCreationFileTime,
+ &NewCreationFileTime
+ )) {
+ goto Done;
+ }
+
+ NewLastAccessSystemTime.wYear = NewFileInfo->LastAccessTime.Year;
+ NewLastAccessSystemTime.wMonth = NewFileInfo->LastAccessTime.Month;
+ NewLastAccessSystemTime.wDay = NewFileInfo->LastAccessTime.Day;
+ NewLastAccessSystemTime.wHour = NewFileInfo->LastAccessTime.Hour;
+ NewLastAccessSystemTime.wMinute = NewFileInfo->LastAccessTime.Minute;
+ NewLastAccessSystemTime.wSecond = NewFileInfo->LastAccessTime.Second;
+ NewLastAccessSystemTime.wMilliseconds = 0;
+
+ if (!SystemTimeToFileTime (
+ &NewLastAccessSystemTime,
+ &NewLastAccessFileTime
+ )) {
+ goto Done;
+ }
+
+ if (!LocalFileTimeToFileTime (
+ &NewLastAccessFileTime,
+ &NewLastAccessFileTime
+ )) {
+ goto Done;
+ }
+
+ NewLastWriteSystemTime.wYear = NewFileInfo->ModificationTime.Year;
+ NewLastWriteSystemTime.wMonth = NewFileInfo->ModificationTime.Month;
+ NewLastWriteSystemTime.wDay = NewFileInfo->ModificationTime.Day;
+ NewLastWriteSystemTime.wHour = NewFileInfo->ModificationTime.Hour;
+ NewLastWriteSystemTime.wMinute = NewFileInfo->ModificationTime.Minute;
+ NewLastWriteSystemTime.wSecond = NewFileInfo->ModificationTime.Second;
+ NewLastWriteSystemTime.wMilliseconds = 0;
+
+ if (!SystemTimeToFileTime (
+ &NewLastWriteSystemTime,
+ &NewLastWriteFileTime
+ )) {
+ goto Done;
+ }
+
+ if (!LocalFileTimeToFileTime (
+ &NewLastWriteFileTime,
+ &NewLastWriteFileTime
+ )) {
+ goto Done;
+ }
+
+ if (!SetFileTime (
+ PrivateFile->IsDirectoryPath ? PrivateFile->DirHandle : PrivateFile->LHandle,
+ &NewCreationFileTime,
+ &NewLastAccessFileTime,
+ &NewLastWriteFileTime
+ )) {
+ Status = EFI_DEVICE_ERROR;
+ goto Done;
+ }
+
+ }
+
+ //
+ // No matter about AttrChangeFlag, Attribute must be set.
+ // Because operation before may cause attribute change.
+ //
+ NewAttr = OldAttr;
+
+ if (NewFileInfo->Attribute & EFI_FILE_ARCHIVE) {
+ NewAttr |= FILE_ATTRIBUTE_ARCHIVE;
+ } else {
+ NewAttr &= ~FILE_ATTRIBUTE_ARCHIVE;
+ }
+
+ if (NewFileInfo->Attribute & EFI_FILE_HIDDEN) {
+ NewAttr |= FILE_ATTRIBUTE_HIDDEN;
+ } else {
+ NewAttr &= ~FILE_ATTRIBUTE_HIDDEN;
+ }
+
+ if (NewFileInfo->Attribute & EFI_FILE_SYSTEM) {
+ NewAttr |= FILE_ATTRIBUTE_SYSTEM;
+ } else {
+ NewAttr &= ~FILE_ATTRIBUTE_SYSTEM;
+ }
+
+ if (NewFileInfo->Attribute & EFI_FILE_READ_ONLY) {
+ NewAttr |= FILE_ATTRIBUTE_READONLY;
+ } else {
+ NewAttr &= ~FILE_ATTRIBUTE_READONLY;
+ }
+
+ NtStatus = SetFileAttributes (NewFileName, NewAttr);
+
+ if (!NtStatus) {
+ Status = EFI_DEVICE_ERROR;
+ goto Reopen;
+ }
+
+Done:
+ if (OldFileInfo != NULL) {
+ FreePool (OldFileInfo);
+ }
+
+ if (OldFileName != NULL) {
+ FreePool (OldFileName);
+ }
+
+ if (NewFileName != NULL) {
+ FreePool (NewFileName);
+ }
+
+ return Status;
+}
+
+
+/**
+ Flush data back for the file handle.
+
+ @param This Protocol instance pointer.
+
+ @retval EFI_SUCCESS Data was written.
+ @retval EFI_UNSUPPORTED Writes to Open directory are not supported.
+ @retval EFI_NO_MEDIA The device has no media.
+ @retval EFI_DEVICE_ERROR The device reported an error.
+ @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.
+ @retval EFI_WRITE_PROTECTED The device is write protected.
+ @retval EFI_ACCESS_DENIED The file was open for read only.
+ @retval EFI_VOLUME_FULL The volume is full.
+
+**/
+EFI_STATUS
+WinNtFileFlush (
+ IN EFI_FILE_PROTOCOL *This
+ )
+{
+ BY_HANDLE_FILE_INFORMATION FileInfo;
+ WIN_NT_EFI_FILE_PRIVATE *PrivateFile;
+ EFI_STATUS Status;
+
+ PrivateFile = WIN_NT_EFI_FILE_PRIVATE_DATA_FROM_THIS (This);
+
+ if (PrivateFile->LHandle == INVALID_HANDLE_VALUE) {
+ Status = EFI_DEVICE_ERROR;
+ goto Done;
+ }
+
+ if (PrivateFile->IsDirectoryPath) {
+ Status = EFI_SUCCESS;
+ goto Done;
+ }
+
+ if (PrivateFile->IsOpenedByRead) {
+ Status = EFI_ACCESS_DENIED;
+ goto Done;
+ }
+
+ GetFileInformationByHandle (PrivateFile->LHandle, &FileInfo);
+
+ if (FileInfo.dwFileAttributes & FILE_ATTRIBUTE_READONLY) {
+ Status = EFI_ACCESS_DENIED;
+ goto Done;
+ }
+
+ Status = FlushFileBuffers (PrivateFile->LHandle) ? EFI_SUCCESS : EFI_DEVICE_ERROR;
+
+Done:
+ return Status;
+ //
+ // bugbug: - Use Windows error reporting.
+ //
+
+}
+
+
+
+EFI_STATUS
+WinNtFileSystmeThunkOpen (
+ IN EMU_IO_THUNK_PROTOCOL *This
+ )
+{
+ WIN_NT_SIMPLE_FILE_SYSTEM_PRIVATE *Private;
+
+ Private = AllocateZeroPool (sizeof (*Private));
+ if (Private == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ Private->FilePath = AllocateCopyPool (StrSize (This->ConfigString), This->ConfigString);
+ if (Private->FilePath == NULL) {
+ FreePool (Private);
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ Private->VolumeLabel = AllocateCopyPool (StrSize (L"EFI_EMULATED"), L"EFI_EMULATED");
+ if (Private->VolumeLabel == NULL) {
+ FreePool (Private->FilePath);
+ FreePool (Private);
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ Private->Signature = WIN_NT_SIMPLE_FILE_SYSTEM_PRIVATE_SIGNATURE;
+ Private->Thunk = This;
+ CopyMem (&Private->SimpleFileSystem, &gWinNtFileSystemProtocol, sizeof (Private->SimpleFileSystem));
+
+ This->Interface = &Private->SimpleFileSystem;
+ This->Private = Private;
+ return EFI_SUCCESS;
+}
+
+
+EFI_STATUS
+WinNtFileSystmeThunkClose (
+ IN EMU_IO_THUNK_PROTOCOL *This
+ )
+{
+ WIN_NT_SIMPLE_FILE_SYSTEM_PRIVATE *Private;
+
+ Private = This->Private;
+ ASSERT (Private != NULL);
+
+ if (Private->VolumeLabel != NULL) {
+ FreePool (Private->VolumeLabel);
+ }
+ if (Private->FilePath != NULL) {
+ FreePool (Private->FilePath);
+ }
+ FreePool (Private);
+ return EFI_SUCCESS;
+}
+
+
+EFI_FILE_PROTOCOL gWinNtFileProtocol = {
+ EFI_FILE_REVISION,
+ WinNtFileOpen,
+ WinNtFileClose,
+ WinNtFileDelete,
+ WinNtFileRead,
+ WinNtFileWrite,
+ WinNtFileGetPossition,
+ WinNtFileSetPossition,
+ WinNtFileGetInfo,
+ WinNtFileSetInfo,
+ WinNtFileFlush
+};
+
+EFI_SIMPLE_FILE_SYSTEM_PROTOCOL gWinNtFileSystemProtocol = {
+ EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_REVISION,
+ WinNtOpenVolume
+};
+
+
+EMU_IO_THUNK_PROTOCOL mWinNtFileSystemThunkIo = {
+ &gEfiSimpleFileSystemProtocolGuid,
+ NULL,
+ NULL,
+ 0,
+ WinNtFileSystmeThunkOpen,
+ WinNtFileSystmeThunkClose,
+ NULL
+};
+
+
diff --git a/EmulatorPkg/Win/Host/WinHost.c b/EmulatorPkg/Win/Host/WinHost.c
index f8d21d26d9..266ae59382 100644
--- a/EmulatorPkg/Win/Host/WinHost.c
+++ b/EmulatorPkg/Win/Host/WinHost.c
@@ -428,6 +428,7 @@ Returns:
// Emulator Bus Driver Thunks
//
AddThunkProtocol (&mWinNtWndThunkIo, (CHAR16 *)PcdGetPtr (PcdEmuGop), TRUE);
+ AddThunkProtocol (&mWinNtFileSystemThunkIo, (CHAR16 *)PcdGetPtr (PcdEmuFileSystem), TRUE);
//
// Allocate space for gSystemMemory Array
diff --git a/EmulatorPkg/Win/Host/WinHost.h b/EmulatorPkg/Win/Host/WinHost.h
index 3dc6a7e641..3c7529fa91 100644
--- a/EmulatorPkg/Win/Host/WinHost.h
+++ b/EmulatorPkg/Win/Host/WinHost.h
@@ -26,8 +26,12 @@ Abstract:
#include <PiPei.h>
#include <IndustryStandard/PeImage.h>
+#include <Guid/FileInfo.h>
+#include <Guid/FileSystemInfo.h>
+#include <Guid/FileSystemVolumeLabelInfo.h>
#include <Ppi/EmuThunk.h>
#include <Protocol/EmuThunk.h>
+#include <Protocol/SimpleFileSystem.h>
#include <Library/BaseLib.h>
@@ -198,4 +202,5 @@ SecInitializeThunk (
);
extern EMU_THUNK_PROTOCOL gEmuThunkProtocol;
extern EMU_IO_THUNK_PROTOCOL mWinNtWndThunkIo;
+extern EMU_IO_THUNK_PROTOCOL mWinNtFileSystemThunkIo;
#endif
\ No newline at end of file
diff --git a/EmulatorPkg/Win/Host/WinHost.inf b/EmulatorPkg/Win/Host/WinHost.inf
index b62791bcfa..358d000857 100644
--- a/EmulatorPkg/Win/Host/WinHost.inf
+++ b/EmulatorPkg/Win/Host/WinHost.inf
@@ -33,6 +33,7 @@ [Sources]
WinGopInput.c
WinGopScreen.c
WinGop.h
+ WinFileSystem.c
WinThunk.c
WinHost.h
WinHost.c
@@ -61,6 +62,13 @@ [Ppis]
[Protocols]
gEmuIoThunkProtocolGuid
gEmuGraphicsWindowProtocolGuid
+ gEfiSimpleFileSystemProtocolGuid
+
+[Guids]
+ gEfiFileSystemVolumeLabelInfoIdGuid # SOMETIMES_CONSUMED
+ gEfiFileInfoGuid # SOMETIMES_CONSUMED
+ gEfiFileSystemInfoGuid # SOMETIMES_CONSUMED
+
[Pcd]
gEfiMdeModulePkgTokenSpaceGuid.PcdInitValueInTempStack
@@ -69,6 +77,7 @@ [Pcd]
gEmulatorPkgTokenSpaceGuid.PcdEmuMemorySize
gEmulatorPkgTokenSpaceGuid.PcdEmuFdBaseAddress
gEmulatorPkgTokenSpaceGuid.PcdEmuGop|L"GOP Window"
+ gEmulatorPkgTokenSpaceGuid.PcdEmuFileSystem
gEmulatorPkgTokenSpaceGuid.PcdPeiServicesTablePage
[BuildOptions]
--
2.16.1.windows.1
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [PATCH 09/12] EmulatorPkg/Win: Add BlockIo support
2018-08-23 9:52 [PATCH 00/12] Add WinHost support in EmulatorPkg Ruiyu Ni
` (7 preceding siblings ...)
2018-08-23 9:52 ` [PATCH 08/12] EmulatorPkg/Win: Add SimpleFileSystem support Ruiyu Ni
@ 2018-08-23 9:52 ` Ruiyu Ni
2018-08-23 9:52 ` [PATCH 10/12] EmulatorPkg/PlatformBds: Signal EndOfDxe in platform BDS Ruiyu Ni
` (3 subsequent siblings)
12 siblings, 0 replies; 14+ messages in thread
From: Ruiyu Ni @ 2018-08-23 9:52 UTC (permalink / raw)
To: edk2-devel; +Cc: Hao Wu, Andrew Fish
Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Ruiyu Ni <ruiyu.ni@intel.com>
Cc: Hao Wu <hao.a.wu@intel.com>
Cc: Andrew Fish <afish@intel.com>
---
EmulatorPkg/Win/Host/WinBlockIo.c | 563 ++++++++++++++++++++++++++++++++++++++
EmulatorPkg/Win/Host/WinHost.c | 1 +
EmulatorPkg/Win/Host/WinHost.h | 3 +
EmulatorPkg/Win/Host/WinHost.inf | 3 +
4 files changed, 570 insertions(+)
create mode 100644 EmulatorPkg/Win/Host/WinBlockIo.c
diff --git a/EmulatorPkg/Win/Host/WinBlockIo.c b/EmulatorPkg/Win/Host/WinBlockIo.c
new file mode 100644
index 0000000000..14491a6e90
--- /dev/null
+++ b/EmulatorPkg/Win/Host/WinBlockIo.c
@@ -0,0 +1,563 @@
+/**@file
+
+Copyright (c) 2004 - 2018, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "WinHost.h"
+
+#define WIN_NT_BLOCK_IO_PRIVATE_SIGNATURE SIGNATURE_32 ('N', 'T', 'b', 'k')
+typedef struct {
+ UINTN Signature;
+
+ EMU_IO_THUNK_PROTOCOL *Thunk;
+
+ CHAR16 *FileName;
+ BOOLEAN Removable;
+ BOOLEAN Readonly;
+
+ HANDLE NtHandle;
+ UINTN BlockSize;
+
+ EFI_BLOCK_IO_MEDIA *Media;
+ EMU_BLOCK_IO_PROTOCOL EmuBlockIo;
+} WIN_NT_BLOCK_IO_PRIVATE;
+
+#define WIN_NT_BLOCK_IO_PRIVATE_DATA_FROM_THIS(a) \
+ CR(a, WIN_NT_BLOCK_IO_PRIVATE, EmuBlockIo, WIN_NT_BLOCK_IO_PRIVATE_SIGNATURE)
+
+
+EFI_STATUS
+WinNtBlockIoReset (
+ IN EMU_BLOCK_IO_PROTOCOL *This,
+ IN BOOLEAN ExtendedVerification
+ );
+
+
+
+
+EFI_STATUS
+SetFilePointer64 (
+ IN WIN_NT_BLOCK_IO_PRIVATE *Private,
+ IN INT64 DistanceToMove,
+ OUT UINT64 *NewFilePointer,
+ IN DWORD MoveMethod
+)
+/*++
+
+This function extends the capability of SetFilePointer to accept 64 bit parameters
+
+--*/
+{
+ EFI_STATUS Status;
+ LARGE_INTEGER LargeInt;
+
+ LargeInt.QuadPart = DistanceToMove;
+ Status = EFI_SUCCESS;
+
+ LargeInt.LowPart = SetFilePointer (
+ Private->NtHandle,
+ LargeInt.LowPart,
+ &LargeInt.HighPart,
+ MoveMethod
+ );
+
+ if (LargeInt.LowPart == -1 && GetLastError () != NO_ERROR) {
+ Status = EFI_INVALID_PARAMETER;
+ }
+
+ if (NewFilePointer != NULL) {
+ *NewFilePointer = LargeInt.QuadPart;
+ }
+
+ return Status;
+}
+
+
+
+EFI_STATUS
+WinNtBlockIoOpenDevice (
+ IN WIN_NT_BLOCK_IO_PRIVATE *Private,
+ IN EFI_BLOCK_IO_MEDIA *Media
+ )
+{
+ EFI_STATUS Status;
+ UINT64 FileSize;
+
+ //
+ // If the device is already opened, close it
+ //
+ if (Private->NtHandle != INVALID_HANDLE_VALUE) {
+ WinNtBlockIoReset (&Private->EmuBlockIo, FALSE);
+ }
+
+ //
+ // Open the device
+ //
+ Private->NtHandle = CreateFile (
+ Private->FileName,
+ GENERIC_READ | (Private->Readonly ? 0 : GENERIC_WRITE),
+ FILE_SHARE_READ | FILE_SHARE_WRITE,
+ NULL,
+ OPEN_ALWAYS, // Create if it doesn't exist
+ 0,
+ NULL
+ );
+
+ if (Private->NtHandle == INVALID_HANDLE_VALUE) {
+ DEBUG ((EFI_D_INFO, "OpenBlock: Could not open %S, %x\n", Private->FileName, GetLastError ()));
+ Media->MediaPresent = FALSE;
+ Status = EFI_NO_MEDIA;
+ goto Done;
+ }
+
+ //
+ // get the size of the file
+ //
+ Status = SetFilePointer64 (Private, 0, &FileSize, FILE_END);
+
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "OpenBlock: Could not get filesize of %s\n", Private->FileName));
+ Status = EFI_UNSUPPORTED;
+ goto Done;
+ }
+
+ Media->LastBlock = DivU64x32 (FileSize, (UINT32)Private->BlockSize) - 1;
+
+ DEBUG ((EFI_D_INIT, "OpenBlock: opened %S\n", Private->FileName));
+ Status = EFI_SUCCESS;
+
+Done:
+ if (EFI_ERROR (Status)) {
+ if (Private->NtHandle != INVALID_HANDLE_VALUE) {
+ WinNtBlockIoReset (&Private->EmuBlockIo, FALSE);
+ }
+ }
+
+ return Status;
+}
+
+
+EFI_STATUS
+EFIAPI
+WinNtBlockIoCreateMapping (
+ IN EMU_BLOCK_IO_PROTOCOL *This,
+ IN EFI_BLOCK_IO_MEDIA *Media
+ )
+{
+ WIN_NT_BLOCK_IO_PRIVATE *Private;
+
+ Private = WIN_NT_BLOCK_IO_PRIVATE_DATA_FROM_THIS (This);
+
+ Media->MediaId = 0;
+ Media->RemovableMedia = Private->Removable;
+ Media->MediaPresent = TRUE;
+ Media->LogicalPartition = FALSE;
+ Media->ReadOnly = Private->Readonly;
+ Media->WriteCaching = FALSE;
+ Media->IoAlign = 1;
+ Media->LastBlock = 0; // Filled in by OpenDevice
+ Media->BlockSize = Private->BlockSize;
+
+ // EFI_BLOCK_IO_PROTOCOL_REVISION2
+ Media->LowestAlignedLba = 0;
+ Media->LogicalBlocksPerPhysicalBlock = 0;
+
+
+ // EFI_BLOCK_IO_PROTOCOL_REVISION3
+ Media->OptimalTransferLengthGranularity = 0;
+
+ //
+ // Remember the Media pointer.
+ //
+ Private->Media = Media;
+ return WinNtBlockIoOpenDevice (Private, Media);
+}
+
+
+
+EFI_STATUS
+WinNtBlockIoError (
+ IN WIN_NT_BLOCK_IO_PRIVATE *Private
+)
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ Private - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+{
+ EFI_BLOCK_IO_MEDIA *Media;
+ EFI_STATUS Status;
+
+ Media = Private->Media;
+
+ switch (GetLastError ()) {
+
+ case ERROR_NOT_READY:
+ Media->ReadOnly = FALSE;
+ Media->MediaPresent = FALSE;
+ Status = EFI_NO_MEDIA;
+ break;
+
+ case ERROR_WRONG_DISK:
+ Media->ReadOnly = FALSE;
+ Media->MediaPresent = TRUE;
+ Media->MediaId++;
+ Status = EFI_MEDIA_CHANGED;
+ break;
+
+ case ERROR_WRITE_PROTECT:
+ Media->ReadOnly = TRUE;
+ Status = EFI_WRITE_PROTECTED;
+ break;
+
+ default:
+ Status = EFI_DEVICE_ERROR;
+ break;
+ }
+
+ if (Status == EFI_NO_MEDIA || Status == EFI_MEDIA_CHANGED) {
+ WinNtBlockIoReset (&Private->EmuBlockIo, FALSE);
+ }
+
+ return Status;
+}
+
+
+EFI_STATUS
+WinNtSignalToken (
+ IN OUT EFI_BLOCK_IO2_TOKEN *Token,
+ IN EFI_STATUS Status
+)
+{
+ if (Token != NULL) {
+ if (Token->Event != NULL) {
+ // Caller is responcible for signaling EFI Event
+ Token->TransactionStatus = Status;
+ return EFI_SUCCESS;
+ }
+ }
+ return Status;
+}
+
+/**
+ Read BufferSize bytes from Lba into Buffer.
+
+ This function reads the requested number of blocks from the device. All the
+ blocks are read, or an error is returned.
+ If EFI_DEVICE_ERROR, EFI_NO_MEDIA,_or EFI_MEDIA_CHANGED is returned and
+ non-blocking I/O is being used, the Event associated with this request will
+ not be signaled.
+
+ @param[in] This Indicates a pointer to the calling context.
+ @param[in] MediaId Id of the media, changes every time the media is
+ replaced.
+ @param[in] Lba The starting Logical Block Address to read from.
+ @param[in, out] Token A pointer to the token associated with the transaction.
+ @param[in] BufferSize Size of Buffer, must be a multiple of device block size.
+ @param[out] Buffer A pointer to the destination buffer for the data. The
+ caller is responsible for either having implicit or
+ explicit ownership of the buffer.
+
+ @retval EFI_SUCCESS The read request was queued if Token->Event is
+ not NULL.The data was read correctly from the
+ device if the Token->Event is NULL.
+ @retval EFI_DEVICE_ERROR The device reported an error while performing
+ the read.
+ @retval EFI_NO_MEDIA There is no media in the device.
+ @retval EFI_MEDIA_CHANGED The MediaId is not for the current media.
+ @retval EFI_BAD_BUFFER_SIZE The BufferSize parameter is not a multiple of the
+ intrinsic block size of the device.
+ @retval EFI_INVALID_PARAMETER The read request contains LBAs that are not valid,
+ or the buffer is not on proper alignment.
+ @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack
+ of resources.
+**/
+EFI_STATUS
+WinNtBlockIoReadBlocks (
+ IN EMU_BLOCK_IO_PROTOCOL *This,
+ IN UINT32 MediaId,
+ IN EFI_LBA Lba,
+ IN OUT EFI_BLOCK_IO2_TOKEN *Token,
+ IN UINTN BufferSize,
+ OUT VOID *Buffer
+ )
+{
+ WIN_NT_BLOCK_IO_PRIVATE *Private;
+ BOOL Flag;
+ EFI_STATUS Status;
+ DWORD BytesRead;
+ UINT64 DistanceToMove;
+ UINT64 DistanceMoved;
+
+ Private = WIN_NT_BLOCK_IO_PRIVATE_DATA_FROM_THIS (This);
+
+ //
+ // Seek to proper position
+ //
+ DistanceToMove = MultU64x32 (Lba, (UINT32)Private->BlockSize);
+ Status = SetFilePointer64 (Private, DistanceToMove, &DistanceMoved, FILE_BEGIN);
+
+ if (EFI_ERROR (Status) || (DistanceToMove != DistanceMoved)) {
+ DEBUG ((EFI_D_INIT, "ReadBlocks: SetFilePointer failed\n"));
+ return WinNtBlockIoError (Private->Media);
+ }
+
+ Flag = ReadFile (Private->NtHandle, Buffer, (DWORD)BufferSize, (LPDWORD)&BytesRead, NULL);
+ if (!Flag || (BytesRead != BufferSize)) {
+ return WinNtBlockIoError (Private->Media);
+ }
+
+ Private->Media->MediaPresent = TRUE;
+ return WinNtSignalToken (Token, EFI_SUCCESS);
+}
+
+
+/**
+ Write BufferSize bytes from Lba into Buffer.
+
+ This function writes the requested number of blocks to the device. All blocks
+ are written, or an error is returned.If EFI_DEVICE_ERROR, EFI_NO_MEDIA,
+ EFI_WRITE_PROTECTED or EFI_MEDIA_CHANGED is returned and non-blocking I/O is
+ being used, the Event associated with this request will not be signaled.
+
+ @param[in] This Indicates a pointer to the calling context.
+ @param[in] MediaId The media ID that the write request is for.
+ @param[in] Lba The starting logical block address to be written. The
+ caller is responsible for writing to only legitimate
+ locations.
+ @param[in, out] Token A pointer to the token associated with the transaction.
+ @param[in] BufferSize Size of Buffer, must be a multiple of device block size.
+ @param[in] Buffer A pointer to the source buffer for the data.
+
+ @retval EFI_SUCCESS The write request was queued if Event is not NULL.
+ The data was written correctly to the device if
+ the Event is NULL.
+ @retval EFI_WRITE_PROTECTED The device can not be written to.
+ @retval EFI_NO_MEDIA There is no media in the device.
+ @retval EFI_MEDIA_CHNAGED The MediaId does not matched the current device.
+ @retval EFI_DEVICE_ERROR The device reported an error while performing the write.
+ @retval EFI_BAD_BUFFER_SIZE The Buffer was not a multiple of the block size of the device.
+ @retval EFI_INVALID_PARAMETER The write request contains LBAs that are not valid,
+ or the buffer is not on proper alignment.
+ @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack
+ of resources.
+
+**/
+EFI_STATUS
+WinNtBlockIoWriteBlocks (
+ IN EMU_BLOCK_IO_PROTOCOL *This,
+ IN UINT32 MediaId,
+ IN EFI_LBA Lba,
+ IN OUT EFI_BLOCK_IO2_TOKEN *Token,
+ IN UINTN BufferSize,
+ IN VOID *Buffer
+ )
+{
+ WIN_NT_BLOCK_IO_PRIVATE *Private;
+ UINTN BytesWritten;
+ BOOL Success;
+ EFI_STATUS Status;
+ UINT64 DistanceToMove;
+ UINT64 DistanceMoved;
+
+ Private = WIN_NT_BLOCK_IO_PRIVATE_DATA_FROM_THIS (This);
+
+ //
+ // Seek to proper position
+ //
+ DistanceToMove = MultU64x32 (Lba, (UINT32)Private->BlockSize);
+ Status = SetFilePointer64 (Private, DistanceToMove, &DistanceMoved, FILE_BEGIN);
+
+ if (EFI_ERROR (Status) || (DistanceToMove != DistanceMoved)) {
+ DEBUG ((EFI_D_INIT, "WriteBlocks: SetFilePointer failed\n"));
+ return WinNtBlockIoError (Private->Media);
+ }
+
+ Success = WriteFile (Private->NtHandle, Buffer, (DWORD)BufferSize, (LPDWORD)&BytesWritten, NULL);
+ if (!Success || (BytesWritten != BufferSize)) {
+ return WinNtBlockIoError (Private->Media);
+ }
+
+ //
+ // If the write succeeded, we are not write protected and media is present.
+ //
+ Private->Media->MediaPresent = TRUE;
+ Private->Media->ReadOnly = FALSE;
+ return WinNtSignalToken (Token, EFI_SUCCESS);
+}
+
+/**
+ Flush the Block Device.
+
+ If EFI_DEVICE_ERROR, EFI_NO_MEDIA,_EFI_WRITE_PROTECTED or EFI_MEDIA_CHANGED
+ is returned and non-blocking I/O is being used, the Event associated with
+ this request will not be signaled.
+
+ @param[in] This Indicates a pointer to the calling context.
+ @param[in,out] Token A pointer to the token associated with the transaction
+
+ @retval EFI_SUCCESS The flush request was queued if Event is not NULL.
+ All outstanding data was written correctly to the
+ device if the Event is NULL.
+ @retval EFI_DEVICE_ERROR The device reported an error while writting back
+ the data.
+ @retval EFI_WRITE_PROTECTED The device cannot be written to.
+ @retval EFI_NO_MEDIA There is no media in the device.
+ @retval EFI_MEDIA_CHANGED The MediaId is not for the current media.
+ @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack
+ of resources.
+
+**/
+EFI_STATUS
+WinNtBlockIoFlushBlocks (
+ IN EMU_BLOCK_IO_PROTOCOL *This,
+ IN OUT EFI_BLOCK_IO2_TOKEN *Token
+ )
+{
+ return WinNtSignalToken (Token, EFI_SUCCESS);
+}
+
+
+/**
+ Reset the block device hardware.
+
+ @param[in] This Indicates a pointer to the calling context.
+ @param[in] ExtendedVerification Indicates that the driver may perform a more
+ exhausive verfication operation of the device
+ during reset.
+
+ @retval EFI_SUCCESS The device was reset.
+ @retval EFI_DEVICE_ERROR The device is not functioning properly and could
+ not be reset.
+
+**/
+EFI_STATUS
+WinNtBlockIoReset (
+ IN EMU_BLOCK_IO_PROTOCOL *This,
+ IN BOOLEAN ExtendedVerification
+ )
+{
+ WIN_NT_BLOCK_IO_PRIVATE *Private;
+
+ Private = WIN_NT_BLOCK_IO_PRIVATE_DATA_FROM_THIS (This);
+
+ if (Private->NtHandle != INVALID_HANDLE_VALUE) {
+ CloseHandle (Private->NtHandle);
+ Private->NtHandle = INVALID_HANDLE_VALUE;
+ }
+
+ return EFI_SUCCESS;
+}
+
+EMU_BLOCK_IO_PROTOCOL gEmuBlockIoProtocol = {
+ WinNtBlockIoReset,
+ WinNtBlockIoReadBlocks,
+ WinNtBlockIoWriteBlocks,
+ WinNtBlockIoFlushBlocks,
+ WinNtBlockIoCreateMapping
+};
+
+EFI_STATUS
+EFIAPI
+WinNtBlockIoThunkOpen (
+ IN EMU_IO_THUNK_PROTOCOL *This
+ )
+{
+ WIN_NT_BLOCK_IO_PRIVATE *Private;
+ CHAR16 *Str;
+
+ Private = AllocatePool (sizeof (*Private));
+ if (Private == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ Private->Signature = WIN_NT_BLOCK_IO_PRIVATE_SIGNATURE;
+ Private->Thunk = This;
+ CopyMem (&Private->EmuBlockIo, &gEmuBlockIoProtocol, sizeof (gEmuBlockIoProtocol));
+ Private->BlockSize = 512;
+ Private->NtHandle = INVALID_HANDLE_VALUE;
+
+ Private->FileName = AllocateCopyPool (StrSize (This->ConfigString), This->ConfigString);
+ if (Private->FileName == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ //
+ // Parse ConfigString
+ // <ConfigString> := <FileName> ':' [RF][OW] ':' <BlockSize>
+ //
+ Str = StrStr (Private->FileName, L":");
+ if (Str == NULL) {
+ Private->Removable = FALSE;
+ Private->Readonly = FALSE;
+ } else {
+ for (*Str++ = L'\0'; *Str != L'\0'; Str++) {
+ if (*Str == 'R' || *Str == 'F') {
+ Private->Removable = (BOOLEAN) (*Str == L'R');
+ }
+ if (*Str == 'O' || *Str == 'W') {
+ Private->Readonly = (BOOLEAN) (*Str == L'O');
+ }
+ if (*Str == ':') {
+ Private->BlockSize = wcstol (++Str, NULL, 0);
+ break;
+ }
+ }
+ }
+
+ This->Interface = &Private->EmuBlockIo;
+ This->Private = Private;
+ return EFI_SUCCESS;
+}
+
+
+EFI_STATUS
+EFIAPI
+WinNtBlockIoThunkClose (
+ IN EMU_IO_THUNK_PROTOCOL *This
+ )
+{
+ WIN_NT_BLOCK_IO_PRIVATE *Private;
+
+ Private = This->Private;
+
+ if (Private != NULL) {
+ if (Private->FileName != NULL) {
+ FreePool (Private->FileName);
+ }
+ FreePool (Private);
+ }
+
+ return EFI_SUCCESS;
+}
+
+
+
+EMU_IO_THUNK_PROTOCOL mWinNtBlockIoThunkIo = {
+ &gEmuBlockIoProtocolGuid,
+ NULL,
+ NULL,
+ 0,
+ WinNtBlockIoThunkOpen,
+ WinNtBlockIoThunkClose,
+ NULL
+};
+
+
diff --git a/EmulatorPkg/Win/Host/WinHost.c b/EmulatorPkg/Win/Host/WinHost.c
index 266ae59382..0cf02044c2 100644
--- a/EmulatorPkg/Win/Host/WinHost.c
+++ b/EmulatorPkg/Win/Host/WinHost.c
@@ -429,6 +429,7 @@ Returns:
//
AddThunkProtocol (&mWinNtWndThunkIo, (CHAR16 *)PcdGetPtr (PcdEmuGop), TRUE);
AddThunkProtocol (&mWinNtFileSystemThunkIo, (CHAR16 *)PcdGetPtr (PcdEmuFileSystem), TRUE);
+ AddThunkProtocol (&mWinNtBlockIoThunkIo, (CHAR16 *)PcdGetPtr (PcdEmuVirtualDisk), TRUE);
//
// Allocate space for gSystemMemory Array
diff --git a/EmulatorPkg/Win/Host/WinHost.h b/EmulatorPkg/Win/Host/WinHost.h
index 3c7529fa91..6f1f1a2dd3 100644
--- a/EmulatorPkg/Win/Host/WinHost.h
+++ b/EmulatorPkg/Win/Host/WinHost.h
@@ -33,6 +33,8 @@ Abstract:
#include <Protocol/EmuThunk.h>
#include <Protocol/SimpleFileSystem.h>
+#include <Protocol/EmuBlockIo.h>
+#include <Protocol/BlockIo.h>
#include <Library/BaseLib.h>
#include <Library/PeCoffLib.h>
@@ -203,4 +205,5 @@ SecInitializeThunk (
extern EMU_THUNK_PROTOCOL gEmuThunkProtocol;
extern EMU_IO_THUNK_PROTOCOL mWinNtWndThunkIo;
extern EMU_IO_THUNK_PROTOCOL mWinNtFileSystemThunkIo;
+extern EMU_IO_THUNK_PROTOCOL mWinNtBlockIoThunkIo;
#endif
\ No newline at end of file
diff --git a/EmulatorPkg/Win/Host/WinHost.inf b/EmulatorPkg/Win/Host/WinHost.inf
index 358d000857..501edac15e 100644
--- a/EmulatorPkg/Win/Host/WinHost.inf
+++ b/EmulatorPkg/Win/Host/WinHost.inf
@@ -34,6 +34,7 @@ [Sources]
WinGopScreen.c
WinGop.h
WinFileSystem.c
+ WinBlockIo.c
WinThunk.c
WinHost.h
WinHost.c
@@ -62,6 +63,7 @@ [Ppis]
[Protocols]
gEmuIoThunkProtocolGuid
gEmuGraphicsWindowProtocolGuid
+ gEmuBlockIoProtocolGuid
gEfiSimpleFileSystemProtocolGuid
[Guids]
@@ -76,6 +78,7 @@ [Pcd]
gEmulatorPkgTokenSpaceGuid.PcdEmuFirmwareVolume
gEmulatorPkgTokenSpaceGuid.PcdEmuMemorySize
gEmulatorPkgTokenSpaceGuid.PcdEmuFdBaseAddress
+ gEmulatorPkgTokenSpaceGuid.PcdEmuVirtualDisk
gEmulatorPkgTokenSpaceGuid.PcdEmuGop|L"GOP Window"
gEmulatorPkgTokenSpaceGuid.PcdEmuFileSystem
gEmulatorPkgTokenSpaceGuid.PcdPeiServicesTablePage
--
2.16.1.windows.1
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [PATCH 10/12] EmulatorPkg/PlatformBds: Signal EndOfDxe in platform BDS
2018-08-23 9:52 [PATCH 00/12] Add WinHost support in EmulatorPkg Ruiyu Ni
` (8 preceding siblings ...)
2018-08-23 9:52 ` [PATCH 09/12] EmulatorPkg/Win: Add BlockIo support Ruiyu Ni
@ 2018-08-23 9:52 ` Ruiyu Ni
2018-08-23 9:52 ` [PATCH 11/12] EmulatorPkg/EmuFileSystem: Fix a bug that causes Close() assertion Ruiyu Ni
` (2 subsequent siblings)
12 siblings, 0 replies; 14+ messages in thread
From: Ruiyu Ni @ 2018-08-23 9:52 UTC (permalink / raw)
To: edk2-devel; +Cc: Hao Wu, Andrew Fish
Without signal of EndOfDxe, the 3rd party code (.efi from non-flash
storage) cannot run. It's forbidden by
8be37a5cee700777ca8e8e8a34cc2225b21931a7
*MdeModulePkg/SecurityStubDxe: Defer 3rd party image before EndOfDxe
The patch enables running of SCT from internal shell.
Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Ruiyu Ni <ruiyu.ni@intel.com>
Cc: Hao Wu <hao.a.wu@intel.com>
Cc: Andrew Fish <afish@intel.com>
---
EmulatorPkg/Library/EmuBdsLib/BdsPlatform.c | 4 +++-
EmulatorPkg/Library/EmuBdsLib/BdsPlatform.h | 4 +++-
EmulatorPkg/Library/EmuBdsLib/EmuBdsLib.inf | 5 +++--
3 files changed, 9 insertions(+), 4 deletions(-)
diff --git a/EmulatorPkg/Library/EmuBdsLib/BdsPlatform.c b/EmulatorPkg/Library/EmuBdsLib/BdsPlatform.c
index 3580d36779..75fba847f4 100644
--- a/EmulatorPkg/Library/EmuBdsLib/BdsPlatform.c
+++ b/EmulatorPkg/Library/EmuBdsLib/BdsPlatform.c
@@ -1,6 +1,6 @@
/*++ @file
-Copyright (c) 2006 - 2009, Intel Corporation. All rights reserved.<BR>
+Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
Portions copyright (c) 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
@@ -77,6 +77,8 @@ Returns:
**/
{
SetupVariableInit ();
+
+ EfiEventGroupSignal (&gEfiEndOfDxeEventGroupGuid);
}
EFI_STATUS
diff --git a/EmulatorPkg/Library/EmuBdsLib/BdsPlatform.h b/EmulatorPkg/Library/EmuBdsLib/BdsPlatform.h
index a099fecda0..5ececd4bed 100644
--- a/EmulatorPkg/Library/EmuBdsLib/BdsPlatform.h
+++ b/EmulatorPkg/Library/EmuBdsLib/BdsPlatform.h
@@ -1,6 +1,6 @@
/*++ @file
-Copyright (c) 2006, Intel Corporation. All rights reserved.<BR>
+Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
Portions copyright (c) 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
@@ -18,6 +18,7 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
#include <PiDxe.h>
#include <Guid/EmuSystemConfig.h>
+#include <Guid/EventGroup.h>
#include <Protocol/EmuThunk.h>
#include <Protocol/EmuIoThunk.h>
#include <Protocol/EmuGraphicsWindow.h>
@@ -32,6 +33,7 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
#include <Library/GenericBdsLib.h>
#include <Library/PlatformBdsLib.h>
#include <Library/DevicePathLib.h>
+#include <Library/UefiLib.h>
extern BDS_CONSOLE_CONNECT_ENTRY gPlatformConsole[];
diff --git a/EmulatorPkg/Library/EmuBdsLib/EmuBdsLib.inf b/EmulatorPkg/Library/EmuBdsLib/EmuBdsLib.inf
index 526a159b96..755c50c789 100644
--- a/EmulatorPkg/Library/EmuBdsLib/EmuBdsLib.inf
+++ b/EmulatorPkg/Library/EmuBdsLib/EmuBdsLib.inf
@@ -2,7 +2,7 @@
# Platfrom BDS driver
#
# Do platform action customized by IBV/OEM.
-# Copyright (c) 2006 - 2015, Intel Corporation. All rights reserved.<BR>
+# Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
# Portions copyright (c) 2011, Apple Inc. All rights reserved.
#
# This program and the accompanying materials
@@ -51,10 +51,11 @@ [LibraryClasses]
PcdLib
GenericBdsLib
DevicePathLib
-
+ UefiLib
[Guids]
gEmuSystemConfigGuid
+ gEfiEndOfDxeEventGroupGuid
[Pcd]
gEfiMdeModulePkgTokenSpaceGuid.PcdConOutRow
--
2.16.1.windows.1
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [PATCH 11/12] EmulatorPkg/EmuFileSystem: Fix a bug that causes Close() assertion
2018-08-23 9:52 [PATCH 00/12] Add WinHost support in EmulatorPkg Ruiyu Ni
` (9 preceding siblings ...)
2018-08-23 9:52 ` [PATCH 10/12] EmulatorPkg/PlatformBds: Signal EndOfDxe in platform BDS Ruiyu Ni
@ 2018-08-23 9:52 ` Ruiyu Ni
2018-08-23 9:52 ` [PATCH 12/12] EmulatorPkg/DSC: Remove FS mapping to EDK Shell bin directory Ruiyu Ni
2018-08-23 9:56 ` [PATCH 00/12] Add WinHost support in EmulatorPkg Ni, Ruiyu
12 siblings, 0 replies; 14+ messages in thread
From: Ruiyu Ni @ 2018-08-23 9:52 UTC (permalink / raw)
To: edk2-devel; +Cc: Hao Wu, Andrew Fish
The root cause is when a file is opened through File.Open(), the
private data for the File is not allocated, so when later
when File.Close() is called, the signature check in CR() causes
the assertion.
The private data for the File is allocated properly when the file
is opened from FS.OpenVolume().
The patch also fixes a minor issue that wrongly assigns
revision number to File.
Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Ruiyu Ni <ruiyu.ni@intel.com>
Cc: Hao Wu <hao.a.wu@intel.com>
Cc: Andrew Fish <afish@intel.com>
---
.../EmuSimpleFileSystemDxe/EmuSimpleFileSystem.c | 33 +++++++++++++++++++---
1 file changed, 29 insertions(+), 4 deletions(-)
diff --git a/EmulatorPkg/EmuSimpleFileSystemDxe/EmuSimpleFileSystem.c b/EmulatorPkg/EmuSimpleFileSystemDxe/EmuSimpleFileSystem.c
index 4709f7a46f..b5e19bb840 100644
--- a/EmulatorPkg/EmuSimpleFileSystemDxe/EmuSimpleFileSystem.c
+++ b/EmulatorPkg/EmuSimpleFileSystemDxe/EmuSimpleFileSystem.c
@@ -4,7 +4,7 @@
environment variables. The variables must be visible to the Microsoft*
Developer Studio for them to work.
-Copyright (c) 2006 - 2011, Intel Corporation. All rights reserved.<BR>
+Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
Portions copyright (c) 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
@@ -51,7 +51,10 @@ EmuSimpleFileSystemOpen (
IN UINT64 Attributes
)
{
+ EFI_STATUS Status;
+ EFI_TPL OldTpl;
EMU_EFI_FILE_PRIVATE *PrivateFile;
+ EMU_EFI_FILE_PRIVATE *NewPrivateFile;
//
// Check for obvious invalid parameters.
@@ -81,9 +84,29 @@ EmuSimpleFileSystemOpen (
return EFI_INVALID_PARAMETER;
}
- PrivateFile = EMU_EFI_FILE_PRIVATE_DATA_FROM_THIS (This);
+ OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
+
+ PrivateFile = EMU_EFI_FILE_PRIVATE_DATA_FROM_THIS (This);
+
+ NewPrivateFile = AllocateCopyPool (sizeof (EMU_EFI_FILE_PRIVATE), PrivateFile);
+ if (NewPrivateFile == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto Done;
+ }
+
- return PrivateFile->Io->Open (PrivateFile->Io, NewHandle, FileName, OpenMode, Attributes);
+ Status = PrivateFile->Io->Open (PrivateFile->Io, &NewPrivateFile->Io, FileName, OpenMode, Attributes);
+ if (!EFI_ERROR (Status)) {
+ *NewHandle = &NewPrivateFile->EfiFile;
+ } else {
+ *NewHandle = NULL;
+ FreePool (NewPrivateFile);
+ }
+
+Done:
+ gBS->RestoreTPL (OldTpl);
+
+ return Status;
}
@@ -508,7 +531,9 @@ EmuSimpleFileSystemOpenVolume (
PrivateFile->Signature = EMU_EFI_FILE_PRIVATE_SIGNATURE;
PrivateFile->IoThunk = Private->IoThunk;
PrivateFile->SimpleFileSystem = This;
- PrivateFile->EfiFile.Revision = EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_REVISION;
+
+ ZeroMem (&PrivateFile->EfiFile, sizeof (PrivateFile->EfiFile));
+ PrivateFile->EfiFile.Revision = EFI_FILE_PROTOCOL_REVISION;
PrivateFile->EfiFile.Open = EmuSimpleFileSystemOpen;
PrivateFile->EfiFile.Close = EmuSimpleFileSystemClose;
PrivateFile->EfiFile.Delete = EmuSimpleFileSystemDelete;
--
2.16.1.windows.1
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [PATCH 12/12] EmulatorPkg/DSC: Remove FS mapping to EDK Shell bin directory
2018-08-23 9:52 [PATCH 00/12] Add WinHost support in EmulatorPkg Ruiyu Ni
` (10 preceding siblings ...)
2018-08-23 9:52 ` [PATCH 11/12] EmulatorPkg/EmuFileSystem: Fix a bug that causes Close() assertion Ruiyu Ni
@ 2018-08-23 9:52 ` Ruiyu Ni
2018-08-23 9:56 ` [PATCH 00/12] Add WinHost support in EmulatorPkg Ni, Ruiyu
12 siblings, 0 replies; 14+ messages in thread
From: Ruiyu Ni @ 2018-08-23 9:52 UTC (permalink / raw)
To: edk2-devel; +Cc: Hao Wu, Andrew Fish
The EDK Shell is end of line so the FS mapping to old EDK
Shell bin directory is better to be removed.
Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Ruiyu Ni <ruiyu.ni@intel.com>
Cc: Hao Wu <hao.a.wu@intel.com>
Cc: Andrew Fish <afish@intel.com>
---
EmulatorPkg/EmulatorPkg.dsc | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/EmulatorPkg/EmulatorPkg.dsc b/EmulatorPkg/EmulatorPkg.dsc
index 67812f754b..9f9f7d318d 100644
--- a/EmulatorPkg/EmulatorPkg.dsc
+++ b/EmulatorPkg/EmulatorPkg.dsc
@@ -223,7 +223,7 @@ [PcdsFixedAtBuild]
# For a CD-ROM/DVD use L"diag.dmg:RO:2048"
gEmulatorPkgTokenSpaceGuid.PcdEmuVirtualDisk|L"disk.dmg:FW"
gEmulatorPkgTokenSpaceGuid.PcdEmuGop|L"GOP Window"
- gEmulatorPkgTokenSpaceGuid.PcdEmuFileSystem|L".!../../../../EdkShellBinPkg/Bin"
+ gEmulatorPkgTokenSpaceGuid.PcdEmuFileSystem|L"."
gEmulatorPkgTokenSpaceGuid.PcdEmuSerialPort|L"/dev/ttyS0"
gEmulatorPkgTokenSpaceGuid.PcdEmuNetworkInterface|L"en0"
--
2.16.1.windows.1
^ permalink raw reply related [flat|nested] 14+ messages in thread
* Re: [PATCH 00/12] Add WinHost support in EmulatorPkg
2018-08-23 9:52 [PATCH 00/12] Add WinHost support in EmulatorPkg Ruiyu Ni
` (11 preceding siblings ...)
2018-08-23 9:52 ` [PATCH 12/12] EmulatorPkg/DSC: Remove FS mapping to EDK Shell bin directory Ruiyu Ni
@ 2018-08-23 9:56 ` Ni, Ruiyu
12 siblings, 0 replies; 14+ messages in thread
From: Ni, Ruiyu @ 2018-08-23 9:56 UTC (permalink / raw)
To: Ni, Ruiyu, edk2-devel@lists.01.org
Hello,
Please ignore this patch sets.
I used the wrong mail address.
Thanks/Ray
> -----Original Message-----
> From: edk2-devel <edk2-devel-bounces@lists.01.org> On Behalf Of Ruiyu Ni
> Sent: Thursday, August 23, 2018 5:52 PM
> To: edk2-devel@lists.01.org
> Subject: [edk2] [PATCH 00/12] Add WinHost support in EmulatorPkg
>
> REF: https://bugzilla.tianocore.org/show_bug.cgi?id=1112
>
> The patch sets add WinHost support (Nt32) in EmulatorPkg.
> 3 EmulatorPkg common issues were found and fixed.
> Other 9 patches are to step-by-step enable the WinHost.
>
> Ruiyu Ni (12):
> EmulatorPkg/ThunkProtocolList: Fix VS build failure
> EmulatorPkg/Win: Add Windows host support
> EmulatorPkg/Win: Enable source level debugging
> EmulatorPkg/Win: Enable native OS console as firmware console
> EmulatorPkg/Win: Add input/output support
> EmulatorPkg/Win: Add timer and interrupt support
> EmulatorPkg/Win: Add RTC support
> EmulatorPkg/Win: Add SimpleFileSystem support
> EmulatorPkg/Win: Add BlockIo support
> EmulatorPkg/PlatformBds: Signal EndOfDxe in platform BDS
> EmulatorPkg/EmuFileSystem: Fix a bug that causes Close() assertion
> EmulatorPkg/DSC: Remove FS mapping to EDK Shell bin directory
>
> .../EmuSimpleFileSystemDxe/EmuSimpleFileSystem.c | 33 +-
> EmulatorPkg/EmulatorPkg.dsc | 17 +-
> EmulatorPkg/Library/EmuBdsLib/BdsPlatform.c | 4 +-
> EmulatorPkg/Library/EmuBdsLib/BdsPlatform.h | 4 +-
> EmulatorPkg/Library/EmuBdsLib/EmuBdsLib.inf | 5 +-
> .../Library/ThunkProtocolList/ThunkProtocolList.c | 4 +-
> EmulatorPkg/Win/Host/WinBlockIo.c | 563 +++++
> EmulatorPkg/Win/Host/WinFileSystem.c | 2409
> ++++++++++++++++++++
> EmulatorPkg/Win/Host/WinGop.h | 204 ++
> EmulatorPkg/Win/Host/WinGopInput.c | 417 ++++
> EmulatorPkg/Win/Host/WinGopScreen.c | 872 +++++++
> EmulatorPkg/Win/Host/WinHost.c | 947 ++++++++
> EmulatorPkg/Win/Host/WinHost.h | 209 ++
> EmulatorPkg/Win/Host/WinHost.inf | 107 +
> EmulatorPkg/Win/Host/WinInclude.h | 75 +
> EmulatorPkg/Win/Host/WinMemoryAllocationLib.c | 178 ++
> EmulatorPkg/Win/Host/WinThunk.c | 577 +++++
> 17 files changed, 6614 insertions(+), 11 deletions(-) create mode 100644
> EmulatorPkg/Win/Host/WinBlockIo.c create mode 100644
> EmulatorPkg/Win/Host/WinFileSystem.c
> create mode 100644 EmulatorPkg/Win/Host/WinGop.h create mode 100644
> EmulatorPkg/Win/Host/WinGopInput.c
> create mode 100644 EmulatorPkg/Win/Host/WinGopScreen.c
> 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
>
> --
> 2.16.1.windows.1
>
> _______________________________________________
> edk2-devel mailing list
> edk2-devel@lists.01.org
> https://lists.01.org/mailman/listinfo/edk2-devel
^ permalink raw reply [flat|nested] 14+ messages in thread