summaryrefslogtreecommitdiff
path: root/EdkModulePkg/Library
diff options
context:
space:
mode:
authorlgao4 <lgao4@6f19259b-4bc3-4df7-8a09-765794883524>2006-05-14 09:16:06 +0000
committerlgao4 <lgao4@6f19259b-4bc3-4df7-8a09-765794883524>2006-05-14 09:16:06 +0000
commit1b7b460ff9e302343d92c03d78dd713570051b36 (patch)
treeeab6737f4ad1fb6f72e86dd36e4811567c75a3ec /EdkModulePkg/Library
parente20ee534ac22960fef84e868cb45eb54b813a290 (diff)
downloadedk2-platforms-1b7b460ff9e302343d92c03d78dd713570051b36.tar.xz
git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@151 6f19259b-4bc3-4df7-8a09-765794883524
Diffstat (limited to 'EdkModulePkg/Library')
-rw-r--r--EdkModulePkg/Library/EdkPeCoffLoaderLibX64/EdkPeCoffLoaderLibX64.c940
-rw-r--r--EdkModulePkg/Library/EdkPeCoffLoaderLibX64/EdkPeCoffLoaderLibX64.mbd19
-rw-r--r--EdkModulePkg/Library/EdkPeCoffLoaderLibX64/EdkPeCoffLoaderLibX64.msa35
-rw-r--r--EdkModulePkg/Library/EdkPeCoffLoaderLibX64/build.xml46
4 files changed, 1040 insertions, 0 deletions
diff --git a/EdkModulePkg/Library/EdkPeCoffLoaderLibX64/EdkPeCoffLoaderLibX64.c b/EdkModulePkg/Library/EdkPeCoffLoaderLibX64/EdkPeCoffLoaderLibX64.c
new file mode 100644
index 0000000000..5ed74f5a92
--- /dev/null
+++ b/EdkModulePkg/Library/EdkPeCoffLoaderLibX64/EdkPeCoffLoaderLibX64.c
@@ -0,0 +1,940 @@
+/*++
+
+Copyright (c) 2006, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+
+ EdkPeCoffLoaderX64.c
+
+Abstract:
+
+ Wrap the Base PE/COFF loader with the PE COFF Protocol
+
+
+--*/
+
+#define IMAGE_64_MACHINE_TYPE_SUPPORTED(Machine) \
+ ((Machine) == EFI_IMAGE_MACHINE_IA32 || \
+ (Machine) == EFI_IMAGE_MACHINE_X64 || \
+ (Machine) == EFI_IMAGE_MACHINE_EBC)
+
+STATIC
+EFI_STATUS
+PeCoffLoader64GetPeHeader (
+ IN OUT PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext,
+ OUT EFI_IMAGE_NT_HEADERS64 *PeHdr
+ );
+
+STATIC
+EFI_STATUS
+PeCoffLoader64CheckImageType (
+ IN OUT PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext,
+ IN EFI_IMAGE_NT_HEADERS64 *PeHdr
+ );
+
+STATIC
+VOID *
+PeCoffLoader64ImageAddress (
+ IN OUT PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext,
+ IN UINTN Address
+ );
+
+EFI_STATUS
+EFIAPI
+PeCoffLoader64GetImageInfo (
+ IN EFI_PEI_PE_COFF_LOADER_PROTOCOL *This,
+ IN OUT PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext
+ );
+
+EFI_STATUS
+EFIAPI
+PeCoffLoader64RelocateImage (
+ IN EFI_PEI_PE_COFF_LOADER_PROTOCOL *This,
+ IN OUT PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext
+ );
+
+EFI_STATUS
+EFIAPI
+PeCoffLoader64LoadImage (
+ IN EFI_PEI_PE_COFF_LOADER_PROTOCOL *This,
+ IN OUT PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext
+ );
+
+EFI_STATUS
+EFIAPI
+PeCoffLoader64UnloadImage (
+ IN EFI_PEI_PE_COFF_LOADER_PROTOCOL *This,
+ IN PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext
+ );
+
+EFI_STATUS
+PeCoffLoader64RelocateImageEx (
+ IN UINT16 *Reloc,
+ IN OUT CHAR8 *Fixup,
+ IN OUT CHAR8 **FixupData,
+ IN UINT64 Adjust
+ );
+
+EFI_PEI_PE_COFF_LOADER_PROTOCOL mPeCoffLoaderX64 = {
+ PeCoffLoader64GetImageInfo,
+ PeCoffLoader64LoadImage,
+ PeCoffLoader64RelocateImage,
+ PeCoffLoader64UnloadImage
+};
+
+STATIC
+EFI_STATUS
+PeCoffLoader64GetPeHeader (
+ IN OUT PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext,
+ OUT EFI_IMAGE_NT_HEADERS64 *PeHdr
+ )
+/*++
+
+Routine Description:
+ Retrieves the PE Header from a PE/COFF image
+
+Arguments:
+ ImageContext - The context of the image being loaded
+ PeHdr - The buffer in which to return the PE header
+
+Returns:
+ EFI_SUCCESS if the PE Header is read,
+ Otherwise, the error status from reading the PE/COFF image using the ImageRead function.
+
+--*/
+{
+ EFI_STATUS Status;
+ EFI_IMAGE_DOS_HEADER DosHdr;
+ UINTN Size;
+
+ //
+ // Read the DOS image headers
+ //
+ Size = sizeof (EFI_IMAGE_DOS_HEADER);
+ Status = ImageContext->ImageRead (
+ ImageContext->Handle,
+ 0,
+ &Size,
+ &DosHdr
+ );
+ if (EFI_ERROR (Status)) {
+ ImageContext->ImageError = IMAGE_ERROR_IMAGE_READ;
+ return Status;
+ }
+
+ ImageContext->PeCoffHeaderOffset = 0;
+ if (DosHdr.e_magic == EFI_IMAGE_DOS_SIGNATURE) {
+ //
+ // DOS image header is present, so read the PE header after the DOS image header
+ //
+ ImageContext->PeCoffHeaderOffset = DosHdr.e_lfanew;
+ }
+
+ //
+ // Read the PE/COFF Header
+ //
+ Size = sizeof (EFI_IMAGE_NT_HEADERS64);
+ Status = ImageContext->ImageRead (
+ ImageContext->Handle,
+ ImageContext->PeCoffHeaderOffset,
+ &Size,
+ PeHdr
+ );
+ if (EFI_ERROR (Status)) {
+ ImageContext->ImageError = IMAGE_ERROR_IMAGE_READ;
+ return Status;
+ }
+
+ return EFI_SUCCESS;
+}
+
+static
+EFI_STATUS
+PeCoffLoader64CheckImageType (
+ IN OUT PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext,
+ IN EFI_IMAGE_NT_HEADERS64 *PeHdr
+ )
+/*++
+
+Routine Description:
+ Checks the PE header of a PE/COFF image to determine if it supported
+
+Arguments:
+ ImageContext - The context of the image being loaded
+ PeHdr - The buffer in which to return the PE header
+
+Returns:
+ EFI_SUCCESS if the PE/COFF image is supported
+ EFI_UNSUPPORTED of the PE/COFF image is not supported.
+
+--*/
+{
+ //
+ // Check the PE/COFF Header SIgnature
+ //
+ if (PeHdr->Signature != EFI_IMAGE_NT_SIGNATURE) {
+ ImageContext->ImageError = IMAGE_ERROR_INVALID_PE_HEADER_SIGNATURE;
+ return EFI_UNSUPPORTED;
+ }
+
+ //
+ // See if the machine type is supported. We support a native machine type (IA-32/Itanium-based)
+ // and the machine type for the Virtual Machine.
+ //
+ ImageContext->Machine = PeHdr->FileHeader.Machine;
+ if (!(IMAGE_64_MACHINE_TYPE_SUPPORTED (ImageContext->Machine))) {
+ ImageContext->ImageError = IMAGE_ERROR_INVALID_MACHINE_TYPE;
+ return EFI_UNSUPPORTED;
+ }
+
+ //
+ // See if the image type is supported. We support EFI Applications,
+ // EFI Boot Service Drivers, and EFI Runtime Drivers.
+ //
+ ImageContext->ImageType = PeHdr->OptionalHeader.Subsystem;
+ switch (ImageContext->ImageType) {
+
+ case EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION:
+ ImageContext->ImageCodeMemoryType = EfiLoaderCode;
+ ImageContext->ImageDataMemoryType = EfiLoaderData;
+ break;
+
+ case EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER:
+ ImageContext->ImageCodeMemoryType = EfiBootServicesCode;
+ ImageContext->ImageDataMemoryType = EfiBootServicesData;
+ break;
+
+ case EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER:
+ case EFI_IMAGE_SUBSYSTEM_SAL_RUNTIME_DRIVER:
+ ImageContext->ImageCodeMemoryType = EfiRuntimeServicesCode;
+ ImageContext->ImageDataMemoryType = EfiRuntimeServicesData;
+ break;
+
+ default:
+ ImageContext->ImageError = IMAGE_ERROR_INVALID_SUBSYSTEM;
+ return EFI_UNSUPPORTED;
+ }
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+EFIAPI
+PeCoffLoader64GetImageInfo (
+ IN EFI_PEI_PE_COFF_LOADER_PROTOCOL *This,
+ IN OUT PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext
+ )
+/*++
+
+Routine Description:
+ Retrieves information on a PE/COFF image
+
+Arguments:
+ ImageContext - The context of the image being loaded
+ PeHdr - The buffer in which to return the PE header
+
+Returns:
+ EFI_SUCCESS if the information on the PE/COFF image was collected.
+ EFI_UNSUPPORTED of the PE/COFF image is not supported.
+ Otherwise, the error status from reading the PE/COFF image using the
+ ImageContext->ImageRead() function
+
+--*/
+{
+ EFI_STATUS Status;
+ EFI_IMAGE_NT_HEADERS64 PeHdr;
+ EFI_IMAGE_DATA_DIRECTORY *DebugDirectoryEntry;
+ UINTN Size;
+ UINTN Index;
+ UINTN DebugDirectoryEntryRva;
+ UINTN DebugDirectoryEntryFileOffset;
+ UINTN SectionHeaderOffset;
+ EFI_IMAGE_SECTION_HEADER SectionHeader;
+ EFI_IMAGE_DEBUG_DIRECTORY_ENTRY DebugEntry;
+
+ if (NULL == ImageContext) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Assume success
+ //
+ ImageContext->ImageError = IMAGE_ERROR_SUCCESS;
+
+ Status = PeCoffLoader64GetPeHeader (ImageContext, &PeHdr);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Verify machine type
+ //
+ Status = PeCoffLoader64CheckImageType (ImageContext, &PeHdr);
+ if (EFI_ERROR(Status)) {
+ return Status;
+ }
+
+ //
+ // Retrieve the base address of the image
+ //
+ ImageContext->ImageAddress = PeHdr.OptionalHeader.ImageBase;
+
+ //
+ // Initialize the alternate destination address to 0 indicating that it
+ // should not be used.
+ //
+ ImageContext->DestinationAddress = 0;
+
+ //
+ // Initialize the codeview pointer.
+ //
+ ImageContext->CodeView = NULL;
+ ImageContext->PdbPointer = NULL;
+
+ //
+ // Three cases with regards to relocations:
+ // - Image has base relocs, RELOCS_STRIPPED==0 => image is relocatable
+ // - Image has no base relocs, RELOCS_STRIPPED==1 => Image is not relocatable
+ // - Image has no base relocs, RELOCS_STRIPPED==0 => Image is relocatable but
+ // has no base relocs to apply
+ // Obviously having base relocations with RELOCS_STRIPPED==1 is invalid.
+ //
+ // Look at the file header to determine if relocations have been stripped, and
+ // save this info in the image context for later use.
+ //
+ if (PeHdr.FileHeader.Characteristics & EFI_IMAGE_FILE_RELOCS_STRIPPED) {
+ ImageContext->RelocationsStripped = TRUE;
+ } else {
+ ImageContext->RelocationsStripped = FALSE;
+ }
+
+ ImageContext->ImageSize = (UINT64)PeHdr.OptionalHeader.SizeOfImage;
+ ImageContext->SectionAlignment = PeHdr.OptionalHeader.SectionAlignment;
+ ImageContext->SizeOfHeaders = PeHdr.OptionalHeader.SizeOfHeaders;
+
+ //
+ // Modify ImageSize to contain .PDB file name if required and initialize
+ // PdbRVA field...
+ //
+
+ if (PeHdr.OptionalHeader.NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_DEBUG) {
+ DebugDirectoryEntry = (EFI_IMAGE_DATA_DIRECTORY *)
+ &(PeHdr.OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG]);
+
+ DebugDirectoryEntryRva = DebugDirectoryEntry->VirtualAddress;
+
+ //
+ // Determine the file offset of the debug directory... This means we walk
+ // the sections to find which section contains the RVA of the debug
+ // directory
+ //
+
+ DebugDirectoryEntryFileOffset = 0;
+
+ SectionHeaderOffset = (UINTN) (
+ ImageContext->PeCoffHeaderOffset +
+ sizeof (UINT32) +
+ sizeof (EFI_IMAGE_FILE_HEADER) +
+ PeHdr.FileHeader.SizeOfOptionalHeader
+ );
+
+ for (Index = 0; Index < PeHdr.FileHeader.NumberOfSections; Index += 1) {
+ //
+ // Read section header from file
+ //
+ Size = sizeof (EFI_IMAGE_SECTION_HEADER);
+ Status = ImageContext->ImageRead (
+ ImageContext->Handle,
+ SectionHeaderOffset,
+ &Size,
+ &SectionHeader
+ );
+ if (EFI_ERROR (Status)) {
+ ImageContext->ImageError = IMAGE_ERROR_IMAGE_READ;
+ return Status;
+ }
+
+ if (DebugDirectoryEntryRva >= SectionHeader.VirtualAddress &&
+ DebugDirectoryEntryRva < SectionHeader.VirtualAddress + SectionHeader.Misc.VirtualSize) {
+ DebugDirectoryEntryFileOffset = DebugDirectoryEntryRva - SectionHeader.VirtualAddress + SectionHeader.PointerToRawData;
+ break;
+ }
+
+ SectionHeaderOffset += sizeof (EFI_IMAGE_SECTION_HEADER);
+ }
+
+ if (DebugDirectoryEntryFileOffset != 0) {
+ for (Index = 0; Index < DebugDirectoryEntry->Size; Index++) {
+ //
+ // Read next debug directory entry
+ //
+ Size = sizeof (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY);
+ Status = ImageContext->ImageRead (
+ ImageContext->Handle,
+ DebugDirectoryEntryFileOffset,
+ &Size,
+ &DebugEntry
+ );
+ if (EFI_ERROR (Status)) {
+ ImageContext->ImageError = IMAGE_ERROR_IMAGE_READ;
+ return Status;
+ }
+ if (DebugEntry.Type == EFI_IMAGE_DEBUG_TYPE_CODEVIEW) {
+ ImageContext->DebugDirectoryEntryRva = (UINT32) (DebugDirectoryEntryRva + Index * sizeof (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY));
+ if (DebugEntry.RVA == 0 && DebugEntry.FileOffset != 0) {
+ ImageContext->ImageSize += DebugEntry.SizeOfData;
+ }
+ return EFI_SUCCESS;
+ }
+ }
+ }
+ }
+ return EFI_SUCCESS;
+}
+
+static
+VOID *
+PeCoffLoader64ImageAddress (
+ IN OUT PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext,
+ IN UINTN Address
+ )
+/*++
+
+Routine Description:
+ Converts an image address to the loaded address
+
+Arguments:
+ ImageContext - The context of the image being loaded
+ Address - The address to be converted to the loaded address
+
+Returns:
+ NULL if the address can not be converted, otherwise, the converted address
+
+--*/
+{
+ if (Address >= ImageContext->ImageSize) {
+ ImageContext->ImageError = IMAGE_ERROR_INVALID_IMAGE_ADDRESS;
+ return NULL;
+ }
+ return (CHAR8 *)((UINTN)ImageContext->ImageAddress + Address);
+}
+
+EFI_STATUS
+EFIAPI
+PeCoffLoader64RelocateImage (
+ IN EFI_PEI_PE_COFF_LOADER_PROTOCOL *This,
+ IN OUT PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext
+ )
+/*++
+
+Routine Description:
+ Relocates a PE/COFF image in memory
+
+Arguments:
+ ImageContext - Contains information on the loaded image to relocate
+
+Returns:
+ EFI_SUCCESS if the PE/COFF image was relocated
+ EFI_LOAD_ERROR if the image is not a valid PE/COFF image
+
+--*/
+{
+ EFI_STATUS Status;
+ EFI_IMAGE_NT_HEADERS64 *PeHdr;
+ EFI_IMAGE_DATA_DIRECTORY *RelocDir;
+ IN UINT64 Adjust;
+ EFI_IMAGE_BASE_RELOCATION *RelocBase;
+ EFI_IMAGE_BASE_RELOCATION *RelocBaseEnd;
+ UINT16 *Reloc;
+ UINT16 *RelocEnd;
+ CHAR8 *Fixup;
+ CHAR8 *FixupBase;
+ UINT16 *F16;
+ UINT32 *F32;
+ CHAR8 *FixupData;
+ EFI_PHYSICAL_ADDRESS BaseAddress;
+
+
+ //
+ // Assume success
+ //
+ ImageContext->ImageError = IMAGE_ERROR_SUCCESS;
+
+ //
+ // If there are no relocation entries, then we are done
+ //
+ if (ImageContext->RelocationsStripped) {
+ return EFI_SUCCESS;
+ }
+
+ //
+ // If the destination address is not 0, use that rather than the
+ // image address as the relocation target.
+ //
+ if (ImageContext->DestinationAddress) {
+ BaseAddress = ImageContext->DestinationAddress;
+ } else {
+ BaseAddress = ImageContext->ImageAddress;
+ }
+ PeHdr = (EFI_IMAGE_NT_HEADERS64 *)((UINTN)ImageContext->ImageAddress +
+ ImageContext->PeCoffHeaderOffset);
+ Adjust = (UINT64) BaseAddress - PeHdr->OptionalHeader.ImageBase;
+
+ PeHdr->OptionalHeader.ImageBase = (UINTN) BaseAddress;
+
+ //
+ // Find the relocation block
+ //
+ // Per the PE/COFF spec, you can't assume that a given data directory
+ // is present in the image. You have to check the NumberOfRvaAndSizes in
+ // the optional header to verify a desired directory entry is there.
+ //
+ if (PeHdr->OptionalHeader.NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC) {
+ RelocDir = &PeHdr->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC];
+ RelocBase = PeCoffLoader64ImageAddress (ImageContext, RelocDir->VirtualAddress);
+ RelocBaseEnd = PeCoffLoader64ImageAddress (
+ ImageContext,
+ RelocDir->VirtualAddress + RelocDir->Size - 1
+ );
+} else {
+ //
+ // Set base and end to bypass processing below.
+ //
+ RelocBase = RelocBaseEnd = 0;
+ }
+ //
+ // Run the relocation information and apply the fixups
+ //
+ FixupData = ImageContext->FixupData;
+ while (RelocBase < RelocBaseEnd) {
+
+ Reloc = (UINT16 *) ((CHAR8 *) RelocBase + sizeof(EFI_IMAGE_BASE_RELOCATION));
+ RelocEnd = (UINT16 *) ((CHAR8 *) RelocBase + RelocBase->SizeOfBlock);
+ FixupBase = PeCoffLoader64ImageAddress (ImageContext, RelocBase->VirtualAddress);
+ if ((CHAR8 *) RelocEnd < (CHAR8 *)((UINTN)ImageContext->ImageAddress) ||
+ (CHAR8 *) RelocEnd > (CHAR8 *)((UINTN)ImageContext->ImageAddress +
+ (UINTN)ImageContext->ImageSize)) {
+ ImageContext->ImageError = IMAGE_ERROR_FAILED_RELOCATION;
+ return EFI_LOAD_ERROR;
+ }
+
+ //
+ // Run this relocation record
+ //
+ while (Reloc < RelocEnd) {
+
+ Fixup = FixupBase + (*Reloc & 0xFFF);
+ switch ((*Reloc) >> 12) {
+ case EFI_IMAGE_REL_BASED_ABSOLUTE:
+ break;
+ case EFI_IMAGE_REL_BASED_HIGH:
+ F16 = (UINT16 *) Fixup;
+ *F16 = (UINT16)((*F16 << 16) + (UINT16) Adjust);
+ if (FixupData != NULL) {
+ *(UINT16 *) FixupData = *F16;
+ FixupData = FixupData + sizeof(UINT16);
+ }
+ break;
+ case EFI_IMAGE_REL_BASED_LOW:
+ F16 = (UINT16 *) Fixup;
+ *F16 = (UINT16)(*F16 + (UINT16) Adjust);
+ if (FixupData != NULL) {
+ *(UINT16 *) FixupData = *F16;
+ FixupData = FixupData + sizeof(UINT16);
+ }
+ break;
+ case EFI_IMAGE_REL_BASED_HIGHLOW:
+ F32 = (UINT32 *) Fixup;
+ *F32 = *F32 + (UINT32) Adjust;
+ if (FixupData != NULL) {
+ FixupData = ALIGN_POINTER(FixupData, sizeof(UINT32));
+ *(UINT32 *) FixupData = *F32;
+ FixupData = FixupData + sizeof(UINT32);
+ }
+ break;
+ case EFI_IMAGE_REL_BASED_HIGHADJ:
+ // Return the same EFI_UNSUPPORTED return code as
+ // PeCoffLoader64RelocateImageEx() returns if it does not recognize
+ // the relocation type.
+ //
+ ImageContext->ImageError = IMAGE_ERROR_FAILED_RELOCATION;
+ return EFI_UNSUPPORTED;
+ default:
+ Status = PeCoffLoader64RelocateImageEx (Reloc, Fixup, &FixupData, Adjust);
+ if (EFI_ERROR (Status)) {
+ ImageContext->ImageError = IMAGE_ERROR_FAILED_RELOCATION;
+ return Status;
+ }
+ }
+
+ //
+ // Next relocation record
+ //
+ Reloc += 1;
+ }
+
+ //
+ // Next reloc block
+ //
+ RelocBase = (EFI_IMAGE_BASE_RELOCATION *) RelocEnd;
+ }
+
+ return EFI_SUCCESS;
+}
+
+
+EFI_STATUS
+PeCoffLoader64RelocateImageEx (
+ IN UINT16 *Reloc,
+ IN OUT CHAR8 *Fixup,
+ IN OUT CHAR8 **FixupData,
+ IN UINT64 Adjust
+ )
+/*++
+
+Routine Description:
+ Performs an IA-32 specific relocation fixup
+
+Arguments:
+ Reloc - Pointer to the relocation record
+ Fixup - Pointer to the address to fix up
+ FixupData - Pointer to a buffer to log the fixups
+ Adjust - The offset to adjust the fixup
+
+Returns:
+ None
+
+--*/
+{
+ UINT64 *F64;
+
+ switch ((*Reloc) >> 12) {
+
+ case EFI_IMAGE_REL_BASED_DIR64:
+ F64 = (UINT64 *) Fixup;
+ *F64 = *F64 + (UINT64) Adjust;
+ if (*FixupData != NULL) {
+ *FixupData = ALIGN_POINTER(*FixupData, sizeof(UINT64));
+ *(UINT64 *)(*FixupData) = *F64;
+ *FixupData = *FixupData + sizeof(UINT64);
+ }
+ break;
+
+ default:
+ return EFI_UNSUPPORTED;
+ }
+
+ return EFI_SUCCESS;
+}
+
+
+
+EFI_STATUS
+EFIAPI
+PeCoffLoader64LoadImage (
+ IN EFI_PEI_PE_COFF_LOADER_PROTOCOL *This,
+ IN OUT PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext
+ )
+/*++
+
+Routine Description:
+ Loads a PE/COFF image into memory
+
+Arguments:
+ ImageContext - Contains information on image to load into memory
+
+Returns:
+ EFI_SUCCESS if the PE/COFF image was loaded
+ EFI_BUFFER_TOO_SMALL if the caller did not provide a large enough buffer
+ EFI_LOAD_ERROR if the image is a runtime driver with no relocations
+ EFI_INVALID_PARAMETER if the image address is invalid
+
+--*/
+{
+ EFI_STATUS Status;
+ EFI_IMAGE_NT_HEADERS64 *PeHdr;
+ PE_COFF_LOADER_IMAGE_CONTEXT CheckContext;
+ EFI_IMAGE_SECTION_HEADER *FirstSection;
+ EFI_IMAGE_SECTION_HEADER *Section;
+ UINTN Index;
+ CHAR8 *Base;
+ CHAR8 *End;
+ CHAR8 *MaxEnd;
+ EFI_IMAGE_DATA_DIRECTORY *DirectoryEntry;
+ EFI_IMAGE_DEBUG_DIRECTORY_ENTRY *DebugEntry;
+ UINTN Size;
+ UINT32 TempDebugEntryRva;
+
+ //
+ // Assume success
+ //
+ ImageContext->ImageError = IMAGE_ERROR_SUCCESS;
+
+ //
+ // Copy the provided context info into our local version, get what we
+ // can from the original image, and then use that to make sure everything
+ // is legit.
+ //
+ CopyMem (
+ &CheckContext,
+ ImageContext,
+ sizeof (PE_COFF_LOADER_IMAGE_CONTEXT)
+ );
+
+ Status = PeCoffLoader64GetImageInfo (
+ This,
+ &CheckContext
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Make sure there is enough allocated space for the image being loaded
+ //
+ if (ImageContext->ImageSize < CheckContext.ImageSize) {
+ ImageContext->ImageError = IMAGE_ERROR_INVALID_IMAGE_SIZE;
+ return EFI_BUFFER_TOO_SMALL;
+ }
+
+ //
+ // If there's no relocations, then make sure it's not a runtime driver,
+ // and that it's being loaded at the linked address.
+ //
+ if (CheckContext.RelocationsStripped == TRUE) {
+ //
+ // If the image does not contain relocations and it is a runtime driver
+ // then return an error.
+ //
+ if (CheckContext.ImageType == EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER) {
+ ImageContext->ImageError = IMAGE_ERROR_INVALID_SUBSYSTEM;
+ return EFI_LOAD_ERROR;
+ }
+ //
+ // If the image does not contain relocations, and the requested load address
+ // is not the linked address, then return an error.
+ //
+ if (CheckContext.ImageAddress != ImageContext->ImageAddress) {
+ ImageContext->ImageError = IMAGE_ERROR_INVALID_IMAGE_ADDRESS;
+ return EFI_INVALID_PARAMETER;
+ }
+ }
+
+ //
+ // Make sure the allocated space has the proper section alignment
+ //
+ if ((ImageContext->ImageAddress & (CheckContext.SectionAlignment - 1)) != 0) {
+ ImageContext->ImageError = IMAGE_ERROR_INVALID_SECTION_ALIGNMENT;
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Read the entire PE/COFF header into memory
+ //
+ Status = ImageContext->ImageRead (
+ ImageContext->Handle,
+ 0,
+ &ImageContext->SizeOfHeaders,
+ (VOID *)(UINTN)ImageContext->ImageAddress
+ );
+ if (EFI_ERROR(Status)) {
+ ImageContext->ImageError = IMAGE_ERROR_IMAGE_READ;
+ return EFI_LOAD_ERROR;
+ }
+
+ PeHdr = (EFI_IMAGE_NT_HEADERS64 *)
+ ((UINTN)ImageContext->ImageAddress + ImageContext->PeCoffHeaderOffset);
+
+ //
+ // Load each section of the image
+ //
+ FirstSection = (EFI_IMAGE_SECTION_HEADER *) (
+ (UINTN)ImageContext->ImageAddress +
+ ImageContext->PeCoffHeaderOffset +
+ sizeof(UINT32) +
+ sizeof(EFI_IMAGE_FILE_HEADER) +
+ PeHdr->FileHeader.SizeOfOptionalHeader
+ );
+
+ Section = FirstSection;
+ for ( Index=0, MaxEnd = NULL;
+ Index < PeHdr->FileHeader.NumberOfSections;
+ Index += 1) {
+
+ //
+ // Compute sections address
+ //
+ Base = PeCoffLoader64ImageAddress (ImageContext, Section->VirtualAddress);
+ End = PeCoffLoader64ImageAddress (
+ ImageContext,
+ Section->VirtualAddress + Section->Misc.VirtualSize - 1);
+ if (End > MaxEnd) {
+ MaxEnd = End;
+ }
+ //
+ // If the base start or end address resolved to 0, then fail.
+ //
+ if (!Base || !End) {
+ ImageContext->ImageError = IMAGE_ERROR_SECTION_NOT_LOADED;
+ return EFI_LOAD_ERROR;
+ }
+
+ //
+ // Read the section, we can resume the length of PE image can't
+ // exceed the max 32bit integer
+ //
+ Size = (UINTN) Section->Misc.VirtualSize;
+ if ((Size == 0) || (Size > Section->SizeOfRawData)) {
+ Size = (UINTN) Section->SizeOfRawData;
+ }
+ if (Section->SizeOfRawData) {
+ Status = ImageContext->ImageRead (
+ ImageContext->Handle,
+ Section->PointerToRawData,
+ &Size,
+ Base);
+ if (EFI_ERROR(Status)) {
+ ImageContext->ImageError = IMAGE_ERROR_IMAGE_READ;
+ return Status;
+ }
+ }
+
+ //
+ // If raw size is less then virt size, zero fill the remaining
+ //
+
+ if (Size < Section->Misc.VirtualSize) {
+ ZeroMem (Base + Size, Section->Misc.VirtualSize - (UINTN)Size);
+ }
+
+ //
+ // Next Section
+ //
+ Section += 1;
+ }
+
+ //
+ // Get image's entry point
+ //
+ ImageContext->EntryPoint =
+ (EFI_PHYSICAL_ADDRESS) (UINTN) PeCoffLoader64ImageAddress (
+ ImageContext,
+ PeHdr->OptionalHeader.AddressOfEntryPoint
+ );
+
+ //
+ // Determine the size of the fixup data
+ //
+ // Per the PE/COFF spec, you can't assume that a given data directory
+ // is present in the image. You have to check the NumberOfRvaAndSizes in
+ // the optional header to verify a desired directory entry is there.
+ //
+ if (PeHdr->OptionalHeader.NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC) {
+ DirectoryEntry = (EFI_IMAGE_DATA_DIRECTORY *)
+ &PeHdr->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC];
+ ImageContext->FixupDataSize =
+ DirectoryEntry->Size / sizeof(UINT16) * sizeof(UINTN);
+ } else {
+ ImageContext->FixupDataSize = 0;
+ }
+ //
+ // Consumer must allocate a buffer for the relocation fixup log.
+ // Only used for runtime drivers.
+ //
+ ImageContext->FixupData = NULL;
+
+ //
+ // Load the Codeview info if present
+ //
+ if (ImageContext->DebugDirectoryEntryRva != 0) {
+ DebugEntry = PeCoffLoader64ImageAddress (
+ ImageContext,
+ ImageContext->DebugDirectoryEntryRva
+ );
+ if (DebugEntry != NULL) {
+ TempDebugEntryRva = DebugEntry->RVA;
+ if (DebugEntry->RVA == 0 && DebugEntry->FileOffset != 0) {
+ Section--;
+ if ((UINTN) Section->SizeOfRawData < Section->Misc.VirtualSize) {
+ TempDebugEntryRva = Section->VirtualAddress + Section->Misc.VirtualSize;
+ } else {
+ TempDebugEntryRva = Section->VirtualAddress + Section->SizeOfRawData;
+ }
+ }
+ if (TempDebugEntryRva != 0) {
+ ImageContext->CodeView = PeCoffLoader64ImageAddress (ImageContext, TempDebugEntryRva);
+ if (ImageContext->CodeView == NULL) {
+ ImageContext->ImageError = IMAGE_ERROR_IMAGE_READ;
+ return EFI_LOAD_ERROR;
+ }
+
+ if (DebugEntry->RVA == 0) {
+ Size = (UINTN) DebugEntry->SizeOfData;
+ Status = ImageContext->ImageRead (
+ ImageContext->Handle,
+ DebugEntry->FileOffset,
+ &Size,
+ ImageContext->CodeView
+ );
+ if (EFI_ERROR(Status)) {
+ ImageContext->ImageError = IMAGE_ERROR_IMAGE_READ;
+ return EFI_LOAD_ERROR;
+ }
+ DebugEntry->RVA = TempDebugEntryRva;
+ }
+
+ switch (* (UINT32 *) ImageContext->CodeView) {
+ case CODEVIEW_SIGNATURE_NB10:
+ ImageContext->PdbPointer = (CHAR8 *) ImageContext->CodeView + sizeof (EFI_IMAGE_DEBUG_CODEVIEW_NB10_ENTRY);
+ break;
+ case CODEVIEW_SIGNATURE_RSDS:
+ ImageContext->PdbPointer = (CHAR8 *) ImageContext->CodeView + sizeof (EFI_IMAGE_DEBUG_CODEVIEW_RSDS_ENTRY);
+ break;
+ default:
+ break;
+ }
+ }
+ }
+ }
+
+ return Status;
+}
+
+EFI_STATUS
+EFIAPI
+PeCoffLoader64UnloadImage (
+ IN EFI_PEI_PE_COFF_LOADER_PROTOCOL *This,
+ IN PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext
+ )
+/*++
+
+Routine Description:
+ Unload of images is not supported
+
+Arguments:
+ ImageContext - The image to unload
+
+Returns:
+ EFI_SUCCESS
+
+--*/
+{
+ return EFI_SUCCESS;
+}
+
+EFI_PEI_PE_COFF_LOADER_PROTOCOL *
+EFIAPI
+GetPeCoffLoaderProtocol (
+ )
+{
+ return &mPeCoffLoaderX64;
+}
+
+
diff --git a/EdkModulePkg/Library/EdkPeCoffLoaderLibX64/EdkPeCoffLoaderLibX64.mbd b/EdkModulePkg/Library/EdkPeCoffLoaderLibX64/EdkPeCoffLoaderLibX64.mbd
new file mode 100644
index 0000000000..fd0b050241
--- /dev/null
+++ b/EdkModulePkg/Library/EdkPeCoffLoaderLibX64/EdkPeCoffLoaderLibX64.mbd
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<LibraryModuleBuildDescription xmlns="http://www.TianoCore.org/2006/Edk2.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.TianoCore.org/2006/Edk2.0 http://www.TianoCore.org/2006/Edk2.0/SurfaceArea.xsd">
+ <MbdLibHeader>
+ <BaseName>EdkPeCoffLoaderLibX64</BaseName>
+ <Guid>742597d6-2b50-4120-bfba-2400549a792f</Guid>
+ <Version>EDK_RELEASE_VERSION 0x00090000</Version>
+ <Description>FIX ME!</Description>
+ <Copyright>Copyright (c) 2006, Intel Corporation</Copyright>
+ <License>
+ All rights reserved. This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+ </License>
+ <Created>2006-04-26 13:50</Created>
+ </MbdLibHeader>
+</LibraryModuleBuildDescription>
diff --git a/EdkModulePkg/Library/EdkPeCoffLoaderLibX64/EdkPeCoffLoaderLibX64.msa b/EdkModulePkg/Library/EdkPeCoffLoaderLibX64/EdkPeCoffLoaderLibX64.msa
new file mode 100644
index 0000000000..eeb13ddefb
--- /dev/null
+++ b/EdkModulePkg/Library/EdkPeCoffLoaderLibX64/EdkPeCoffLoaderLibX64.msa
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<LibraryModuleSurfaceArea xmlns="http://www.TianoCore.org/2006/Edk2.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.TianoCore.org/2006/Edk2.0 http://www.TianoCore.org/2006/Edk2.0/SurfaceArea.xsd">
+ <MsaLibHeader>
+ <BaseName>EdkPeCoffLoaderLibX64</BaseName>
+ <ModuleType>DXE_CORE</ModuleType>
+ <ComponentType>LIBRARY</ComponentType>
+ <Guid>742597d6-2b50-4120-bfba-2400549a792f</Guid>
+ <Version>EDK_RELEASE_VERSION 0x00090000</Version>
+ <Abstract>Component description file for the PEI library.</Abstract>
+ <Description>FIX ME!</Description>
+ <Copyright>Copyright (c) 2006, Intel Corporation</Copyright>
+ <License>
+ All rights reserved. This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+ </License>
+ <Specification>EFI_SPECIFICATION_VERSION 0x00000000</Specification>
+ <Created>2006-04-26 13:50</Created>
+ </MsaLibHeader>
+ <LibraryClassDefinitions>
+ <LibraryClass Usage="ALWAYS_PRODUCED">EdkPeCoffLoaderLib</LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">BaseMemoryLib</LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">PeCoffLib</LibraryClass>
+ </LibraryClassDefinitions>
+ <SourceFiles>
+ <Filename>EdkPeCoffLoaderLibX64.c</Filename>
+ </SourceFiles>
+ <Includes>
+ <PackageName>MdePkg</PackageName>
+ <PackageName>EdkModulePkg</PackageName>
+ </Includes>
+</LibraryModuleSurfaceArea>
diff --git a/EdkModulePkg/Library/EdkPeCoffLoaderLibX64/build.xml b/EdkModulePkg/Library/EdkPeCoffLoaderLibX64/build.xml
new file mode 100644
index 0000000000..6a4190076f
--- /dev/null
+++ b/EdkModulePkg/Library/EdkPeCoffLoaderLibX64/build.xml
@@ -0,0 +1,46 @@
+<?xml version="1.0" encoding="UTF-8"?><!-- Copyright (c) 2006, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.-->
+<project basedir="." default="EdkPeCoffLoaderLibX64"><!--Apply external ANT tasks-->
+ <taskdef resource="GenBuild.tasks"/>
+ <property environment="env"/>
+ <property name="WORKSPACE_DIR" value="${env.WORKSPACE}"/>
+ <import file="${WORKSPACE_DIR}/Tools/Conf/BuildMacro.xml"/><!--MODULE_RELATIVE PATH is relative to PACKAGE_DIR-->
+ <property name="MODULE_RELATIVE_PATH" value="Library/EdkPeCoffLoaderLibX64"/>
+ <property name="MODULE_DIR" value="${PACKAGE_DIR}/${MODULE_RELATIVE_PATH}"/>
+ <property name="COMMON_FILE" value="${WORKSPACE_DIR}/Tools/Conf/Common.xml"/>
+ <target name="EdkPeCoffLoaderLibX64">
+ <GenBuild baseName="EdkPeCoffLoaderLibX64" mbdFilename="${MODULE_DIR}/EdkPeCoffLoaderLibX64.mbd" msaFilename="${MODULE_DIR}/EdkPeCoffLoaderLibX64.msa"/>
+ </target>
+ <target depends="EdkPeCoffLoaderLibX64_clean" name="clean"/>
+ <target depends="EdkPeCoffLoaderLibX64_cleanAll" name="cleanAll"/>
+ <target name="EdkPeCoffLoaderLibX64_clean">
+ <OutputDirSetup baseName="EdkPeCoffLoaderLibX64" mbdFilename="${MODULE_DIR}/EdkPeCoffLoaderLibX64.mbd" msaFilename="${MODULE_DIR}/EdkPeCoffLoaderLibX64.msa"/>
+ <if>
+ <available file="${DEST_DIR_OUTPUT}/EdkPeCoffLoaderLibX64_build.xml"/>
+ <then>
+ <ant antfile="${DEST_DIR_OUTPUT}/EdkPeCoffLoaderLibX64_build.xml" target="clean"/>
+ </then>
+ </if>
+ <delete dir="${DEST_DIR_OUTPUT}" excludes="*.xml"/>
+ </target>
+ <target name="EdkPeCoffLoaderLibX64_cleanAll">
+ <OutputDirSetup baseName="EdkPeCoffLoaderLibX64" mbdFilename="${MODULE_DIR}/EdkPeCoffLoaderLibX64.mbd" msaFilename="${MODULE_DIR}/EdkPeCoffLoaderLibX64.msa"/>
+ <if>
+ <available file="${DEST_DIR_OUTPUT}/EdkPeCoffLoaderLibX64_build.xml"/>
+ <then>
+ <ant antfile="${DEST_DIR_OUTPUT}/EdkPeCoffLoaderLibX64_build.xml" target="cleanAll"/>
+ </then>
+ </if>
+ <delete dir="${DEST_DIR_OUTPUT}"/>
+ <delete dir="${DEST_DIR_DEBUG}"/>
+ <delete>
+ <fileset dir="${BIN_DIR}" includes="**EdkPeCoffLoaderLibX64*"/>
+ </delete>
+ </target>
+</project> \ No newline at end of file