/** @file Copyright (c) 2023, Marvin Häuser. All rights reserved. SPDX-License-Identifier: BSD-3-Clause **/ #include "ImageTool.h" #include #include #include #include "ImageToolEmit.h" static RETURN_STATUS ToolContextConstruct ( OUT image_tool_image_info_t *ImageInfo, OUT int8_t *Format, IN const void *File, IN uint32_t FileSize, IN const char *SymbolsPath OPTIONAL ) { RETURN_STATUS Status; *Format = -1; Status = ToolContextConstructUefiImage ( ImageInfo, Format, File, FileSize ); #ifndef IMAGE_TOOL_DISABLE_ELF if (Status == RETURN_UNSUPPORTED) { Status = ScanElf (ImageInfo, File, FileSize, SymbolsPath); } #endif return Status; } static RETURN_STATUS ValidateOutputFile ( void *OutputFile, uint32_t OutputFileSize, const image_tool_image_info_t *ImageInfo ) { RETURN_STATUS Status; bool Result; image_tool_image_info_t OutputImageInfo; int8_t Format; Status = ToolContextConstruct ( &OutputImageInfo, &Format, OutputFile, OutputFileSize, NULL ); if (EFI_ERROR (Status)) { assert (Status == RETURN_OUT_OF_RESOURCES); return Status; } Result = CheckToolImage (&OutputImageInfo); // LCOV_EXCL_START if (!Result) { assert (false); ToolImageDestruct (&OutputImageInfo); return RETURN_UNSUPPORTED; } // LCOV_EXCL_STOP Result = ToolImageCompare (&OutputImageInfo, ImageInfo); ToolImageDestruct (&OutputImageInfo); // LCOV_EXCL_START if (!Result) { assert (false); return RETURN_VOLUME_CORRUPTED; } // LCOV_EXCL_STOP return RETURN_SUCCESS; } void * ToolImageEmit ( OUT uint32_t *OutputFileSize, IN const void *Buffer, IN uint32_t BufferSize, IN int8_t Format, IN int32_t Type, IN bool Relocate, IN uint64_t BaseAddress, IN const char *SymbolsPath OPTIONAL, IN bool Xip, IN bool Strip, IN bool FixedAddress ) { RETURN_STATUS Status; bool Success; image_tool_image_info_t ImageInfo; int8_t SourceFormat; void *OutputFile; Status = ToolContextConstruct ( &ImageInfo, &SourceFormat, Buffer, BufferSize, SymbolsPath ); // LCOV_EXCL_START if (SymbolsPath == NULL) { SymbolsPath = ""; } // LCOV_EXCL_STOP if (RETURN_ERROR (Status)) { fprintf (stderr, "ImageTool: Could not parse input file %s - %llx\n", SymbolsPath, (unsigned long long)Status); return NULL; } // LCOV_EXCL_START if (Format == -1) { Format = SourceFormat; if (Format == -1) { fprintf (stderr, "ImageTool: Unknown output format of file %s\n", SymbolsPath); ToolImageDestruct (&ImageInfo); return NULL; } } if (Type != -1) { ImageInfo.HeaderInfo.Subsystem = (uint16_t)Type; } // LCOV_EXCL_STOP ToolImageSortRelocs (&ImageInfo); Success = CheckToolImage (&ImageInfo); if (!Success) { DEBUG_RAISE (); ToolImageDestruct (&ImageInfo); return NULL; } if (Relocate) { Success = ToolImageRelocate (&ImageInfo, BaseAddress, 0); if (!Success) { fprintf (stderr, "ImageTool: Failed to relocate input file %s\n", SymbolsPath); ToolImageDestruct (&ImageInfo); return NULL; } } if (FixedAddress) { ImageInfo.HeaderInfo.FixedAddress = true; } OutputFile = NULL; // LCOV_EXCL_START if (Format == UefiImageFormatUe) { // LCOV_EXCL_STOP OutputFile = ToolImageEmitUe (&ImageInfo, OutputFileSize, Xip, Strip); } // LCOV_EXCL_START else if (Format == UefiImageFormatPe) { OutputFile = ToolImageEmitPe (&ImageInfo, OutputFileSize, Xip, Strip); } else { assert (false); } // LCOV_EXCL_STOP if (OutputFile == NULL) { DEBUG_RAISE (); ToolImageDestruct (&ImageInfo); return NULL; } if ((Format == UefiImageFormatUe) && Xip) { ToolImageDestruct (&ImageInfo); return OutputFile; } Status = ValidateOutputFile (OutputFile, *OutputFileSize, &ImageInfo); ToolImageDestruct (&ImageInfo); if (EFI_ERROR (Status)) { assert (Status == RETURN_OUT_OF_RESOURCES); FreePool (OutputFile); return NULL; } return OutputFile; }