]> git.proxmox.com Git - mirror_edk2.git/blobdiff - DuetPkg/EfiLdr/PeLoader.c
Add missing module for duet package.
[mirror_edk2.git] / DuetPkg / EfiLdr / PeLoader.c
diff --git a/DuetPkg/EfiLdr/PeLoader.c b/DuetPkg/EfiLdr/PeLoader.c
new file mode 100644 (file)
index 0000000..73608da
--- /dev/null
@@ -0,0 +1,641 @@
+/*++\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
+which accompanies this distribution.  The full text of the license may be found at        \r
+http://opensource.org/licenses/bsd-license.php                                            \r
+                                                                                          \r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     \r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             \r
+\r
+Module Name:\r
+  PeLoader.c\r
+\r
+Abstract:\r
+\r
+Revision History:\r
+\r
+--*/\r
+#include "EfiLdr.h"\r
+#include "Debug.h"\r
+#include "Support.h"\r
+\r
+STATIC\r
+EFI_STATUS\r
+EfiLdrPeCoffLoadPeRelocate (\r
+  IN EFILDR_LOADED_IMAGE      *Image,\r
+  IN EFI_IMAGE_DATA_DIRECTORY *RelocDir,\r
+  IN UINTN                     Adjust,\r
+  IN UINTN                    *NumberOfMemoryMapEntries,\r
+  IN EFI_MEMORY_DESCRIPTOR    *EfiMemoryDescriptor\r
+  );\r
+\r
+STATIC\r
+EFI_STATUS\r
+EfiLdrPeCoffImageRead (\r
+    IN VOID                 *FHand,\r
+    IN UINTN                Offset,\r
+    IN OUT UINTN            ReadSize,\r
+    OUT VOID                *Buffer\r
+    );\r
+\r
+STATIC\r
+VOID *\r
+EfiLdrPeCoffImageAddress (\r
+  IN EFILDR_LOADED_IMAGE     *Image,\r
+  IN UINTN                   Address\r
+  );\r
+\r
+\r
+EFI_STATUS\r
+EfiLdrPeCoffSetImageType (\r
+  IN OUT EFILDR_LOADED_IMAGE      *Image,\r
+  IN UINTN                        ImageType\r
+  );\r
+\r
+EFI_STATUS\r
+EfiLdrPeCoffCheckImageMachineType (\r
+  IN UINT16           MachineType\r
+  );\r
+\r
+EFI_STATUS\r
+EfiLdrGetPeImageInfo (\r
+  IN  VOID                    *FHand,\r
+  OUT UINT64                  *ImageBase,\r
+  OUT UINT32                  *ImageSize\r
+  )\r
+{\r
+  EFI_STATUS                        Status;\r
+  EFI_IMAGE_DOS_HEADER              DosHdr;\r
+  EFI_IMAGE_OPTIONAL_HEADER_UNION   PeHdr;\r
+\r
+  ZeroMem (&DosHdr, sizeof(DosHdr));\r
+  ZeroMem (&PeHdr, sizeof(PeHdr));\r
+\r
+  //\r
+  // Read image headers\r
+  //\r
+\r
+  EfiLdrPeCoffImageRead (FHand, 0, sizeof(DosHdr), &DosHdr);\r
+  if (DosHdr.e_magic != EFI_IMAGE_DOS_SIGNATURE) {\r
+    return EFI_UNSUPPORTED;\r
+  }\r
+\r
+  EfiLdrPeCoffImageRead (FHand, DosHdr.e_lfanew, sizeof(PeHdr), &PeHdr);\r
+\r
+  if (PeHdr.Pe32.Signature != EFI_IMAGE_NT_SIGNATURE) {\r
+    return EFI_UNSUPPORTED;\r
+  }\r
+    \r
+  //\r
+  // Verify machine type\r
+  //\r
+\r
+  Status = EfiLdrPeCoffCheckImageMachineType (PeHdr.Pe32.FileHeader.Machine);\r
+  if (EFI_ERROR(Status)) {\r
+    return Status;\r
+  }\r
+\r
+  if (PeHdr.Pe32.OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {\r
+    *ImageBase = (UINT32)PeHdr.Pe32.OptionalHeader.ImageBase;\r
+  } else if (PeHdr.Pe32.OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC) {\r
+    *ImageBase = PeHdr.Pe32Plus.OptionalHeader.ImageBase;\r
+  } else {\r
+    return EFI_UNSUPPORTED;\r
+  }\r
+  \r
+  *ImageSize = PeHdr.Pe32.OptionalHeader.SizeOfImage;\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+EfiLdrPeCoffLoadPeImage (\r
+  IN VOID                     *FHand,\r
+  IN EFILDR_LOADED_IMAGE      *Image,\r
+  IN UINTN                    *NumberOfMemoryMapEntries,\r
+  IN EFI_MEMORY_DESCRIPTOR    *EfiMemoryDescriptor\r
+  )\r
+{\r
+  EFI_IMAGE_DOS_HEADER            DosHdr;\r
+  EFI_IMAGE_OPTIONAL_HEADER_UNION PeHdr;\r
+  EFI_IMAGE_SECTION_HEADER        *FirstSection;\r
+  EFI_IMAGE_SECTION_HEADER        *Section;\r
+  UINTN                           Index;\r
+  EFI_STATUS                      Status;\r
+  UINT8                           *Base;\r
+  UINT8                           *End;\r
+  EFI_IMAGE_DATA_DIRECTORY        *DirectoryEntry;\r
+  UINTN                           DirCount;\r
+  EFI_IMAGE_DEBUG_DIRECTORY_ENTRY TempDebugEntry;\r
+  EFI_IMAGE_DEBUG_DIRECTORY_ENTRY *DebugEntry;\r
+  UINTN                           CodeViewSize;\r
+  UINTN                           CodeViewOffset;\r
+  UINTN                           CodeViewFileOffset;\r
+  UINTN                           OptionalHeaderSize;\r
+  UINTN                           PeHeaderSize;\r
+  UINT32                          NumberOfRvaAndSizes;\r
+  EFI_IMAGE_DATA_DIRECTORY        *DataDirectory;\r
+  UINT64                          ImageBase;\r
+\r
+  ZeroMem (&DosHdr, sizeof(DosHdr));\r
+  ZeroMem (&PeHdr, sizeof(PeHdr));\r
+\r
+  //\r
+  // Read image headers\r
+  //\r
+\r
+  EfiLdrPeCoffImageRead (FHand, 0, sizeof(DosHdr), &DosHdr);\r
+  if (DosHdr.e_magic != EFI_IMAGE_DOS_SIGNATURE) {\r
+//    DEBUG ((D_LOAD, "PeCoffLoadPeImage: Dos header signature not found\n"));\r
+PrintHeader ('F');\r
+    return EFI_UNSUPPORTED;\r
+  }\r
+\r
+  EfiLdrPeCoffImageRead (FHand, DosHdr.e_lfanew, sizeof(PeHdr), &PeHdr);\r
+\r
+  if (PeHdr.Pe32.Signature != EFI_IMAGE_NT_SIGNATURE) {\r
+//    DEBUG ((D_LOAD, "PeCoffLoadPeImage: PE image header signature not found\n"));\r
+PrintHeader ('G');\r
+    return EFI_UNSUPPORTED;\r
+  }\r
+    \r
+  //\r
+  // Set the image subsystem type\r
+  //\r
+\r
+  Status = EfiLdrPeCoffSetImageType (Image, PeHdr.Pe32.OptionalHeader.Subsystem);\r
+  if (EFI_ERROR(Status)) {\r
+//    DEBUG ((D_LOAD, "PeCoffLoadPeImage: Subsystem type not known\n"));\r
+PrintHeader ('H');\r
+    return Status;\r
+  }\r
+\r
+  //\r
+  // Verify machine type\r
+  //\r
+\r
+  Status = EfiLdrPeCoffCheckImageMachineType (PeHdr.Pe32.FileHeader.Machine);\r
+  if (EFI_ERROR(Status)) {\r
+//    DEBUG ((D_LOAD, "PeCoffLoadPeImage: Incorrect machine type\n"));\r
+PrintHeader ('I');\r
+    return Status;\r
+  }\r
+\r
+  //\r
+  // Compute the amount of memory needed to load the image and \r
+  // allocate it.  This will include all sections plus the codeview debug info.\r
+  // Since the codeview info is actually outside of the image, we calculate\r
+  // its size seperately and add it to the total.\r
+  //\r
+  // Memory starts off as data\r
+  //\r
+\r
+  CodeViewSize       = 0;\r
+  CodeViewFileOffset = 0;\r
+  if (PeHdr.Pe32.OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {\r
+    DirectoryEntry = (EFI_IMAGE_DATA_DIRECTORY *)&(PeHdr.Pe32.OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG]);\r
+  } else if (PeHdr.Pe32.OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC) {\r
+    DirectoryEntry = (EFI_IMAGE_DATA_DIRECTORY *)&(PeHdr.Pe32Plus.OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG]);\r
+  } else {\r
+    return EFI_UNSUPPORTED;\r
+  }\r
+  for (DirCount = 0; \r
+       (DirCount < DirectoryEntry->Size / sizeof (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY)) && (CodeViewSize == 0);\r
+       DirCount++) {\r
+    Status = EfiLdrPeCoffImageRead (\r
+               FHand, \r
+               DirectoryEntry->VirtualAddress + DirCount * sizeof (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY),\r
+               sizeof (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY),\r
+               &TempDebugEntry\r
+               );\r
+    if (!EFI_ERROR (Status)) {\r
+      if (TempDebugEntry.Type == EFI_IMAGE_DEBUG_TYPE_CODEVIEW) {\r
+        CodeViewSize = TempDebugEntry.SizeOfData;\r
+        CodeViewFileOffset = TempDebugEntry.FileOffset;\r
+      }\r
+    }\r
+  }\r
+    \r
+  CodeViewOffset = PeHdr.Pe32.OptionalHeader.SizeOfImage + PeHdr.Pe32.OptionalHeader.SectionAlignment;\r
+  Image->NoPages = EFI_SIZE_TO_PAGES (CodeViewOffset + CodeViewSize);\r
+\r
+  //\r
+  // Compute the amount of memory needed to load the image and \r
+  // allocate it.  Memory starts off as data\r
+  //\r
+\r
+  Image->ImageBasePage = (EFI_PHYSICAL_ADDRESS)FindSpace (Image->NoPages, NumberOfMemoryMapEntries, EfiMemoryDescriptor, EfiRuntimeServicesCode, EFI_MEMORY_WB);\r
+  if (Image->ImageBasePage == 0) {\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+\r
+  if (EFI_ERROR(Status)) {\r
+PrintHeader ('J');\r
+    return Status;\r
+  }\r
+\r
+//  DEBUG((D_LOAD, "LoadPe: new image base %lx\n", Image->ImageBasePage));\r
+  Image->Info.ImageBase = (VOID *)(UINTN)Image->ImageBasePage;\r
+  Image->Info.ImageSize = (Image->NoPages << EFI_PAGE_SHIFT) - 1;\r
+  Image->ImageBase      = (UINT8 *)(UINTN)Image->ImageBasePage;\r
+  Image->ImageEof       = Image->ImageBase + Image->Info.ImageSize;\r
+  Image->ImageAdjust    = Image->ImageBase;\r
+\r
+  //\r
+  // Copy the Image header to the base location\r
+  //\r
+  Status = EfiLdrPeCoffImageRead (\r
+             FHand, \r
+             0, \r
+             PeHdr.Pe32.OptionalHeader.SizeOfHeaders, \r
+             Image->ImageBase\r
+             );\r
+\r
+  if (EFI_ERROR(Status)) {\r
+PrintHeader ('K');\r
+    return Status;\r
+  }\r
+\r
+  //\r
+  // Load each directory of the image into memory... \r
+  //  Save the address of the Debug directory for later\r
+  //\r
+  if (PeHdr.Pe32.OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {\r
+    NumberOfRvaAndSizes = PeHdr.Pe32.OptionalHeader.NumberOfRvaAndSizes;\r
+    DataDirectory = PeHdr.Pe32.OptionalHeader.DataDirectory;\r
+  } else {\r
+    NumberOfRvaAndSizes = PeHdr.Pe32Plus.OptionalHeader.NumberOfRvaAndSizes;\r
+    DataDirectory = PeHdr.Pe32Plus.OptionalHeader.DataDirectory;\r
+  }\r
+  DebugEntry = NULL;\r
+  for (Index = 0; Index < NumberOfRvaAndSizes; Index++) {\r
+    if ((DataDirectory[Index].VirtualAddress != 0) && (DataDirectory[Index].Size != 0)) {\r
+      Status = EfiLdrPeCoffImageRead (\r
+                 FHand,\r
+                 DataDirectory[Index].VirtualAddress,\r
+                 DataDirectory[Index].Size,\r
+                 Image->ImageBase + DataDirectory[Index].VirtualAddress\r
+                 );\r
+      if (EFI_ERROR(Status)) {\r
+        return Status;\r
+      }\r
+      if (Index == EFI_IMAGE_DIRECTORY_ENTRY_DEBUG) {\r
+        DebugEntry = (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY *) (Image->ImageBase + DataDirectory[Index].VirtualAddress);\r
+      }\r
+    }\r
+  }\r
+\r
+  //\r
+  // Load each section of the image\r
+  //\r
+\r
+  // BUGBUG: change this to use the in memory copy\r
+  if (PeHdr.Pe32.OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {\r
+    OptionalHeaderSize = sizeof(EFI_IMAGE_OPTIONAL_HEADER32);\r
+    PeHeaderSize       = sizeof(EFI_IMAGE_NT_HEADERS32);\r
+  } else {\r
+    OptionalHeaderSize = sizeof(EFI_IMAGE_OPTIONAL_HEADER64);\r
+    PeHeaderSize       = sizeof(EFI_IMAGE_NT_HEADERS64);\r
+  }\r
+  FirstSection = (EFI_IMAGE_SECTION_HEADER *) (\r
+                   Image->ImageBase +\r
+                   DosHdr.e_lfanew + \r
+                   PeHeaderSize + \r
+                   PeHdr.Pe32.FileHeader.SizeOfOptionalHeader - \r
+                   OptionalHeaderSize\r
+                   );\r
+\r
+  Section = FirstSection;\r
+  for (Index=0; Index < PeHdr.Pe32.FileHeader.NumberOfSections; Index += 1) {\r
+\r
+    //\r
+    // Compute sections address\r
+    //\r
+\r
+    Base = EfiLdrPeCoffImageAddress (Image, (UINTN)Section->VirtualAddress);\r
+    End = EfiLdrPeCoffImageAddress (Image, (UINTN)(Section->VirtualAddress + Section->Misc.VirtualSize));\r
+        \r
+    if (EFI_ERROR(Status) || !Base || !End) {\r
+//      DEBUG((D_LOAD|D_ERROR, "LoadPe: Section %d was not loaded\n", Index));\r
+PrintHeader ('L');\r
+      return EFI_LOAD_ERROR;\r
+    }\r
+\r
+//    DEBUG((D_LOAD, "LoadPe: Section %d, loaded at %x\n", Index, Base));\r
+\r
+    //\r
+    // Read the section\r
+    //\r
\r
+    if (Section->SizeOfRawData) {\r
+      Status = EfiLdrPeCoffImageRead (FHand, Section->PointerToRawData, Section->SizeOfRawData, Base);\r
+      if (EFI_ERROR(Status)) {\r
+PrintHeader ('M');\r
+        return Status;\r
+      }\r
+    }\r
+\r
+    //\r
+    // If raw size is less then virt size, zero fill the remaining\r
+    //\r
+\r
+    if (Section->SizeOfRawData < Section->Misc.VirtualSize) {\r
+      ZeroMem (\r
+        Base + Section->SizeOfRawData, \r
+        Section->Misc.VirtualSize - Section->SizeOfRawData\r
+        );\r
+    }\r
+\r
+    //\r
+    // Next Section\r
+    //\r
+\r
+    Section += 1;\r
+  }\r
+\r
+  //\r
+  // Copy in CodeView information if it exists\r
+  //\r
+  if (CodeViewSize != 0) {\r
+    Status = EfiLdrPeCoffImageRead (FHand, CodeViewFileOffset, CodeViewSize, Image->ImageBase + CodeViewOffset);\r
+    DebugEntry->RVA = (UINT32) (CodeViewOffset);\r
+  }\r
+\r
+  //\r
+  // Apply relocations only if needed\r
+  //\r
+  if (PeHdr.Pe32.OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {\r
+    ImageBase = (UINT64)PeHdr.Pe32.OptionalHeader.ImageBase;\r
+  } else {\r
+    ImageBase = PeHdr.Pe32Plus.OptionalHeader.ImageBase;\r
+  }\r
+  if ((UINTN)(Image->ImageBase) != (UINTN) (ImageBase)) {\r
+    Status = EfiLdrPeCoffLoadPeRelocate (\r
+               Image,\r
+               &DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC],\r
+               (UINTN) Image->ImageBase - (UINTN)ImageBase,\r
+               NumberOfMemoryMapEntries,\r
+               EfiMemoryDescriptor\r
+               );\r
+\r
+    if (EFI_ERROR(Status)) {\r
+PrintHeader ('N');\r
+      return Status;\r
+    }\r
+  }\r
+\r
+  //\r
+  // Use exported EFI specific interface if present, else use the image's entry point\r
+  //\r
+  Image->EntryPoint = (EFI_IMAGE_ENTRY_POINT)(UINTN)\r
+                        (EfiLdrPeCoffImageAddress(\r
+                           Image, \r
+                           PeHdr.Pe32.OptionalHeader.AddressOfEntryPoint\r
+                           ));\r
+\r
+  return Status;\r
+}\r
+\r
+STATIC\r
+EFI_STATUS\r
+EfiLdrPeCoffLoadPeRelocate (\r
+  IN EFILDR_LOADED_IMAGE      *Image,\r
+  IN EFI_IMAGE_DATA_DIRECTORY *RelocDir,\r
+  IN UINTN                     Adjust,\r
+  IN UINTN                    *NumberOfMemoryMapEntries,\r
+  IN EFI_MEMORY_DESCRIPTOR    *EfiMemoryDescriptor\r
+  )\r
+{\r
+  EFI_IMAGE_BASE_RELOCATION   *RelocBase;\r
+  EFI_IMAGE_BASE_RELOCATION   *RelocBaseEnd;\r
+  UINT16                      *Reloc;\r
+  UINT16                      *RelocEnd;\r
+  UINT8                       *Fixup;\r
+  UINT8                       *FixupBase;\r
+  UINT16                      *F16;\r
+  UINT32                      *F32;\r
+  UINT64                      *F64;\r
+  UINT8                       *FixupData;\r
+  UINTN                       NoFixupPages;\r
+\r
+  //\r
+  // Find the relocation block\r
+  //\r
+\r
+  RelocBase = EfiLdrPeCoffImageAddress (Image, RelocDir->VirtualAddress);\r
+  RelocBaseEnd = EfiLdrPeCoffImageAddress (Image, RelocDir->VirtualAddress + RelocDir->Size);\r
+  if (!RelocBase || !RelocBaseEnd) {\r
+PrintHeader ('O');\r
+    return EFI_LOAD_ERROR;\r
+  }\r
+\r
+  NoFixupPages = EFI_SIZE_TO_PAGES(RelocDir->Size / sizeof(UINT16) * sizeof(UINTN));\r
+  Image->FixupData = (UINT8*) FindSpace (NoFixupPages, NumberOfMemoryMapEntries, EfiMemoryDescriptor, EfiRuntimeServicesData, EFI_MEMORY_WB);\r
+  if (Image->FixupData == 0) {\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+\r
+  //\r
+  // Run the whole relocation block\r
+  //\r
+\r
+  FixupData = Image->FixupData;\r
+  while (RelocBase < RelocBaseEnd) {\r
+           \r
+    Reloc = (UINT16 *) ((UINT8 *) RelocBase + sizeof(EFI_IMAGE_BASE_RELOCATION));\r
+    RelocEnd = (UINT16 *) ((UINT8 *) RelocBase + RelocBase->SizeOfBlock);\r
+    FixupBase = EfiLdrPeCoffImageAddress (Image, RelocBase->VirtualAddress);\r
+    if ((UINT8 *) RelocEnd < Image->ImageBase || (UINT8 *) RelocEnd > Image->ImageEof) {\r
+PrintHeader ('P');\r
+      return EFI_LOAD_ERROR;\r
+    }\r
+\r
+    //\r
+    // Run this relocation record\r
+    //\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
+        *F16  = (UINT16) (*F16 + (UINT16)(((UINT32)Adjust) >> 16));\r
+        if (FixupData != NULL) {\r
+          *(UINT16 *) FixupData = *F16;\r
+          FixupData = FixupData + sizeof(UINT16);\r
+        }\r
+        break;\r
+\r
+      case EFI_IMAGE_REL_BASED_LOW:\r
+        F16 = (UINT16 *) Fixup;\r
+        *F16 = *F16 + (UINT16) Adjust;\r
+        if (FixupData != NULL) {\r
+          *(UINT16 *) FixupData = *F16;\r
+          FixupData = FixupData + sizeof(UINT16);\r
+        }\r
+        break;\r
+\r
+      case EFI_IMAGE_REL_BASED_HIGHLOW:\r
+        F32 = (UINT32 *) Fixup;\r
+        *F32 = *F32 + (UINT32) Adjust;\r
+        if (FixupData != NULL) {\r
+          FixupData = ALIGN_POINTER(FixupData, sizeof(UINT32));\r
+          *(UINT32 *) FixupData = *F32;\r
+          FixupData = FixupData + sizeof(UINT32);\r
+        }\r
+        break;\r
+\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
+      case EFI_IMAGE_REL_BASED_HIGHADJ:\r
+        CpuDeadLoop();                 // BUGBUG: not done\r
+        break;\r
+\r
+      default:\r
+//        DEBUG((D_LOAD|D_ERROR, "PeRelocate: unknown fixed type\n"));\r
+PrintHeader ('Q');\r
+        CpuDeadLoop();\r
+        return EFI_LOAD_ERROR;\r
+      }\r
+\r
+      // Next reloc record\r
+      Reloc += 1;\r
+    }\r
+\r
+    // next reloc block\r
+    RelocBase = (EFI_IMAGE_BASE_RELOCATION *) RelocEnd;\r
+  }\r
+\r
+  //\r
+  // Add Fixup data to whole Image (assume Fixup data just below the image), so that there is no hole in the descriptor.\r
+  // Because only NoPages or ImageBasePage will be used in EfiLoader(), we update these 2 fields.\r
+  //\r
+  Image->NoPages += NoFixupPages;\r
+  Image->ImageBasePage -= (NoFixupPages << EFI_PAGE_SHIFT);\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+STATIC\r
+EFI_STATUS\r
+EfiLdrPeCoffImageRead (\r
+  IN VOID                 *FHand,\r
+  IN UINTN                Offset,\r
+  IN OUT UINTN            ReadSize,\r
+  OUT VOID                *Buffer\r
+  )\r
+{\r
+  CopyMem (Buffer, (VOID *)((UINTN)FHand + Offset), ReadSize);\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+STATIC\r
+VOID *\r
+EfiLdrPeCoffImageAddress (\r
+  IN EFILDR_LOADED_IMAGE     *Image,\r
+  IN UINTN                   Address\r
+  )\r
+{\r
+  UINT8        *FixedAddress;\r
+\r
+  FixedAddress = Image->ImageAdjust + Address;\r
+\r
+  if ((FixedAddress < Image->ImageBase) || (FixedAddress > Image->ImageEof)) {\r
+//    DEBUG((D_LOAD|D_ERROR, "PeCoffImageAddress: pointer is outside of image\n"));\r
+    FixedAddress = NULL;\r
+  }\r
+\r
+//  DEBUG((\r
+//    D_LOAD,\r
+//    "PeCoffImageAddress: ImageBase %x, ImageEof %x, Address %x, FixedAddress %x\n", \r
+//    Image->ImageBase,\r
+//    Image->ImageEof,\r
+//    Address,\r
+//    FixedAddress\r
+//    ));\r
+    return FixedAddress;\r
+}\r
+\r
+\r
+EFI_STATUS\r
+EfiLdrPeCoffSetImageType (\r
+  IN OUT EFILDR_LOADED_IMAGE      *Image,\r
+  IN UINTN                        ImageType\r
+  )\r
+{\r
+  EFI_MEMORY_TYPE                 CodeType;\r
+  EFI_MEMORY_TYPE                 DataType;\r
+\r
+  switch (ImageType) {\r
+  case EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION:\r
+    CodeType = EfiLoaderCode;\r
+    DataType = EfiLoaderData;\r
+    break;\r
+\r
+  case EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER:\r
+    CodeType = EfiBootServicesCode;\r
+    DataType = EfiBootServicesData;\r
+    break;\r
+\r
+  case EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER:\r
+    CodeType = EfiRuntimeServicesCode;\r
+    DataType = EfiRuntimeServicesData;\r
+    break;\r
+\r
+  default:\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  Image->Type = ImageType;\r
+  Image->Info.ImageCodeType = CodeType;    \r
+  Image->Info.ImageDataType = DataType;\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+EfiLdrPeCoffCheckImageMachineType (\r
+  IN UINT16           MachineType\r
+  )\r
+{\r
+  EFI_STATUS          Status;\r
+\r
+  Status = EFI_UNSUPPORTED;\r
+\r
+#if EFI32\r
+  if (MachineType == EFI_IMAGE_MACHINE_IA32) {\r
+    Status = EFI_SUCCESS;\r
+  }\r
+#endif\r
+\r
+#if EFIX64\r
+  if (MachineType == EFI_IMAGE_MACHINE_X64) {\r
+    Status = EFI_SUCCESS;\r
+  }\r
+#endif\r
+\r
+#if EFI64\r
+  if (MachineType == EFI_IMAGE_MACHINE_IA64) {\r
+    Status = EFI_SUCCESS;\r
+  }\r
+#endif\r
+\r
+  return Status;\r
+}\r
+\r