📄 pe.c
字号:
Image->Handle,
(VOID *)(UINTN)Image->EntryPoint,
(VOID **)&Image->EntryPoint);
if (EFI_ERROR(Status)) {
return Status;
}
}
if (CodeViewEntry != NULL) {
#ifdef EFI_NT_EMULATOR
//
// Load NT DLL if we know the name
//
if (Image->Machine != EFI_IMAGE_MACHINE_EBC) {
DllEntryPoint = NULL;
if(CodeViewEntry->Signature == CODEVIEW_SIGNATURE_RSDS){
Status = WinNtLoadAsDll ((CHAR8 *)( (EFI_IMAGE_DEBUG_CODEVIEW_RSDS_ENTRY*)CodeViewEntry + 1), &DllEntryPoint);
}else if(CodeViewEntry->Signature == CODEVIEW_SIGNATURE_NB10){
Status = WinNtLoadAsDll ((CHAR8 *)(CodeViewEntry + 1), &DllEntryPoint);
}
if (!EFI_ERROR(Status) && DllEntryPoint != NULL) {
Image->EntryPoint = (EFI_IMAGE_ENTRY_POINT)(UINTN)DllEntryPoint;
}
}
#endif
}
return EFI_SUCCESS;
}
#define ALIGN_POINTER(p,s) ((VOID *) (p + ((s - ((UINTN)p)) & (s-1))))
STATIC
EFI_STATUS
RUNTIMEFUNCTION
LoadPeRelocate (
IN LOADED_IMAGE *Image,
IN IMAGE_DATA_DIRECTORY *RelocDir,
IN UINT64 Adjust,
IN BOOLEAN RelocsStripped
)
{
IMAGE_BASE_RELOCATION *RelocBase, *RelocBaseEnd;
UINT16 *Reloc, *RelocEnd;
CHAR8 *Fixup, *FixupBase;
UINT16 *F16;
UINT32 *F32;
CHAR8 *FixupData;
UINTN BufferSize;
EFI_STATUS Status;
//
// Find the relocation block
//
RelocBase = (VOID *)RelocDir->VirtualAddress;
RelocBaseEnd = (VOID *)(RelocDir->VirtualAddress + RelocDir->Size);
//
// If no relocations, then make sure they weren't stripped.
//
if (!RelocDir || !RelocBase || !RelocBaseEnd) {
if (RelocsStripped) {
//
// If the image is a runtime driver, then never load it with relocations
// stripped. Otherwise, if the link address is the same as the load
// address, then it's ok.
//
return (Adjust == 0 && Image->Type != IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER) ? EFI_SUCCESS : EFI_LOAD_ERROR;
}
//
// PIC code
//
return EFI_SUCCESS;
}
RelocBase = ImageAddress (Image, RelocDir->VirtualAddress);
RelocBaseEnd = ImageAddress (Image, RelocDir->VirtualAddress + RelocDir->Size);
//
// Allocate a buffer large enough for the maximum fixup data size
//
Image->FixupData = AllocatePool (RelocDir->Size / sizeof(UINT16) * sizeof(UINTN));
if (!Image->FixupData) {
return EFI_OUT_OF_RESOURCES;
}
//
// Run the relocation information and apply the fixups
//
Status = EFI_LOAD_ERROR;
FixupData = Image->FixupData;
while (RelocBase < RelocBaseEnd) {
Reloc = (UINT16 *) ((CHAR8 *) RelocBase + sizeof(IMAGE_BASE_RELOCATION));
RelocEnd = (UINT16 *) ((CHAR8 *) RelocBase + RelocBase->SizeOfBlock);
FixupBase = ImageAddress (Image, RelocBase->VirtualAddress);
if ((CHAR8 *) RelocEnd < Image->ImageBase || (CHAR8 *) RelocEnd > Image->ImageEof) {
goto Done;
}
//
// Run this relocation record
//
while (Reloc < RelocEnd) {
Fixup = FixupBase + (*Reloc & 0xFFF);
switch ((*Reloc) >> 12) {
case IMAGE_REL_BASED_ABSOLUTE:
break;
case IMAGE_REL_BASED_HIGH:
F16 = (UINT16 *) Fixup;
*F16 = (*F16 << 16) + (UINT16) Adjust;
*(UINT16 *) FixupData = *F16;
FixupData = FixupData + sizeof(UINT16);
break;
case IMAGE_REL_BASED_LOW:
F16 = (UINT16 *) Fixup;
*F16 = *F16 + (UINT16) Adjust;
*(UINT16 *) FixupData = *F16;
FixupData = FixupData + sizeof(UINT16);
break;
case IMAGE_REL_BASED_HIGHLOW:
F32 = (UINT32 *) Fixup;
*F32 = *F32 + (UINT32) Adjust;
FixupData = ALIGN_POINTER(FixupData, sizeof(UINT32));
*(UINT32 *) FixupData = *F32;
FixupData = FixupData + sizeof(UINT32);
break;
case IMAGE_REL_BASED_HIGHADJ:
BREAKPOINT(); // BUGBUG: not done
break;
default:
Status = LoadPeRelocate_Ex (Reloc,Fixup,&FixupData,Adjust);
if (EFI_ERROR (Status)) {
goto Done;
}
}
// Next reloc record
Reloc += 1;
}
// next reloc block
RelocBase = (IMAGE_BASE_RELOCATION *) RelocEnd;
}
Status = EFI_SUCCESS;
Done:
//
// If the image was loaded re-size the fixup data buffer (into
// the proper type for the image)
//
if (!EFI_ERROR(Status)) {
BufferSize = (UINTN) (FixupData - Image->FixupData);
Status = BSAllocatePool(Image->Info.ImageCodeType, BufferSize, &FixupData);
if (!EFI_ERROR(Status)) {
CopyMem (FixupData, Image->FixupData, BufferSize);
FreePool (Image->FixupData);
Image->FixupData = FixupData;
}
}
return Status;
}
VOID
RUNTIMEFUNCTION INTERNAL
ConvertPeImage (
IN LOADED_IMAGE *Image
)
// Reapply fixups to move an image to a new address
{
CHAR8 *OldBase, *NewBase;
IMAGE_DOS_HEADER *DosHdr;
IMAGE_NT_HEADERS *PeHdr;
IMAGE_DATA_DIRECTORY *RelocDir;
IMAGE_BASE_RELOCATION *RelocBase, *RelocBaseEnd;
UINT16 *Reloc, *RelocEnd;
CHAR8 *Fixup, *FixupBase;
UINT16 *F16;
UINT32 *F32;
CHAR8 *FixupData;
UINTN Adjust;
EFI_STATUS Status;
OldBase = Image->ImageBase;
NewBase = Image->ImageBase;
RT->ConvertPointer (0, &NewBase);
DEBUG ((D_INIT, "ConvertPeImage: Changing image base from %x to %x\n", OldBase, NewBase));
Adjust = (UINTN) NewBase - (UINTN) OldBase;
//
// Find the image's relocate dir info
//
DosHdr = (IMAGE_DOS_HEADER *) Image->ImageBase;
ASSERT (DosHdr->e_magic == IMAGE_DOS_SIGNATURE);
PeHdr = (IMAGE_NT_HEADERS *) (((CHAR8 *) DosHdr) + DosHdr->e_lfanew);
ASSERT (PeHdr->Signature == IMAGE_NT_SIGNATURE);
if (IMAGE_DIRECTORY_ENTRY_BASERELOC < PeHdr->OptionalHeader.NumberOfRvaAndSizes) {
RelocDir = &PeHdr->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC];
RelocBase = ImageAddress(Image, RelocDir->VirtualAddress);
RelocBaseEnd = ImageAddress(Image, RelocDir->VirtualAddress + RelocDir->Size);
ASSERT (RelocBase && RelocBaseEnd);
} else {
//
// No relocation directory entry
//
RelocBase = NULL;
RelocBaseEnd = NULL;
}
//
// Run the whole relocation block
//
FixupData = Image->FixupData;
while (RelocBase < RelocBaseEnd) {
Reloc = (UINT16 *) ((CHAR8 *) RelocBase + sizeof(IMAGE_BASE_RELOCATION));
RelocEnd = (UINT16 *) ((CHAR8 *) RelocBase + RelocBase->SizeOfBlock);
ASSERT ((CHAR8 *) RelocEnd >= Image->ImageBase && (CHAR8 *) RelocEnd <= Image->ImageEof);
FixupBase = ImageAddress (Image, RelocBase->VirtualAddress);
//
// Run this relocation record
//
while (Reloc < RelocEnd) {
Fixup = FixupBase + (*Reloc & 0xFFF);
switch ((*Reloc) >> 12) {
case IMAGE_REL_BASED_ABSOLUTE:
break;
case IMAGE_REL_BASED_HIGH:
F16 = (UINT16 *) Fixup;
if (*(UINT16 *) FixupData == *F16) {
*F16 = (*F16 << 16) + (UINT16) Adjust;
}
FixupData = FixupData + sizeof(UINT16);
break;
case IMAGE_REL_BASED_LOW:
F16 = (UINT16 *) Fixup;
if (*(UINT16 *) FixupData == *F16) {
*F16 = *F16 + (UINT16) Adjust;
}
FixupData = FixupData + sizeof(UINT16);
break;
case IMAGE_REL_BASED_HIGHLOW:
F32 = (UINT32 *) Fixup;
FixupData = ALIGN_POINTER(FixupData, sizeof(UINT32));
if (*(UINT32 *) FixupData == *F32) {
*F32 = *F32 + (UINT32) Adjust;
}
FixupData = FixupData + sizeof(UINT32);
break;
case IMAGE_REL_BASED_HIGHADJ:
BREAKPOINT(); // BUGBUG: not done
break;
default:
Status = ConvertPeImage_Ex (Reloc,Fixup,&FixupData,Adjust);
if (EFI_ERROR (Status)) {
return;
}
}
// Next reloc record
Reloc += 1;
}
// next reloc block
RelocBase = (IMAGE_BASE_RELOCATION *) RelocEnd;
}
if (PL->FlushCache) {
//
// On some machines I-caches do not maintain coherency so you need to
// flush the data that we loaded out of any D-cache.
//
PL->FlushCache (Image->ImageBase, Image->ImageEof);
}
}
// BUGBUG -- function no longer used?
STATIC
VOID *
GetPeProcAddress (
IN LOADED_IMAGE *Image,
IN IMAGE_NT_HEADERS *PeHdr,
IN CHAR8 *FunctionName
)
{
IMAGE_DATA_DIRECTORY *DataDir;
IMAGE_EXPORT_DIRECTORY *ExportDir, *ExportDirEnd;
CHAR8 *Name;
UINT32 *Fncs, *Names;
UINTN Index;
//
// If we have a directory entry for the exports, search it
//
if (IMAGE_DIRECTORY_ENTRY_EXPORT < PeHdr->OptionalHeader.NumberOfRvaAndSizes) {
DataDir = &PeHdr->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT];
//
// Locate the export directory table
//
ExportDir = ImageAddress (Image, DataDir->VirtualAddress);
ExportDirEnd = ImageAddress (Image, DataDir->VirtualAddress + DataDir->Size);
if (!ExportDir || !ExportDirEnd || ExportDir == ExportDirEnd) {
return NULL;
}
//
// Locate the export function table
//
Fncs = ImageAddress (Image, (UINTN) ExportDir->AddressOfFunctions);
Names = ImageAddress (Image, (UINTN) ExportDir->AddressOfNames);
if (!Fncs || !Names) {
return NULL;
}
//
// Scan the export directory looking for a match
//
for (Index=0; Index < ExportDir->NumberOfNames; Index++) {
Name = ImageAddress(Image, Names[Index]);
if (Name && strcmpa (Name, FunctionName) == 0) {
break;
}
}
//
// If found, return the address of the function
//
if (Index < ExportDir->NumberOfNames && Index < ExportDir->NumberOfFunctions) {
return ImageAddress (Image, Fncs[Index]);
}
}
//
// Not found
//
return NULL;
}
STATIC
EFI_STATUS
ImageRead (
IN SIMPLE_READ_FILE FHand,
IN UINTN Offset,
IN OUT UINTN ReadSize,
OUT VOID *Buffer
)
// Load some data from the image
{
UINTN OrigReadSize;
EFI_STATUS Status;
//
// Read the data
//
OrigReadSize = ReadSize;
Status = ReadSimpleReadFile (FHand, Offset, &ReadSize, Buffer);
//
// If we didn't get it all, then there is an error
//
if (OrigReadSize != ReadSize) {
Status = EFI_LOAD_ERROR;
}
//
// If there's an error, zero the buffer
//
if (EFI_ERROR(Status)) {
ZeroMem (Buffer, OrigReadSize);
}
return Status;
}
STATIC
VOID *
RUNTIMEFUNCTION
ImageAddress (
IN LOADED_IMAGE *Image,
IN UINTN Address
)
// Convert an image address to the loaded address
{
CHAR8 *p;
p = Image->ImageAdjust + Address;
if (p < Image->ImageBase || p > Image->ImageEof) {
DEBUG((D_LOAD|D_ERROR, "ImageAddress: pointer is outside of image\n"));
p = NULL;
}
// DEBUG((D_LOAD, "ImageAddress: ImageBase %x, ImageEof %x, Address %x, p %x\n",
// Image->ImageBase, Image->ImageEof,
// Address, p));
return p;
}
//
// This callback function is used by the EBC interpreter driver to flush the
// processor instruction cache after creating thunks. We're simply hiding
// the "this" pointer that must be passed into the real flush function.
//
STATIC
EFI_STATUS
FlushICache (
IN EFI_PHYSICAL_ADDRESS Start,
IN UINT64 Length
)
{
if (PL->FlushCache) {
//
// On some machines I-caches do not maintain coherency so you need to
// flush the data that we loaded out of any D-cache.
//
PL->FlushCache ((VOID *)Start, (CHAR8 *)(Start+Length));
DEBUG((D_LOAD, "LoadPe: Cache Flush Done\n"));
}
return EFI_SUCCESS;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -