Correct TeImage file format and Clean up PeiRebase tool to remove unused code and only relocate image.

Move two EFI_DEP_REPLACE_TRUE and DEPEX_STACK_SIZE_INCREMENT macros from MdePkg to EdkModule/DxeMain module, because these two macros are specific implementation, not defined in spec.

git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@2249 6f19259b-4bc3-4df7-8a09-765794883524
This commit is contained in:
lgao4 2007-01-15 11:13:40 +00:00
parent 591ee27e84
commit 5b66424456
9 changed files with 146 additions and 372 deletions

View File

@ -33,6 +33,18 @@ Revision History
#include "Exec.h" #include "Exec.h"
#include "hand.h" #include "hand.h"
///
/// EFI_DEP_REPLACE_TRUE - Used to dynamically patch the dependecy expression
/// to save time. A EFI_DEP_PUSH is evauated one an
/// replaced with EFI_DEP_REPLACE_TRUE
///
#define EFI_DEP_REPLACE_TRUE 0xff
///
/// Define the initial size of the dependency expression evaluation stack
///
#define DEPEX_STACK_SIZE_INCREMENT 0x1000
typedef struct { typedef struct {
EFI_GUID *ProtocolGuid; EFI_GUID *ProtocolGuid;
VOID **Protocol; VOID **Protocol;

View File

@ -208,7 +208,7 @@ Returns:
} }
if (DebugEntry != NULL && DirectoryEntry != NULL) { if (DebugEntry != NULL && DirectoryEntry != NULL) {
for (DirCount = 0; DirCount < DirectoryEntry->Size; DirCount++, DebugEntry++) { for (DirCount = 0; DirCount < DirectoryEntry->Size; DirCount += sizeof(EFI_IMAGE_DEBUG_DIRECTORY_ENTRY), DebugEntry++) {
if (DebugEntry->Type == EFI_IMAGE_DEBUG_TYPE_CODEVIEW) { if (DebugEntry->Type == EFI_IMAGE_DEBUG_TYPE_CODEVIEW) {
if (DebugEntry->SizeOfData > 0) { if (DebugEntry->SizeOfData > 0) {
CodeViewEntryPointer = (VOID *) ((UINTN) DebugEntry->RVA + (UINTN) ImageAddress + (UINTN)TEImageAdjust); CodeViewEntryPointer = (VOID *) ((UINTN) DebugEntry->RVA + (UINTN) ImageAddress + (UINTN)TEImageAdjust);

View File

@ -12,6 +12,9 @@
Module Name: Dependency.h Module Name: Dependency.h
@par Revision Reference:
These definitions are from DxeCis 0.91 spec.
**/ **/
#ifndef __DEPENDENCY_H__ #ifndef __DEPENDENCY_H__
@ -34,16 +37,4 @@
/// EFI_DEP_SOR - If present, this must be the first opcode /// EFI_DEP_SOR - If present, this must be the first opcode
#define EFI_DEP_SOR 0x09 #define EFI_DEP_SOR 0x09
///
/// EFI_DEP_REPLACE_TRUE - Used to dynamically patch the dependecy expression
/// to save time. A EFI_DEP_PUSH is evauated one an
/// replaced with EFI_DEP_REPLACE_TRUE
///
#define EFI_DEP_REPLACE_TRUE 0xff
///
/// Define the initial size of the dependency expression evaluation stack
///
#define DEPEX_STACK_SIZE_INCREMENT 0x1000
#endif #endif

View File

@ -60,13 +60,6 @@
EFI_FILE_HEADER_INVALID \ EFI_FILE_HEADER_INVALID \
) )
#define EFI_TEST_FFS_ATTRIBUTES_BIT(FvbAttributes, TestAttributes, Bit) \
( \
(BOOLEAN) ( \
(FvbAttributes & EFI_FVB_ERASE_POLARITY) ? (((~TestAttributes) & Bit) == Bit) : ((TestAttributes & Bit) == Bit) \
) \
)
typedef UINT16 EFI_FFS_FILE_TAIL; typedef UINT16 EFI_FFS_FILE_TAIL;
/// ///

View File

@ -70,6 +70,13 @@ typedef UINT32 EFI_FVB_ATTRIBUTES;
EFI_FVB_LOCK_CAP \ EFI_FVB_LOCK_CAP \
) )
#define EFI_TEST_FFS_ATTRIBUTES_BIT(FvbAttributes, TestAttributes, Bit) \
( \
(BOOLEAN) ( \
(FvbAttributes & EFI_FVB_ERASE_POLARITY) ? (((~TestAttributes) & Bit) == Bit) : ((TestAttributes & Bit) == Bit) \
) \
)
#define EFI_FVB_STATUS (EFI_FVB_READ_STATUS | EFI_FVB_WRITE_STATUS | EFI_FVB_LOCK_STATUS) #define EFI_FVB_STATUS (EFI_FVB_READ_STATUS | EFI_FVB_WRITE_STATUS | EFI_FVB_LOCK_STATUS)
/// ///

View File

@ -299,7 +299,7 @@ PeCoffLoaderGetImageInfo (
ImageContext->ImageAddress = Hdr.Pe32Plus->OptionalHeader.ImageBase; ImageContext->ImageAddress = Hdr.Pe32Plus->OptionalHeader.ImageBase;
} }
} else { } else {
ImageContext->ImageAddress = (PHYSICAL_ADDRESS)(Hdr.Te->ImageBase); ImageContext->ImageAddress = (PHYSICAL_ADDRESS)(Hdr.Te->ImageBase + sizeof (EFI_TE_IMAGE_HEADER) - Hdr.Te->StrippedSize);
} }
// //
@ -598,8 +598,11 @@ PeCoffLoaderRelocateImage (
// //
if (ImageContext->DestinationAddress != 0) { if (ImageContext->DestinationAddress != 0) {
BaseAddress = ImageContext->DestinationAddress; BaseAddress = ImageContext->DestinationAddress;
} else { } else if (!(ImageContext->IsTeImage)) {
BaseAddress = ImageContext->ImageAddress; BaseAddress = ImageContext->ImageAddress;
} else {
Hdr.Te = (EFI_TE_IMAGE_HEADER *)(UINTN)(ImageContext->ImageAddress);
BaseAddress = ImageContext->ImageAddress + sizeof (EFI_TE_IMAGE_HEADER) - Hdr.Te->StrippedSize;
} }
if (!(ImageContext->IsTeImage)) { if (!(ImageContext->IsTeImage)) {

View File

@ -272,6 +272,7 @@ Returns:
// //
// Double-check the file to make sure it's what we expect it to be // Double-check the file to make sure it's what we expect it to be
// //
if (CheckPE32File (InFileName, InFptr, &MachineType, &SubSystem) != STATUS_SUCCESS) { if (CheckPE32File (InFileName, InFptr, &MachineType, &SubSystem) != STATUS_SUCCESS) {
goto Finish; goto Finish;
} }
@ -372,7 +373,7 @@ Returns:
TEImageHeader.Subsystem = (UINT8) OptionalHeader32.Subsystem; TEImageHeader.Subsystem = (UINT8) OptionalHeader32.Subsystem;
TEImageHeader.BaseOfCode = OptionalHeader32.BaseOfCode; TEImageHeader.BaseOfCode = OptionalHeader32.BaseOfCode;
TEImageHeader.ImageBase = (UINT64) (OptionalHeader32.ImageBase + TEImageHeader.StrippedSize - sizeof (EFI_TE_IMAGE_HEADER)); TEImageHeader.ImageBase = (UINT64) (OptionalHeader32.ImageBase);
if (OptionalHeader32.NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC) { if (OptionalHeader32.NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC) {
TEImageHeader.DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress = OptionalHeader32.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress; TEImageHeader.DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress = OptionalHeader32.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress;
TEImageHeader.DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size = OptionalHeader32.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size; TEImageHeader.DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size = OptionalHeader32.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size;
@ -413,7 +414,7 @@ Returns:
TEImageHeader.Subsystem = (UINT8) OptionalHeader64.Subsystem; TEImageHeader.Subsystem = (UINT8) OptionalHeader64.Subsystem;
TEImageHeader.BaseOfCode = OptionalHeader32.BaseOfCode; TEImageHeader.BaseOfCode = OptionalHeader32.BaseOfCode;
TEImageHeader.ImageBase = (UINT64) (OptionalHeader64.ImageBase + TEImageHeader.StrippedSize - sizeof (EFI_TE_IMAGE_HEADER)); TEImageHeader.ImageBase = (UINT64) (OptionalHeader64.ImageBase);
if (OptionalHeader64.NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC) { if (OptionalHeader64.NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC) {
TEImageHeader.DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress = OptionalHeader64.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress; TEImageHeader.DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress = OptionalHeader64.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress;
TEImageHeader.DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size = OptionalHeader64.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size; TEImageHeader.DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size = OptionalHeader64.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size;
@ -620,6 +621,17 @@ Returns:
goto Finish; goto Finish;
} }
//
// Check FileAlginment and SectionAlignment match or not
// Because TeImage header doesn't record filealginment and sectionalignment info,
// TeImage is used for PEIM and PeiCore XIP module.
// So, check alignment match before generate TeImage to check.
//
if (OptionalHdr.SectionAlignment != OptionalHdr.FileAlignment) {
Error (NULL, 0, 0, FileName, "Section-Alignment and File-Alignment does not match");
goto Finish;
}
*SubSystem = OptionalHdr.Subsystem; *SubSystem = OptionalHdr.Subsystem;
if (mOptions.Verbose) { if (mOptions.Verbose) {
fprintf (stdout, " Got subsystem = 0x%X from image\n", (int) *SubSystem); fprintf (stdout, " Got subsystem = 0x%X from image\n", (int) *SubSystem);

View File

@ -260,7 +260,7 @@ Returns:
if (!(ImageContext->IsTeImage)) { if (!(ImageContext->IsTeImage)) {
ImageContext->ImageAddress = PeHdr.OptionalHeader.ImageBase; ImageContext->ImageAddress = PeHdr.OptionalHeader.ImageBase;
} else { } else {
ImageContext->ImageAddress = (PHYSICAL_ADDRESS) (TeHdr.ImageBase); ImageContext->ImageAddress = (PHYSICAL_ADDRESS) (TeHdr.ImageBase + sizeof (EFI_TE_IMAGE_HEADER) - TeHdr.StrippedSize);
} }
// //
// Initialize the alternate destination address to 0 indicating that it // Initialize the alternate destination address to 0 indicating that it
@ -346,7 +346,7 @@ Returns:
} }
if (DebugDirectoryEntryFileOffset != 0) { if (DebugDirectoryEntryFileOffset != 0) {
for (Index = 0; Index < DebugDirectoryEntry->Size; Index++) { for (Index = 0; Index < (DebugDirectoryEntry->Size); Index += Size) {
// //
// Read next debug directory entry // Read next debug directory entry
// //
@ -363,7 +363,7 @@ Returns:
} }
if (DebugEntry.Type == EFI_IMAGE_DEBUG_TYPE_CODEVIEW) { if (DebugEntry.Type == EFI_IMAGE_DEBUG_TYPE_CODEVIEW) {
ImageContext->DebugDirectoryEntryRva = (UINT32) (DebugDirectoryEntryRva + Index * sizeof (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY)); ImageContext->DebugDirectoryEntryRva = (UINT32) (DebugDirectoryEntryRva + Index);
if (DebugEntry.RVA == 0 && DebugEntry.FileOffset != 0) { if (DebugEntry.RVA == 0 && DebugEntry.FileOffset != 0) {
ImageContext->ImageSize += DebugEntry.SizeOfData; ImageContext->ImageSize += DebugEntry.SizeOfData;
} }
@ -438,7 +438,7 @@ Returns:
} }
if (DebugDirectoryEntryFileOffset != 0) { if (DebugDirectoryEntryFileOffset != 0) {
for (Index = 0; Index < DebugDirectoryEntry->Size; Index++) { for (Index = 0; Index < (DebugDirectoryEntry->Size); Index += Size) {
// //
// Read next debug directory entry // Read next debug directory entry
// //
@ -455,7 +455,7 @@ Returns:
} }
if (DebugEntry.Type == EFI_IMAGE_DEBUG_TYPE_CODEVIEW) { if (DebugEntry.Type == EFI_IMAGE_DEBUG_TYPE_CODEVIEW) {
ImageContext->DebugDirectoryEntryRva = (UINT32) (DebugDirectoryEntryRva + Index * sizeof (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY)); ImageContext->DebugDirectoryEntryRva = (UINT32) (DebugDirectoryEntryRva + Index);
return RETURN_SUCCESS; return RETURN_SUCCESS;
} }
} }

View File

@ -279,6 +279,7 @@ Returns:
break; break;
} }
} }
// //
// Open the file containing the FV // Open the file containing the FV
// //
@ -553,14 +554,18 @@ Returns:
Version(); Version();
printf ( printf (
"\nUsage: %s -I InputFileName -O OutputFileName -B BaseAddress\n", "Usage: %s -I InputFileName -O OutputFileName -B BaseAddress [-F InputFvInfName]\n",
UTILITY_NAME UTILITY_NAME
); );
printf (" [-D BootDriverBaseAddress] [-R RuntimeDriverBaseAddress]\n");
printf (" Where:\n"); printf (" Where:\n");
printf (" InputFileName is the name of the EFI FV file to rebase.\n"); printf (" InputFileName is the name of the EFI FV file to rebase.\n");
printf (" OutputFileName is the desired output file name.\n"); printf (" OutputFileName is the desired output file name.\n");
printf (" BaseAddress is the FV base address to rebase agains.\n"); printf (" BaseAddress is the rebase address for all drivers run in Flash.\n");
printf (" Argument pair may be in any order.\n"); printf (" InputFvInfName is the Fv.inf file that contains this FV base address to rebase against.\n");
printf (" BootDriverBaseAddress is the rebase address for all boot drivers in this fv image.\n");
printf (" RuntimeDriverBaseAddress is the rebase address for all runtime drivers in this fv image.\n");
printf (" Argument pair may be in any order.\n\n");
} }
EFI_STATUS EFI_STATUS
@ -596,27 +601,18 @@ Returns:
{ {
EFI_STATUS Status; EFI_STATUS Status;
PE_COFF_LOADER_IMAGE_CONTEXT ImageContext; PE_COFF_LOADER_IMAGE_CONTEXT ImageContext;
UINTN MemoryImagePointer;
UINTN MemoryImagePointerAligned;
EFI_PHYSICAL_ADDRESS ImageAddress;
UINT64 ImageSize;
EFI_PHYSICAL_ADDRESS EntryPoint;
UINT32 Pe32ImageSize;
EFI_PHYSICAL_ADDRESS NewPe32BaseAddress; EFI_PHYSICAL_ADDRESS NewPe32BaseAddress;
UINTN Index; UINTN Index;
EFI_FILE_SECTION_POINTER CurrentPe32Section; EFI_FILE_SECTION_POINTER CurrentPe32Section;
EFI_FFS_FILE_STATE SavedState; EFI_FFS_FILE_STATE SavedState;
EFI_IMAGE_NT_HEADERS32 *PeHdr; EFI_IMAGE_NT_HEADERS32 *PeHdr;
EFI_IMAGE_NT_HEADERS64 *PePlusHdr;
UINT32 *PeHdrSizeOfImage;
UINT32 *PeHdrChecksum;
EFI_TE_IMAGE_HEADER *TEImageHeader; EFI_TE_IMAGE_HEADER *TEImageHeader;
UINT8 *TEBuffer;
EFI_IMAGE_DOS_HEADER *DosHeader;
UINT8 FileGuidString[80]; UINT8 FileGuidString[80];
UINT32 TailSize; UINT32 TailSize;
EFI_FFS_FILE_TAIL TailValue; EFI_FFS_FILE_TAIL TailValue;
EFI_PHYSICAL_ADDRESS *BaseToUpdate; EFI_PHYSICAL_ADDRESS *BaseToUpdate;
EFI_IMAGE_DEBUG_DIRECTORY_ENTRY *DebugEntry;
// //
// Verify input parameters // Verify input parameters
@ -668,7 +664,6 @@ Returns:
break; break;
} }
// //
// Initialize context // Initialize context
// //
@ -681,6 +676,50 @@ Returns:
return Status; return Status;
} }
//
// Don't Load PeImage, only to relocate current image.
//
ImageContext.ImageAddress = (UINTN) CurrentPe32Section.Pe32Section + sizeof (EFI_PE32_SECTION);
//
// Check if section-alignment and file-alignment match or not
//
PeHdr = (EFI_IMAGE_NT_HEADERS *)((UINTN)ImageContext.ImageAddress + ImageContext.PeCoffHeaderOffset);
if (PeHdr->OptionalHeader.SectionAlignment != PeHdr->OptionalHeader.FileAlignment) {
//
// Nor XIP module can be ignored.
//
if ((Flags & 1) == 0) {
continue;
}
Error (NULL, 0, 0, "Section-Alignment and File-Alignment does not match", FileGuidString);
return EFI_ABORTED;
}
//
// Update CodeView and PdbPointer in ImageContext
//
DebugEntry = (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY *)(UINTN)(
ImageContext.ImageAddress +
ImageContext.DebugDirectoryEntryRva
);
ImageContext.CodeView = (VOID *)(UINTN)(
ImageContext.ImageAddress +
DebugEntry->RVA
);
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;
}
// //
// Calculate the PE32 base address, based on file type // Calculate the PE32 base address, based on file type
// //
@ -697,19 +736,12 @@ Returns:
} }
NewPe32BaseAddress = NewPe32BaseAddress =
XipBase + XipBase + (UINTN)ImageContext.ImageAddress - (UINTN)FfsFile;
(UINTN)CurrentPe32Section.Pe32Section +
sizeof (EFI_COMMON_SECTION_HEADER) -
(UINTN)FfsFile;
BaseToUpdate = &XipBase; BaseToUpdate = &XipBase;
break; break;
case EFI_FV_FILETYPE_DRIVER: case EFI_FV_FILETYPE_DRIVER:
PeHdr = (EFI_IMAGE_NT_HEADERS32*)( PeHdr = (EFI_IMAGE_NT_HEADERS32*)(ImageContext.ImageAddress + ImageContext.PeCoffHeaderOffset);
(UINTN)CurrentPe32Section.Pe32Section +
sizeof (EFI_COMMON_SECTION_HEADER) +
ImageContext.PeCoffHeaderOffset
);
switch (PeHdr->OptionalHeader.Subsystem) { switch (PeHdr->OptionalHeader.Subsystem) {
case EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER: case EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER:
if ((Flags & 4) == 0) { if ((Flags & 4) == 0) {
@ -759,72 +791,13 @@ Returns:
return EFI_SUCCESS; return EFI_SUCCESS;
} }
//
// Allocate a buffer for the image to be loaded into.
//
Pe32ImageSize = GetLength (CurrentPe32Section.Pe32Section->CommonHeader.Size) - sizeof (EFI_PE32_SECTION);
MemoryImagePointer = (UINTN) (malloc (Pe32ImageSize + 0x100000));
if (MemoryImagePointer == 0) {
Error (NULL, 0, 0, "memory allocation failure", NULL);
return EFI_OUT_OF_RESOURCES;
}
memset ((void *) MemoryImagePointer, 0, Pe32ImageSize + 0x100000);
MemoryImagePointerAligned = (MemoryImagePointer + 0x0FFFF) & (-1 << 16);
ImageContext.ImageAddress = MemoryImagePointerAligned;
Status = PeCoffLoaderLoadImage (&ImageContext);
if (EFI_ERROR (Status)) {
Error (NULL, 0, 0, "LoadImage() call failed on rebase", FileGuidString);
free ((VOID *) MemoryImagePointer);
return Status;
}
//
// Check if section-alignment and file-alignment match or not
//
if (!(ImageContext.IsTeImage)) {
PeHdr = (EFI_IMAGE_NT_HEADERS *)((UINTN)ImageContext.ImageAddress +
ImageContext.PeCoffHeaderOffset);
if (PeHdr->OptionalHeader.SectionAlignment != PeHdr->OptionalHeader.FileAlignment) {
Error (NULL, 0, 0, "Section-Alignment and File-Alignment does not match", FileGuidString);
free ((VOID *) MemoryImagePointer);
return EFI_ABORTED;
}
}
else {
//
// BUGBUG: TE Image Header lack section-alignment and file-alignment info
//
}
ImageContext.DestinationAddress = NewPe32BaseAddress; ImageContext.DestinationAddress = NewPe32BaseAddress;
Status = PeCoffLoaderRelocateImage (&ImageContext); Status = PeCoffLoaderRelocateImage (&ImageContext);
if (EFI_ERROR (Status)) { if (EFI_ERROR (Status)) {
Error (NULL, 0, 0, "RelocateImage() call failed on rebase", FileGuidString); Error (NULL, 0, 0, "RelocateImage() call failed on rebase", FileGuidString);
free ((VOID *) MemoryImagePointer);
return Status; return Status;
} }
ImageAddress = ImageContext.ImageAddress;
ImageSize = ImageContext.ImageSize;
EntryPoint = ImageContext.EntryPoint;
if (ImageSize > Pe32ImageSize) {
Error (
NULL,
0,
0,
"rebased image is larger than original PE32 image",
"0x%X > 0x%X, file %s",
ImageSize,
Pe32ImageSize,
FileGuidString
);
free ((VOID *) MemoryImagePointer);
return EFI_ABORTED;
}
// //
// Update BASE address // Update BASE address
// //
@ -837,47 +810,6 @@ Returns:
); );
*BaseToUpdate += EFI_SIZE_TO_PAGES (ImageContext.ImageSize) * EFI_PAGE_SIZE; *BaseToUpdate += EFI_SIZE_TO_PAGES (ImageContext.ImageSize) * EFI_PAGE_SIZE;
//
// Since we may have updated the Codeview RVA, we need to insure the PE
// header indicates the image is large enough to contain the Codeview data
// so it will be loaded properly later if the PEIM is reloaded into memory...
//
PeHdr = (VOID *) ((UINTN) ImageAddress + ImageContext.PeCoffHeaderOffset);
PePlusHdr = (EFI_IMAGE_NT_HEADERS64*)PeHdr;
if (PeHdr->FileHeader.Machine == EFI_IMAGE_MACHINE_IA32) {
PeHdrSizeOfImage = (UINT32 *) (&(PeHdr->OptionalHeader).SizeOfImage);
PeHdrChecksum = (UINT32 *) (&(PeHdr->OptionalHeader).CheckSum);
} else if (PeHdr->FileHeader.Machine == EFI_IMAGE_MACHINE_IA64) {
PeHdrSizeOfImage = (UINT32 *) (&(PePlusHdr->OptionalHeader).SizeOfImage);
PeHdrChecksum = (UINT32 *) (&(PePlusHdr->OptionalHeader).CheckSum);
} else if (PeHdr->FileHeader.Machine == EFI_IMAGE_MACHINE_X64) {
PeHdrSizeOfImage = (UINT32 *) (&(PePlusHdr->OptionalHeader).SizeOfImage);
PeHdrChecksum = (UINT32 *) (&(PePlusHdr->OptionalHeader).CheckSum);
} else {
Error (
NULL,
0,
0,
"unknown machine type in PE32 image",
"machine type=0x%X, file=%s",
(UINT32) PeHdr->FileHeader.Machine,
FileGuidString
);
free ((VOID *) MemoryImagePointer);
return EFI_ABORTED;
}
if (*PeHdrSizeOfImage != ImageContext.ImageSize) {
*PeHdrSizeOfImage = (UINT32) ImageContext.ImageSize;
if (*PeHdrChecksum) {
*PeHdrChecksum = 0;
}
}
memcpy (CurrentPe32Section.Pe32Section + 1, (VOID *) MemoryImagePointerAligned, (UINT32) ImageSize);
free ((VOID *) MemoryImagePointer);
// //
// Now update file checksum // Now update file checksum
// //
@ -939,235 +871,65 @@ Returns:
// //
TEImageHeader = (EFI_TE_IMAGE_HEADER *) ((UINT8 *) CurrentPe32Section.Pe32Section + sizeof (EFI_COMMON_SECTION_HEADER)); TEImageHeader = (EFI_TE_IMAGE_HEADER *) ((UINT8 *) CurrentPe32Section.Pe32Section + sizeof (EFI_COMMON_SECTION_HEADER));
NewPe32BaseAddress = ((UINT32) XipBase) +
(
(UINTN) CurrentPe32Section.Pe32Section +
sizeof (EFI_COMMON_SECTION_HEADER) +
sizeof (EFI_TE_IMAGE_HEADER) -
TEImageHeader->StrippedSize -
(UINTN) FfsFile
);
// //
// Allocate a buffer to unshrink the image into. // Initialize context, load image info.
//
Pe32ImageSize = GetLength (CurrentPe32Section.Pe32Section->CommonHeader.Size) - sizeof (EFI_PE32_SECTION) -
sizeof (EFI_TE_IMAGE_HEADER);
Pe32ImageSize += TEImageHeader->StrippedSize;
TEBuffer = (UINT8 *) malloc (Pe32ImageSize);
if (TEBuffer == NULL) {
Error (NULL, 0, 0, "failed to allocate memory", NULL);
return EFI_OUT_OF_RESOURCES;
}
//
// Expand the image into our buffer and fill in critical fields in the DOS header
// Fill in fields required by the loader.
// At offset 0x3C is the offset to the PE signature. We'll put it immediately following the offset value
// itself.
//
memset (TEBuffer, 0, Pe32ImageSize);
DosHeader = (EFI_IMAGE_DOS_HEADER *) TEBuffer;
DosHeader->e_magic = EFI_IMAGE_DOS_SIGNATURE;
*(UINT32 *) (TEBuffer + 0x3C) = 0x40;
PeHdr = (EFI_IMAGE_NT_HEADERS *) (TEBuffer + 0x40);
PePlusHdr = (EFI_IMAGE_NT_HEADERS64*)PeHdr;
PeHdr->Signature = EFI_IMAGE_NT_SIGNATURE;
PeHdr->FileHeader.Machine = TEImageHeader->Machine;
PeHdr->FileHeader.NumberOfSections = TEImageHeader->NumberOfSections;
//
// Say the size of the optional header is the total we stripped off less the size of a PE file header and PE signature and
// the 0x40 bytes for our DOS header.
//
PeHdr->FileHeader.SizeOfOptionalHeader = (UINT16) (TEImageHeader->StrippedSize - 0x40 - sizeof (UINT32) - sizeof (EFI_IMAGE_FILE_HEADER));
if (TEImageHeader->Machine == EFI_IMAGE_MACHINE_IA32) {
PeHdr->OptionalHeader.Magic = EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC;
} else if (TEImageHeader->Machine == EFI_IMAGE_MACHINE_IA64) {
PePlusHdr->OptionalHeader.Magic = EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC;
} else if (TEImageHeader->Machine == EFI_IMAGE_MACHINE_X64) {
PePlusHdr->OptionalHeader.Magic = EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC;
} else {
Error (
NULL,
0,
0,
"unknown machine type in TE image",
"machine type=0x%X, file=%s",
(UINT32) TEImageHeader->Machine,
FileGuidString
);
free (TEBuffer);
return EFI_ABORTED;
}
if (PeHdr->OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
PeHdr->OptionalHeader.ImageBase = (UINTN) (TEImageHeader->ImageBase - TEImageHeader->StrippedSize + sizeof (EFI_TE_IMAGE_HEADER));
PeHdr->OptionalHeader.SizeOfImage = Pe32ImageSize;
PeHdr->OptionalHeader.Subsystem = TEImageHeader->Subsystem;
PeHdr->OptionalHeader.SizeOfHeaders = TEImageHeader->StrippedSize + TEImageHeader->NumberOfSections *
sizeof (EFI_IMAGE_SECTION_HEADER) - 12;
//
// Set NumberOfRvaAndSizes in the optional header to what we had available in the original image
//
if ((TEImageHeader->DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress != 0) ||
(TEImageHeader->DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size != 0)
) {
PeHdr->OptionalHeader.NumberOfRvaAndSizes = EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC + 1;
PeHdr->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress = TEImageHeader->DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress;
PeHdr->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size = TEImageHeader->DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size;
}
if ((TEImageHeader->DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress != 0) ||
(TEImageHeader->DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG].Size != 0)
) {
PeHdr->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress = TEImageHeader->DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress;
PeHdr->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].Size = TEImageHeader->DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG].Size;
if (PeHdr->OptionalHeader.NumberOfRvaAndSizes < EFI_IMAGE_DIRECTORY_ENTRY_DEBUG + 1) {
PeHdr->OptionalHeader.NumberOfRvaAndSizes = EFI_IMAGE_DIRECTORY_ENTRY_DEBUG + 1;
}
}
//
// NOTE: These values are defaults, and should be verified to be correct in the GenTE utility
//
PeHdr->OptionalHeader.SectionAlignment = 0x10;
} else {
PePlusHdr->OptionalHeader.ImageBase = (UINTN) (TEImageHeader->ImageBase - TEImageHeader->StrippedSize + sizeof (EFI_TE_IMAGE_HEADER));
PePlusHdr->OptionalHeader.SizeOfImage = Pe32ImageSize;
PePlusHdr->OptionalHeader.Subsystem = TEImageHeader->Subsystem;
PePlusHdr->OptionalHeader.SizeOfHeaders = TEImageHeader->StrippedSize + TEImageHeader->NumberOfSections *
sizeof (EFI_IMAGE_SECTION_HEADER) - 12;
//
// Set NumberOfRvaAndSizes in the optional header to what we had available in the original image
//
if ((TEImageHeader->DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress != 0) ||
(TEImageHeader->DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size != 0)
) {
PePlusHdr->OptionalHeader.NumberOfRvaAndSizes = EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC + 1;
PePlusHdr->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress = TEImageHeader->DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress;
PePlusHdr->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size = TEImageHeader->DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size;
}
if ((TEImageHeader->DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress != 0) ||
(TEImageHeader->DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG].Size != 0)
) {
PePlusHdr->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress = TEImageHeader->DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress;
PePlusHdr->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].Size = TEImageHeader->DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG].Size;
if (PePlusHdr->OptionalHeader.NumberOfRvaAndSizes < EFI_IMAGE_DIRECTORY_ENTRY_DEBUG + 1) {
PePlusHdr->OptionalHeader.NumberOfRvaAndSizes = EFI_IMAGE_DIRECTORY_ENTRY_DEBUG + 1;
}
}
//
// NOTE: These values are defaults, and should be verified to be correct in the GenTE utility
//
PePlusHdr->OptionalHeader.SectionAlignment = 0x10;
}
//
// Copy the rest of the image to its original offset
//
memcpy (
TEBuffer + TEImageHeader->StrippedSize,
(UINT8 *) CurrentPe32Section.Pe32Section + sizeof (EFI_PE32_SECTION) + sizeof (EFI_TE_IMAGE_HEADER),
GetLength (CurrentPe32Section.Pe32Section->CommonHeader.Size) - sizeof (EFI_PE32_SECTION) -
sizeof (EFI_TE_IMAGE_HEADER)
);
//
// Initialize context
// //
memset (&ImageContext, 0, sizeof (ImageContext)); memset (&ImageContext, 0, sizeof (ImageContext));
ImageContext.Handle = (VOID *) TEBuffer; ImageContext.Handle = (VOID *) TEImageHeader;
ImageContext.ImageRead = (PE_COFF_LOADER_READ_FILE) FfsRebaseImageRead; ImageContext.ImageRead = (PE_COFF_LOADER_READ_FILE) FfsRebaseImageRead;
Status = PeCoffLoaderGetImageInfo (&ImageContext); Status = PeCoffLoaderGetImageInfo (&ImageContext);
if (EFI_ERROR (Status)) { if (EFI_ERROR (Status)) {
Error (NULL, 0, 0, "GetImageInfo() call failed on rebase of TE image", FileGuidString); Error (NULL, 0, 0, "GetImageInfo() call failed on rebase of TE image", FileGuidString);
free (TEBuffer);
return Status; return Status;
} }
// //
// Allocate a buffer for the image to be loaded into. // Don't reload TeImage
// //
MemoryImagePointer = (UINTN) (malloc (Pe32ImageSize + 0x100000)); ImageContext.ImageAddress = (UINTN) TEImageHeader;
if (MemoryImagePointer == 0) {
Error (NULL, 0, 0, "memory allocation error on rebase of TE image", FileGuidString);
free (TEBuffer);
return EFI_OUT_OF_RESOURCES;
}
memset ((void *) MemoryImagePointer, 0, Pe32ImageSize + 0x100000);
MemoryImagePointerAligned = (MemoryImagePointer + 0x0FFFF) & (-1 << 16);
//
// Update CodeView and PdbPointer in ImageContext
//
DebugEntry = (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY *)(UINTN)(
ImageContext.ImageAddress +
ImageContext.DebugDirectoryEntryRva +
sizeof(EFI_TE_IMAGE_HEADER) -
TEImageHeader->StrippedSize
);
ImageContext.ImageAddress = MemoryImagePointerAligned; ImageContext.CodeView = (VOID *)(UINTN)(
Status = PeCoffLoaderLoadImage (&ImageContext); ImageContext.ImageAddress +
if (EFI_ERROR (Status)) { DebugEntry->RVA +
Error (NULL, 0, 0, "LoadImage() call failed on rebase of TE image", FileGuidString); sizeof(EFI_TE_IMAGE_HEADER) -
free (TEBuffer); TEImageHeader->StrippedSize
free ((VOID *) MemoryImagePointer); );
return Status;
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;
} }
ImageContext.DestinationAddress = NewPe32BaseAddress; //
// Reloacate TeImage
//
ImageContext.DestinationAddress = XipBase + (UINTN) TEImageHeader + sizeof (EFI_TE_IMAGE_HEADER) \
- TEImageHeader->StrippedSize - (UINTN) FfsFile;
Status = PeCoffLoaderRelocateImage (&ImageContext); Status = PeCoffLoaderRelocateImage (&ImageContext);
if (EFI_ERROR (Status)) { if (EFI_ERROR (Status)) {
Error (NULL, 0, 0, "RelocateImage() call failed on rebase of TE image", FileGuidString); Error (NULL, 0, 0, "RelocateImage() call failed on rebase of TE image", FileGuidString);
free ((VOID *) MemoryImagePointer);
free (TEBuffer);
return Status; return Status;
} }
ImageAddress = ImageContext.ImageAddress;
ImageSize = ImageContext.ImageSize;
EntryPoint = ImageContext.EntryPoint;
//
// Since we may have updated the Codeview RVA, we need to insure the PE
// header indicates the image is large enough to contain the Codeview data
// so it will be loaded properly later if the PEIM is reloaded into memory...
//
PeHdr = (VOID *) ((UINTN) ImageAddress + ImageContext.PeCoffHeaderOffset);
PePlusHdr = (EFI_IMAGE_NT_HEADERS64*)PeHdr;
if (PeHdr->FileHeader.Machine == EFI_IMAGE_MACHINE_IA32) {
PeHdrSizeOfImage = (UINT32 *) (&(PeHdr->OptionalHeader).SizeOfImage);
PeHdrChecksum = (UINT32 *) (&(PeHdr->OptionalHeader).CheckSum);
} else if (PeHdr->FileHeader.Machine == EFI_IMAGE_MACHINE_IA64) {
PeHdrSizeOfImage = (UINT32 *) (&(PePlusHdr->OptionalHeader).SizeOfImage);
PeHdrChecksum = (UINT32 *) (&(PePlusHdr->OptionalHeader).CheckSum);
} else if (PeHdr->FileHeader.Machine == EFI_IMAGE_MACHINE_X64) {
PeHdrSizeOfImage = (UINT32 *) (&(PePlusHdr->OptionalHeader).SizeOfImage);
PeHdrChecksum = (UINT32 *) (&(PePlusHdr->OptionalHeader).CheckSum);
} else {
Error (
NULL,
0,
0,
"unknown machine type in TE image",
"machine type=0x%X, file=%s",
(UINT32) PeHdr->FileHeader.Machine,
FileGuidString
);
free ((VOID *) MemoryImagePointer);
free (TEBuffer);
return EFI_ABORTED;
}
if (*PeHdrSizeOfImage != ImageContext.ImageSize) {
*PeHdrSizeOfImage = (UINT32) ImageContext.ImageSize;
if (*PeHdrChecksum) {
*PeHdrChecksum = 0;
}
}
TEImageHeader->ImageBase = (UINT64) (NewPe32BaseAddress + TEImageHeader->StrippedSize - sizeof (EFI_TE_IMAGE_HEADER));
memcpy (
(UINT8 *) (CurrentPe32Section.Pe32Section + 1) + sizeof (EFI_TE_IMAGE_HEADER),
(VOID *) ((UINT8 *) MemoryImagePointerAligned + TEImageHeader->StrippedSize),
GetLength (CurrentPe32Section.Pe32Section->CommonHeader.Size) - sizeof (EFI_PE32_SECTION) -
sizeof (EFI_TE_IMAGE_HEADER)
);
if (FfsFile->Attributes & FFS_ATTRIB_TAIL_PRESENT) { if (FfsFile->Attributes & FFS_ATTRIB_TAIL_PRESENT) {
TailSize = sizeof (EFI_FFS_FILE_TAIL); TailSize = sizeof (EFI_FFS_FILE_TAIL);
} else { } else {
@ -1206,12 +968,6 @@ Returns:
ImageContext.DestinationAddress, ImageContext.DestinationAddress,
ImageContext.PdbPointer == NULL ? "*" : ImageContext.PdbPointer ImageContext.PdbPointer == NULL ? "*" : ImageContext.PdbPointer
); );
//
// Free buffers
//
free ((VOID *) MemoryImagePointer);
free (TEBuffer);
} }
return EFI_SUCCESS; return EFI_SUCCESS;