]> git.proxmox.com Git - mirror_edk2.git/blobdiff - MdeModulePkg/Core/Dxe/Image/Image.c
MdeModulePkg/DxeCore: invoke the emulator protocol for foreign images
[mirror_edk2.git] / MdeModulePkg / Core / Dxe / Image / Image.c
index 3587460990d3435fea6ed32db8667be0fe38a349..7ff1dfec5173ff5128895ccbdbbc2952d8a5491d 100644 (file)
@@ -1,29 +1,17 @@
-/*++\r
+/** @file\r
+  Core image handling services to load and unload PeImage.\r
 \r
-Copyright (c) 2006 - 2007, Intel Corporation\r
-All rights reserved. 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
+Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>\r
+SPDX-License-Identifier: BSD-2-Clause-Patent\r
 \r
-THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
-WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+**/\r
 \r
-Module Name:\r
+#include "DxeMain.h"\r
+#include "Image.h"\r
 \r
-  Image.c\r
-\r
-Abstract:\r
-\r
-  Core image handling services\r
-\r
---*/\r
-\r
-#include <DxeMain.h>\r
 //\r
 // Module Globals\r
 //\r
-\r
 LOADED_IMAGE_PRIVATE_DATA  *mCurrentImage = NULL;\r
 \r
 LOAD_PE32_IMAGE_PRIVATE_DATA  mLoadPe32PrivateData = {\r
@@ -35,6 +23,15 @@ LOAD_PE32_IMAGE_PRIVATE_DATA  mLoadPe32PrivateData = {
   }\r
 };\r
 \r
+typedef struct {\r
+  LIST_ENTRY                            Link;\r
+  EDKII_PECOFF_IMAGE_EMULATOR_PROTOCOL  *Emulator;\r
+  UINT16                                MachineType;\r
+} EMULATOR_ENTRY;\r
+\r
+STATIC LIST_ENTRY                       mAvailableEmulators;\r
+STATIC EFI_EVENT                        mPeCoffEmuProtocolRegistrationEvent;\r
+STATIC VOID                             *mPeCoffEmuProtocolNotifyRegistration;\r
 \r
 //\r
 // This code is needed to build the Image handle for the DXE Core\r
@@ -73,31 +70,126 @@ LOADED_IMAGE_PRIVATE_DATA mCorePrivateImage  = {
   NULL,                       // JumpContext\r
   0,                          // Machine\r
   NULL,                       // Ebc\r
+  NULL,                       // PeCoffEmu\r
   NULL,                       // RuntimeData\r
   NULL                        // LoadedImageDevicePath\r
 };\r
+//\r
+// The field is define for Loading modules at fixed address feature to tracker the PEI code\r
+// memory range usage. It is a bit mapped array in which every bit indicates the correspoding memory page\r
+// available or not.\r
+//\r
+GLOBAL_REMOVE_IF_UNREFERENCED    UINT64                *mDxeCodeMemoryRangeUsageBitMap=NULL;\r
+\r
+typedef struct {\r
+  UINT16  MachineType;\r
+  CHAR16  *MachineTypeName;\r
+} MACHINE_TYPE_INFO;\r
+\r
+//\r
+// EBC machine is not listed in this table, because EBC is in the default supported scopes of other machine type.\r
+//\r
+GLOBAL_REMOVE_IF_UNREFERENCED MACHINE_TYPE_INFO  mMachineTypeInfo[] = {\r
+  {EFI_IMAGE_MACHINE_IA32,           L"IA32"},\r
+  {EFI_IMAGE_MACHINE_IA64,           L"IA64"},\r
+  {EFI_IMAGE_MACHINE_X64,            L"X64"},\r
+  {EFI_IMAGE_MACHINE_ARMTHUMB_MIXED, L"ARM"},\r
+  {EFI_IMAGE_MACHINE_AARCH64,        L"AARCH64"}\r
+};\r
 \r
+UINT16 mDxeCoreImageMachineType = 0;\r
 \r
