pecoffloader.c
来自「EFI BIOS是Intel提出的下一代的BIOS标准。这里上传的Edk源代码是」· C语言 代码 · 共 1,408 行 · 第 1/4 页
C
1,408 行
/*++
Copyright (c) 2005 - 2006, Intel Corporation
All rights reserved. This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
Module Name:
PeCoffLoader.c
Abstract:
Tiano PE/COFF loader
Revision History
--*/
#include "Tiano.h"
#include "Pei.h"
#include "PeiLib.h"
#include "PeCoffLoaderEx.h"
#ifdef EFI_NT_EMULATOR
#include "peilib.h"
#include "EfiHobLib.h"
#include EFI_PPI_DEFINITION (NtLoadAsDll)
#endif
STATIC
EFI_STATUS
PeCoffLoaderGetPeHeader (
IN OUT EFI_PEI_PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext,
OUT EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION Hdr
);
STATIC
VOID*
PeCoffLoaderImageAddress (
IN OUT EFI_PEI_PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext,
IN UINTN Address
);
EFI_STATUS
EFIAPI
PeCoffLoaderGetImageInfo (
IN EFI_PEI_PE_COFF_LOADER_PROTOCOL *This,
IN OUT EFI_PEI_PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext
);
EFI_STATUS
EFIAPI
PeCoffLoaderRelocateImage (
IN EFI_PEI_PE_COFF_LOADER_PROTOCOL *This,
IN OUT EFI_PEI_PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext
);
EFI_STATUS
EFIAPI
PeCoffLoaderLoadImage (
IN EFI_PEI_PE_COFF_LOADER_PROTOCOL *This,
IN OUT EFI_PEI_PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext
);
EFI_STATUS
EFIAPI
PeCoffLoaderUnloadImage (
IN EFI_PEI_PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext
);
#if defined (EFI_DEBUG_ITP_BREAK) && !defined (_CONSOLE)
VOID
AsmEfiSetBreakSupport (
IN UINTN LoadAddr
);
#endif
EFI_PEI_PE_COFF_LOADER_PROTOCOL mPeCoffLoader = {
PeCoffLoaderGetImageInfo,
PeCoffLoaderLoadImage,
PeCoffLoaderRelocateImage,
PeCoffLoaderUnloadImage
};
#ifdef EFI_NT_EMULATOR
EFI_NT_LOAD_AS_DLL_PPI *mPeCoffLoaderWinNtLoadAsDll = NULL;
#endif
EFI_STATUS
InstallEfiPeiPeCoffLoader (
IN EFI_PEI_SERVICES **PeiServices,
IN OUT EFI_PEI_PE_COFF_LOADER_PROTOCOL **This,
IN EFI_PEI_PPI_DESCRIPTOR *ThisPpi
)
/*++
Routine Description:
Install PE/COFF loader PPI
Arguments:
PeiServices - General purpose services available to every PEIM
This - Pointer to get Pei PE coff loader protocol as output
ThisPpi - Passed in as EFI_NT_LOAD_AS_DLL_PPI on NT_EMULATOR platform
Returns:
EFI_SUCCESS
--*/
{
EFI_STATUS Status;
Status = EFI_SUCCESS;
#ifdef EFI_NT_EMULATOR
//
// For use by PEI Core and Modules
//
if (NULL != PeiServices) {
Status = (**PeiServices).LocatePpi (
PeiServices,
&gEfiNtLoadAsDllPpiGuid,
0,
NULL,
&mPeCoffLoaderWinNtLoadAsDll
);
} else {
//
// Now in SecMain or ERM usage, bind appropriately
//
PEI_ASSERT (PeiServices, (NULL != ThisPpi));
mPeCoffLoaderWinNtLoadAsDll = (EFI_NT_LOAD_AS_DLL_PPI *) ThisPpi;
PEI_ASSERT (PeiServices, (NULL != mPeCoffLoaderWinNtLoadAsDll));
}
#endif
if (NULL != This) {
*This = &mPeCoffLoader;
}
return Status;
}
STATIC
EFI_STATUS
PeCoffLoaderGetPeHeader (
IN OUT EFI_PEI_PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext,
OUT EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION Hdr
)
/*++
Routine Description:
Retrieves the PE or TE Header from a PE/COFF or TE image
Arguments:
ImageContext - The context of the image being loaded
PeHdr - The buffer in which to return the PE32, PE32+, or TE header
Returns:
EFI_SUCCESS if the PE or TE Header is read,
Otherwise, the error status from reading the PE/COFF or TE image using the ImageRead function.
--*/
{
EFI_STATUS Status;
EFI_IMAGE_DOS_HEADER DosHdr;
UINTN Size;
UINT16 Magic;
//
// Read the DOS image header to check for it's existance
//
Size = sizeof (EFI_IMAGE_DOS_HEADER);
Status = ImageContext->ImageRead (
ImageContext->Handle,
0,
&Size,
&DosHdr
);
if (EFI_ERROR (Status)) {
ImageContext->ImageError = EFI_IMAGE_ERROR_IMAGE_READ;
return Status;
}
ImageContext->PeCoffHeaderOffset = 0;
if (DosHdr.e_magic == EFI_IMAGE_DOS_SIGNATURE) {
//
// DOS image header is present, so read the PE header after the DOS image
// header
//
ImageContext->PeCoffHeaderOffset = DosHdr.e_lfanew;
}
//
// Read the PE/COFF Header. For PE32 (32-bit) this will read in too much
// data, but that should not hurt anythine. Hdr.Pe32->OptionalHeader.Magic
// determins if this is a PE32 or PE32+ image. The magic is in the same
// location in both images.
//
Size = sizeof (EFI_IMAGE_OPTIONAL_HEADER_UNION);
Status = ImageContext->ImageRead (
ImageContext->Handle,
ImageContext->PeCoffHeaderOffset,
&Size,
Hdr.Pe32
);
if (EFI_ERROR (Status)) {
ImageContext->ImageError = EFI_IMAGE_ERROR_IMAGE_READ;
return Status;
}
//
// Use Signature to figure out if we understand the image format
//
if (Hdr.Te->Signature == EFI_TE_IMAGE_HEADER_SIGNATURE) {
ImageContext->IsTeImage = TRUE;
ImageContext->Machine = Hdr.Te->Machine;
ImageContext->ImageType = (UINT16)(Hdr.Te->Subsystem);
ImageContext->ImageSize = 0;
ImageContext->SectionAlignment = 4096;
ImageContext->SizeOfHeaders = sizeof (EFI_TE_IMAGE_HEADER) + (UINTN)Hdr.Te->BaseOfCode - (UINTN)Hdr.Te->StrippedSize;
} else if (Hdr.Pe32->Signature == EFI_IMAGE_NT_SIGNATURE) {
ImageContext->IsTeImage = FALSE;
ImageContext->Machine = Hdr.Pe32->FileHeader.Machine;
//
// NOTE: We use Machine to identify PE32/PE32+, instead of Magic.
// It is for backward-compatibility consideration, because
// some system will generate PE32+ image with PE32 Magic.
//
if (Hdr.Pe32->FileHeader.Machine == EFI_IMAGE_MACHINE_IA32) {
Magic = EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC;
} else if (Hdr.Pe32->FileHeader.Machine == EFI_IMAGE_MACHINE_IA64) {
Magic = EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC;
} else if (Hdr.Pe32->FileHeader.Machine == EFI_IMAGE_MACHINE_X64) {
Magic = EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC;
} else {
Magic = Hdr.Pe32->OptionalHeader.Magic;
}
if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
//
// Use PE32 offset
//
ImageContext->ImageType = Hdr.Pe32->OptionalHeader.Subsystem;
ImageContext->ImageSize = (UINT64)Hdr.Pe32->OptionalHeader.SizeOfImage;
ImageContext->SectionAlignment = Hdr.Pe32->OptionalHeader.SectionAlignment;
ImageContext->SizeOfHeaders = Hdr.Pe32->OptionalHeader.SizeOfHeaders;
} else if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC) {
//
// Use PE32+ offset
//
ImageContext->ImageType = Hdr.Pe32Plus->OptionalHeader.Subsystem;
ImageContext->ImageSize = (UINT64) Hdr.Pe32Plus->OptionalHeader.SizeOfImage;
ImageContext->SectionAlignment = Hdr.Pe32Plus->OptionalHeader.SectionAlignment;
ImageContext->SizeOfHeaders = Hdr.Pe32Plus->OptionalHeader.SizeOfHeaders;
} else {
ImageContext->ImageError = EFI_IMAGE_ERROR_INVALID_MACHINE_TYPE;
return EFI_UNSUPPORTED;
}
} else {
ImageContext->ImageError = EFI_IMAGE_ERROR_INVALID_MACHINE_TYPE;
return EFI_UNSUPPORTED;
}
if (!PeCoffLoaderImageFormatSupported (ImageContext->Machine)) {
//
// If the PE/COFF loader does not support the image type return
// unsupported. This library can suport lots of types of images
// this does not mean the user of this library can call the entry
// point of the image.
//
return EFI_UNSUPPORTED;
}
return EFI_SUCCESS;
}
STATIC
EFI_STATUS
PeCoffLoaderCheckImageType (
IN OUT EFI_PEI_PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext
)
/*++
Routine Description:
Checks the PE or TE header of a PE/COFF or TE image to determine if it supported
Arguments:
ImageContext - The context of the image being loaded
Returns:
EFI_SUCCESS if the PE/COFF or TE image is supported
EFI_UNSUPPORTED of the PE/COFF or TE image is not supported.
--*/
{
switch (ImageContext->ImageType) {
case EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION:
ImageContext->ImageCodeMemoryType = EfiLoaderCode;
ImageContext->ImageDataMemoryType = EfiLoaderData;
break;
case EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER:
ImageContext->ImageCodeMemoryType = EfiBootServicesCode;
ImageContext->ImageDataMemoryType = EfiBootServicesData;
break;
case EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER:
case EFI_IMAGE_SUBSYSTEM_SAL_RUNTIME_DRIVER:
ImageContext->ImageCodeMemoryType = EfiRuntimeServicesCode;
ImageContext->ImageDataMemoryType = EfiRuntimeServicesData;
break;
default:
ImageContext->ImageError = EFI_IMAGE_ERROR_INVALID_SUBSYSTEM;
return EFI_UNSUPPORTED;
}
return EFI_SUCCESS;
}
EFI_STATUS
EFIAPI
PeCoffLoaderGetImageInfo (
IN EFI_PEI_PE_COFF_LOADER_PROTOCOL *This,
IN OUT EFI_PEI_PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext
)
/*++
Routine Description:
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?