\r
Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>\r
(C) Copyright 2016 Hewlett Packard Enterprise Development LP<BR>\r
-This program and the accompanying materials\r
-are licensed and made available under the terms and conditions of the BSD License\r
-which accompanies this distribution. The full text of the license may be found at\r
-http://opensource.org/licenses/bsd-license.php\r
-\r
-THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
-WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+SPDX-License-Identifier: BSD-2-Clause-Patent\r
**/\r
\r
#include "WinHost.h"\r
#define SE_TIME_ZONE_NAME TEXT("SeTimeZonePrivilege")\r
#endif\r
\r
+//\r
+// The growth size for array of module handle entries\r
+//\r
+#define MAX_PDB_NAME_TO_MOD_HANDLE_ARRAY_SIZE 0x100\r
+\r
+//\r
+// Module handle entry structure\r
+//\r
+typedef struct {\r
+ CHAR8 *PdbPointer;\r
+ VOID *ModHandle;\r
+} PDB_NAME_TO_MOD_HANDLE;\r
+\r
+//\r
+// An Array to hold the module handles\r
+//\r
+PDB_NAME_TO_MOD_HANDLE *mPdbNameModHandleArray = NULL;\r
+UINTN mPdbNameModHandleArraySize = 0;\r
+\r
//\r
// Default information about where the FD is located.\r
// This array gets filled in with information from PcdWinNtFirmwareVolume\r
MemorySizeStr = (CHAR16 *) PcdGetPtr (PcdEmuMemorySize);\r
FirmwareVolumesStr = (CHAR16 *) PcdGetPtr (PcdEmuFirmwareVolume);\r
\r
- SecPrint ("\nEDK II WIN Host Emulation Environment from http://www.tianocore.org/edk2/\n");\r
+ SecPrint ("\n\rEDK II WIN Host Emulation Environment from http://www.tianocore.org/edk2/\n\r");\r
\r
//\r
// Determine the first thread available to this process.\r
//\r
AddThunkPpi (EFI_PEI_PPI_DESCRIPTOR_PPI, &gEmuThunkPpiGuid, &mSecEmuThunkPpi);\r
\r
+ //\r
+ // Emulator Bus Driver Thunks\r
+ //\r
+ AddThunkProtocol (&mWinNtWndThunkIo, (CHAR16 *)PcdGetPtr (PcdEmuGop), TRUE);\r
+ AddThunkProtocol (&mWinNtFileSystemThunkIo, (CHAR16 *)PcdGetPtr (PcdEmuFileSystem), TRUE);\r
+ AddThunkProtocol (&mWinNtBlockIoThunkIo, (CHAR16 *)PcdGetPtr (PcdEmuVirtualDisk), TRUE);\r
+\r
//\r
// Allocate space for gSystemMemory Array\r
//\r
gSystemMemoryCount = CountSeparatorsInString (MemorySizeStr, '!') + 1;\r
gSystemMemory = calloc (gSystemMemoryCount, sizeof (NT_SYSTEM_MEMORY));\r
if (gSystemMemory == NULL) {\r
- SecPrint ("ERROR : Can not allocate memory for %S. Exiting.\n", MemorySizeStr);\r
+ SecPrint ("ERROR : Can not allocate memory for %S. Exiting.\n\r", MemorySizeStr);\r
exit (1);\r
}\r
\r
gFdInfoCount = CountSeparatorsInString (FirmwareVolumesStr, '!') + 1;\r
gFdInfo = calloc (gFdInfoCount, sizeof (NT_FD_INFO));\r
if (gFdInfo == NULL) {\r
- SecPrint ("ERROR : Can not allocate memory for %S. Exiting.\n", FirmwareVolumesStr);\r
+ SecPrint ("ERROR : Can not allocate memory for %S. Exiting.\n\r", FirmwareVolumesStr);\r
exit (1);\r
}\r
//\r
// Setup Boot Mode.\r
//\r
- SecPrint (" BootMode 0x%02x\n", PcdGet32 (PcdEmuBootMode));\r
+ SecPrint (" BootMode 0x%02x\n\r", PcdGet32 (PcdEmuBootMode));\r
\r
//\r
// Allocate 128K memory to emulate temp memory for PEI.\r
TemporaryRamSize = TEMPORARY_RAM_SIZE;\r
TemporaryRam = VirtualAlloc (NULL, (SIZE_T) (TemporaryRamSize), MEM_COMMIT, PAGE_EXECUTE_READWRITE);\r
if (TemporaryRam == NULL) {\r
- SecPrint ("ERROR : Can not allocate enough space for SecStack\n");\r
+ SecPrint ("ERROR : Can not allocate enough space for SecStack\n\r");\r
exit (1);\r
}\r
- SetMemN (TemporaryRam, TemporaryRamSize, PcdGet32 (PcdInitValueInTempStack));\r
+ SetMem32 (TemporaryRam, TemporaryRamSize, PcdGet32 (PcdInitValueInTempStack));\r
\r
- SecPrint (" OS Emulator passing in %u KB of temp RAM at 0x%08lx to SEC\n",\r
+ SecPrint (" OS Emulator passing in %u KB of temp RAM at 0x%08lx to SEC\n\r",\r
TemporaryRamSize / SIZE_1KB,\r
TemporaryRam\r
);\r
&Size\r
);\r
if (EFI_ERROR (Status)) {\r
- SecPrint ("ERROR : Could not allocate PeiServicesTablePage @ %p\n", EmuMagicPage);\r
+ SecPrint ("ERROR : Could not allocate PeiServicesTablePage @ %p\n\r", EmuMagicPage);\r
return EFI_DEVICE_ERROR;\r
}\r
}\r
//\r
FileNamePtr = AllocateCopyPool (StrSize (FirmwareVolumesStr), FirmwareVolumesStr);\r
if (FileNamePtr == NULL) {\r
- SecPrint ("ERROR : Can not allocate memory for firmware volume string\n");\r
+ SecPrint ("ERROR : Can not allocate memory for firmware volume string\n\r");\r
exit (1);\r
}\r
\r
&gFdInfo[Index].Size\r
);\r
if (EFI_ERROR (Status)) {\r
- SecPrint ("ERROR : Can not open Firmware Device File %S (0x%X). Exiting.\n", FileName, Status);\r
+ SecPrint ("ERROR : Can not open Firmware Device File %S (0x%X). Exiting.\n\r", FileName, Status);\r
exit (1);\r
}\r
\r
- SecPrint (" FD loaded from %S\n", FileName);\r
+ SecPrint (" FD loaded from %S", FileName);\r
\r
if (SecFile == NULL) {\r
//\r
}\r
}\r
\r
- SecPrint ("\n");\r
+ SecPrint ("\n\r");\r
}\r
//\r
// Calculate memory regions and store the information in the gSystemMemory\r
MemorySizeStr = MemorySizeStr + Index1 + 1;\r
}\r
\r
- SecPrint ("\n");\r
+ SecPrint ("\n\r");\r
\r
//\r
// Hand off to SEC Core\r
// If we get here, then the SEC Core returned. This is an error as SEC should\r
// always hand off to PEI Core and then on to DXE Core.\r
//\r
- SecPrint ("ERROR : SEC returned\n");\r
+ SecPrint ("ERROR : SEC returned\n\r");\r
exit (1);\r
}\r
\r
// Transfer control to the SEC Core\r
//\r
SwitchStack (\r
- (SWITCH_STACK_ENTRY_POINT)SecCoreEntryPoint,\r
+ (SWITCH_STACK_ENTRY_POINT)(UINTN)SecCoreEntryPoint,\r
SecCoreData,\r
GetThunkPpiList (),\r
TopOfStack\r
return Count;\r
}\r
\r
+/**\r
+ Store the ModHandle in an array indexed by the Pdb File name.\r
+ The ModHandle is needed to unload the image.\r
+ @param ImageContext - Input data returned from PE Laoder Library. Used to find the\r
+ .PDB file name of the PE Image.\r
+ @param ModHandle - Returned from LoadLibraryEx() and stored for call to\r
+ FreeLibrary().\r
+ @return return EFI_SUCCESS when ModHandle was stored.\r
+--*/\r
+EFI_STATUS\r
+AddModHandle (\r
+ IN PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext,\r
+ IN VOID *ModHandle\r
+ )\r
+\r
+{\r
+ UINTN Index;\r
+ PDB_NAME_TO_MOD_HANDLE *Array;\r
+ UINTN PreviousSize;\r
+ PDB_NAME_TO_MOD_HANDLE *TempArray;\r
+ HANDLE Handle;\r
+ UINTN Size;\r
+\r
+ //\r
+ // Return EFI_ALREADY_STARTED if this DLL has already been loaded\r
+ //\r
+ Array = mPdbNameModHandleArray;\r
+ for (Index = 0; Index < mPdbNameModHandleArraySize; Index++, Array++) {\r
+ if (Array->PdbPointer != NULL && Array->ModHandle == ModHandle) {\r
+ return EFI_ALREADY_STARTED;\r
+ }\r
+ }\r
+\r
+ Array = mPdbNameModHandleArray;\r
+ for (Index = 0; Index < mPdbNameModHandleArraySize; Index++, Array++) {\r
+ if (Array->PdbPointer == NULL) {\r
+ //\r
+ // Make a copy of the stirng and store the ModHandle\r
+ //\r
+ Handle = GetProcessHeap ();\r
+ Size = AsciiStrLen (ImageContext->PdbPointer) + 1;\r
+ Array->PdbPointer = HeapAlloc ( Handle, HEAP_ZERO_MEMORY, Size);\r
+ ASSERT (Array->PdbPointer != NULL);\r
+\r
+ AsciiStrCpyS (Array->PdbPointer, Size, ImageContext->PdbPointer);\r
+ Array->ModHandle = ModHandle;\r
+ return EFI_SUCCESS;\r
+ }\r
+ }\r
+\r
+ //\r
+ // No free space in mPdbNameModHandleArray so grow it by\r
+ // MAX_PDB_NAME_TO_MOD_HANDLE_ARRAY_SIZE entires.\r
+ //\r
+ PreviousSize = mPdbNameModHandleArraySize * sizeof (PDB_NAME_TO_MOD_HANDLE);\r
+ mPdbNameModHandleArraySize += MAX_PDB_NAME_TO_MOD_HANDLE_ARRAY_SIZE;\r
+ //\r
+ // re-allocate a new buffer and copy the old values to the new locaiton.\r
+ //\r
+ TempArray = HeapAlloc (GetProcessHeap (),\r
+ HEAP_ZERO_MEMORY,\r
+ mPdbNameModHandleArraySize * sizeof (PDB_NAME_TO_MOD_HANDLE)\r
+ );\r
+\r
+ CopyMem ((VOID *) (UINTN) TempArray, (VOID *) (UINTN)mPdbNameModHandleArray, PreviousSize);\r
+\r
+ HeapFree (GetProcessHeap (), 0, mPdbNameModHandleArray);\r
+\r
+ mPdbNameModHandleArray = TempArray;\r
+ if (mPdbNameModHandleArray == NULL) {\r
+ ASSERT (FALSE);\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ return AddModHandle (ImageContext, ModHandle);\r
+}\r
+\r
+/**\r
+ Return the ModHandle and delete the entry in the array.\r
+ @param ImageContext - Input data returned from PE Laoder Library. Used to find the\r
+ .PDB file name of the PE Image.\r
+ @return\r
+ ModHandle - ModHandle assoicated with ImageContext is returned\r
+ NULL - No ModHandle associated with ImageContext\r
+**/\r
+VOID *\r
+RemoveModHandle (\r
+ IN PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext\r
+ )\r
+{\r
+ UINTN Index;\r
+ PDB_NAME_TO_MOD_HANDLE *Array;\r
+\r
+ if (ImageContext->PdbPointer == NULL) {\r
+ //\r
+ // If no PDB pointer there is no ModHandle so return NULL\r
+ //\r
+ return NULL;\r
+ }\r
+\r
+ Array = mPdbNameModHandleArray;\r
+ for (Index = 0; Index < mPdbNameModHandleArraySize; Index++, Array++) {\r
+ if ((Array->PdbPointer != NULL) && (AsciiStrCmp(Array->PdbPointer, ImageContext->PdbPointer) == 0)) {\r
+ //\r
+ // If you find a match return it and delete the entry\r
+ //\r
+ HeapFree (GetProcessHeap (), 0, Array->PdbPointer);\r
+ Array->PdbPointer = NULL;\r
+ return Array->ModHandle;\r
+ }\r
+ }\r
+\r
+ return NULL;\r
+}\r
\r
VOID\r
EFIAPI\r
IN OUT PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext\r
)\r
{\r
+ EFI_STATUS Status;\r
VOID *DllEntryPoint;\r
CHAR16 *DllFileName;\r
HMODULE Library;\r
ASSERT (ImageContext != NULL);\r
//\r
// If we load our own PE COFF images the Windows debugger can not source\r
- // level debug our code. If a valid PDB pointer exists usw it to load\r
+ // level debug our code. If a valid PDB pointer exists use it to load\r
// the *.dll file as a library using Windows* APIs. This allows\r
// source level debug. The image is still loaded and relocated\r
// in the Framework memory space like on a real system (by the code above),\r
}\r
\r
if ((Library != NULL) && (DllEntryPoint != NULL)) {\r
- ImageContext->EntryPoint = (EFI_PHYSICAL_ADDRESS) (UINTN) DllEntryPoint;\r
- SecPrint ("LoadLibraryEx (%S,\n NULL, DONT_RESOLVE_DLL_REFERENCES)\n", DllFileName);\r
+ Status = AddModHandle (ImageContext, Library);\r
+ if (Status == EFI_ALREADY_STARTED) {\r
+ //\r
+ // If the DLL has already been loaded before, then this instance of the DLL can not be debugged.\r
+ //\r
+ ImageContext->PdbPointer = NULL;\r
+ SecPrint ("WARNING: DLL already loaded. No source level debug %S.\n\r", DllFileName);\r
+ } else {\r
+ //\r
+ // This DLL is not already loaded, so source level debugging is supported.\r
+ //\r
+ ImageContext->EntryPoint = (EFI_PHYSICAL_ADDRESS) (UINTN) DllEntryPoint;\r
+ SecPrint ("LoadLibraryEx (\n\r %S,\n\r NULL, DONT_RESOLVE_DLL_REFERENCES)\n\r", DllFileName);\r
+ }\r
} else {\r
- SecPrint ("WARNING: No source level debug %S. \n", DllFileName);\r
+ SecPrint ("WARNING: No source level debug %S. \n\r", DllFileName);\r
}\r
\r
free (DllFileName);\r
VOID\r
EFIAPI\r
PeCoffLoaderUnloadImageExtraAction (\r
- IN PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext\r
+ IN PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext\r
)\r
{\r
+ VOID *ModHandle;\r
+\r
ASSERT (ImageContext != NULL);\r
-}\r
\r
+ ModHandle = RemoveModHandle (ImageContext);\r
+ if (ModHandle != NULL) {\r
+ FreeLibrary (ModHandle);\r
+ SecPrint ("FreeLibrary (\n\r %s)\n\r", ImageContext->PdbPointer);\r
+ } else {\r
+ SecPrint ("WARNING: Unload image without source level debug\n\r");\r
+ }\r
+}\r
\r
VOID\r
_ModuleEntryPoint (\r