From b03c9c2a25224c1544280a29ea68e41945d60a37 Mon Sep 17 00:00:00 2001 From: belliash Date: Sat, 12 Nov 2022 12:37:49 +0100 Subject: [PATCH] Further PE/COFF module improvements --- sdk/xtdk/xtimage.h | 4 + xtldr/includes/blmod.h | 5 +- xtldr/modules/pecoff/includes/pecoff.h | 23 +++-- xtldr/modules/pecoff/pecoff.c | 122 ++++++++++++++++--------- xtldr/modules/xtos/xtos.c | 7 +- 5 files changed, 107 insertions(+), 54 deletions(-) diff --git a/sdk/xtdk/xtimage.h b/sdk/xtdk/xtimage.h index 7588cb6..1a0b79a 100644 --- a/sdk/xtdk/xtimage.h +++ b/sdk/xtdk/xtimage.h @@ -12,6 +12,7 @@ #include "xtdefs.h" #include "xtstruct.h" #include "xttypes.h" +#include "xtfw.h" /* PE/COFF file image signatures */ @@ -190,10 +191,13 @@ /* PE/COFF image representation structure */ typedef struct _PECOFF_IMAGE_CONTEXT { + PPECOFF_IMAGE_DOS_HEADER DosHeader; + PPECOFF_IMAGE_PE_HEADER PeHeader; PVOID Data; UINT64 FileSize; UINT ImagePages; UINT ImageSize; + LOADER_MEMORY_TYPE MemoryType; PVOID VirtualAddress; } PECOFF_IMAGE_CONTEXT, *PPECOFF_IMAGE_CONTEXT; diff --git a/xtldr/includes/blmod.h b/xtldr/includes/blmod.h index a469f79..3d36606 100644 --- a/xtldr/includes/blmod.h +++ b/xtldr/includes/blmod.h @@ -21,7 +21,9 @@ typedef struct _XT_PECOFFF_IMAGE_PROTOCOL XT_PECOFF_IMAGE_PROTOCOL, *PXT_PECOFF_ /* Pointers to the routines provided by the modules */ typedef EFI_STATUS (*PXT_BOOTPROTO_BOOT_SYSTEM)(IN PXT_BOOT_PROTOCOL_PARAMETERS Parameters); -typedef EFI_STATUS (*PXT_PECOFF_PROTOCOL_LOAD)(IN PEFI_FILE_HANDLE FileHandle, IN PVOID VirtualAddress, OUT PPECOFF_IMAGE_CONTEXT *Image); +typedef EFI_STATUS (*PXT_PECOFF_GET_ENTRY_POINT)(IN PPECOFF_IMAGE_CONTEXT Image, OUT PVOID *EntryPoint); +typedef EFI_STATUS (*PXT_PECOFF_PROTOCOL_LOAD)(IN PEFI_FILE_HANDLE FileHandle, IN LOADER_MEMORY_TYPE MemoryType, + IN PVOID VirtualAddress, OUT PPECOFF_IMAGE_CONTEXT *Image); /* XT common boot protocols */ typedef struct _XT_BOOT_PROTOCOL @@ -44,6 +46,7 @@ typedef struct _XT_BOOT_PROTOCOL_PARAMETERS /* EFI XT PE/COFF Image Protocol */ typedef struct _XT_PECOFFF_IMAGE_PROTOCOL { + PXT_PECOFF_GET_ENTRY_POINT GetEntryPoint; PXT_PECOFF_PROTOCOL_LOAD Load; } XT_PECOFF_IMAGE_PROTOCOL, *PXT_PECOFF_IMAGE_PROTOCOL; diff --git a/xtldr/modules/pecoff/includes/pecoff.h b/xtldr/modules/pecoff/includes/pecoff.h index 94e1799..bed588e 100644 --- a/xtldr/modules/pecoff/includes/pecoff.h +++ b/xtldr/modules/pecoff/includes/pecoff.h @@ -12,17 +12,24 @@ #include -EFI_STATUS PeLoadImage(IN PEFI_FILE_HANDLE FileHandle, - IN PVOID VirtualAddress, - OUT PPECOFF_IMAGE_CONTEXT *Image); +/* PE/COFF image protocol related routines forward references */ +EFI_STATUS +PeGetEntryPoint(IN PPECOFF_IMAGE_CONTEXT Image, + OUT PVOID *EntryPoint); EFI_STATUS -PepReadImageHeader(IN PUCHAR ImageData, - IN SIZE_T FileSize, - OUT PPECOFF_IMAGE_PE_HEADER *PeHeader); +PeLoadImage(IN PEFI_FILE_HANDLE FileHandle, + IN LOADER_MEMORY_TYPE MemoryType, + IN PVOID VirtualAddress, + OUT PPECOFF_IMAGE_CONTEXT *Image); EFI_STATUS -BlXtLdrModuleMain(EFI_HANDLE ImageHandle, - PEFI_SYSTEM_TABLE SystemTable); +PepValidateImageHeaders(IN PPECOFF_IMAGE_DOS_HEADER DosHeader, + IN PPECOFF_IMAGE_PE_HEADER PeHeader, + IN SIZE_T FileSize); + +EFI_STATUS +BlXtLdrModuleMain(IN EFI_HANDLE ImageHandle, + IN PEFI_SYSTEM_TABLE SystemTable); #endif /* __XTLDR_MODULES_PECOFF_H */ diff --git a/xtldr/modules/pecoff/pecoff.c b/xtldr/modules/pecoff/pecoff.c index 76e41f1..431c8a0 100644 --- a/xtldr/modules/pecoff/pecoff.c +++ b/xtldr/modules/pecoff/pecoff.c @@ -21,41 +21,76 @@ PXT_BOOT_LOADER_PROTOCOL XtLdrProtocol; /* XTOS PE/COFF Image Protocol */ XT_PECOFF_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 + */ +EFI_STATUS +PeGetEntryPoint(IN PPECOFF_IMAGE_CONTEXT Image, + OUT PVOID *EntryPoint) +{ + /* Validate input date */ + if(!Image || !Image->PeHeader) + { + /* Invalid parameter passed */ + return STATUS_EFI_INVALID_PARAMETER; + } + + /* Set entry point and return success */ + *EntryPoint = (UINT8*)Image->VirtualAddress + Image->PeHeader->OptionalHeader.AddressOfEntryPoint; + 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 */ -EFI_STATUS PeLoadImage(IN PEFI_FILE_HANDLE FileHandle, - IN PVOID VirtualAddress, - OUT PPECOFF_IMAGE_CONTEXT *Image) +EFI_STATUS +PeLoadImage(IN PEFI_FILE_HANDLE FileHandle, + IN LOADER_MEMORY_TYPE MemoryType, + IN PVOID VirtualAddress, + OUT PPECOFF_IMAGE_CONTEXT *Image) { EFI_GUID FileInfoGuid = EFI_FILE_INFO_PROTOCOL_GUID; PPECOFF_IMAGE_SECTION_HEADER SectionHeader; - PPECOFF_IMAGE_PE_HEADER PeHeader; PPECOFF_IMAGE_CONTEXT ImageData; EFI_PHYSICAL_ADDRESS Address; PEFI_FILE_INFO FileInfo; - SIZE_T Size, Pages; + SIZE_T Pages, ReadSize; EFI_STATUS Status; - UINT_PTR ReadSize; UINT SectionSize; PUCHAR Data; UINT Index; /* Set required size for getting file information */ - Size = sizeof(EFI_FILE_INFO) + 32; + ReadSize = sizeof(EFI_FILE_INFO) + 32; /* Allocate necessary amount of memory */ - Status = XtLdrProtocol->AllocatePool(Size, (PVOID *)&FileInfo); + Status = XtLdrProtocol->AllocatePool(ReadSize, (PVOID *)&FileInfo); if(Status != STATUS_EFI_SUCCESS) { /* Memory allocation failure */ @@ -64,20 +99,21 @@ EFI_STATUS PeLoadImage(IN PEFI_FILE_HANDLE FileHandle, } /* First attempt to get file information */ - Status = FileHandle->GetInfo(FileHandle, &FileInfoGuid, &Size, FileInfo); + 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->FreePool(&FileInfo); - Status = XtLdrProtocol->AllocatePool(Size, (PVOID *)&FileInfo); + Status = XtLdrProtocol->AllocatePool(ReadSize, (PVOID *)&FileInfo); if(Status != STATUS_EFI_SUCCESS) { /* Memory allocation failure */ XtLdrProtocol->DbgPrint(L"ERROR: Memory pool allocation failure\n"); return Status; } + /* Second attempt to get file information */ - Status = FileHandle->GetInfo(FileHandle, &FileInfoGuid, &Size, FileInfo); + Status = FileHandle->GetInfo(FileHandle, &FileInfoGuid, &ReadSize, FileInfo); } if(Status != STATUS_EFI_SUCCESS) { @@ -95,8 +131,10 @@ EFI_STATUS PeLoadImage(IN PEFI_FILE_HANDLE FileHandle, return Status; } - /* Store file size and free memory */ + /* Store file size and memory type, nullify data and free up memory */ + ImageData->Data = NULL; ImageData->FileSize = FileInfo->FileSize; + ImageData->MemoryType = MemoryType; XtLdrProtocol->FreePool(FileInfo); /* Calculate number of pages */ @@ -125,19 +163,23 @@ EFI_STATUS PeLoadImage(IN PEFI_FILE_HANDLE FileHandle, return Status; } - /* Read and validate headers */ - Status = PepReadImageHeader(Data, ImageData->FileSize, &PeHeader); + /* 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->DbgPrint(L"ERROR: Invalid PE/COFF image header\n"); + XtLdrProtocol->DbgPrint(L"ERROR: Invalid PE/COFF image headers\n"); XtLdrProtocol->FreePages(Pages, (EFI_PHYSICAL_ADDRESS)(UINT_PTR)Data); XtLdrProtocol->FreePool(ImageData); return Status; } /* Store image size and calculate number of image pages */ - ImageData->ImageSize = PeHeader->OptionalHeader.SizeOfImage; + ImageData->ImageSize = ImageData->PeHeader->OptionalHeader.SizeOfImage; ImageData->ImagePages = EFI_SIZE_TO_PAGES(ImageData->ImageSize); /* Allocate image pages */ @@ -150,7 +192,7 @@ EFI_STATUS PeLoadImage(IN PEFI_FILE_HANDLE FileHandle, return Status; } - /* Store image data and base address */ + /* Store image data and virtual address */ ImageData->Data = (PUINT8)(UINT_PTR)Address; if(VirtualAddress) { @@ -164,14 +206,14 @@ EFI_STATUS PeLoadImage(IN PEFI_FILE_HANDLE FileHandle, } /* Copy all sections */ - RtlCopyMemory(ImageData->Data, Data, PeHeader->OptionalHeader.SizeOfHeaders); + RtlCopyMemory(ImageData->Data, Data, ImageData->PeHeader->OptionalHeader.SizeOfHeaders); /* Find section header */ - SectionHeader = (PPECOFF_IMAGE_SECTION_HEADER)((PUCHAR)&PeHeader->OptionalHeader + - PeHeader->FileHeader.SizeOfOptionalHeader); + SectionHeader = (PPECOFF_IMAGE_SECTION_HEADER)((PUCHAR)&ImageData->PeHeader->OptionalHeader + + ImageData->PeHeader->FileHeader.SizeOfOptionalHeader); /* Load each section into memory */ - for(Index = 0; Index < PeHeader->FileHeader.NumberOfSections; Index++) + 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) @@ -213,28 +255,26 @@ EFI_STATUS PeLoadImage(IN PEFI_FILE_HANDLE FileHandle, } /** - * Reads and validate a PE/COFF image headers + * Validates a PE/COFF image headers. * - * @param ImageData - * A pointer to the buffer containing PE/COFF image contents. - * - * @param FileSize - * An input PE/COFF image file size. + * @param DosHeader + * Pointer to the memory area with DOS header stored. * * @param PeHeader - * Pointer to the memory area where PE header will be saved. + * 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 */ EFI_STATUS -PepReadImageHeader(IN PUCHAR ImageData, - IN SIZE_T FileSize, - OUT PPECOFF_IMAGE_PE_HEADER *PeHeader) +PepValidateImageHeaders(IN PPECOFF_IMAGE_DOS_HEADER DosHeader, + IN PPECOFF_IMAGE_PE_HEADER PeHeader, + IN SIZE_T FileSize) { - PPECOFF_IMAGE_DOS_HEADER DosHeader; - /* Validate file size */ if(FileSize < sizeof(PECOFF_IMAGE_DOS_HEADER)) { @@ -243,30 +283,27 @@ PepReadImageHeader(IN PUCHAR ImageData, } /* Validate DOS header */ - DosHeader = (PPECOFF_IMAGE_DOS_HEADER)ImageData; if(DosHeader->e_magic != PECOFF_IMAGE_DOS_SIGNATURE) { XtLdrProtocol->DbgPrint(L"WARNING: Invalid DOS signature found\n"); return STATUS_EFI_INCOMPATIBLE_VERSION; } - /* Validate NT/XT header */ - *PeHeader = (PPECOFF_IMAGE_PE_HEADER)(ImageData + DosHeader->e_lfanew); - if((*PeHeader)->Signature != PECOFF_IMAGE_NT_SIGNATURE && (*PeHeader)->Signature != PECOFF_IMAGE_XT_SIGNATURE) + /* Validate PE header */ + if(PeHeader->Signature != PECOFF_IMAGE_NT_SIGNATURE && PeHeader->Signature != PECOFF_IMAGE_XT_SIGNATURE) { XtLdrProtocol->DbgPrint(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) + if(PeHeader->OptionalHeader.Magic != PECOFF_IMAGE_PE_OPTIONAL_HDR32_MAGIC && + PeHeader->OptionalHeader.Magic != PECOFF_IMAGE_PE_OPTIONAL_HDR64_MAGIC) { XtLdrProtocol->DbgPrint(L"WARNING: Invalid optional header signature found\n"); return STATUS_EFI_INCOMPATIBLE_VERSION; } - /* Return SUCCESS */ return STATUS_EFI_SUCCESS; } @@ -284,8 +321,8 @@ PepReadImageHeader(IN PUCHAR ImageData, * @since XT 1.0 */ EFI_STATUS -BlXtLdrModuleMain(EFI_HANDLE ImageHandle, - PEFI_SYSTEM_TABLE SystemTable) +BlXtLdrModuleMain(IN EFI_HANDLE ImageHandle, + IN PEFI_SYSTEM_TABLE SystemTable) { EFI_GUID Guid = XT_PECOFF_IMAGE_PROTOCOL_GUID; EFI_HANDLE Handle = NULL; @@ -304,6 +341,7 @@ BlXtLdrModuleMain(EFI_HANDLE ImageHandle, } /* Set routines available via PE/COFF image protocol */ + XtPeCoffProtocol.GetEntryPoint = PeGetEntryPoint; XtPeCoffProtocol.Load = PeLoadImage; /* Register PE/COFF protocol */ diff --git a/xtldr/modules/xtos/xtos.c b/xtldr/modules/xtos/xtos.c index e011865..ab599bd 100644 --- a/xtldr/modules/xtos/xtos.c +++ b/xtldr/modules/xtos/xtos.c @@ -160,6 +160,7 @@ XtpBootSequence(IN PEFI_FILE_HANDLE BootDir, IN PXT_BOOT_PROTOCOL_PARAMETERS Parameters) { PEFI_FILE_HANDLE KernelHandle; + PPECOFF_IMAGE_CONTEXT Image; EFI_STATUS Status; XtLdrProtocol->DbgPrint(L"Issuing XT startup sequence\n"); @@ -174,7 +175,7 @@ XtpBootSequence(IN PEFI_FILE_HANDLE BootDir, } /* Load the PE/COFF kernel file */ - Status = XtPeCoffProtocol->Load(KernelHandle, (PVOID)XTOS_KERNEL_ADDRESS, NULL); + Status = XtPeCoffProtocol->Load(KernelHandle, LoaderSystemCode, NULL, &Image); if(Status != STATUS_EFI_SUCCESS) { /* Unable to load the file */ @@ -203,8 +204,8 @@ XtpBootSequence(IN PEFI_FILE_HANDLE BootDir, * @since XT 1.0 */ EFI_STATUS -BlXtLdrModuleMain(EFI_HANDLE ImageHandle, - PEFI_SYSTEM_TABLE SystemTable) +BlXtLdrModuleMain(IN EFI_HANDLE ImageHandle, + IN PEFI_SYSTEM_TABLE SystemTable) { EFI_GUID Guid = XT_XTOS_BOOT_PROTOCOL_GUID; EFI_HANDLE Handle = NULL;