]> git.proxmox.com Git - mirror_edk2.git/blobdiff - MdePkg/Library/BasePeCoffLib/BasePeCoff.c
Add License Head to all files
[mirror_edk2.git] / MdePkg / Library / BasePeCoffLib / BasePeCoff.c
index 6b8adc1fd63006ff021f862fa927a575a8c40c74..eee4dc713fe746684f080a2ae07eab64be272f9f 100644 (file)
@@ -1,6 +1,9 @@
 /** @file\r
   Tiano PE/COFF loader.\r
 \r
+  This PE/COFF loader supports loading any PE32 or PE32+ image type, but\r
+  only supports relocating IA32, X64, IPF, and EBC images.\r
+\r
   Copyright (c) 2006, 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
 \r
 **/\r
 \r
+\r
 /**\r
-  Performs an Itanium-based specific relocation fixup.\r
+  Performs an Itanium-based specific relocation fixup and is a no-op on other\r
+  instruction sets.\r
 \r
   @param  Reloc       Pointer to the relocation record.\r
   @param  Fixup       Pointer to the address to fix up.\r
@@ -34,33 +39,68 @@ PeCoffLoaderRelocateImageEx (
   );\r
 \r
 \r
+/**\r
+  Performs an Itanium-based specific re-relocation fixup and is a no-op on other\r
+  instruction sets. This is used to re-relocated the image into the EFI virtual\r
+  space for runtime calls.\r
+\r
+  @param  Reloc       Pointer to the relocation record.\r
+  @param  Fixup       Pointer to the address to fix up.\r
+  @param  FixupData   Pointer to a buffer to log the fixups.\r
+  @param  Adjust      The offset to adjust the fixup.\r
+\r
+  @return Status code.\r
+\r
+**/\r
+RETURN_STATUS\r
+PeHotRelocateImageEx (\r
+  IN UINT16      *Reloc,\r
+  IN OUT CHAR8   *Fixup,\r
+  IN OUT CHAR8   **FixupData,\r
+  IN UINT64      Adjust\r
+  );\r
+\r
+\r
+/**\r
+  Returns TRUE if the machine type of PE/COFF image is supported. Supported \r
+  does not mean the image can be executed it means the PE/COFF loader supports\r
+  loading and relocating of the image type. It's up to the caller to support\r
+  the entry point. \r
+\r
+  @param  Machine   Machine type from the PE Header.\r
+\r
+  @return TRUE if this PE/COFF loader can load the image\r
+\r
+**/\r
+BOOLEAN\r
+PeCoffLoaderImageFormatSupported (\r
+  IN  UINT16  Machine\r
+  );\r
+\r
+\r
 \r
 /**\r
   Retrieves the PE or TE Header from a PE/COFF or TE image.\r
 \r
   @param  ImageContext    The context of the image being loaded.\r
-  @param  PeHdr           The buffer in which to return the PE header.\r
-  @param  TeHdr           The buffer in which to return the TE header.\r
+  @param  Hdr             The buffer in which to return the PE32, PE32+, or TE header.\r
 \r
   @retval RETURN_SUCCESS  The PE or TE Header is read.\r
   @retval Other           The error status from reading the PE/COFF or TE image using the ImageRead function.\r
 \r
 **/\r
