Import old and deprecated 'pecoff_o' module from old XTLDR
This commit is contained in:
parent
ee0603c318
commit
45e2a7ec66
@ -64,6 +64,11 @@ typedef VOID (*PBL_CONSOLE_SET_ATTRIBUTES)(IN ULONGLONG Attributes);
|
||||
typedef VOID (*PBL_CONSOLE_SET_CURSOR_POSITION)(IN ULONGLONG PosX, IN ULONGLONG PosY);
|
||||
typedef VOID (*PBL_CONSOLE_WRITE)(IN PUSHORT String);
|
||||
typedef VOID (*PBL_DEBUG_PRINT)(IN PUINT16 Format, IN ...);
|
||||
typedef EFI_STATUS (*PBL_EXECIMAGE_GET_ENTRY_POINT)(IN PVOID ImagePointer, OUT PVOID *EntryPoint);
|
||||
typedef EFI_STATUS (*PBL_EXECIMAGE_GET_MACHINE_TYPE)(IN PVOID ImagePointer, OUT PUSHORT MachineType);
|
||||
typedef EFI_STATUS (*PBL_EXECIMAGE_GET_SUBSYSTEM)(IN PVOID ImagePointer, OUT PUSHORT SubSystem);
|
||||
typedef EFI_STATUS (*PBL_EXECIMAGE_LOAD_IMAGE)(IN PEFI_FILE_HANDLE FileHandle, IN LOADER_MEMORY_TYPE MemoryType, IN PVOID VirtualAddress, OUT PVOID *ImagePointer);
|
||||
typedef EFI_STATUS (*PBL_EXECIMAGE_RELOCATE_IMAGE)(IN PVOID ImagePointer, IN EFI_VIRTUAL_ADDRESS Address);
|
||||
typedef EFI_STATUS (*PBL_EXIT_BOOT_SERVICES)(IN UINT_PTR MapKey);
|
||||
typedef EFI_STATUS (*PBL_FIND_BOOT_PROTOCOL)(IN PWCHAR SystemType, OUT PEFI_GUID BootProtocolGuid);
|
||||
typedef EFI_STATUS (*PBL_FREE_PAGES)(IN UINT64 Size, IN EFI_PHYSICAL_ADDRESS Memory);
|
||||
@ -84,26 +89,6 @@ typedef VOID (*PBL_TUI_UPDATE_PROGRESS_BAR)(IN PXTBL_DIALOG_HANDLE Handle, IN PW
|
||||
typedef EFI_STATUS (*PBL_WAIT_FOR_EFI_EVENT)(IN UINT_PTR NumberOfEvents, IN PEFI_EVENT Event, OUT PUINT_PTR Index);
|
||||
typedef VOID (*PBL_XT_BOOT_MENU)();
|
||||
|
||||
/* XTLDR Boot protocol structure */
|
||||
typedef struct _XTBL_BOOT_PROTOCOL
|
||||
{
|
||||
PBL_BOOTPROTO_BOOT_SYSTEM BootSystem;
|
||||
} XTBL_BOOT_PROTOCOL, *PXTBL_BOOT_PROTOCOL;
|
||||
|
||||
/* XTLDR Executable image protocol structure */
|
||||
typedef struct _XTBL_EXECUTABLE_IMAGE_PROTOCOL
|
||||
{
|
||||
// PBL_EXECIMAGE_GET_ENTRY_POINT GetEntryPoint;
|
||||
// PBL_EXECIMAGE_GET_MACHINE_TYPE GetMachineType;
|
||||
// PBL_EXECIMAGE_GET_SECTION GetSection;
|
||||
// PBL_EXECIMAGE_GET_SUBSYSTEM GetSubSystem;
|
||||
// PBL_EXECIMAGE_GET_VERSION GetVersion;
|
||||
// PBL_EXECIMAGE_LOAD_IMAGE LoadImage;
|
||||
// PBL_EXECIMAGE_PRINT_INFO PrintDebugInfo;
|
||||
// PBL_EXECIMAGE_RELOCATE_IMAGE RelocateImage;
|
||||
// PBL_EXECUTABLE_VERIFY_IMAGE VerifyImage;
|
||||
} XTBL_EXECUTABLE_IMAGE_PROTOCOL, *PXTBL_EXECUTABLE_IMAGE_PROTOCOL;
|
||||
|
||||
/* Boot parameters structure */
|
||||
typedef struct _XTBL_BOOT_PARAMETERS
|
||||
{
|
||||
@ -162,6 +147,52 @@ typedef struct _XTBL_KNOWN_BOOT_PROTOCOL
|
||||
EFI_GUID Guid;
|
||||
} XTBL_KNOWN_BOOT_PROTOCOL, *PXTBL_KNOWN_BOOT_PROTOCOL;
|
||||
|
||||
/* XTLDR Module dependencies data */
|
||||
typedef struct _XTBL_MODULE_DEPS
|
||||
{
|
||||
LIST_ENTRY Flink;
|
||||
PWCHAR ModuleName;
|
||||
} XTBL_MODULE_DEPS, *PXTBL_MODULE_DEPS;
|
||||
|
||||
/* XTLDR Module information data */
|
||||
typedef struct _XTBL_MODULE_INFO
|
||||
{
|
||||
LIST_ENTRY Flink;
|
||||
PWCHAR ModuleName;
|
||||
PWCHAR ModuleDescription;
|
||||
LIST_ENTRY Dependencies;
|
||||
} XTBL_MODULE_INFO, *PXTBL_MODULE_INFO;
|
||||
|
||||
/* XTLDR Status data */
|
||||
typedef struct _XTBL_STATUS
|
||||
{
|
||||
PBL_XT_BOOT_MENU BootMenu;
|
||||
BOOLEAN BootServices;
|
||||
ULONG DebugPort;
|
||||
INT_PTR SecureBoot;
|
||||
CPPORT SerialPort;
|
||||
} XTBL_STATUS, *PXTBL_STATUS;
|
||||
|
||||
/* XTLDR Boot protocol structure */
|
||||
typedef struct _XTBL_BOOT_PROTOCOL
|
||||
{
|
||||
PBL_BOOTPROTO_BOOT_SYSTEM BootSystem;
|
||||
} XTBL_BOOT_PROTOCOL, *PXTBL_BOOT_PROTOCOL;
|
||||
|
||||
/* XTLDR Executable image protocol structure */
|
||||
typedef struct _XTBL_EXECUTABLE_IMAGE_PROTOCOL
|
||||
{
|
||||
PBL_EXECIMAGE_GET_ENTRY_POINT GetEntryPoint;
|
||||
PBL_EXECIMAGE_GET_MACHINE_TYPE GetMachineType;
|
||||
// PBL_EXECIMAGE_GET_SECTION GetSection;
|
||||
PBL_EXECIMAGE_GET_SUBSYSTEM GetSubSystem;
|
||||
// PBL_EXECIMAGE_GET_VERSION GetVersion;
|
||||
PBL_EXECIMAGE_LOAD_IMAGE LoadImage;
|
||||
// PBL_EXECIMAGE_PRINT_INFO PrintDebugInfo;
|
||||
PBL_EXECIMAGE_RELOCATE_IMAGE RelocateImage;
|
||||
// PBL_EXECUTABLE_VERIFY_IMAGE VerifyImage;
|
||||
} XTBL_EXECUTABLE_IMAGE_PROTOCOL, *PXTBL_EXECUTABLE_IMAGE_PROTOCOL;
|
||||
|
||||
/* XTLDR Loader protocol */
|
||||
typedef struct _XTBL_LOADER_PROTOCOL
|
||||
{
|
||||
@ -225,30 +256,4 @@ typedef struct _XTBL_LOADER_PROTOCOL
|
||||
} Util;
|
||||
} XTBL_LOADER_PROTOCOL, *PXTBL_LOADER_PROTOCOL;
|
||||
|
||||
/* XTLDR Module dependencies data */
|
||||
typedef struct _XTBL_MODULE_DEPS
|
||||
{
|
||||
LIST_ENTRY Flink;
|
||||
PWCHAR ModuleName;
|
||||
} XTBL_MODULE_DEPS, *PXTBL_MODULE_DEPS;
|
||||
|
||||
/* XTLDR Module information data */
|
||||
typedef struct _XTBL_MODULE_INFO
|
||||
{
|
||||
LIST_ENTRY Flink;
|
||||
PWCHAR ModuleName;
|
||||
PWCHAR ModuleDescription;
|
||||
LIST_ENTRY Dependencies;
|
||||
} XTBL_MODULE_INFO, *PXTBL_MODULE_INFO;
|
||||
|
||||
/* XTLDR Status data */
|
||||
typedef struct _XTBL_STATUS
|
||||
{
|
||||
PBL_XT_BOOT_MENU BootMenu;
|
||||
BOOLEAN BootServices;
|
||||
ULONG DebugPort;
|
||||
INT_PTR SecureBoot;
|
||||
CPPORT SerialPort;
|
||||
} XTBL_STATUS, *PXTBL_STATUS;
|
||||
|
||||
#endif /* __XTDK_BLTYPES_H */
|
||||
|
@ -1 +1,2 @@
|
||||
add_subdirectory(dummy)
|
||||
add_subdirectory(pecoff_o)
|
||||
|
27
xtldr2/modules/pecoff_o/CMakeLists.txt
Normal file
27
xtldr2/modules/pecoff_o/CMakeLists.txt
Normal file
@ -0,0 +1,27 @@
|
||||
# XT Boot Loader
|
||||
PROJECT(XTLDR_PECOFF_O)
|
||||
|
||||
# Specify include directories
|
||||
include_directories(
|
||||
${EXECTOS_SOURCE_DIR}/sdk/xtdk
|
||||
${XTLDR_SOURCE_DIR}/includes
|
||||
${XTLDR_PECOFF_SOURCE_DIR}/includes)
|
||||
|
||||
# Specify list of source code files
|
||||
list(APPEND XTLDR_PECOFF_O_SOURCE
|
||||
${XTLDR_PECOFF_O_SOURCE_DIR}/pecoff.c)
|
||||
|
||||
# Link bootloader executable
|
||||
add_executable(pecoff_o ${XTLDR_PECOFF_O_SOURCE})
|
||||
|
||||
# Add linker libraries
|
||||
target_link_libraries(pecoff_o libxtos libxtldr)
|
||||
|
||||
# Set proper binary name and install target
|
||||
set_target_properties(pecoff_o PROPERTIES SUFFIX .efi)
|
||||
set_install_target(pecoff_o efi/boot/xtldr)
|
||||
|
||||
# Set module entrypoint and subsystem
|
||||
set_entrypoint(pecoff_o "XtLdrModuleMain")
|
||||
set_linker_map(pecoff_o TRUE)
|
||||
set_subsystem(pecoff_o efi_boot_service_driver)
|
58
xtldr2/modules/pecoff_o/includes/pecoff.h
Normal file
58
xtldr2/modules/pecoff_o/includes/pecoff.h
Normal file
@ -0,0 +1,58 @@
|
||||
/**
|
||||
* PROJECT: ExectOS
|
||||
* COPYRIGHT: See COPYING.md in the top level directory
|
||||
* FILE: xtldr/modules/pecoff_o/includes/pecoff.h
|
||||
* DESCRIPTION: PE/COFF executable file format support header
|
||||
* DEVELOPERS: Rafal Kupiec <belliash@codingworkshop.eu.org>
|
||||
*/
|
||||
|
||||
#ifndef __XTLDR_MODULES_PECOFF_O_H
|
||||
#define __XTLDR_MODULES_PECOFF_O_H
|
||||
|
||||
#include <xtblapi.h>
|
||||
|
||||
|
||||
/* PE/COFF image protocol related routines forward references */
|
||||
XTCDECL
|
||||
EFI_STATUS
|
||||
PeGetEntryPoint(IN PVOID ImagePointer,
|
||||
OUT PVOID *EntryPoint);
|
||||
|
||||
XTCDECL
|
||||
EFI_STATUS
|
||||
PeGetMachineType(IN PVOID ImagePointer,
|
||||
OUT PUSHORT MachineType);
|
||||
|
||||
XTCDECL
|
||||
EFI_STATUS
|
||||
PeGetSubSystem(IN PVOID ImagePointer,
|
||||
OUT PUSHORT SubSystem);
|
||||
|
||||
XTCDECL
|
||||
EFI_STATUS
|
||||
PeLoadImage(IN PEFI_FILE_HANDLE FileHandle,
|
||||
IN LOADER_MEMORY_TYPE MemoryType,
|
||||
IN PVOID VirtualAddress,
|
||||
OUT PVOID *ImagePointer);
|
||||
|
||||
XTCDECL
|
||||
EFI_STATUS
|
||||
PeRelocateImage(IN PVOID ImagePointer,
|
||||
IN EFI_VIRTUAL_ADDRESS Address);
|
||||
|
||||
XTCDECL
|
||||
EFI_STATUS
|
||||
PepRelocateLoadedImage(IN PPECOFF_IMAGE_CONTEXT Image);
|
||||
|
||||
XTCDECL
|
||||
EFI_STATUS
|
||||
PepValidateImageHeaders(IN PPECOFF_IMAGE_DOS_HEADER DosHeader,
|
||||
IN PPECOFF_IMAGE_PE_HEADER PeHeader,
|
||||
IN SIZE_T FileSize);
|
||||
|
||||
XTCDECL
|
||||
EFI_STATUS
|
||||
BlXtLdrModuleMain(IN EFI_HANDLE ImageHandle,
|
||||
IN PEFI_SYSTEM_TABLE SystemTable);
|
||||
|
||||
#endif /* __XTLDR_MODULES_PECOFF_O_H */
|
607
xtldr2/modules/pecoff_o/pecoff.c
Normal file
607
xtldr2/modules/pecoff_o/pecoff.c
Normal file
@ -0,0 +1,607 @@
|
||||
/**
|
||||
* PROJECT: ExectOS
|
||||
* COPYRIGHT: See COPYING.md in the top level directory
|
||||
* FILE: xtldr/modules/pecoff_o/pecoff.c
|
||||
* DESCRIPTION: OLD and deprecated PE/COFF executable file format support module
|
||||
* DEVELOPERS: Rafal Kupiec <belliash@codingworkshop.eu.org>
|
||||
*/
|
||||
|
||||
#include <pecoff.h>
|
||||
|
||||
|
||||
/* PE/COFF_O module information */
|
||||
XTBL_MODINFO = L"PE/COFF executable file format support";
|
||||
|
||||
/* EFI XT Loader Protocol */
|
||||
PXTBL_LOADER_PROTOCOL XtLdrProtocol;
|
||||
|
||||
/* XTOS PE/COFF Image Protocol */
|
||||
XTBL_EXECUTABLE_IMAGE_PROTOCOL XtPeCoffProtocol;
|
||||
|
||||
/**
|
||||
* Returns the address of the entry point.
|
||||
*
|
||||
* @param Image
|
||||
* A pointer to the PE/COFF context structure representing the loaded image.
|
||||
*
|
||||
* @param EntryPoint
|
||||
* A pointer to the memory area where address of the image entry point will be stored.
|
||||
*
|
||||
* @return This routine returns a status code.
|
||||
*
|
||||
* @since XT 1.0
|
||||
*/
|
||||
XTCDECL
|
||||
EFI_STATUS
|
||||
PeGetEntryPoint(IN PVOID ImagePointer,
|
||||
OUT PVOID *EntryPoint)
|
||||
{
|
||||
PPECOFF_IMAGE_CONTEXT Image = ImagePointer;
|
||||
|
||||
/* Validate input data */
|
||||
if(!Image || !Image->PeHeader)
|
||||
{
|
||||
/* Invalid parameter passed */
|
||||
return STATUS_EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
/* Get entry point and return success */
|
||||
*EntryPoint = (PUINT8)Image->VirtualAddress + Image->PeHeader->OptionalHeader.AddressOfEntryPoint;
|
||||
return STATUS_EFI_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the machine type of the PE/COFF image.
|
||||
*
|
||||
* @param Image
|
||||
* A pointer to the PE/COFF context structure representing the loaded image.
|
||||
*
|
||||
* @param MachineType
|
||||
* A pointer to the memory area where a value defined for the 'machine' field will be stored.
|
||||
*
|
||||
* @return This routine returns a status code.
|
||||
*
|
||||
* @since XT 1.0
|
||||
*/
|
||||
XTCDECL
|
||||
EFI_STATUS
|
||||
PeGetMachineType(IN PVOID ImagePointer,
|
||||
OUT PUSHORT MachineType)
|
||||
{
|
||||
PPECOFF_IMAGE_CONTEXT Image = ImagePointer;
|
||||
|
||||
/* Validate input data */
|
||||
if(!Image || !Image->PeHeader)
|
||||
{
|
||||
/* Invalid parameter passed */
|
||||
return STATUS_EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
/* Get image machine type and return success */
|
||||
*MachineType = Image->PeHeader->FileHeader.Machine;
|
||||
return STATUS_EFI_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an information about subsystem that is required to run PE/COFF image.
|
||||
*
|
||||
* @param Image
|
||||
* A pointer to the PE/COFF context structure representing the loaded image.
|
||||
*
|
||||
* @param SubSystem
|
||||
* A pointer to the memory area storing a value defined for the 'subsystem' field of the image.
|
||||
*
|
||||
* @return This routine returns a status code.
|
||||
*
|
||||
* @since XT 1.0
|
||||
*/
|
||||
XTCDECL
|
||||
EFI_STATUS
|
||||
PeGetSubSystem(IN PVOID ImagePointer,
|
||||
OUT PUSHORT SubSystem)
|
||||
{
|
||||
PPECOFF_IMAGE_CONTEXT Image = ImagePointer;
|
||||
|
||||
/* Validate input data */
|
||||
if(!Image || !Image->PeHeader)
|
||||
{
|
||||
/* Invalid parameter passed */
|
||||
return STATUS_EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
/* Get image subsystem and return success */
|
||||
*SubSystem = Image->PeHeader->OptionalHeader.Subsystem;
|
||||
return STATUS_EFI_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads a PE/COFF image file.
|
||||
*
|
||||
* @param FileHandle
|
||||
* The handle of the opened portable executable (PE) file.
|
||||
*
|
||||
* @param MemoryType
|
||||
* Supplies the type of memory to be assigned to the memory descriptor.
|
||||
*
|
||||
* @param VirtualAddress
|
||||
* Optional virtual address pointing to the memory area where PE/COFF file will be loaded.
|
||||
*
|
||||
* @param Image
|
||||
* Supplies pointer to the memory area where loaded PE/COFF image context will be stored.
|
||||
*
|
||||
* @return This routine returns status code.
|
||||
*
|
||||
* @since XT 1.0
|
||||
*/
|
||||
XTCDECL
|
||||
EFI_STATUS
|
||||
PeLoadImage(IN PEFI_FILE_HANDLE FileHandle,
|
||||
IN LOADER_MEMORY_TYPE MemoryType,
|
||||
IN PVOID VirtualAddress,
|
||||
OUT PVOID *ImagePointer)
|
||||
{
|
||||
EFI_GUID FileInfoGuid = EFI_FILE_INFO_PROTOCOL_GUID;
|
||||
PPECOFF_IMAGE_SECTION_HEADER SectionHeader;
|
||||
PPECOFF_IMAGE_CONTEXT ImageData;
|
||||
EFI_PHYSICAL_ADDRESS Address;
|
||||
PEFI_FILE_INFO FileInfo;
|
||||
UINT_PTR ReadSize;
|
||||
EFI_STATUS Status;
|
||||
UINT SectionSize;
|
||||
SIZE_T Pages;
|
||||
PUCHAR Data;
|
||||
UINT Index;
|
||||
|
||||
/* Set required size for getting file information */
|
||||
ReadSize = sizeof(EFI_FILE_INFO) + 32;
|
||||
|
||||
/* Allocate necessary amount of memory */
|
||||
Status = XtLdrProtocol->Memory.AllocatePool(ReadSize, (PVOID *)&FileInfo);
|
||||
if(Status != STATUS_EFI_SUCCESS)
|
||||
{
|
||||
/* Memory allocation failure */
|
||||
XtLdrProtocol->Debug.Print(L"ERROR: Memory pool allocation failure\n");
|
||||
return Status;
|
||||
}
|
||||
|
||||
/* First attempt to get file information */
|
||||
Status = FileHandle->GetInfo(FileHandle, &FileInfoGuid, &ReadSize, FileInfo);
|
||||
if(Status == STATUS_EFI_BUFFER_TOO_SMALL)
|
||||
{
|
||||
/* Buffer it too small, but EFI tells the required size, let's reallocate */
|
||||
XtLdrProtocol->Memory.FreePool(&FileInfo);
|
||||
Status = XtLdrProtocol->Memory.AllocatePool(ReadSize, (PVOID *)&FileInfo);
|
||||
if(Status != STATUS_EFI_SUCCESS)
|
||||
{
|
||||
/* Memory allocation failure */
|
||||
XtLdrProtocol->Debug.Print(L"ERROR: Memory pool allocation failure\n");
|
||||
return Status;
|
||||
}
|
||||
|
||||
/* Second attempt to get file information */
|
||||
Status = FileHandle->GetInfo(FileHandle, &FileInfoGuid, &ReadSize, FileInfo);
|
||||
}
|
||||
if(Status != STATUS_EFI_SUCCESS)
|
||||
{
|
||||
/* Unable to get file information */
|
||||
XtLdrProtocol->Debug.Print(L"ERROR: Failed to get file information\n");
|
||||
return Status;
|
||||
}
|
||||
|
||||
/* Allocate memory for storing image data */
|
||||
Status = XtLdrProtocol->Memory.AllocatePool(sizeof(PECOFF_IMAGE_CONTEXT), (PVOID *)&ImageData);
|
||||
if(Status != STATUS_EFI_SUCCESS)
|
||||
{
|
||||
/* Memory allocation failure */
|
||||
XtLdrProtocol->Debug.Print(L"ERROR: Memory pool allocation failure\n");
|
||||
return Status;
|
||||
}
|
||||
|
||||
/* Store file size and memory type, nullify data and free up memory */
|
||||
ImageData->Data = NULL;
|
||||
ImageData->FileSize = FileInfo->FileSize;
|
||||
ImageData->MemoryType = MemoryType;
|
||||
XtLdrProtocol->Memory.FreePool(FileInfo);
|
||||
|
||||
/* Calculate number of pages */
|
||||
Pages = EFI_SIZE_TO_PAGES(ImageData->FileSize);
|
||||
|
||||
/* Allocate pages */
|
||||
Status = XtLdrProtocol->Memory.AllocatePages(Pages, &Address);
|
||||
if(Status != STATUS_EFI_SUCCESS)
|
||||
{
|
||||
/* Pages allocation failure */
|
||||
XtLdrProtocol->Debug.Print(L"ERROR: Pages allocation failure\n");
|
||||
XtLdrProtocol->Memory.FreePool(ImageData);
|
||||
return Status;
|
||||
}
|
||||
|
||||
/* Read PE/COFF image */
|
||||
ReadSize = Pages * EFI_PAGE_SIZE;
|
||||
Data = (PUCHAR)(UINT_PTR)Address;
|
||||
Status = FileHandle->Read(FileHandle, &ReadSize, Data);
|
||||
if(Status != STATUS_EFI_SUCCESS)
|
||||
{
|
||||
/* Failed to read data */
|
||||
XtLdrProtocol->Debug.Print(L"ERROR: Unable to read PE/COFF image file\n");
|
||||
XtLdrProtocol->Memory.FreePages(Pages, (EFI_PHYSICAL_ADDRESS)(UINT_PTR)Data);
|
||||
XtLdrProtocol->Memory.FreePool(ImageData);
|
||||
return Status;
|
||||
}
|
||||
|
||||
/* Extract DOS and PE headers */
|
||||
ImageData->DosHeader = (PPECOFF_IMAGE_DOS_HEADER)Data;
|
||||
ImageData->PeHeader = (PPECOFF_IMAGE_PE_HEADER)((PUINT8)Data + ImageData->DosHeader->e_lfanew);
|
||||
|
||||
/* Validate headers */
|
||||
Status = PepValidateImageHeaders(ImageData->DosHeader, ImageData->PeHeader, ImageData->FileSize);
|
||||
if(Status != STATUS_EFI_SUCCESS)
|
||||
{
|
||||
/* Header validation failed, probably broken or invalid PE/COFF image */
|
||||
XtLdrProtocol->Debug.Print(L"ERROR: Invalid PE/COFF image headers\n");
|
||||
XtLdrProtocol->Memory.FreePages(Pages, (EFI_PHYSICAL_ADDRESS)(UINT_PTR)Data);
|
||||
XtLdrProtocol->Memory.FreePool(ImageData);
|
||||
return Status;
|
||||
}
|
||||
|
||||
/* Make sure image is executable */
|
||||
if (!(ImageData->PeHeader->FileHeader.Characteristics & PECOFF_IMAGE_FILE_EXECUTABLE_IMAGE))
|
||||
{
|
||||
/* Loaded image is not executable */
|
||||
XtLdrProtocol->Debug.Print(L"ERROR: Non-executable PE/COFF image loaded\n");
|
||||
XtLdrProtocol->Memory.FreePages(Pages, (EFI_PHYSICAL_ADDRESS)(UINT_PTR)Data);
|
||||
XtLdrProtocol->Memory.FreePool(ImageData);
|
||||
return STATUS_EFI_LOAD_ERROR;
|
||||
}
|
||||
|
||||
/* Store image size and calculate number of image pages */
|
||||
ImageData->ImageSize = ImageData->PeHeader->OptionalHeader.SizeOfImage;
|
||||
ImageData->ImagePages = EFI_SIZE_TO_PAGES(ImageData->ImageSize);
|
||||
|
||||
/* Allocate image pages */
|
||||
Status = XtLdrProtocol->Memory.AllocatePages(ImageData->ImagePages, &Address);
|
||||
if(Status != STATUS_EFI_SUCCESS)
|
||||
{
|
||||
/* Pages reallocation failure */
|
||||
XtLdrProtocol->Debug.Print(L"ERROR: Pages reallocation failure\n");
|
||||
XtLdrProtocol->Memory.FreePool(ImageData);
|
||||
return Status;
|
||||
}
|
||||
|
||||
/* Store image data and virtual address */
|
||||
ImageData->Data = (PUINT8)(UINT_PTR)Address;
|
||||
ImageData->PhysicalAddress = (PVOID)(UINT_PTR)Address;
|
||||
if(VirtualAddress)
|
||||
{
|
||||
/* Virtual address passed to this routine */
|
||||
ImageData->VirtualAddress = VirtualAddress;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Virtual address not specified, use physical address */
|
||||
ImageData->VirtualAddress = (PVOID)(UINT_PTR)Address;
|
||||
}
|
||||
|
||||
/* Copy all sections */
|
||||
RtlCopyMemory(ImageData->Data, Data, ImageData->PeHeader->OptionalHeader.SizeOfHeaders);
|
||||
|
||||
/* Find section header */
|
||||
SectionHeader = (PPECOFF_IMAGE_SECTION_HEADER)((PUCHAR)&ImageData->PeHeader->OptionalHeader +
|
||||
ImageData->PeHeader->FileHeader.SizeOfOptionalHeader);
|
||||
|
||||
/* Load each section into memory */
|
||||
for(Index = 0; Index < ImageData->PeHeader->FileHeader.NumberOfSections; Index++)
|
||||
{
|
||||
/* Check section raw data size and section virtual size */
|
||||
if(SectionHeader[Index].SizeOfRawData < SectionHeader[Index].Misc.VirtualSize)
|
||||
{
|
||||
/* Use raw data size if it is smaller than virtual size */
|
||||
SectionSize = SectionHeader[Index].SizeOfRawData;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* User virtual size otherwise */
|
||||
SectionSize = SectionHeader[Index].Misc.VirtualSize;
|
||||
}
|
||||
|
||||
/* Make sure section is available */
|
||||
if(SectionSize > 0 && SectionHeader[Index].PointerToRawData != 0)
|
||||
{
|
||||
/* Copy section */
|
||||
RtlCopyMemory((PUINT8)ImageData->Data + SectionHeader[Index].VirtualAddress,
|
||||
Data + SectionHeader[Index].PointerToRawData, SectionSize);
|
||||
}
|
||||
|
||||
/* Check if raw size is shorter than virtual size */
|
||||
if(SectionSize < SectionHeader[Index].Misc.VirtualSize)
|
||||
{
|
||||
/* Fill remaining space with zeroes */
|
||||
RtlZeroMemory((PUINT8)ImageData->Data + SectionHeader[Index].VirtualAddress + SectionSize,
|
||||
SectionHeader[Index].Misc.VirtualSize - SectionSize);
|
||||
}
|
||||
}
|
||||
|
||||
/* Free pages */
|
||||
XtLdrProtocol->Memory.FreePages((EFI_PHYSICAL_ADDRESS)(UINT_PTR)Data, Pages);
|
||||
|
||||
/* Perform relocation fixups */
|
||||
Status = PepRelocateLoadedImage(ImageData);
|
||||
if(Status != STATUS_EFI_SUCCESS)
|
||||
{
|
||||
/* Failed to relocate image */
|
||||
XtLdrProtocol->Debug.Print(L"ERROR: PE/COFF image relocation failed\n");
|
||||
return Status;
|
||||
}
|
||||
|
||||
/* Store image data */
|
||||
*ImagePointer = ImageData;
|
||||
|
||||
/* Return SUCCESS */
|
||||
return STATUS_EFI_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* Relocates PE/COFF image to the specified address.
|
||||
*
|
||||
* @param Image
|
||||
* A pointer to the PE/COFF context structure representing the loaded image.
|
||||
*
|
||||
* @param Address
|
||||
* Destination address of memory region, where image should be relocated.
|
||||
*
|
||||
* @return This routine returns status code.
|
||||
*
|
||||
* @since XT 1.0
|
||||
*/
|
||||
XTCDECL
|
||||
EFI_STATUS
|
||||
PeRelocateImage(IN PVOID ImagePointer,
|
||||
IN EFI_VIRTUAL_ADDRESS Address)
|
||||
{
|
||||
PPECOFF_IMAGE_CONTEXT Image = ImagePointer;
|
||||
|
||||
UINT64 ImageBase, OldVirtualAddress;
|
||||
EFI_STATUS Status;
|
||||
|
||||
/* Store original virtual address */
|
||||
OldVirtualAddress = (UINT_PTR)Image->VirtualAddress;
|
||||
|
||||
/* Check PE/COFF image type */
|
||||
if(Image->PeHeader->OptionalHeader.Magic == PECOFF_IMAGE_PE_OPTIONAL_HDR64_MAGIC)
|
||||
{
|
||||
/* This is 64-bit PE32+, store its image base address */
|
||||
ImageBase = Image->PeHeader->OptionalHeader.ImageBase64;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* This is 32-bit PE32, store its image base address */
|
||||
ImageBase = Image->PeHeader->OptionalHeader.ImageBase32;
|
||||
}
|
||||
|
||||
/* Overwrite virtual address and relocate image once again */
|
||||
Image->VirtualAddress = (PVOID)(Address - OldVirtualAddress + ImageBase);
|
||||
Status = PepRelocateLoadedImage(Image);
|
||||
if(Status != STATUS_EFI_SUCCESS)
|
||||
{
|
||||
/* Relocation failed */
|
||||
return Status;
|
||||
}
|
||||
|
||||
/* Store new image virtual address */
|
||||
Image->VirtualAddress = (PVOID)Address;
|
||||
|
||||
/* Return success */
|
||||
return STATUS_EFI_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* Relocates a loaded PE/COFF image.
|
||||
*
|
||||
* @param Image
|
||||
* A pointer to the PE/COFF context structure representing the loaded image.
|
||||
*
|
||||
* @return This routine returns a status code.
|
||||
*
|
||||
* @since XT 1.0
|
||||
*/
|
||||
XTCDECL
|
||||
EFI_STATUS
|
||||
PepRelocateLoadedImage(IN PPECOFF_IMAGE_CONTEXT Image)
|
||||
{
|
||||
PPECOFF_IMAGE_BASE_RELOCATION RelocationDir, RelocationEnd;
|
||||
PPECOFF_IMAGE_DATA_DIRECTORY DataDirectory;
|
||||
USHORT Offset, Type, Count;
|
||||
PUSHORT TypeOffset;
|
||||
UINT64 ImageBase;
|
||||
PUINT32 Address;
|
||||
PUINT64 LongPtr;
|
||||
PUINT ShortPtr;
|
||||
|
||||
/* Make sure image is not stripped */
|
||||
if(Image->PeHeader->FileHeader.Characteristics & PECOFF_IMAGE_FILE_RELOCS_STRIPPED)
|
||||
{
|
||||
/* No relocation information found */
|
||||
XtLdrProtocol->Debug.Print(L"WARNING: PE/COFF image is stripped and contains no information about relocations\n");
|
||||
return STATUS_EFI_SUCCESS;
|
||||
}
|
||||
|
||||
/* Set relocation data directory */
|
||||
DataDirectory = &Image->PeHeader->OptionalHeader.DataDirectory[PECOFF_IMAGE_DIRECTORY_ENTRY_BASERELOC];
|
||||
|
||||
/* Check if loaded image should be relocated */
|
||||
if(Image->PeHeader->OptionalHeader.NumberOfRvaAndSizes <= PECOFF_IMAGE_DIRECTORY_ENTRY_BASERELOC ||
|
||||
DataDirectory->VirtualAddress == 0 || DataDirectory->Size < sizeof(PECOFF_IMAGE_BASE_RELOCATION))
|
||||
{
|
||||
/* No need to relocate the image */
|
||||
return STATUS_EFI_SUCCESS;
|
||||
}
|
||||
|
||||
/* Check PE/COFF image type */
|
||||
if(Image->PeHeader->OptionalHeader.Magic == PECOFF_IMAGE_PE_OPTIONAL_HDR64_MAGIC)
|
||||
{
|
||||
/* This is 64-bit PE32+, store its image base address */
|
||||
ImageBase = Image->PeHeader->OptionalHeader.ImageBase64;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* This is 32-bit PE32, store its image base address */
|
||||
ImageBase = Image->PeHeader->OptionalHeader.ImageBase32;
|
||||
}
|
||||
|
||||
/* Set relocation pointers */
|
||||
RelocationDir = (PPECOFF_IMAGE_BASE_RELOCATION)((ULONG_PTR)Image->Data + DataDirectory->VirtualAddress);
|
||||
RelocationEnd = (PPECOFF_IMAGE_BASE_RELOCATION)((ULONG_PTR)RelocationDir + DataDirectory->Size);
|
||||
|
||||
/* Do relocations */
|
||||
while(RelocationDir < RelocationEnd && RelocationDir->SizeOfBlock > 0)
|
||||
{
|
||||
/* Calculate number of relocations needed, address and type offset */
|
||||
Count = (RelocationDir->SizeOfBlock - sizeof(PECOFF_IMAGE_BASE_RELOCATION)) / sizeof(USHORT);
|
||||
Address = (PUINT)((PUCHAR)Image->Data + RelocationDir->VirtualAddress);
|
||||
TypeOffset = (PUSHORT)((PUCHAR)RelocationDir + sizeof(PECOFF_IMAGE_BASE_RELOCATION));
|
||||
|
||||
/* Do relocations */
|
||||
while(Count--)
|
||||
{
|
||||
/* Calculate offset and relocation type */
|
||||
Offset = *TypeOffset & 0xFFF;
|
||||
Type = *TypeOffset >> 12;
|
||||
|
||||
/* Check if end of the loaded address reached */
|
||||
if((PVOID)(PUSHORT)(Address + Offset) >= Image->Data + Image->ImageSize)
|
||||
{
|
||||
/* Do not relocate after the end of loaded image */
|
||||
break;
|
||||
}
|
||||
|
||||
/* Make sure we are not going to relocate into .reloc section */
|
||||
if((ULONG_PTR)(Address + Offset) < (ULONG_PTR)RelocationDir ||
|
||||
(ULONG_PTR)(Address + Offset) >= (ULONG_PTR)RelocationEnd)
|
||||
{
|
||||
/* Apply relocation fixup */
|
||||
switch (Type)
|
||||
{
|
||||
case PECOFF_IMAGE_REL_BASED_ABSOLUTE:
|
||||
/* No relocation required */
|
||||
break;
|
||||
case PECOFF_IMAGE_REL_BASED_DIR64:
|
||||
/* 64-bit relocation */
|
||||
LongPtr = (PULONGLONG)((PUCHAR)Address + Offset);
|
||||
*LongPtr = *LongPtr - ImageBase + (UINT_PTR)Image->VirtualAddress;
|
||||
break;
|
||||
case PECOFF_IMAGE_REL_BASED_HIGHLOW:
|
||||
/* 32-bit relocation of hight and low half of address */
|
||||
ShortPtr = (PUINT32)((PUCHAR)Address + Offset);
|
||||
*ShortPtr = *ShortPtr - ImageBase + (UINT_PTR)Image->VirtualAddress;
|
||||
break;
|
||||
default:
|
||||
/* Unknown or unsupported relocation type */
|
||||
return STATUS_EFI_UNSUPPORTED;
|
||||
}
|
||||
}
|
||||
/* Increment the type offset */
|
||||
TypeOffset++;
|
||||
}
|
||||
|
||||
/* Next relocation */
|
||||
RelocationDir = (PPECOFF_IMAGE_BASE_RELOCATION)((PUCHAR)RelocationDir + RelocationDir->SizeOfBlock);
|
||||
}
|
||||
|
||||
/* Return SUCCESS */
|
||||
return STATUS_EFI_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates a PE/COFF image headers.
|
||||
*
|
||||
* @param DosHeader
|
||||
* Pointer to the memory area with DOS header stored.
|
||||
*
|
||||
* @param PeHeader
|
||||
* Pointer to the memory area with PE header stored.
|
||||
*
|
||||
* @param FileSize
|
||||
* A PE/COFF image file size.
|
||||
*
|
||||
* @return This routine returns a status code.
|
||||
*
|
||||
* @since XT 1.0
|
||||
*/
|
||||
XTCDECL
|
||||
EFI_STATUS
|
||||
PepValidateImageHeaders(IN PPECOFF_IMAGE_DOS_HEADER DosHeader,
|
||||
IN PPECOFF_IMAGE_PE_HEADER PeHeader,
|
||||
IN SIZE_T FileSize)
|
||||
{
|
||||
/* Validate file size */
|
||||
if(FileSize < sizeof(PECOFF_IMAGE_DOS_HEADER))
|
||||
{
|
||||
XtLdrProtocol->Debug.Print(L"WARNING: PE/COFF image shorter than DOS header\n");
|
||||
return STATUS_EFI_END_OF_FILE;
|
||||
}
|
||||
|
||||
/* Validate DOS header */
|
||||
if(DosHeader->e_magic != PECOFF_IMAGE_DOS_SIGNATURE)
|
||||
{
|
||||
XtLdrProtocol->Debug.Print(L"WARNING: Invalid DOS signature found\n");
|
||||
return STATUS_EFI_INCOMPATIBLE_VERSION;
|
||||
}
|
||||
|
||||
/* Validate PE header */
|
||||
if(PeHeader->Signature != PECOFF_IMAGE_NT_SIGNATURE && PeHeader->Signature != PECOFF_IMAGE_XT_SIGNATURE)
|
||||
{
|
||||
XtLdrProtocol->Debug.Print(L"WARNING: Invalid NT/XT signature found\n");
|
||||
return STATUS_EFI_INCOMPATIBLE_VERSION;
|
||||
}
|
||||
|
||||
/* Validate optional header */
|
||||
if(PeHeader->OptionalHeader.Magic != PECOFF_IMAGE_PE_OPTIONAL_HDR32_MAGIC &&
|
||||
PeHeader->OptionalHeader.Magic != PECOFF_IMAGE_PE_OPTIONAL_HDR64_MAGIC)
|
||||
{
|
||||
XtLdrProtocol->Debug.Print(L"WARNING: Invalid optional header signature found\n");
|
||||
return STATUS_EFI_INCOMPATIBLE_VERSION;
|
||||
}
|
||||
|
||||
/* Return success */
|
||||
return STATUS_EFI_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* This routine is the entry point of the XT EFI boot loader module.
|
||||
*
|
||||
* @param ImageHandle
|
||||
* Firmware-allocated handle that identifies the image.
|
||||
*
|
||||
* @param SystemTable
|
||||
* Provides the EFI system table.
|
||||
*
|
||||
* @return This routine returns status code.
|
||||
*
|
||||
* @since XT 1.0
|
||||
*/
|
||||
XTCDECL
|
||||
EFI_STATUS
|
||||
XtLdrModuleMain(IN EFI_HANDLE ImageHandle,
|
||||
IN PEFI_SYSTEM_TABLE SystemTable)
|
||||
{
|
||||
EFI_GUID Guid = XT_PECOFF_IMAGE_PROTOCOL_GUID;
|
||||
EFI_STATUS Status;
|
||||
|
||||
/* Open the XTLDR protocol */
|
||||
Status = BlGetXtLdrProtocol(SystemTable, ImageHandle, &XtLdrProtocol);
|
||||
if(Status != STATUS_EFI_SUCCESS)
|
||||
{
|
||||
/* Failed to open loader protocol */
|
||||
return STATUS_EFI_PROTOCOL_ERROR;
|
||||
}
|
||||
|
||||
/* Set routines available via PE/COFF image protocol */
|
||||
XtPeCoffProtocol.GetEntryPoint = PeGetEntryPoint;
|
||||
XtPeCoffProtocol.GetMachineType = PeGetMachineType;
|
||||
XtPeCoffProtocol.GetSubSystem = PeGetSubSystem;
|
||||
XtPeCoffProtocol.LoadImage = PeLoadImage;
|
||||
XtPeCoffProtocol.RelocateImage = PeRelocateImage;
|
||||
|
||||
/* Register PE/COFF protocol */
|
||||
return XtLdrProtocol->Protocol.Register(&Guid, &XtPeCoffProtocol);
|
||||
}
|
Loading…
Reference in New Issue
Block a user