/** @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
);\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
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
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
//\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
// 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
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
\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
}\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
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
// 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
return RETURN_SUCCESS;\r
}\r
\r
+\r
/**\r
Converts an image address to the loaded address.\r
\r
@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
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
}\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
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
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
*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
)\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
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
(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
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
} 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
// 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
// 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
);\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
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
} 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
\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
\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