summaryrefslogtreecommitdiff
path: root/Library/PELoader.c
diff options
context:
space:
mode:
authorraywu <raywu0301@gmail.com>2018-06-15 00:00:50 +0800
committerraywu <raywu0301@gmail.com>2018-06-15 00:00:50 +0800
commitb7c51c9cf4864df6aabb99a1ae843becd577237c (patch)
treeeebe9b0d0ca03062955223097e57da84dd618b9a /Library/PELoader.c
downloadzprj-b7c51c9cf4864df6aabb99a1ae843becd577237c.tar.xz
init. 1AQQW051HEADmaster
Diffstat (limited to 'Library/PELoader.c')
-rw-r--r--Library/PELoader.c800
1 files changed, 800 insertions, 0 deletions
diff --git a/Library/PELoader.c b/Library/PELoader.c
new file mode 100644
index 0000000..0a0673f
--- /dev/null
+++ b/Library/PELoader.c
@@ -0,0 +1,800 @@
+//*************************************************************************
+//*************************************************************************
+//** **
+//** (C)Copyright 1985-2009, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//*************************************************************************
+//*************************************************************************
+
+//*************************************************************************
+// $Header: /Alaska/SOURCE/Core/Library/PELoader.c 15 7/10/09 3:49p Felixp $
+//
+// $Revision: 15 $
+//
+// $Date: 7/10/09 3:49p $
+//*************************************************************************
+// Revision History
+// ----------------
+// $Log: /Alaska/SOURCE/Core/Library/PELoader.c $
+//
+// 15 7/10/09 3:49p Felixp
+// Function headers added
+//
+// 14 11/20/08 3:00p Felixp
+// ReallocatePeImage function is upadted to properly handle virtual
+// address fixups of the runtime images.
+//
+// 13 9/05/07 12:22p Felixp
+// GetName updated to support TE images.
+//
+// 12 9/05/07 2:38a Felixp
+// Boundary condition is IsTeImageValid routine is fixed.
+//
+// 11 8/02/07 1:35a Felixp
+// Always define GetDebugDirectory and GetName routines (used to be only
+// when EFI_DEBUG is defined). This is needed to support selective
+// debugging.
+//
+// 10 6/01/07 2:55p Felixp
+// GetDebugDirectory routine updated: TE image support added; unused code
+// removed.
+//
+// 9 3/12/07 10:58a Felixp
+// Bug fix in reallocation fixups of PE32+ images.
+//
+// 8 10/12/06 9:40a Felixp
+// SectionSize parameter of FindPeSection changed from UINT32 to UINTN
+//
+// 7 8/24/06 9:26a Felixp
+// Preliminary x64 support (work in progress):
+// 1. Processor architecture specific functions moved to a processor
+// library
+// 2. Makefile removed (AmiLib files are build by the AmiPeiLib and
+// AmeDxeLib makefile)
+//
+// 3 1/25/05 3:31p Felixp
+// handling of debug directory slightly changed
+//
+// 2 1/18/05 3:22p Felixp
+// PrintDebugMessage renamed to Trace
+//
+// 9 11/24/04 9:37a Felixp
+// NameAndEntryStr removed
+//
+// 8 11/10/04 5:13p Felixp
+// 1. IsTeImageValid added
+// 2. NameAndEntryStr added
+//
+// 4 1/30/04 5:02p Felixp
+// parameter order in memset changed
+//
+// 2 1/27/04 3:58a Felixp
+// Bug fixes and improvements as a part of PEI CORE integration
+//
+// 1 1/19/04 4:23p Felixp
+// PE and TE Loader
+//
+//*************************************************************************
+//<AMI_FHDR_START>
+//
+// Name: PELoader.c
+//
+// Description:
+// Loader functions for PE32/PE32+ files.
+// The functions are used by Core to implement standard image loading API.
+// Consumers outside Core should not use functions from this file.
+// The public API should be used instead.
+//
+//<AMI_FHDR_END>
+//*************************************************************************
+#include <amilib.h>
+/************************************************************************/
+/* PE Loader */
+/************************************************************************/
+#define PE32_SUPPORT (PE_LOADER_SUPPORT_ALL||!EFI64&&!EFIx64)
+#define PE32_PLUS_SUPPORT (PE_LOADER_SUPPORT_ALL||EFI64||EFIx64)
+
+#pragma pack(push)
+#pragma pack(2)
+//**********************************************************************//
+// Structure type definitions for standard PE headers //
+//**********************************************************************//
+typedef struct _SECTION_HEADER { // Section Header
+ UINT64 Name;
+ UINT32 VirtualSize;
+ UINT32 VirtualAddress;
+ UINT32 SizeOfRawData;
+ UINT32 PointerToRawData;
+ UINT32 Dummy[4];
+} SECTION_HEADER;
+
+typedef struct _FIXUP_BLOCK{
+ UINT32 VirtualAddress;
+ UINT32 Size;
+} FIXUP_BLOCK;
+
+typedef struct _FIXUP{
+ UINT16 Offset : 12, Type: 4;
+}FIXUP;
+
+typedef struct _OPTIONAL_HEADER_CODA { // Optional header coda
+ UINT32 NumberOfRvaAndSizes;
+ DIRECTORY_ENTRY Export, Import, Resource, Exception,
+ Certificate, Reallocations, Debug;
+} OPTIONAL_HEADER_CODA;
+#pragma pack(pop)
+
+// Header format for TE images
+typedef struct {
+ UINT16 Signature;
+ UINT16 Machine; // from the original file header
+ UINT8 NumberOfSections; // from the original file header
+ UINT8 Subsystem; // from original optional header
+ UINT16 StrippedSize; // how many bytes we removed from the header
+ UINT32 AddressOfEntryPoint; // offset to entry point from original optional header
+ UINT32 BaseOfCode; // from original image -- required for ITP
+ UINT64 ImageBase; // from original file header
+ DIRECTORY_ENTRY DataDirectory[2]; // only base relocation and debug directory
+} EFI_TE_IMAGE_HEADER;
+
+#define EFI_TE_IMAGE_HEADER_SIGNATURE 0x5A56 // TE
+
+// Data directory indexes in our TE image header
+#define EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC 0
+#define EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG 1
+
+//*************************************************************************
+//<AMI_PHDR_START>
+//
+// Name: IsPeImageValid
+//
+// Description:
+// BOOLEAN IsPeImageValid(IN UINT8 *pstart) reads the header signature of a
+// portable executable (PE) image and returns TRUE if it is valid.
+//
+// Input:
+// IN UINT8 *pstart
+// Pointer to the start of the PE image.
+//
+// Output:
+// FALSE if image is invalid, otherwise TRUE.
+//
+// Modified:
+//
+// Referrals:
+//
+// Notes:
+// If x64_BUILD enabled, supports both PE32 and PE32+. Otherwise only
+// supports PE32.
+//
+//<AMI_PHDR_END>
+//*************************************************************************
+BOOLEAN IsPeImageValid(UINT8* pstart){
+ return
+ *(UINT16*)pstart == 0x5A4D && //DOS header signature is valid
+ *(UINT32*)(pstart+=*(UINT32*)(pstart+60)) == 0x00004550 && //PE signature is valid
+#if PE_LOADER_SUPPORT_ALL
+ (
+#endif
+#if PE32_SUPPORT
+ *(UINT16*)(pstart+4) == 0x14c && // IA32 machine
+ *(UINT16*)(pstart+24) == 0x10b // this is PE32
+#endif
+#if PE_LOADER_SUPPORT_ALL
+ ||
+#endif
+#if PE32_PLUS_SUPPORT
+ (*(UINT16*)(pstart+4) == 0x200 || *(UINT16*)(pstart+4) == 0x8664)&& // x64 or IA64 machine
+ *(UINT16*)(pstart+24) == 0x20b // this is PE32+
+#endif
+#if PE_LOADER_SUPPORT_ALL
+ )
+#endif
+ ;
+}
+
+//*************************************************************************
+//<AMI_PHDR_START>
+//
+// Name: isTeImageValid
+//
+// Description:
+// BOOLEAN isTeImageValid(IN UINT8 *pstart) reads the header signature of a
+// terse executable (TE) image and returns true if it is valid.
+//
+// Input:
+// IN UINT8 *pstart
+// Pointer to the start of the TE image.
+//
+// Output:
+// FALSE if image is invalid, otherwise TRUE.
+//
+// Modified:
+//
+// Referrals:
+//
+// Notes:
+// If x64_BUILD enabled, supports both PE32 and PE32+. Otherwise only
+// supports PE32.
+//
+//<AMI_PHDR_END>
+//*************************************************************************
+BOOLEAN IsTeImageValid(UINT8* pstart){
+ EFI_TE_IMAGE_HEADER *pTe = (EFI_TE_IMAGE_HEADER*)pstart;
+ return
+ pTe->Signature == EFI_TE_IMAGE_HEADER_SIGNATURE && //TE signature is valid
+#if PE_LOADER_SUPPORT_ALL
+ (
+#endif
+#if PE32_SUPPORT
+ pTe->Machine == 0x14c // IA32 machine
+#endif
+#if PE_LOADER_SUPPORT_ALL
+ ||
+#endif
+#if PE32_PLUS_SUPPORT
+ (pTe->Machine == 0x200 || pTe->Machine == 0x8664) // x64 or IA64 machine
+#endif
+#if PE_LOADER_SUPPORT_ALL
+ )
+#endif
+ && pTe->StrippedSize >= 2/*MZ signature*/+4/*PE signature*/+
+ sizeof(FILE_HEADER)+
+ //number of directory entries may vary
+ sizeof(OPTIONAL_HEADER)-sizeof(DIRECTORY_ENTRY)*7 &&
+ pTe->AddressOfEntryPoint>=pTe->BaseOfCode;
+}
+
+//*************************************************************************
+//<AMI_PHDR_START>
+//
+// Name: PEEntryPoint
+//
+// Description:
+// VOID* PEEntryPoint(IN VOID *p) returns the address of the entry point to
+// a portable executable (PE) image.
+//
+// Input:
+// IN VOID *p
+// Pointer to the start of the PE image whose entry point is desired.
+//
+// Output:
+// VOID* address to the entry point of the PE image, p.
+//
+// Modified:
+//
+// Referrals:
+//
+// Notes:
+//
+//<AMI_PHDR_END>
+//*************************************************************************
+VOID* PEEntryPoint(VOID *p)
+{
+ UINT8 *q = (UINT8*)p;
+ return q+((OPTIONAL_HEADER*)((FILE_HEADER*)(q+*(UINT32*)(q+60)+4)+1))->AddressOfEntryPoint;
+}
+
+//*************************************************************************
+//<AMI_PHDR_START>
+//
+// Name: TEEntryPoint
+//
+// Description:
+// VOID* TEEntryPoint(IN VOID *p) returns the address of the entry point to
+// a terse executable (TE) image.
+//
+// Input:
+// IN VOID *p
+// Pointer to the start of the TE image whose entry point is desired.
+//
+// Output:
+// VOID* address to the entry point of the TE image, p.
+//
+// Modified:
+//
+// Referrals:
+//
+// Notes:
+//
+//<AMI_PHDR_END>
+//*************************************************************************
+VOID* TEEntryPoint(VOID *p)
+{
+ EFI_TE_IMAGE_HEADER* pTE = (EFI_TE_IMAGE_HEADER*)p;
+ return (UINT8*)(pTE+1) + pTE->AddressOfEntryPoint - pTE->StrippedSize;
+}
+
+//*************************************************************************
+//<AMI_PHDR_START>
+//
+// Name: GetDebugDirectory
+//
+// Description:
+// DEBUG_DIRECTORY* GetDebugDirectory(IN VOID *ptr, OUT UINTN *TeAdjustment)
+// locates and returns the location of DEBUG_DIRECTORY in a terse executable
+// (TE) or portable executable (PE) image.
+//
+// Input:
+// IN VOID *ptr
+// Pointer to the start of the TE or PE image.
+//
+// OUT UINTN *TeAdjustment
+// If ptr is a valid TE image and not NULL, returns the number of bytes
+// stripped from the header. If ptr is a PE image, returns 0.
+//
+// Output:
+// DEBUG_DIRECTORY* address to the image's DEBUG_DIRECTORY structure.
+//
+// Modified:
+//
+// Referrals:
+// IsTeImageValid
+//
+// Notes:
+//
+//<AMI_PHDR_END>
+//*************************************************************************
+DEBUG_DIRECTORY* GetDebugDirectory(VOID *ptr, UINTN *TeAdjustment)
+{
+ FILE_HEADER *pFileHeader;
+ OPTIONAL_HEADER* pOptHeader;
+ UINT8 *p = (UINT8*)ptr;
+ OPTIONAL_HEADER_CODA *pCoda;
+ if (IsTeImageValid(ptr))
+ {
+ EFI_TE_IMAGE_HEADER* pTE = (EFI_TE_IMAGE_HEADER*)p;
+ UINT32 DebugDirectoryOffset = pTE->DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress;
+ if (DebugDirectoryOffset == 0) return NULL;
+ if (TeAdjustment) *TeAdjustment=sizeof(*pTE)-pTE->StrippedSize;
+ return (DEBUG_DIRECTORY*)((UINT8*)(pTE+1) + DebugDirectoryOffset - pTE->StrippedSize);
+ }
+ pFileHeader = (FILE_HEADER*)(p+*(UINT32*)(p+60)+4);
+ pOptHeader= (OPTIONAL_HEADER*)(pFileHeader+1);
+#if PE_LOADER_SUPPORT_ALL
+ if (pOptHeader->Magic == 0x10b)
+ {//PE32
+ pCoda = (OPTIONAL_HEADER_CODA*)((UINT8*)pOptHeader+92);
+ }
+ else
+ {//PE32+
+ pCoda = (OPTIONAL_HEADER_CODA*)((UINT8*)pOptHeader+108);
+ }
+#else
+ pCoda = (OPTIONAL_HEADER_CODA*)&pOptHeader->NumberOfRvaAndSizes;
+#endif
+ if (pCoda->NumberOfRvaAndSizes<(UINT32)(&pCoda->Debug - &pCoda->Export))
+ return NULL;
+ if (pCoda->Debug.VirtualAddress >= pOptHeader->SizeOfImage) return NULL;
+ if (TeAdjustment) *TeAdjustment=0;
+ return (DEBUG_DIRECTORY*)(p + pCoda->Debug.VirtualAddress);
+}
+
+//*************************************************************************
+//<AMI_PHDR_START>
+//
+// Name: GetImageSize
+//
+// Description:
+// UINT32 GetImageSize(IN VOID *p) retrieves the size of a terse executable
+// (TE) image or portable executable (PE) image.
+//
+// Input:
+// IN VOID *p
+// Pointer to the start of the TE or PE image.
+//
+// Output:
+// UINT32 size of the image.
+//
+// Modified:
+//
+// Referrals:
+// GetDebugDirectory
+//
+// Notes:
+//
+//<AMI_PHDR_END>
+//*************************************************************************
+UINT32 GetImageSize(VOID *p)
+{
+ UINT8 *q = (UINT8*)p;
+ UINT32 Size = ((OPTIONAL_HEADER*)((FILE_HEADER*)(q+*(UINT32*)(q+60)+4)+1))->SizeOfImage;
+#ifdef EFI_DEBUG
+{
+ //ITP Support
+ DEBUG_DIRECTORY *pDebug = GetDebugDirectory(q,NULL);
+ if (pDebug /*&& !pDebug->AddressOfRawData*/ && pDebug->PointerToRawData)
+ Size+=pDebug->SizeOfData;
+}
+#endif
+ return Size;
+}
+
+//*************************************************************************
+//<AMI_PHDR_START>
+//
+// Name: GetPeOptionalHeader
+//
+// Description:
+// OPTIONAL_HEADER* GetPeOptionalHeader(IN VOID *p) returns the address of a
+// portable executable (PE) image's optional header.
+//
+// Input:
+// IN VOID *p
+// Pointer to the start of the PE image whose optional header is desired.
+//
+// Output:
+// OPTIONAL_HEADER* address to the PE image's optional header.
+//
+// Modified:
+//
+// Referrals:
+//
+// Notes:
+//
+//<AMI_PHDR_END>
+//*************************************************************************
+OPTIONAL_HEADER* GetPeOptionalHeader(VOID *p)
+{
+ UINT8 *q = (UINT8*)p;
+ return (OPTIONAL_HEADER*)((FILE_HEADER*)(q+*(UINT32*)(q+60)+4)+1);
+}
+
+//*************************************************************************
+//<AMI_PHDR_START>
+//
+// Name: GetName
+//
+// Description:
+// BOOLEAN GetName(IN UINT8 *p, OUT CHAR8 *sName) retrieves the name of
+// portable executable (PE) or terse executable (TE) image, if it is
+// available.
+//
+// Input:
+// IN UINT8 *p
+// Pointer to the start of the PE or TE image whose name is desired.
+//
+// OUT CHAR8 *sName
+// Returns string containing image's name, if it is available. User is
+// responsible for allocating the necessary memory resources.
+//
+// Output:
+// TRUE, if name is located; otherwise FALSE.
+//
+// Modified:
+//
+// Referrals:
+// GetDebugDirectory
+// Strlen
+// Strcmp
+// MemCpy
+//
+// Notes:
+//
+//<AMI_PHDR_END>
+//*************************************************************************
+BOOLEAN GetName(UINT8 *p, CHAR8 *sName)
+{
+ UINTN TeAdjustment;
+ DEBUG_DIRECTORY *pDebug=GetDebugDirectory(p,&TeAdjustment);
+ UINT32 sig;
+ UINTN length;
+ CHAR8 *s, *q, *CvEntry;
+ if (!pDebug||pDebug->Type!=2) return FALSE;
+ CvEntry = (CHAR8*)(p+pDebug->AddressOfRawData+TeAdjustment);
+ sig = *(UINT32*)CvEntry;
+ if (sig==('N'+('B'<<8)+(('1'+('0'<<8))<<16))) //NB10
+ s = CvEntry + 0x10;
+ else if (sig==('R'+('S'<<8)+(('D'+('S'<<8))<<16))) //RSDS
+ s = CvEntry + 0x18;
+ else return FALSE;
+ length = Strlen(s);
+ if (length<5 || Strcmp(&s[length-4],".pdb")) return FALSE;
+ for(q = &s[length-5]; q>=s && *q!='\\'; q--);
+ q++;
+ length = s+length-4-q;
+ MemCpy(sName,q,length);
+ sName[length]=0;
+ return TRUE;
+}
+
+//*************************************************************************
+//<AMI_PHDR_START>
+//
+// Name: ReallocatePeImage
+//
+// Description:
+// BOOLEAN ReallocatePeImage(IN UINT8 *pcurrent, IN UINT8 *pnew,
+// IN UINT8 *prealloc) loads an already loaded portable executable (PE) image
+// at a new memory location with the proper fixup.
+//
+// Input:
+// IN UINT8 *pcurrent
+// Pointer to the current location of the PE image in memory.
+//
+// IN UINT8 *pnew
+// Pointer to the new location of the PE image in memory. May be set to the
+// same value as pcurrent to adjust fixup only.
+//
+// IN UINT8 *prealloc
+// Pointer to an array of UINTN fixup reallocations. May be set to NULL.
+//
+// Output:
+// FALSE if image contains an unknown fixup type; otherwise TRUE.
+//
+// Modified:
+//
+// Referrals:
+// GetPeOptionalHeader
+//
+// Notes:
+// Can only handle the IA32 or IA64 fix up types.
+//
+//<AMI_PHDR_END>
+//*************************************************************************
+BOOLEAN ReallocatePeImage(UINT8 *pcurrent, UINT8 *pnew, UINT8 *prealloc)
+{
+ // Fix up
+ // There is a lot of fix up types but we can handle only IA32 or IA64 specific fix up types.
+ OPTIONAL_HEADER* pOptHeader = GetPeOptionalHeader(pcurrent);
+ OPTIONAL_HEADER_CODA *pCoda;
+ UINT64 ImageBase;
+ UINT64 Delta;
+ FIXUP_BLOCK *pBegin, *pEnd;
+ UINTN *pReallocations = (UINTN*)prealloc;
+#if PE_LOADER_SUPPORT_ALL
+ if (pOptHeader->Magic == 0x10b)
+ {//PE32
+ pCoda = (OPTIONAL_HEADER_CODA*)((UINT8*)pOptHeader+92);
+ ImageBase = *(UINT32*)((UINT8*)pOptHeader+28);
+ *(UINT32*)((UINT8*)pOptHeader+28)=(UINT32)pnew;
+ }
+ else
+ {//PE32+
+ pCoda = (OPTIONAL_HEADER_CODA*)((UINT8*)pOptHeader+108);
+ ImageBase = *(UINT64*)((UINT8*)pOptHeader+24);
+ *(UINT64*)((UINT8*)pOptHeader+24)=(UINT64)(UINTN)pnew;
+ }
+#else
+ pCoda = (OPTIONAL_HEADER_CODA*)&pOptHeader->NumberOfRvaAndSizes;
+ ImageBase = pOptHeader->ImageBase;
+ pOptHeader->ImageBase=(UINTN)pnew;
+#endif
+ Delta = (UINT64)(UINTN)pnew-ImageBase;
+ if (!Delta) return TRUE;
+ pBegin = (FIXUP_BLOCK*)(pcurrent+pCoda->Reallocations.VirtualAddress);
+ pEnd = (FIXUP_BLOCK*)((UINT8*)pBegin + pCoda->Reallocations.Size);
+ while(pBegin<pEnd){
+ FIXUP *pFixupInfo,*pEndOfBlock;
+ UINT8 *pFixupPage;
+ if (!pBegin->Size) return FALSE;
+ pFixupInfo = (FIXUP*)(pBegin+1);
+ pEndOfBlock = (FIXUP*)((UINT8*)pBegin+pBegin->Size);
+ pFixupPage = pcurrent + pBegin->VirtualAddress;
+ for(;pFixupInfo<pEndOfBlock;pFixupInfo++){
+ UINTN *pFixup = (UINTN*)(pFixupPage + pFixupInfo->Offset);
+ switch (pFixupInfo->Type){
+#if PE32_SUPPORT
+ case 3://IMAGE_REL_BASED_HIGHLOW
+ if (!pReallocations || *pReallocations++ == *pFixup) *pFixup += (UINTN)Delta;
+ break;
+#endif
+#if PE32_PLUS_SUPPORT
+ case 10://IMAGE_REL_BASED_DIR64:
+ {
+#if EFI64
+ if ((UINT64)pFixup&0x7){
+ UINT8 *p;
+ UINT32 i;
+ UINT64 R;
+ p = (UINT8*)&R;
+ for(i=0;i<8;i++) p[i]=((UINT8*)pFixup)[i];
+ if (!Pred || Pred((UINTN)R))
+ {
+ R+=Delta;
+ for(i=0;i<8;i++) ((UINT8*)pFixup)[i]=p[i];
+ }
+ }else
+#endif
+ if (!pReallocations || *pReallocations++ == *pFixup) *(UINT64*)pFixup += Delta;
+ break;
+ }
+#endif
+ case 0://IMAGE_REL_BASED_ABSOLUTE:
+ break;
+ default://Error: Unknown fixup type
+ return FALSE;
+ }//switch
+ }//for
+ pBegin=(FIXUP_BLOCK*)pEndOfBlock;
+ }//while
+ return TRUE;
+}
+
+//*************************************************************************
+//<AMI_PHDR_START>
+//
+// Name: LoadPeImageEx
+//
+// Description:
+// VOID* LoadPeImageEx(IN UINT8 *pold, IN UINT8 *pnew, IN UINT8 *prealloc)
+// loads a portal executable into memory from a file.
+//
+// Input:
+// IN UINT8 *pold
+// Pointer to the start of the file in memory.
+//
+// IN UINT8 *pnew
+// Pointer to starting location in memory for the loaded image.
+//
+// IN UINT8 *prealloc
+// Pointer to an array of UINTN fixup reallocations. May be set to NULL.
+//
+// Output:
+// If successful, VOID* address of the entry point for the newly loaded
+// image; otherwise, NULL if pold and or pnew are not 16-byte aligned, or
+// pold does not point to valid PE image.
+//
+// Modified:
+//
+// Referrals:
+// IsPeImageValid
+// MemCpy
+// MemSet
+// ReallocatePeImage
+// GetDebugDirectory
+//
+// Notes:
+//
+//<AMI_PHDR_END>
+//*************************************************************************
+VOID* LoadPeImageEx(UINT8* pold, UINT8* pnew, UINT8 *prealloc){
+ FILE_HEADER *pFileHeader;
+ OPTIONAL_HEADER* pOptHeader;
+ SECTION_HEADER *pSection;
+ UINT8 *p;
+ UINT32 i;
+#ifdef EFI64
+ // Destination and source buffers should starts at the 16-byte boundary
+ if ((int)pnew&0xf || (int)pold&0xf) return NULL;
+#endif
+ if (!IsPeImageValid(pold)) return NULL;
+ pFileHeader = (FILE_HEADER*)(pold+*(UINT32*)(pold+60)+4);
+ pOptHeader= (OPTIONAL_HEADER*)(pFileHeader+1);
+ // Sections should have at least sizeof(INTN)-byte alignment
+ if (pOptHeader->SectionAlignment<sizeof(INTN)) return NULL;
+ pSection=(SECTION_HEADER*)((UINT8*)pOptHeader+pFileHeader->OptionalHeaderSize);
+ // copy headers
+ MemCpy(pnew,pold,pOptHeader->SizeOfHeaders);
+ //copy sections
+ // in the file image pSection->PointerToRawData contains offset of the section data
+ // in the memory image the section data should be placed at pSection->VirtualAddress RVA.
+ p=pnew+pOptHeader->SizeOfHeaders;
+ for(i=0;i<pFileHeader->NumberOfSections;i++,pSection++){
+ // fill with zeros am empty space between sections
+ MemSet(p,pnew+pSection->VirtualAddress-p,0);
+ p=pnew+pSection->VirtualAddress;
+ if (pSection->PointerToRawData){
+ UINTN SectionSize = (pSection->VirtualSize<pSection->SizeOfRawData)?pSection->VirtualSize:pSection->SizeOfRawData;
+ MemCpy(
+ pnew+pSection->VirtualAddress,
+ pold+pSection->PointerToRawData,
+ SectionSize
+ );
+ p+=SectionSize;
+ }
+ }
+ //align the last section
+ MemSet(p,pnew+pOptHeader->SizeOfImage-p,0);
+ // Fix up
+ if (!ReallocatePeImage(pnew, pnew, prealloc)) return NULL;
+#ifdef EFI_DEBUG
+{
+ //ITP Support
+ DEBUG_DIRECTORY *pDebug = GetDebugDirectory(pnew,NULL);
+ if (pDebug /*&& !pDebug->AddressOfRawData*/ && pDebug->PointerToRawData)
+ {
+ MemCpy(pnew+pOptHeader->SizeOfImage,pold+pDebug->PointerToRawData,pDebug->SizeOfData);
+ pDebug->AddressOfRawData = pOptHeader->SizeOfImage;
+ }
+}
+#endif
+ return pnew+pOptHeader->AddressOfEntryPoint;
+}
+
+//*************************************************************************
+//<AMI_PHDR_START>
+//
+// Name: LoadPeImage
+//
+// Description:
+// VOID* LoadPeImage(IN UINT8 *pold, IN UINT8 *pnew) is a wrapper function
+// for LoadPeImageEx which passes NULL for prealloc.
+//
+// Input:
+// IN UINT8 *pold
+// Pointer to the start of the file in memory.
+//
+// IN UINT8 *pnew
+// Pointer to starting location in memory for the loaded image.
+//
+// Output:
+// If successful, VOID* address of the entry point for the newly loaded
+// image; otherwise, NULL if pold and or pnew are not 16-byte aligned, or
+// pold does not point to valid PE image.
+//
+// Modified:
+//
+// Referrals:
+// LoadPeImageEx
+//
+// Notes:
+//
+//<AMI_PHDR_END>
+//*************************************************************************
+VOID* LoadPeImage(UINT8* pold, UINT8* pnew){
+ return LoadPeImageEx(pold,pnew,NULL);
+}
+
+//*************************************************************************
+//<AMI_PHDR_START>
+//
+// Name: FindPeSection
+//
+// Description:
+// VOID* FindPeSection(IN UINT8 *pstart, IN UINT64 name, OUT UINTN *pSize)
+// locates a section with the user provided name inside a portable executable
+// (PE) image.
+//
+// Input:
+// IN UINT8 *pstart
+// Pointer to the start of the image to be searched.
+//
+// IN UINT64 name
+// UINT64 name associated with the section to be located.
+//
+// OUT UINTN *pSize
+// Contains the size of the located section.
+//
+// Output:
+// If located, VOID* pointer to the virtual address of the located section;
+// otherwise, NULL.
+//
+// Modified:
+//
+// Referrals:
+//
+// Notes:
+//
+//<AMI_PHDR_END>
+//*************************************************************************
+VOID* FindPeSection(UINT8* pstart, UINT64 name, UINTN* pSize){
+ FILE_HEADER *pFileHeader = (FILE_HEADER*)(pstart+*(UINT32*)(pstart+60)+4);
+ SECTION_HEADER *pSection = (SECTION_HEADER*)((UINT8*)(pFileHeader+1)+pFileHeader->OptionalHeaderSize);
+ UINT32 i;
+ for(i=0;i<pFileHeader->NumberOfSections;i++,pSection++){
+ if (pSection->Name!=name) continue;
+ if (pSize) *pSize = pSection->VirtualSize;
+ return pstart+pSection->VirtualAddress;
+ }
+ return NULL;
+}
+//*************************************************************************
+//*************************************************************************
+//** **
+//** (C)Copyright 1985-2009, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//*************************************************************************
+//*************************************************************************