-STATIC\r
 RETURN_STATUS\r
 PeCoffLoaderGetPeHeader (\r
-  IN OUT PE_COFF_LOADER_IMAGE_CONTEXT  *ImageContext,\r
-  OUT    EFI_IMAGE_NT_HEADERS          *PeHdr,\r
-  OUT    EFI_TE_IMAGE_HEADER           *TeHdr\r
+  IN OUT PE_COFF_LOADER_IMAGE_CONTEXT         *ImageContext,\r
+  OUT    EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION  Hdr\r
   )\r
 {\r
   RETURN_STATUS         Status;\r
   EFI_IMAGE_DOS_HEADER  DosHdr;\r
   UINTN                 Size;\r
 \r
-  ImageContext->IsTeImage = FALSE;\r
   //\r
-  // Read the DOS image headers\r
+  // Read the DOS image header to check for it's existance\r
   //\r
   Size = sizeof (EFI_IMAGE_DOS_HEADER);\r
   Status = ImageContext->ImageRead (\r
@@ -77,93 +117,85 @@ PeCoffLoaderGetPeHeader (
   ImageContext->PeCoffHeaderOffset = 0;\r
   if (DosHdr.e_magic == EFI_IMAGE_DOS_SIGNATURE) {\r
     //\r
-    // DOS image header is present, so read the PE header after the DOS image header\r
+    // DOS image header is present, so read the PE header after the DOS image \r
+    // header\r
     //\r
     ImageContext->PeCoffHeaderOffset = DosHdr.e_lfanew;\r
   }\r
+\r
   //\r
-  // Read the PE/COFF Header\r
+  // Read the PE/COFF Header. For PE32 (32-bit) this will read in too much \r
+  // data, but that should not hurt anythine. Hdr.Pe32->OptionalHeader.Magic\r
+  // determins if this is a PE32 or PE32+ image. The magic is in the same \r
+  // location in both images.\r
   //\r
-  Size = sizeof (EFI_IMAGE_NT_HEADERS);\r
+  Size = sizeof (EFI_IMAGE_OPTIONAL_HEADER_UNION);\r
   Status = ImageContext->ImageRead (\r
                            ImageContext->Handle,\r
                            ImageContext->PeCoffHeaderOffset,\r
                            &Size,\r
-                           PeHdr\r
+                           Hdr.Pe32\r
                            );\r
   if (RETURN_ERROR (Status)) {\r
     ImageContext->ImageError = IMAGE_ERROR_IMAGE_READ;\r
     return Status;\r
   }\r
+\r
   //\r
-  // Check the PE/COFF Header Signature. If not, then try to read a TE header\r
+  // Use Signature to figure out if we understand the image format\r
   //\r
-  if (PeHdr->Signature != EFI_IMAGE_NT_SIGNATURE) {\r
-    Size = sizeof (EFI_TE_IMAGE_HEADER);\r
-    Status = ImageContext->ImageRead (\r
-                             ImageContext->Handle,\r
-                             0,\r
-                             &Size,\r
-                             TeHdr\r
-                             );\r
-    if (TeHdr->Signature != EFI_TE_IMAGE_HEADER_SIGNATURE) {\r
-      return RETURN_UNSUPPORTED;\r
-    }\r
-\r
-    ImageContext->IsTeImage = TRUE;\r
-  }\r
-\r
-  return RETURN_SUCCESS;\r
-}\r
-\r
-/**\r
-  Checks the PE or TE header of a PE/COFF or TE image to determine if it supported.\r
-\r
-  @param  ImageContext        The context of the image being loaded.\r
-  @param  PeHdr               The buffer in which to return the PE header.\r
-  @param  TeHdr               The buffer in which to return the TE header.\r
+  if (Hdr.Te->Signature == EFI_TE_IMAGE_HEADER_SIGNATURE) {\r
+    ImageContext->IsTeImage         = TRUE;\r
+    ImageContext->Machine           = Hdr.Te->Machine;\r
+    ImageContext->ImageType         = (UINT16)(Hdr.Te->Subsystem);\r
+    ImageContext->ImageSize         = 0;\r
+    ImageContext->SectionAlignment  = 4096;\r
+    ImageContext->SizeOfHeaders     = sizeof (EFI_TE_IMAGE_HEADER) + (UINTN)Hdr.Te->BaseOfCode - (UINTN)Hdr.Te->StrippedSize;\r
 \r
-  @retval RETURN_SUCCESS      The PE/COFF or TE image is supported.\r
-  @retval RETURN_UNSUPPORTED  The PE/COFF or TE image is not supported.\r
+  } else if (Hdr.Pe32->Signature == EFI_IMAGE_NT_SIGNATURE)  {\r
+    ImageContext->IsTeImage = FALSE;\r
+    ImageContext->Machine = Hdr.Pe32->FileHeader.Machine;\r
+    \r
+    if (Hdr.Pe32->OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {\r
+      //\r
+      // Use PE32 offset\r
+      //\r
+      ImageContext->ImageType         = Hdr.Pe32->OptionalHeader.Subsystem;\r
+      ImageContext->ImageSize         = (UINT64)Hdr.Pe32->OptionalHeader.SizeOfImage;\r
+      ImageContext->SectionAlignment  = Hdr.Pe32->OptionalHeader.SectionAlignment;\r
+      ImageContext->SizeOfHeaders     = Hdr.Pe32->OptionalHeader.SizeOfHeaders;\r
 \r
-**/\r
-STATIC\r
-RETURN_STATUS\r
-PeCoffLoaderCheckImageType (\r
-  IN OUT PE_COFF_LOADER_IMAGE_CONTEXT          *ImageContext,\r
-  IN     EFI_IMAGE_NT_HEADERS                  *PeHdr,\r
-  IN     EFI_TE_IMAGE_HEADER                   *TeHdr\r
-  )\r
-{\r
-  //\r
-  // See if the machine type is supported.  We support a native machine type (IA-32/Itanium-based)\r
-  // and the machine type for the Virtual Machine.\r
-  //\r
-  if (ImageContext->IsTeImage == FALSE) {\r
-    ImageContext->Machine = PeHdr->FileHeader.Machine;\r
+    } else if (Hdr.Pe32->OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC) {\r
+      //\r
+      // Use PE32+ offset\r
+      //\r
+      ImageContext->ImageType         = Hdr.Pe32Plus->OptionalHeader.Subsystem;\r
+      ImageContext->ImageSize         = (UINT64) Hdr.Pe32Plus->OptionalHeader.SizeOfImage;\r
+      ImageContext->SectionAlignment  = Hdr.Pe32Plus->OptionalHeader.SectionAlignment;\r
+      ImageContext->SizeOfHeaders     = Hdr.Pe32Plus->OptionalHeader.SizeOfHeaders;\r
+    } else {\r
+      ImageContext->ImageError = IMAGE_ERROR_INVALID_MACHINE_TYPE;\r
+      return RETURN_UNSUPPORTED;    \r
+    }\r
   } else {\r
-    ImageContext->Machine = TeHdr->Machine;\r
-  }\r
-\r
-  if (!(EFI_IMAGE_MACHINE_TYPE_SUPPORTED (ImageContext->Machine))) {\r
     ImageContext->ImageError = IMAGE_ERROR_INVALID_MACHINE_TYPE;\r
     return RETURN_UNSUPPORTED;\r
   }\r
 \r
-  //\r
-  // See if the image type is supported.  We support EFI Applications,\r
-  // EFI Boot Service Drivers, and EFI Runtime Drivers.\r
-  //\r
-  if (ImageContext->IsTeImage == FALSE) {\r
-    ImageContext->ImageType = PeHdr->OptionalHeader.Subsystem;\r
-  } else {\r
-    ImageContext->ImageType = (UINT16) (TeHdr->Subsystem);\r
+  if (!PeCoffLoaderImageFormatSupported (ImageContext->Machine)) {\r
+    //\r
+    // If the PE/COFF loader does not support the image type return\r
+    // unsupported. This library can suport lots of types of images\r
+    // this does not mean the user of this library can call the entry\r
+    // point of the image. \r
+    //\r
+    return RETURN_UNSUPPORTED;\r
   }\r
 \r
-\r
   return RETURN_SUCCESS;\r
 }\r
 \r
+\r
 /**\r
   Retrieves information about a PE/COFF image.\r
 \r
@@ -189,17 +221,18 @@ PeCoffLoaderGetImageInfo (
   IN OUT PE_COFF_LOADER_IMAGE_CONTEXT           *ImageContext\r
   )\r
 {\r
-  RETURN_STATUS                   Status;\r
-  EFI_IMAGE_NT_HEADERS            PeHdr;\r
-  EFI_TE_IMAGE_HEADER             TeHdr;\r
-  EFI_IMAGE_DATA_DIRECTORY        *DebugDirectoryEntry;\r
-  UINTN                           Size;\r
-  UINTN                           Index;\r
-  UINTN                           DebugDirectoryEntryRva;\r
-  UINTN                           DebugDirectoryEntryFileOffset;\r
-  UINTN                           SectionHeaderOffset;\r
-  EFI_IMAGE_SECTION_HEADER        SectionHeader;\r
-  EFI_IMAGE_DEBUG_DIRECTORY_ENTRY DebugEntry;\r
+  RETURN_STATUS                         Status;\r
+  EFI_IMAGE_OPTIONAL_HEADER_UNION       HdrData;\r
+  EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION   Hdr;\r
+  EFI_IMAGE_DATA_DIRECTORY              *DebugDirectoryEntry;\r
+  UINTN                                 Size;\r
+  UINTN                                 Index;\r
+  UINTN                                 DebugDirectoryEntryRva;\r
+  UINTN                                 DebugDirectoryEntryFileOffset;\r
+  UINTN                                 SectionHeaderOffset;\r
+  EFI_IMAGE_SECTION_HEADER              SectionHeader;\r
+  EFI_IMAGE_DEBUG_DIRECTORY_ENTRY       DebugEntry;\r
+  UINT32                                NumberOfRvaAndSizes;\r
 \r
   if (NULL == ImageContext) {\r
     return RETURN_INVALID_PARAMETER;\r
@@ -209,25 +242,31 @@ PeCoffLoaderGetImageInfo (
   //\r
   ImageContext->ImageError  = IMAGE_ERROR_SUCCESS;\r
 \r
-  Status                    = PeCoffLoaderGetPeHeader (ImageContext, &PeHdr, &TeHdr);\r
-  if (RETURN_ERROR (Status)) {\r
-    return Status;\r
-  }\r
-  //\r
-  // Verify machine type\r
-  //\r
-  Status = PeCoffLoaderCheckImageType (ImageContext, &PeHdr, &TeHdr);\r
+  Hdr.Union = &HdrData;\r
+  Status = PeCoffLoaderGetPeHeader (ImageContext, Hdr);\r
   if (RETURN_ERROR (Status)) {\r
     return Status;\r
   }\r
+\r
   //\r
   // Retrieve the base address of the image\r
   //\r
   if (!(ImageContext->IsTeImage)) {\r
-    ImageContext->ImageAddress = PeHdr.OptionalHeader.ImageBase;\r
+    if (Hdr.Pe32->OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {\r
+      //\r
+      // Use PE32 offset\r
+      //\r
+      ImageContext->ImageAddress = Hdr.Pe32->OptionalHeader.ImageBase;\r
+    } else {\r
+      //\r
+      // Use PE32+ offset\r
+      //\r
+      ImageContext->ImageAddress = Hdr.Pe32Plus->OptionalHeader.ImageBase;\r
+    }\r
   } else {\r
-    ImageContext->ImageAddress = (PHYSICAL_ADDRESS) (TeHdr.ImageBase);\r
+    ImageContext->ImageAddress = (PHYSICAL_ADDRESS)(Hdr.Te->ImageBase);\r
   }\r
+\r
   //\r
   // Initialize the alternate destination address to 0 indicating that it\r
   // should not be used.\r
@@ -251,23 +290,28 @@ PeCoffLoaderGetImageInfo (
   // Look at the file header to determine if relocations have been stripped, and\r
   // save this info in the image context for later use.\r
   //\r
-  if ((!(ImageContext->IsTeImage)) && ((PeHdr.FileHeader.Characteristics & EFI_IMAGE_FILE_RELOCS_STRIPPED) != 0)) {\r
+  if ((!(ImageContext->IsTeImage)) && ((Hdr.Pe32->FileHeader.Characteristics & EFI_IMAGE_FILE_RELOCS_STRIPPED) != 0)) {\r
     ImageContext->RelocationsStripped = TRUE;\r
   } else {\r
     ImageContext->RelocationsStripped = FALSE;\r
   }\r
 \r
   if (!(ImageContext->IsTeImage)) {\r
-    ImageContext->ImageSize         = (UINT64) PeHdr.OptionalHeader.SizeOfImage;\r
-    ImageContext->SectionAlignment  = PeHdr.OptionalHeader.SectionAlignment;\r
-    ImageContext->SizeOfHeaders     = PeHdr.OptionalHeader.SizeOfHeaders;\r
-\r
-    //\r
-    // Modify ImageSize to contain .PDB file name if required and initialize\r
-    // PdbRVA field...\r
-    //\r
-    if (PeHdr.OptionalHeader.NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_DEBUG) {\r
-      DebugDirectoryEntry = (EFI_IMAGE_DATA_DIRECTORY *) &(PeHdr.OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG]);\r
+    if (Hdr.Pe32->OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {\r
+      //     \r
+      // Use PE32 offset\r
+      //\r
+      NumberOfRvaAndSizes = Hdr.Pe32->OptionalHeader.NumberOfRvaAndSizes;\r
+      DebugDirectoryEntry = (EFI_IMAGE_DATA_DIRECTORY *)&(Hdr.Pe32->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG]);\r
+    } else {\r
+      //     \r
+      // Use PE32+ offset\r
+      //\r
+      NumberOfRvaAndSizes = Hdr.Pe32Plus->OptionalHeader.NumberOfRvaAndSizes;\r
+      DebugDirectoryEntry = (EFI_IMAGE_DATA_DIRECTORY *)&(Hdr.Pe32Plus->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG]);\r
+    }    \r
+    \r
+    if (NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_DEBUG) {\r
 \r
       DebugDirectoryEntryRva = DebugDirectoryEntry->VirtualAddress;\r
 \r
@@ -282,10 +326,10 @@ PeCoffLoaderGetImageInfo (
                                ImageContext->PeCoffHeaderOffset +\r
                                sizeof (UINT32) + \r
                                sizeof (EFI_IMAGE_FILE_HEADER) + \r
-                               PeHdr.FileHeader.SizeOfOptionalHeader\r
+                               Hdr.Pe32->FileHeader.SizeOfOptionalHeader\r
                                );\r
 \r
-      for (Index = 0; Index < PeHdr.FileHeader.NumberOfSections; Index++) {\r
+      for (Index = 0; Index < Hdr.Pe32->FileHeader.NumberOfSections; Index++) {\r
         //\r
         // Read section header from file\r
         //\r
@@ -303,8 +347,8 @@ PeCoffLoaderGetImageInfo (
 \r
         if (DebugDirectoryEntryRva >= SectionHeader.VirtualAddress &&\r
             DebugDirectoryEntryRva < SectionHeader.VirtualAddress + SectionHeader.Misc.VirtualSize) {\r
-            DebugDirectoryEntryFileOffset =\r
-            DebugDirectoryEntryRva - SectionHeader.VirtualAddress + SectionHeader.PointerToRawData;\r
+\r
+          DebugDirectoryEntryFileOffset = DebugDirectoryEntryRva - SectionHeader.VirtualAddress + SectionHeader.PointerToRawData;\r
           break;\r
         }\r
 \r
@@ -340,17 +384,14 @@ PeCoffLoaderGetImageInfo (
       }\r
     }\r
   } else {\r
-    ImageContext->ImageSize         = 0;\r
-    ImageContext->SectionAlignment  = 4096;\r
-    ImageContext->SizeOfHeaders     = sizeof (EFI_TE_IMAGE_HEADER) + (UINTN) TeHdr.BaseOfCode - (UINTN) TeHdr.StrippedSize;\r
 \r
-    DebugDirectoryEntry             = &TeHdr.DataDirectory[1];\r
+    DebugDirectoryEntry             = &Hdr.Te->DataDirectory[1];\r
     DebugDirectoryEntryRva          = DebugDirectoryEntry->VirtualAddress;\r
-    SectionHeaderOffset             = (UINTN) (sizeof (EFI_TE_IMAGE_HEADER));\r
+    SectionHeaderOffset             = (UINTN)(sizeof (EFI_TE_IMAGE_HEADER));\r
 \r
     DebugDirectoryEntryFileOffset   = 0;\r
 \r
-    for (Index = 0; Index < TeHdr.NumberOfSections;) {\r
+    for (Index = 0; Index < Hdr.Te->NumberOfSections;) {\r
       //\r
       // Read section header from file\r
       //\r
@@ -372,15 +413,15 @@ PeCoffLoaderGetImageInfo (
                                         SectionHeader.VirtualAddress +\r
                                         SectionHeader.PointerToRawData +\r
                                         sizeof (EFI_TE_IMAGE_HEADER) -\r
-                                        TeHdr.StrippedSize;\r
+                                        Hdr.Te->StrippedSize;\r
 \r
         //\r
         // File offset of the debug directory was found, if this is not the last\r
         // section, then skip to the last section for calculating the image size.\r
         //\r
-        if (Index < (UINTN) TeHdr.NumberOfSections - 1) {\r
-          SectionHeaderOffset += (TeHdr.NumberOfSections - 1 - Index) * sizeof (EFI_IMAGE_SECTION_HEADER);\r
-          Index = TeHdr.NumberOfSections - 1;\r
+        if (Index < (UINTN) Hdr.Te->NumberOfSections - 1) {\r
+          SectionHeaderOffset += (Hdr.Te->NumberOfSections - 1 - Index) * sizeof (EFI_IMAGE_SECTION_HEADER);\r
+          Index = Hdr.Te->NumberOfSections - 1;\r
           continue;\r
         }\r
       }\r
@@ -395,7 +436,7 @@ PeCoffLoaderGetImageInfo (
       // by the RVA and the VirtualSize of the last section header in the\r
       // Section Table.\r
       //\r
-      if ((++Index) == (UINTN) TeHdr.NumberOfSections) {\r
+      if ((++Index) == (UINTN)Hdr.Te->NumberOfSections) {\r
         ImageContext->ImageSize = (SectionHeader.VirtualAddress + SectionHeader.Misc.VirtualSize +\r
                                    ImageContext->SectionAlignment - 1) & ~(ImageContext->SectionAlignment - 1);\r
       }\r
@@ -431,6 +472,7 @@ PeCoffLoaderGetImageInfo (
   return RETURN_SUCCESS;\r
 }\r
 \r
+\r
 /**\r
   Converts an image address to the loaded address.\r
 \r
@@ -440,19 +482,22 @@ PeCoffLoaderGetImageInfo (
   @return The converted address or NULL if the address can not be converted.\r
 \r
 **/\r
-STATIC\r
 VOID *\r
 PeCoffLoaderImageAddress (\r
   IN OUT PE_COFF_LOADER_IMAGE_CONTEXT          *ImageContext,\r
   IN     UINTN                                 Address\r
   )\r
 {\r
+  //\r
+  // @bug Check to make sure ImageSize is correct for the relocated image. \r
+  //      it may only work for the file we start with and not the relocated image\r
+  //\r
   if (Address >= ImageContext->ImageSize) {\r
     ImageContext->ImageError = IMAGE_ERROR_INVALID_IMAGE_ADDRESS;\r
     return NULL;\r
   }\r
 \r
-  return (CHAR8 *) ((UINTN) ImageContext->ImageAddress + Address);\r
+  return (CHAR8 *)((UINTN) ImageContext->ImageAddress + Address);\r
 }\r
 \r
 /**\r
@@ -481,26 +526,25 @@ PeCoffLoaderRelocateImage (
   IN OUT PE_COFF_LOADER_IMAGE_CONTEXT  *ImageContext\r
   )\r
 {\r
-  RETURN_STATUS             Status;\r
-  EFI_IMAGE_NT_HEADERS      *PeHdr;\r
-  EFI_TE_IMAGE_HEADER       *TeHdr;\r
-  EFI_IMAGE_DATA_DIRECTORY  *RelocDir;\r
-  UINT64                    Adjust;\r
-  EFI_IMAGE_BASE_RELOCATION *RelocBase;\r
-  EFI_IMAGE_BASE_RELOCATION *RelocBaseEnd;\r
-  UINT16                    *Reloc;\r
-  UINT16                    *RelocEnd;\r
-  CHAR8                     *Fixup;\r
-  CHAR8                     *FixupBase;\r
-  UINT16                    *F16;\r
-  UINT32                    *F32;\r
-  CHAR8                     *FixupData;\r
-  PHYSICAL_ADDRESS          BaseAddress;\r
+  RETURN_STATUS                         Status;\r
+  EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION   Hdr;\r
+  EFI_IMAGE_DATA_DIRECTORY              *RelocDir;\r
+  UINT64                                Adjust;\r
+  EFI_IMAGE_BASE_RELOCATION             *RelocBase;\r
+  EFI_IMAGE_BASE_RELOCATION             *RelocBaseEnd;\r
+  UINT16                                *Reloc;\r
+  UINT16                                *RelocEnd;\r
+  CHAR8                                 *Fixup;\r
+  CHAR8                                 *FixupBase;\r
+  UINT16                                *F16;\r
+  UINT32                                *F32;  \r
+  UINT64                                *F64;\r
+  CHAR8                                 *FixupData;\r
+  PHYSICAL_ADDRESS                      BaseAddress;\r
+  UINT32                                NumberOfRvaAndSizes;\r
 \r
   ASSERT (ImageContext != NULL);\r
 \r
-  PeHdr = NULL;\r
-  TeHdr = NULL;\r
   //\r
   // Assume success\r
   //\r
@@ -524,21 +568,35 @@ PeCoffLoaderRelocateImage (
   }\r
 \r
   if (!(ImageContext->IsTeImage)) {\r
-    PeHdr = (EFI_IMAGE_NT_HEADERS *)((UINTN)ImageContext->ImageAddress + \r
-                                            ImageContext->PeCoffHeaderOffset);\r
-   \r
-    Adjust = (UINT64) BaseAddress - PeHdr->OptionalHeader.ImageBase;\r
-    PeHdr->OptionalHeader.ImageBase = (UINTN)BaseAddress;\r
+    Hdr.Pe32 = (EFI_IMAGE_NT_HEADERS32 *)((UINTN)ImageContext->ImageAddress + ImageContext->PeCoffHeaderOffset);\r
+    if (Hdr.Pe32->OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {\r
+      //\r
+      // Use PE32 offset\r
+      //\r
+      Adjust = (UINT64)BaseAddress - Hdr.Pe32->OptionalHeader.ImageBase;\r
+      Hdr.Pe32->OptionalHeader.ImageBase = (UINT32)BaseAddress;\r
+  \r
+      NumberOfRvaAndSizes = Hdr.Pe32->OptionalHeader.NumberOfRvaAndSizes;\r
+      RelocDir  = &Hdr.Pe32->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC];\r
+    } else {\r
+      //\r
+      // Use PE32+ offset\r
+      //\r
+      Adjust = (UINT64) BaseAddress - Hdr.Pe32Plus->OptionalHeader.ImageBase;\r
+      Hdr.Pe32Plus->OptionalHeader.ImageBase = (UINT64)BaseAddress;\r
+\r
+      NumberOfRvaAndSizes = Hdr.Pe32Plus->OptionalHeader.NumberOfRvaAndSizes;\r
+      RelocDir  = &Hdr.Pe32Plus->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC];\r
+    }\r
 \r
     //\r
     // Find the relocation block\r
-    //\r
     // Per the PE/COFF spec, you can't assume that a given data directory\r
     // is present in the image. You have to check the NumberOfRvaAndSizes in\r
     // the optional header to verify a desired directory entry is there.\r
     //\r
-    if (PeHdr->OptionalHeader.NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC) {\r
-      RelocDir  = &PeHdr->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC];\r
+\r
+    if (NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC) {\r
       RelocBase = PeCoffLoaderImageAddress (ImageContext, RelocDir->VirtualAddress);\r
       RelocBaseEnd = PeCoffLoaderImageAddress (\r
                       ImageContext,\r
@@ -551,19 +609,19 @@ PeCoffLoaderRelocateImage (
       RelocBase = RelocBaseEnd = 0;\r
     }\r
   } else {\r
-    TeHdr             = (EFI_TE_IMAGE_HEADER *) (UINTN) (ImageContext->ImageAddress);\r
-    Adjust            = (UINT64) (BaseAddress - TeHdr->ImageBase);\r
-    TeHdr->ImageBase  = (UINT64) (BaseAddress);\r
+    Hdr.Te             = (EFI_TE_IMAGE_HEADER *)(UINTN)(ImageContext->ImageAddress);\r
+    Adjust             = (UINT64) (BaseAddress - Hdr.Te->ImageBase);\r
+    Hdr.Te->ImageBase  = (UINT64) (BaseAddress);\r
 \r
     //\r
     // Find the relocation block\r
     //\r
-    RelocDir = &TeHdr->DataDirectory[0];\r
+    RelocDir = &Hdr.Te->DataDirectory[0];\r
     RelocBase = (EFI_IMAGE_BASE_RELOCATION *)(UINTN)(\r
                                     ImageContext->ImageAddress + \r
                                     RelocDir->VirtualAddress +\r
                                     sizeof(EFI_TE_IMAGE_HEADER) - \r
-                                    TeHdr->StrippedSize\r
+                                    Hdr.Te->StrippedSize\r
                                     );\r
     RelocBaseEnd = (EFI_IMAGE_BASE_RELOCATION *) ((UINTN) RelocBase + (UINTN) RelocDir->Size - 1);\r
   }\r
@@ -582,7 +640,7 @@ PeCoffLoaderRelocateImage (
       FixupBase = (CHAR8 *)(UINTN)(ImageContext->ImageAddress +\r
                     RelocBase->VirtualAddress +\r
                     sizeof(EFI_TE_IMAGE_HEADER) - \r
-                    TeHdr->StrippedSize\r
+                    Hdr.Te->StrippedSize\r
                     );\r
     }\r
 \r
@@ -626,21 +684,27 @@ PeCoffLoaderRelocateImage (
         *F32  = *F32 + (UINT32) Adjust;\r
         if (FixupData != NULL) {\r
           FixupData             = ALIGN_POINTER (FixupData, sizeof (UINT32));\r
-          *(UINT32 *) FixupData = *F32;\r
+          *(UINT32 *)FixupData  = *F32;\r
           FixupData             = FixupData + sizeof (UINT32);\r
         }\r
         break;\r
 \r
-      case EFI_IMAGE_REL_BASED_HIGHADJ:\r
-        //\r
-        // Return the same EFI_UNSUPPORTED return code as\r
-        // PeCoffLoaderRelocateImageEx() returns if it does not recognize\r
-        // the relocation type.\r
-        //\r
-        ImageContext->ImageError = IMAGE_ERROR_FAILED_RELOCATION;\r
-        return RETURN_UNSUPPORTED;\r
+      case EFI_IMAGE_REL_BASED_DIR64:\r
+        F64 = (UINT64 *) Fixup;\r
+        *F64 = *F64 + (UINT64) Adjust;\r
+        if (FixupData != NULL) {\r
+          FixupData = ALIGN_POINTER (FixupData, sizeof(UINT64));\r
+          *(UINT64 *)(FixupData) = *F64;\r
+          FixupData = FixupData + sizeof(UINT64);\r
+        }\r
+        break;\r
 \r
       default:\r
+        //\r
+        // The common code does not handle some of the stranger IPF relocations\r
+        // PeCoffLoaderRelocateImageEx () addes support for these complex fixups\r
+        // on IPF and is a No-Op on other archtiectures.\r
+        //\r
         Status = PeCoffLoaderRelocateImageEx (Reloc, Fixup, &FixupData, Adjust);\r
         if (RETURN_ERROR (Status)) {\r
           ImageContext->ImageError = IMAGE_ERROR_FAILED_RELOCATION;\r
@@ -693,8 +757,7 @@ PeCoffLoaderLoadImage (
   )\r
 {\r
   RETURN_STATUS                         Status;\r
-  EFI_IMAGE_NT_HEADERS                  *PeHdr;\r
-  EFI_TE_IMAGE_HEADER                   *TeHdr;\r
+  EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION   Hdr;\r
   PE_COFF_LOADER_IMAGE_CONTEXT          CheckContext;\r
   EFI_IMAGE_SECTION_HEADER              *FirstSection;\r
   EFI_IMAGE_SECTION_HEADER              *Section;\r
@@ -707,12 +770,10 @@ PeCoffLoaderLoadImage (
   EFI_IMAGE_DEBUG_DIRECTORY_ENTRY       *DebugEntry;\r
   UINTN                                 Size;\r
   UINT32                                TempDebugEntryRva;\r
+  UINT32                                NumberOfRvaAndSizes;\r
 \r
   ASSERT (ImageContext != NULL);\r
 \r
-  PeHdr = NULL;\r
-  TeHdr = NULL;\r
-\r
   //\r
   // Assume success\r
   //\r
@@ -786,32 +847,31 @@ PeCoffLoaderLoadImage (
                             (VOID *) (UINTN) ImageContext->ImageAddress\r
                             );\r
 \r
-    PeHdr = (EFI_IMAGE_NT_HEADERS *)\r
-      ((UINTN)ImageContext->ImageAddress + ImageContext->PeCoffHeaderOffset);\r
+    Hdr.Pe32 = (EFI_IMAGE_NT_HEADERS32 *)((UINTN)ImageContext->ImageAddress + ImageContext->PeCoffHeaderOffset);\r
 \r
     FirstSection = (EFI_IMAGE_SECTION_HEADER *) (\r
                       (UINTN)ImageContext->ImageAddress +\r
                       ImageContext->PeCoffHeaderOffset +\r
                       sizeof(UINT32) + \r
                       sizeof(EFI_IMAGE_FILE_HEADER) + \r
-                      PeHdr->FileHeader.SizeOfOptionalHeader\r
+                      Hdr.Pe32->FileHeader.SizeOfOptionalHeader\r
       );\r
-    NumberOfSections = (UINTN) (PeHdr->FileHeader.NumberOfSections);\r
+    NumberOfSections = (UINTN) (Hdr.Pe32->FileHeader.NumberOfSections);\r
   } else {\r
     Status = ImageContext->ImageRead (\r
                             ImageContext->Handle,\r
                             0,\r
                             &ImageContext->SizeOfHeaders,\r
-                            (void *) (UINTN) ImageContext->ImageAddress\r
+                            (void *)(UINTN)ImageContext->ImageAddress\r
                             );\r
 \r
-    TeHdr             = (EFI_TE_IMAGE_HEADER *) (UINTN) (ImageContext->ImageAddress);\r
+    Hdr.Te = (EFI_TE_IMAGE_HEADER *)(UINTN)(ImageContext->ImageAddress);\r
 \r
     FirstSection = (EFI_IMAGE_SECTION_HEADER *) (\r
-          (UINTN)ImageContext->ImageAddress +\r
-          sizeof(EFI_TE_IMAGE_HEADER)\r
-          );\r
-    NumberOfSections  = (UINTN) (TeHdr->NumberOfSections);\r
+                      (UINTN)ImageContext->ImageAddress +\r
+                      sizeof(EFI_TE_IMAGE_HEADER)\r
+                      );\r
+    NumberOfSections  = (UINTN) (Hdr.Te->NumberOfSections);\r
 \r
   }\r
 \r
@@ -835,8 +895,8 @@ PeCoffLoaderLoadImage (
             Section->VirtualAddress + Section->Misc.VirtualSize - 1\r
             );\r
     if (ImageContext->IsTeImage) {\r
-      Base  = (CHAR8 *) ((UINTN) Base + sizeof (EFI_TE_IMAGE_HEADER) - (UINTN) TeHdr->StrippedSize);\r
-      End   = (CHAR8 *) ((UINTN) End + sizeof (EFI_TE_IMAGE_HEADER) - (UINTN) TeHdr->StrippedSize);\r
+      Base = (CHAR8 *)((UINTN) Base + sizeof (EFI_TE_IMAGE_HEADER) - (UINTN)Hdr.Te->StrippedSize);\r
+      End  = (CHAR8 *)((UINTN) End +  sizeof (EFI_TE_IMAGE_HEADER) - (UINTN)Hdr.Te->StrippedSize);\r
     }\r
 \r
     if (End > MaxEnd) {\r
@@ -869,7 +929,7 @@ PeCoffLoaderLoadImage (
       } else {\r
         Status = ImageContext->ImageRead (\r
                                 ImageContext->Handle,\r
-                                Section->PointerToRawData + sizeof (EFI_TE_IMAGE_HEADER) - (UINTN) TeHdr->StrippedSize,\r
+                                Section->PointerToRawData + sizeof (EFI_TE_IMAGE_HEADER) - (UINTN)Hdr.Te->StrippedSize,\r
                                 &Size,\r
                                 Base\r
                                 );\r
@@ -899,17 +959,33 @@ PeCoffLoaderLoadImage (
   // Get image's entry point\r
   //\r
   if (!(ImageContext->IsTeImage)) {\r
-    ImageContext->EntryPoint = (PHYSICAL_ADDRESS) (UINTN) PeCoffLoaderImageAddress (\r
-                                                                ImageContext,\r
-                                                                PeHdr->OptionalHeader.AddressOfEntryPoint\r
-                                                                );\r
+    //\r
+    // Sizes of AddressOfEntryPoint are different so we need to do this safely\r
+    //\r
+    if (Hdr.Pe32->OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {\r
+      //\r
+      // Use PE32 offset\r
+      //      \r
+      ImageContext->EntryPoint = (PHYSICAL_ADDRESS)(UINTN)PeCoffLoaderImageAddress (\r
+                                                            ImageContext,\r
+                                                            (UINTN)Hdr.Pe32->OptionalHeader.AddressOfEntryPoint\r
+                                                            );\r
+    } else {\r
+      //\r
+      // Use PE32+ offset\r
+      //\r
+      ImageContext->EntryPoint = (PHYSICAL_ADDRESS)(UINTN)PeCoffLoaderImageAddress (\r
+                                                            ImageContext,\r
+                                                            (UINTN)Hdr.Pe32Plus->OptionalHeader.AddressOfEntryPoint\r
+                                                            );\r
+    }\r
   } else {\r
     ImageContext->EntryPoint =  (PHYSICAL_ADDRESS) (\r
-                       (UINTN)ImageContext->ImageAddress +\r
-                       (UINTN)TeHdr->AddressOfEntryPoint +\r
-                       (UINTN)sizeof(EFI_TE_IMAGE_HEADER) -\r
-          (UINTN) TeHdr->StrippedSize\r
-      );\r
+                                (UINTN)ImageContext->ImageAddress  +\r
+                                (UINTN)Hdr.Te->AddressOfEntryPoint +\r
+                                (UINTN)sizeof(EFI_TE_IMAGE_HEADER) -\r
+                                (UINTN)Hdr.Te->StrippedSize\r
+                                );\r
   }\r
 \r
   //\r
@@ -920,15 +996,27 @@ PeCoffLoaderLoadImage (
   // the optional header to verify a desired directory entry is there.\r
   //\r
   if (!(ImageContext->IsTeImage)) {\r
-    if (PeHdr->OptionalHeader.NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC) {\r
-      DirectoryEntry = (EFI_IMAGE_DATA_DIRECTORY *)\r
-        &PeHdr->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC];\r
+    if (Hdr.Pe32->OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {\r
+      //\r
+      // Use PE32 offset\r
+      //\r
+      NumberOfRvaAndSizes = Hdr.Pe32->OptionalHeader.NumberOfRvaAndSizes;\r
+      DirectoryEntry = (EFI_IMAGE_DATA_DIRECTORY *)&Hdr.Pe32->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC];\r
+    } else {\r
+      //\r
+      // Use PE32+ offset\r
+      //\r
+      NumberOfRvaAndSizes = Hdr.Pe32Plus->OptionalHeader.NumberOfRvaAndSizes;\r
+      DirectoryEntry = (EFI_IMAGE_DATA_DIRECTORY *)&Hdr.Pe32Plus->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC];\r
+    }\r
\r
+    if (NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC) {\r
       ImageContext->FixupDataSize = DirectoryEntry->Size / sizeof (UINT16) * sizeof (UINTN);\r
     } else {\r
       ImageContext->FixupDataSize = 0;\r
     }\r
   } else {\r
-    DirectoryEntry              = &TeHdr->DataDirectory[0];\r
+    DirectoryEntry              = &Hdr.Te->DataDirectory[0];\r
     ImageContext->FixupDataSize = DirectoryEntry->Size / sizeof (UINT16) * sizeof (UINTN);\r
   }\r
   //\r
@@ -948,18 +1036,18 @@ PeCoffLoaderLoadImage (
                     );\r
     } else {\r
       DebugEntry = (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY *)(UINTN)(\r
-                                               ImageContext->ImageAddress +\r
-                                               ImageContext->DebugDirectoryEntryRva +\r
-                                               sizeof(EFI_TE_IMAGE_HEADER) -\r
-                                               TeHdr->StrippedSize\r
-                                               );\r
+                      ImageContext->ImageAddress +\r
+                      ImageContext->DebugDirectoryEntryRva +\r
+                      sizeof(EFI_TE_IMAGE_HEADER) -\r
+                      Hdr.Te->StrippedSize\r
+                      );\r
     }\r
 \r
     if (DebugEntry != NULL) {\r
       TempDebugEntryRva = DebugEntry->RVA;\r
       if (DebugEntry->RVA == 0 && DebugEntry->FileOffset != 0) {\r
         Section--;\r
-        if ((UINTN) Section->SizeOfRawData < Section->Misc.VirtualSize) {\r
+        if ((UINTN)Section->SizeOfRawData < Section->Misc.VirtualSize) {\r
           TempDebugEntryRva = Section->VirtualAddress + Section->Misc.VirtualSize;\r
         } else {\r
           TempDebugEntryRva = Section->VirtualAddress + Section->SizeOfRawData;\r
@@ -971,11 +1059,11 @@ PeCoffLoaderLoadImage (
           ImageContext->CodeView = PeCoffLoaderImageAddress (ImageContext, TempDebugEntryRva);\r
         } else {\r
           ImageContext->CodeView = (VOID *)(\r
-                      (UINTN)ImageContext->ImageAddress +\r
-                      (UINTN)TempDebugEntryRva +\r
-                      (UINTN)sizeof(EFI_TE_IMAGE_HEADER) -\r
-                (UINTN) TeHdr->StrippedSize\r
-            );\r
+                                    (UINTN)ImageContext->ImageAddress +\r
+                                    (UINTN)TempDebugEntryRva +\r
+                                    (UINTN)sizeof (EFI_TE_IMAGE_HEADER) -\r
+                                    (UINTN) Hdr.Te->StrippedSize\r
+                                    );\r
         }\r
 \r
         if (ImageContext->CodeView == NULL) {\r
@@ -995,7 +1083,7 @@ PeCoffLoaderLoadImage (
           } else {\r
             Status = ImageContext->ImageRead (\r
                                     ImageContext->Handle,\r
-                                    DebugEntry->FileOffset + sizeof (EFI_TE_IMAGE_HEADER) - TeHdr->StrippedSize,\r
+                                    DebugEntry->FileOffset + sizeof (EFI_TE_IMAGE_HEADER) - Hdr.Te->StrippedSize,\r
                                     &Size,\r
                                     ImageContext->CodeView\r
                                     );\r
@@ -1016,11 +1104,11 @@ PeCoffLoaderLoadImage (
 \r
         switch (*(UINT32 *) ImageContext->CodeView) {\r
         case CODEVIEW_SIGNATURE_NB10:\r
-          ImageContext->PdbPointer = (CHAR8 *) ImageContext->CodeView + sizeof (EFI_IMAGE_DEBUG_CODEVIEW_NB10_ENTRY);\r
+          ImageContext->PdbPointer = (CHAR8 *)ImageContext->CodeView + sizeof (EFI_IMAGE_DEBUG_CODEVIEW_NB10_ENTRY);\r
           break;\r
 \r
         case CODEVIEW_SIGNATURE_RSDS:\r
-          ImageContext->PdbPointer = (CHAR8 *) ImageContext->CodeView + sizeof (EFI_IMAGE_DEBUG_CODEVIEW_RSDS_ENTRY);\r
+          ImageContext->PdbPointer = (CHAR8 *)ImageContext->CodeView + sizeof (EFI_IMAGE_DEBUG_CODEVIEW_RSDS_ENTRY);\r
           break;\r
 \r
         default:\r
@@ -1032,3 +1120,230 @@ PeCoffLoaderLoadImage (
 \r
   return Status;\r
 }\r
+\r
+\r
+/**\r
+  Reapply fixups on a fixed up PE32/PE32+ image to allow virutal calling at EFI\r
+  runtime. \r
+  \r
+  PE_COFF_LOADER_IMAGE_CONTEXT.FixupData stores information needed to reapply\r
+  the fixups with a virtual mapping.\r
+\r
+\r
+  @param  ImageBase          Base address of relocated image\r
+  @param  VirtImageBase      Virtual mapping for ImageBase\r
+  @param  ImageSize          Size of the image to relocate\r
+  @param  RelocationData     Location to place results of read\r
+  \r
+**/\r
+VOID\r
+EFIAPI\r
+PeCoffLoaderRelocateImageForRuntime (\r
+  IN  PHYSICAL_ADDRESS        ImageBase,\r
+  IN  PHYSICAL_ADDRESS        VirtImageBase,\r
+  IN  UINTN                   ImageSize,\r
+  IN  VOID                    *RelocationData\r
+  )\r
+{\r
+  CHAR8                               *OldBase;\r
+  CHAR8                               *NewBase;\r
+  EFI_IMAGE_DOS_HEADER                *DosHdr;\r
+  EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION Hdr;\r
+  UINT32                              NumberOfRvaAndSizes;\r
+  EFI_IMAGE_DATA_DIRECTORY            *DataDirectory;\r
+  EFI_IMAGE_DATA_DIRECTORY            *RelocDir;\r
+  EFI_IMAGE_BASE_RELOCATION           *RelocBase;\r
+  EFI_IMAGE_BASE_RELOCATION           *RelocBaseEnd;\r
+  UINT16                              *Reloc;\r
+  UINT16                              *RelocEnd;\r
+  CHAR8                               *Fixup;\r
+  CHAR8                               *FixupBase;\r
+  UINT16                              *F16;\r
+  UINT32                              *F32;\r
+  UINT64                              *F64;\r
+  CHAR8                               *FixupData;\r
+  UINTN                               Adjust;\r
+  RETURN_STATUS                       Status;\r
+\r
+  OldBase = (CHAR8 *)((UINTN)ImageBase);\r
+  NewBase = (CHAR8 *)((UINTN)VirtImageBase);\r
+  Adjust = (UINTN) NewBase - (UINTN) OldBase;\r
+\r
+  //\r
+  // Find the image's relocate dir info\r
+  //\r
+  DosHdr = (EFI_IMAGE_DOS_HEADER *)OldBase;\r
+  if (DosHdr->e_magic == EFI_IMAGE_DOS_SIGNATURE) {\r
+    //\r
+    // Valid DOS header so get address of PE header\r
+    //\r
+    Hdr.Pe32 = (EFI_IMAGE_NT_HEADERS32 *)(((CHAR8 *)DosHdr) + DosHdr->e_lfanew);\r
+  } else {\r
+    //\r
+    // No Dos header so assume image starts with PE header.\r
+    //\r
+    Hdr.Pe32 = (EFI_IMAGE_NT_HEADERS32 *)OldBase;\r
+  }\r
+\r
+  if (Hdr.Pe32->Signature != EFI_IMAGE_NT_SIGNATURE) {\r
+    //\r
+    // Not a valid PE image so Exit\r
+    //\r
+    return ;\r
+  }\r
+\r
+  //\r
+  // Get some data from the PE type dependent data\r
+  //\r
+  if (Hdr.Pe32->OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {\r
+    //     \r
+    // Use PE32 offset\r
+    //\r
+    NumberOfRvaAndSizes = Hdr.Pe32->OptionalHeader.NumberOfRvaAndSizes;\r
+    DataDirectory = (EFI_IMAGE_DATA_DIRECTORY *)&(Hdr.Pe32->OptionalHeader.DataDirectory[0]);\r
+  } else {\r
+    //     \r
+    // Use PE32+ offset\r
+    //\r
+    NumberOfRvaAndSizes = Hdr.Pe32Plus->OptionalHeader.NumberOfRvaAndSizes;\r
+    DataDirectory = (EFI_IMAGE_DATA_DIRECTORY *)&(Hdr.Pe32Plus->OptionalHeader.DataDirectory[0]);\r
+  }    \r
+\r
+  //\r
+  // Find the relocation block\r
+  //\r
+  // Per the PE/COFF spec, you can't assume that a given data directory\r
+  // is present in the image. You have to check the NumberOfRvaAndSizes in\r
+  // the optional header to verify a desired directory entry is there.\r
+  //    \r
+  if (NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC) {\r
+    RelocDir      = DataDirectory + EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC;\r
+    RelocBase     = (EFI_IMAGE_BASE_RELOCATION *)(UINTN)(ImageBase + RelocDir->VirtualAddress);\r
+    RelocBaseEnd  = (EFI_IMAGE_BASE_RELOCATION *)(UINTN)(ImageBase + RelocDir->VirtualAddress + RelocDir->Size);\r
+  } else {\r
+    //\r
+    // Cannot find relocations, cannot continue\r
+    //\r
+    ASSERT (FALSE);\r
+    return ;\r
+  }\r
+\r
+  ASSERT (RelocBase != NULL && RelocBaseEnd != NULL);\r
+\r
+  //\r
+  // Run the whole relocation block. And re-fixup data that has not been\r
+  // modified. The FixupData is used to see if the image has been modified\r
+  // since it was relocated. This is so data sections that have been updated\r
+  // by code will not be fixed up, since that would set them back to\r
+  // defaults.\r
+  //\r
+  FixupData = RelocationData;\r
+  while (RelocBase < RelocBaseEnd) {\r
+\r
+    Reloc     = (UINT16 *) ((UINT8 *) RelocBase + sizeof (EFI_IMAGE_BASE_RELOCATION));\r
+    RelocEnd  = (UINT16 *) ((UINT8 *) RelocBase + RelocBase->SizeOfBlock);\r
+    FixupBase = (CHAR8 *) ((UINTN)ImageBase) + RelocBase->VirtualAddress;\r
+\r
+    //\r
+    // Run this relocation record\r
+    //\r
+    while (Reloc < RelocEnd) {\r
+\r
+      Fixup = FixupBase + (*Reloc & 0xFFF);\r
+      switch ((*Reloc) >> 12) {\r
+\r
+      case EFI_IMAGE_REL_BASED_ABSOLUTE:\r
+        break;\r
+\r
+      case EFI_IMAGE_REL_BASED_HIGH:\r
+        F16 = (UINT16 *) Fixup;\r
+        if (*(UINT16 *) FixupData == *F16) {\r
+          *F16 = (UINT16) (*F16 + ((UINT16)(Adjust >> 16)));\r
+        }\r
+\r
+        FixupData = FixupData + sizeof (UINT16);\r
+        break;\r
+\r
+      case EFI_IMAGE_REL_BASED_LOW:\r
+        F16 = (UINT16 *) Fixup;\r
+        if (*(UINT16 *) FixupData == *F16) {\r
+          *F16 = (UINT16) (*F16 + ((UINT16) Adjust & 0xffff));\r
+        }\r
+\r
+        FixupData = FixupData + sizeof (UINT16);\r
+        break;\r
+\r
+      case EFI_IMAGE_REL_BASED_HIGHLOW:\r
+        F32       = (UINT32 *) Fixup;\r
+        FixupData = ALIGN_POINTER (FixupData, sizeof (UINT32));\r
+        if (*(UINT32 *) FixupData == *F32) {\r
+          *F32 = *F32 + (UINT32) Adjust;\r
+        }\r
+\r
+        FixupData = FixupData + sizeof (UINT32);\r
+        break;\r
+\r
+      case EFI_IMAGE_REL_BASED_DIR64:\r
+        F64       = (UINT64 *)Fixup;\r
+        FixupData = ALIGN_POINTER (FixupData, sizeof (UINT64));\r
+        if (*(UINT64 *) FixupData == *F64) {\r
+          *F64 = *F64 + (UINT64)Adjust;\r
+        }\r
+\r
+        FixupData = FixupData + sizeof (UINT64);\r
+        break;\r
+\r
+      case EFI_IMAGE_REL_BASED_HIGHADJ:\r
+        //\r
+        // Not implemented, but not used in EFI 1.0\r
+        //\r
+        ASSERT (FALSE);\r
+        break;\r
+\r
+      default:\r
+        //\r
+        // Only Itanium requires ConvertPeImage_Ex\r
+        //\r
+        Status = PeHotRelocateImageEx (Reloc, Fixup, &FixupData, Adjust);\r
+        if (RETURN_ERROR (Status)) {\r
+          return ;\r
+        }\r
+      }\r
+      //\r
+      // Next relocation record\r
+      //\r
+      Reloc += 1;\r
+    }\r
+    //\r
+    // next reloc block\r
+    //\r
+    RelocBase = (EFI_IMAGE_BASE_RELOCATION *) RelocEnd;\r
+  }\r
+}\r
+\r
+\r
+/**\r
+  ImageRead function that operates on a memory buffer whos base is passed into\r
+  FileHandle. \r
+\r
+  @param  FileHandle        Ponter to baes of the input stream\r
+  @param  FileOffset        Offset to the start of the buffer\r
+  @param  ReadSize          Number of bytes to copy into the buffer\r
+  @param  Buffer            Location to place results of read\r
+\r
+  @retval RETURN_SUCCESS    Data is read from FileOffset from the Handle into \r
+                            the buffer.\r
+**/\r
+RETURN_STATUS\r
+EFIAPI\r
+PeCoffLoaderImageReadFromMemory (\r
+  IN     VOID    *FileHandle,\r
+  IN     UINTN   FileOffset,\r
+  IN OUT UINTN   *ReadSize,\r
+  OUT    VOID    *Buffer\r
+  )\r
+{\r
+  CopyMem (Buffer, ((UINT8 *)FileHandle) + FileOffset, *ReadSize);\r
+  return RETURN_SUCCESS;\r
+}\r
+\r