-EFI_STATUS\r
-CoreInitializeImageServices (\r
-  IN  VOID *HobStart\r
+/**\r
+ Return machine type name.\r
+\r
+ @param MachineType The machine type\r
+\r
+ @return machine type name\r
+**/\r
+CHAR16 *\r
+GetMachineTypeName (\r
+  UINT16 MachineType\r
   )\r
-/*++\r
+{\r
+  UINTN  Index;\r
 \r
-Routine Description:\r
+  for (Index = 0; Index < sizeof(mMachineTypeInfo)/sizeof(mMachineTypeInfo[0]); Index++) {\r
+    if (mMachineTypeInfo[Index].MachineType == MachineType) {\r
+      return mMachineTypeInfo[Index].MachineTypeName;\r
+    }\r
+  }\r
 \r
-  Add the Image Services to EFI Boot Services Table and install the protocol\r
-  interfaces for this image.\r
+  return L"<Unknown>";\r
+}\r
+\r
+/**\r
+  Notification event handler registered by CoreInitializeImageServices () to\r
+  keep track of which PE/COFF image emulators are available.\r
+\r
+  @param  Event          The Event that is being processed, not used.\r
+  @param  Context        Event Context, not used.\r
+\r
+**/\r
+STATIC\r
+VOID\r
+EFIAPI\r
+PeCoffEmuProtocolNotify (\r
+  IN  EFI_EVENT       Event,\r
+  IN  VOID            *Context\r
+  )\r
+{\r
+  EFI_STATUS          Status;\r
+  UINTN               BufferSize;\r
+  EFI_HANDLE          EmuHandle;\r
+  EMULATOR_ENTRY      *Entry;\r
 \r
-Arguments:\r
+  EmuHandle = NULL;\r
 \r
-  HobStart        - The HOB to initialize\r
+  while (TRUE) {\r
+    BufferSize = sizeof (EmuHandle);\r
+    Status = CoreLocateHandle (\r
+               ByRegisterNotify,\r
+               NULL,\r
+               mPeCoffEmuProtocolNotifyRegistration,\r
+               &BufferSize,\r
+               &EmuHandle\r
+               );\r
+    if (EFI_ERROR (Status)) {\r
+      //\r
+      // If no more notification events exit\r
+      //\r
+      return;\r
+    }\r
+\r
+    Entry = AllocateZeroPool (sizeof (*Entry));\r
+    ASSERT (Entry != NULL);\r
+\r
+    Status = CoreHandleProtocol (\r
+               EmuHandle,\r
+               &gEdkiiPeCoffImageEmulatorProtocolGuid,\r
+               (VOID **)&Entry->Emulator\r
+               );\r
+    ASSERT_EFI_ERROR (Status);\r
+\r
+    Entry->MachineType = Entry->Emulator->MachineType;\r
+\r
+    InsertTailList (&mAvailableEmulators, &Entry->Link);\r
+  }\r
+}\r
+\r
+/**\r
+  Add the Image Services to EFI Boot Services Table and install the protocol\r
+  interfaces for this image.\r
 \r
-Returns:\r
+  @param  HobStart                The HOB to initialize\r
 \r
-  Status code.\r
+  @return Status code.\r
 \r
---*/\r
+**/\r
+EFI_STATUS\r
+CoreInitializeImageServices (\r
+  IN  VOID *HobStart\r
+  )\r
 {\r
   EFI_STATUS                        Status;\r
   LOADED_IMAGE_PRIVATE_DATA         *Image;\r
@@ -105,6 +197,7 @@ Returns:
   UINT64                            DxeCoreImageLength;\r
   VOID                              *DxeCoreEntryPoint;\r
   EFI_PEI_HOB_POINTERS              DxeCoreHob;\r
+\r
   //\r
   // Searching for image hob\r
   //\r
@@ -124,6 +217,7 @@ Returns:
   DxeCoreImageLength      = DxeCoreHob.MemoryAllocationModule->MemoryAllocationHeader.MemoryLength;\r
   DxeCoreEntryPoint       = (VOID *) (UINTN) DxeCoreHob.MemoryAllocationModule->EntryPoint;\r
   gDxeCoreFileName        = &DxeCoreHob.MemoryAllocationModule->ModuleName;\r
+\r
   //\r
   // Initialize the fields for an internal driver\r
   //\r
@@ -153,64 +247,345 @@ Returns:
   //\r
   // Fill in DXE globals\r
   //\r
+  mDxeCoreImageMachineType = PeCoffLoaderGetMachineType (Image->Info.ImageBase);\r
   gDxeCoreImageHandle = Image->Handle;\r
   gDxeCoreLoadedImage = &Image->Info;\r
 \r
   //\r
-  // Export DXE Core PE Loader functionality\r
+  // Create the PE/COFF emulator protocol registration event\r
   //\r
-  return CoreInstallProtocolInterface (\r
-           &mLoadPe32PrivateData.Handle,\r
-           &gEfiLoadPeImageProtocolGuid,\r
-           EFI_NATIVE_INTERFACE,\r
-           &mLoadPe32PrivateData.Pe32Image\r
-           );\r
+  Status = CoreCreateEvent (\r
+             EVT_NOTIFY_SIGNAL,\r
+             TPL_CALLBACK,\r
+             PeCoffEmuProtocolNotify,\r
+             NULL,\r
+             &mPeCoffEmuProtocolRegistrationEvent\r
+             );\r
+  ASSERT_EFI_ERROR(Status);\r
+\r
+  //\r
+  // Register for protocol notifications on this event\r
+  //\r
+  Status = CoreRegisterProtocolNotify (\r
+             &gEdkiiPeCoffImageEmulatorProtocolGuid,\r
+             mPeCoffEmuProtocolRegistrationEvent,\r
+             &mPeCoffEmuProtocolNotifyRegistration\r
+             );\r
+  ASSERT_EFI_ERROR(Status);\r
+\r
+  InitializeListHead (&mAvailableEmulators);\r
+\r
+  if (FeaturePcdGet (PcdFrameworkCompatibilitySupport)) {\r
+    //\r
+    // Export DXE Core PE Loader functionality for backward compatibility.\r
+    //\r
+    Status = CoreInstallProtocolInterface (\r
+               &mLoadPe32PrivateData.Handle,\r
+               &gEfiLoadPeImageProtocolGuid,\r
+               EFI_NATIVE_INTERFACE,\r
+               &mLoadPe32PrivateData.Pe32Image\r
+               );\r
+  }\r
+\r
+  ProtectUefiImage (&Image->Info, Image->LoadedImageDevicePath);\r
+\r
+  return Status;\r
 }\r
 \r
+/**\r
+  Read image file (specified by UserHandle) into user specified buffer with specified offset\r
+  and length.\r
+\r
+  @param  UserHandle             Image file handle\r
+  @param  Offset                 Offset to the source file\r
+  @param  ReadSize               For input, pointer of size to read; For output,\r
+                                 pointer of size actually read.\r
+  @param  Buffer                 Buffer to write into\r
+\r
+  @retval EFI_SUCCESS            Successfully read the specified part of file\r
+                                 into buffer.\r
+\r
+**/\r
 EFI_STATUS\r
-CoreLoadPeImage (\r
-  IN BOOLEAN                     BootPolicy,  \r
-  IN VOID                        *Pe32Handle,\r
-  IN LOADED_IMAGE_PRIVATE_DATA   *Image,\r
-  IN EFI_PHYSICAL_ADDRESS        DstBuffer    OPTIONAL,\r
-  OUT EFI_PHYSICAL_ADDRESS       *EntryPoint  OPTIONAL,\r
-  IN  UINT32                     Attribute\r
+EFIAPI\r
+CoreReadImageFile (\r
+  IN     VOID    *UserHandle,\r
+  IN     UINTN   Offset,\r
+  IN OUT UINTN   *ReadSize,\r
+  OUT    VOID    *Buffer\r
   )\r
-/*++\r
+{\r
+  UINTN               EndPosition;\r
+  IMAGE_FILE_HANDLE  *FHand;\r
+\r
+  if (UserHandle == NULL || ReadSize == NULL || Buffer == NULL) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
 \r
-Routine Description:\r
+  if (MAX_ADDRESS - Offset < *ReadSize) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
 \r
-  Loads, relocates, and invokes a PE/COFF image\r
+  FHand = (IMAGE_FILE_HANDLE  *)UserHandle;\r
+  ASSERT (FHand->Signature == IMAGE_FILE_HANDLE_SIGNATURE);\r
+\r
+  //\r
+  // Move data from our local copy of the file\r
+  //\r
+  EndPosition = Offset + *ReadSize;\r
+  if (EndPosition > FHand->SourceSize) {\r
+    *ReadSize = (UINT32)(FHand->SourceSize - Offset);\r
+  }\r
+  if (Offset >= FHand->SourceSize) {\r
+      *ReadSize = 0;\r
+  }\r
+\r
+  CopyMem (Buffer, (CHAR8 *)FHand->Source + Offset, *ReadSize);\r
+  return EFI_SUCCESS;\r
+}\r
+/**\r
+  To check memory usage bit map array to figure out if the memory range the image will be loaded in is available or not. If\r
+  memory range is available, the function will mark the corresponding bits to 1 which indicates the memory range is used.\r
+  The function is only invoked when load modules at fixed address feature is enabled.\r
 \r
-Arguments:\r
-  BootPolicy       - If TRUE, indicates that the request originates from the boot manager,\r
-                     and that the boot manager is attempting to load FilePath as a boot selection.\r
-  Pe32Handle       - The handle of PE32 image\r
-  Image            - PE image to be loaded\r
-  DstBuffer        - The buffer to store the image\r
-  EntryPoint       - A pointer to the entry point\r
-  Attribute        - The bit mask of attributes to set for the load PE image\r
+  @param  ImageBase                The base address the image will be loaded at.\r
+  @param  ImageSize                The size of the image\r
 \r
-Returns:\r
+  @retval EFI_SUCCESS              The memory range the image will be loaded in is available\r
+  @retval EFI_NOT_FOUND            The memory range the image will be loaded in is not available\r
+**/\r
+EFI_STATUS\r
+CheckAndMarkFixLoadingMemoryUsageBitMap (\r
+  IN  EFI_PHYSICAL_ADDRESS          ImageBase,\r
+  IN  UINTN                         ImageSize\r
+  )\r
+{\r
+   UINT32                             DxeCodePageNumber;\r
+   UINT64                             DxeCodeSize;\r
+   EFI_PHYSICAL_ADDRESS               DxeCodeBase;\r
+   UINTN                              BaseOffsetPageNumber;\r
+   UINTN                              TopOffsetPageNumber;\r
+   UINTN                              Index;\r
+   //\r
+   // The DXE code range includes RuntimeCodePage range and Boot time code range.\r
+   //\r
+   DxeCodePageNumber = PcdGet32(PcdLoadFixAddressRuntimeCodePageNumber);\r
+   DxeCodePageNumber += PcdGet32(PcdLoadFixAddressBootTimeCodePageNumber);\r
+   DxeCodeSize       = EFI_PAGES_TO_SIZE(DxeCodePageNumber);\r
+   DxeCodeBase       =  gLoadModuleAtFixAddressConfigurationTable.DxeCodeTopAddress - DxeCodeSize;\r
+\r
+   //\r
+   // If the memory usage bit map is not initialized,  do it. Every bit in the array\r
+   // indicate the status of the corresponding memory page, available or not\r
+   //\r
+   if (mDxeCodeMemoryRangeUsageBitMap == NULL) {\r
+     mDxeCodeMemoryRangeUsageBitMap = AllocateZeroPool(((DxeCodePageNumber/64) + 1)*sizeof(UINT64));\r
+   }\r
+   //\r
+   // If the Dxe code memory range is not allocated or the bit map array allocation failed, return EFI_NOT_FOUND\r
+   //\r
+   if (!gLoadFixedAddressCodeMemoryReady || mDxeCodeMemoryRangeUsageBitMap == NULL) {\r
+     return EFI_NOT_FOUND;\r
+   }\r
+   //\r
+   // Test the memory range for loading the image in the DXE code range.\r
+   //\r
+   if (gLoadModuleAtFixAddressConfigurationTable.DxeCodeTopAddress <  ImageBase + ImageSize ||\r
+       DxeCodeBase >  ImageBase) {\r
+     return EFI_NOT_FOUND;\r
+   }\r
+   //\r
+   // Test if the memory is avalaible or not.\r
+   //\r
+   BaseOffsetPageNumber = EFI_SIZE_TO_PAGES((UINT32)(ImageBase - DxeCodeBase));\r
+   TopOffsetPageNumber  = EFI_SIZE_TO_PAGES((UINT32)(ImageBase + ImageSize - DxeCodeBase));\r
+   for (Index = BaseOffsetPageNumber; Index < TopOffsetPageNumber; Index ++) {\r
+     if ((mDxeCodeMemoryRangeUsageBitMap[Index / 64] & LShiftU64(1, (Index % 64))) != 0) {\r
+       //\r
+       // This page is already used.\r
+       //\r
+       return EFI_NOT_FOUND;\r
+     }\r
+   }\r
+\r
+   //\r
+   // Being here means the memory range is available.  So mark the bits for the memory range\r
+   //\r
+   for (Index = BaseOffsetPageNumber; Index < TopOffsetPageNumber; Index ++) {\r
+     mDxeCodeMemoryRangeUsageBitMap[Index / 64] |= LShiftU64(1, (Index % 64));\r
+   }\r
+   return  EFI_SUCCESS;\r
+}\r
+/**\r
+\r
+  Get the fixed loading address from image header assigned by build tool. This function only be called\r
+  when Loading module at Fixed address feature enabled.\r
+\r
+  @param  ImageContext              Pointer to the image context structure that describes the PE/COFF\r
+                                    image that needs to be examined by this function.\r
+  @retval EFI_SUCCESS               An fixed loading address is assigned to this image by build tools .\r
+  @retval EFI_NOT_FOUND             The image has no assigned fixed loading address.\r
+\r
+**/\r
+EFI_STATUS\r
+GetPeCoffImageFixLoadingAssignedAddress(\r
+  IN OUT PE_COFF_LOADER_IMAGE_CONTEXT  *ImageContext\r
+  )\r
+{\r
+   UINTN                              SectionHeaderOffset;\r
+   EFI_STATUS                         Status;\r
+   EFI_IMAGE_SECTION_HEADER           SectionHeader;\r
+   EFI_IMAGE_OPTIONAL_HEADER_UNION    *ImgHdr;\r
+   UINT16                             Index;\r
+   UINTN                              Size;\r
+   UINT16                             NumberOfSections;\r
+   IMAGE_FILE_HANDLE                  *Handle;\r
+   UINT64                             ValueInSectionHeader;\r
+\r
+\r
+   Status = EFI_NOT_FOUND;\r
+\r
+   //\r
+   // Get PeHeader pointer\r
+   //\r
+   Handle = (IMAGE_FILE_HANDLE*)ImageContext->Handle;\r
+   ImgHdr = (EFI_IMAGE_OPTIONAL_HEADER_UNION *)((CHAR8* )Handle->Source + ImageContext->PeCoffHeaderOffset);\r
+   SectionHeaderOffset = ImageContext->PeCoffHeaderOffset +\r
+                         sizeof (UINT32) +\r
+                         sizeof (EFI_IMAGE_FILE_HEADER) +\r
+                         ImgHdr->Pe32.FileHeader.SizeOfOptionalHeader;\r
+   NumberOfSections = ImgHdr->Pe32.FileHeader.NumberOfSections;\r
+\r
+   //\r
+   // Get base address from the first section header that doesn't point to code section.\r
+   //\r
+   for (Index = 0; Index < NumberOfSections; Index++) {\r
+     //\r
+     // Read section header from file\r
+     //\r
+     Size = sizeof (EFI_IMAGE_SECTION_HEADER);\r
+     Status = ImageContext->ImageRead (\r
+                              ImageContext->Handle,\r
+                              SectionHeaderOffset,\r
+                              &Size,\r
+                              &SectionHeader\r
+                              );\r
+     if (EFI_ERROR (Status)) {\r
+       return Status;\r
+     }\r
+     if (Size != sizeof (EFI_IMAGE_SECTION_HEADER)) {\r
+       return EFI_NOT_FOUND;\r
+     }\r
+\r
+     Status = EFI_NOT_FOUND;\r
+\r
+     if ((SectionHeader.Characteristics & EFI_IMAGE_SCN_CNT_CODE) == 0) {\r
+       //\r
+       // Build tool will save the address in PointerToRelocations & PointerToLineNumbers fields in the first section header\r
+       // that doesn't point to code section in image header, as well as ImageBase field of image header. And there is an\r
+       // assumption that when the feature is enabled, if a module is assigned a loading address by tools, PointerToRelocations\r
+       // & PointerToLineNumbers fields should NOT be Zero, or else, these 2 fields should be set to Zero\r
+       //\r
+       ValueInSectionHeader = ReadUnaligned64((UINT64*)&SectionHeader.PointerToRelocations);\r
+       if (ValueInSectionHeader != 0) {\r
+         //\r
+         // When the feature is configured as load module at fixed absolute address, the ImageAddress field of ImageContext\r
+         // hold the spcified address. If the feature is configured as load module at fixed offset, ImageAddress hold an offset\r
+         // relative to top address\r
+         //\r
+         if ((INT64)PcdGet64(PcdLoadModuleAtFixAddressEnable) < 0) {\r
+            ImageContext->ImageAddress = gLoadModuleAtFixAddressConfigurationTable.DxeCodeTopAddress + (INT64)(INTN)ImageContext->ImageAddress;\r
+         }\r
+         //\r
+         // Check if the memory range is available.\r
+         //\r
+         Status = CheckAndMarkFixLoadingMemoryUsageBitMap (ImageContext->ImageAddress, (UINTN)(ImageContext->ImageSize + ImageContext->SectionAlignment));\r
+       }\r
+       break;\r
+     }\r
+     SectionHeaderOffset += sizeof (EFI_IMAGE_SECTION_HEADER);\r
+   }\r
+   DEBUG ((EFI_D_INFO|EFI_D_LOAD, "LOADING MODULE FIXED INFO: Loading module at fixed address 0x%11p. Status = %r \n", (VOID *)(UINTN)(ImageContext->ImageAddress), Status));\r
+   return Status;\r
+}\r
+\r
+/**\r
+  Decides whether a PE/COFF image can execute on this system, either natively\r
+  or via emulation/interpretation. In the latter case, the PeCoffEmu member\r
+  of the LOADED_IMAGE_PRIVATE_DATA struct pointer is populated with a pointer\r
+  to the emulator protocol that supports this image.\r
+\r
+  @param[in, out]   Image         LOADED_IMAGE_PRIVATE_DATA struct pointer\r
+\r
+  @retval           TRUE          The image is supported\r
+  @retval           FALSE         The image is not supported\r
+\r
+**/\r
+STATIC\r
+BOOLEAN\r
+CoreIsImageTypeSupported (\r
+  IN OUT LOADED_IMAGE_PRIVATE_DATA  *Image\r
+  )\r
+{\r
+  LIST_ENTRY                        *Link;\r
+  EMULATOR_ENTRY                    *Entry;\r
 \r
-  EFI_SUCCESS          - The file was loaded, relocated, and invoked\r
+  for (Link = GetFirstNode (&mAvailableEmulators);\r
+       !IsNull (&mAvailableEmulators, Link);\r
+       Link = GetNextNode (&mAvailableEmulators, Link)) {\r
+\r
+    Entry = BASE_CR (Link, EMULATOR_ENTRY, Link);\r
+    if (Entry->MachineType != Image->ImageContext.Machine) {\r
+      continue;\r
+    }\r
 \r
-  EFI_OUT_OF_RESOURCES - There was not enough memory to load and relocate the PE/COFF file\r
+    if (Entry->Emulator->IsImageSupported (Entry->Emulator,\r
+                           Image->ImageContext.ImageType,\r
+                           Image->Info.FilePath)) {\r
+      Image->PeCoffEmu = Entry->Emulator;\r
+      return TRUE;\r
+    }\r
+  }\r
 \r
-  EFI_INVALID_PARAMETER - Invalid parameter\r
+  return EFI_IMAGE_MACHINE_TYPE_SUPPORTED (Image->ImageContext.Machine) ||\r
+         EFI_IMAGE_MACHINE_CROSS_TYPE_SUPPORTED (Image->ImageContext.Machine);\r
+}\r
 \r
-  EFI_BUFFER_TOO_SMALL  - Buffer for image is too small\r
+/**\r
+  Loads, relocates, and invokes a PE/COFF image\r
 \r
---*/\r
+  @param  BootPolicy              If TRUE, indicates that the request originates\r
+                                  from the boot manager, and that the boot\r
+                                  manager is attempting to load FilePath as a\r
+                                  boot selection.\r
+  @param  Pe32Handle              The handle of PE32 image\r
+  @param  Image                   PE image to be loaded\r
+  @param  DstBuffer               The buffer to store the image\r
+  @param  EntryPoint              A pointer to the entry point\r
+  @param  Attribute               The bit mask of attributes to set for the load\r
+                                  PE image\r
+\r
+  @retval EFI_SUCCESS             The file was loaded, relocated, and invoked\r
+  @retval EFI_OUT_OF_RESOURCES    There was not enough memory to load and\r
+                                  relocate the PE/COFF file\r
+  @retval EFI_INVALID_PARAMETER   Invalid parameter\r
+  @retval EFI_BUFFER_TOO_SMALL    Buffer for image is too small\r
+\r
+**/\r
+EFI_STATUS\r
+CoreLoadPeImage (\r
+  IN BOOLEAN                     BootPolicy,\r
+  IN VOID                        *Pe32Handle,\r
+  IN LOADED_IMAGE_PRIVATE_DATA   *Image,\r
+  IN EFI_PHYSICAL_ADDRESS        DstBuffer    OPTIONAL,\r
+  OUT EFI_PHYSICAL_ADDRESS       *EntryPoint  OPTIONAL,\r
+  IN  UINT32                     Attribute\r
+  )\r
 {\r
   EFI_STATUS                Status;\r
   BOOLEAN                   DstBufAlocated;\r
   UINTN                     Size;\r
-  UINTN                     LinkTimeBase;\r
-  EFI_TCG_PLATFORM_PROTOCOL *TcgPlatformProtocol;\r
-  IMAGE_FILE_HANDLE         *FHandle;\r
 \r
-  FHandle = NULL;\r
   ZeroMem (&Image->ImageContext, sizeof (Image->ImageContext));\r
 \r
   Image->ImageContext.Handle    = Pe32Handle;\r
@@ -224,14 +599,17 @@ Returns:
     return Status;\r
   }\r
 \r
-  if (!EFI_IMAGE_MACHINE_TYPE_SUPPORTED (Image->ImageContext.Machine)) {\r
+  if (!CoreIsImageTypeSupported (Image)) {\r
     //\r
     // The PE/COFF loader can support loading image types that can be executed.\r
-    // If we loaded an image type that we can not execute return EFI_UNSUPORTED.\r
+    // If we loaded an image type that we can not execute return EFI_UNSUPPORTED.\r
     //\r
+    DEBUG ((DEBUG_ERROR, "Image type %s can't be loaded on %s UEFI system.\n",\r
+      GetMachineTypeName (Image->ImageContext.Machine),\r
+      GetMachineTypeName (mDxeCoreImageMachineType)));\r
     return EFI_UNSUPPORTED;\r
   }\r
-  \r
+\r
   //\r
   // Set EFI memory type based on ImageType\r
   //\r
@@ -253,13 +631,9 @@ Returns:
     Image->ImageContext.ImageError = IMAGE_ERROR_INVALID_SUBSYSTEM;\r
     return EFI_UNSUPPORTED;\r
   }\r
-  //\r
-  // Get the image base address in the original PeImage.\r
-  //\r
-  LinkTimeBase = (UINTN) Image->ImageContext.ImageAddress;\r
 \r
   //\r
-  // Allocate memory of the correct memory type aligned on the required image boundry\r
+  // Allocate memory of the correct memory type aligned on the required image boundary\r
   //\r
   DstBufAlocated = FALSE;\r
   if (DstBuffer == 0) {\r
@@ -283,21 +657,43 @@ Returns:
     // no modules whose preferred load addresses are below 1MB.\r
     //\r
     Status = EFI_OUT_OF_RESOURCES;\r
-    if (Image->ImageContext.ImageAddress >= 0x100000 || Image->ImageContext.RelocationsStripped) {\r
-      Status = CoreAllocatePages (\r
-                 AllocateAddress,\r
-                 (EFI_MEMORY_TYPE) (Image->ImageContext.ImageCodeMemoryType),\r
-                 Image->NumberOfPages,\r
-                 &Image->ImageContext.ImageAddress\r
-                 );\r
-    }\r
-    if (EFI_ERROR (Status) && !Image->ImageContext.RelocationsStripped) {\r
-      Status = CoreAllocatePages (\r
-                 AllocateAnyPages,\r
-                 (EFI_MEMORY_TYPE) (Image->ImageContext.ImageCodeMemoryType),\r
-                 Image->NumberOfPages,\r
-                 &Image->ImageContext.ImageAddress\r
-                 );\r
+    //\r
+    // If Loading Module At Fixed Address feature is enabled, the module should be loaded to\r
+    // a specified address.\r
+    //\r
+    if (PcdGet64(PcdLoadModuleAtFixAddressEnable) != 0 ) {\r
+      Status = GetPeCoffImageFixLoadingAssignedAddress (&(Image->ImageContext));\r
+\r
+      if (EFI_ERROR (Status))  {\r
+          //\r
+          // If the code memory is not ready, invoke CoreAllocatePage with AllocateAnyPages to load the driver.\r
+          //\r
+          DEBUG ((EFI_D_INFO|EFI_D_LOAD, "LOADING MODULE FIXED ERROR: Loading module at fixed address failed since specified memory is not available.\n"));\r
+\r
+          Status = CoreAllocatePages (\r
+                     AllocateAnyPages,\r
+                     (EFI_MEMORY_TYPE) (Image->ImageContext.ImageCodeMemoryType),\r
+                     Image->NumberOfPages,\r
+                     &Image->ImageContext.ImageAddress\r
+                     );\r
+      }\r
+    } else {\r
+      if (Image->ImageContext.ImageAddress >= 0x100000 || Image->ImageContext.RelocationsStripped) {\r
+        Status = CoreAllocatePages (\r
+                   AllocateAddress,\r
+                   (EFI_MEMORY_TYPE) (Image->ImageContext.ImageCodeMemoryType),\r
+                   Image->NumberOfPages,\r
+                   &Image->ImageContext.ImageAddress\r
+                   );\r
+      }\r
+      if (EFI_ERROR (Status) && !Image->ImageContext.RelocationsStripped) {\r
+        Status = CoreAllocatePages (\r
+                   AllocateAnyPages,\r
+                   (EFI_MEMORY_TYPE) (Image->ImageContext.ImageCodeMemoryType),\r
+                   Image->NumberOfPages,\r
+                   &Image->ImageContext.ImageAddress\r
+                   );\r
+      }\r
     }\r
     if (EFI_ERROR (Status)) {\r
       return Status;\r
@@ -329,9 +725,11 @@ Returns:
   }\r
 \r
   Image->ImageBasePage = Image->ImageContext.ImageAddress;\r
-  Image->ImageContext.ImageAddress =\r
-      (Image->ImageContext.ImageAddress + Image->ImageContext.SectionAlignment - 1) &\r
-      ~((UINTN)Image->ImageContext.SectionAlignment - 1);\r
+  if (!Image->ImageContext.IsTeImage) {\r
+    Image->ImageContext.ImageAddress =\r
+        (Image->ImageContext.ImageAddress + Image->ImageContext.SectionAlignment - 1) &\r
+        ~((UINTN)Image->ImageContext.SectionAlignment - 1);\r
+  }\r
 \r
   //\r
   // Load the image from the file into the allocated memory\r
@@ -346,9 +744,9 @@ Returns:
   // is used to relocate the image when SetVirtualAddressMap() is called. The\r
   // relocation is done by the Runtime AP.\r
   //\r
-  if (Attribute & EFI_LOAD_PE_IMAGE_ATTRIBUTE_RUNTIME_REGISTRATION) {\r
+  if ((Attribute & EFI_LOAD_PE_IMAGE_ATTRIBUTE_RUNTIME_REGISTRATION) != 0) {\r
     if (Image->ImageContext.ImageType == EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER) {\r
-      Image->ImageContext.FixupData = CoreAllocateRuntimePool ((UINTN)(Image->ImageContext.FixupDataSize));\r
+      Image->ImageContext.FixupData = AllocateRuntimePool ((UINTN)(Image->ImageContext.FixupDataSize));\r
       if (Image->ImageContext.FixupData == NULL) {\r
         Status = EFI_OUT_OF_RESOURCES;\r
         goto Done;\r
@@ -356,29 +754,6 @@ Returns:
     }\r
   }\r
 \r
-  //\r
-  // Measure the image before applying fixup\r
-  //\r
-  Status = CoreLocateProtocol (\r
-             &gEfiTcgPlatformProtocolGuid,\r
-             NULL,\r
-             (VOID **) &TcgPlatformProtocol\r
-             );\r
-  if (!EFI_ERROR (Status)) {\r
-    FHandle = (IMAGE_FILE_HANDLE *) Image->ImageContext.Handle;\r
-    Status = TcgPlatformProtocol->MeasurePeImage (\r
-                                    BootPolicy,\r
-                                    (EFI_PHYSICAL_ADDRESS) (UINTN) FHandle->Source,\r
-                                    FHandle->SourceSize,\r
-                                    LinkTimeBase,\r
-                                    Image->ImageContext.ImageType,\r
-                                    Image->Info.DeviceHandle,\r
-                                    Image->Info.FilePath\r
-                                    );\r
-\r
-    ASSERT_EFI_ERROR (Status);\r
-  }\r
-\r
   //\r
   // Relocate the image in memory\r
   //\r
@@ -410,7 +785,8 @@ Returns:
     // Locate the EBC interpreter protocol\r
     //\r
     Status = CoreLocateProtocol (&gEfiEbcProtocolGuid, NULL, (VOID **)&Image->Ebc);\r
-    if (EFI_ERROR(Status)) {\r
+    if (EFI_ERROR(Status) || Image->Ebc == NULL) {\r
+      DEBUG ((DEBUG_LOAD | DEBUG_ERROR, "CoreLoadPeImage: There is no EBC interpreter for an EBC image.\n"));\r
       goto Done;\r
     }\r
 \r
@@ -430,12 +806,22 @@ Returns:
     Status = Image->Ebc->CreateThunk (\r
                            Image->Ebc,\r
                            Image->Handle,\r
-                           (VOID *)(UINTN)Image->ImageContext.EntryPoint,\r
-                           (VOID **)&Image->EntryPoint\r
+                           (VOID *)(UINTN) Image->ImageContext.EntryPoint,\r
+                           (VOID **) &Image->EntryPoint\r
                            );\r
     if (EFI_ERROR(Status)) {\r
       goto Done;\r
     }\r
+  } else if (Image->PeCoffEmu != NULL) {\r
+    Status = Image->PeCoffEmu->RegisterImage (Image->PeCoffEmu,\r
+                                 Image->ImageBasePage,\r
+                                 EFI_PAGES_TO_SIZE (Image->NumberOfPages),\r
+                                 &Image->EntryPoint);\r
+    if (EFI_ERROR (Status)) {\r
+      DEBUG ((DEBUG_LOAD | DEBUG_ERROR,\r
+        "CoreLoadPeImage: Failed to register foreign image with emulator.\n"));\r
+      goto Done;\r
+    }\r
   }\r
 \r
   //\r
@@ -446,12 +832,12 @@ Returns:
   Image->Info.ImageSize     = Image->ImageContext.ImageSize;\r
   Image->Info.ImageCodeType = (EFI_MEMORY_TYPE) (Image->ImageContext.ImageCodeMemoryType);\r
   Image->Info.ImageDataType = (EFI_MEMORY_TYPE) (Image->ImageContext.ImageDataMemoryType);\r
-  if (Attribute & EFI_LOAD_PE_IMAGE_ATTRIBUTE_RUNTIME_REGISTRATION) {\r
+  if ((Attribute & EFI_LOAD_PE_IMAGE_ATTRIBUTE_RUNTIME_REGISTRATION) != 0) {\r
     if (Image->ImageContext.ImageType == EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER) {\r
       //\r
       // Make a list off all the RT images so we can let the RT AP know about them.\r
       //\r
-      Image->RuntimeData = CoreAllocateRuntimePool (sizeof(EFI_RUNTIME_IMAGE_ENTRY));\r
+      Image->RuntimeData = AllocateRuntimePool (sizeof(EFI_RUNTIME_IMAGE_ENTRY));\r
       if (Image->RuntimeData == NULL) {\r
         goto Done;\r
       }\r
@@ -460,6 +846,7 @@ Returns:
       Image->RuntimeData->RelocationData = Image->ImageContext.FixupData;\r
       Image->RuntimeData->Handle         = Image->Handle;\r
       InsertTailList (&gRuntime->ImageHead, &Image->RuntimeData->Link);\r
+      InsertImageRecord (Image->RuntimeData);\r
     }\r
   }\r
 \r
@@ -479,36 +866,31 @@ Returns:
     UINTN Index;\r
     UINTN StartIndex;\r
     CHAR8 EfiFileName[256];\r
-    \r
-    if (Image->ImageContext.Machine != IMAGE_FILE_MACHINE_IA64) {\r
-      DEBUG ((EFI_D_INFO | EFI_D_LOAD, \r
-              "Loading driver at 0x%10p EntryPoint=0x%10p ", \r
-              (VOID *)(UINTN)Image->ImageContext.ImageAddress, \r
-              (VOID *)(UINTN)Image->ImageContext.EntryPoint));\r
-    } else {\r
-      //\r
-      // For IPF Image, the real entry point should be print.\r
-      //      \r
-      DEBUG ((EFI_D_INFO | EFI_D_LOAD, \r
-              "Loading driver at 0x%10p EntryPoint=0x%10p ", \r
-              (VOID *)(UINTN)Image->ImageContext.ImageAddress, \r
-              (VOID *)(UINTN)(*(UINT64 *)(UINTN)Image->ImageContext.EntryPoint)));\r
-    }\r
-    \r
+\r
+\r
+    DEBUG ((DEBUG_INFO | DEBUG_LOAD,\r
+           "Loading driver at 0x%11p EntryPoint=0x%11p ",\r
+           (VOID *)(UINTN) Image->ImageContext.ImageAddress,\r
+           FUNCTION_ENTRY_POINT (Image->ImageContext.EntryPoint)));\r
+\r
+\r
     //\r
-    // Print Module Name by Pdb file path\r
+    // Print Module Name by Pdb file path.\r
+    // Windows and Unix style file path are all trimmed correctly.\r
     //\r
     if (Image->ImageContext.PdbPointer != NULL) {\r
       StartIndex = 0;\r
       for (Index = 0; Image->ImageContext.PdbPointer[Index] != 0; Index++) {\r
-        if (Image->ImageContext.PdbPointer[Index] == '\\') {\r
+        if ((Image->ImageContext.PdbPointer[Index] == '\\') || (Image->ImageContext.PdbPointer[Index] == '/')) {\r
           StartIndex = Index + 1;\r
         }\r
       }\r
       //\r
       // Copy the PDB file name to our temporary string, and replace .pdb with .efi\r
+      // The PDB file name is limited in the range of 0~255.\r
+      // If the length is bigger than 255, trim the redudant characters to avoid overflow in array boundary.\r
       //\r
-      for (Index = 0; Index < sizeof (EfiFileName); Index++) {\r
+      for (Index = 0; Index < sizeof (EfiFileName) - 4; Index++) {\r
         EfiFileName[Index] = Image->ImageContext.PdbPointer[Index + StartIndex];\r
         if (EfiFileName[Index] == 0) {\r
           EfiFileName[Index] = '.';\r
@@ -521,9 +903,13 @@ Returns:
           break;\r
         }\r
       }\r
-      DEBUG ((EFI_D_INFO | EFI_D_LOAD, "%a", EfiFileName)); // &Image->ImageContext.PdbPointer[StartIndex]));\r
+\r
+      if (Index == sizeof (EfiFileName) - 4) {\r
+        EfiFileName[Index] = 0;\r
+      }\r
+      DEBUG ((DEBUG_INFO | DEBUG_LOAD, "%a", EfiFileName)); // &Image->ImageContext.PdbPointer[StartIndex]));\r
     }\r
-    DEBUG ((EFI_D_INFO | EFI_D_LOAD, "\n"));\r
+    DEBUG ((DEBUG_INFO | DEBUG_LOAD, "\n"));\r
 \r
   DEBUG_CODE_END ();\r
 \r
@@ -537,6 +923,8 @@ Done:
 \r
   if (DstBufAlocated) {\r
     CoreFreePages (Image->ImageContext.ImageAddress, Image->NumberOfPages);\r
+    Image->ImageContext.ImageAddress = 0;\r
+    Image->ImageBasePage = 0;\r
   }\r
 \r
   if (Image->ImageContext.FixupData != NULL) {\r
@@ -547,25 +935,19 @@ Done:
 }\r
 \r
 \r
-LOADED_IMAGE_PRIVATE_DATA *\r
-CoreLoadedImageInfo (\r
-  IN EFI_HANDLE  ImageHandle\r
-  )\r
-/*++\r
-\r
-Routine Description:\r
 \r
+/**\r
   Get the image's private data from its handle.\r
 \r
-Arguments:\r
-\r
-  ImageHandle     - The image handle\r
+  @param  ImageHandle             The image handle\r
 \r
-Returns:\r
+  @return Return the image private data associated with ImageHandle.\r
 \r
-  Return the image private data associated with ImageHandle.\r
-\r
---*/\r
+**/\r
+LOADED_IMAGE_PRIVATE_DATA *\r
+CoreLoadedImageInfo (\r
+  IN EFI_HANDLE  ImageHandle\r
+  )\r
 {\r
   EFI_STATUS                 Status;\r
   EFI_LOADED_IMAGE_PROTOCOL  *LoadedImage;\r
@@ -579,154 +961,437 @@ Returns:
   if (!EFI_ERROR (Status)) {\r
     Image = LOADED_IMAGE_PRIVATE_DATA_FROM_THIS (LoadedImage);\r
   } else {\r
-    DEBUG ((EFI_D_LOAD, "CoreLoadedImageInfo: Not an ImageHandle %x\n", ImageHandle));\r
+    DEBUG ((DEBUG_LOAD, "CoreLoadedImageInfo: Not an ImageHandle %p\n", ImageHandle));\r
     Image = NULL;\r
   }\r
 \r
   return Image;\r
 }\r
 \r
-STATIC\r
-EFI_STATUS\r
-CoreLoadImageCommon (\r
-  IN  BOOLEAN                          BootPolicy,\r
-  IN  EFI_HANDLE                       ParentImageHandle,\r
-  IN  EFI_DEVICE_PATH_PROTOCOL         *FilePath,\r
-  IN  VOID                             *SourceBuffer       OPTIONAL,\r
-  IN  UINTN                            SourceSize,\r
-  IN  EFI_PHYSICAL_ADDRESS             DstBuffer           OPTIONAL,\r
-  IN OUT UINTN                         *NumberOfPages      OPTIONAL,\r
-  OUT EFI_HANDLE                       *ImageHandle,\r
-  OUT EFI_PHYSICAL_ADDRESS             *EntryPoint         OPTIONAL,\r
-  IN  UINT32                           Attribute\r
-  )\r
-/*++\r
 \r
-Routine Description:\r
+/**\r
+  Unloads EFI image from memory.\r
 \r
-  Loads an EFI image into memory and returns a handle to the image.\r
+  @param  Image                   EFI image\r
+  @param  FreePage                Free allocated pages\r
 \r
-Arguments:\r
-\r
-  BootPolicy          - If TRUE, indicates that the request originates from the boot manager,\r
-                        and that the boot manager is attempting to load FilePath as a boot selection.\r
-  ParentImageHandle   - The caller's image handle.\r
-  FilePath            - The specific file path from which the image is loaded.\r
-  SourceBuffer        - If not NULL, a pointer to the memory location containing a copy of\r
-                        the image to be loaded.\r
-  SourceSize          - The size in bytes of SourceBuffer.\r
-  DstBuffer           - The buffer to store the image\r
-  NumberOfPages       - If not NULL, a pointer to the image's page number, if this number\r
-                        is not enough, return EFI_BUFFER_TOO_SMALL and this parameter contain\r
-                        the required number.\r
-  ImageHandle         - Pointer to the returned image handle that is created when the image\r
-                        is successfully loaded.\r
-  EntryPoint          - A pointer to the entry point\r
-  Attribute           - The bit mask of attributes to set for the load PE image\r
-\r
-Returns:\r
-\r
-  EFI_SUCCESS            - The image was loaded into memory.\r
-  EFI_NOT_FOUND          - The FilePath was not found.\r
-  EFI_INVALID_PARAMETER  - One of the parameters has an invalid value.\r
-  EFI_BUFFER_TOO_SMALL   - The buffer is too small\r
-  EFI_UNSUPPORTED        - The image type is not supported, or the device path cannot be\r
-                           parsed to locate the proper protocol for loading the file.\r
-  EFI_OUT_OF_RESOURCES   - Image was not loaded due to insufficient resources.\r
---*/\r
+**/\r
+VOID\r
+CoreUnloadAndCloseImage (\r
+  IN LOADED_IMAGE_PRIVATE_DATA  *Image,\r
+  IN BOOLEAN                    FreePage\r
+  )\r
 {\r
-  LOADED_IMAGE_PRIVATE_DATA  *Image;\r
-  LOADED_IMAGE_PRIVATE_DATA  *ParentImage;\r
-  IMAGE_FILE_HANDLE          FHand;\r
-  EFI_STATUS                 Status;\r
-  EFI_STATUS                 SecurityStatus;\r
-  EFI_HANDLE                 DeviceHandle;\r
-  UINT32                     AuthenticationStatus;\r
-  EFI_DEVICE_PATH_PROTOCOL   *OriginalFilePath;\r
-  EFI_DEVICE_PATH_PROTOCOL   *HandleFilePath;\r
-  UINTN                      FilePathSize;\r
+  EFI_STATUS                          Status;\r
+  UINTN                               HandleCount;\r
+  EFI_HANDLE                          *HandleBuffer;\r
+  UINTN                               HandleIndex;\r
+  EFI_GUID                            **ProtocolGuidArray;\r
+  UINTN                               ArrayCount;\r
+  UINTN                               ProtocolIndex;\r
+  EFI_OPEN_PROTOCOL_INFORMATION_ENTRY *OpenInfo;\r
+  UINTN                               OpenInfoCount;\r
+  UINTN                               OpenInfoIndex;\r
 \r
-  SecurityStatus = EFI_SUCCESS;\r
+  HandleBuffer = NULL;\r
+  ProtocolGuidArray = NULL;\r
 \r
-  ASSERT (gEfiCurrentTpl < TPL_NOTIFY);\r
-  ParentImage = NULL;\r
+  if (Image->Started) {\r
+    UnregisterMemoryProfileImage (Image);\r
+  }\r
 \r
-  //\r
-  // The caller must pass in a valid ParentImageHandle\r
-  //\r
-  if (ImageHandle == NULL || ParentImageHandle == NULL) {\r
-    return EFI_INVALID_PARAMETER;\r
+  UnprotectUefiImage (&Image->Info, Image->LoadedImageDevicePath);\r
+\r
+  if (Image->Ebc != NULL) {\r
+    //\r
+    // If EBC protocol exists we must perform cleanups for this image.\r
+    //\r
+    Image->Ebc->UnloadImage (Image->Ebc, Image->Handle);\r
   }\r
 \r
-  ParentImage = CoreLoadedImageInfo (ParentImageHandle);\r
-  if (ParentImage == NULL) {\r
-    DEBUG((EFI_D_LOAD|EFI_D_ERROR, "LoadImageEx: Parent handle not an image handle\n"));\r
-    return EFI_INVALID_PARAMETER;\r
+  if (Image->PeCoffEmu != NULL) {\r
+    //\r
+    // If the PE/COFF Emulator protocol exists we must unregister the image.\r
+    //\r
+    Image->PeCoffEmu->UnregisterImage (Image->PeCoffEmu, Image->ImageBasePage);\r
   }\r
 \r
   //\r
-  // Get simple read access to the source file\r
+  // Unload image, free Image->ImageContext->ModHandle\r
   //\r
-  OriginalFilePath = FilePath;\r
-  Status = CoreOpenImageFile (\r
-             BootPolicy,\r
-             SourceBuffer,\r
-             SourceSize,\r
-             &FilePath,\r
-             &DeviceHandle,\r
-             &FHand,\r
-             &AuthenticationStatus\r
-             );\r
-  if (Status == EFI_ALREADY_STARTED) {\r
-    Image = NULL;\r
-    goto Done;\r
-  } else if (EFI_ERROR (Status)) {\r
-    return Status;\r
-  }\r
+  PeCoffLoaderUnloadImage (&Image->ImageContext);\r
 \r
   //\r
-  // Verify the Authentication Status through the Security Architectural Protocol\r
+  // Free our references to the image handle\r
   //\r
-  if ((gSecurity != NULL) && (OriginalFilePath != NULL)) {\r
-    SecurityStatus = gSecurity->FileAuthenticationState (\r
-                                  gSecurity,\r
-                                  AuthenticationStatus,\r
-                                  OriginalFilePath\r
-                                  );\r
-    if (EFI_ERROR (SecurityStatus) && SecurityStatus != EFI_SECURITY_VIOLATION) {\r
-      Status = SecurityStatus;\r
-      Image = NULL;\r
-      goto Done;\r
+  if (Image->Handle != NULL) {\r
+\r
+    Status = CoreLocateHandleBuffer (\r
+               AllHandles,\r
+               NULL,\r
+               NULL,\r
+               &HandleCount,\r
+               &HandleBuffer\r
+               );\r
+    if (!EFI_ERROR (Status)) {\r
+      for (HandleIndex = 0; HandleIndex < HandleCount; HandleIndex++) {\r
+        Status = CoreProtocolsPerHandle (\r
+                   HandleBuffer[HandleIndex],\r
+                   &ProtocolGuidArray,\r
+                   &ArrayCount\r
+                   );\r
+        if (!EFI_ERROR (Status)) {\r
+          for (ProtocolIndex = 0; ProtocolIndex < ArrayCount; ProtocolIndex++) {\r
+            Status = CoreOpenProtocolInformation (\r
+                       HandleBuffer[HandleIndex],\r
+                       ProtocolGuidArray[ProtocolIndex],\r
+                       &OpenInfo,\r
+                       &OpenInfoCount\r
+                       );\r
+            if (!EFI_ERROR (Status)) {\r
+              for (OpenInfoIndex = 0; OpenInfoIndex < OpenInfoCount; OpenInfoIndex++) {\r
+                if (OpenInfo[OpenInfoIndex].AgentHandle == Image->Handle) {\r
+                  Status = CoreCloseProtocol (\r
+                             HandleBuffer[HandleIndex],\r
+                             ProtocolGuidArray[ProtocolIndex],\r
+                             Image->Handle,\r
+                             OpenInfo[OpenInfoIndex].ControllerHandle\r
+                             );\r
+                }\r
+              }\r
+              if (OpenInfo != NULL) {\r
+                CoreFreePool(OpenInfo);\r
+              }\r
+            }\r
+          }\r
+          if (ProtocolGuidArray != NULL) {\r
+            CoreFreePool(ProtocolGuidArray);\r
+          }\r
+        }\r
+      }\r
+      if (HandleBuffer != NULL) {\r
+        CoreFreePool (HandleBuffer);\r
+      }\r
+    }\r
+\r
+    CoreRemoveDebugImageInfoEntry (Image->Handle);\r
+\r
+    Status = CoreUninstallProtocolInterface (\r
+               Image->Handle,\r
+               &gEfiLoadedImageDevicePathProtocolGuid,\r
+               Image->LoadedImageDevicePath\r
+               );\r
+\r
+    Status = CoreUninstallProtocolInterface (\r
+               Image->Handle,\r
+               &gEfiLoadedImageProtocolGuid,\r
+               &Image->Info\r
+               );\r
+\r
+    if (Image->ImageContext.HiiResourceData != 0) {\r
+      Status = CoreUninstallProtocolInterface (\r
+                 Image->Handle,\r
+                 &gEfiHiiPackageListProtocolGuid,\r
+                 (VOID *) (UINTN) Image->ImageContext.HiiResourceData\r
+                 );\r
+    }\r
+\r
+  }\r
+\r
+  if (Image->RuntimeData != NULL) {\r
+    if (Image->RuntimeData->Link.ForwardLink != NULL) {\r
+      //\r
+      // Remove the Image from the Runtime Image list as we are about to Free it!\r
+      //\r
+      RemoveEntryList (&Image->RuntimeData->Link);\r
+      RemoveImageRecord (Image->RuntimeData);\r
+    }\r
+    CoreFreePool (Image->RuntimeData);\r
+  }\r
+\r
+  //\r
+  // Free the Image from memory\r
+  //\r
+  if ((Image->ImageBasePage != 0) && FreePage) {\r
+    CoreFreePages (Image->ImageBasePage, Image->NumberOfPages);\r
+  }\r
+\r
+  //\r
+  // Done with the Image structure\r
+  //\r
+  if (Image->Info.FilePath != NULL) {\r
+    CoreFreePool (Image->Info.FilePath);\r
+  }\r
+\r
+  if (Image->LoadedImageDevicePath != NULL) {\r
+    CoreFreePool (Image->LoadedImageDevicePath);\r
+  }\r
+\r
+  if (Image->FixupData != NULL) {\r
+    CoreFreePool (Image->FixupData);\r
+  }\r
+\r
+  CoreFreePool (Image);\r
+}\r
+\r
+\r
+/**\r
+  Loads an EFI image into memory and returns a handle to the image.\r
+\r
+  @param  BootPolicy              If TRUE, indicates that the request originates\r
+                                  from the boot manager, and that the boot\r
+                                  manager is attempting to load FilePath as a\r
+                                  boot selection.\r
+  @param  ParentImageHandle       The caller's image handle.\r
+  @param  FilePath                The specific file path from which the image is\r
+                                  loaded.\r
+  @param  SourceBuffer            If not NULL, a pointer to the memory location\r
+                                  containing a copy of the image to be loaded.\r
+  @param  SourceSize              The size in bytes of SourceBuffer.\r
+  @param  DstBuffer               The buffer to store the image\r
+  @param  NumberOfPages           If not NULL, it inputs a pointer to the page\r
+                                  number of DstBuffer and outputs a pointer to\r
+                                  the page number of the image. If this number is\r
+                                  not enough,  return EFI_BUFFER_TOO_SMALL and\r
+                                  this parameter contains the required number.\r
+  @param  ImageHandle             Pointer to the returned image handle that is\r
+                                  created when the image is successfully loaded.\r
+  @param  EntryPoint              A pointer to the entry point\r
+  @param  Attribute               The bit mask of attributes to set for the load\r
+                                  PE image\r
+\r
+  @retval EFI_SUCCESS             The image was loaded into memory.\r
+  @retval EFI_NOT_FOUND           The FilePath was not found.\r
+  @retval EFI_INVALID_PARAMETER   One of the parameters has an invalid value.\r
+  @retval EFI_BUFFER_TOO_SMALL    The buffer is too small\r
+  @retval EFI_UNSUPPORTED         The image type is not supported, or the device\r
+                                  path cannot be parsed to locate the proper\r
+                                  protocol for loading the file.\r
+  @retval EFI_OUT_OF_RESOURCES    Image was not loaded due to insufficient\r
+                                  resources.\r
+  @retval EFI_LOAD_ERROR          Image was not loaded because the image format was corrupt or not\r
+                                  understood.\r
+  @retval EFI_DEVICE_ERROR        Image was not loaded because the device returned a read error.\r
+  @retval EFI_ACCESS_DENIED       Image was not loaded because the platform policy prohibits the\r
+                                  image from being loaded. NULL is returned in *ImageHandle.\r
+  @retval EFI_SECURITY_VIOLATION  Image was loaded and an ImageHandle was created with a\r
+                                  valid EFI_LOADED_IMAGE_PROTOCOL. However, the current\r
+                                  platform policy specifies that the image should not be started.\r
+\r
+**/\r
+EFI_STATUS\r
+CoreLoadImageCommon (\r
+  IN  BOOLEAN                          BootPolicy,\r
+  IN  EFI_HANDLE                       ParentImageHandle,\r
+  IN  EFI_DEVICE_PATH_PROTOCOL         *FilePath,\r
+  IN  VOID                             *SourceBuffer       OPTIONAL,\r
+  IN  UINTN                            SourceSize,\r
+  IN  EFI_PHYSICAL_ADDRESS             DstBuffer           OPTIONAL,\r
+  IN OUT UINTN                         *NumberOfPages      OPTIONAL,\r
+  OUT EFI_HANDLE                       *ImageHandle,\r
+  OUT EFI_PHYSICAL_ADDRESS             *EntryPoint         OPTIONAL,\r
+  IN  UINT32                           Attribute\r
+  )\r
+{\r
+  LOADED_IMAGE_PRIVATE_DATA  *Image;\r
+  LOADED_IMAGE_PRIVATE_DATA  *ParentImage;\r
+  IMAGE_FILE_HANDLE          FHand;\r
+  EFI_STATUS                 Status;\r
+  EFI_STATUS                 SecurityStatus;\r
+  EFI_HANDLE                 DeviceHandle;\r
+  UINT32                     AuthenticationStatus;\r
+  EFI_DEVICE_PATH_PROTOCOL   *OriginalFilePath;\r
+  EFI_DEVICE_PATH_PROTOCOL   *HandleFilePath;\r
+  EFI_DEVICE_PATH_PROTOCOL   *InputFilePath;\r
+  EFI_DEVICE_PATH_PROTOCOL   *Node;\r
+  UINTN                      FilePathSize;\r
+  BOOLEAN                    ImageIsFromFv;\r
+  BOOLEAN                    ImageIsFromLoadFile;\r
+\r
+  SecurityStatus = EFI_SUCCESS;\r
+\r
+  ASSERT (gEfiCurrentTpl < TPL_NOTIFY);\r
+  ParentImage = NULL;\r
+\r
+  //\r
+  // The caller must pass in a valid ParentImageHandle\r
+  //\r
+  if (ImageHandle == NULL || ParentImageHandle == NULL) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  ParentImage = CoreLoadedImageInfo (ParentImageHandle);\r
+  if (ParentImage == NULL) {\r
+    DEBUG((DEBUG_LOAD|DEBUG_ERROR, "LoadImageEx: Parent handle not an image handle\n"));\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  ZeroMem (&FHand, sizeof (IMAGE_FILE_HANDLE));\r
+  FHand.Signature  = IMAGE_FILE_HANDLE_SIGNATURE;\r
+  OriginalFilePath = FilePath;\r
+  InputFilePath    = FilePath;\r
+  HandleFilePath   = FilePath;\r
+  DeviceHandle     = NULL;\r
+  Status           = EFI_SUCCESS;\r
+  AuthenticationStatus = 0;\r
+  ImageIsFromFv        = FALSE;\r
+  ImageIsFromLoadFile  = FALSE;\r
+\r
+  //\r
+  // If the caller passed a copy of the file, then just use it\r
+  //\r
+  if (SourceBuffer != NULL) {\r
+    FHand.Source     = SourceBuffer;\r
+    FHand.SourceSize = SourceSize;\r
+    Status = CoreLocateDevicePath (&gEfiDevicePathProtocolGuid, &HandleFilePath, &DeviceHandle);\r
+    if (EFI_ERROR (Status)) {\r
+      DeviceHandle = NULL;\r
+    }\r
+    if (SourceSize > 0) {\r
+      Status = EFI_SUCCESS;\r
+    } else {\r
+      Status = EFI_LOAD_ERROR;\r
+    }\r
+  } else {\r
+    if (FilePath == NULL) {\r
+      return EFI_INVALID_PARAMETER;\r
+    }\r
+\r
+    //\r
+    // Try to get the image device handle by checking the match protocol.\r
+    //\r
+    Node   = NULL;\r
+    Status = CoreLocateDevicePath (&gEfiFirmwareVolume2ProtocolGuid, &HandleFilePath, &DeviceHandle);\r
+    if (!EFI_ERROR (Status)) {\r
+      ImageIsFromFv = TRUE;\r
+    } else {\r
+      HandleFilePath = FilePath;\r
+      Status = CoreLocateDevicePath (&gEfiSimpleFileSystemProtocolGuid, &HandleFilePath, &DeviceHandle);\r
+      if (EFI_ERROR (Status)) {\r
+        if (!BootPolicy) {\r
+          HandleFilePath = FilePath;\r
+          Status = CoreLocateDevicePath (&gEfiLoadFile2ProtocolGuid, &HandleFilePath, &DeviceHandle);\r
+        }\r
+        if (EFI_ERROR (Status)) {\r
+          HandleFilePath = FilePath;\r
+          Status = CoreLocateDevicePath (&gEfiLoadFileProtocolGuid, &HandleFilePath, &DeviceHandle);\r
+          if (!EFI_ERROR (Status)) {\r
+            ImageIsFromLoadFile = TRUE;\r
+            Node = HandleFilePath;\r
+          }\r
+        }\r
+      }\r
+    }\r
+\r
+    //\r
+    // Get the source file buffer by its device path.\r
+    //\r
+    FHand.Source = GetFileBufferByFilePath (\r
+                      BootPolicy,\r
+                      FilePath,\r
+                      &FHand.SourceSize,\r
+                      &AuthenticationStatus\r
+                      );\r
+    if (FHand.Source == NULL) {\r
+      Status = EFI_NOT_FOUND;\r
+    } else {\r
+      FHand.FreeBuffer = TRUE;\r
+      if (ImageIsFromLoadFile) {\r
+        //\r
+        // LoadFile () may cause the device path of the Handle be updated.\r
+        //\r
+        OriginalFilePath = AppendDevicePath (DevicePathFromHandle (DeviceHandle), Node);\r
+      }\r
+    }\r
+  }\r
+\r
+  if (EFI_ERROR (Status)) {\r
+    Image = NULL;\r
+    goto Done;\r
+  }\r
+\r
+  if (gSecurity2 != NULL) {\r
+    //\r
+    // Verify File Authentication through the Security2 Architectural Protocol\r
+    //\r
+    SecurityStatus = gSecurity2->FileAuthentication (\r
+                                  gSecurity2,\r
+                                  OriginalFilePath,\r
+                                  FHand.Source,\r
+                                  FHand.SourceSize,\r
+                                  BootPolicy\r
+                                  );\r
+    if (!EFI_ERROR (SecurityStatus) && ImageIsFromFv) {\r
+      //\r
+      // When Security2 is installed, Security Architectural Protocol must be published.\r
+      //\r
+      ASSERT (gSecurity != NULL);\r
+\r
+      //\r
+      // Verify the Authentication Status through the Security Architectural Protocol\r
+      // Only on images that have been read using Firmware Volume protocol.\r
+      //\r
+      SecurityStatus = gSecurity->FileAuthenticationState (\r
+                                    gSecurity,\r
+                                    AuthenticationStatus,\r
+                                    OriginalFilePath\r
+                                    );\r
     }\r
+  } else if ((gSecurity != NULL) && (OriginalFilePath != NULL)) {\r
+    //\r
+    // Verify the Authentication Status through the Security Architectural Protocol\r
+    //\r
+    SecurityStatus = gSecurity->FileAuthenticationState (\r
+                                  gSecurity,\r
+                                  AuthenticationStatus,\r
+                                  OriginalFilePath\r
+                                  );\r
   }\r
 \r
+  //\r
+  // Check Security Status.\r
+  //\r
+  if (EFI_ERROR (SecurityStatus) && SecurityStatus != EFI_SECURITY_VIOLATION) {\r
+    if (SecurityStatus == EFI_ACCESS_DENIED) {\r
+      //\r
+      // Image was not loaded because the platform policy prohibits the image from being loaded.\r
+      // It's the only place we could meet EFI_ACCESS_DENIED.\r
+      //\r
+      *ImageHandle = NULL;\r
+    }\r
+    Status = SecurityStatus;\r
+    Image = NULL;\r
+    goto Done;\r
+  }\r
 \r
   //\r
   // Allocate a new image structure\r
   //\r
-  Image = CoreAllocateZeroBootServicesPool (sizeof(LOADED_IMAGE_PRIVATE_DATA));\r
+  Image = AllocateZeroPool (sizeof(LOADED_IMAGE_PRIVATE_DATA));\r
   if (Image == NULL) {\r
-    return EFI_OUT_OF_RESOURCES;\r
+    Status = EFI_OUT_OF_RESOURCES;\r
+    goto Done;\r
   }\r
 \r
   //\r
   // Pull out just the file portion of the DevicePath for the LoadedImage FilePath\r
   //\r
   FilePath = OriginalFilePath;\r
-  Status = CoreHandleProtocol (DeviceHandle, &gEfiDevicePathProtocolGuid, (VOID **)&HandleFilePath);\r
-  if (!EFI_ERROR (Status)) {\r
-    FilePathSize = CoreDevicePathSize (HandleFilePath) - sizeof(EFI_DEVICE_PATH_PROTOCOL);\r
-    FilePath = (EFI_DEVICE_PATH_PROTOCOL *) ( ((UINT8 *)FilePath) + FilePathSize );\r
+  if (DeviceHandle != NULL) {\r
+    Status = CoreHandleProtocol (DeviceHandle, &gEfiDevicePathProtocolGuid, (VOID **)&HandleFilePath);\r
+    if (!EFI_ERROR (Status)) {\r
+      FilePathSize = GetDevicePathSize (HandleFilePath) - sizeof(EFI_DEVICE_PATH_PROTOCOL);\r
+      FilePath = (EFI_DEVICE_PATH_PROTOCOL *) (((UINT8 *)FilePath) + FilePathSize );\r
+    }\r
   }\r
-\r
   //\r
   // Initialize the fields for an internal driver\r
   //\r
   Image->Signature         = LOADED_IMAGE_PRIVATE_DATA_SIGNATURE;\r
   Image->Info.SystemTable  = gDxeCoreST;\r
   Image->Info.DeviceHandle = DeviceHandle;\r
-  Image->Info.Revision     = EFI_LOADED_IMAGE_INFORMATION_REVISION;\r
-  Image->Info.FilePath     = CoreDuplicateDevicePath (FilePath);\r
+  Image->Info.Revision     = EFI_LOADED_IMAGE_PROTOCOL_REVISION;\r
+  Image->Info.FilePath     = DuplicateDevicePath (FilePath);\r
   Image->Info.ParentHandle = ParentImageHandle;\r
 \r
 \r
@@ -764,10 +1429,14 @@ Returns:
     goto Done;\r
   }\r
 \r
+  if (NumberOfPages != NULL) {\r
+    *NumberOfPages = Image->NumberOfPages;\r
+  }\r
+\r
   //\r
   // Register the image in the Debug Image Info Table if the attribute is set\r
   //\r
-  if (Attribute & EFI_LOAD_PE_IMAGE_ATTRIBUTE_DEBUG_IMAGE_INFO_TABLE_REGISTRATION) {\r
+  if ((Attribute & EFI_LOAD_PE_IMAGE_ATTRIBUTE_DEBUG_IMAGE_INFO_TABLE_REGISTRATION) != 0) {\r
     CoreNewDebugImageInfoEntry (EFI_DEBUG_IMAGE_INFO_TYPE_NORMAL, &Image->Info, Image->Handle);\r
   }\r
 \r
@@ -789,7 +1458,7 @@ Returns:
   // otherwise Loaded Image Device Path Protocol is installed with a NULL interface pointer.\r
   //\r
   if (OriginalFilePath != NULL) {\r
-    Image->LoadedImageDevicePath = CoreDuplicateDevicePath (OriginalFilePath);\r
+    Image->LoadedImageDevicePath = DuplicateDevicePath (OriginalFilePath);\r
   }\r
 \r
   //\r
@@ -805,6 +1474,22 @@ Returns:
     goto Done;\r
   }\r
 \r
+  //\r
+  // Install HII Package List Protocol onto the image handle\r
+  //\r
+  if (Image->ImageContext.HiiResourceData != 0) {\r
+    Status = CoreInstallProtocolInterface (\r
+               &Image->Handle,\r
+               &gEfiHiiPackageListProtocolGuid,\r
+               EFI_NATIVE_INTERFACE,\r
+               (VOID *) (UINTN) Image->ImageContext.HiiResourceData\r
+               );\r
+    if (EFI_ERROR (Status)) {\r
+      goto Done;\r
+    }\r
+  }\r
+  ProtectUefiImage (&Image->Info, Image->LoadedImageDevicePath);\r
+\r
   //\r
   // Success.  Return the image handle\r
   //\r
@@ -818,6 +1503,9 @@ Done:
   if (FHand.FreeBuffer) {\r
     CoreFreePool (FHand.Source);\r
   }\r
+  if (OriginalFilePath != InputFilePath) {\r
+    CoreFreePool (OriginalFilePath);\r
+  }\r
 \r
   //\r
   // There was an error.  If there's an Image structure, free it\r
@@ -825,17 +1513,59 @@ Done:
   if (EFI_ERROR (Status)) {\r
     if (Image != NULL) {\r
       CoreUnloadAndCloseImage (Image, (BOOLEAN)(DstBuffer == 0));\r
-      *ImageHandle = NULL;\r
+      Image = NULL;\r
     }\r
   } else if (EFI_ERROR (SecurityStatus)) {\r
     Status = SecurityStatus;\r
   }\r
 \r
+  //\r
+  // Track the return status from LoadImage.\r
+  //\r
+  if (Image != NULL) {\r
+    Image->LoadImageStatus = Status;\r
+  }\r
+\r
   return Status;\r
 }\r
 \r
 \r
 \r
+\r
+/**\r
+  Loads an EFI image into memory and returns a handle to the image.\r
+\r
+  @param  BootPolicy              If TRUE, indicates that the request originates\r
+                                  from the boot manager, and that the boot\r
+                                  manager is attempting to load FilePath as a\r
+                                  boot selection.\r
+  @param  ParentImageHandle       The caller's image handle.\r
+  @param  FilePath                The specific file path from which the image is\r
+                                  loaded.\r
+  @param  SourceBuffer            If not NULL, a pointer to the memory location\r
+                                  containing a copy of the image to be loaded.\r
+  @param  SourceSize              The size in bytes of SourceBuffer.\r
+  @param  ImageHandle             Pointer to the returned image handle that is\r
+                                  created when the image is successfully loaded.\r
+\r
+  @retval EFI_SUCCESS             The image was loaded into memory.\r
+  @retval EFI_NOT_FOUND           The FilePath was not found.\r
+  @retval EFI_INVALID_PARAMETER   One of the parameters has an invalid value.\r
+  @retval EFI_UNSUPPORTED         The image type is not supported, or the device\r
+                                  path cannot be parsed to locate the proper\r
+                                  protocol for loading the file.\r
+  @retval EFI_OUT_OF_RESOURCES    Image was not loaded due to insufficient\r
+                                  resources.\r
+  @retval EFI_LOAD_ERROR          Image was not loaded because the image format was corrupt or not\r
+                                  understood.\r
+  @retval EFI_DEVICE_ERROR        Image was not loaded because the device returned a read error.\r
+  @retval EFI_ACCESS_DENIED       Image was not loaded because the platform policy prohibits the\r
+                                  image from being loaded. NULL is returned in *ImageHandle.\r
+  @retval EFI_SECURITY_VIOLATION  Image was loaded and an ImageHandle was created with a\r
+                                  valid EFI_LOADED_IMAGE_PROTOCOL. However, the current\r
+                                  platform policy specifies that the image should not be started.\r
+\r
+**/\r
 EFI_STATUS\r
 EFIAPI\r
 CoreLoadImage (\r
@@ -846,37 +1576,11 @@ CoreLoadImage (
   IN UINTN                      SourceSize,\r
   OUT EFI_HANDLE                *ImageHandle\r
   )\r
-/*++\r
-\r
-Routine Description:\r
-\r
-  Loads an EFI image into memory and returns a handle to the image.\r
-\r
-Arguments:\r
-\r
-  BootPolicy          - If TRUE, indicates that the request originates from the boot manager,\r
-                        and that the boot manager is attempting to load FilePath as a boot selection.\r
-  ParentImageHandle   - The caller's image handle.\r
-  FilePath            - The specific file path from which the image is loaded.\r
-  SourceBuffer        - If not NULL, a pointer to the memory location containing a copy of\r
-                        the image to be loaded.\r
-  SourceSize          - The size in bytes of SourceBuffer.\r
-  ImageHandle         - Pointer to the returned image handle that is created when the image\r
-                        is successfully loaded.\r
-\r
-Returns:\r
-\r
-  EFI_SUCCESS            - The image was loaded into memory.\r
-  EFI_NOT_FOUND          - The FilePath was not found.\r
-  EFI_INVALID_PARAMETER  - One of the parameters has an invalid value.\r
-  EFI_UNSUPPORTED        - The image type is not supported, or the device path cannot be\r
-                           parsed to locate the proper protocol for loading the file.\r
-  EFI_OUT_OF_RESOURCES   - Image was not loaded due to insufficient resources.\r
---*/\r
 {\r
   EFI_STATUS    Status;\r
+  EFI_HANDLE    Handle;\r
 \r
-  PERF_START (NULL, "LoadImage", NULL, 0);\r
+  PERF_LOAD_IMAGE_BEGIN (NULL);\r
 \r
   Status = CoreLoadImageCommon (\r
              BootPolicy,\r
@@ -884,19 +1588,65 @@ Returns:
              FilePath,\r
              SourceBuffer,\r
              SourceSize,\r
-             (EFI_PHYSICAL_ADDRESS)NULL,\r
+             (EFI_PHYSICAL_ADDRESS) (UINTN) NULL,\r
              NULL,\r
              ImageHandle,\r
              NULL,\r
              EFI_LOAD_PE_IMAGE_ATTRIBUTE_RUNTIME_REGISTRATION | EFI_LOAD_PE_IMAGE_ATTRIBUTE_DEBUG_IMAGE_INFO_TABLE_REGISTRATION\r
              );\r
 \r
-  PERF_END (NULL, "LoadImage", NULL, 0);\r
+  Handle = NULL;\r
+  if (!EFI_ERROR (Status)) {\r
+    //\r
+    // ImageHandle will be valid only Status is success.\r
+    //\r
+    Handle = *ImageHandle;\r
+  }\r
+\r
+  PERF_LOAD_IMAGE_END (Handle);\r
 \r
   return Status;\r
 }\r
 \r
 \r
+\r
+/**\r
+  Loads an EFI image into memory and returns a handle to the image with extended parameters.\r
+\r
+  @param  This                    Calling context\r
+  @param  ParentImageHandle       The caller's image handle.\r
+  @param  FilePath                The specific file path from which the image is\r
+                                  loaded.\r
+  @param  SourceBuffer            If not NULL, a pointer to the memory location\r
+                                  containing a copy of the image to be loaded.\r
+  @param  SourceSize              The size in bytes of SourceBuffer.\r
+  @param  DstBuffer               The buffer to store the image.\r
+  @param  NumberOfPages           For input, specifies the space size of the\r
+                                  image by caller if not NULL. For output,\r
+                                  specifies the actual space size needed.\r
+  @param  ImageHandle             Image handle for output.\r
+  @param  EntryPoint              Image entry point for output.\r
+  @param  Attribute               The bit mask of attributes to set for the load\r
+                                  PE image.\r
+\r
+  @retval EFI_SUCCESS             The image was loaded into memory.\r
+  @retval EFI_NOT_FOUND           The FilePath was not found.\r
+  @retval EFI_INVALID_PARAMETER   One of the parameters has an invalid value.\r
+  @retval EFI_UNSUPPORTED         The image type is not supported, or the device\r
+                                  path cannot be parsed to locate the proper\r
+                                  protocol for loading the file.\r
+  @retval EFI_OUT_OF_RESOURCES    Image was not loaded due to insufficient\r
+                                  resources.\r
+  @retval EFI_LOAD_ERROR          Image was not loaded because the image format was corrupt or not\r
+                                  understood.\r
+  @retval EFI_DEVICE_ERROR        Image was not loaded because the device returned a read error.\r
+  @retval EFI_ACCESS_DENIED       Image was not loaded because the platform policy prohibits the\r
+                                  image from being loaded. NULL is returned in *ImageHandle.\r
+  @retval EFI_SECURITY_VIOLATION  Image was loaded and an ImageHandle was created with a\r
+                                  valid EFI_LOADED_IMAGE_PROTOCOL. However, the current\r
+                                  platform policy specifies that the image should not be started.\r
+\r
+**/\r
 EFI_STATUS\r
 EFIAPI\r
 CoreLoadImageEx (\r
@@ -911,38 +1661,13 @@ CoreLoadImageEx (
   OUT EFI_PHYSICAL_ADDRESS             *EntryPoint         OPTIONAL,\r
   IN  UINT32                           Attribute\r
   )\r
-/*++\r
-\r
-Routine Description:\r
+{\r
+  EFI_STATUS    Status;\r
+  EFI_HANDLE    Handle;\r
 \r
-  Loads an EFI image into memory and returns a handle to the image with extended parameters.\r
+  PERF_LOAD_IMAGE_BEGIN (NULL);\r
 \r
-Arguments:\r
-\r
-  This                - Calling context\r
-  ParentImageHandle   - The caller's image handle.\r
-  FilePath            - The specific file path from which the image is loaded.\r
-  SourceBuffer        - If not NULL, a pointer to the memory location containing a copy of\r
-                        the image to be loaded.\r
-  SourceSize          - The size in bytes of SourceBuffer.\r
-  DstBuffer           - The buffer to store the image.\r
-  NumberOfPages       - For input, specifies the space size of the image by caller if not NULL.\r
-                        For output, specifies the actual space size needed.\r
-  ImageHandle         - Image handle for output.\r
-  EntryPoint          - Image entry point for output.\r
-  Attribute           - The bit mask of attributes to set for the load PE image.\r
-\r
-Returns:\r
-\r
-  EFI_SUCCESS            - The image was loaded into memory.\r
-  EFI_NOT_FOUND          - The FilePath was not found.\r
-  EFI_INVALID_PARAMETER  - One of the parameters has an invalid value.\r
-  EFI_UNSUPPORTED        - The image type is not supported, or the device path cannot be\r
-                           parsed to locate the proper protocol for loading the file.\r
-  EFI_OUT_OF_RESOURCES   - Image was not loaded due to insufficient resources.\r
---*/\r
-{\r
-  return CoreLoadImageCommon (\r
+  Status = CoreLoadImageCommon (\r
            TRUE,\r
            ParentImageHandle,\r
            FilePath,\r
@@ -954,8 +1679,40 @@ Returns:
            EntryPoint,\r
            Attribute\r
            );\r
+\r
+  Handle = NULL;\r
+  if (!EFI_ERROR (Status)) {\r
+    //\r
+    // ImageHandle will be valid only Status is success.\r
+    //\r
+    Handle = *ImageHandle;\r
+  }\r
+\r
+  PERF_LOAD_IMAGE_END (Handle);\r
+\r
+  return Status;\r
 }\r
 \r
+\r
+/**\r
+  Transfer control to a loaded image's entry point.\r
+\r
+  @param  ImageHandle             Handle of image to be started.\r
+  @param  ExitDataSize            Pointer of the size to ExitData\r
+  @param  ExitData                Pointer to a pointer to a data buffer that\r
+                                  includes a Null-terminated string,\r
+                                  optionally followed by additional binary data.\r
+                                  The string is a description that the caller may\r
+                                  use to further indicate the reason for the\r
+                                  image's exit.\r
+\r
+  @retval EFI_INVALID_PARAMETER   Invalid parameter\r
+  @retval EFI_OUT_OF_RESOURCES    No enough buffer to allocate\r
+  @retval EFI_SECURITY_VIOLATION  The current platform policy specifies that the image should not be started.\r
+  @retval EFI_SUCCESS             Successfully transfer control to the image's\r
+                                  entry point.\r
+\r
+**/\r
 EFI_STATUS\r
 EFIAPI\r
 CoreStartImage (\r
@@ -963,48 +1720,39 @@ CoreStartImage (
   OUT UINTN      *ExitDataSize,\r
   OUT CHAR16     **ExitData  OPTIONAL\r
   )\r
-/*++\r
-\r
-Routine Description:\r
-\r
-  Transfer control to a loaded image's entry point.\r
-\r
-Arguments:\r
-\r
-  ImageHandle     - Handle of image to be started.\r
-\r
-  ExitDataSize    - Pointer of the size to ExitData\r
-\r
-  ExitData        - Pointer to a pointer to a data buffer that includes a Null-terminated\r
-                    Unicode string, optionally followed by additional binary data. The string\r
-                    is a description that the caller may use to further indicate the reason for\r
-                    the image's exit.\r
-\r
-Returns:\r
-\r
-  EFI_INVALID_PARAMETER     - Invalid parameter\r
-\r
-  EFI_OUT_OF_RESOURCES       - No enough buffer to allocate\r
-\r
-  EFI_SUCCESS               - Successfully transfer control to the image's entry point.\r
-\r
---*/\r
 {\r
   EFI_STATUS                    Status;\r
   LOADED_IMAGE_PRIVATE_DATA     *Image;\r
   LOADED_IMAGE_PRIVATE_DATA     *LastImage;\r
   UINT64                        HandleDatabaseKey;\r
   UINTN                         SetJumpFlag;\r
+  EFI_HANDLE                    Handle;\r
+\r
+  Handle = ImageHandle;\r
 \r
   Image = CoreLoadedImageInfo (ImageHandle);\r
-  if (Image == NULL_HANDLE  ||  Image->Started) {\r
+  if (Image == NULL  ||  Image->Started) {\r
     return EFI_INVALID_PARAMETER;\r
   }\r
+  if (EFI_ERROR (Image->LoadImageStatus)) {\r
+    return Image->LoadImageStatus;\r
+  }\r
 \r
   //\r
-  // Don't profile Objects or invalid start requests\r
+  // The image to be started must have the machine type supported by DxeCore.\r
   //\r
-  PERF_START (ImageHandle, START_IMAGE_TOK, NULL, 0);\r
+  if (!EFI_IMAGE_MACHINE_TYPE_SUPPORTED (Image->Machine) &&\r
+      Image->PeCoffEmu == NULL) {\r
+    //\r
+    // Do not ASSERT here, because image might be loaded via EFI_IMAGE_MACHINE_CROSS_TYPE_SUPPORTED\r
+    // But it can not be started.\r
+    //\r
+    DEBUG ((EFI_D_ERROR, "Image type %s can't be started ", GetMachineTypeName(Image->Machine)));\r
+    DEBUG ((EFI_D_ERROR, "on %s UEFI system.\n", GetMachineTypeName(mDxeCoreImageMachineType)));\r
+    return EFI_UNSUPPORTED;\r
+  }\r
+\r
+  PERF_START_IMAGE_BEGIN (Handle);\r
 \r
 \r
   //\r
@@ -1022,9 +1770,19 @@ Returns:
   // JumpContext must be aligned on a CPU specific boundary.\r
   // Overallocate the buffer and force the required alignment\r
   //\r
-  Image->JumpBuffer = CoreAllocateBootServicesPool (sizeof (BASE_LIBRARY_JUMP_BUFFER) + BASE_LIBRARY_JUMP_BUFFER_ALIGNMENT);\r
+  Image->JumpBuffer = AllocatePool (sizeof (BASE_LIBRARY_JUMP_BUFFER) + BASE_LIBRARY_JUMP_BUFFER_ALIGNMENT);\r
   if (Image->JumpBuffer == NULL) {\r
-    PERF_END (ImageHandle, START_IMAGE_TOK, NULL, 0);\r
+    //\r
+    // Image may be unloaded after return with failure,\r
+    // then ImageHandle may be invalid, so use NULL handle to record perf log.\r
+    //\r
+    PERF_START_IMAGE_END (NULL);\r
+\r
+    //\r
+    // Pop the current start image context\r
+    //\r
+    mCurrentImage = LastImage;\r
+\r
     return EFI_OUT_OF_RESOURCES;\r
   }\r
   Image->JumpContext = ALIGN_POINTER (Image->JumpBuffer, BASE_LIBRARY_JUMP_BUFFER_ALIGNMENT);\r
@@ -1034,7 +1792,8 @@ Returns:
   // The initial call to SetJump() must always return 0.\r
   // Subsequent calls to LongJump() cause a non-zero value to be returned by SetJump().\r
   //\r
-  if (!SetJumpFlag) {\r
+  if (SetJumpFlag == 0) {\r
+    RegisterMemoryProfileImage (Image, (Image->ImageContext.ImageType == EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION ? EFI_FV_FILETYPE_APPLICATION : EFI_FV_FILETYPE_DRIVER));\r
     //\r
     // Call the image's entry point\r
     //\r
@@ -1048,7 +1807,7 @@ Returns:
     //\r
     DEBUG_CODE_BEGIN ();\r
       if (EFI_ERROR (Image->Status)) {\r
-        DEBUG ((EFI_D_ERROR, "Error: Image at %10p start failed: %r\n", Image->Info.ImageBase, Image->Status));\r
+        DEBUG ((DEBUG_ERROR, "Error: Image at %11p start failed: %r\n", Image->Info.ImageBase, Image->Status));\r
       }\r
     DEBUG_CODE_END ();\r
 \r
@@ -1072,9 +1831,17 @@ Returns:
   mCurrentImage = LastImage;\r
 \r
   //\r
-  // Go connect any handles that were created or modified while the image executed.\r
+  // UEFI Specification - StartImage() - EFI 1.10 Extension\r
+  // To maintain compatibility with UEFI drivers that are written to the EFI\r
+  // 1.02 Specification, StartImage() must monitor the handle database before\r
+  // and after each image is started. If any handles are created or modified\r
+  // when an image is started, then EFI_BOOT_SERVICES.ConnectController() must\r
+  // be called with the Recursive parameter set to TRUE for each of the newly\r
+  // created or modified handles before StartImage() returns.\r
   //\r
-  CoreConnectHandlesByKey (HandleDatabaseKey);\r
+  if (Image->Type != EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION) {\r
+    CoreConnectHandlesByKey (HandleDatabaseKey);\r
+  }\r
 \r
   //\r
   // Handle the image's returned ExitData\r
@@ -1082,16 +1849,11 @@ Returns:
   DEBUG_CODE_BEGIN ();\r
     if (Image->ExitDataSize != 0 || Image->ExitData != NULL) {\r
 \r
-      DEBUG (\r
-        (EFI_D_LOAD,\r
-        "StartImage: ExitDataSize %d, ExitData %x",\r
-                            Image->ExitDataSize,\r
-        Image->ExitData)\r
-        );\r
+      DEBUG ((DEBUG_LOAD, "StartImage: ExitDataSize %d, ExitData %p", (UINT32)Image->ExitDataSize, Image->ExitData));\r
       if (Image->ExitData != NULL) {\r
-        DEBUG ((EFI_D_LOAD, " (%hs)", Image->ExitData));\r
+        DEBUG ((DEBUG_LOAD, " (%hs)", Image->ExitData));\r
       }\r
-      DEBUG ((EFI_D_LOAD, "\n"));\r
+      DEBUG ((DEBUG_LOAD, "\n"));\r
     }\r
   DEBUG_CODE_END ();\r
 \r
@@ -1120,167 +1882,42 @@ Returns:
   //\r
   if (EFI_ERROR (Image->Status) || Image->Type == EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION) {\r
     CoreUnloadAndCloseImage (Image, TRUE);\r
-  }\r
-\r
-  //\r
-  // Done\r
-  //\r
-  PERF_END (ImageHandle, START_IMAGE_TOK, NULL, 0);\r
-  return Status;\r
-}\r
-\r
-\r
-VOID\r
-CoreUnloadAndCloseImage (\r
-  IN LOADED_IMAGE_PRIVATE_DATA  *Image,\r
-  IN BOOLEAN                    FreePage\r
-  )\r
-/*++\r
-\r
-Routine Description:\r
-\r
-  Unloads EFI image from memory.\r
-\r
-Arguments:\r
-\r
-  Image      - EFI image\r
-  FreePage   - Free allocated pages\r
-\r
-Returns:\r
-\r
-  None\r
-\r
---*/\r
-{\r
-  EFI_STATUS                          Status;\r
-  UINTN                               HandleCount;\r
-  EFI_HANDLE                          *HandleBuffer;\r
-  UINTN                               HandleIndex;\r
-  EFI_GUID                            **ProtocolGuidArray;\r
-  UINTN                               ArrayCount;\r
-  UINTN                               ProtocolIndex;\r
-  EFI_OPEN_PROTOCOL_INFORMATION_ENTRY *OpenInfo;\r
-  UINTN                               OpenInfoCount;\r
-  UINTN                               OpenInfoIndex;\r
-\r
-  if (Image->Ebc != NULL) {\r
     //\r
-    // If EBC protocol exists we must perform cleanups for this image.\r
+    // ImageHandle may be invalid after the image is unloaded, so use NULL handle to record perf log.\r
     //\r
-    Image->Ebc->UnloadImage (Image->Ebc, Image->Handle);\r
-  }\r
-\r
-  //\r
-  // Unload image, free Image->ImageContext->ModHandle\r
-  //\r
-  PeCoffLoaderUnloadImage (&Image->ImageContext);\r
-\r
-  //\r
-  // Free our references to the image handle\r
-  //\r
-  if (Image->Handle != NULL_HANDLE) {\r
-\r
-    Status = CoreLocateHandleBuffer (\r
-               AllHandles,\r
-               NULL,\r
-               NULL,\r
-               &HandleCount,\r
-               &HandleBuffer\r
-               );\r
-    if (!EFI_ERROR (Status)) {\r
-      for (HandleIndex = 0; HandleIndex < HandleCount; HandleIndex++) {\r
-        Status = CoreProtocolsPerHandle (\r
-                   HandleBuffer[HandleIndex],\r
-                   &ProtocolGuidArray,\r
-                   &ArrayCount\r
-                   );\r
-        if (!EFI_ERROR (Status)) {\r
-          for (ProtocolIndex = 0; ProtocolIndex < ArrayCount; ProtocolIndex++) {\r
-            Status = CoreOpenProtocolInformation (\r
-                       HandleBuffer[HandleIndex],\r
-                       ProtocolGuidArray[ProtocolIndex],\r
-                       &OpenInfo,\r
-                       &OpenInfoCount\r
-                       );\r
-            if (!EFI_ERROR (Status)) {\r
-              for (OpenInfoIndex = 0; OpenInfoIndex < OpenInfoCount; OpenInfoIndex++) {\r
-                if (OpenInfo[OpenInfoIndex].AgentHandle == Image->Handle) {\r
-                  Status = CoreCloseProtocol (\r
-                             HandleBuffer[HandleIndex],\r
-                             ProtocolGuidArray[ProtocolIndex],\r
-                             Image->Handle,\r
-                             OpenInfo[OpenInfoIndex].ControllerHandle\r
-                             );\r
-                }\r
-              }\r
-              if (OpenInfo != NULL) {\r
-                CoreFreePool(OpenInfo);\r
-              }\r
-            }\r
-          }\r
-          if (ProtocolGuidArray != NULL) {\r
-            CoreFreePool(ProtocolGuidArray);\r
-          }\r
-        }\r
-      }\r
-      if (HandleBuffer != NULL) {\r
-        CoreFreePool (HandleBuffer);\r
-      }\r
-    }\r
-\r
-    CoreRemoveDebugImageInfoEntry (Image->Handle);\r
-\r
-    Status = CoreUninstallProtocolInterface (\r
-               Image->Handle,\r
-               &gEfiLoadedImageDevicePathProtocolGuid,\r
-               Image->LoadedImageDevicePath\r
-               );\r
-\r
-    Status = CoreUninstallProtocolInterface (\r
-               Image->Handle,\r
-               &gEfiLoadedImageProtocolGuid,\r
-               &Image->Info\r
-               );\r
-\r
-  }\r
-\r
-  if (Image->RuntimeData != NULL) {\r
-    if (Image->RuntimeData->Link.ForwardLink != NULL) {\r
-      //\r
-      // Remove the Image from the Runtime Image list as we are about to Free it!\r
-      //\r
-      RemoveEntryList (&Image->RuntimeData->Link);\r
-    }\r
-    CoreFreePool (Image->RuntimeData);\r
-  }\r
-\r
-  //\r
-  // Free the Image from memory\r
-  //\r
-  if ((Image->ImageBasePage != 0) && FreePage) {\r
-    CoreFreePages (Image->ImageBasePage, Image->NumberOfPages);\r
+    Handle = NULL;\r
   }\r
 \r
   //\r
-  // Done with the Image structure\r
+  // Done\r
   //\r
-  if (Image->Info.FilePath != NULL) {\r
-    CoreFreePool (Image->Info.FilePath);\r
-  }\r
-\r
-  if (Image->LoadedImageDevicePath != NULL) {\r
-    CoreFreePool (Image->LoadedImageDevicePath);\r
-  }\r
-\r
-  if (Image->FixupData != NULL) {\r
-    CoreFreePool (Image->FixupData);\r
-  }\r
-\r
-  CoreFreePool (Image);\r
+  PERF_START_IMAGE_END (Handle);\r
+  return Status;\r
 }\r
 \r
+/**\r
+  Terminates the currently loaded EFI image and returns control to boot services.\r
 \r
-\r
+  @param  ImageHandle             Handle that identifies the image. This\r
+                                  parameter is passed to the image on entry.\r
+  @param  Status                  The image's exit code.\r
+  @param  ExitDataSize            The size, in bytes, of ExitData. Ignored if\r
+                                  ExitStatus is EFI_SUCCESS.\r
+  @param  ExitData                Pointer to a data buffer that includes a\r
+                                  Null-terminated Unicode string, optionally\r
+                                  followed by additional binary data. The string\r
+                                  is a description that the caller may use to\r
+                                  further indicate the reason for the image's\r
+                                  exit.\r
+\r
+  @retval EFI_INVALID_PARAMETER   Image handle is NULL or it is not current\r
+                                  image.\r
+  @retval EFI_SUCCESS             Successfully terminates the currently loaded\r
+                                  EFI image.\r
+  @retval EFI_ACCESS_DENIED       Should never reach there.\r
+  @retval EFI_OUT_OF_RESOURCES    Could not allocate pool\r
+\r
+**/\r
 EFI_STATUS\r
 EFIAPI\r
 CoreExit (\r
@@ -1289,35 +1926,6 @@ CoreExit (
   IN UINTN       ExitDataSize,\r
   IN CHAR16      *ExitData  OPTIONAL\r
   )\r
-/*++\r
-\r
-Routine Description:\r
-\r
-  Terminates the currently loaded EFI image and returns control to boot services.\r
-\r
-Arguments:\r
-\r
-  ImageHandle       - Handle that identifies the image. This parameter is passed to the image\r
-                      on entry.\r
-  Status            - The image's exit code.\r
-  ExitDataSize      - The size, in bytes, of ExitData. Ignored if ExitStatus is\r
-                      EFI_SUCCESS.\r
-  ExitData          - Pointer to a data buffer that includes a Null-terminated Unicode string,\r
-                      optionally followed by additional binary data. The string is a\r
-                      description that the caller may use to further indicate the reason for\r
-                      the image's exit.\r
-\r
-Returns:\r
-\r
-  EFI_INVALID_PARAMETER     - Image handle is NULL or it is not current image.\r
-\r
-  EFI_SUCCESS               - Successfully terminates the currently loaded EFI image.\r
-\r
-  EFI_ACCESS_DENIED         - Should never reach there.\r
-\r
-  EFI_OUT_OF_RESOURCES      - Could not allocate pool\r
-\r
---*/\r
 {\r
   LOADED_IMAGE_PRIVATE_DATA  *Image;\r
   EFI_TPL                    OldTpl;\r
@@ -1325,11 +1933,11 @@ Returns:
   //\r
   // Prevent possible reentrance to this function\r
   // for the same ImageHandle\r
-  // \r
-  OldTpl = CoreRaiseTpl (TPL_NOTIFY); \r
\r
+  //\r
+  OldTpl = CoreRaiseTpl (TPL_NOTIFY);\r
+\r
   Image = CoreLoadedImageInfo (ImageHandle);\r
-  if (Image == NULL_HANDLE) {\r
+  if (Image == NULL) {\r
     Status = EFI_INVALID_PARAMETER;\r
     goto Done;\r
   }\r
@@ -1347,7 +1955,7 @@ Returns:
   // Image has been started, verify this image can exit\r
   //\r
   if (Image != mCurrentImage) {\r
-    DEBUG ((EFI_D_LOAD|EFI_D_ERROR, "Exit: Image is not exitable image\n"));\r
+    DEBUG ((DEBUG_LOAD|DEBUG_ERROR, "Exit: Image is not exitable image\n"));\r
     Status = EFI_INVALID_PARAMETER;\r
     goto Done;\r
   }\r
@@ -1362,7 +1970,7 @@ Returns:
   //\r
   if (ExitData != NULL) {\r
     Image->ExitDataSize = ExitDataSize;\r
-    Image->ExitData = CoreAllocateBootServicesPool (Image->ExitDataSize);\r
+    Image->ExitData = AllocatePool (Image->ExitDataSize);\r
     if (Image->ExitData == NULL) {\r
       Status = EFI_OUT_OF_RESOURCES;\r
       goto Done;\r
@@ -1388,39 +1996,28 @@ Done:
 \r
 \r
 \r
-EFI_STATUS\r
-EFIAPI\r
-CoreUnloadImage (\r
-  IN EFI_HANDLE  ImageHandle\r
-  )\r
-/*++\r
-\r
-Routine Description:\r
 \r
+/**\r
   Unloads an image.\r
 \r
-Arguments:\r
-\r
-  ImageHandle           - Handle that identifies the image to be unloaded.\r
+  @param  ImageHandle             Handle that identifies the image to be\r
+                                  unloaded.\r
 \r
-Returns:\r
+  @retval EFI_SUCCESS             The image has been unloaded.\r
+  @retval EFI_UNSUPPORTED         The image has been started, and does not support\r
+                                  unload.\r
+  @retval EFI_INVALID_PARAMPETER  ImageHandle is not a valid image handle.\r
 \r
- EFI_SUCCESS            - The image has been unloaded.\r
- EFI_UNSUPPORTED        - The image has been sarted, and does not support unload.\r
- EFI_INVALID_PARAMPETER - ImageHandle is not a valid image handle.\r
-\r
---*/\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+CoreUnloadImage (\r
+  IN EFI_HANDLE  ImageHandle\r
+  )\r
 {\r
   EFI_STATUS                 Status;\r
   LOADED_IMAGE_PRIVATE_DATA  *Image;\r
-  EFI_TPL                    OldTpl;\r
 \r
-  //\r
-  // Prevent possible reentrance to this function\r
-  // for the same ImageHandle\r
-  // \r
-  OldTpl = CoreRaiseTpl (TPL_NOTIFY);\r
\r
   Image = CoreLoadedImageInfo (ImageHandle);\r
   if (Image == NULL ) {\r
     //\r
@@ -1455,38 +2052,28 @@ Returns:
   }\r
 \r
 Done:\r
-  CoreRestoreTpl (OldTpl);\r
   return Status;\r
 }\r
 \r
 \r
+\r
+/**\r
+  Unload the specified image.\r
+\r
+  @param  This                    Indicates the calling context.\r
+  @param  ImageHandle             The specified image handle.\r
+\r
+  @retval EFI_INVALID_PARAMETER   Image handle is NULL.\r
+  @retval EFI_UNSUPPORTED         Attempt to unload an unsupported image.\r
+  @retval EFI_SUCCESS             Image successfully unloaded.\r
+\r
+**/\r
 EFI_STATUS\r
 EFIAPI\r
 CoreUnloadImageEx (\r
   IN EFI_PE32_IMAGE_PROTOCOL  *This,\r
   IN EFI_HANDLE                         ImageHandle\r
   )\r
-/*++\r
-\r
-Routine Description:\r
-\r
-  Unload the specified image.\r
-\r
-Arguments:\r
-\r
-  This              - Indicates the calling context.\r
-\r
-  ImageHandle       - The specified image handle.\r
-\r
-Returns:\r
-\r
-  EFI_INVALID_PARAMETER       - Image handle is NULL.\r
-\r
-  EFI_UNSUPPORTED             - Attempt to unload an unsupported image.\r
-\r
-  EFI_SUCCESS                 - Image successfully unloaded.\r
-\r
---*/\r
 {\r
   return CoreUnloadImage (ImageHandle);\r
 }\r