From 08778e2a3da83eac76a4e0be73df2f146b81c4f5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marvin=20Ha=CC=88user?= <8659494+mhaeuser@users.noreply.github.com> Date: Sun, 2 Apr 2023 15:09:31 +0200 Subject: [PATCH] ImageTool: Abstract executable generation --- BaseTools/ImageTool/ElfScan.c | 77 ++++---------- BaseTools/ImageTool/ImageTool.c | 178 ++++++++++++++++++-------------- BaseTools/ImageTool/ImageTool.h | 10 +- BaseTools/ImageTool/PeScan.c | 45 +------- 4 files changed, 127 insertions(+), 183 deletions(-) diff --git a/BaseTools/ImageTool/ElfScan.c b/BaseTools/ImageTool/ElfScan.c index 27525411f6..b6b9081861 100644 --- a/BaseTools/ImageTool/ElfScan.c +++ b/BaseTools/ImageTool/ElfScan.c @@ -180,8 +180,9 @@ SetHiiResourceHeader ( static RETURN_STATUS -ReadElfFile ( - IN const char *Name +ParseElfFile ( + IN const void *File, + IN uint32_t FileSize ) { static const unsigned char Ident[] = { @@ -190,23 +191,18 @@ ReadElfFile ( const Elf_Shdr *Shdr; UINTN Offset; UINT32 Index; - UINT32 FileSize; char *Last; - assert (Name != NULL); + assert (File != NULL || FileSize == 0); - mEhdr = (Elf_Ehdr *)UserReadFile (Name, &FileSize); - if (mEhdr == NULL) { - fprintf (stderr, "ImageTool: Could not open %s: %s\n", Name, strerror (errno)); - return RETURN_VOLUME_CORRUPTED; - } + mEhdr = (Elf_Ehdr *)File; // // Check header // if ((FileSize < sizeof (*mEhdr)) || (memcmp (Ident, mEhdr->e_ident, sizeof (Ident)) != 0)) { - fprintf (stderr, "ImageTool: Invalid ELF header in file %s\n", Name); + fprintf (stderr, "ImageTool: Invalid ELF header\n"); fprintf (stderr, "ImageTool: mEhdr->e_ident[0] = 0x%x expected 0x%x\n", mEhdr->e_ident[0], Ident[0]); fprintf (stderr, "ImageTool: mEhdr->e_ident[1] = 0x%x expected 0x%x\n", mEhdr->e_ident[1], Ident[1]); fprintf (stderr, "ImageTool: mEhdr->e_ident[2] = 0x%x expected 0x%x\n", mEhdr->e_ident[2], Ident[2]); @@ -241,7 +237,7 @@ ReadElfFile ( Offset = (UINTN)mEhdr->e_shoff + Index * mEhdr->e_shentsize; if (FileSize < (Offset + sizeof (*Shdr))) { - fprintf (stderr, "ImageTool: ELF section header is outside file %s\n", Name); + fprintf (stderr, "ImageTool: ELF section header is outside file\n"); return RETURN_VOLUME_CORRUPTED; } @@ -249,7 +245,7 @@ ReadElfFile ( if ((Shdr->sh_type != SHT_NOBITS) && ((FileSize < Shdr->sh_offset) || ((FileSize - Shdr->sh_offset) < Shdr->sh_size))) { - fprintf (stderr, "ImageTool: ELF section %d points outside file %s\n", Index, Name); + fprintf (stderr, "ImageTool: ELF section %d points outside file\n", Index); return RETURN_VOLUME_CORRUPTED; } @@ -764,20 +760,17 @@ CreateIntermediate ( RETURN_STATUS ScanElf ( - IN const char *ElfName, - IN const char *ModuleType + IN const void *File, + IN uint32_t FileSize, + IN const char *SymbolsPath ) { RETURN_STATUS Status; - assert (ElfName != NULL); - assert (ModuleType != NULL); + assert (File != NULL || FileSize == 0); - Status = ReadElfFile (ElfName); + Status = ParseElfFile (File, FileSize); if (RETURN_ERROR (Status)) { - if (mEhdr != NULL) { - free (mEhdr); - } return Status; } @@ -788,7 +781,7 @@ ScanElf ( mImageInfo.HeaderInfo.IsXip = true; mImageInfo.SegmentInfo.SegmentAlignment = (uint32_t)mPeAlignment; mImageInfo.RelocInfo.RelocsStripped = false; - mImageInfo.DebugInfo.SymbolsPathLen = strlen (ElfName); + mImageInfo.DebugInfo.SymbolsPathLen = strlen (SymbolsPath); switch (mEhdr->e_machine) { #if defined(EFI_TARGET64) @@ -808,58 +801,26 @@ ScanElf ( #endif default: fprintf (stderr, "ImageTool: Unknown ELF architecture %d\n", mEhdr->e_machine); - free (mEhdr); return RETURN_INCOMPATIBLE_VERSION; } mImageInfo.DebugInfo.SymbolsPath = malloc (mImageInfo.DebugInfo.SymbolsPathLen + 1); if (mImageInfo.DebugInfo.SymbolsPath == NULL) { fprintf (stderr, "ImageTool: Could not allocate memory for Debug Data\n"); - free (mEhdr); return RETURN_OUT_OF_RESOURCES; }; - memmove (mImageInfo.DebugInfo.SymbolsPath, ElfName, mImageInfo.DebugInfo.SymbolsPathLen + 1); + memmove (mImageInfo.DebugInfo.SymbolsPath, SymbolsPath, mImageInfo.DebugInfo.SymbolsPathLen + 1); - if ((strcmp (ModuleType, "BASE") == 0) - || (strcmp (ModuleType, "SEC") == 0) - || (strcmp (ModuleType, "SECURITY_CORE") == 0) - || (strcmp (ModuleType, "PEI_CORE") == 0) - || (strcmp (ModuleType, "PEIM") == 0) - || (strcmp (ModuleType, "COMBINED_PEIM_DRIVER") == 0) - || (strcmp (ModuleType, "PIC_PEIM") == 0) - || (strcmp (ModuleType, "RELOCATABLE_PEIM") == 0) - || (strcmp (ModuleType, "DXE_CORE") == 0) - || (strcmp (ModuleType, "BS_DRIVER") == 0) - || (strcmp (ModuleType, "DXE_DRIVER") == 0) - || (strcmp (ModuleType, "DXE_SMM_DRIVER") == 0) - || (strcmp (ModuleType, "UEFI_DRIVER") == 0) - || (strcmp (ModuleType, "SMM_CORE") == 0) - || (strcmp (ModuleType, "MM_STANDALONE") == 0) - || (strcmp (ModuleType, "MM_CORE_STANDALONE") == 0)) { - mImageInfo.HeaderInfo.Subsystem = EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER; - } else if ((strcmp (ModuleType, "UEFI_APPLICATION") == 0) - || (strcmp (ModuleType, "APPLICATION") == 0)) { - mImageInfo.HeaderInfo.Subsystem = EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION; - } else if ((strcmp (ModuleType, "DXE_RUNTIME_DRIVER") == 0) - || (strcmp (ModuleType, "RT_DRIVER") == 0)) { - mImageInfo.HeaderInfo.Subsystem = EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER; - } else if ((strcmp (ModuleType, "DXE_SAL_DRIVER") == 0) - || (strcmp (ModuleType, "SAL_RT_DRIVER") == 0)) { - mImageInfo.HeaderInfo.Subsystem = EFI_IMAGE_SUBSYSTEM_SAL_RUNTIME_DRIVER; - } else { - fprintf (stderr, "ImageTool: Unknown EFI_FILETYPE = %s\n", ModuleType); - free (mImageInfo.DebugInfo.SymbolsPath); - free (mEhdr); - return RETURN_UNSUPPORTED; - } + // + // There is no corresponding ELF property. + // + mImageInfo.HeaderInfo.Subsystem = 0; Status = CreateIntermediate (); if (RETURN_ERROR (Status)) { ToolImageDestruct (&mImageInfo); } - free (mEhdr); - return Status; } diff --git a/BaseTools/ImageTool/ImageTool.c b/BaseTools/ImageTool/ImageTool.c index 019e9730ba..272af4966c 100644 --- a/BaseTools/ImageTool/ImageTool.c +++ b/BaseTools/ImageTool/ImageTool.c @@ -14,53 +14,6 @@ image_tool_image_info_t mImageInfo; -static -RETURN_STATUS -PeXip ( - IN const char *OldName, - IN const char *NewName, - IN const char *ModuleType - ) -{ - void *Pe; - uint32_t PeSize; - RETURN_STATUS Status; - image_tool_image_info_t Image; - - assert (OldName != NULL); - assert (NewName != NULL); - assert (ModuleType != NULL); - - Pe = UserReadFile (OldName, &PeSize); - if (Pe == NULL) { - fprintf (stderr, "ImageTool: Could not open %s: %s\n", OldName, strerror (errno)); - return RETURN_ABORTED; - } - - Status = ToolContextConstructPe (&Image, Pe, PeSize, ModuleType); - - free (Pe); - Pe = NULL; - - if (RETURN_ERROR (Status)) { - return RETURN_ABORTED; - } - - Pe = ToolImageEmitPe (&Image, &PeSize); - if (Pe == NULL) { - ToolImageDestruct (&Image); - return RETURN_ABORTED; - } - - ToolImageDestruct (&Image); - - UserWriteFile (NewName, Pe, PeSize); - - free (Pe); - - return RETURN_SUCCESS; -} - static RETURN_STATUS HiiBin ( @@ -341,37 +294,115 @@ GetAcpi ( } static -RETURN_STATUS -ElfToPe ( - IN const char *ElfName, - IN const char *PeName, - IN const char *ModuleType +bool +ImageSetModuleType ( + OUT image_tool_image_info_t *Image, + IN const char *TypeName ) { - RETURN_STATUS Status; - void *Pe; - uint32_t PeSize; + uint16_t ModuleType; - assert (ElfName != NULL); - assert (PeName != NULL); - assert (ModuleType != NULL); + assert (Image != NULL); + + if ((strcmp (TypeName, "BASE") == 0) + || (strcmp (TypeName, "SEC") == 0) + || (strcmp (TypeName, "SECURITY_CORE") == 0) + || (strcmp (TypeName, "PEI_CORE") == 0) + || (strcmp (TypeName, "PEIM") == 0) + || (strcmp (TypeName, "COMBINED_PEIM_DRIVER") == 0) + || (strcmp (TypeName, "PIC_PEIM") == 0) + || (strcmp (TypeName, "RELOCATABLE_PEIM") == 0) + || (strcmp (TypeName, "DXE_CORE") == 0) + || (strcmp (TypeName, "BS_DRIVER") == 0) + || (strcmp (TypeName, "DXE_DRIVER") == 0) + || (strcmp (TypeName, "DXE_SMM_DRIVER") == 0) + || (strcmp (TypeName, "UEFI_DRIVER") == 0) + || (strcmp (TypeName, "SMM_CORE") == 0) + || (strcmp (TypeName, "MM_STANDALONE") == 0) + || (strcmp (TypeName, "MM_CORE_STANDALONE") == 0)) { + ModuleType = EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER; + } else if ((strcmp (TypeName, "UEFI_APPLICATION") == 0) + || (strcmp (TypeName, "APPLICATION") == 0)) { + ModuleType = EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION; + } else if ((strcmp (TypeName, "DXE_RUNTIME_DRIVER") == 0) + || (strcmp (TypeName, "RT_DRIVER") == 0)) { + ModuleType = EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER; + } else if ((strcmp (TypeName, "DXE_SAL_DRIVER") == 0) + || (strcmp (TypeName, "SAL_RT_DRIVER") == 0)) { + ModuleType = EFI_IMAGE_SUBSYSTEM_SAL_RUNTIME_DRIVER; + } else { + fprintf (stderr, "ImageTool: Unknown EFI_FILETYPE = %s\n", TypeName); + return false; + } + + Image->HeaderInfo.Subsystem = ModuleType; + + return true; +} + +static +RETURN_STATUS +GenExecutable ( + IN const char *OutputFileName, + IN const char *InputFileName, + IN const char *FormatName, + IN const char *TypeName + ) +{ + UINT32 InputFileSize; + VOID *InputFile; + RETURN_STATUS Status; + bool Result; + void *OutputFile; + uint32_t OutputFileSize; + + InputFile = UserReadFile (InputFileName, &InputFileSize); + if (InputFile == NULL) { + fprintf (stderr, "ImageTool: Could not open %s: %s\n", InputFileName, strerror (errno)); + return RETURN_ABORTED; + } + + Status = ToolContextConstructPe (&mImageInfo, InputFile, InputFileSize); + if (Status == RETURN_UNSUPPORTED) { + Status = ScanElf (InputFile, InputFileSize, InputFileName); + } + + free (InputFile); - Status = ScanElf (ElfName, ModuleType); if (RETURN_ERROR (Status)) { + fprintf (stderr, "ImageTool: Could not parse input file %s - %llx\n", InputFileName, (unsigned long long)Status); return Status; } - Pe = ToolImageEmitPe (&mImageInfo, &PeSize); - if (Pe == NULL) { + if (TypeName != NULL) { + Result = ImageSetModuleType (&mImageInfo, TypeName); + if (!Result) { + ToolImageDestruct (&mImageInfo); + return RETURN_UNSUPPORTED; + } + } + + Result = CheckToolImage (&mImageInfo); + if (!Result) { ToolImageDestruct (&mImageInfo); - return RETURN_ABORTED; + return RETURN_UNSUPPORTED; + } + + if (strcmp (FormatName, "PE") == 0) { + OutputFile = ToolImageEmitPe (&mImageInfo, &OutputFileSize); + } else { + assert (false); } ToolImageDestruct (&mImageInfo); - UserWriteFile (PeName, Pe, PeSize); + if (OutputFile == NULL) { + return RETURN_ABORTED; + } - free (Pe); + UserWriteFile (OutputFileName, OutputFile, OutputFileSize); + + free (OutputFile); return RETURN_SUCCESS; } @@ -387,28 +418,15 @@ int main (int argc, const char *argv[]) return -1; } - if (strcmp (argv[1], "ElfToPe") == 0) { + if (strcmp (argv[1], "ElfToPe") == 0 || strcmp (argv[1], "PeXip") == 0) { if (argc < 5) { fprintf (stderr, "ImageTool: Command arguments are missing\n"); - fprintf (stderr, " Usage: ImageTool ElfToPe InputFile OutputFile ModuleType\n"); + fprintf (stderr, " Usage: ImageTool %s InputFile OutputFile ModuleType\n", argv[1]); raise (); return -1; } - Status = ElfToPe (argv[2], argv [3], argv[4]); - if (RETURN_ERROR (Status)) { - raise (); - return -1; - } - } else if (strcmp (argv[1], "PeXip") == 0) { - if (argc < 5) { - fprintf (stderr, "ImageTool: Command arguments are missing\n"); - fprintf (stderr, " Usage: ImageTool PeXip InputFile OutputFile ModuleType\n"); - raise (); - return -1; - } - - Status = PeXip (argv[2], argv[3], argv[4]); + Status = GenExecutable (argv[3], argv[2], "PE", argv[4]); if (RETURN_ERROR (Status)) { raise (); return -1; diff --git a/BaseTools/ImageTool/ImageTool.h b/BaseTools/ImageTool/ImageTool.h index 295930f8c1..dc261294d6 100644 --- a/BaseTools/ImageTool/ImageTool.h +++ b/BaseTools/ImageTool/ImageTool.h @@ -7,6 +7,8 @@ #ifndef IMAGE_TOOL_H #define IMAGE_TOOL_H +#include + #include #include #include @@ -152,8 +154,7 @@ RETURN_STATUS ToolContextConstructPe ( OUT image_tool_image_info_t *Image, IN const void *File, - IN size_t FileSize, - IN const char *ModuleType OPTIONAL + IN size_t FileSize ); bool @@ -169,8 +170,9 @@ ToolImageEmitPe ( RETURN_STATUS ScanElf ( - IN const char *ElfName, - IN const char *ModuleType + IN const void *File, + IN uint32_t FileSize, + IN const char *SymbolsPath ); RETURN_STATUS diff --git a/BaseTools/ImageTool/PeScan.c b/BaseTools/ImageTool/PeScan.c index 2752ceb769..381c9bc6b8 100644 --- a/BaseTools/ImageTool/PeScan.c +++ b/BaseTools/ImageTool/PeScan.c @@ -14,8 +14,7 @@ static bool ScanPeGetHeaderInfo ( OUT image_tool_header_info_t *HeaderInfo, - IN PE_COFF_LOADER_IMAGE_CONTEXT *Context, - IN const char *ModuleType OPTIONAL + IN PE_COFF_LOADER_IMAGE_CONTEXT *Context ) { assert (HeaderInfo != NULL); @@ -26,42 +25,7 @@ ScanPeGetHeaderInfo ( // FIXME: HeaderInfo->Machine = PeCoffGetMachine (Context); HeaderInfo->IsXip = true; - - if (ModuleType == NULL) { - HeaderInfo->Subsystem = PeCoffGetSubsystem (Context); - return true; - } - - if ((strcmp (ModuleType, "BASE") == 0) - || (strcmp (ModuleType, "SEC") == 0) - || (strcmp (ModuleType, "SECURITY_CORE") == 0) - || (strcmp (ModuleType, "PEI_CORE") == 0) - || (strcmp (ModuleType, "PEIM") == 0) - || (strcmp (ModuleType, "COMBINED_PEIM_DRIVER") == 0) - || (strcmp (ModuleType, "PIC_PEIM") == 0) - || (strcmp (ModuleType, "RELOCATABLE_PEIM") == 0) - || (strcmp (ModuleType, "DXE_CORE") == 0) - || (strcmp (ModuleType, "BS_DRIVER") == 0) - || (strcmp (ModuleType, "DXE_DRIVER") == 0) - || (strcmp (ModuleType, "DXE_SMM_DRIVER") == 0) - || (strcmp (ModuleType, "UEFI_DRIVER") == 0) - || (strcmp (ModuleType, "SMM_CORE") == 0) - || (strcmp (ModuleType, "MM_STANDALONE") == 0) - || (strcmp (ModuleType, "MM_CORE_STANDALONE") == 0)) { - HeaderInfo->Subsystem = EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER; - } else if ((strcmp (ModuleType, "UEFI_APPLICATION") == 0) - || (strcmp (ModuleType, "APPLICATION") == 0)) { - HeaderInfo->Subsystem = EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION; - } else if ((strcmp (ModuleType, "DXE_RUNTIME_DRIVER") == 0) - || (strcmp (ModuleType, "RT_DRIVER") == 0)) { - HeaderInfo->Subsystem = EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER; - } else if ((strcmp (ModuleType, "DXE_SAL_DRIVER") == 0) - || (strcmp (ModuleType, "SAL_RT_DRIVER") == 0)) { - HeaderInfo->Subsystem = EFI_IMAGE_SUBSYSTEM_SAL_RUNTIME_DRIVER; - } else { - fprintf (stderr, "ImageTool: Unknown EFI_FILETYPE = %s\n", ModuleType); - return false; - } + HeaderInfo->Subsystem = PeCoffGetSubsystem (Context); return true; } @@ -397,8 +361,7 @@ RETURN_STATUS ToolContextConstructPe ( OUT image_tool_image_info_t *Image, IN const void *File, - IN size_t FileSize, - IN const char *ModuleType OPTIONAL + IN size_t FileSize ) { PE_COFF_LOADER_IMAGE_CONTEXT Context; @@ -446,7 +409,7 @@ ToolContextConstructPe ( memset (Image, 0, sizeof (*Image)); - Result = ScanPeGetHeaderInfo (&Image->HeaderInfo, &Context, ModuleType); + Result = ScanPeGetHeaderInfo (&Image->HeaderInfo, &Context); if (!Result) { fprintf (stderr, "ImageTool: Could not retrieve header info\n"); ToolImageDestruct (Image);