--- /dev/null
+/*++\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