audk/BaseTools/ImageTool/ImageToolEmit.c

207 lines
4.7 KiB
C

/** @file
Copyright (c) 2023, Marvin Häuser. All rights reserved.
SPDX-License-Identifier: BSD-3-Clause
**/
#include "ImageTool.h"
#include <Uefi/UefiBaseType.h>
#include <Library/UefiImageLib.h>
#include <stdlib.h>
#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 = "<unknown>";
}
// 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;
}