ImageTool: Abstract executable generation

This commit is contained in:
Marvin Häuser 2023-04-02 15:09:31 +02:00
parent 75fcd420f6
commit 08778e2a3d
4 changed files with 127 additions and 183 deletions

View File

@ -180,8 +180,9 @@ SetHiiResourceHeader (
static static
RETURN_STATUS RETURN_STATUS
ReadElfFile ( ParseElfFile (
IN const char *Name IN const void *File,
IN uint32_t FileSize
) )
{ {
static const unsigned char Ident[] = { static const unsigned char Ident[] = {
@ -190,23 +191,18 @@ ReadElfFile (
const Elf_Shdr *Shdr; const Elf_Shdr *Shdr;
UINTN Offset; UINTN Offset;
UINT32 Index; UINT32 Index;
UINT32 FileSize;
char *Last; char *Last;
assert (Name != NULL); assert (File != NULL || FileSize == 0);
mEhdr = (Elf_Ehdr *)UserReadFile (Name, &FileSize); mEhdr = (Elf_Ehdr *)File;
if (mEhdr == NULL) {
fprintf (stderr, "ImageTool: Could not open %s: %s\n", Name, strerror (errno));
return RETURN_VOLUME_CORRUPTED;
}
// //
// Check header // Check header
// //
if ((FileSize < sizeof (*mEhdr)) if ((FileSize < sizeof (*mEhdr))
|| (memcmp (Ident, mEhdr->e_ident, sizeof (Ident)) != 0)) { || (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[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[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]); 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; Offset = (UINTN)mEhdr->e_shoff + Index * mEhdr->e_shentsize;
if (FileSize < (Offset + sizeof (*Shdr))) { 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; return RETURN_VOLUME_CORRUPTED;
} }
@ -249,7 +245,7 @@ ReadElfFile (
if ((Shdr->sh_type != SHT_NOBITS) if ((Shdr->sh_type != SHT_NOBITS)
&& ((FileSize < Shdr->sh_offset) || ((FileSize - Shdr->sh_offset) < Shdr->sh_size))) { && ((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; return RETURN_VOLUME_CORRUPTED;
} }
@ -764,20 +760,17 @@ CreateIntermediate (
RETURN_STATUS RETURN_STATUS
ScanElf ( ScanElf (
IN const char *ElfName, IN const void *File,
IN const char *ModuleType IN uint32_t FileSize,
IN const char *SymbolsPath
) )
{ {
RETURN_STATUS Status; RETURN_STATUS Status;
assert (ElfName != NULL); assert (File != NULL || FileSize == 0);
assert (ModuleType != NULL);
Status = ReadElfFile (ElfName); Status = ParseElfFile (File, FileSize);
if (RETURN_ERROR (Status)) { if (RETURN_ERROR (Status)) {
if (mEhdr != NULL) {
free (mEhdr);
}
return Status; return Status;
} }
@ -788,7 +781,7 @@ ScanElf (
mImageInfo.HeaderInfo.IsXip = true; mImageInfo.HeaderInfo.IsXip = true;
mImageInfo.SegmentInfo.SegmentAlignment = (uint32_t)mPeAlignment; mImageInfo.SegmentInfo.SegmentAlignment = (uint32_t)mPeAlignment;
mImageInfo.RelocInfo.RelocsStripped = false; mImageInfo.RelocInfo.RelocsStripped = false;
mImageInfo.DebugInfo.SymbolsPathLen = strlen (ElfName); mImageInfo.DebugInfo.SymbolsPathLen = strlen (SymbolsPath);
switch (mEhdr->e_machine) { switch (mEhdr->e_machine) {
#if defined(EFI_TARGET64) #if defined(EFI_TARGET64)
@ -808,58 +801,26 @@ ScanElf (
#endif #endif
default: default:
fprintf (stderr, "ImageTool: Unknown ELF architecture %d\n", mEhdr->e_machine); fprintf (stderr, "ImageTool: Unknown ELF architecture %d\n", mEhdr->e_machine);
free (mEhdr);
return RETURN_INCOMPATIBLE_VERSION; return RETURN_INCOMPATIBLE_VERSION;
} }
mImageInfo.DebugInfo.SymbolsPath = malloc (mImageInfo.DebugInfo.SymbolsPathLen + 1); mImageInfo.DebugInfo.SymbolsPath = malloc (mImageInfo.DebugInfo.SymbolsPathLen + 1);
if (mImageInfo.DebugInfo.SymbolsPath == NULL) { if (mImageInfo.DebugInfo.SymbolsPath == NULL) {
fprintf (stderr, "ImageTool: Could not allocate memory for Debug Data\n"); fprintf (stderr, "ImageTool: Could not allocate memory for Debug Data\n");
free (mEhdr);
return RETURN_OUT_OF_RESOURCES; 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) // There is no corresponding ELF property.
|| (strcmp (ModuleType, "SECURITY_CORE") == 0) //
|| (strcmp (ModuleType, "PEI_CORE") == 0) mImageInfo.HeaderInfo.Subsystem = 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;
}
Status = CreateIntermediate (); Status = CreateIntermediate ();
if (RETURN_ERROR (Status)) { if (RETURN_ERROR (Status)) {
ToolImageDestruct (&mImageInfo); ToolImageDestruct (&mImageInfo);
} }
free (mEhdr);
return Status; return Status;
} }

View File

@ -14,53 +14,6 @@
image_tool_image_info_t mImageInfo; 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 static
RETURN_STATUS RETURN_STATUS
HiiBin ( HiiBin (
@ -341,37 +294,115 @@ GetAcpi (
} }
static static
RETURN_STATUS bool
ElfToPe ( ImageSetModuleType (
IN const char *ElfName, OUT image_tool_image_info_t *Image,
IN const char *PeName, IN const char *TypeName
IN const char *ModuleType
) )
{ {
RETURN_STATUS Status; uint16_t ModuleType;
void *Pe;
uint32_t PeSize;
assert (ElfName != NULL); assert (Image != NULL);
assert (PeName != NULL);
assert (ModuleType != 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)) { if (RETURN_ERROR (Status)) {
fprintf (stderr, "ImageTool: Could not parse input file %s - %llx\n", InputFileName, (unsigned long long)Status);
return Status; return Status;
} }
Pe = ToolImageEmitPe (&mImageInfo, &PeSize); if (TypeName != NULL) {
if (Pe == NULL) { Result = ImageSetModuleType (&mImageInfo, TypeName);
if (!Result) {
ToolImageDestruct (&mImageInfo);
return RETURN_UNSUPPORTED;
}
}
Result = CheckToolImage (&mImageInfo);
if (!Result) {
ToolImageDestruct (&mImageInfo); ToolImageDestruct (&mImageInfo);
return RETURN_ABORTED; return RETURN_UNSUPPORTED;
}
if (strcmp (FormatName, "PE") == 0) {
OutputFile = ToolImageEmitPe (&mImageInfo, &OutputFileSize);
} else {
assert (false);
} }
ToolImageDestruct (&mImageInfo); ToolImageDestruct (&mImageInfo);
UserWriteFile (PeName, Pe, PeSize); if (OutputFile == NULL) {
return RETURN_ABORTED;
}
free (Pe); UserWriteFile (OutputFileName, OutputFile, OutputFileSize);
free (OutputFile);
return RETURN_SUCCESS; return RETURN_SUCCESS;
} }
@ -387,28 +418,15 @@ int main (int argc, const char *argv[])
return -1; return -1;
} }
if (strcmp (argv[1], "ElfToPe") == 0) { if (strcmp (argv[1], "ElfToPe") == 0 || strcmp (argv[1], "PeXip") == 0) {
if (argc < 5) { if (argc < 5) {
fprintf (stderr, "ImageTool: Command arguments are missing\n"); 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 (); raise ();
return -1; return -1;
} }
Status = ElfToPe (argv[2], argv [3], argv[4]); Status = GenExecutable (argv[3], argv[2], "PE", 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]);
if (RETURN_ERROR (Status)) { if (RETURN_ERROR (Status)) {
raise (); raise ();
return -1; return -1;

View File

@ -7,6 +7,8 @@
#ifndef IMAGE_TOOL_H #ifndef IMAGE_TOOL_H
#define IMAGE_TOOL_H #define IMAGE_TOOL_H
#include <Base.h>
#include <stdbool.h> #include <stdbool.h>
#include <errno.h> #include <errno.h>
#include <assert.h> #include <assert.h>
@ -152,8 +154,7 @@ RETURN_STATUS
ToolContextConstructPe ( ToolContextConstructPe (
OUT image_tool_image_info_t *Image, OUT image_tool_image_info_t *Image,
IN const void *File, IN const void *File,
IN size_t FileSize, IN size_t FileSize
IN const char *ModuleType OPTIONAL
); );
bool bool
@ -169,8 +170,9 @@ ToolImageEmitPe (
RETURN_STATUS RETURN_STATUS
ScanElf ( ScanElf (
IN const char *ElfName, IN const void *File,
IN const char *ModuleType IN uint32_t FileSize,
IN const char *SymbolsPath
); );
RETURN_STATUS RETURN_STATUS

View File

@ -14,8 +14,7 @@ static
bool bool
ScanPeGetHeaderInfo ( ScanPeGetHeaderInfo (
OUT image_tool_header_info_t *HeaderInfo, OUT image_tool_header_info_t *HeaderInfo,
IN PE_COFF_LOADER_IMAGE_CONTEXT *Context, IN PE_COFF_LOADER_IMAGE_CONTEXT *Context
IN const char *ModuleType OPTIONAL
) )
{ {
assert (HeaderInfo != NULL); assert (HeaderInfo != NULL);
@ -26,42 +25,7 @@ ScanPeGetHeaderInfo (
// FIXME: // FIXME:
HeaderInfo->Machine = PeCoffGetMachine (Context); HeaderInfo->Machine = PeCoffGetMachine (Context);
HeaderInfo->IsXip = true; HeaderInfo->IsXip = true;
HeaderInfo->Subsystem = PeCoffGetSubsystem (Context);
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;
}
return true; return true;
} }
@ -397,8 +361,7 @@ RETURN_STATUS
ToolContextConstructPe ( ToolContextConstructPe (
OUT image_tool_image_info_t *Image, OUT image_tool_image_info_t *Image,
IN const void *File, IN const void *File,
IN size_t FileSize, IN size_t FileSize
IN const char *ModuleType OPTIONAL
) )
{ {
PE_COFF_LOADER_IMAGE_CONTEXT Context; PE_COFF_LOADER_IMAGE_CONTEXT Context;
@ -446,7 +409,7 @@ ToolContextConstructPe (
memset (Image, 0, sizeof (*Image)); memset (Image, 0, sizeof (*Image));
Result = ScanPeGetHeaderInfo (&Image->HeaderInfo, &Context, ModuleType); Result = ScanPeGetHeaderInfo (&Image->HeaderInfo, &Context);
if (!Result) { if (!Result) {
fprintf (stderr, "ImageTool: Could not retrieve header info\n"); fprintf (stderr, "ImageTool: Could not retrieve header info\n");
ToolImageDestruct (Image); ToolImageDestruct (Image);