From 5ed47e7c710300cfe63d7d9f222f6170e9fcf749 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marvin=20Ha=CC=88user?= <8659494+mhaeuser@users.noreply.github.com> Date: Sun, 23 Apr 2023 23:45:16 +0200 Subject: [PATCH] ImageTool: Utilize UefiImageLib --- BaseTools/ImageTool/GNUmakefile | 8 +- BaseTools/ImageTool/ImageTool.h | 3 +- BaseTools/ImageTool/ImageToolEmit.c | 11 +- BaseTools/ImageTool/ImageToolEmit.h | 2 +- BaseTools/ImageTool/Makefile | 12 +- BaseTools/ImageTool/PeScan.c | 123 ------------- BaseTools/ImageTool/PeScan.h | 23 +++ BaseTools/ImageTool/UefiImageScan.c | 261 ++++++++++++++++++++++++++++ 8 files changed, 306 insertions(+), 137 deletions(-) create mode 100644 BaseTools/ImageTool/PeScan.h create mode 100644 BaseTools/ImageTool/UefiImageScan.c diff --git a/BaseTools/ImageTool/GNUmakefile b/BaseTools/ImageTool/GNUmakefile index 43291a4ac1..597b87698a 100644 --- a/BaseTools/ImageTool/GNUmakefile +++ b/BaseTools/ImageTool/GNUmakefile @@ -7,9 +7,10 @@ PROJECT = ImageTool PRODUCT = $(PROJECT)$(INFIX)$(SUFFIX) OBJS = $(PROJECT).o -OBJS += Image.o PeEmit32.o PeEmit64.o PeEmitCommon.o PeScan.o ElfScan32.o ElfScan64.o ElfScanCommon.o BinEmit.o ImageToolEmit.o +OBJS += Image.o UefiImageScan.o PeEmit32.o PeEmit64.o PeEmitCommon.o PeScan.o ElfScan32.o ElfScan64.o ElfScanCommon.o BinEmit.o ImageToolEmit.o OBJS += UefiImageExtraActionLib.o -OBJS += PeCoffInit.o PeCoffInfo.o PeCoffLoad.o PeCoffRelocate.o PeCoffHii.o PeCoffDebug.o +OBJS += PeCoffInit.o PeCoffInfo.o PeCoffLoad.o PeCoffRelocate.o PeCoffHii.o PeCoffDebug.o PeCoffHash.o +OBJS += UefiImageLibPeCoff.o PeCoffSupport.o CommonSupport.o WERROR = 1 DEBUG = 1 @@ -18,6 +19,7 @@ OC_USER = ../../OpenCorePkg UDK_PATH = ../.. VPATH += ../../MdePkg/Library/BasePeCoffLib2:$\ - ../../MdePkg/Library/BaseUefiImageExtraActionLibNull + ../../MdePkg/Library/BaseUefiImageExtraActionLibNull:$\ + ../../MdePkg/Library/BaseUefiImageLib include $(OC_USER)/User/Makefile diff --git a/BaseTools/ImageTool/ImageTool.h b/BaseTools/ImageTool/ImageTool.h index 8b9650a7f7..8426d8f5b1 100644 --- a/BaseTools/ImageTool/ImageTool.h +++ b/BaseTools/ImageTool/ImageTool.h @@ -136,8 +136,9 @@ ToolImageStripRelocs ( ); RETURN_STATUS -ToolContextConstructPe ( +ToolContextConstructUefiImage ( OUT image_tool_image_info_t *Image, + OUT INT8 *Format, IN const void *File, IN size_t FileSize ); diff --git a/BaseTools/ImageTool/ImageToolEmit.c b/BaseTools/ImageTool/ImageToolEmit.c index a9fd32689b..8ddda2354c 100644 --- a/BaseTools/ImageTool/ImageToolEmit.c +++ b/BaseTools/ImageTool/ImageToolEmit.c @@ -19,7 +19,7 @@ ToolContextConstruct ( OUT image_tool_image_info_t *ImageInfo, OUT int8_t *Format, IN const void *File, - IN size_t FileSize, + IN uint32_t FileSize, IN const char *SymbolsPath OPTIONAL ) { @@ -27,14 +27,13 @@ ToolContextConstruct ( *Format = -1; - Status = ToolContextConstructPe ( + Status = ToolContextConstructUefiImage ( ImageInfo, + Format, File, FileSize ); - if (!RETURN_ERROR (Status)) { - *Format = UefiImageFormatPe; - } else if (Status == RETURN_UNSUPPORTED) { + if (Status == RETURN_UNSUPPORTED) { Status = ScanElf (ImageInfo, File, FileSize, SymbolsPath); } @@ -89,7 +88,7 @@ void * ToolImageEmit ( OUT uint32_t *OutputFileSize, IN const void *Buffer, - IN uint64_t BufferSize, + IN uint32_t BufferSize, IN int8_t Format, IN int32_t Type, IN void *HiiFile, diff --git a/BaseTools/ImageTool/ImageToolEmit.h b/BaseTools/ImageTool/ImageToolEmit.h index 8f056d94a8..11b8b3fa97 100644 --- a/BaseTools/ImageTool/ImageToolEmit.h +++ b/BaseTools/ImageTool/ImageToolEmit.h @@ -14,7 +14,7 @@ void * ToolImageEmit ( OUT uint32_t *OutputFileSize, IN const void *Buffer, - IN uint64_t BufferSize, + IN uint32_t BufferSize, IN int8_t Format, IN int32_t Type, IN void *HiiFile, diff --git a/BaseTools/ImageTool/Makefile b/BaseTools/ImageTool/Makefile index d071a6554e..9b587d25d6 100644 --- a/BaseTools/ImageTool/Makefile +++ b/BaseTools/ImageTool/Makefile @@ -19,19 +19,21 @@ OV = $(UDK_PATH)\MdePkg\Library\BaseOverflowLib PE = $(UDK_PATH)\MdePkg\Library\BasePeCoffLib2 UA = $(UDK_PATH)\MdePkg\Library\BaseUefiImageExtraActionLibNull -OBJECTS = ImageTool.obj Image.obj PeEmit32.obj PeEmit64.obj PeEmitCommon.obj PeScan.obj ElfScan32.obj ElfScan64.obj ElfScanCommon.obj BinEmit.obj ImageToolEmit.obj +OBJECTS = ImageTool.obj Image.obj PeEmit32.obj PeEmit64.obj PeEmitCommon.obj UefiImageScan.obj PeScan.obj ElfScan32.obj ElfScan64.obj ElfScanCommon.obj BinEmit.obj ImageToolEmit.obj OBJECTS = $(OBJECTS) {$(OV)}BaseAlignment.obj BaseBitOverflow.obj {$(UA)}UefiImageExtraActionLib.obj -OBJECTS = $(OBJECTS) {$(PE)}PeCoffInit.obj PeCoffInfo.obj PeCoffRelocate.obj PeCoffLoad.obj PeCoffHii.obj PeCoffDebug.obj +OBJECTS = $(OBJECTS) {$(PE)}PeCoffInit.obj PeCoffInfo.obj PeCoffRelocate.obj PeCoffLoad.obj PeCoffHii.obj PeCoffDebug.obj PeCoffHash.obj BASE = $(UDK_PATH)\MdePkg\Library\BaseLib OUT = $(UDK_PATH)\MdePkg\Library\UefiDebugLibConOut PRIN = $(UDK_PATH)\MdePkg\Library\BasePrintLib ERRO = $(UDK_PATH)\MdePkg\Library\BaseDebugPrintErrorLevelLib +UIMG = $(UDK_PATH)\MdePkg\Library\BaseUefiImageLib BMPN = $(UDK_PATH)\MdeModulePkg\Library\BaseMemoryProfileLibNull CMEM = $(UDK_PATH)\MdeModulePkg\Library\CommonMemoryAllocationLib USER = $(OC_USER)\User\Library -OBJECTS = $(OBJECTS) {$(BASE)}SafeString.obj String.obj SwapBytes16.obj SwapBytes32.obj CpuDeadLoop.obj CheckSum.obj QuickSort.obj +OBJECTS = $(OBJECTS) {$(BASE)}SafeString.obj String.obj SwapBytes16.obj SwapBytes32.obj CpuDeadLoop.obj CheckSum.obj QuickSort.obj LinkedList.obj OBJECTS = $(OBJECTS) {$(OUT)}DebugLib.obj {$(PRIN)}PrintLib.obj PrintLibInternal.obj {$(ERRO)}BaseDebugPrintErrorLevelLib.obj +OBJECTS = $(OBJECTS) {$(UIMG)}UefiImageLibPeCoff.obj PeCoffSupport.obj CommonSupport.obj OBJECTS = $(OBJECTS) {$(USER)}UserFile.obj UserBaseMemoryLib.obj UserMath.obj UserPcd.obj UserMisc.obj UserGlobalVar.obj UserBootServices.obj OBJECTS = $(OBJECTS) {$(BMPN)}BaseMemoryProfileLibNull.obj {$(CMEM)}CommonMemoryAllocationLib.obj {$(CMEM)}CommonMemoryAllocationLibEx.obj @@ -99,6 +101,10 @@ cleanall: $(CC) -c $(CFLAGS) $(INC) $< -Fo$@ @move $@ $(OUT_DIR)\ +{$(UIMG)}.c.obj : + $(CC) -c $(CFLAGS) $(INC) $< -Fo$@ + @move $@ $(OUT_DIR)\ + {$(USER)}.c.obj : $(CC) -c $(CFLAGS) $(INC) /D WIN32 /wd 4754 $< -Fo$@ @move $@ $(OUT_DIR)\ diff --git a/BaseTools/ImageTool/PeScan.c b/BaseTools/ImageTool/PeScan.c index 121d94661a..2ff017249e 100644 --- a/BaseTools/ImageTool/PeScan.c +++ b/BaseTools/ImageTool/PeScan.c @@ -10,27 +10,6 @@ #define PE_COFF_SECT_NAME_RESRC ".rsrc\0\0" #define PE_COFF_SECT_NAME_DEBUG ".debug\0" -static -bool -ScanPeGetHeaderInfo ( - OUT image_tool_header_info_t *HeaderInfo, - IN PE_COFF_LOADER_IMAGE_CONTEXT *Context - ) -{ - assert (HeaderInfo != NULL); - assert (Context != NULL); - - HeaderInfo->BaseAddress = (uint64_t)PeCoffGetImageBase (Context); - HeaderInfo->EntryPointAddress = PeCoffGetAddressOfEntryPoint (Context); - // FIXME: - HeaderInfo->Machine = PeCoffGetMachine (Context); - HeaderInfo->IsXip = true; - HeaderInfo->Subsystem = PeCoffGetSubsystem (Context); - - return true; -} - -static bool ScanPeGetRelocInfo ( OUT image_tool_reloc_info_t *RelocInfo, @@ -54,8 +33,6 @@ ScanPeGetRelocInfo ( assert (RelocInfo != NULL); assert (Context != NULL); - RelocInfo->RelocsStripped = false; - // FIXME: PE/COFF context access RelocBlockRva = Context->RelocDirRva; RelocDirSize = Context->RelocDirSize; @@ -169,7 +146,6 @@ ScanPeGetRelocInfo ( return true; } -static bool ScanPeGetSegmentInfo ( OUT image_tool_segment_info_t *SegmentInfo, @@ -185,8 +161,6 @@ ScanPeGetSegmentInfo ( assert (SegmentInfo != NULL); assert (Context != NULL); - SegmentInfo->SegmentAlignment = PeCoffGetSectionAlignment (Context); - NumSections = PeCoffGetSectionTable (Context, &Section); SegmentInfo->Segments = calloc (NumSections, sizeof (*SegmentInfo->Segments)); @@ -319,100 +293,3 @@ ScanPeGetHiiInfo ( return true; } - -RETURN_STATUS -ToolContextConstructPe ( - OUT image_tool_image_info_t *Image, - IN const void *File, - IN size_t FileSize - ) -{ - PE_COFF_LOADER_IMAGE_CONTEXT Context; - RETURN_STATUS Status; - UINT32 ImageSize; - UINT32 ImageAlignment; - UINT32 DestinationSize; - UINT32 DestinationPages; - void *Destination; - bool Result; - - assert (Image != NULL); - assert (File != NULL || FileSize == 0); - - if (FileSize > MAX_UINT32) { - fprintf (stderr, "ImageTool: FileSize is too huge\n"); - return RETURN_UNSUPPORTED; - } - - Status = PeCoffInitializeContext (&Context, File, (UINT32)FileSize); - if (RETURN_ERROR (Status)) { - return Status; - } - - ImageSize = PeCoffGetSizeOfImage (&Context); - DestinationPages = EFI_SIZE_TO_PAGES (ImageSize); - DestinationSize = EFI_PAGES_TO_SIZE (DestinationPages); - ImageAlignment = PeCoffGetSectionAlignment (&Context); - - Destination = AllocateAlignedCodePages ( - DestinationPages, - ImageAlignment - ); - if (Destination == NULL) { - fprintf (stderr, "ImageTool: Could not allocate Destination buffer\n"); - return RETURN_OUT_OF_RESOURCES; - } - - Status = PeCoffLoadImage (&Context, Destination, DestinationSize); - if (RETURN_ERROR (Status)) { - fprintf (stderr, "ImageTool: Could not Load Image\n"); - FreeAlignedPages (Destination, DestinationPages); - return RETURN_VOLUME_CORRUPTED; - } - - memset (Image, 0, sizeof (*Image)); - - Result = ScanPeGetHeaderInfo (&Image->HeaderInfo, &Context); - if (!Result) { - fprintf (stderr, "ImageTool: Could not retrieve header info\n"); - ToolImageDestruct (Image); - FreeAlignedPages (Destination, DestinationPages); - return RETURN_VOLUME_CORRUPTED; - } - - Result = ScanPeGetDebugInfo (&Image->DebugInfo, &Context); - if (!Result) { - fprintf (stderr, "ImageTool: Could not retrieve debug info\n"); - ToolImageDestruct (Image); - FreeAlignedPages (Destination, DestinationPages); - return RETURN_VOLUME_CORRUPTED; - } - - Result = ScanPeGetSegmentInfo (&Image->SegmentInfo, &Context); - if (!Result) { - fprintf (stderr, "ImageTool: Could not retrieve segment info\n"); - ToolImageDestruct (Image); - FreeAlignedPages (Destination, DestinationPages); - return RETURN_VOLUME_CORRUPTED; - } - - Result = ScanPeGetRelocInfo (&Image->RelocInfo, &Context); - if (!Result) { - fprintf (stderr, "ImageTool: Could not retrieve reloc info\n"); - ToolImageDestruct (Image); - FreeAlignedPages (Destination, DestinationPages); - return RETURN_VOLUME_CORRUPTED; - } - - Result = ScanPeGetHiiInfo (&Image->HiiInfo, &Context); - if (!Result) { - fprintf (stderr, "ImageTool: Could not retrieve HII info\n"); - ToolImageDestruct (Image); - FreeAlignedPages (Destination, DestinationPages); - return RETURN_VOLUME_CORRUPTED; - } - - FreeAlignedPages (Destination, DestinationPages); - - return RETURN_SUCCESS; -} diff --git a/BaseTools/ImageTool/PeScan.h b/BaseTools/ImageTool/PeScan.h new file mode 100644 index 0000000000..133eb1c0ae --- /dev/null +++ b/BaseTools/ImageTool/PeScan.h @@ -0,0 +1,23 @@ +/** @file + Copyright (c) 2023, Marvin Häuser. All rights reserved. + SPDX-License-Identifier: BSD-3-Clause +**/ + +#ifndef PE_SCAN_H +#define PE_SCAN_H + +#include "ImageTool.h" + +bool +ScanPeGetRelocInfo ( + OUT image_tool_reloc_info_t *RelocInfo, + IN PE_COFF_LOADER_IMAGE_CONTEXT *Context + ); + +bool +ScanPeGetSegmentInfo ( + OUT image_tool_segment_info_t *SegmentInfo, + IN PE_COFF_LOADER_IMAGE_CONTEXT *Context + ); + +#endif // PE_SCAN_H diff --git a/BaseTools/ImageTool/UefiImageScan.c b/BaseTools/ImageTool/UefiImageScan.c new file mode 100644 index 0000000000..c4c97f5405 --- /dev/null +++ b/BaseTools/ImageTool/UefiImageScan.c @@ -0,0 +1,261 @@ +/** @file + Copyright (c) 2023, Marvin Häuser. All rights reserved. + SPDX-License-Identifier: BSD-3-Clause +**/ + +#include "ImageTool.h" + +#include + +#include + +#include "PeScan.h" + +static +bool +ScanUefiImageGetHeaderInfo ( + OUT image_tool_header_info_t *HeaderInfo, + IN UEFI_IMAGE_LOADER_IMAGE_CONTEXT *Context + ) +{ + assert (HeaderInfo != NULL); + assert (Context != NULL); + + HeaderInfo->BaseAddress = (uint64_t)UefiImageGetPreferredAddress (Context); + HeaderInfo->EntryPointAddress = UefiImageGetEntryPointAddress (Context); + HeaderInfo->Machine = UefiImageGetMachine (Context); + HeaderInfo->Subsystem = UefiImageGetSubsystem (Context); + // FIXME: + HeaderInfo->IsXip = true; + + return true; +} + +static +bool +ScanUefiImageGetRelocInfo ( + OUT image_tool_reloc_info_t *RelocInfo, + IN UEFI_IMAGE_LOADER_IMAGE_CONTEXT *Context + ) +{ + UINT8 FormatIndex; + + assert (RelocInfo != NULL); + assert (Context != NULL); + + FormatIndex = UefiImageGetFormat (Context); + + RelocInfo->RelocsStripped = UefiImageGetRelocsStripped (Context); + + if (FormatIndex == UefiImageFormatPe) { + return ScanPeGetRelocInfo ( + RelocInfo, + (PE_COFF_LOADER_IMAGE_CONTEXT *)Context + ); + } + + fprintf ( + stderr, + "ImageTool: Unsupported UefiImage format %u\n", + FormatIndex + ); + return false; +} + +static +bool +ScanUefiImageGetSegmentInfo ( + OUT image_tool_segment_info_t *SegmentInfo, + IN UEFI_IMAGE_LOADER_IMAGE_CONTEXT *Context + ) +{ + UINT8 FormatIndex; + + assert (SegmentInfo != NULL); + assert (Context != NULL); + + FormatIndex = UefiImageGetFormat (Context); + + SegmentInfo->SegmentAlignment = UefiImageGetSegmentAlignment (Context); + + if (FormatIndex == UefiImageFormatPe) { + return ScanPeGetSegmentInfo ( + SegmentInfo, + (PE_COFF_LOADER_IMAGE_CONTEXT *)Context + ); + } + + fprintf ( + stderr, + "ImageTool: Unsupported UefiImage format %u\n", + FormatIndex + ); + return false; +} + +bool +ScanUefiImageGetDebugInfo ( + OUT image_tool_debug_info_t *DebugInfo, + IN UEFI_IMAGE_LOADER_IMAGE_CONTEXT *Context + ) +{ + RETURN_STATUS Status; + const CHAR8 *SymbolsPath; + UINT32 SymbolsPathSize; + + assert (DebugInfo != NULL); + assert (Context != NULL); + + Status = UefiImageGetSymbolsPath (Context, &SymbolsPath, &SymbolsPathSize); + if (Status == RETURN_NOT_FOUND) { + return true; + } + if (RETURN_ERROR (Status)) { + fprintf (stderr, "ImageTool: Could not get SymbolsPath\n"); + return false; + } + + assert (SymbolsPathSize >= 1); + + DebugInfo->SymbolsPath = malloc (SymbolsPathSize + 1); + if (DebugInfo->SymbolsPath == NULL) { + fprintf (stderr, "ImageTool: Could not allocate memory for SymbolsPath\n"); + return false; + } + + memmove (DebugInfo->SymbolsPath, SymbolsPath, SymbolsPathSize); + assert (DebugInfo->SymbolsPath[SymbolsPathSize - 1] == '\0'); + + DebugInfo->SymbolsPathLen = SymbolsPathSize - 1; + + return true; +} + +bool +ScanUefiImageGetHiiInfo ( + OUT image_tool_hii_info_t *HiiInfo, + IN UEFI_IMAGE_LOADER_IMAGE_CONTEXT *Context + ) +{ + RETURN_STATUS Status; + UINT32 HiiRva; + UINT32 HiiSize; + const char *ImageBuffer; + + assert (HiiInfo != NULL); + assert (Context != NULL); + + Status = UefiImageGetHiiDataRva (Context, &HiiRva, &HiiSize); + if (Status == RETURN_NOT_FOUND) { + return true; + } + if (RETURN_ERROR (Status)) { + fprintf (stderr, "ImageTool: Malformed HII data\n"); + return false; + } + + HiiInfo->Data = malloc (HiiSize); + if (HiiInfo->Data == NULL) { + fprintf (stderr, "ImageTool: Could not allocate memory for HiiInfo Data\n"); + return false; + } + + ImageBuffer = (char *)UefiImageLoaderGetImageAddress (Context); + + memmove (HiiInfo->Data, ImageBuffer + HiiRva, HiiSize); + HiiInfo->DataSize = HiiSize; + + return true; +} + +RETURN_STATUS +ToolContextConstructUefiImage ( + OUT image_tool_image_info_t *Image, + OUT int8_t *Format, + IN const void *File, + IN size_t FileSize + ) +{ + RETURN_STATUS Status; + UEFI_IMAGE_LOADER_IMAGE_CONTEXT Context; + UINT32 ImageSize; + UINT32 ImageAlignment; + UINT32 DestinationPages; + UINT32 DestinationSize; + void *Destination; + bool Success; + + assert (Image != NULL); + assert (File != NULL || FileSize == 0); + + if (FileSize > MAX_UINT32) { + fprintf (stderr, "ImageTool: FileSize is too huge\n"); + return RETURN_UNSUPPORTED; + } + + Status = UefiImageInitializeContext (&Context, File, (UINT32)FileSize); + if (RETURN_ERROR (Status)) { + return Status; + } + + *Format = (int8_t)UefiImageGetFormat (&Context); + + ImageSize = UefiImageGetImageSize (&Context); + DestinationPages = EFI_SIZE_TO_PAGES (ImageSize); + DestinationSize = EFI_PAGES_TO_SIZE (DestinationPages); + ImageAlignment = UefiImageGetSegmentAlignment (&Context); + + Destination = AllocateAlignedCodePages (DestinationPages, ImageAlignment); + if (Destination == NULL) { + fprintf (stderr, "ImageTool: Could not allocate Destination buffer\n"); + return RETURN_OUT_OF_RESOURCES; + } + + Status = UefiImageLoadImage (&Context, Destination, DestinationSize); + if (RETURN_ERROR (Status)) { + fprintf (stderr, "ImageTool: Could not Load Image\n"); + FreeAlignedPages (Destination, DestinationPages); + return RETURN_VOLUME_CORRUPTED; + } + + memset (Image, 0, sizeof (*Image)); + + Success = ScanUefiImageGetHeaderInfo (&Image->HeaderInfo, &Context); + if (!Success) { + fprintf (stderr, "ImageTool: Could not retrieve header info\n"); + FreeAlignedPages (Destination, DestinationPages); + return RETURN_VOLUME_CORRUPTED; + } + + Success = ScanUefiImageGetSegmentInfo (&Image->SegmentInfo, &Context); + if (!Success) { + fprintf (stderr, "ImageTool: Could not retrieve segment info\n"); + FreeAlignedPages (Destination, DestinationPages); + return RETURN_VOLUME_CORRUPTED; + } + + Success = ScanUefiImageGetRelocInfo (&Image->RelocInfo, &Context); + if (!Success) { + fprintf (stderr, "ImageTool: Could not retrieve reloc info\n"); + FreeAlignedPages (Destination, DestinationPages); + return RETURN_VOLUME_CORRUPTED; + } + + Success = ScanUefiImageGetHiiInfo (&Image->HiiInfo, &Context); + if (!Success) { + fprintf (stderr, "ImageTool: Could not retrieve HII info\n"); + FreeAlignedPages (Destination, DestinationPages); + return RETURN_VOLUME_CORRUPTED; + } + + Success = ScanUefiImageGetDebugInfo (&Image->DebugInfo, &Context); + if (!Success) { + fprintf (stderr, "ImageTool: Could not retrieve debug info\n"); + FreeAlignedPages (Destination, DestinationPages); + return RETURN_VOLUME_CORRUPTED; + } + + FreeAlignedPages (Destination, DestinationPages); + + return RETURN_SUCCESS; +}