BaseTools: Replaced GenFw with ImageTool and MicroTool.

This commit is contained in:
Mikhail Krichanov 2023-05-09 17:49:27 +03:00
parent 29ab261538
commit 1e0cdd036d
48 changed files with 5002 additions and 886 deletions

6
.gitmodules vendored
View File

@ -16,10 +16,14 @@
[submodule "BaseTools/Source/C/BrotliCompress/brotli"]
path = BaseTools/Source/C/BrotliCompress/brotli
url = https://github.com/google/brotli
ignore = untracked
ignore = untracked
[submodule "RedfishPkg/Library/JsonLib/jansson"]
path = RedfishPkg/Library/JsonLib/jansson
url = https://github.com/akheron/jansson
[submodule "UnitTestFrameworkPkg/Library/GoogleTestLib/googletest"]
path = UnitTestFrameworkPkg/Library/GoogleTestLib/googletest
url = https://github.com/google/googletest.git
[submodule "OpenCorePkg"]
path = OpenCorePkg
url = https://github.com/acidanthera/OpenCorePkg.git
branch = SecurePeAndImageTool-202211-rebase

View File

@ -26,12 +26,9 @@
DEFINE FD_NUM_BLOCKS = 0x300
!endif
[BuildOptions.common.EDKII.DXE_CORE,BuildOptions.common.EDKII.DXE_DRIVER,BuildOptions.common.EDKII.UEFI_DRIVER,BuildOptions.common.EDKII.UEFI_APPLICATION]
GCC:*_*_*_DLINK_FLAGS = -z common-page-size=0x1000
[BuildOptions.common.EDKII.DXE_RUNTIME_DRIVER]
GCC:*_*_ARM_DLINK_FLAGS = -z common-page-size=0x1000
GCC:*_*_AARCH64_DLINK_FLAGS = -z common-page-size=0x10000
GCC:*_*_ARM_DLINK_FLAGS = -z max-page-size=0x1000
GCC:*_*_AARCH64_DLINK_FLAGS = -z max-page-size=0x10000
[LibraryClasses.common]
!if $(TARGET) == RELEASE

View File

@ -18,4 +18,8 @@ Source/C/bin/
Source/C/libs/
Bin/Win32
Lib
BaseToolsBuild/
BaseToolsBuild/
ImageTool/ImageTool
ImageTool/ImageTool32
ImageTool/ImageTool64
MicroTool/MicroTool

View File

@ -0,0 +1,43 @@
#!/usr/bin/env bash
#
# Copyright (c) 2022, Mikhail Krichanov. All rights reserved.
# SPDX-License-Identifier: BSD-3-Clause
#
full_cmd=${BASH_SOURCE:-$0} # see http://mywiki.wooledge.org/BashFAQ/028 for a discussion of why $0 is not a good choice here
dir=$(dirname "$full_cmd")
cmd=${full_cmd##*/}
if [ -n "$WORKSPACE" ] && [ -e "$EDK_TOOLS_PATH/ImageTool" ]
then
if [ $1 == 'IA32' ] || [ $1 == 'ARM' ]
then
if [ ! -e "$EDK_TOOLS_PATH/ImageTool/ImageTool32" ]
then
echo "BaseTools C Tool binary was not found (ImageTool32)"
echo "You may need to run:"
echo " make -C $EDK_TOOLS_PATH/ImageTool"
else
shift
exec "$EDK_TOOLS_PATH/ImageTool/ImageTool32" "$@"
fi
elif [ $1 == 'X64' ] || [ $1 == 'AARCH64' ]
then
if [ ! -e "$EDK_TOOLS_PATH/ImageTool/ImageTool64" ]
then
echo "BaseTools C Tool binary was not found (ImageTool64)"
echo "You may need to run:"
echo " make -C $EDK_TOOLS_PATH/ImageTool"
else
shift
exec "$EDK_TOOLS_PATH/ImageTool/ImageTool64" "$@"
fi
else
echo "ImageTool for $1 is not supported"
exit 127
fi
else
echo "Unable to find the real '$cmd' to run"
echo "This message was printed by"
echo " $0"
exit 127
fi

View File

@ -0,0 +1,25 @@
#!/usr/bin/env bash
#
# Copyright (c) 2022, Mikhail Krichanov. All rights reserved.
# SPDX-License-Identifier: BSD-3-Clause
#
full_cmd=${BASH_SOURCE:-$0} # see http://mywiki.wooledge.org/BashFAQ/028 for a discussion of why $0 is not a good choice here
dir=$(dirname "$full_cmd")
cmd=${full_cmd##*/}
if [ -n "$WORKSPACE" ] && [ -e "$EDK_TOOLS_PATH/MicroTool" ]
then
if [ ! -e "$EDK_TOOLS_PATH/MicroTool/MicroTool" ]
then
echo "BaseTools C Tool binary was not found (MicroTool)"
echo "You may need to run:"
echo " make -C $EDK_TOOLS_PATH/MicroTool"
else
exec "$EDK_TOOLS_PATH/MicroTool/MicroTool" "$@"
fi
else
echo "Unable to find the real '$cmd' to run"
echo "This message was printed by"
echo " $0"
exit 127
fi

View File

@ -0,0 +1,30 @@
::
:: Copyright (c) 2022, Mikhail Krichanov. All rights reserved.
:: SPDX-License-Identifier: BSD-3-Clause
::
@echo off
set args=%2
:start
shift /2
if "%2"=="" goto done
set args=%args% %2
goto start
:done
if "%1%"=="IA32" (
call ImageTool32.exe %args%
exit
)
if "%1%"=="ARM" (
call ImageTool32.exe %args%
exit
)
if "%1%"=="X64" (
call ImageTool64.exe %args%
exit
)
if "%1%"=="AARCH64" (
call ImageTool64.exe %args%
exit
)
echo ImageTool for %1% is not supported

View File

@ -0,0 +1,6 @@
::
:: Copyright (c) 2022, Mikhail Krichanov. All rights reserved.
:: SPDX-License-Identifier: BSD-3-Clause
::
@echo off
call MicroTool.exe %*

View File

@ -272,7 +272,14 @@
<Command.GCC>
$(RM) ${dst}
"$(SLINK)" cr ${dst} $(SLINK_FLAGS) @$(OBJECT_FILES_LIST)
<Command.RVCT>
"$(SLINK)" $(SLINK_FLAGS) ${dst} --via $(OBJECT_FILES_LIST)
<Command.RVCTCYGWIN>
# $(OBJECT_FILES_LIST) has wrong paths for cygwin
"$(SLINK)" $(SLINK_FLAGS) ${dst} $(OBJECT_FILES)
<Command.XCODE>
"$(SLINK)" $(SLINK_FLAGS) ${dst} -filelist $(OBJECT_FILES_LIST)
@ -295,12 +302,11 @@
<Command.GCC>
"$(DLINK)" -o ${dst} $(DLINK_FLAGS) -Wl,--start-group,@$(STATIC_LIBRARY_FILES_LIST),--end-group $(CC_FLAGS) $(DLINK2_FLAGS)
"$(OBJCOPY)" $(OBJCOPY_FLAGS) ${dst}
<Command.XCODE>
"$(DLINK)" $(DLINK_FLAGS) -o ${dst} $(DLINK_SPATH) -filelist $(STATIC_LIBRARY_FILES_LIST) $(DLINK2_FLAGS)
[Static-Library-File.SEC.AARCH64, Static-Library-File.PEI_CORE.AARCH64, Static-Library-File.PEIM.AARCH64,Static-Library-File.SEC.ARM, Static-Library-File.PEI_CORE.ARM, Static-Library-File.PEIM.ARM]
<InputFile>
*.lib
@ -313,8 +319,6 @@
<Command.GCC>
"$(DLINK)" -o ${dst} $(DLINK_FLAGS) $(DLINK_XIPFLAGS) -Wl,--start-group,@$(STATIC_LIBRARY_FILES_LIST),--end-group $(CC_FLAGS) $(CC_XIPFLAGS) $(DLINK2_FLAGS)
"$(OBJCOPY)" $(OBJCOPY_FLAGS) ${dst}
[Static-Library-File.USER_DEFINED, Static-Library-File.HOST_APPLICATION]
<InputFile>
@ -334,8 +338,8 @@
<Command.XCODE>
"$(DLINK)" -o ${dst} $(DLINK_FLAGS) $(DLINK_SPATH) -filelist $(STATIC_LIBRARY_FILES_LIST) $(DLINK2_FLAGS)
[Dynamic-Library-File]
<InputFile>
?.dll
@ -345,32 +349,33 @@
$(OUTPUT_DIR)(+)$(MODULE_NAME).map
<Command.MSFT, Command.INTEL, Command.CLANGPDB>
"$(GENFW)" -e $(MODULE_TYPE) -o ${dst} ${src} $(GENFW_FLAGS)
ImageTool $(ARCH) PeXip ${src} ${dst} $(MODULE_TYPE)
$(CP) ${dst} $(DEBUG_DIR)
$(CP) ${dst} $(BIN_DIR)(+)$(MODULE_NAME_GUID).efi
-$(CP) $(DEBUG_DIR)(+)*.map $(OUTPUT_DIR)
-$(CP) $(DEBUG_DIR)(+)*.pdb $(OUTPUT_DIR)
<Command.GCC>
-$(CP) $(DEBUG_DIR)(+)*.pdb $(OUTPUT_DIR)
<Command.GCC, Command.CLANGGCC>
$(CP) ${src} $(DEBUG_DIR)(+)$(MODULE_NAME).debug
$(OBJCOPY) $(OBJCOPY_STRIPFLAG) ${src}
#
#The below 2 lines are only needed for UNIXGCC tool chain, which generates PE image directly
# The below 2 lines are only needed for UNIXGCC tool chain, which generates PE image directly
#
-$(OBJCOPY) $(OBJCOPY_ADDDEBUGFLAG) ${src}
-$(CP) $(DEBUG_DIR)(+)$(MODULE_NAME).debug $(BIN_DIR)(+)$(MODULE_NAME_GUID).debug
ImageTool $(ARCH) ElfToPe ${src} ${dst} $(MODULE_TYPE)
"$(GENFW)" -e $(MODULE_TYPE) -o ${dst} ${src} $(GENFW_FLAGS)
$(CP) ${dst} $(DEBUG_DIR)
$(CP) ${dst} $(BIN_DIR)(+)$(MODULE_NAME_GUID).efi
-$(CP) $(DEBUG_DIR)(+)*.map $(OUTPUT_DIR)
<Command.XCODE>
# tool to convert Mach-O to PE/COFF
"$(MTOC)" -subsystem $(MODULE_TYPE) $(MTOC_FLAGS) ${src} $(DEBUG_DIR)(+)$(MODULE_NAME).pecoff
# create symbol file for GDB debug
-$(DSYMUTIL) ${src}
"$(GENFW)" -e $(MODULE_TYPE) -o ${dst} $(DEBUG_DIR)(+)$(MODULE_NAME).pecoff $(GENFW_FLAGS)
ImageTool $(ARCH) PeXip $(DEBUG_DIR)(+)$(MODULE_NAME).pecoff ${dst} $(MODULE_TYPE)
$(CP) ${dst} $(DEBUG_DIR)
$(CP) ${dst} $(BIN_DIR)(+)$(MODULE_NAME_GUID).efi
-$(CP) $(DEBUG_DIR)(+)*.map $(OUTPUT_DIR)
@ -404,14 +409,14 @@
<Command.MSFT, Command.INTEL>
Trim --asl-file --asl-deps -o $(OUTPUT_DIR)(+)${s_dir}(+)${s_base}.i -i $(INC_LIST) ${src}
"$(ASLPP)" $(DEPS_FLAGS) $(ASLPP_FLAGS) $(INC) /I${s_path} $(OUTPUT_DIR)(+)${s_dir}(+)${s_base}.i > $(OUTPUT_DIR)(+)${s_dir}(+)${s_base}.iii
Trim --source-code -l -o $(OUTPUT_DIR)(+)${s_dir}(+)${s_base}.iiii $(OUTPUT_DIR)(+)${s_dir}(+)${s_base}.iii
Trim --source-code -l -o $(OUTPUT_DIR)(+)${s_dir}(+)${s_base}.iiii $(OUTPUT_DIR)(+)${s_dir}(+)${s_base}.iii
"$(ASL)" $(ASL_FLAGS) $(ASL_OUTFLAGS)${dst} $(OUTPUT_DIR)(+)${s_dir}(+)${s_base}.iiii
$(CP) $(OUTPUT_DIR)(+)${s_dir}(+)${s_base}.aml $(OUTPUT_DIR)(+)${s_dir}(+)${s_base}.amli
<Command.GCC>
Trim --asl-file --asl-deps -o $(OUTPUT_DIR)(+)${s_dir}(+)${s_base}.i -i $(INC_LIST) ${src}
"$(ASLPP)" $(DEPS_FLAGS) $(ASLPP_FLAGS) $(INC) -I${s_path} $(OUTPUT_DIR)(+)${s_dir}(+)${s_base}.i > $(OUTPUT_DIR)(+)${s_dir}(+)${s_base}.iii
Trim --source-code -l -o $(OUTPUT_DIR)(+)${s_dir}(+)${s_base}.iiii $(OUTPUT_DIR)(+)${s_dir}(+)${s_base}.iii
Trim --source-code -l -o $(OUTPUT_DIR)(+)${s_dir}(+)${s_base}.iiii $(OUTPUT_DIR)(+)${s_dir}(+)${s_base}.iii
"$(ASL)" $(ASL_FLAGS) $(ASL_OUTFLAGS)${dst} $(OUTPUT_DIR)(+)${s_dir}(+)${s_base}.iiii
$(CP) $(OUTPUT_DIR)(+)${s_dir}(+)${s_base}.aml $(OUTPUT_DIR)(+)${s_dir}(+)${s_base}.amli
@ -438,12 +443,12 @@
<Command.MSFT, Command.INTEL>
"$(ASLCC)" $(DEPS_FLAGS) /Fo$(OUTPUT_DIR)(+)${s_dir}(+)${s_base}.obj $(ASLCC_FLAGS) $(DEPS_FLAGS) $(INC) ${src}
"$(ASLDLINK)" /OUT:$(OUTPUT_DIR)(+)${s_dir}(+)${s_base}.dll $(ASLDLINK_FLAGS) $(OUTPUT_DIR)(+)${s_dir}(+)${s_base}.obj
"$(GENFW)" -o ${dst} -c $(OUTPUT_DIR)(+)${s_dir}(+)${s_base}.dll $(GENFW_FLAGS)
ImageTool $(ARCH) GetAcpi $(OUTPUT_DIR)(+)${s_dir}(+)${s_base}.dll ${dst}
<Command.GCC>
"$(ASLCC)" $(DEPS_FLAGS) -c -o $(OUTPUT_DIR)(+)${s_dir}(+)${s_base}.obj $(CC_FLAGS) $(ASLCC_FLAGS) $(DEPS_FLAGS) $(INC) ${src}
"$(ASLDLINK)" -o $(OUTPUT_DIR)(+)${s_dir}(+)${s_base}.dll $(ASLDLINK_FLAGS) $(OUTPUT_DIR)(+)${s_dir}(+)${s_base}.obj
"$(GENFW)" -o ${dst} -c $(OUTPUT_DIR)(+)${s_dir}(+)${s_base}.dll $(GENFW_FLAGS)
ImageTool $(ARCH) GetAcpi $(OUTPUT_DIR)(+)${s_dir}(+)${s_base}.dll ${dst}
[Acpi-Table-Code-File]
<InputFile>
@ -458,25 +463,24 @@
<Command.MSFT, Command.INTEL>
"$(ASLCC)" $(DEPS_FLAGS) /Fo$(OUTPUT_DIR)(+)${s_dir}(+)${s_base}.obj $(ASLCC_FLAGS) $(DEPS_FLAGS) $(INC) ${src}
"$(ASLDLINK)" /OUT:$(OUTPUT_DIR)(+)${s_dir}(+)${s_base}.dll $(ASLDLINK_FLAGS) $(OUTPUT_DIR)(+)${s_dir}(+)${s_base}.obj
"$(GENFW)" -o ${dst} -c $(OUTPUT_DIR)(+)${s_dir}(+)${s_base}.dll $(GENFW_FLAGS)
ImageTool $(ARCH) GetAcpi $(OUTPUT_DIR)(+)${s_dir}(+)${s_base}.dll ${dst}
<Command.GCC>
"$(ASLCC)" $(DEPS_FLAGS) -c -o $(OUTPUT_DIR)(+)${s_dir}(+)${s_base}.obj $(CC_FLAGS) $(ASLCC_FLAGS) $(DEPS_FLAGS) $(INC) ${src}
"$(ASLDLINK)" -o $(OUTPUT_DIR)(+)${s_dir}(+)${s_base}.dll $(ASLDLINK_FLAGS) $(OUTPUT_DIR)(+)${s_dir}(+)${s_base}.obj
"$(GENFW)" -o ${dst} -c $(OUTPUT_DIR)(+)${s_dir}(+)${s_base}.dll $(GENFW_FLAGS)
"$(ASLDLINK)" -o $(OUTPUT_DIR)(+)${s_dir}(+)${s_base}.dll $(ASLDLINK_FLAGS) $(OUTPUT_DIR)(+)${s_dir}(+)${s_base}.obj $(CC_FLAGS) $(ASLCC_FLAGS)
ImageTool $(ARCH) GetAcpi $(OUTPUT_DIR)(+)${s_dir}(+)${s_base}.dll ${dst}
<Command.CLANGPDB>
"$(ASLCC)" $(DEPS_FLAGS) -c -o $(OUTPUT_DIR)(+)${s_dir}(+)${s_base}.obj $(CC_FLAGS) $(ASLCC_FLAGS) $(DEPS_FLAGS) $(INC) ${src}
"$(ASLDLINK)" /OUT:$(OUTPUT_DIR)(+)${s_dir}(+)${s_base}.dll $(ASLDLINK_FLAGS) $(OUTPUT_DIR)(+)${s_dir}(+)${s_base}.obj
"$(GENFW)" -o ${dst} -c $(OUTPUT_DIR)(+)${s_dir}(+)${s_base}.dll $(GENFW_FLAGS)
ImageTool $(ARCH) GetAcpi $(OUTPUT_DIR)(+)${s_dir}(+)${s_base}.dll ${dst}
<Command.XCODE>
<Command.XCODE>
"$(ASLCC)" $(DEPS_FLAGS) -o $(OUTPUT_DIR)(+)${s_dir}(+)${s_base}.obj $(ASLCC_FLAGS) $(DEPS_FLAGS) $(INC) ${src}
"$(ASLDLINK)" -o $(OUTPUT_DIR)(+)${s_dir}(+)${s_base}.dll $(ASLDLINK_FLAGS) $(OUTPUT_DIR)(+)${s_dir}(+)${s_base}.obj
"$(MTOC)" -subsystem $(MODULE_TYPE) $(MTOC_FLAGS) $(OUTPUT_DIR)(+)${s_dir}(+)${s_base}.dll $(OUTPUT_DIR)(+)${s_dir}(+)${s_base}.pecoff
"$(GENFW)" -o ${dst} -c $(OUTPUT_DIR)(+)${s_dir}(+)${s_base}.pecoff $(GENFW_FLAGS)
ImageTool $(ARCH) GetAcpi $(OUTPUT_DIR)(+)${s_dir}(+)${s_base}.pecoff ${dst}
[Masm16-Code-File]
<InputFile>
?.asm16, ?.Asm16, ?.ASM16, ?.s16, ?.S16
@ -501,7 +505,7 @@
Trim --source-code -o ${d_path}(+)${s_base}.iii ${d_path}(+)${s_base}.ii
"$(ASM)" -o $(OUTPUT_DIR)(+)${s_dir}(+)${s_base}.obj $(ASM_FLAGS) $(INC) ${d_path}(+)${s_base}.iii
"$(DLINK)" -o ${dst} $(DLINK_FLAGS) --start-group $(DLINK_SPATH) $(LIBS) $(OUTPUT_DIR)(+)${s_dir}(+)${s_base}.obj --end-group
<Command.XCODE>
Trim --asm-file -o ${d_path}(+)${s_base}.i -i $(INC_LIST) ${src}
"$(PP)" $(DEPS_FLAGS) $(PP_FLAGS) $(INC) ${src} > ${d_path}(+)${s_base}.ii
@ -509,7 +513,7 @@
"$(ASM)" -o $(OUTPUT_DIR)(+)${s_dir}(+)${s_base}.obj $(ASM_FLAGS) $(INC) ${d_path}(+)${s_base}.iii
"$(SLINK)" $(SLINK_FLAGS) $(OUTPUT_DIR)(+)${s_dir}(+)${s_base}.slib $(OUTPUT_DIR)(+)${s_dir}(+)${s_base}.obj
otool -t $(OUTPUT_DIR)(+)${s_dir}(+)${s_base}.slib | hex2bin.py ${dst}
[Nasm-to-Binary-Code-File]
<InputFile>
@ -537,7 +541,7 @@
$(OUTPUT_DIR)(+)${s_base}.mcb
<Command>
"$(GENFW)" -o ${dst} -m ${src} $(GENFW_FLAGS)
MicroTool TxtToBin ${src} ${dst}
[Microcode-Binary-File]
<InputFile>
@ -550,7 +554,7 @@
$(OUTPUT_DIR)(+)$(MODULE_NAME).bin
<Command>
"$(GENFW)" -o ${dst} -j $(MICROCODE_BINARY_FILES) $(GENFW_FLAGS)
MicroTool Merge ${dst} $(MICROCODE_BINARY_FILES)
-$(CP) ${dst} $(BIN_DIR)(+)$(MODULE_NAME_GUID).bin
[EFI-Image-File]
@ -639,13 +643,17 @@
<OutputFile.XCODE>
$(OUTPUT_DIR)(+)$(MODULE_NAME)hii.rc
<Command.MSFT, Command.INTEL, Command.CLANGPDB>
"$(GENFW)" -o $(OUTPUT_DIR)(+)$(MODULE_NAME)hii.rc -g $(MODULE_GUID) --hiipackage $(HII_BINARY_PACKAGES) $(GENFW_FLAGS)
<Command.CLANGPDB>
ImageTool $(ARCH) HiiBinPe $(OUTPUT_DIR)(+)$(MODULE_NAME)hii.rc $(MODULE_GUID) $(HII_BINARY_PACKAGES)
"$(RC)" /Fo${dst} -- $(OUTPUT_DIR)(+)$(MODULE_NAME)hii.rc
<Command.MSFT, Command.INTEL>
ImageTool $(ARCH) HiiBinPe $(OUTPUT_DIR)(+)$(MODULE_NAME)hii.rc $(MODULE_GUID) $(HII_BINARY_PACKAGES)
"$(RC)" /Fo${dst} $(OUTPUT_DIR)(+)$(MODULE_NAME)hii.rc
<Command.GCC, Command.CLANGGCC>
"$(GENFW)" -o $(OUTPUT_DIR)(+)$(MODULE_NAME)hii.rc -g $(MODULE_GUID) --hiibinpackage $(HII_BINARY_PACKAGES) $(GENFW_FLAGS)
ImageTool $(ARCH) HiiBinElf $(OUTPUT_DIR)(+)$(MODULE_NAME)hii.rc $(MODULE_GUID) $(HII_BINARY_PACKAGES)
"$(RC)" $(RC_FLAGS) $(OUTPUT_DIR)(+)$(MODULE_NAME)hii.rc ${dst}
<Command.XCODE>
"$(GENFW)" -o $(OUTPUT_DIR)(+)$(MODULE_NAME)hii.rc -g $(MODULE_GUID) --hiibinpackage $(HII_BINARY_PACKAGES) $(GENFW_FLAGS)
ImageTool $(ARCH) HiiBinElf $(OUTPUT_DIR)(+)$(MODULE_NAME)hii.rc $(MODULE_GUID) $(HII_BINARY_PACKAGES)

File diff suppressed because it is too large Load Diff

View File

@ -10,7 +10,7 @@ all: subdirs
LANGUAGES = C Python
SOURCE_SUBDIRS := $(patsubst %,Source/%,$(sort $(LANGUAGES)))
SUBDIRS := $(SOURCE_SUBDIRS) Tests
SUBDIRS := $(SOURCE_SUBDIRS) Tests ImageTool MicroTool
CLEAN_SUBDIRS := $(patsubst %,%-clean,$(sort $(SUBDIRS)))
.PHONY: subdirs $(SUBDIRS)

View File

@ -0,0 +1,301 @@
/** @file
Copyright (c) 2022, Mikhail Krichanov. All rights reserved.
SPDX-License-Identifier: BSD-3-Clause
**/
#include "ImageTool.h"
static
EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY *
CreateEntry (
IN UINT8 *HiiSectionHeader,
IN OUT UINT32 *HiiSectionOffset,
IN BOOLEAN DataIsDirectory
)
{
EFI_IMAGE_RESOURCE_DIRECTORY *RDir;
EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY *Entry;
assert (HiiSectionHeader != NULL);
assert (HiiSectionOffset != NULL);
RDir = (EFI_IMAGE_RESOURCE_DIRECTORY *)(HiiSectionHeader + *HiiSectionOffset);
*HiiSectionOffset += sizeof (EFI_IMAGE_RESOURCE_DIRECTORY);
RDir->NumberOfNamedEntries = 1;
Entry = (EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY *)(HiiSectionHeader + *HiiSectionOffset);
*HiiSectionOffset += sizeof (EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY);
Entry->u1.s.NameIsString = 1;
if (DataIsDirectory) {
Entry->u2.s.DataIsDirectory = 1;
Entry->u2.s.OffsetToDirectory = *HiiSectionOffset;
}
return Entry;
}
static
void
CreateStringEntry (
IN OUT EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY *Entry,
IN UINT8 *HiiSectionHeader,
IN OUT UINT32 *HiiSectionOffset,
IN CHAR16 *String
)
{
EFI_IMAGE_RESOURCE_DIRECTORY_STRING *RDStr;
assert (Entry != NULL);
assert (HiiSectionHeader != NULL);
assert (HiiSectionOffset != NULL);
assert (String != NULL);
Entry->u1.s.NameOffset = *HiiSectionOffset;
RDStr = (EFI_IMAGE_RESOURCE_DIRECTORY_STRING *)(HiiSectionHeader + *HiiSectionOffset);
RDStr->Length = (UINT16)StrLen (String);
memcpy (RDStr->String, String, RDStr->Length * sizeof (RDStr->String[0]));
*HiiSectionOffset += sizeof (*RDStr) + RDStr->Length * sizeof (RDStr->String[0]);
}
static
UINT8 *
CreateHiiResouceSectionHeader (
OUT UINT32 *HiiHeaderSize,
IN UINT32 HiiDataSize
)
{
UINT32 HiiSectionHeaderSize;
UINT32 HiiSectionOffset;
UINT8 *HiiSectionHeader;
EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY *TypeRDirEntry;
EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY *NameRDirEntry;
EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY *LangRDirEntry;
EFI_IMAGE_RESOURCE_DATA_ENTRY *ResourceDataEntry;
assert (HiiHeaderSize != NULL);
//
// Calculate the total size for the resource header (include Type, Name and Language)
// then allocate memory for whole Hii file.
//
HiiSectionHeaderSize = 3 * (sizeof (EFI_IMAGE_RESOURCE_DIRECTORY) + sizeof (EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY)
+ sizeof (EFI_IMAGE_RESOURCE_DIRECTORY_STRING) + 3 * sizeof (CHAR16)) + sizeof (EFI_IMAGE_RESOURCE_DATA_ENTRY);
HiiSectionHeader = calloc (1, HiiSectionHeaderSize + HiiDataSize);
if (HiiSectionHeader == NULL) {
fprintf (stderr, "ImageTool: Could not allocate memory for Hii\n");
return NULL;
}
HiiSectionOffset = 0;
//
// Create Type, Name, Language entries
//
TypeRDirEntry = CreateEntry (HiiSectionHeader, &HiiSectionOffset, TRUE);
NameRDirEntry = CreateEntry (HiiSectionHeader, &HiiSectionOffset, TRUE);
LangRDirEntry = CreateEntry (HiiSectionHeader, &HiiSectionOffset, FALSE);
//
// Create string entry for Type, Name, Language
//
CreateStringEntry (TypeRDirEntry, HiiSectionHeader, &HiiSectionOffset, L"HII");
CreateStringEntry (NameRDirEntry, HiiSectionHeader, &HiiSectionOffset, L"EFI");
CreateStringEntry (LangRDirEntry, HiiSectionHeader, &HiiSectionOffset, L"BIN");
//
// Create Leaf data
//
LangRDirEntry->u2.OffsetToData = HiiSectionOffset;
ResourceDataEntry = (EFI_IMAGE_RESOURCE_DATA_ENTRY *)(HiiSectionHeader + HiiSectionOffset);
HiiSectionOffset += sizeof (EFI_IMAGE_RESOURCE_DATA_ENTRY);
ResourceDataEntry->OffsetToData = HiiSectionOffset;
ResourceDataEntry->Size = HiiDataSize;
*HiiHeaderSize = HiiSectionHeaderSize;
return HiiSectionHeader;
}
RETURN_STATUS
ConstructHii (
IN const char *FileNames[],
IN UINT32 NumOfFiles,
IN GUID *HiiGuid,
OUT void **Hii,
OUT UINT32 *HiiSize,
IN BOOLEAN IsElf
)
{
UINT8 *HiiPackageDataPointer;
EFI_HII_PACKAGE_LIST_HEADER HiiPackageListHeader;
EFI_HII_PACKAGE_HEADER *HiiPackageHeader;
EFI_IFR_FORM_SET *IfrFormSet;
EFI_HII_PACKAGE_HEADER EndPackage;
UINT32 HiiSectionHeaderSize;
UINT8 *HiiSectionHeader;
const char *HiiPackageRCFileHeader;
UINT32 Index;
UINT32 Total;
UINT8 *Buffer;
UINT8 *BufferStart;
UINT32 Step;
void *File;
UINT32 FileSize;
UINT8 NumberOfFormPackages;
UINT32 TempSize;
assert (Hii != NULL);
assert (HiiGuid != NULL);
assert (FileNames != NULL);
NumberOfFormPackages = 0;
EndPackage.Length = sizeof (EFI_HII_PACKAGE_HEADER);
EndPackage.Type = EFI_HII_PACKAGE_END;
HiiPackageListHeader.PackageLength = sizeof (EFI_HII_PACKAGE_LIST_HEADER) + sizeof (EndPackage);
for (Index = 0; Index < NumOfFiles; ++Index) {
File = UserReadFile (FileNames[Index], &FileSize);
if (File == NULL) {
fprintf (stderr, "ImageTool: Could not open %s: %s\n", FileNames[Index], strerror (errno));
return RETURN_ABORTED;
}
HiiPackageHeader = (EFI_HII_PACKAGE_HEADER *)File;
if (HiiPackageHeader->Type == EFI_HII_PACKAGE_FORMS) {
if (HiiPackageHeader->Length != FileSize) {
fprintf (stderr, "ImageTool: Wrong package size in HII package file %s\n", FileNames[Index]);
free (File);
return RETURN_ABORTED;
}
if (IsZeroGuid (HiiGuid)) {
IfrFormSet = (EFI_IFR_FORM_SET *)(HiiPackageHeader + 1);
CopyGuid (HiiGuid, &IfrFormSet->Guid);
}
++NumberOfFormPackages;
}
HiiPackageListHeader.PackageLength += FileSize;
free (File);
}
if (NumberOfFormPackages > 1) {
fprintf (stderr, "ImageTool: The input HII packages contain more than one HII Form package\n");
return RETURN_INVALID_PARAMETER;
}
if (IsZeroGuid (HiiGuid)) {
fprintf (stderr, "ImageTool: HII package list guid is not specified\n");
return RETURN_ABORTED;
}
CopyGuid (&HiiPackageListHeader.PackageListGuid, HiiGuid);
if (IsElf) {
HiiSectionHeader = CreateHiiResouceSectionHeader (&HiiSectionHeaderSize, HiiPackageListHeader.PackageLength);
if (HiiSectionHeader == NULL) {
return RETURN_OUT_OF_RESOURCES;
}
HiiPackageDataPointer = HiiSectionHeader + HiiSectionHeaderSize;
memcpy (HiiPackageDataPointer, &HiiPackageListHeader, sizeof (HiiPackageListHeader));
HiiPackageDataPointer += sizeof (HiiPackageListHeader);
for (Index = 0; Index < NumOfFiles; ++Index) {
File = UserReadFile (FileNames[Index], &FileSize);
if (File == NULL) {
fprintf (stderr, "ImageTool: Could not open %s: %s\n", FileNames[Index], strerror (errno));
free (HiiSectionHeader);
return RETURN_ABORTED;
}
memcpy (HiiPackageDataPointer, File, FileSize);
HiiPackageDataPointer += FileSize;
free (File);
}
memcpy (HiiPackageDataPointer, &EndPackage, sizeof (EndPackage));
*Hii = HiiSectionHeader;
*HiiSize = HiiSectionHeaderSize + HiiPackageListHeader.PackageLength;
return RETURN_SUCCESS;
}
HiiPackageRCFileHeader = "//\n// DO NOT EDIT -- auto-generated file\n//\n\n1 HII\n{";
HiiSectionHeaderSize = (UINT32)AsciiStrLen (HiiPackageRCFileHeader);
TempSize = HiiSectionHeaderSize + 5 * HiiPackageListHeader.PackageLength;
HiiSectionHeader = calloc (1, TempSize);
if (HiiSectionHeader == NULL) {
fprintf (stderr, "ImageTool: Could not allocate memory for HiiRC\n");
return RETURN_OUT_OF_RESOURCES;
}
Buffer = calloc (1, HiiPackageListHeader.PackageLength);
if (Buffer == NULL) {
fprintf (stderr, "ImageTool: Could not allocate memory for Buffer\n");
free (HiiSectionHeader);
return RETURN_OUT_OF_RESOURCES;
}
BufferStart = Buffer;
memcpy (Buffer, &HiiPackageListHeader, sizeof (HiiPackageListHeader));
Buffer += sizeof (HiiPackageListHeader);
for (Index = 0; Index < NumOfFiles; ++Index) {
File = UserReadFile (FileNames[Index], &FileSize);
if (File == NULL) {
fprintf (stderr, "ImageTool: Could not open %s: %s\n", FileNames[Index], strerror (errno));
free (HiiSectionHeader);
free (BufferStart);
return RETURN_ABORTED;
}
memcpy (Buffer, File, FileSize);
Buffer += FileSize;
free (File);
}
memcpy (Buffer, &EndPackage, sizeof (EndPackage));
memcpy (HiiSectionHeader, HiiPackageRCFileHeader, HiiSectionHeaderSize);
HiiPackageDataPointer = HiiSectionHeader + HiiSectionHeaderSize;
Total = HiiSectionHeaderSize;
Buffer = BufferStart;
for (Index = 0; Index + 2 < HiiPackageListHeader.PackageLength; Index += 2) {
if (Index % 16 == 0) {
Step = snprintf ((char *)HiiPackageDataPointer, TempSize - Total, "\n ");
HiiPackageDataPointer += Step;
Total += Step;
}
Step = snprintf ((char *)HiiPackageDataPointer, TempSize - Total, " 0x%04X,", *(UINT16 *)Buffer);
HiiPackageDataPointer += Step;
Total += Step;
Buffer += 2;
}
if (Index % 16 == 0) {
Step = snprintf ((char *)HiiPackageDataPointer, TempSize - Total, "\n ");
HiiPackageDataPointer += Step;
Total += Step;
}
if ((Index + 2) == HiiPackageListHeader.PackageLength) {
Total += snprintf ((char *)HiiPackageDataPointer, TempSize - Total, " 0x%04X\n}\n", *(UINT16 *)Buffer);
} else if ((Index + 1) == HiiPackageListHeader.PackageLength) {
Total += snprintf ((char *)HiiPackageDataPointer, TempSize - Total, " 0x%04X\n}\n", *(UINT8 *)Buffer);
}
*Hii = HiiSectionHeader;
*HiiSize = Total;
free (BufferStart);
return RETURN_SUCCESS;
}

View File

@ -0,0 +1,734 @@
/** @file
Copyright (c) 2022, Mikhail Krichanov. All rights reserved.
SPDX-License-Identifier: BSD-3-Clause
**/
#include "ImageTool.h"
static Elf_Ehdr *mEhdr = NULL;
static Elf_Size mPeAlignment = 0x0;
static Elf_Addr mBaseAddress = 0x0;
static bool mHasPieRelocs = FALSE;
#if defined (_MSC_EXTENSIONS)
#define EFI_IMAGE_MACHINE_IA32 0x014C
#define EFI_IMAGE_MACHINE_X64 0x8664
#define EFI_IMAGE_MACHINE_ARMTHUMB_MIXED 0x01C2
#define EFI_IMAGE_MACHINE_AARCH64 0xAA64
#endif
extern image_tool_image_info_t mImageInfo;
static
Elf_Shdr *
GetShdrByIndex (
IN UINT32 Index
)
{
UINTN Offset;
assert (Index < mEhdr->e_shnum);
Offset = (UINTN)mEhdr->e_shoff + Index * mEhdr->e_shentsize;
return (Elf_Shdr *)((UINT8 *)mEhdr + Offset);
}
static
char *
GetString (
IN UINT32 Offset,
IN UINT32 Index
)
{
const Elf_Shdr *Shdr;
char *String;
if (Index == 0) {
Shdr = GetShdrByIndex (mEhdr->e_shstrndx);
} else {
Shdr = GetShdrByIndex (Index);
}
if (Offset >= Shdr->sh_size) {
fprintf (stderr, "ImageTool: Invalid ELF string offset\n");
return NULL;
}
String = (char *)((UINT8 *)mEhdr + Shdr->sh_offset + Offset);
return String;
}
static
BOOLEAN
IsHiiRsrcShdr (
IN const Elf_Shdr *Shdr
)
{
assert (Shdr != NULL);
Elf_Shdr *Namedr = GetShdrByIndex (mEhdr->e_shstrndx);
return (BOOLEAN) (strcmp ((CHAR8*)mEhdr + Namedr->sh_offset + Shdr->sh_name, ELF_HII_SECTION_NAME) == 0);
}
static
BOOLEAN
IsShdrLoadable (
IN const Elf_Shdr *Shdr
)
{
assert (Shdr != NULL);
return (Shdr->sh_flags & SHF_ALLOC) != 0 && !IsHiiRsrcShdr (Shdr);
}
static
VOID
SetHiiResourceHeader (
IN OUT UINT8 *Hii,
IN UINT32 Offset
)
{
UINT32 Index;
EFI_IMAGE_RESOURCE_DIRECTORY *RDir;
EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY *RDirEntry;
EFI_IMAGE_RESOURCE_DIRECTORY_STRING *RDirString;
EFI_IMAGE_RESOURCE_DATA_ENTRY *RDataEntry;
assert (Hii != NULL);
//
// Fill Resource section entry
//
RDir = (EFI_IMAGE_RESOURCE_DIRECTORY *)Hii;
RDirEntry = (EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY *)(RDir + 1);
for (Index = 0; Index < RDir->NumberOfNamedEntries; ++Index) {
if (RDirEntry->u1.s.NameIsString) {
RDirString = (EFI_IMAGE_RESOURCE_DIRECTORY_STRING *)(Hii + RDirEntry->u1.s.NameOffset);
if ((RDirString->Length == 3)
&& (RDirString->String[0] == L'H')
&& (RDirString->String[1] == L'I')
&& (RDirString->String[2] == L'I')) {
//
// Resource Type "HII" found
//
if (RDirEntry->u2.s.DataIsDirectory) {
//
// Move to next level - resource Name
//
RDir = (EFI_IMAGE_RESOURCE_DIRECTORY *)(Hii + RDirEntry->u2.s.OffsetToDirectory);
RDirEntry = (EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY *)(RDir + 1);
if (RDirEntry->u2.s.DataIsDirectory) {
//
// Move to next level - resource Language
//
RDir = (EFI_IMAGE_RESOURCE_DIRECTORY *)(Hii + RDirEntry->u2.s.OffsetToDirectory);
RDirEntry = (EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY *)(RDir + 1);
}
}
//
// Now it ought to be resource Data. Update its OffsetToData value
//
if (!RDirEntry->u2.s.DataIsDirectory) {
RDataEntry = (EFI_IMAGE_RESOURCE_DATA_ENTRY *)(Hii + RDirEntry->u2.OffsetToData);
RDataEntry->OffsetToData = RDataEntry->OffsetToData + Offset;
break;
}
}
}
RDirEntry++;
}
return;
}
static
RETURN_STATUS
ParseElfFile (
IN const void *File,
IN uint32_t FileSize
)
{
static const unsigned char Ident[] = {
ELFMAG0, ELFMAG1, ELFMAG2, ELFMAG3, ELFCLASS, ELFDATA2LSB
};
const Elf_Shdr *Shdr;
UINTN Offset;
UINT32 Index;
char *Last;
assert (File != NULL || FileSize == 0);
mEhdr = (Elf_Ehdr *)File;
//
// Check header
//
if ((FileSize < sizeof (*mEhdr))
|| (memcmp (Ident, mEhdr->e_ident, sizeof (Ident)) != 0)) {
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]);
fprintf (stderr, "ImageTool: mEhdr->e_ident[3] = 0x%x expected 0x%x\n", mEhdr->e_ident[3], Ident[3]);
fprintf (stderr, "ImageTool: mEhdr->e_ident[4] = 0x%x expected 0x%x\n", mEhdr->e_ident[4], Ident[4]);
fprintf (stderr, "ImageTool: mEhdr->e_ident[5] = 0x%x expected 0x%x\n", mEhdr->e_ident[5], Ident[5]);
fprintf (stderr, "ImageTool: FileSize = 0x%x sizeof(*mEhdr) = 0x%lx\n", FileSize, sizeof (*mEhdr));
return RETURN_UNSUPPORTED;
}
if ((mEhdr->e_type != ET_EXEC) && (mEhdr->e_type != ET_DYN)) {
fprintf (stderr, "ImageTool: ELF e_type not ET_EXEC or ET_DYN\n");
return RETURN_INCOMPATIBLE_VERSION;
}
#if defined(EFI_TARGET64)
if ((mEhdr->e_machine != EM_X86_64) && (mEhdr->e_machine != EM_AARCH64)) {
fprintf (stderr, "ImageTool: Unsupported ELF e_machine\n");
return RETURN_INCOMPATIBLE_VERSION;
}
#elif defined(EFI_TARGET32)
if ((mEhdr->e_machine != EM_386) && (mEhdr->e_machine != EM_ARM)) {
fprintf (stderr, "ImageTool: Unsupported ELF e_machine\n");
return RETURN_INCOMPATIBLE_VERSION;
}
#endif
//
// Check section headers
//
mBaseAddress = ~(Elf_Addr)0;
for (Index = 0; Index < mEhdr->e_shnum; ++Index) {
Offset = (UINTN)mEhdr->e_shoff + Index * mEhdr->e_shentsize;
if (FileSize < (Offset + sizeof (*Shdr))) {
fprintf (stderr, "ImageTool: ELF section header is outside file\n");
return RETURN_VOLUME_CORRUPTED;
}
Shdr = (Elf_Shdr *)((UINT8 *)mEhdr + Offset);
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\n", Index);
return RETURN_VOLUME_CORRUPTED;
}
if (Shdr->sh_link >= mEhdr->e_shnum) {
fprintf (stderr, "ImageTool: ELF %d-th section's sh_link is out of range\n", Index);
return RETURN_VOLUME_CORRUPTED;
}
if ((Shdr->sh_type == SHT_RELA) || (Shdr->sh_type == SHT_REL)) {
if (Shdr->sh_info >= mEhdr->e_shnum) {
fprintf (stderr, "ImageTool: ELF %d-th section's sh_info is out of range\n", Index);
return RETURN_VOLUME_CORRUPTED;
}
if (Shdr->sh_info == 0) {
mHasPieRelocs = TRUE;
}
}
if (Shdr->sh_addr < mBaseAddress) {
mBaseAddress = Shdr->sh_addr;
}
if (!IsShdrLoadable (Shdr)) {
continue;
}
if (mPeAlignment < Shdr->sh_addralign) {
mPeAlignment = Shdr->sh_addralign;
}
}
if (mEhdr->e_shstrndx >= mEhdr->e_shnum) {
fprintf (stderr, "ImageTool: Invalid section name string table\n");
return RETURN_VOLUME_CORRUPTED;
}
Shdr = GetShdrByIndex (mEhdr->e_shstrndx);
if (Shdr->sh_type != SHT_STRTAB) {
fprintf (stderr, "ImageTool: ELF string table section has wrong type\n");
return RETURN_VOLUME_CORRUPTED;
}
Last = (char *)((UINT8 *)mEhdr + Shdr->sh_offset + Shdr->sh_size - 1);
if (*Last != '\0') {
fprintf (stderr, "ImageTool: ELF string table section is not NUL-terminated\n");
return RETURN_VOLUME_CORRUPTED;
}
if ((!IS_POW2(mPeAlignment)) || (mPeAlignment > MAX_PE_ALIGNMENT)) {
fprintf (stderr, "ImageTool: Invalid section alignment\n");
return RETURN_VOLUME_CORRUPTED;
}
return RETURN_SUCCESS;
}
static
bool
ProcessRelocSection (
const Elf_Shdr *Shdr
)
{
const Elf_Shdr *SecShdr;
//
// PIE relocations will target dummy section 0.
//
if (Shdr->sh_info != 0) {
//
// If PIE relocations exist, prefer them.
//
if (mHasPieRelocs) {
return FALSE;
}
//
// Only translate relocations targetting sections that are translated.
//
SecShdr = GetShdrByIndex (Shdr->sh_info);
if (!IsShdrLoadable (SecShdr)) {
return FALSE;
}
} else {
assert (mHasPieRelocs);
}
return TRUE;
}
static
RETURN_STATUS
SetRelocs (
VOID
)
{
UINT32 Index;
const Elf_Shdr *RelShdr;
UINTN RelIdx;
const Elf_Rela *Rel;
UINT32 RelNum;
RelNum = 0;
for (Index = 0; Index < mEhdr->e_shnum; Index++) {
RelShdr = GetShdrByIndex (Index);
if ((RelShdr->sh_type != SHT_REL) && (RelShdr->sh_type != SHT_RELA)) {
continue;
}
if (!ProcessRelocSection (RelShdr)) {
continue;
}
for (RelIdx = 0; RelIdx < RelShdr->sh_size; RelIdx += (UINTN)RelShdr->sh_entsize) {
Rel = (Elf_Rela *)((UINT8 *)mEhdr + RelShdr->sh_offset + RelIdx);
//
// Assume ELF virtual addresses match corresponding PE virtual adresses one to one,
// so we don't need to recalculate relocations computed by the linker at all r_offset's.
// We only need to transform ELF relocations' format into PE one.
//
#if defined(EFI_TARGET64)
if (mEhdr->e_machine == EM_X86_64) {
switch (ELF_R_TYPE(Rel->r_info)) {
case R_X86_64_NONE:
break;
case R_X86_64_RELATIVE:
case R_X86_64_64:
mImageInfo.RelocInfo.Relocs[RelNum].Type = EFI_IMAGE_REL_BASED_DIR64;
mImageInfo.RelocInfo.Relocs[RelNum].Target = (uint32_t)(Rel->r_offset - mBaseAddress);
++RelNum;
break;
case R_X86_64_32:
mImageInfo.RelocInfo.Relocs[RelNum].Type = EFI_IMAGE_REL_BASED_HIGHLOW;
mImageInfo.RelocInfo.Relocs[RelNum].Target = (uint32_t)(Rel->r_offset - mBaseAddress);
++RelNum;
break;
case R_X86_64_32S:
case R_X86_64_PLT32:
case R_X86_64_PC32:
break;
case R_X86_64_GOTPCREL:
case R_X86_64_GOTPCRELX:
case R_X86_64_REX_GOTPCRELX:
//
// Relocations of these types point to instructions' arguments containing
// offsets relative to RIP leading to .got entries. As sections' virtual
// addresses do not change during ELF->PE transform, we don't need to
// add them to relocations' list. But .got entries contain virtual
// addresses which must be updated.
//
// At r_offset the following value is stored: G + GOT + A - P.
// To derive .got entry address (G + GOT) compute: value - A + P.
//
// Such a method of finding relocatable .got entries can not be used,
// due to a BUG in clang compiler, which sometimes generates
// R_X86_64_REX_GOTPCRELX relocations instead of R_X86_64_PC32.
//
break;
default:
fprintf (stderr, "ImageTool: Unsupported ELF EM_X86_64 relocation 0x%llx in %s\n", ELF_R_TYPE(Rel->r_info), mImageInfo.DebugInfo.SymbolsPath);
return RETURN_UNSUPPORTED;
}
} else if (mEhdr->e_machine == EM_AARCH64) {
switch (ELF_R_TYPE(Rel->r_info)) {
case R_AARCH64_NONE0:
case R_AARCH64_NONE:
case R_AARCH64_LD64_GOTOFF_LO15:
case R_AARCH64_LD64_GOTPAGE_LO15:
case R_AARCH64_LD64_GOT_LO12_NC:
case R_AARCH64_ADR_GOT_PAGE:
case R_AARCH64_ADR_PREL_PG_HI21:
case R_AARCH64_ADD_ABS_LO12_NC:
case R_AARCH64_LDST8_ABS_LO12_NC:
case R_AARCH64_LDST16_ABS_LO12_NC:
case R_AARCH64_LDST32_ABS_LO12_NC:
case R_AARCH64_LDST64_ABS_LO12_NC:
case R_AARCH64_LDST128_ABS_LO12_NC:
case R_AARCH64_ADR_PREL_LO21:
case R_AARCH64_CONDBR19:
case R_AARCH64_LD_PREL_LO19:
case R_AARCH64_CALL26:
case R_AARCH64_JUMP26:
case R_AARCH64_PREL64:
case R_AARCH64_PREL32:
case R_AARCH64_PREL16:
break;
case R_AARCH64_ABS64:
case R_AARCH64_RELATIVE:
mImageInfo.RelocInfo.Relocs[RelNum].Type = EFI_IMAGE_REL_BASED_DIR64;
mImageInfo.RelocInfo.Relocs[RelNum].Target = (uint32_t)(Rel->r_offset - mBaseAddress);
++RelNum;
break;
case R_AARCH64_ABS32:
mImageInfo.RelocInfo.Relocs[RelNum].Type = EFI_IMAGE_REL_BASED_HIGHLOW;
mImageInfo.RelocInfo.Relocs[RelNum].Target = (uint32_t)(Rel->r_offset - mBaseAddress);
++RelNum;
break;
default:
fprintf (stderr, "ImageTool: Unsupported ELF EM_AARCH64 relocation 0x%llx in %s\n", ELF_R_TYPE(Rel->r_info), mImageInfo.DebugInfo.SymbolsPath);
return RETURN_UNSUPPORTED;
}
}
#elif defined(EFI_TARGET32)
if (mEhdr->e_machine == EM_386) {
switch (ELF_R_TYPE(Rel->r_info)) {
case R_386_NONE:
break;
case R_386_32:
mImageInfo.RelocInfo.Relocs[RelNum].Type = EFI_IMAGE_REL_BASED_HIGHLOW;
mImageInfo.RelocInfo.Relocs[RelNum].Target = (Rel->r_offset - mBaseAddress);
++RelNum;
break;
case R_386_PLT32:
case R_386_PC32:
break;
default:
fprintf (stderr, "ImageTool: Unsupported ELF EM_386 relocation 0x%x in %s\n", ELF_R_TYPE(Rel->r_info), mImageInfo.DebugInfo.SymbolsPath);
return RETURN_UNSUPPORTED;
}
} else if (mEhdr->e_machine == EM_ARM) {
switch (ELF32_R_TYPE(Rel->r_info)) {
case R_ARM_NONE:
case R_ARM_PC24:
case R_ARM_REL32:
case R_ARM_XPC25:
case R_ARM_THM_PC22:
case R_ARM_THM_JUMP19:
case R_ARM_CALL:
case R_ARM_JMP24:
case R_ARM_THM_JUMP24:
case R_ARM_PREL31:
case R_ARM_MOVW_PREL_NC:
case R_ARM_MOVT_PREL:
case R_ARM_THM_MOVW_PREL_NC:
case R_ARM_THM_MOVT_PREL:
case R_ARM_THM_JMP6:
case R_ARM_THM_ALU_PREL_11_0:
case R_ARM_THM_PC12:
case R_ARM_REL32_NOI:
case R_ARM_ALU_PC_G0_NC:
case R_ARM_ALU_PC_G0:
case R_ARM_ALU_PC_G1_NC:
case R_ARM_ALU_PC_G1:
case R_ARM_ALU_PC_G2:
case R_ARM_LDR_PC_G1:
case R_ARM_LDR_PC_G2:
case R_ARM_LDRS_PC_G0:
case R_ARM_LDRS_PC_G1:
case R_ARM_LDRS_PC_G2:
case R_ARM_LDC_PC_G0:
case R_ARM_LDC_PC_G1:
case R_ARM_LDC_PC_G2:
case R_ARM_THM_JUMP11:
case R_ARM_THM_JUMP8:
case R_ARM_TLS_GD32:
case R_ARM_TLS_LDM32:
case R_ARM_TLS_IE32:
break;
case R_ARM_ABS32:
mImageInfo.RelocInfo.Relocs[RelNum].Type = EFI_IMAGE_REL_BASED_HIGHLOW;
mImageInfo.RelocInfo.Relocs[RelNum].Target = (Rel->r_offset - mBaseAddress);
++RelNum;
break;
default:
fprintf (stderr, "ImageTool: Unsupported ELF EM_ARM relocation 0x%x in %s\n", ELF_R_TYPE(Rel->r_info), mImageInfo.DebugInfo.SymbolsPath);
return RETURN_UNSUPPORTED;
}
}
#endif
}
}
mImageInfo.RelocInfo.NumRelocs = RelNum;
return RETURN_SUCCESS;
}
static
RETURN_STATUS
CreateIntermediate (
VOID
)
{
const Elf_Shdr *Shdr;
UINT32 Index;
image_tool_segment_t *Segments;
image_tool_reloc_t *Relocs;
UINT32 SIndex;
const Elf_Rel *Rel;
UINTN RIndex;
char *Name;
UINT32 NumRelocs;
Segments = NULL;
SIndex = 0;
Relocs = NULL;
NumRelocs = 0;
for (Index = 0; Index < mEhdr->e_shnum; ++Index) {
Shdr = GetShdrByIndex (Index);
if ((Shdr->sh_type == SHT_REL) || (Shdr->sh_type == SHT_RELA)) {
if ((Shdr->sh_flags & SHF_ALLOC) != 0) {
fprintf (stderr, "ImageTool: Loadable reloc sections are unsupported\n");
return RETURN_VOLUME_CORRUPTED;
}
if (!ProcessRelocSection (Shdr)) {
continue;
}
for (RIndex = 0; RIndex < Shdr->sh_size; RIndex += (UINTN)Shdr->sh_entsize) {
Rel = (Elf_Rel *)((UINT8 *)mEhdr + Shdr->sh_offset + RIndex);
#if defined(EFI_TARGET64)
if (mEhdr->e_machine == EM_X86_64) {
if ((ELF_R_TYPE(Rel->r_info) == R_X86_64_RELATIVE)
|| (ELF_R_TYPE(Rel->r_info) == R_X86_64_64)
|| (ELF_R_TYPE(Rel->r_info) == R_X86_64_32)
|| (ELF_R_TYPE(Rel->r_info) == R_X86_64_GOTPCREL)
|| (ELF_R_TYPE(Rel->r_info) == R_X86_64_GOTPCRELX)
|| (ELF_R_TYPE(Rel->r_info) == R_X86_64_REX_GOTPCRELX)) {
++NumRelocs;
}
} else if (mEhdr->e_machine == EM_AARCH64) {
if ((ELF_R_TYPE(Rel->r_info) == R_AARCH64_ABS64)
|| (ELF_R_TYPE(Rel->r_info) == R_AARCH64_RELATIVE)
|| (ELF_R_TYPE(Rel->r_info) == R_AARCH64_ABS32)) {
++NumRelocs;
}
}
#elif defined(EFI_TARGET32)
if (mEhdr->e_machine == EM_386) {
if (ELF_R_TYPE(Rel->r_info) == R_386_32) {
++NumRelocs;
}
} else if (mEhdr->e_machine == EM_ARM) {
if (ELF_R_TYPE(Rel->r_info) == R_ARM_ABS32) {
++NumRelocs;
}
}
#endif
}
}
if (!IsShdrLoadable (Shdr)) {
continue;
}
++mImageInfo.SegmentInfo.NumSegments;
}
if (mImageInfo.SegmentInfo.NumSegments == 0) {
fprintf (stderr, "ImageTool: No loadable sections\n");
return RETURN_VOLUME_CORRUPTED;
}
Segments = calloc (1, sizeof (*Segments) * mImageInfo.SegmentInfo.NumSegments);
if (Segments == NULL) {
fprintf (stderr, "ImageTool: Could not allocate memory for Segments\n");
return RETURN_OUT_OF_RESOURCES;
};
mImageInfo.SegmentInfo.Segments = Segments;
if (NumRelocs != 0) {
Relocs = calloc (1, sizeof (*Relocs) * NumRelocs);
if (Relocs == NULL) {
fprintf (stderr, "ImageTool: Could not allocate memory for Relocs\n");
return RETURN_OUT_OF_RESOURCES;
};
mImageInfo.RelocInfo.Relocs = Relocs;
}
for (Index = 0; Index < mEhdr->e_shnum; ++Index) {
Shdr = GetShdrByIndex (Index);
if ((Shdr->sh_flags & SHF_ALLOC) == 0) {
continue;
}
if (Shdr->sh_type != SHT_PROGBITS && Shdr->sh_type != SHT_NOBITS) {
fprintf (stderr, "ImageTool: Segment #%d type %x unsupported\n", Index, Shdr->sh_type);
return RETURN_VOLUME_CORRUPTED;
}
if (IsHiiRsrcShdr (Shdr)) {
mImageInfo.HiiInfo.DataSize = (uint32_t)Shdr->sh_size;
mImageInfo.HiiInfo.Data = calloc (1, mImageInfo.HiiInfo.DataSize);
if (mImageInfo.HiiInfo.Data == NULL) {
fprintf (stderr, "ImageTool: Could not allocate memory for Hii Data\n");
return RETURN_OUT_OF_RESOURCES;
};
if (Shdr->sh_type == SHT_PROGBITS) {
memcpy (mImageInfo.HiiInfo.Data, (UINT8 *)mEhdr + Shdr->sh_offset, mImageInfo.HiiInfo.DataSize);
}
SetHiiResourceHeader (mImageInfo.HiiInfo.Data, (UINT32)(Shdr->sh_addr - mBaseAddress));
} else {
Name = GetString (Shdr->sh_name, 0);
if (Name == NULL) {
return RETURN_VOLUME_CORRUPTED;
}
Segments[SIndex].Name = calloc (1, strlen (Name) + 1);
if (Segments[SIndex].Name == NULL) {
fprintf (stderr, "ImageTool: Could not allocate memory for Segment #%d Name\n", Index);
return RETURN_OUT_OF_RESOURCES;
};
memcpy (Segments[SIndex].Name, Name, strlen (Name));
Segments[SIndex].DataSize = (uint32_t)ALIGN_VALUE (Shdr->sh_size, mPeAlignment);
Segments[SIndex].Data = calloc (1, Segments[SIndex].DataSize);
if (Segments[SIndex].Data == NULL) {
fprintf (stderr, "ImageTool: Could not allocate memory for Segment #%d Data\n", Index);
return RETURN_OUT_OF_RESOURCES;
};
if (Shdr->sh_type == SHT_PROGBITS) {
memcpy (Segments[SIndex].Data, (UINT8 *)mEhdr + Shdr->sh_offset, (size_t)Shdr->sh_size);
}
Segments[SIndex].ImageAddress = Shdr->sh_addr - mBaseAddress;
Segments[SIndex].ImageSize = Segments[SIndex].DataSize;
Segments[SIndex].Read = true;
Segments[SIndex].Write = (Shdr->sh_flags & SHF_WRITE) != 0;
Segments[SIndex].Execute = (Shdr->sh_flags & SHF_EXECINSTR) != 0;
++SIndex;
}
}
assert (SIndex == mImageInfo.SegmentInfo.NumSegments);
return SetRelocs();
}
RETURN_STATUS
ScanElf (
IN const void *File,
IN uint32_t FileSize,
IN const char *SymbolsPath
)
{
RETURN_STATUS Status;
assert (File != NULL || FileSize == 0);
Status = ParseElfFile (File, FileSize);
if (RETURN_ERROR (Status)) {
return Status;
}
memset (&mImageInfo, 0, sizeof (mImageInfo));
mImageInfo.HeaderInfo.BaseAddress = mBaseAddress;
mImageInfo.HeaderInfo.EntryPointAddress = (uint32_t)(mEhdr->e_entry - mBaseAddress);
mImageInfo.HeaderInfo.IsXip = true;
mImageInfo.SegmentInfo.SegmentAlignment = (uint32_t)mPeAlignment;
mImageInfo.RelocInfo.RelocsStripped = false;
mImageInfo.DebugInfo.SymbolsPathLen = strlen (SymbolsPath);
switch (mEhdr->e_machine) {
#if defined(EFI_TARGET64)
case EM_X86_64:
mImageInfo.HeaderInfo.Machine = EFI_IMAGE_MACHINE_X64;
break;
case EM_AARCH64:
mImageInfo.HeaderInfo.Machine = EFI_IMAGE_MACHINE_AARCH64;
break;
#elif defined(EFI_TARGET32)
case EM_386:
mImageInfo.HeaderInfo.Machine = EFI_IMAGE_MACHINE_IA32;
break;
case EM_ARM:
mImageInfo.HeaderInfo.Machine = EFI_IMAGE_MACHINE_ARMTHUMB_MIXED;
break;
#endif
default:
fprintf (stderr, "ImageTool: Unknown ELF architecture %d\n", mEhdr->e_machine);
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");
return RETURN_OUT_OF_RESOURCES;
};
memmove (mImageInfo.DebugInfo.SymbolsPath, SymbolsPath, mImageInfo.DebugInfo.SymbolsPathLen + 1);
//
// There is no corresponding ELF property.
//
mImageInfo.HeaderInfo.Subsystem = 0;
Status = CreateIntermediate ();
if (RETURN_ERROR (Status)) {
ToolImageDestruct (&mImageInfo);
}
return Status;
}

View File

@ -0,0 +1,33 @@
## @file
# Copyright (c) 2021, Marvin Häuser. All rights reserved.
# Copyright (c) 2022, Mikhail Krichanov. All rights reserved.
# SPDX-License-Identifier: BSD-3-Clause
##
PROJECT = ImageTool
OBJS = $(PROJECT).o
OBJS += Image.o PeEmit.o PeScan.o ElfScan.o BinEmit.o
OBJS += UefiImageExtraActionLib.o
OBJS += PeCoffInit.o PeCoffInfo.o PeCoffLoad.o PeCoffRelocate.o PeCoffHii.o PeCoffDebug.o
DEBUG = 1
SANITIZE = 0
OC_USER = ../../OpenCorePkg
UDK_PATH = ../..
include $(OC_USER)/User/Makefile
.DEFAULT_GOAL := Tools
CFLAGS += -Werror
VPATH += ../../MdePkg/Library/BasePeCoffLib2:$\
../../MdePkg/Library/BaseUefiImageExtraActionLibNull
Tools: Tool32 Tool64
Tool32:
$(MAKE) all CFLAGS="$(CFLAGS) -DEFI_TARGET32" PRODUCT=ImageTool32 INFIX=_Tool32
Tool64:
$(MAKE) all CFLAGS="$(CFLAGS) -DEFI_TARGET64" PRODUCT=ImageTool64 INFIX=_Tool64

311
BaseTools/ImageTool/Image.c Normal file
View File

@ -0,0 +1,311 @@
/** @file
Copyright (c) 2021, Marvin Häuser. All rights reserved.
Copyright (c) 2022, Mikhail Krichanov. All rights reserved.
SPDX-License-Identifier: BSD-3-Clause
**/
#include "ImageTool.h"
static
bool
CheckToolImageSegment (
image_tool_segment_info_t *SegmentInfo,
image_tool_segment_t *Segment,
uint32_t *PreviousEndAddress
)
{
bool Overflow;
assert (Segment != NULL);
assert (PreviousEndAddress != NULL);
Overflow = BaseOverflowAlignUpU32 (
Segment->ImageSize,
SegmentInfo->SegmentAlignment,
&Segment->ImageSize
);
if (Overflow) {
raise ();
return false;
}
if (Segment->Write && Segment->Execute) {
raise ();
return false;
}
//
// Shrink segment.
//
if (Segment->ImageSize < Segment->DataSize) {
Segment->DataSize = Segment->ImageSize;
}
for (; Segment->DataSize > 0; --Segment->DataSize) {
if (Segment->Data[Segment->DataSize - 1] != 0) {
break;
}
}
// FIXME: Expand prior segment
if (Segment->ImageAddress != *PreviousEndAddress) {
raise ();
return false;
}
Overflow = BaseOverflowAddU32 (
(uint32_t)Segment->ImageAddress,
Segment->ImageSize,
PreviousEndAddress
);
if (Overflow) {
raise ();
return false;
}
return true;
}
static
bool
CheckToolImageSegmentInfo (
image_tool_segment_info_t *SegmentInfo,
uint32_t *ImageSize
)
{
uint64_t Index;
bool Result;
assert (SegmentInfo != NULL);
assert (ImageSize != NULL);
if (!IS_POW2 (SegmentInfo->SegmentAlignment)) {
raise ();
return false;
}
if (SegmentInfo->NumSegments == 0) {
raise ();
return false;
}
*ImageSize = (uint32_t)SegmentInfo->Segments[0].ImageAddress;
for (Index = 0; Index < SegmentInfo->NumSegments; ++Index) {
Result = CheckToolImageSegment (
SegmentInfo,
&SegmentInfo->Segments[Index],
ImageSize
);
if (!Result) {
raise ();
return false;
}
}
return true;
}
static
const image_tool_segment_t *
ImageGetSegmentByAddress (
const image_tool_segment_info_t *SegmentInfo,
uint64_t Address
)
{
uint64_t Index;
assert (SegmentInfo != NULL);
for (Index = 0; Index < SegmentInfo->NumSegments; ++Index) {
if ((SegmentInfo->Segments[Index].ImageAddress <= Address)
&& (Address < SegmentInfo->Segments[Index].ImageAddress + SegmentInfo->Segments[Index].ImageSize)) {
return &SegmentInfo->Segments[Index];
}
}
return NULL;
}
static
bool
CheckToolImageReloc (
const image_tool_image_info_t *Image,
const image_tool_reloc_t *Reloc
)
{
const image_tool_segment_t *Segment;
assert (Image != NULL);
assert (Reloc != NULL);
Segment = ImageGetSegmentByAddress (&Image->SegmentInfo, Reloc->Target);
if (Segment == NULL) {
raise ();
return false;
}
/*if (Segment->Write) {
printf("!!! writable reloc at %x !!!\n", Reloc->Target);
}*/
return true;
}
static
bool
CheckToolImageRelocInfo (
const image_tool_image_info_t *Image
)
{
const image_tool_reloc_info_t *RelocInfo;
uint32_t Index;
bool Result;
assert (Image != NULL);
RelocInfo = &Image->RelocInfo;
if (RelocInfo->RelocsStripped && (RelocInfo->NumRelocs > 0)) {
raise ();
return false;
}
if (RelocInfo->NumRelocs > (MAX_UINT32 / sizeof (UINT16))) {
raise ();
return false;
}
for (Index = 0; Index < RelocInfo->NumRelocs; ++Index) {
Result = CheckToolImageReloc (Image, &RelocInfo->Relocs[Index]);
if (!Result) {
raise ();
return false;
}
}
return true;
}
static
bool
CheckToolImageDebugInfo (
image_tool_debug_info_t *DebugInfo
)
{
assert (DebugInfo != NULL);
if (DebugInfo->SymbolsPath != NULL) {
// FIXME: UE-only?
if (DebugInfo->SymbolsPathLen > MAX_UINT8) {
raise ();
return false;
}
}
return true;
}
bool
CheckToolImage (
image_tool_image_info_t *Image
)
{
bool Result;
uint32_t ImageSize;
assert (Image != NULL);
Result = CheckToolImageSegmentInfo (&Image->SegmentInfo, &ImageSize);
if (!Result) {
raise ();
return false;
}
Result = CheckToolImageRelocInfo (Image);
if (!Result) {
raise ();
return false;
}
Result = CheckToolImageDebugInfo (&Image->DebugInfo);
if (!Result) {
raise ();
return false;
}
return true;
}
bool
ImageConvertToXip (
image_tool_image_info_t *Image
)
{
image_tool_segment_info_t *SegmentInfo;
uint64_t Index;
image_tool_segment_t *Segment;
void *Data;
assert (Image != NULL);
SegmentInfo = &Image->SegmentInfo;
for (Index = 0; Index < SegmentInfo->NumSegments; ++Index) {
Segment = &SegmentInfo->Segments[Index];
assert (Segment->DataSize <= Segment->ImageSize);
Data = realloc (Segment->Data, Segment->ImageSize);
if (Data == NULL) {
return false;
}
memset (
(char *)Data + Segment->DataSize,
0,
Segment->ImageSize - Segment->DataSize
);
Segment->Data = Data;
Segment->DataSize = Segment->ImageSize;
}
Image->HeaderInfo.IsXip = true;
return true;
}
void
ToolImageDestruct (
image_tool_image_info_t *Image
)
{
uint8_t Index;
assert (Image != NULL);
if (Image->SegmentInfo.Segments != NULL) {
for (Index = 0; Index < Image->SegmentInfo.NumSegments; ++Index) {
if (Image->SegmentInfo.Segments[Index].Name != NULL) {
free (Image->SegmentInfo.Segments[Index].Name);
}
if (Image->SegmentInfo.Segments[Index].DataSize != 0) {
free (Image->SegmentInfo.Segments[Index].Data);
}
}
free (Image->SegmentInfo.Segments);
}
if (Image->HiiInfo.Data != NULL) {
free (Image->HiiInfo.Data);
}
if (Image->RelocInfo.Relocs != NULL) {
free (Image->RelocInfo.Relocs);
}
if (Image->DebugInfo.SymbolsPath != NULL) {
free (Image->DebugInfo.SymbolsPath);
}
memset (Image, 0, sizeof (*Image));
}

View File

@ -0,0 +1,493 @@
/** @file
Copyright (c) 2021, Marvin Häuser. All rights reserved.
Copyright (c) 2022, Mikhail Krichanov. All rights reserved.
SPDX-License-Identifier: BSD-3-Clause
**/
#include "ImageTool.h"
#include <IndustryStandard/Acpi10.h>
#include <IndustryStandard/Acpi30.h>
#include <IndustryStandard/MemoryMappedConfigurationSpaceAccessTable.h>
#define EFI_ACPI_1_0_FIRMWARE_ACPI_CONTROL_STRUCTURE_VERSION 0x0
image_tool_image_info_t mImageInfo;
static
RETURN_STATUS
HiiBin (
IN const char *HiiName,
IN const char *Guid,
IN const char *FileNames[],
IN UINT32 NumOfFiles,
IN BOOLEAN IsElf
)
{
RETURN_STATUS Status;
void *Hii;
UINT32 HiiSize;
GUID HiiGuid;
assert (FileNames != NULL);
assert (HiiName != NULL);
assert (Guid != NULL);
Status = AsciiStrToGuid (Guid, &HiiGuid);
if (RETURN_ERROR (Status)) {
fprintf (stderr, "ImageTool: Invalid GUID - %s\n", Guid);
return Status;
}
Status = ConstructHii (FileNames, NumOfFiles, &HiiGuid, &Hii, &HiiSize, IsElf);
if (RETURN_ERROR (Status)) {
fprintf (stderr, "ImageTool: Could not construct HiiBin\n");
return Status;
}
UserWriteFile (HiiName, Hii, HiiSize);
free (Hii);
return RETURN_SUCCESS;
}
static
RETURN_STATUS
Rebase (
IN const char *BaseAddress,
IN const char *OldName,
IN const char *NewName
)
{
RETURN_STATUS Status;
void *Pe;
uint32_t PeSize;
UINT64 NewBaseAddress;
PE_COFF_LOADER_IMAGE_CONTEXT Context;
EFI_IMAGE_NT_HEADERS *PeHdr;
assert (BaseAddress != NULL);
assert (OldName != NULL);
assert (NewName != NULL);
Status = AsciiStrHexToUint64S (BaseAddress, NULL, &NewBaseAddress);
if (RETURN_ERROR (Status)) {
fprintf (stderr, "ImageTool: Could not convert ASCII string to UINT64\n");
return Status;
}
#ifdef EFI_TARGET32
if (NewBaseAddress > MAX_UINT32) {
fprintf (stderr, "ImageTool: New Base Address exceeds MAX value\n");
return RETURN_INVALID_PARAMETER;
}
#endif
Pe = UserReadFile (OldName, &PeSize);
if (Pe == NULL) {
fprintf (stderr, "ImageTool: Could not open %s: %s\n", OldName, strerror (errno));
return RETURN_ABORTED;
}
Status = PeCoffInitializeContext (&Context, Pe, (UINT32)PeSize);
if (RETURN_ERROR (Status)) {
fprintf (stderr, "ImageTool: Could not initialise Context\n");
free (Pe);
return Status;
}
Context.ImageBuffer = (void *)Context.FileBuffer;
Status = PeCoffRelocateImage (&Context, NewBaseAddress, NULL, 0);
if (EFI_ERROR (Status)) {
fprintf (stderr, "ImageTool: Could not relocate image\n");
free (Pe);
return Status;
}
PeHdr = (EFI_IMAGE_NT_HEADERS *)(void *)((char *)Context.ImageBuffer + Context.ExeHdrOffset);
#ifdef EFI_TARGET32
PeHdr->ImageBase = (UINT32)NewBaseAddress;
#else
PeHdr->ImageBase = NewBaseAddress;
#endif
UserWriteFile (NewName, Pe, PeSize);
free (Pe);
return RETURN_SUCCESS;
}
static
RETURN_STATUS
CheckAcpiTable (
IN const void *AcpiTable,
IN UINT32 Length
)
{
const EFI_ACPI_DESCRIPTION_HEADER *AcpiHeader;
const EFI_ACPI_3_0_FIRMWARE_ACPI_CONTROL_STRUCTURE *Facs;
UINT32 ExpectedLength;
AcpiHeader = (const EFI_ACPI_DESCRIPTION_HEADER *)AcpiTable;
if (AcpiHeader->Length > Length) {
fprintf (stderr, "ImageTool: AcpiTable length section size\n");
return RETURN_VOLUME_CORRUPTED;
}
switch (AcpiHeader->Signature) {
case EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE_SIGNATURE:
switch (AcpiHeader->Revision) {
case EFI_ACPI_1_0_FIXED_ACPI_DESCRIPTION_TABLE_REVISION:
ExpectedLength = sizeof(EFI_ACPI_1_0_FIXED_ACPI_DESCRIPTION_TABLE);
break;
case EFI_ACPI_2_0_FIXED_ACPI_DESCRIPTION_TABLE_REVISION:
ExpectedLength = sizeof(EFI_ACPI_2_0_FIXED_ACPI_DESCRIPTION_TABLE);
break;
case EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE_REVISION:
ExpectedLength = sizeof(EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE);
break;
default:
if (AcpiHeader->Revision > EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE_REVISION) {
ExpectedLength = AcpiHeader->Length;
break;
}
fprintf (stderr, "ImageTool: FACP revision check failed\n");
return RETURN_VOLUME_CORRUPTED;
}
if (ExpectedLength != AcpiHeader->Length) {
fprintf (stderr, "ImageTool: FACP length check failed\n");
return RETURN_VOLUME_CORRUPTED;
}
break;
case EFI_ACPI_3_0_FIRMWARE_ACPI_CONTROL_STRUCTURE_SIGNATURE:
Facs = (const EFI_ACPI_3_0_FIRMWARE_ACPI_CONTROL_STRUCTURE *)AcpiTable;
if (Facs->Version > EFI_ACPI_3_0_FIRMWARE_ACPI_CONTROL_STRUCTURE_VERSION) {
break;
}
if ((Facs->Version != EFI_ACPI_1_0_FIRMWARE_ACPI_CONTROL_STRUCTURE_VERSION)
&& (Facs->Version != EFI_ACPI_2_0_FIRMWARE_ACPI_CONTROL_STRUCTURE_VERSION)
&& (Facs->Version != EFI_ACPI_3_0_FIRMWARE_ACPI_CONTROL_STRUCTURE_VERSION)) {
fprintf (stderr, "ImageTool: FACS version check failed\n");
return RETURN_VOLUME_CORRUPTED;
}
if ((Facs->Length != sizeof(EFI_ACPI_1_0_FIRMWARE_ACPI_CONTROL_STRUCTURE))
&& (Facs->Length != sizeof(EFI_ACPI_2_0_FIRMWARE_ACPI_CONTROL_STRUCTURE))
&& (Facs->Length != sizeof(EFI_ACPI_3_0_FIRMWARE_ACPI_CONTROL_STRUCTURE))) {
fprintf (stderr, "ImageTool: FACS length check failed\n");
return RETURN_VOLUME_CORRUPTED;
}
break;
case EFI_ACPI_3_0_DIFFERENTIATED_SYSTEM_DESCRIPTION_TABLE_SIGNATURE:
if (AcpiHeader->Revision > EFI_ACPI_3_0_DIFFERENTIATED_SYSTEM_DESCRIPTION_TABLE_REVISION) {
break;
}
if (AcpiHeader->Length <= sizeof(EFI_ACPI_DESCRIPTION_HEADER)) {
fprintf (stderr, "ImageTool: DSDT length check failed\n");
return RETURN_VOLUME_CORRUPTED;
}
break;
case EFI_ACPI_3_0_MULTIPLE_APIC_DESCRIPTION_TABLE_SIGNATURE:
if (AcpiHeader->Revision > EFI_ACPI_3_0_MULTIPLE_APIC_DESCRIPTION_TABLE_REVISION) {
break;
}
if ((AcpiHeader->Revision != EFI_ACPI_1_0_MULTIPLE_APIC_DESCRIPTION_TABLE_REVISION)
&& (AcpiHeader->Revision != EFI_ACPI_2_0_MULTIPLE_APIC_DESCRIPTION_TABLE_REVISION)
&& (AcpiHeader->Revision != EFI_ACPI_3_0_MULTIPLE_APIC_DESCRIPTION_TABLE_REVISION)) {
fprintf (stderr, "ImageTool: APIC revision check failed\n");
return RETURN_VOLUME_CORRUPTED;
}
if (AcpiHeader->Length <= (sizeof(EFI_ACPI_DESCRIPTION_HEADER) + sizeof(UINT32) + sizeof(UINT32))) {
fprintf (stderr, "ImageTool: APIC length check failed\n");
return RETURN_VOLUME_CORRUPTED;
}
break;
case EFI_ACPI_3_0_PCI_EXPRESS_MEMORY_MAPPED_CONFIGURATION_SPACE_BASE_ADDRESS_DESCRIPTION_TABLE_SIGNATURE:
if (AcpiHeader->Revision > EFI_ACPI_MEMORY_MAPPED_CONFIGURATION_SPACE_ACCESS_TABLE_REVISION) {
break;
}
if (AcpiHeader->Revision != EFI_ACPI_MEMORY_MAPPED_CONFIGURATION_SPACE_ACCESS_TABLE_REVISION) {
fprintf (stderr, "ImageTool: MCFG revision check failed\n");
return RETURN_VOLUME_CORRUPTED;
}
if (AcpiHeader->Length <= (sizeof(EFI_ACPI_DESCRIPTION_HEADER) + sizeof(UINT64))) {
fprintf (stderr, "ImageTool: MCFG length check failed\n");
return RETURN_VOLUME_CORRUPTED;
}
break;
default:
break;
}
return RETURN_SUCCESS;
}
static
RETURN_STATUS
GetAcpi (
IN const char *PeName,
IN const char *AcpiName
)
{
RETURN_STATUS Status;
void *Pe;
uint32_t PeSize;
PE_COFF_LOADER_IMAGE_CONTEXT Context;
UINT16 NumberOfSections;
const EFI_IMAGE_SECTION_HEADER *Sections;
UINT16 Index;
UINT32 FileLength;
assert (PeName != NULL);
assert (AcpiName != NULL);
Pe = UserReadFile (PeName, &PeSize);
if (Pe == NULL) {
fprintf (stderr, "ImageTool: Could not open %s: %s\n", PeName, strerror (errno));
return RETURN_ABORTED;
}
Status = PeCoffInitializeContext (&Context, Pe, (UINT32)PeSize);
if (RETURN_ERROR (Status)) {
fprintf (stderr, "ImageTool: Could not initialise Context\n");
free (Pe);
return Status;
}
NumberOfSections = PeCoffGetSectionTable (&Context, &Sections);
for (Index = 0; Index < NumberOfSections; ++Index) {
if ((strcmp ((char *)Sections[Index].Name, ".data") == 0)
|| (strcmp ((char *)Sections[Index].Name, ".sdata") == 0)
|| (strcmp ((char *)Sections[Index].Name, ".rdata") == 0)) {
if (Sections[Index].VirtualSize < Sections[Index].SizeOfRawData) {
FileLength = Sections[Index].VirtualSize;
} else {
FileLength = Sections[Index].SizeOfRawData;
}
Status = CheckAcpiTable ((char *)Context.FileBuffer + Sections[Index].PointerToRawData, FileLength);
if (RETURN_ERROR (Status)) {
free (Pe);
return Status;
}
UserWriteFile (AcpiName, (char *)Context.FileBuffer + Sections[Index].PointerToRawData, FileLength);
free (Pe);
return RETURN_SUCCESS;
}
}
return RETURN_NOT_FOUND;
}
static
bool
ImageSetModuleType (
OUT image_tool_image_info_t *Image,
IN const char *TypeName
)
{
uint16_t ModuleType;
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);
if (RETURN_ERROR (Status)) {
fprintf (stderr, "ImageTool: Could not parse input file %s - %llx\n", InputFileName, (unsigned long long)Status);
return Status;
}
if (TypeName != NULL) {
Result = ImageSetModuleType (&mImageInfo, TypeName);
if (!Result) {
ToolImageDestruct (&mImageInfo);
return RETURN_UNSUPPORTED;
}
}
Result = CheckToolImage (&mImageInfo);
if (!Result) {
ToolImageDestruct (&mImageInfo);
return RETURN_UNSUPPORTED;
}
if (strcmp (FormatName, "PE") == 0) {
OutputFile = ToolImageEmitPe (&mImageInfo, &OutputFileSize);
} else {
assert (false);
}
ToolImageDestruct (&mImageInfo);
if (OutputFile == NULL) {
return RETURN_ABORTED;
}
UserWriteFile (OutputFileName, OutputFile, OutputFileSize);
free (OutputFile);
return RETURN_SUCCESS;
}
int main (int argc, const char *argv[])
{
RETURN_STATUS Status;
UINT32 NumOfFiles;
if (argc < 2) {
fprintf (stderr, "ImageTool: No command is specified\n");
raise ();
return -1;
}
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 %s InputFile OutputFile ModuleType\n", argv[1]);
raise ();
return -1;
}
Status = GenExecutable (argv[3], argv[2], "PE", argv[4]);
if (RETURN_ERROR (Status)) {
raise ();
return -1;
}
} else if (strcmp (argv[1], "HiiBinElf") == 0) {
if (argc < 5) {
fprintf (stderr, "ImageTool: Command arguments are missing\n");
fprintf (stderr, " Usage: ImageTool HiiBinElf OutputFile GUID InputFile1 InputFile2 ...\n");
raise ();
return -1;
}
NumOfFiles = (UINT32)argc - 4U;
Status = HiiBin (argv[2], argv[3], &argv[4], NumOfFiles, TRUE);
if (RETURN_ERROR (Status)) {
raise ();
return -1;
}
} else if (strcmp (argv[1], "HiiBinPe") == 0) {
if (argc < 5) {
fprintf (stderr, "ImageTool: Command arguments are missing\n");
fprintf (stderr, " Usage: ImageTool HiiBinPe OutputFile GUID InputFile1 InputFile2 ...\n");
raise ();
return -1;
}
NumOfFiles = (UINT32)argc - 4U;
Status = HiiBin (argv[2], argv[3], &argv[4], NumOfFiles, FALSE);
if (RETURN_ERROR (Status)) {
raise ();
return -1;
}
} else if (strcmp (argv[1], "Rebase") == 0) {
if (argc < 5) {
fprintf (stderr, "ImageTool: Command arguments are missing\n");
fprintf (stderr, " Usage: ImageTool Rebase Address InputFile OutputFile\n");
raise ();
return -1;
}
Status = Rebase (argv[2], argv[3], argv[4]);
if (RETURN_ERROR (Status)) {
raise ();
return -1;
}
} else if (strcmp (argv[1], "GetAcpi") == 0) {
if (argc < 4) {
fprintf (stderr, "ImageTool: Command arguments are missing\n");
fprintf (stderr, " Usage: ImageTool GetAcpi InputFile OutputFile\n");
raise ();
return -1;
}
Status = GetAcpi (argv[2], argv[3]);
if (RETURN_ERROR (Status)) {
raise ();
return -1;
}
}
return 0;
}

View File

@ -0,0 +1,181 @@
/** @file
Copyright (c) 2021, Marvin Häuser. All rights reserved.
Copyright (c) 2022, Mikhail Krichanov. All rights reserved.
SPDX-License-Identifier: BSD-3-Clause
**/
#ifndef IMAGE_TOOL_H
#define IMAGE_TOOL_H
#include <Base.h>
#include <stdbool.h>
#include <errno.h>
#include <assert.h>
#include <IndustryStandard/PeImage2.h>
#include <Library/PeCoffLib2.h>
#include <Library/BaseLib.h>
#include <Library/BaseMemoryLib.h>
#include <Library/BaseOverflowLib.h>
#include <Library/MemoryAllocationLib.h>
#include <UserFile.h>
#include "../../UefiPayloadPkg/PayloadLoaderPeim/ElfLib/ElfCommon.h"
#undef ELF_R_TYPE
#undef ELF_R_SYM
#ifdef EFI_TARGET32
#include "../../UefiPayloadPkg/PayloadLoaderPeim/ElfLib/Elf32.h"
#define EFI_IMAGE_NT_HEADERS EFI_IMAGE_NT_HEADERS32
#define EFI_IMAGE_NT_OPTIONAL_HDR_MAGIC EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
#define EFI_IMAGE_FILE_MACHINE EFI_IMAGE_FILE_32BIT_MACHINE
#define ELFCLASS ELFCLASS32
#define Elf_Ehdr Elf32_Ehdr
#define Elf_Shdr Elf32_Shdr
#define Elf_Sym Elf32_Sym
#define Elf_Rel Elf32_Rel
#define Elf_Rela Elf32_Rela
#define Elf_Size Elf32_Size
#define Elf_Addr Elf32_Addr
#define ELF_R_TYPE ELF32_R_TYPE
#define ELF_R_SYM ELF32_R_SYM
#elif defined(EFI_TARGET64)
#include "../../UefiPayloadPkg/PayloadLoaderPeim/ElfLib/Elf64.h"
#define EFI_IMAGE_NT_HEADERS EFI_IMAGE_NT_HEADERS64
#define EFI_IMAGE_NT_OPTIONAL_HDR_MAGIC EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC
#define EFI_IMAGE_FILE_MACHINE 0
#define ELFCLASS ELFCLASS64
#define Elf_Ehdr Elf64_Ehdr
#define Elf_Shdr Elf64_Shdr
#define Elf_Sym Elf64_Sym
#define Elf_Rel Elf64_Rel
#define Elf_Rela Elf64_Rela
#define Elf_Size Elf64_Size
#define Elf_Addr Elf64_Addr
#define ELF_R_TYPE ELF64_R_TYPE
#define ELF_R_SYM ELF64_R_SYM
#endif
#define ELF_HII_SECTION_NAME ".hii"
#define MAX_PE_ALIGNMENT 0x10000
#define raise() assert(false)
typedef struct {
EFI_IMAGE_DEBUG_DIRECTORY_ENTRY Dir;
EFI_IMAGE_DEBUG_CODEVIEW_NB10_ENTRY Nb10;
char Name[];
} DebugData;
#define PAGE(x) ((x) & ~4095U)
#define PAGE_OFF(x) ((x) & 4095U)
typedef struct {
uint64_t BaseAddress;
uint32_t EntryPointAddress;
uint16_t Machine;
uint16_t Subsystem;
bool IsXip;
} image_tool_header_info_t;
typedef struct {
char *Name;
uint8_t *Data;
uint32_t DataSize;
uint64_t ImageAddress;
uint32_t ImageSize;
bool Read;
bool Write;
bool Execute;
} image_tool_segment_t;
typedef struct {
uint32_t SegmentAlignment;
uint32_t NumSegments;
image_tool_segment_t *Segments;
} image_tool_segment_info_t;
typedef struct {
uint8_t Type;
uint32_t Target;
} image_tool_reloc_t;
typedef struct {
uint32_t NumRelocs;
bool RelocsStripped;
image_tool_reloc_t *Relocs;
} image_tool_reloc_info_t;
typedef struct {
char *SymbolsPath;
uint32_t SymbolsPathLen;
} image_tool_debug_info_t;
typedef struct {
uint32_t DebugDirAddress;
uint32_t DebugDirSize;
} image_tool_pe_datadir_info_t;
typedef struct {
void *Data;
uint32_t DataSize;
} image_tool_hii_info_t;
typedef struct {
image_tool_header_info_t HeaderInfo;
image_tool_segment_info_t SegmentInfo;
image_tool_reloc_info_t RelocInfo;
image_tool_hii_info_t HiiInfo;
image_tool_debug_info_t DebugInfo;
} image_tool_image_info_t;
void
ToolImageDestruct (
image_tool_image_info_t *Image
);
bool
ImageConvertToXip (
image_tool_image_info_t *Image
);
RETURN_STATUS
ToolContextConstructPe (
OUT image_tool_image_info_t *Image,
IN const void *File,
IN size_t FileSize
);
bool
CheckToolImage (
image_tool_image_info_t *Image
);
void *
ToolImageEmitPe (
const image_tool_image_info_t *Image,
uint32_t *FileSize
);
RETURN_STATUS
ScanElf (
IN const void *File,
IN uint32_t FileSize,
IN const char *SymbolsPath
);
RETURN_STATUS
ConstructHii (
IN const char *FileNames[],
IN UINT32 NumOfFiles,
IN GUID *HiiGuid,
OUT void **Hii,
OUT UINT32 *HiiSize,
IN BOOLEAN IsElf
);
#endif // IMAGE_TOOL_H

View File

@ -0,0 +1,104 @@
## @file
# Windows makefile for 'ImageTool' module build.
#
# Copyright (c) 2022, Mikhail Krichanov. All rights reserved.
# SPDX-License-Identifier: BSD-3-Clause
#
!INCLUDE ..\Source\C\Makefiles\ms.common
APP = ImageTool
OC_USER = ..\..\OpenCorePkg
UDK_PATH = ..\..
UDK_ARCH = $(HOST_ARCH)
OUT_DIR = .\Windows_$(INFIX)
OV = $(UDK_PATH)\MdePkg\Library\BaseOverflowLib
PE = $(UDK_PATH)\MdePkg\Library\BasePeCoffLib2
UA = $(UDK_PATH)\MdePkg\Library\BaseUefiImageExtraActionLibNull
OBJECTS = ImageTool.obj Image.obj PeEmit.obj PeScan.obj ElfScan.obj BinEmit.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
BASE = $(UDK_PATH)\MdePkg\Library\BaseLib
OUT = $(UDK_PATH)\MdePkg\Library\UefiDebugLibConOut
PRIN = $(UDK_PATH)\MdePkg\Library\BasePrintLib
ERRO = $(UDK_PATH)\MdePkg\Library\BaseDebugPrintErrorLevelLib
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
OBJECTS = $(OBJECTS) {$(OUT)}DebugLib.obj {$(PRIN)}PrintLib.obj PrintLibInternal.obj {$(ERRO)}BaseDebugPrintErrorLevelLib.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
INC = -I . -I $(OC_USER)\User\Include -I $(OC_USER)\Include\Acidanthera
INC = $(INC) -I $(UDK_PATH)\MdePkg\Include -I $(UDK_PATH)\MdePkg\Include\Library -I $(UDK_PATH)\MdePkg\Include\$(UDK_ARCH)
INC = $(INC) -I $(UDK_PATH)\MdePkg\Library\BaseLib -I $(UDK_PATH)\MdeModulePkg\Include -I $(UDK_PATH)\UefiCpuPkg\Include
INC = $(INC) /FI $(OC_USER)\User\Include\UserPcd.h /FI $(UDK_PATH)\MdePkg\Include\Base.h /FI $(OC_USER)\User\Include\UserGlobalVar.h
all:
-if not exist $(OUT_DIR)64 mkdir $(OUT_DIR)64
$(MAKE) $(APP)64 CFLAGS="$(CFLAGS) /D EFI_TARGET64" INFIX=64
-if not exist $(OUT_DIR)32 mkdir $(OUT_DIR)32
$(MAKE) $(APP)32 CFLAGS="$(CFLAGS) /D EFI_TARGET32" INFIX=32
$(APP)$(INFIX) : $(OBJECTS)
-@if not exist $(BIN_PATH) mkdir $(BIN_PATH)
@cd $(OUT_DIR)
$(LD) /nologo /debug /OPT:REF /OPT:ICF=10 /incremental:no /nodefaultlib:libc.lib /out:..\$@ $(LIBS) $**
@copy /y ..\$@ $(BIN_PATH)\$@.exe
.PHONY:clean
.PHONY:cleanall
clean:
del /f /q $(OUT_DIR)32 $(OUT_DIR)64 $(APP)32 $(APP)64 *.pdb > nul
cleanall:
del /f /q $(OUT_DIR)32 $(OUT_DIR)64 *.pdb $(BIN_PATH)\$(APP)64.exe $(BIN_PATH)\$(APP)32.exe > nul
.c.obj :
$(CC) -c $(CFLAGS) $(INC) $< -Fo$@
@move $@ $(OUT_DIR)\
{$(OV)}.c.obj :
$(CC) -c $(CFLAGS) $(INC) $< -Fo$@
@move $@ $(OUT_DIR)\
{$(PE)}.c.obj :
$(CC) -c $(CFLAGS) $(INC) $< -Fo$@
@move $@ $(OUT_DIR)\
{$(UA)}.c.obj :
$(CC) -c $(CFLAGS) $(INC) $< -Fo$@
@move $@ $(OUT_DIR)\
{$(BASE)}.c.obj :
$(CC) -c $(CFLAGS) $(INC) /wd 4005 $< -Fo$@
@move $@ $(OUT_DIR)\
{$(BMPN)}.c.obj :
$(CC) -c $(CFLAGS) $(INC) $< -Fo$@
@move $@ $(OUT_DIR)\
{$(CMEM)}.c.obj :
$(CC) -c $(CFLAGS) $(INC) $< -Fo$@
@move $@ $(OUT_DIR)\
{$(OUT)}.c.obj :
$(CC) -c $(CFLAGS) $(INC) $< -Fo$@
@move $@ $(OUT_DIR)\
{$(PRIN)}.c.obj :
$(CC) -c $(CFLAGS) $(INC) /wd 4005 $< -Fo$@
@move $@ $(OUT_DIR)\
{$(ERRO)}.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)\

View File

@ -0,0 +1,965 @@
/** @file
Copyright (c) 2021, Marvin Häuser. All rights reserved.
Copyright (c) 2022, Mikhail Krichanov. All rights reserved.
SPDX-License-Identifier: BSD-3-Clause
**/
#include "ImageTool.h"
typedef struct {
uint8_t NumExtraSections;
uint32_t SizeOfHeaders;
uint8_t NumberOfRvaAndSizes;
uint16_t SizeOfOptionalHeader;
uint32_t SectionHeadersSize;
uint32_t ExtraSectionHeadersSize;
} image_tool_emit_pe_hdr_info_t;
typedef struct {
const image_tool_image_info_t *Image;
EFI_IMAGE_NT_HEADERS *PeHdr;
image_tool_emit_pe_hdr_info_t HdrInfo;
uint32_t SectionsSize;
uint32_t ExtraSectionsSize;
uint32_t UnsignedFileSize;
uint32_t RelocTableSize;
uint32_t DebugTableSize;
uint32_t FileAlignment;
} image_tool_pe_emit_context_t;
static
bool
EmitPeGetHeaderSizes (
const image_tool_image_info_t *Image,
image_tool_emit_pe_hdr_info_t *HdrInfo
)
{
assert (Image != NULL);
assert (HdrInfo != NULL);
if (Image->RelocInfo.NumRelocs > 0) {
HdrInfo->ExtraSectionHeadersSize += sizeof (EFI_IMAGE_SECTION_HEADER);
}
if (Image->HiiInfo.DataSize > 0) {
HdrInfo->ExtraSectionHeadersSize += sizeof (EFI_IMAGE_SECTION_HEADER);
}
if (Image->DebugInfo.SymbolsPath != NULL) {
HdrInfo->ExtraSectionHeadersSize += sizeof (EFI_IMAGE_SECTION_HEADER);
}
HdrInfo->SectionHeadersSize = (uint32_t)Image->SegmentInfo.NumSegments * sizeof (EFI_IMAGE_SECTION_HEADER);
HdrInfo->NumberOfRvaAndSizes = EFI_IMAGE_NUMBER_OF_DIRECTORY_ENTRIES;
HdrInfo->SizeOfOptionalHeader = sizeof (EFI_IMAGE_NT_HEADERS) - sizeof (EFI_IMAGE_NT_HEADERS_COMMON_HDR)
+ HdrInfo->NumberOfRvaAndSizes * sizeof (EFI_IMAGE_DATA_DIRECTORY);
HdrInfo->SizeOfHeaders = sizeof (EFI_IMAGE_DOS_HEADER) + sizeof (EFI_IMAGE_NT_HEADERS)
+ HdrInfo->NumberOfRvaAndSizes * sizeof (EFI_IMAGE_DATA_DIRECTORY)
+ HdrInfo->SectionHeadersSize + HdrInfo->ExtraSectionHeadersSize;
return true;
}
static
bool
EmitPeGetSectionsSize (
const image_tool_pe_emit_context_t *Context,
uint32_t *SectionsSize
)
{
const image_tool_image_info_t *Image;
uint8_t Index;
uint32_t DataSize;
bool Overflow;
assert (Context != NULL);
assert (SectionsSize != NULL);
Image = Context->Image;
*SectionsSize = 0;
for (Index = 0; Index < Image->SegmentInfo.NumSegments; ++Index) {
Overflow = BaseOverflowAlignUpU32 (
Image->SegmentInfo.Segments[Index].DataSize,
Context->FileAlignment,
&DataSize
);
if (Overflow) {
raise ();
return false;
}
Overflow = BaseOverflowAddU32 (*SectionsSize, DataSize, SectionsSize);
if (Overflow) {
raise ();
return false;
}
}
return true;
}
static
bool
EmitPeGetRelocSectionSize (
const image_tool_image_info_t *Image,
uint32_t *RelocsSize
)
{
uint32_t RelocTableSize;
uint32_t BlockAddress;
uint32_t BlockSize;
uint32_t Index;
uint32_t RelocAddress;
assert (Image != NULL);
assert (RelocsSize != NULL);
if (Image->RelocInfo.NumRelocs == 0) {
*RelocsSize = 0;
return true;
}
assert (Image->RelocInfo.NumRelocs <= MAX_UINT32);
RelocTableSize = 0;
BlockAddress = PAGE(Image->RelocInfo.Relocs[0].Target);
BlockSize = sizeof (EFI_IMAGE_BASE_RELOCATION_BLOCK);
for (Index = 0; Index < Image->RelocInfo.NumRelocs; ++Index) {
RelocAddress = PAGE(Image->RelocInfo.Relocs[Index].Target);
if (RelocAddress != BlockAddress) {
BlockSize = ALIGN_VALUE (BlockSize, 4);
RelocTableSize += BlockSize;
BlockAddress = RelocAddress;
BlockSize = sizeof (EFI_IMAGE_BASE_RELOCATION_BLOCK);
}
BlockSize += sizeof (UINT16);
}
BlockSize = ALIGN_VALUE (BlockSize, 4);
RelocTableSize += BlockSize;
*RelocsSize = RelocTableSize;
return true;
}
static
void
EmitPeGetDebugSectionSize (
const image_tool_image_info_t *Image,
uint32_t *DebugSize
)
{
uint32_t Size;
assert (Image != NULL);
assert (DebugSize != NULL);
Size = 0;
if (Image->DebugInfo.SymbolsPath != NULL) {
Size = sizeof (DebugData) + Image->DebugInfo.SymbolsPathLen + 1;
}
*DebugSize = Size;
}
static
bool
EmitPeGetExtraSectionsSize (
image_tool_pe_emit_context_t *Context,
uint32_t *SectionsSize
)
{
const image_tool_image_info_t *Image;
bool Result;
uint32_t AlignedRelocTableSize;
bool Overflow;
uint32_t AlignedDebugTableSize;
uint32_t AlignedHiiTableSize;
assert (Context != NULL);
assert (SectionsSize != NULL);
Image = Context->Image;
Result = EmitPeGetRelocSectionSize (Image, &Context->RelocTableSize);
if (!Result) {
raise ();
return false;
}
EmitPeGetDebugSectionSize (Image, &Context->DebugTableSize);
Overflow = BaseOverflowAlignUpU32 (
Context->RelocTableSize,
Context->FileAlignment,
&AlignedRelocTableSize
);
if (Overflow) {
raise ();
return false;
}
Overflow = BaseOverflowAlignUpU32 (
Context->DebugTableSize,
Context->FileAlignment,
&AlignedDebugTableSize
);
if (Overflow) {
raise ();
return false;
}
Overflow = BaseOverflowAlignUpU32 (
Context->Image->HiiInfo.DataSize,
Context->FileAlignment,
&AlignedHiiTableSize
);
if (Overflow) {
raise ();
return false;
}
Overflow = BaseOverflowAddU32 (
AlignedRelocTableSize,
AlignedDebugTableSize,
SectionsSize
);
if (Overflow) {
raise ();
return false;
}
Overflow = BaseOverflowAddU32 (
*SectionsSize,
AlignedHiiTableSize,
SectionsSize
);
if (Overflow) {
raise ();
return false;
}
return true;
}
static
bool
ToolImageEmitPeSectionHeaders (
const image_tool_pe_emit_context_t *Context,
uint8_t **Buffer,
uint32_t *BufferSize,
uint32_t AlignedHeaderSize
)
{
const image_tool_image_info_t *Image;
uint16_t SectionHeadersSize;
uint32_t SectionOffset;
EFI_IMAGE_SECTION_HEADER *Sections;
uint8_t Index;
assert (Context != NULL);
assert (Buffer != NULL);
assert (BufferSize != NULL);
Image = Context->Image;
SectionHeadersSize = (uint16_t) (Image->SegmentInfo.NumSegments * sizeof (EFI_IMAGE_SECTION_HEADER));
SectionOffset = AlignedHeaderSize;
Sections = (void *) *Buffer;
assert (SectionHeadersSize <= *BufferSize);
for (Index = 0; Index < Image->SegmentInfo.NumSegments; ++Index) {
assert (Sections[Index].Characteristics == 0);
if (Image->SegmentInfo.Segments[Index].Read) {
Sections[Index].Characteristics |= EFI_IMAGE_SCN_MEM_READ;
}
if (Image->SegmentInfo.Segments[Index].Write) {
Sections[Index].Characteristics |= EFI_IMAGE_SCN_MEM_WRITE;
}
if (Image->SegmentInfo.Segments[Index].Execute) {
Sections[Index].Characteristics |= EFI_IMAGE_SCN_MEM_EXECUTE | EFI_IMAGE_SCN_CNT_CODE;
} else {
Sections[Index].Characteristics |= EFI_IMAGE_SCN_CNT_INITIALIZED_DATA;
}
Sections[Index].PointerToRawData = SectionOffset;
Sections[Index].VirtualAddress = SectionOffset;
Sections[Index].SizeOfRawData = ALIGN_VALUE (Image->SegmentInfo.Segments[Index].DataSize, Context->FileAlignment);
Sections[Index].VirtualSize = Image->SegmentInfo.Segments[Index].ImageSize;
strncpy (
(char *) Sections[Index].Name,
Image->SegmentInfo.Segments[Index].Name,
sizeof (Sections[Index].Name)
);
SectionOffset += Sections[Index].SizeOfRawData;
}
*BufferSize -= SectionHeadersSize;
*Buffer += SectionHeadersSize;
assert (SectionHeadersSize == Context->HdrInfo.SectionHeadersSize);
return true;
}
static
bool
ToolImageEmitPeExtraSectionHeaders (
image_tool_pe_emit_context_t *Context,
uint8_t **Buffer,
uint32_t *BufferSize,
uint32_t AlignedHeaderSize
)
{
uint32_t SectionHeadersSize;
EFI_IMAGE_SECTION_HEADER *Section;
uint32_t SectionOffset;
assert (Context != NULL);
assert (Buffer != NULL);
assert (BufferSize != NULL);
SectionHeadersSize = 0;
SectionOffset = AlignedHeaderSize + Context->SectionsSize;
if (Context->Image->HiiInfo.DataSize > 0) {
++Context->PeHdr->CommonHeader.FileHeader.NumberOfSections;
assert (sizeof (EFI_IMAGE_SECTION_HEADER) <= *BufferSize);
Section = (void *) *Buffer;
strncpy ((char *)Section->Name, ".rsrc", sizeof (Section->Name));
Section->SizeOfRawData = ALIGN_VALUE (Context->Image->HiiInfo.DataSize, Context->FileAlignment);
Section->VirtualSize = Section->SizeOfRawData;
Section->Characteristics = EFI_IMAGE_SCN_CNT_INITIALIZED_DATA | EFI_IMAGE_SCN_MEM_READ;
Section->PointerToRawData = SectionOffset;
Section->VirtualAddress = Section->PointerToRawData;
SectionOffset += Section->SizeOfRawData;
Context->PeHdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE].Size = Context->Image->HiiInfo.DataSize;
Context->PeHdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE].VirtualAddress = Section->PointerToRawData;
*BufferSize -= sizeof (EFI_IMAGE_SECTION_HEADER);
*Buffer += sizeof (EFI_IMAGE_SECTION_HEADER);
SectionHeadersSize += sizeof (EFI_IMAGE_SECTION_HEADER);
}
if (Context->RelocTableSize > 0) {
++Context->PeHdr->CommonHeader.FileHeader.NumberOfSections;
assert (sizeof (EFI_IMAGE_SECTION_HEADER) <= *BufferSize);
Section = (void *) *Buffer;
strncpy ((char *)Section->Name, ".reloc", sizeof (Section->Name));
Section->SizeOfRawData = ALIGN_VALUE (Context->RelocTableSize, Context->FileAlignment);
Section->VirtualSize = Section->SizeOfRawData;
Section->Characteristics = EFI_IMAGE_SCN_CNT_INITIALIZED_DATA
| EFI_IMAGE_SCN_MEM_DISCARDABLE | EFI_IMAGE_SCN_MEM_READ;
Section->PointerToRawData = SectionOffset;
Section->VirtualAddress = Section->PointerToRawData;
SectionOffset += Section->SizeOfRawData;
Context->PeHdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size = Context->RelocTableSize;
Context->PeHdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress = Section->PointerToRawData;
*BufferSize -= sizeof (EFI_IMAGE_SECTION_HEADER);
*Buffer += sizeof (EFI_IMAGE_SECTION_HEADER);
SectionHeadersSize += sizeof (EFI_IMAGE_SECTION_HEADER);
}
if (Context->DebugTableSize > 0) {
++Context->PeHdr->CommonHeader.FileHeader.NumberOfSections;
assert (sizeof (EFI_IMAGE_SECTION_HEADER) <= *BufferSize);
Section = (void *) *Buffer;
strncpy ((char *)Section->Name, ".debug", sizeof (Section->Name));
Section->SizeOfRawData = ALIGN_VALUE (Context->DebugTableSize, Context->FileAlignment);
Section->VirtualSize = Section->SizeOfRawData;
Section->Characteristics = EFI_IMAGE_SCN_CNT_INITIALIZED_DATA | EFI_IMAGE_SCN_MEM_READ;
Section->PointerToRawData = SectionOffset;
Section->VirtualAddress = Section->PointerToRawData;
SectionOffset += Section->SizeOfRawData;
Context->PeHdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].Size = sizeof (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY);
Context->PeHdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress = Section->VirtualAddress;
*BufferSize -= sizeof (EFI_IMAGE_SECTION_HEADER);
*Buffer += sizeof (EFI_IMAGE_SECTION_HEADER);
SectionHeadersSize += sizeof (EFI_IMAGE_SECTION_HEADER);
}
assert (SectionHeadersSize == Context->HdrInfo.ExtraSectionHeadersSize);
assert (SectionOffset == Context->UnsignedFileSize);
return true;
}
static
bool
ToolImageEmitPeHeaders (
image_tool_pe_emit_context_t *Context,
uint8_t **Buffer,
uint32_t *BufferSize,
uint32_t AlignedHeaderSize
)
{
const image_tool_image_info_t *Image;
EFI_IMAGE_DOS_HEADER *DosHdr;
EFI_IMAGE_NT_HEADERS *PePlusHdr;
bool Result;
uint32_t HeaderPadding;
assert (Context != NULL);
assert (Buffer != NULL);
assert (BufferSize != NULL);
assert (sizeof (EFI_IMAGE_DOS_HEADER) <= *BufferSize);
Image = Context->Image;
DosHdr = (void *) *Buffer;
DosHdr->e_magic = EFI_IMAGE_DOS_SIGNATURE;
DosHdr->e_lfanew = sizeof (EFI_IMAGE_DOS_HEADER);
*BufferSize -= sizeof (EFI_IMAGE_DOS_HEADER);
*Buffer += sizeof (EFI_IMAGE_DOS_HEADER);
assert (sizeof (EFI_IMAGE_NT_HEADERS) <= *BufferSize);
PePlusHdr = (EFI_IMAGE_NT_HEADERS *)(VOID *) *Buffer;
PePlusHdr->CommonHeader.Signature = EFI_IMAGE_NT_SIGNATURE;
PePlusHdr->CommonHeader.FileHeader.Machine = Image->HeaderInfo.Machine;
PePlusHdr->CommonHeader.FileHeader.NumberOfSections = (UINT16)Image->SegmentInfo.NumSegments;
PePlusHdr->CommonHeader.FileHeader.SizeOfOptionalHeader = Context->HdrInfo.SizeOfOptionalHeader;
PePlusHdr->CommonHeader.FileHeader.Characteristics =
EFI_IMAGE_FILE_EXECUTABLE_IMAGE | EFI_IMAGE_FILE_LINE_NUMS_STRIPPED |
EFI_IMAGE_FILE_LOCAL_SYMS_STRIPPED | EFI_IMAGE_FILE_LARGE_ADDRESS_AWARE;
if (Image->RelocInfo.RelocsStripped) {
PePlusHdr->CommonHeader.FileHeader.Characteristics |= EFI_IMAGE_FILE_RELOCS_STRIPPED;
}
PePlusHdr->Magic = EFI_IMAGE_NT_OPTIONAL_HDR_MAGIC;
PePlusHdr->AddressOfEntryPoint = Image->HeaderInfo.EntryPointAddress;
PePlusHdr->SectionAlignment = Image->SegmentInfo.SegmentAlignment;
PePlusHdr->FileAlignment = Context->FileAlignment;
PePlusHdr->SizeOfHeaders = AlignedHeaderSize;
PePlusHdr->SizeOfImage = AlignedHeaderSize;
PePlusHdr->ImageBase = (UINTN)Image->HeaderInfo.BaseAddress;
PePlusHdr->Subsystem = Image->HeaderInfo.Subsystem;
PePlusHdr->NumberOfRvaAndSizes = Context->HdrInfo.NumberOfRvaAndSizes;
STATIC_ASSERT(
OFFSET_OF(EFI_IMAGE_NT_HEADERS, DataDirectory) == sizeof (EFI_IMAGE_NT_HEADERS),
"The following code needs to be updated to consider padding."
);
Context->PeHdr = PePlusHdr;
*BufferSize -= sizeof (EFI_IMAGE_NT_HEADERS) + PePlusHdr->NumberOfRvaAndSizes * sizeof (EFI_IMAGE_DATA_DIRECTORY);
*Buffer += sizeof (EFI_IMAGE_NT_HEADERS) + PePlusHdr->NumberOfRvaAndSizes * sizeof (EFI_IMAGE_DATA_DIRECTORY);
Result = ToolImageEmitPeSectionHeaders (Context, Buffer, BufferSize, AlignedHeaderSize);
if (!Result) {
return false;
}
Result = ToolImageEmitPeExtraSectionHeaders (Context, Buffer, BufferSize, AlignedHeaderSize);
if (!Result) {
return false;
}
HeaderPadding = AlignedHeaderSize - Context->HdrInfo.SizeOfHeaders;
assert (HeaderPadding <= *BufferSize);
*BufferSize -= HeaderPadding;
*Buffer += HeaderPadding;
return true;
}
static
bool
ToolImageEmitPeSections (
const image_tool_pe_emit_context_t *Context,
uint8_t **Buffer,
uint32_t *BufferSize
)
{
const image_tool_image_info_t *Image;
uint32_t SectionsSize;
uint8_t Index;
const image_tool_segment_t *Segment;
uint32_t SectionPadding;
bool FirstCode;
#if defined(EFI_TARGET32)
bool FirstData;
#endif
assert (Context != NULL);
assert (Buffer != NULL);
assert (BufferSize != NULL);
assert (Context->SectionsSize <= *BufferSize);
Image = Context->Image;
SectionsSize = 0;
FirstCode = true;
#if defined(EFI_TARGET32)
FirstData = true;
#endif
for (Index = 0; Index < Image->SegmentInfo.NumSegments; ++Index) {
Segment = &Image->SegmentInfo.Segments[Index];
Context->PeHdr->SizeOfImage += Segment->ImageSize;
if (Segment->Execute) {
if (FirstCode) {
Context->PeHdr->BaseOfCode = (UINT32)Segment->ImageAddress;
FirstCode = false;
}
}
#if defined(EFI_TARGET32)
else {
if (FirstData) {
Context->PeHdr->BaseOfData = (UINT32)Segment->ImageAddress;
FirstData = false;
}
}
#endif
assert (Segment->DataSize <= *BufferSize);
memmove (*Buffer, Segment->Data, Segment->DataSize);
*BufferSize -= Segment->DataSize;
*Buffer += Segment->DataSize;
SectionsSize += Segment->DataSize;
SectionPadding = ALIGN_VALUE_ADDEND (
Segment->DataSize,
Context->FileAlignment
);
assert (SectionPadding <= *BufferSize);
*BufferSize -= SectionPadding;
*Buffer += SectionPadding;
SectionsSize += SectionPadding;
if (Segment->Execute) {
Context->PeHdr->BaseOfCode = MIN(Context->PeHdr->BaseOfCode, (UINT32)Segment->ImageAddress);
Context->PeHdr->SizeOfCode += Segment->ImageSize;
} else {
#if defined(EFI_TARGET32)
Context->PeHdr->BaseOfData = MIN(Context->PeHdr->BaseOfData, (UINT32)Segment->ImageAddress);
#endif
Context->PeHdr->SizeOfInitializedData += Segment->ImageSize;
}
}
assert (SectionsSize == Context->SectionsSize);
return true;
}
static
bool
ToolImageEmitPeRelocTable (
const image_tool_pe_emit_context_t *Context,
uint8_t **Buffer,
uint32_t *BufferSize
)
{
const image_tool_image_info_t *Image;
uint32_t RelocTableSize;
EFI_IMAGE_BASE_RELOCATION_BLOCK *RelocBlock;
uint32_t BlockAddress;
uint32_t BlockNumRelocs;
uint32_t Index;
uint32_t RelocAddress;
uint32_t RelocTablePadding;
assert (Context != NULL);
assert (Buffer != NULL);
assert (BufferSize != NULL);
if (Context->RelocTableSize == 0) {
return true;
}
Image = Context->Image;
Context->PeHdr->SizeOfImage += ALIGN_VALUE (Context->RelocTableSize, Image->SegmentInfo.SegmentAlignment);
assert (Image->RelocInfo.NumRelocs > 0);
assert (Image->RelocInfo.NumRelocs <= MAX_UINT32);
assert (sizeof (EFI_IMAGE_BASE_RELOCATION_BLOCK) <= *BufferSize);
RelocTableSize = 0;
RelocBlock = (void *) *Buffer;
BlockAddress = PAGE(Image->RelocInfo.Relocs[0].Target);
BlockNumRelocs = 0;
RelocBlock->VirtualAddress = BlockAddress;
RelocBlock->SizeOfBlock = sizeof (*RelocBlock);
for (Index = 0; Index < Image->RelocInfo.NumRelocs; ++Index) {
RelocAddress = PAGE(Image->RelocInfo.Relocs[Index].Target);
if (RelocAddress != BlockAddress) {
RelocBlock->SizeOfBlock = ALIGN_VALUE (RelocBlock->SizeOfBlock, 4);
assert (RelocBlock->SizeOfBlock <= *BufferSize);
*BufferSize -= RelocBlock->SizeOfBlock;
*Buffer += RelocBlock->SizeOfBlock;
RelocTableSize += RelocBlock->SizeOfBlock;
RelocBlock = (void *) *Buffer;
BlockAddress = RelocAddress;
BlockNumRelocs = 0;
RelocBlock->VirtualAddress = BlockAddress;
RelocBlock->SizeOfBlock = sizeof (*RelocBlock);
}
RelocBlock->SizeOfBlock += sizeof (*RelocBlock->Relocations);
assert (RelocBlock->SizeOfBlock <= *BufferSize);
RelocBlock->Relocations[BlockNumRelocs] = PAGE_OFF(Image->RelocInfo.Relocs[Index].Target);
RelocBlock->Relocations[BlockNumRelocs] |= ((uint16_t)Image->RelocInfo.Relocs[Index].Type) << 12U;
++BlockNumRelocs;
}
RelocBlock->SizeOfBlock = ALIGN_VALUE (RelocBlock->SizeOfBlock, 4);
assert (RelocBlock->SizeOfBlock <= *BufferSize);
*BufferSize -= RelocBlock->SizeOfBlock;
*Buffer += RelocBlock->SizeOfBlock;
RelocTableSize += RelocBlock->SizeOfBlock;
assert (RelocTableSize == Context->RelocTableSize);
RelocTablePadding = ALIGN_VALUE_ADDEND (
RelocTableSize,
Context->FileAlignment
);
assert (RelocTablePadding <= *BufferSize);
*BufferSize -= RelocTablePadding;
*Buffer += RelocTablePadding;
return true;
}
typedef struct {
EFI_IMAGE_DEBUG_DIRECTORY_ENTRY CodeViewDirEntry;
EFI_IMAGE_DEBUG_CODEVIEW_RSDS_ENTRY CodeViewEntry;
uint8_t PdbPath[];
} image_tool_debug_dir_t;
STATIC_ASSERT(
OFFSET_OF(image_tool_debug_dir_t, PdbPath) == sizeof (image_tool_debug_dir_t),
"Flexible array aliases padding."
);
static
bool
ToolImageEmitPeDebugTable (
const image_tool_pe_emit_context_t *Context,
uint8_t **Buffer,
uint32_t *BufferSize
)
{
const image_tool_image_info_t *Image;
uint32_t DebugTablePadding;
DebugData *Data;
assert (Context != NULL);
assert (Buffer != NULL);
assert (BufferSize != NULL);
Image = Context->Image;
if (Context->DebugTableSize == 0) {
return true;
}
Context->PeHdr->SizeOfImage += ALIGN_VALUE (Context->DebugTableSize, Image->SegmentInfo.SegmentAlignment);
assert (Image->DebugInfo.SymbolsPathLen + 1 <= Context->DebugTableSize);
assert (Context->DebugTableSize <= *BufferSize);
Data = (DebugData *) *Buffer;
Data->Dir.Type = EFI_IMAGE_DEBUG_TYPE_CODEVIEW;
Data->Dir.SizeOfData = sizeof (EFI_IMAGE_DEBUG_CODEVIEW_NB10_ENTRY) + Image->DebugInfo.SymbolsPathLen + 1;
Data->Dir.RVA = (Context->UnsignedFileSize - ALIGN_VALUE (Context->DebugTableSize, Context->FileAlignment)) + sizeof (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY);
Data->Dir.FileOffset = Data->Dir.RVA;
Data->Nb10.Signature = CODEVIEW_SIGNATURE_NB10;
memmove (Data->Name, Image->DebugInfo.SymbolsPath, Image->DebugInfo.SymbolsPathLen + 1);
assert (sizeof (*Data) + Image->DebugInfo.SymbolsPathLen + 1 == Context->DebugTableSize);
*BufferSize -= Context->DebugTableSize;
*Buffer += Context->DebugTableSize;
DebugTablePadding = ALIGN_VALUE_ADDEND(
Context->DebugTableSize,
Context->FileAlignment
);
assert (DebugTablePadding <= *BufferSize);
*BufferSize -= DebugTablePadding;
*Buffer += DebugTablePadding;
return true;
}
static
bool
ToolImageEmitPeHiiTable (
const image_tool_pe_emit_context_t *Context,
uint8_t **Buffer,
uint32_t *BufferSize
)
{
const image_tool_image_info_t *Image;
uint32_t HiiTablePadding;
assert (Context != NULL);
assert (Buffer != NULL);
assert (BufferSize != NULL);
Image = Context->Image;
if (Image->HiiInfo.DataSize == 0) {
return true;
}
Context->PeHdr->SizeOfImage += ALIGN_VALUE (Image->HiiInfo.DataSize, Image->SegmentInfo.SegmentAlignment);
assert (Image->HiiInfo.DataSize <= *BufferSize);
memmove (*Buffer, Image->HiiInfo.Data, Image->HiiInfo.DataSize);
*BufferSize -= Image->HiiInfo.DataSize;
*Buffer += Image->HiiInfo.DataSize;
HiiTablePadding = ALIGN_VALUE_ADDEND(
Image->HiiInfo.DataSize,
Context->FileAlignment
);
assert (HiiTablePadding <= *BufferSize);
*BufferSize -= HiiTablePadding;
*Buffer += HiiTablePadding;
return true;
}
static
bool
ToolImageEmitPeExtraSections (
const image_tool_pe_emit_context_t *Context,
uint8_t **Buffer,
uint32_t *BufferSize
)
{
uint32_t OldBufferSize;
bool Result;
assert (Context != NULL);
assert (Buffer != NULL);
assert (BufferSize != NULL);
OldBufferSize = *BufferSize;
Result = ToolImageEmitPeHiiTable (Context, Buffer, BufferSize);
if (!Result) {
return false;
}
Result = ToolImageEmitPeRelocTable (Context, Buffer, BufferSize);
if (!Result) {
return false;
}
Result = ToolImageEmitPeDebugTable (Context, Buffer, BufferSize);
if (!Result) {
return false;
}
assert ((OldBufferSize - *BufferSize) == Context->ExtraSectionsSize);
return true;
}
void *
ToolImageEmitPe (
const image_tool_image_info_t *Image,
uint32_t *FileSize
)
{
image_tool_pe_emit_context_t Context;
bool Result;
uint32_t AlignedHeaderSize;
bool Overflow;
uint32_t SectionsOffset;
void *FileBuffer;
uint8_t *Buffer;
uint32_t RemainingSize;
uint32_t ExpectedSize;
assert (Image != NULL);
assert (FileSize != NULL);
memset (&Context, 0, sizeof (Context));
// FIXME: Non-XIP is not well-supported right now.
Context.FileAlignment = Image->SegmentInfo.SegmentAlignment;
Result = ImageConvertToXip ((image_tool_image_info_t *)Image);
if (!Result) {
raise ();
return NULL;
}
Context.Image = Image;
Result = EmitPeGetHeaderSizes (Image, &Context.HdrInfo);
if (!Result) {
raise ();
return NULL;
}
Overflow = BaseOverflowAlignUpU32 (
Context.HdrInfo.SizeOfHeaders,
Context.FileAlignment,
&AlignedHeaderSize
);
if (Overflow) {
raise ();
return NULL;
}
if (AlignedHeaderSize > Image->SegmentInfo.Segments[0].ImageAddress) {
raise ();
return NULL;
}
AlignedHeaderSize = (uint32_t)Image->SegmentInfo.Segments[0].ImageAddress;
Result = EmitPeGetSectionsSize (&Context, &Context.SectionsSize);
if (!Result) {
raise ();
return NULL;
}
Overflow = BaseOverflowAddU32 (
AlignedHeaderSize,
Context.SectionsSize,
&SectionsOffset
);
if (Overflow) {
raise ();
return NULL;
}
Result = EmitPeGetExtraSectionsSize (&Context, &Context.ExtraSectionsSize);
if (!Result) {
raise ();
return NULL;
}
Overflow = BaseOverflowAddU32 (
SectionsOffset,
Context.ExtraSectionsSize,
&Context.UnsignedFileSize
);
if (Overflow) {
raise ();
return NULL;
}
FileBuffer = calloc (1, Context.UnsignedFileSize);
if (FileBuffer == NULL) {
raise ();
return NULL;
}
Buffer = FileBuffer;
RemainingSize = Context.UnsignedFileSize;
ExpectedSize = Context.UnsignedFileSize;
Result = ToolImageEmitPeHeaders (&Context, &Buffer, &RemainingSize, AlignedHeaderSize);
if (!Result) {
raise ();
free (FileBuffer);
return NULL;
}
ExpectedSize -= AlignedHeaderSize;
assert (RemainingSize == ExpectedSize);
Result = ToolImageEmitPeSections (&Context, &Buffer, &RemainingSize);
if (!Result) {
raise ();
free (FileBuffer);
return NULL;
}
ExpectedSize -= Context.SectionsSize;
assert (RemainingSize == ExpectedSize);
Result = ToolImageEmitPeExtraSections (&Context, &Buffer, &RemainingSize);
if (!Result) {
raise ();
free (FileBuffer);
return NULL;
}
ExpectedSize -= Context.ExtraSectionsSize;
assert (RemainingSize == ExpectedSize);
assert (RemainingSize == 0);
Context.PeHdr->SizeOfInitializedData += Context.ExtraSectionsSize;
*FileSize = Context.UnsignedFileSize;
return FileBuffer;
}

View File

@ -0,0 +1,433 @@
/** @file
Copyright (c) 2021, Marvin Häuser. All rights reserved.
Copyright (c) 2022, Mikhail Krichanov. All rights reserved.
SPDX-License-Identifier: BSD-3-Clause
**/
#include "ImageTool.h"
#define PE_COFF_SECT_NAME_RELOC ".reloc\0"
#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,
IN PE_COFF_LOADER_IMAGE_CONTEXT *Context
)
{
BOOLEAN Overflow;
UINT32 RelocBlockRvaMax;
UINT32 TopOfRelocDir;
UINT32 RelocBlockRva;
const EFI_IMAGE_BASE_RELOCATION_BLOCK *RelocBlock;
UINT32 RelocBlockSize;
UINT32 SizeOfRelocs;
UINT32 NumRelocs;
UINT32 RelocIndex;
uint32_t RelocDirSize;
const char *ImageBuffer;
UINT16 RelocType;
UINT16 RelocOffset;
assert (RelocInfo != NULL);
assert (Context != NULL);
RelocInfo->RelocsStripped = false;
// FIXME: PE/COFF context access
RelocBlockRva = Context->RelocDirRva;
RelocDirSize = Context->RelocDirSize;
//
// Verify the Relocation Directory is not empty.
//
if (RelocDirSize == 0) {
return true;
}
RelocInfo->Relocs = calloc (RelocDirSize / sizeof (UINT16), sizeof (*RelocInfo->Relocs));
if (RelocInfo->Relocs == NULL) {
fprintf (stderr, "ImageTool: Could not allocate memory for Relocs[]\n");
return false;
}
TopOfRelocDir = RelocBlockRva + RelocDirSize;
RelocBlockRvaMax = TopOfRelocDir - sizeof (EFI_IMAGE_BASE_RELOCATION_BLOCK);
//
// Align TopOfRelocDir because, if the policy does not demand Relocation Block
// sizes to be aligned, the code below will manually align them. Thus, the
// end offset of the last Relocation Block must be compared to a manually
// aligned Relocation Directoriy end offset.
//
Overflow = BaseOverflowAlignUpU32 (
TopOfRelocDir,
ALIGNOF (EFI_IMAGE_BASE_RELOCATION_BLOCK),
&TopOfRelocDir
);
if (Overflow) {
fprintf (stderr, "ImageTool: Overflow during TopOfRelocDir calculation\n");
return false;
}
//
// Apply all Base Relocations of the Image.
//
ImageBuffer = (char *)PeCoffLoaderGetImageAddress (Context);
while (RelocBlockRva <= RelocBlockRvaMax) {
RelocBlock = (const EFI_IMAGE_BASE_RELOCATION_BLOCK *)(const void *)(ImageBuffer + RelocBlockRva);
//
// Verify the Base Relocation Block size is well-formed.
//
Overflow = BaseOverflowSubU32 (
RelocBlock->SizeOfBlock,
sizeof (EFI_IMAGE_BASE_RELOCATION_BLOCK),
&SizeOfRelocs
);
if (Overflow) {
fprintf (stderr, "ImageTool: Overflow during SizeOfRelocs calculation\n");
return false;
}
//
// Verify the Base Relocation Block is in bounds of the Relocation
// Directory.
//
if (SizeOfRelocs > RelocBlockRvaMax - RelocBlockRva) {
fprintf (stderr, "ImageTool: Base Relocation Block is out of bounds of the Relocation Directory\n");
return false;
}
//
// This arithmetic cannot overflow because we know
// 1) RelocBlock->SizeOfBlock <= RelocMax <= TopOfRelocDir
// 2) IS_ALIGNED (TopOfRelocDir, ALIGNOF (EFI_IMAGE_BASE_RELOCATION_BLOCK)).
//
RelocBlockSize = ALIGN_VALUE (
RelocBlock->SizeOfBlock,
ALIGNOF (EFI_IMAGE_BASE_RELOCATION_BLOCK)
);
//
// This division is safe due to the guarantee made above.
//
NumRelocs = SizeOfRelocs / sizeof (*RelocBlock->Relocations);
//
// Process all Base Relocations of the current Block.
//
for (RelocIndex = 0; RelocIndex < NumRelocs; ++RelocIndex) {
RelocType = IMAGE_RELOC_TYPE (RelocBlock->Relocations[RelocIndex]);
RelocOffset = IMAGE_RELOC_OFFSET (RelocBlock->Relocations[RelocIndex]);
// FIXME: Make separate functions for UE
switch (RelocType) {
case EFI_IMAGE_REL_BASED_ABSOLUTE:
continue;
case EFI_IMAGE_REL_BASED_HIGHLOW:
case EFI_IMAGE_REL_BASED_DIR64:
RelocInfo->Relocs[RelocInfo->NumRelocs].Type = (uint8_t)RelocType;
break;
default:
fprintf (stderr, "ImageTool: Unknown RelocType = 0x%x\n", RelocType);
return false;
}
RelocInfo->Relocs[RelocInfo->NumRelocs].Target = RelocBlock->VirtualAddress + RelocOffset;
++RelocInfo->NumRelocs;
}
//
// This arithmetic cannot overflow because it has been checked that the
// Image Base Relocation Block is in bounds of the Image buffer.
//
RelocBlockRva += RelocBlockSize;
}
//
// Verify the Relocation Directory size matches the contained data.
//
if (RelocBlockRva != TopOfRelocDir) {
fprintf (stderr, "ImageTool: Relocation Directory size does not match the contained data\n");
return false;
}
return true;
}
static
bool
ScanPeGetSegmentInfo (
OUT image_tool_segment_info_t *SegmentInfo,
OUT image_tool_hii_info_t *HiiInfo,
IN PE_COFF_LOADER_IMAGE_CONTEXT *Context
)
{
const EFI_IMAGE_SECTION_HEADER *Section;
uint32_t NumSections;
image_tool_segment_t *ImageSegment;
const char *ImageBuffer;
uint32_t Index;
UINT32 Size;
assert (SegmentInfo != NULL);
assert (HiiInfo != NULL);
assert (Context != NULL);
SegmentInfo->SegmentAlignment = PeCoffGetSectionAlignment (Context);
NumSections = PeCoffGetSectionTable (Context, &Section);
SegmentInfo->Segments = calloc (NumSections, sizeof (*SegmentInfo->Segments));
if (SegmentInfo->Segments == NULL) {
fprintf (stderr, "ImageTool: Could not allocate memory for Segments[]\n");
return false;
}
ImageBuffer = (char *)PeCoffLoaderGetImageAddress (Context);
ImageSegment = SegmentInfo->Segments;
for (Index = 0; Index < NumSections; ++Index, ++Section) {
STATIC_ASSERT (
sizeof(PE_COFF_SECT_NAME_RELOC) == sizeof(Section->Name) &&
sizeof(PE_COFF_SECT_NAME_RESRC) == sizeof(Section->Name) &&
sizeof(PE_COFF_SECT_NAME_DEBUG) == sizeof(Section->Name),
"Section names exceed section name bounds."
);
if ((Section->Characteristics & EFI_IMAGE_SCN_MEM_DISCARDABLE) == 0
&& memcmp (Section->Name, PE_COFF_SECT_NAME_RELOC, sizeof (Section->Name)) != 0
&& memcmp (Section->Name, PE_COFF_SECT_NAME_RESRC, sizeof (Section->Name)) != 0
&& memcmp (Section->Name, PE_COFF_SECT_NAME_DEBUG, sizeof (Section->Name)) != 0) {
ImageSegment->Name = calloc (1, sizeof (Section->Name));
if (ImageSegment->Name == NULL) {
fprintf (stderr, "ImageTool: Could not allocate memory for Segment Name\n");
return false;
}
memmove (ImageSegment->Name, Section->Name, sizeof (Section->Name));
Size = ALIGN_VALUE (Section->VirtualSize, SegmentInfo->SegmentAlignment);
ImageSegment->Data = calloc (1, Size);
if (ImageSegment->Data == NULL) {
fprintf (stderr, "ImageTool: Could not allocate memory for Segment Data\n");
free (ImageSegment->Name);
return false;
}
memmove (
ImageSegment->Data,
ImageBuffer + Section->VirtualAddress,
Section->VirtualSize
);
ImageSegment->DataSize = Size;
ImageSegment->ImageAddress = Section->VirtualAddress;
ImageSegment->ImageSize = Size;
ImageSegment->Read = (Section->Characteristics & EFI_IMAGE_SCN_MEM_READ) != 0;
ImageSegment->Write = (Section->Characteristics & EFI_IMAGE_SCN_MEM_WRITE) != 0;
ImageSegment->Execute = (Section->Characteristics & EFI_IMAGE_SCN_MEM_EXECUTE) != 0;
++SegmentInfo->NumSegments;
++ImageSegment;
} else if (memcmp (Section->Name, PE_COFF_SECT_NAME_RESRC, sizeof (Section->Name)) == 0) {
Size = ALIGN_VALUE (Section->VirtualSize, SegmentInfo->SegmentAlignment);
HiiInfo->Data = calloc (1, Size);
if (HiiInfo->Data == NULL) {
fprintf (stderr, "ImageTool: Could not allocate memory for Hii Data\n");
return false;
}
memmove (
HiiInfo->Data,
ImageBuffer + Section->VirtualAddress,
Section->VirtualSize
);
HiiInfo->DataSize = Size;
}
}
return true;
}
bool
ScanPeGetDebugInfo (
OUT image_tool_debug_info_t *DebugInfo,
IN PE_COFF_LOADER_IMAGE_CONTEXT *Context
)
{
const CHAR8 *PdbPath;
UINT32 PdbPathSize;
RETURN_STATUS Status;
assert (DebugInfo != NULL);
assert (Context != NULL);
Status = PeCoffGetPdbPath (Context, &PdbPath, &PdbPathSize);
if (Status == RETURN_NOT_FOUND) {
return true;
}
if (RETURN_ERROR (Status)) {
fprintf (stderr, "ImageTool: Could not get PdbPath\n");
return false;
}
DebugInfo->SymbolsPath = malloc (PdbPathSize);
if (DebugInfo->SymbolsPath == NULL) {
fprintf (stderr, "ImageTool: Could not allocate memory for SymbolsPath\n");
return false;
}
memmove (DebugInfo->SymbolsPath, PdbPath, PdbPathSize);
assert (PdbPathSize >= 1);
assert (DebugInfo->SymbolsPath[PdbPathSize - 1] == '\0');
DebugInfo->SymbolsPathLen = PdbPathSize - 1;
return true;
}
bool
ScanPeGetHiiInfo (
OUT image_tool_hii_info_t *HiiInfo,
IN PE_COFF_LOADER_IMAGE_CONTEXT *Context
)
{
UINT32 HiiRva;
UINT32 HiiSize;
RETURN_STATUS Status;
const char *ImageBuffer;
assert (HiiInfo != NULL);
assert (Context != NULL);
Status = PeCoffGetHiiDataRva (Context, &HiiRva, &HiiSize);
if (Status == RETURN_NOT_FOUND) {
return true;
}
if (RETURN_ERROR (Status)) {
fprintf (stderr, "ImageTool: Could not get HiiRva\n");
return false;
}
HiiInfo->Data = calloc (1, HiiSize);
if (HiiInfo->Data == NULL) {
fprintf (stderr, "ImageTool: Could not allocate memory for HiiInfo Data\n");
return false;
}
ImageBuffer = (char *)PeCoffLoaderGetImageAddress (Context);
memmove (HiiInfo->Data, ImageBuffer + HiiRva, HiiSize);
HiiInfo->DataSize = HiiSize;
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, &Image->HiiInfo, &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;
}
FreeAlignedPages (Destination, DestinationPages);
return RETURN_SUCCESS;
}

View File

@ -9,13 +9,13 @@
!ERROR "BASE_TOOLS_PATH is not set! Please run toolsetup.bat first!"
!ENDIF
SUBDIRS = $(BASE_TOOLS_PATH)\Source\C $(BASE_TOOLS_PATH)\Source\Python
SUBDIRS = $(BASE_TOOLS_PATH)\Source\C $(BASE_TOOLS_PATH)\Source\Python $(BASE_TOOLS_PATH)\ImageTool $(BASE_TOOLS_PATH)\MicroTool
all: c
c :
@if defined PYTHON_COMMAND $(PYTHON_COMMAND) $(BASE_TOOLS_PATH)\Source\C\Makefiles\NmakeSubdirs.py all $(BASE_TOOLS_PATH)\Source\C
@if not defined PYTHON_COMMAND $(PYTHON_HOME)\python.exe $(BASE_TOOLS_PATH)\Source\C\Makefiles\NmakeSubdirs.py all $(BASE_TOOLS_PATH)\Source\C
@if defined PYTHON_COMMAND $(PYTHON_COMMAND) $(BASE_TOOLS_PATH)\Source\C\Makefiles\NmakeSubdirs.py all $(BASE_TOOLS_PATH)\Source\C $(BASE_TOOLS_PATH)\ImageTool $(BASE_TOOLS_PATH)\MicroTool
@if not defined PYTHON_COMMAND $(PYTHON_HOME)\python.exe $(BASE_TOOLS_PATH)\Source\C\Makefiles\NmakeSubdirs.py all $(BASE_TOOLS_PATH)\Source\C $(BASE_TOOLS_PATH)\ImageTool $(BASE_TOOLS_PATH)\MicroTool
subdirs: $(SUBDIRS)
@ -31,4 +31,3 @@ clean:
cleanall:
@if defined PYTHON_COMMAND $(PYTHON_COMMAND) $(BASE_TOOLS_PATH)\Source\C\Makefiles\NmakeSubdirs.py cleanall $(SUBDIRS)
@if not defined PYTHON_COMMAND $(PYTHON_HOME)\python.exe $(BASE_TOOLS_PATH)\Source\C\Makefiles\NmakeSubdirs.py cleanall $(SUBDIRS)

View File

@ -0,0 +1,15 @@
## @file
# Copyright (c) 2022, Mikhail Krichanov. All rights reserved.
# SPDX-License-Identifier: BSD-3-Clause
##
PROJECT = MicroTool
PRODUCT = $(PROJECT)$(INFIX)$(SUFFIX)
OBJS = $(PROJECT).o
DEBUG = 1
SANITIZE = 0
OC_USER = ../../OpenCorePkg
UDK_PATH = ../..
include $(OC_USER)/User/Makefile

View File

@ -0,0 +1,84 @@
## @file
# Windows makefile for 'MicroTool' module build.
#
# Copyright (c) 2022, Mikhail Krichanov. All rights reserved.
# SPDX-License-Identifier: BSD-3-Clause
#
!INCLUDE ..\Source\C\Makefiles\ms.common
APP = MicroTool
OC_USER = ..\..\OpenCorePkg
UDK_PATH = ..\..
UDK_ARCH = $(HOST_ARCH)
OUT_DIR = .\Windows
OBJECTS = MicroTool.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
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
OBJECTS = $(OBJECTS) {$(OUT)}DebugLib.obj {$(PRIN)}PrintLib.obj PrintLibInternal.obj {$(ERRO)}BaseDebugPrintErrorLevelLib.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
INC = -I . -I $(OC_USER)\User\Include -I $(OC_USER)\Include\Acidanthera
INC = $(INC) -I $(UDK_PATH)\MdePkg\Include -I $(UDK_PATH)\MdePkg\Include\Library -I $(UDK_PATH)\MdePkg\Include\$(UDK_ARCH)
INC = $(INC) -I $(UDK_PATH)\MdePkg\Library\BaseLib -I $(UDK_PATH)\MdeModulePkg\Include -I $(UDK_PATH)\UefiCpuPkg\Include
INC = $(INC) /FI $(OC_USER)\User\Include\UserPcd.h /FI $(UDK_PATH)\MdePkg\Include\Base.h /FI $(OC_USER)\User\Include\UserGlobalVar.h
all:
-@if not exist $(OUT_DIR) mkdir $(OUT_DIR)
$(MAKE) $(APP)
$(APP) : $(OBJECTS)
-@if not exist $(BIN_PATH) mkdir $(BIN_PATH)
@cd $(OUT_DIR)
$(LD) /nologo /debug /OPT:REF /OPT:ICF=10 /incremental:no /nodefaultlib:libc.lib /out:..\$@ $(LIBS) $**
@copy /y ..\$@ $(BIN_PATH)\$@.exe
.PHONY:clean
.PHONY:cleanall
clean:
del /f /q $(OUT_DIR) $(APP) *.pdb > nul
cleanall:
del /f /q $(OUT_DIR) *.pdb $(BIN_PATH)\$(APP).exe $(BIN_PATH)\$(APP).exe > nul
.c.obj :
$(CC) -c $(CFLAGS) $(INC) $< -Fo$@
@move $@ $(OUT_DIR)\
{$(BASE)}.c.obj :
$(CC) -c $(CFLAGS) $(INC) /wd 4005 $< -Fo$@
@move $@ $(OUT_DIR)\
{$(BMPN)}.c.obj :
$(CC) -c $(CFLAGS) $(INC) $< -Fo$@
@move $@ $(OUT_DIR)\
{$(CMEM)}.c.obj :
$(CC) -c $(CFLAGS) $(INC) $< -Fo$@
@move $@ $(OUT_DIR)\
{$(OUT)}.c.obj :
$(CC) -c $(CFLAGS) $(INC) $< -Fo$@
@move $@ $(OUT_DIR)\
{$(PRIN)}.c.obj :
$(CC) -c $(CFLAGS) $(INC) /wd 4005 $< -Fo$@
@move $@ $(OUT_DIR)\
{$(ERRO)}.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)\

View File

@ -0,0 +1,298 @@
/** @file
Copyright (c) 2022, Mikhail Krichanov. All rights reserved.
SPDX-License-Identifier: BSD-3-Clause
**/
#include <assert.h>
#include <ctype.h>
#include <errno.h>
#include <stdbool.h>
#include <UserFile.h>
#define DEFAULT_MC_ALIGNMENT 16
#define DEFAULT_MC_PAD_BYTE_VALUE 0xFF
typedef struct {
UINT32 HeaderVersion;
UINT32 PatchId;
UINT32 Date;
UINT32 CpuId;
UINT32 Checksum;
UINT32 LoaderVersion;
UINT32 PlatformId;
UINT32 DataSize; // if 0, then TotalSize = 2048, and TotalSize field is invalid
UINT32 TotalSize; // number of bytes
UINT32 Reserved[3];
} MICROCODE_HEADER;
static
RETURN_STATUS
TxtToBin (
IN const char *TxtName,
IN const char *BinName
)
{
char *Txt;
char *TxtStart;
uint32_t TxtSize;
UINT32 *Buffer;
UINT32 *BufferStart;
UINT32 FileLength;
UINT32 Index;
MICROCODE_HEADER *Micro;
UINT32 CheckSum;
assert (TxtName != NULL);
assert (BinName != NULL);
Txt = (char *)UserReadFile (TxtName, &TxtSize);
if (Txt == NULL) {
fprintf (stderr, "MicroTool: Could not open %s: %s\n", TxtName, strerror (errno));
return RETURN_ABORTED;
}
Buffer = calloc (1, TxtSize);
if (Buffer == NULL) {
fprintf (stderr, "MicroTool: Could not allocate memory for Buffer\n");
free (Txt);
return RETURN_OUT_OF_RESOURCES;
}
BufferStart = Buffer;
TxtStart = Txt;
FileLength = 0;
for (Index = 0; Index < TxtSize; ++Index, ++Txt) {
//
// Skip Blank Lines and Comment Lines
//
if (isspace ((int)*Txt)) {
continue;
}
if (*Txt == ';') {
while ((Index < TxtSize) && (*Txt != '\n')) {
++Index;
++Txt;
}
if (Index == TxtSize) {
break;
}
++Index;
++Txt;
}
//
// Look for
// dd 000000001h ; comment
// dd XXXXXXXX
// DD XXXXXXXXX
// DD XXXXXXXXX
//
if (((Index + 2) < TxtSize) && (tolower ((int)Txt[0]) == 'd') && (tolower ((int)Txt[1]) == 'd') && isspace ((int)Txt[2])) {
//
// Skip blanks and look for a hex digit
//
Txt += 3;
Index += 3;
while ((Index < TxtSize) && isspace ((int)*Txt)) {
++Index;
++Txt;
}
if (Index == TxtSize) {
break;
}
if (isxdigit ((int)*Txt)) {
if (sscanf (Txt, "%X", Buffer) != 1) {
fprintf (stderr, "MicroTool: Could not write into Buffer\n");
free (TxtStart);
free (BufferStart);
return RETURN_ABORTED;
}
while ((Index < TxtSize) && (*Txt != '\n')) {
++Index;
++Txt;
}
}
++Buffer;
FileLength += sizeof (*Buffer);
continue;
}
fprintf (stderr, "MicroTool: Corrupted input file\n");
break;
}
free (TxtStart);
if (FileLength == 0) {
fprintf (stderr, "MicroTool: No parseable data found in file %s\n", TxtName);
free (BufferStart);
return RETURN_INVALID_PARAMETER;
}
if (FileLength < sizeof (MICROCODE_HEADER)) {
fprintf (stderr, "MicroTool: Amount of parsable data in %s is insufficient to contain a microcode header\n", TxtName);
free (BufferStart);
return RETURN_VOLUME_CORRUPTED;
}
//
// Can't do much checking on the header because, per the spec, the
// DataSize field may be 0, which means DataSize = 2000 and TotalSize = 2K,
// and the TotalSize field is invalid (actually missing). Thus we can't
// even verify the Reserved fields are 0.
//
Micro = (MICROCODE_HEADER *)BufferStart;
if (Micro->DataSize == 0) {
Index = 2048;
} else {
Index = Micro->TotalSize;
}
if (Index != FileLength) {
fprintf (stderr, "MicroTool: File length of %s (0x%x) does not equal expected TotalSize: 0x%04X\n", TxtName, FileLength, Index);
free (BufferStart);
return RETURN_VOLUME_CORRUPTED;
}
//
// Checksum the contents
//
Buffer = BufferStart;
CheckSum = 0;
Index = 0;
while (Index < FileLength) {
CheckSum += *Buffer;
++Buffer;
Index += sizeof (*Buffer);
}
if (CheckSum != 0) {
fprintf (stderr, "MicroTool: Checksum (0x%x) failed on file %s\n", CheckSum, TxtName);
free (BufferStart);
return RETURN_VOLUME_CORRUPTED;
}
UserWriteFile (BinName, BufferStart, FileLength);
free (BufferStart);
return RETURN_SUCCESS;
}
static
RETURN_STATUS
Merge (
IN const char *Output,
IN const char *FileNames[],
IN UINT32 NumOfFiles
)
{
void *File;
uint32_t FileSize;
UINT32 Index;
UINT32 Total;
char *Buffer;
char *BufferStart;
UINT32 Addend;
assert (Output != NULL);
assert (FileNames != NULL);
Total = 0;
for (Index = 0; Index < NumOfFiles; ++Index) {
File = UserReadFile (FileNames[Index], &FileSize);
if (File == NULL) {
fprintf (stderr, "MicroTool: Could not open %s: %s\n", FileNames[Index], strerror (errno));
return RETURN_ABORTED;
}
Total += ALIGN_VALUE (FileSize, DEFAULT_MC_ALIGNMENT);
free (File);
}
Buffer = calloc (1, Total);
if (Buffer == NULL) {
fprintf (stderr, "MicroTool: Could not allocate memory for Buffer\n");
return RETURN_OUT_OF_RESOURCES;
}
BufferStart = Buffer;
for (Index = 0; Index < NumOfFiles; ++Index) {
File = UserReadFile (FileNames[Index], &FileSize);
if (File == NULL) {
fprintf (stderr, "MicroTool: Could not reopen %s: %s\n", FileNames[Index], strerror (errno));
free (BufferStart);
return RETURN_ABORTED;
}
memcpy (Buffer, File, FileSize);
Buffer += FileSize;
Addend = ALIGN_VALUE_ADDEND (FileSize, DEFAULT_MC_ALIGNMENT);
memset (Buffer, DEFAULT_MC_PAD_BYTE_VALUE, Addend);
Buffer += Addend;
free (File);
}
UserWriteFile (Output, BufferStart, Total);
free (BufferStart);
return RETURN_SUCCESS;
}
int main (int argc, const char *argv[])
{
RETURN_STATUS Status;
UINT32 NumOfFiles;
if (argc < 2) {
fprintf (stderr, "MicroTool: No command is specified\n");
assert (false);
return -1;
}
if (strcmp (argv[1], "TxtToBin") == 0) {
if (argc < 4) {
fprintf (stderr, "MicroTool: Command arguments are missing\n");
fprintf (stderr, " Usage: MicroTool TxtToBin InputFile OutputFile\n");
assert (false);
return -1;
}
Status = TxtToBin (argv[2], argv [3]);
if (RETURN_ERROR (Status)) {
assert (false);
return -1;
}
} else if (strcmp (argv[1], "Merge") == 0) {
if (argc < 4) {
fprintf (stderr, "MicroTool: Command arguments are missing\n");
fprintf (stderr, " Usage: MicroTool Merge OutputFile InputFile1 InputFile2 ...\n");
assert (false);
return -1;
}
NumOfFiles = (UINT32)argc - 3U;
Status = Merge (argv[2], &argv[3], NumOfFiles);
if (RETURN_ERROR (Status)) {
assert (false);
return -1;
}
}
return 0;
}

View File

@ -1,7 +1,8 @@
/** @file
Unified linker script for CLANG based builds
Unified linker script for GCC, CLANG based builds
Copyright (c) 2023, Mikhail Krichanov. All rights reserved.<BR>
Copyright (c) 2010 - 2021, Intel Corporation. All rights reserved.<BR>
Copyright (c) 2015, Linaro Ltd. All rights reserved.<BR>
(C) Copyright 2016 Hewlett Packard Enterprise Development LP<BR>
@ -12,17 +13,14 @@
SECTIONS {
/*
* The PE/COFF binary consists of DOS and PE/COFF headers, and a sequence of
* section headers adding up to PECOFF_HEADER_SIZE bytes (which differs
* between 32-bit and 64-bit builds). The actual start of the .text section
* will be rounded up based on its actual alignment.
*/
. = PECOFF_HEADER_SIZE;
. = ALIGNED_PE_HEADER_SIZE;
.text : ALIGN(CONSTANT(MAXPAGESIZE)) {
*(.text .text.* .stub .gnu.linkonce.t.*)
*(.rodata .rodata.* .gnu.linkonce.r.*)
}
.rodata : ALIGN(CONSTANT(MAXPAGESIZE)) {
*(.rodata .rodata.* .data.rel.ro .data.rel.ro.* .gnu.linkonce.r.*)
*(.got .got.*)
/*
@ -36,18 +34,16 @@ SECTIONS {
*:AutoGen.obj(.data.g*Guid)
}
/*
* The alignment of the .data section should be less than or equal to the
* alignment of the .text section. This ensures that the relative offset
* between these sections is the same in the ELF and the PE/COFF versions of
* this binary.
*/
.data ALIGN(ALIGNOF(.text)) : ALIGN(CONSTANT(MAXPAGESIZE)) {
.data : ALIGN(CONSTANT(MAXPAGESIZE)) {
*(.data .data.* .gnu.linkonce.d.*)
*(.bss .bss.*)
}
.eh_frame ALIGN(CONSTANT(MAXPAGESIZE)) : {
.hii : ALIGN(CONSTANT(MAXPAGESIZE)) {
KEEP (*(.hii))
}
.eh_frame : ALIGN(CONSTANT(MAXPAGESIZE)) {
KEEP (*(.eh_frame))
}
@ -55,14 +51,6 @@ SECTIONS {
*(.rela .rela.*)
}
.hii : ALIGN(CONSTANT(MAXPAGESIZE)) {
KEEP (*(.hii))
}
/*
* Retain the GNU build id but in a non-allocatable section so GenFw
* does not copy it into the PE/COFF image.
*/
.build-id (INFO) : { *(.note.gnu.build-id) }
/DISCARD/ : {
@ -74,5 +62,7 @@ SECTIONS {
*(.hash .gnu.hash)
*(.comment)
*(COMMON)
*(.dynamic)
*(.ARM.exidx .ARM.exidx.*)
}
}

View File

@ -1,78 +0,0 @@
/** @file
Unified linker script for GCC based builds
Copyright (c) 2010 - 2015, Intel Corporation. All rights reserved.<BR>
Copyright (c) 2015, Linaro Ltd. All rights reserved.<BR>
(C) Copyright 2016 Hewlett Packard Enterprise Development LP<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
SECTIONS {
/*
* The PE/COFF binary consists of DOS and PE/COFF headers, and a sequence of
* section headers adding up to PECOFF_HEADER_SIZE bytes (which differs
* between 32-bit and 64-bit builds). The actual start of the .text section
* will be rounded up based on its actual alignment.
*/
. = PECOFF_HEADER_SIZE;
.text : ALIGN(CONSTANT(COMMONPAGESIZE)) {
*(.text .text.* .stub .gnu.linkonce.t.*)
*(.rodata .rodata.* .gnu.linkonce.r.*)
*(.got .got.*)
/*
* The contents of AutoGen.c files are mostly constant from the POV of the
* program, but most of it ends up in .data or .bss by default since few of
* the variable definitions that get emitted are declared as CONST.
* Unfortunately, we cannot pull it into the .text section entirely, since
* patchable PCDs are also emitted here, but we can at least move all of the
* emitted GUIDs here.
*/
*:AutoGen.obj(.data.g*Guid)
}
/*
* The alignment of the .data section should be less than or equal to the
* alignment of the .text section. This ensures that the relative offset
* between these sections is the same in the ELF and the PE/COFF versions of
* this binary.
*/
.data ALIGN(ALIGNOF(.text)) : ALIGN(CONSTANT(COMMONPAGESIZE)) {
*(.data .data.* .gnu.linkonce.d.*)
*(.bss .bss.*)
}
.eh_frame ALIGN(CONSTANT(COMMONPAGESIZE)) : {
KEEP (*(.eh_frame))
}
.rela (INFO) : {
*(.rela .rela.*)
}
.hii : ALIGN(CONSTANT(COMMONPAGESIZE)) {
KEEP (*(.hii))
}
/*
* Retain the GNU build id but in a non-allocatable section so GenFw
* does not copy it into the PE/COFF image.
*/
.build-id (INFO) : { *(.note.gnu.build-id) }
/DISCARD/ : {
*(.note.GNU-stack)
*(.gnu_debuglink)
*(.interp)
*(.dynsym)
*(.dynstr)
*(.dynamic)
*(.hash .gnu.hash)
*(.comment)
}
}

View File

@ -0,0 +1,65 @@
/** @file
Unified linker script for GCC, CLANG based builds
Copyright (c) 2023, Mikhail Krichanov. All rights reserved.<BR>
Copyright (c) 2010 - 2021, Intel Corporation. All rights reserved.<BR>
Copyright (c) 2015, Linaro Ltd. All rights reserved.<BR>
(C) Copyright 2016 Hewlett Packard Enterprise Development LP<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
SECTIONS {
. = ALIGNED_PE_HEADER_SIZE;
.text : ALIGN(CONSTANT(MAXPAGESIZE)) {
*(.text .text.* .stub .gnu.linkonce.t.*)
*(.rodata .rodata.* .data.rel.ro .data.rel.ro.* .gnu.linkonce.r.*)
*(.got .got.*)
/*
* The contents of AutoGen.c files are mostly constant from the POV of the
* program, but most of it ends up in .data or .bss by default since few of
* the variable definitions that get emitted are declared as CONST.
* Unfortunately, we cannot pull it into the .text section entirely, since
* patchable PCDs are also emitted here, but we can at least move all of the
* emitted GUIDs here.
*/
*:AutoGen.obj(.data.g*Guid)
}
.data : ALIGN(CONSTANT(MAXPAGESIZE)) {
*(.data .data.* .gnu.linkonce.d.*)
*(.bss .bss.*)
}
.hii : ALIGN(CONSTANT(MAXPAGESIZE)) {
KEEP (*(.hii))
}
.eh_frame : ALIGN(CONSTANT(MAXPAGESIZE)) {
KEEP (*(.eh_frame))
}
.rela (INFO) : {
*(.rela .rela.*)
}
.build-id (INFO) : { *(.note.gnu.build-id) }
/DISCARD/ : {
*(.note.GNU-stack)
*(.gnu_debuglink)
*(.interp)
*(.dynsym)
*(.dynstr)
*(.hash .gnu.hash)
*(.comment)
*(COMMON)
*(.dynamic)
*(.ARM.exidx .ARM.exidx.*)
}
}

View File

@ -3586,7 +3586,7 @@ Returns:
return EFI_SUCCESS;
}
EFI_PHYSICAL_ADDRESS
EFI_STATUS
AddPadSection (
IN OUT EFI_PHYSICAL_ADDRESS *BaseAddress,
IN UINT32 Alignment,
@ -3599,14 +3599,14 @@ AddPadSection (
UINT32 FfsHeaderLength;
UINT32 FfsFileLength;
UINT32 PadSize;
UINTN PadAddress;
EFI_PHYSICAL_ADDRESS PadAddress;
UINT8 *FfsPart;
UINT32 PartSize;
UINT32 Offset;
EFI_FFS_INTEGRITY_CHECK *IntegrityCheck;
PadAddress = ALIGN_VALUE (*BaseAddress + sizeof (EFI_COMMON_SECTION_HEADER), Alignment);
PadSize = PadAddress - *BaseAddress;
PadSize = (UINT32)(PadAddress - *BaseAddress);
Offset = (UINT32)((UINTN)((*Section).Pe32Section) - (UINTN)(*FfsFile));
PartSize = GetFfsFileLength (*FfsFile) - Offset;
@ -3636,7 +3636,7 @@ AddPadSection (
++NewSection;
ZeroMem ((VOID *)NewSection, PadSize - sizeof (EFI_COMMON_SECTION_HEADER));
*Section = (EFI_FILE_SECTION_POINTER)(EFI_PE32_SECTION *)((UINT8 *)NewSection + PadSize - sizeof (EFI_COMMON_SECTION_HEADER));
(*Section).Pe32Section = (EFI_PE32_SECTION *)((UINT8 *)NewSection + PadSize - sizeof (EFI_COMMON_SECTION_HEADER));
CopyMem (
(UINT8 *)((*Section).Pe32Section),
@ -4070,7 +4070,7 @@ Returns:
PdbPointer = FileName;
}
WriteMapFile (FvMapFile, PdbPointer, *FfsFile, NewPe32BaseAddress, &OrigImageContext);
WriteMapFile (FvMapFile, PdbPointer, *FfsFile, NewPe32BaseAddress, &ImageContext);
}
if ((*FfsFile)->Type != EFI_FV_FILETYPE_SECURITY_CORE &&

View File

@ -19,10 +19,9 @@ $(OBJECTS) : $(SOURCE_PATH)\Include\Common\BuildVersion.h
.PHONY:cleanall
clean:
del /f /q $(OBJECTS) *.pdb > nul
del /f /q *.obj *.pdb > nul
cleanall:
del /f /q $(OBJECTS) $(APPLICATION) *.pdb $(BIN_PATH)\$(APPNAME).pdb > nul
del /f /q *.obj $(APPLICATION) *.pdb $(BIN_PATH)\$(APPNAME).pdb > nul
!INCLUDE $(SOURCE_PATH)\Makefiles\ms.rule

View File

@ -103,11 +103,32 @@ class ToolDefClassObject(object):
else:
EdkLogger.error("tools_def.txt parser", FILE_NOT_FOUND, ExtraData=FileName)
Branch = 0
for Index in range(len(FileContent)):
Line = FileContent[Index].strip()
if Line == "" or Line[0] == '#':
continue
if Line.startswith("!ifdef"):
Condition = Line[6:].strip()
Reference = GlobalData.gMacroRefPattern.findall(Condition)
if Reference[0] in GlobalData.gCommandLineDefines:
Branch = 1
else:
Branch = -1
continue
if Line.startswith("!else"):
Branch *= -1
continue
if Line.startswith("!endif"):
Branch = 0
continue
if Branch == -1:
continue
if Line.startswith("!include"):
IncFile = Line[8:].strip()
Done, IncFile = self.ExpandMacros(IncFile)

View File

@ -130,36 +130,6 @@ typedef unsigned __int32 UINT32;
/// 4-byte signed value.
///
typedef __int32 INT32;
///
/// 2-byte unsigned value.
///
typedef unsigned short UINT16;
///
/// 2-byte Character. Unless otherwise specified all strings are stored in the
/// UTF-16 encoding format as defined by Unicode 2.1 and ISO/IEC 10646 standards.
///
typedef unsigned short CHAR16;
///
/// 2-byte signed value.
///
typedef short INT16;
///
/// Logical Boolean. 1-byte value containing 0 for FALSE or a 1 for TRUE. Other
/// values are undefined.
///
typedef unsigned char BOOLEAN;
///
/// 1-byte unsigned value.
///
typedef unsigned char UINT8;
///
/// 1-byte Character.
///
typedef char CHAR8;
///
/// 1-byte signed value.
///
typedef signed char INT8;
#else
///
/// 8-byte unsigned value.
@ -177,6 +147,8 @@ typedef unsigned int UINT32;
/// 4-byte signed value.
///
typedef int INT32;
#endif
///
/// 2-byte unsigned value.
///
@ -207,7 +179,6 @@ typedef char CHAR8;
/// 1-byte signed value
///
typedef signed char INT8;
#endif
///
/// Unsigned value of native width. (4 bytes on supported 32-bit processor instructions;

View File

@ -143,36 +143,6 @@ typedef unsigned __int32 UINT32;
/// 4-byte signed value
///
typedef __int32 INT32;
///
/// 2-byte unsigned value
///
typedef unsigned short UINT16;
///
/// 2-byte Character. Unless otherwise specified all strings are stored in the
/// UTF-16 encoding format as defined by Unicode 2.1 and ISO/IEC 10646 standards.
///
typedef unsigned short CHAR16;
///
/// 2-byte signed value
///
typedef short INT16;
///
/// Logical Boolean. 1-byte value containing 0 for FALSE or a 1 for TRUE. Other
/// values are undefined.
///
typedef unsigned char BOOLEAN;
///
/// 1-byte unsigned value
///
typedef unsigned char UINT8;
///
/// 1-byte Character
///
typedef char CHAR8;
///
/// 1-byte signed value
///
typedef signed char INT8;
#elif defined (__clang__)
///
/// 8-byte unsigned value
@ -190,36 +160,6 @@ typedef unsigned int UINT32;
/// 4-byte signed value
///
typedef signed int INT32;
///
/// 2-byte unsigned value
///
typedef unsigned short UINT16;
///
/// 2-byte Character. Unless otherwise specified all strings are stored in the
/// UTF-16 encoding format as defined by Unicode 2.1 and ISO/IEC 10646 standards.
///
typedef unsigned short CHAR16;
///
/// 2-byte signed value
///
typedef short INT16;
///
/// Logical Boolean. 1-byte value containing 0 for FALSE or a 1 for TRUE. Other
/// values are undefined.
///
typedef unsigned char BOOLEAN;
///
/// 1-byte unsigned value
///
typedef unsigned char UINT8;
///
/// 1-byte Character
///
typedef char CHAR8;
///
/// 1-byte signed value
///
typedef signed char INT8;
#else
///
/// 8-byte unsigned value
@ -237,6 +177,8 @@ typedef unsigned int UINT32;
/// 4-byte signed value
///
typedef int INT32;
#endif
///
/// 2-byte unsigned value
///
@ -267,7 +209,6 @@ typedef char CHAR8;
/// 1-byte signed value
///
typedef signed char INT8;
#endif
///
/// Unsigned value of native width. (4 bytes on supported 32-bit processor instructions,

1
OpenCorePkg Submodule

@ -0,0 +1 @@
Subproject commit ca9a501490ccce20431f095182b4fb0d359d80e3

View File

@ -109,20 +109,6 @@
!include NetworkPkg/NetworkBuildOptions.dsc.inc
[BuildOptions.common.EDKII.DXE_RUNTIME_DRIVER]
GCC:*_*_*_DLINK_FLAGS = -z common-page-size=0x1000
XCODE:*_*_*_DLINK_FLAGS = -seg1addr 0x1000 -segalign 0x1000
XCODE:*_*_*_MTOC_FLAGS = -align 0x1000
CLANGPDB:*_*_*_DLINK_FLAGS = /ALIGN:4096
# Force PE/COFF sections to be aligned at 4KB boundaries to support page level
# protection of DXE_SMM_DRIVER/SMM_CORE modules
[BuildOptions.common.EDKII.DXE_SMM_DRIVER, BuildOptions.common.EDKII.SMM_CORE]
GCC:*_*_*_DLINK_FLAGS = -z common-page-size=0x1000
XCODE:*_*_*_DLINK_FLAGS = -seg1addr 0x1000 -segalign 0x1000
XCODE:*_*_*_MTOC_FLAGS = -align 0x1000
CLANGPDB:*_*_*_DLINK_FLAGS = /ALIGN:4096
################################################################################
#
# SKU Identification section - list of all SKU IDs supported by this Platform.
@ -604,14 +590,15 @@
#
!if $(LEGACY_WINDOWS_LOADER) == TRUE
# Allow execution of EfiLoaderData memory regions.
gEfiMdeModulePkgTokenSpaceGuid.PcdDxeNxMemoryProtectionPolicy|0x7FD1
gEfiMdeModulePkgTokenSpaceGuid.PcdDxeNxMemoryProtectionPolicy|0xFFFFFFFFFFFFFFD1
!elseif $(LINUX_LOADER) == TRUE
# Allow execution of EfiConventionalMemory, EfiBootServicesData and EfiLoaderData memory regions.
gEfiMdeModulePkgTokenSpaceGuid.PcdDxeNxMemoryProtectionPolicy|0x7F41
# Allow execution of EfiReservedMemoryType, EfiConventionalMemory, EfiBootServicesData and EfiLoaderData memory regions.
gEfiMdeModulePkgTokenSpaceGuid.PcdDxeNxMemoryProtectionPolicy|0xFFFFFFFFFFFFFF40
gEfiMdePkgTokenSpaceGuid.PcdImageLoaderAllowMisalignedOffset|TRUE
!elseif $(WINDOWS_10_IA32) == TRUE
# Allow execution of EfiReservedMemoryType, EfiConventionalMemory, EfiBootServicesData and EfiRuntimeServicesData memory regions.
gEfiMdeModulePkgTokenSpaceGuid.PcdDxeNxMemoryProtectionPolicy|0x7F04
gEfiMdeModulePkgTokenSpaceGuid.PcdDxeNxMemoryProtectionPolicy|0xFFFFFFFFFFFFFF04
gEfiMdeModulePkgTokenSpaceGuid.PcdImageProtectionPolicy|0x0
!endif
################################################################################

View File

@ -113,11 +113,6 @@
!include NetworkPkg/NetworkBuildOptions.dsc.inc
GCC:*_*_*_DLINK_FLAGS = -z common-page-size=0x1000
XCODE:*_*_*_DLINK_FLAGS = -seg1addr 0x1000 -segalign 0x1000
XCODE:*_*_*_MTOC_FLAGS = -align 0x1000
CLANGPDB:*_*_*_DLINK_FLAGS = /FILEALIGN:4096 /ALIGN:4096
################################################################################
#
# SKU Identification section - list of all SKU IDs supported by this Platform.
@ -605,14 +600,15 @@
#
!if $(LEGACY_WINDOWS_LOADER) == TRUE
# Allow execution of EfiLoaderData memory regions.
gEfiMdeModulePkgTokenSpaceGuid.PcdDxeNxMemoryProtectionPolicy|0x7FD1
gEfiMdeModulePkgTokenSpaceGuid.PcdDxeNxMemoryProtectionPolicy|0xFFFFFFFFFFFFFFD1
!elseif $(LINUX_LOADER) == TRUE
# Allow execution of EfiConventionalMemory, EfiBootServicesData and EfiLoaderData memory regions.
gEfiMdeModulePkgTokenSpaceGuid.PcdDxeNxMemoryProtectionPolicy|0x7F41
# Allow execution of EfiReservedMemoryType, EfiConventionalMemory, EfiBootServicesData and EfiLoaderData memory regions.
gEfiMdeModulePkgTokenSpaceGuid.PcdDxeNxMemoryProtectionPolicy|0xFFFFFFFFFFFFFF40
gEfiMdePkgTokenSpaceGuid.PcdImageLoaderAllowMisalignedOffset|TRUE
!elseif $(WINDOWS_10_IA32) == TRUE
# Allow execution of EfiReservedMemoryType, EfiConventionalMemory, EfiBootServicesData and EfiRuntimeServicesData memory regions.
gEfiMdeModulePkgTokenSpaceGuid.PcdDxeNxMemoryProtectionPolicy|0x7F04
gEfiMdeModulePkgTokenSpaceGuid.PcdDxeNxMemoryProtectionPolicy|0xFFFFFFFFFFFFFF04
gEfiMdeModulePkgTokenSpaceGuid.PcdImageProtectionPolicy|0x0
!endif
################################################################################

View File

@ -62,10 +62,10 @@ FV = SECFV
[FD.MEMFD]
BaseAddress = $(MEMFD_BASE_ADDRESS)
Size = 0xE00000
Size = 0xE30000
ErasePolarity = 1
BlockSize = 0x10000
NumBlocks = 0xE0
NumBlocks = 0xE3
0x000000|0x006000
gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecPageTablesBase|gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecPageTablesSize
@ -82,11 +82,11 @@ gUefiOvmfPkgTokenSpaceGuid.PcdOvmfWorkAreaBase|gUefiOvmfPkgTokenSpaceGuid.PcdOvm
0x010000|0x010000
gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecPeiTempRamBase|gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecPeiTempRamSize
0x020000|0x0E0000
0x020000|0x100000
gUefiOvmfPkgTokenSpaceGuid.PcdOvmfPeiMemFvBase|gUefiOvmfPkgTokenSpaceGuid.PcdOvmfPeiMemFvSize
FV = PEIFV
0x100000|0xD00000
0x120000|0xCE0000
gUefiOvmfPkgTokenSpaceGuid.PcdOvmfDxeMemFvBase|gUefiOvmfPkgTokenSpaceGuid.PcdOvmfDxeMemFvSize
FV = DXEFV

View File

@ -126,20 +126,6 @@
!include NetworkPkg/NetworkBuildOptions.dsc.inc
[BuildOptions.common.EDKII.DXE_RUNTIME_DRIVER]
GCC:*_*_*_DLINK_FLAGS = -z common-page-size=0x1000
XCODE:*_*_*_DLINK_FLAGS = -seg1addr 0x1000 -segalign 0x1000
XCODE:*_*_*_MTOC_FLAGS = -align 0x1000
CLANGPDB:*_*_*_DLINK_FLAGS = /ALIGN:4096
# Force PE/COFF sections to be aligned at 4KB boundaries to support page level
# protection of DXE_SMM_DRIVER/SMM_CORE modules
[BuildOptions.common.EDKII.DXE_SMM_DRIVER, BuildOptions.common.EDKII.SMM_CORE]
GCC:*_*_*_DLINK_FLAGS = -z common-page-size=0x1000
XCODE:*_*_*_DLINK_FLAGS = -seg1addr 0x1000 -segalign 0x1000
XCODE:*_*_*_MTOC_FLAGS = -align 0x1000
CLANGPDB:*_*_*_DLINK_FLAGS = /ALIGN:4096
################################################################################
#
# SKU Identification section - list of all SKU IDs supported by this Platform.
@ -608,7 +594,8 @@
gEmbeddedTokenSpaceGuid.PcdMemoryTypeEfiRuntimeServicesData|0x100
#
# TDX need 1G PageTable support
# TDX needs 1G PageTable support
#
gEfiMdeModulePkgTokenSpaceGuid.PcdUse1GPageTable|TRUE
#
@ -633,10 +620,10 @@
#
!if $(LEGACY_WINDOWS_LOADER) == TRUE
# Allow execution of EfiLoaderData memory regions.
gEfiMdeModulePkgTokenSpaceGuid.PcdDxeNxMemoryProtectionPolicy|0x7FD1
gEfiMdeModulePkgTokenSpaceGuid.PcdDxeNxMemoryProtectionPolicy|0xFFFFFFFFFFFFFFD1
!elseif $(LINUX_LOADER) == TRUE
# Allow execution of EfiConventionalMemory, EfiBootServicesData and EfiLoaderData memory regions.
gEfiMdeModulePkgTokenSpaceGuid.PcdDxeNxMemoryProtectionPolicy|0x7F41
# Allow execution of EfiReservedMemoryType, EfiConventionalMemory, EfiBootServicesData and EfiLoaderData memory regions.
gEfiMdeModulePkgTokenSpaceGuid.PcdDxeNxMemoryProtectionPolicy|0xFFFFFFFFFFFFFF40
gEfiMdePkgTokenSpaceGuid.PcdImageLoaderAllowMisalignedOffset|TRUE
!endif

View File

@ -62,10 +62,10 @@ FV = SECFV
[FD.MEMFD]
BaseAddress = $(MEMFD_BASE_ADDRESS)
Size = 0xE00000
Size = 0xD00000
ErasePolarity = 1
BlockSize = 0x10000
NumBlocks = 0xE0
NumBlocks = 0xD0
0x000000|0x006000
gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecPageTablesBase|gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecPageTablesSize
@ -97,11 +97,11 @@ gUefiOvmfPkgTokenSpaceGuid.PcdOvmfCpuidBase|gUefiOvmfPkgTokenSpaceGuid.PcdOvmfCp
0x010000|0x010000
gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecPeiTempRamBase|gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecPeiTempRamSize
0x020000|0x0E0000
0x020000|0x110000
gUefiOvmfPkgTokenSpaceGuid.PcdOvmfPeiMemFvBase|gUefiOvmfPkgTokenSpaceGuid.PcdOvmfPeiMemFvSize
FV = PEIFV
0x100000|0xD00000
0x130000|0xBD0000
gUefiOvmfPkgTokenSpaceGuid.PcdOvmfDxeMemFvBase|gUefiOvmfPkgTokenSpaceGuid.PcdOvmfDxeMemFvSize
FV = DXEFV

View File

@ -6,7 +6,7 @@
;*
;------------------------------------------------------------------------------
SECTION .rodata
SECTION RODATA_SECTION_NAME
;
; Float control word initial value:
@ -65,4 +65,3 @@ Done:
pop ebx
ret

View File

@ -6,7 +6,7 @@
;*
;------------------------------------------------------------------------------
SECTION .rodata
SECTION RODATA_SECTION_NAME
;
; Float control word initial value:
; all exceptions masked, double-extended-precision, round-to-nearest
@ -48,4 +48,3 @@ ASM_PFX(InitializeFloatingPointUnits):
ldmxcsr [mMmxControlWord]
ret

View File

@ -46,8 +46,8 @@
DebugAgentLib
CpuLib
UefiCpuLib
PeCoffGetEntryPointLib
PeCoffExtraActionLib
UefiImageLib
UefiImageExtraActionLib
CpuExceptionHandlerLib
ReportStatusCodeLib
PeiServicesLib

View File

@ -1,27 +0,0 @@
# FIXME: Docs
[Defines]
INF_VERSION = 0x00010005
BASE_NAME = UefiPayloadEntryMemoryAllocationLib
FILE_GUID = D3C5B8A1-B946-4D46-8251-9020A527EE40
MODULE_TYPE = BASE
VERSION_STRING = 1.0
LIBRARY_CLASS = UefiPayloadEntryMemoryAllocationLib|SEC
#
# The following information is for reference only and not required by the build tools.
#
# VALID_ARCHITECTURES = IA32 X64
#
[Sources]
MemoryAllocation.c
[Packages]
MdePkg/MdePkg.dec
UefiPayloadPkg/UefiPayloadPkg.dec
[LibraryClasses]
BaseMemoryLib
DebugLib
HobLib

View File

@ -1,198 +1,247 @@
/** @file
Copyright (c) 2008 - 2009, Apple Inc. All rights reserved.<BR>
Copyright (c) 2020, Intel Corporation. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
#include "UefiPayloadEntry.h"
/**
Allocates one or more pages of type EfiBootServicesData.
Allocates the number of pages of MemoryType and returns a pointer to the
allocated buffer. The buffer returned is aligned on a 4KB boundary.
If Pages is 0, then NULL is returned.
If there is not enough memory availble to satisfy the request, then NULL
is returned.
@param Pages The number of 4 KB pages to allocate.
@return A pointer to the allocated buffer or NULL if allocation fails.
**/
VOID *
EFIAPI
AllocatePages (
IN UINTN Pages
)
{
EFI_PEI_HOB_POINTERS Hob;
EFI_PHYSICAL_ADDRESS Offset;
EFI_HOB_HANDOFF_INFO_TABLE *HobTable;
Hob.Raw = GetHobList ();
HobTable = Hob.HandoffInformationTable;
if (Pages == 0) {
return NULL;
}
// Make sure allocation address is page alligned.
Offset = HobTable->EfiFreeMemoryTop & EFI_PAGE_MASK;
if (Offset != 0) {
HobTable->EfiFreeMemoryTop -= Offset;
}
//
// Check available memory for the allocation
//
if (HobTable->EfiFreeMemoryTop - ((Pages * EFI_PAGE_SIZE) + sizeof (EFI_HOB_MEMORY_ALLOCATION)) < HobTable->EfiFreeMemoryBottom) {
return NULL;
}
HobTable->EfiFreeMemoryTop -= Pages * EFI_PAGE_SIZE;
BuildMemoryAllocationHob (HobTable->EfiFreeMemoryTop, Pages * EFI_PAGE_SIZE, EfiBootServicesData);
return (VOID *)(UINTN)HobTable->EfiFreeMemoryTop;
}
/**
Frees one or more 4KB pages that were previously allocated with one of the page allocation
functions in the Memory Allocation Library.
Frees the number of 4KB pages specified by Pages from the buffer specified by Buffer. Buffer
must have been allocated on a previous call to the page allocation services of the Memory
Allocation Library. If it is not possible to free allocated pages, then this function will
perform no actions.
If Buffer was not allocated with a page allocation function in the Memory Allocation Library,
then ASSERT().
If Pages is zero, then ASSERT().
@param Buffer Pointer to the buffer of pages to free.
@param Pages The number of 4 KB pages to free.
**/
VOID
EFIAPI
FreePages (
IN VOID *Buffer,
IN UINTN Pages
)
{
}
/**
Allocates one or more pages of type EfiBootServicesData at a specified alignment.
Allocates the number of pages specified by Pages of type EfiBootServicesData with an
alignment specified by Alignment.
If Pages is 0, then NULL is returned.
If Alignment is not a power of two and Alignment is not zero, then ASSERT().
If there is no enough memory at the specified alignment available to satisfy the
request, then NULL is returned.
@param Pages The number of 4 KB pages to allocate.
@param Alignment The requested alignment of the allocation.
@return A pointer to the allocated buffer or NULL if allocation fails.
**/
VOID *
EFIAPI
AllocateAlignedPages (
IN UINTN Pages,
IN UINTN Alignment
)
{
VOID *Memory;
UINTN AlignmentMask;
//
// Alignment must be a power of two or zero.
//
ASSERT ((Alignment & (Alignment - 1)) == 0);
if (Pages == 0) {
return NULL;
}
//
// Check overflow.
//
ASSERT (Pages <= (MAX_ADDRESS - EFI_SIZE_TO_PAGES (Alignment)));
Memory = (VOID *)(UINTN)AllocatePages (Pages + EFI_SIZE_TO_PAGES (Alignment));
if (Memory == NULL) {
return NULL;
}
if (Alignment == 0) {
AlignmentMask = Alignment;
} else {
AlignmentMask = Alignment - 1;
}
return (VOID *)(UINTN)(((UINTN)Memory + AlignmentMask) & ~AlignmentMask);
}
/**
Allocates a buffer of type EfiBootServicesData.
Allocates the number bytes specified by AllocationSize of type EfiBootServicesData and returns a
pointer to the allocated buffer. If AllocationSize is 0, then a valid buffer of 0 size is
returned. If there is not enough memory remaining to satisfy the request, then NULL is returned.
@param AllocationSize The number of bytes to allocate.
@return A pointer to the allocated buffer or NULL if allocation fails.
**/
VOID *
EFIAPI
AllocatePool (
IN UINTN AllocationSize
)
{
EFI_HOB_MEMORY_POOL *Hob;
if (AllocationSize > 0x4000) {
// Please use AllocatePages for big allocations
return NULL;
}
Hob = (EFI_HOB_MEMORY_POOL *)CreateHob (EFI_HOB_TYPE_MEMORY_POOL, (UINT16)(sizeof (EFI_HOB_MEMORY_POOL) + AllocationSize));
return (VOID *)(Hob + 1);
}
/**
Allocates and zeros a buffer of type EfiBootServicesData.
Allocates the number bytes specified by AllocationSize of type EfiBootServicesData, clears the
buffer with zeros, and returns a pointer to the allocated buffer. If AllocationSize is 0, then a
valid buffer of 0 size is returned. If there is not enough memory remaining to satisfy the
request, then NULL is returned.
@param AllocationSize The number of bytes to allocate and zero.
@return A pointer to the allocated buffer or NULL if allocation fails.
**/
VOID *
EFIAPI
AllocateZeroPool (
IN UINTN AllocationSize
)
{
VOID *Buffer;
Buffer = AllocatePool (AllocationSize);
if (Buffer == NULL) {
return NULL;
}
ZeroMem (Buffer, AllocationSize);
return Buffer;
}
/** @file
Copyright (c) 2008 - 2009, Apple Inc. All rights reserved.<BR>
Copyright (c) 2020, Intel Corporation. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
#include <PiPei.h>
#include <Library/BaseLib.h>
#include <Library/BaseMemoryLib.h>
#include <Library/MemoryAllocationLib.h>
#include <Library/DebugLib.h>
#include <Library/HobLib.h>
#include <Guid/MemoryAllocationHob.h>
/**
Add a new HOB to the HOB List.
@param HobType Type of the new HOB.
@param HobLength Length of the new HOB to allocate.
@return NULL if there is no space to create a hob.
@return The address point to the new created hob.
**/
VOID *
EFIAPI
CreateHob (
IN UINT16 HobType,
IN UINT16 HobLength
);
/**
Allocates one or more pages of type EfiBootServicesData.
Allocates the number of pages of MemoryType and returns a pointer to the
allocated buffer. The buffer returned is aligned on a 4KB boundary.
If Pages is 0, then NULL is returned.
If there is not enough memory availble to satisfy the request, then NULL
is returned.
@param Pages The number of 4 KB pages to allocate.
@return A pointer to the allocated buffer or NULL if allocation fails.
**/
VOID *
EFIAPI
AllocatePages (
IN UINTN Pages
)
{
EFI_PEI_HOB_POINTERS Hob;
EFI_PHYSICAL_ADDRESS Offset;
EFI_HOB_HANDOFF_INFO_TABLE *HobTable;
Hob.Raw = GetHobList ();
HobTable = Hob.HandoffInformationTable;
if (Pages == 0) {
return NULL;
}
// Make sure allocation address is page alligned.
Offset = HobTable->EfiFreeMemoryTop & EFI_PAGE_MASK;
if (Offset != 0) {
HobTable->EfiFreeMemoryTop -= Offset;
}
//
// Check available memory for the allocation
//
if (HobTable->EfiFreeMemoryTop - ((Pages * EFI_PAGE_SIZE) + sizeof (EFI_HOB_MEMORY_ALLOCATION)) < HobTable->EfiFreeMemoryBottom) {
return NULL;
}
HobTable->EfiFreeMemoryTop -= Pages * EFI_PAGE_SIZE;
BuildMemoryAllocationHob (HobTable->EfiFreeMemoryTop, Pages * EFI_PAGE_SIZE, EfiBootServicesData);
return (VOID *)(UINTN)HobTable->EfiFreeMemoryTop;
}
/**
Frees one or more 4KB pages that were previously allocated with one of the page allocation
functions in the Memory Allocation Library.
Frees the number of 4KB pages specified by Pages from the buffer specified by Buffer. Buffer
must have been allocated on a previous call to the page allocation services of the Memory
Allocation Library. If it is not possible to free allocated pages, then this function will
perform no actions.
If Buffer was not allocated with a page allocation function in the Memory Allocation Library,
then ASSERT().
If Pages is zero, then ASSERT().
@param Buffer Pointer to the buffer of pages to free.
@param Pages The number of 4 KB pages to free.
**/
VOID
EFIAPI
FreePages (
IN VOID *Buffer,
IN UINTN Pages
)
{
}
/**
Allocates one or more pages of type EfiBootServicesData at a specified alignment.
Allocates the number of pages specified by Pages of type EfiBootServicesData with an
alignment specified by Alignment.
If Pages is 0, then NULL is returned.
If Alignment is not a power of two and Alignment is not zero, then ASSERT().
If there is no enough memory at the specified alignment available to satisfy the
request, then NULL is returned.
@param Pages The number of 4 KB pages to allocate.
@param Alignment The requested alignment of the allocation.
@return A pointer to the allocated buffer or NULL if allocation fails.
**/
VOID *
EFIAPI
AllocateAlignedPages (
IN UINTN Pages,
IN UINTN Alignment
)
{
VOID *Memory;
UINTN AlignmentMask;
//
// Alignment must be a power of two or zero.
//
ASSERT ((Alignment & (Alignment - 1)) == 0);
if (Pages == 0) {
return NULL;
}
//
// Check overflow.
//
ASSERT (Pages <= (MAX_ADDRESS - EFI_SIZE_TO_PAGES (Alignment)));
Memory = (VOID *)(UINTN)AllocatePages (Pages + EFI_SIZE_TO_PAGES (Alignment));
if (Memory == NULL) {
return NULL;
}
if (Alignment == 0) {
AlignmentMask = Alignment;
} else {
AlignmentMask = Alignment - 1;
}
return (VOID *)(UINTN)(((UINTN)Memory + AlignmentMask) & ~AlignmentMask);
}
/**
Allocates a buffer of type EfiBootServicesData.
Allocates the number bytes specified by AllocationSize of type EfiBootServicesData and returns a
pointer to the allocated buffer. If AllocationSize is 0, then a valid buffer of 0 size is
returned. If there is not enough memory remaining to satisfy the request, then NULL is returned.
@param AllocationSize The number of bytes to allocate.
@return A pointer to the allocated buffer or NULL if allocation fails.
**/
VOID *
EFIAPI
AllocatePool (
IN UINTN AllocationSize
)
{
EFI_HOB_MEMORY_POOL *Hob;
if (AllocationSize > 0x4000) {
// Please use AllocatePages for big allocations
return NULL;
}
Hob = (EFI_HOB_MEMORY_POOL *)CreateHob (EFI_HOB_TYPE_MEMORY_POOL, (UINT16)(sizeof (EFI_HOB_MEMORY_POOL) + AllocationSize));
return (VOID *)(Hob + 1);
}
/**
Allocates and zeros a buffer of type EfiBootServicesData.
Allocates the number bytes specified by AllocationSize of type EfiBootServicesData, clears the
buffer with zeros, and returns a pointer to the allocated buffer. If AllocationSize is 0, then a
valid buffer of 0 size is returned. If there is not enough memory remaining to satisfy the
request, then NULL is returned.
@param AllocationSize The number of bytes to allocate and zero.
@return A pointer to the allocated buffer or NULL if allocation fails.
**/
VOID *
EFIAPI
AllocateZeroPool (
IN UINTN AllocationSize
)
{
VOID *Buffer;
Buffer = AllocatePool (AllocationSize);
if (Buffer == NULL) {
return NULL;
}
ZeroMem (Buffer, AllocationSize);
return Buffer;
}
/**
Frees a buffer that was previously allocated with one of the pool allocation functions in the
Memory Allocation Library.
Frees the buffer specified by Buffer. Buffer must have been allocated on a previous call to the
pool allocation services of the Memory Allocation Library. If it is not possible to free pool
resources, then this function will perform no actions.
If Buffer was not allocated with a pool allocation function in the Memory Allocation Library,
then ASSERT().
@param Buffer The pointer to the buffer to free.
**/
VOID
EFIAPI
FreePool (
IN VOID *Buffer
)
{
//
// PEI phase does not support to free pool, so leave it as NOP.
//
}

View File

@ -0,0 +1,40 @@
## @file
# Instance of Memory Allocation Library using PEI Services.
#
# Memory Allocation Library that uses PEI Services to allocate memory.
# Free operations are ignored.
#
# Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.<BR>
#
# SPDX-License-Identifier: BSD-2-Clause-Patent
#
#
##
[Defines]
INF_VERSION = 0x00010005
BASE_NAME = UefiPayloadMemoryAllocationLib
MODULE_UNI_FILE = UefiPayloadMemoryAllocationLib.uni
FILE_GUID = b694e0dc-cd4e-4b30-885b-9c164ed3e74a
MODULE_TYPE = PEIM
VERSION_STRING = 1.0
LIBRARY_CLASS = MemoryAllocationLib|PEIM PEI_CORE SEC
#
# VALID_ARCHITECTURES = IA32 X64 EBC (EBC is for build only)
#
[Sources]
MemoryAllocationLib.c
[Packages]
MdePkg/MdePkg.dec
[LibraryClasses]
DebugLib
BaseMemoryLib
BaseLib
HobLib

View File

@ -0,0 +1,17 @@
// /** @file
// Instance of Memory Allocation Library using PEI Services.
//
// Memory Allocation Library that uses PEI Services to allocate memory.
// Free operations are ignored.
//
// Copyright (c) 2007 - 2014, Intel Corporation. All rights reserved.<BR>
//
// SPDX-License-Identifier: BSD-2-Clause-Patent
//
// **/
#string STR_MODULE_ABSTRACT #language en-US "Instance of Memory Allocation Library for Uefi payloads"
#string STR_MODULE_DESCRIPTION #language en-US "Memory Allocation Library that allocates memory in uefi payload implementations. Free operations are ignored."

View File

@ -539,7 +539,8 @@ typedef struct {
#define R_386_TLS_TPOFF32 37 /* GOT entry of -ve static TLS offset */
/* Null relocation */
#define R_AARCH64_NONE 256 /* No relocation */
#define R_AARCH64_NONE0 0
#define R_AARCH64_NONE 256 /* No relocation */
/* Static AArch64 relocations */
/* Static data relocations */
#define R_AARCH64_ABS64 257 /* S + A */
@ -735,6 +736,7 @@ typedef struct {
#define R_ARM_THM_MOVW_PREL_NC 49
#define R_ARM_THM_MOVT_PREL 50
#define R_ARM_THM_JMP6 52
#define R_ARM_THM_JUMP19 51
#define R_ARM_THM_ALU_PREL_11_0 53
#define R_ARM_THM_PC12 54
#define R_ARM_REL32_NOI 56
@ -752,21 +754,14 @@ typedef struct {
#define R_ARM_LDC_PC_G1 68
#define R_ARM_LDC_PC_G2 69
#define R_ARM_GOT_PREL 96
#define R_ARM_GNU_VTENTRY 100
#define R_ARM_GNU_VTINHERIT 101
#define R_ARM_THM_JUMP11 102
#define R_ARM_THM_JUMP8 103
#define R_ARM_TLS_GD32 104
#define R_ARM_TLS_LDM32 105
#define R_ARM_TLS_IE32 107
#define R_ARM_THM_JUMP19 51
#define R_ARM_GNU_VTENTRY 100
#define R_ARM_GNU_VTINHERIT 101
#define R_ARM_RSBREL32 250
#define R_ARM_THM_RPC22 251
#define R_ARM_RREL32 252
#define R_ARM_RABS32 253
#define R_ARM_RPC24 254
#define R_ARM_RBASE 255
#define R_PPC_NONE 0/* No relocation. */
#define R_PPC_ADDR32 1

View File

@ -23,7 +23,6 @@
[Sources]
UniversalPayloadEntry.c
LoadDxeCore.c
MemoryAllocation.c
PrintHob.c
AcpiTable.c
@ -54,6 +53,7 @@
CpuLib
UefiImageLib
UefiCpuLib
MemoryAllocationLib
[Guids]
gEfiMemoryTypeInformationGuid

View File

@ -142,13 +142,6 @@
MSFT:RELEASE_*_*_CC_FLAGS = /D MDEPKG_NDEBUG
!endif
[BuildOptions.common.EDKII.DXE_RUNTIME_DRIVER]
GCC:*_*_*_DLINK_FLAGS = -z common-page-size=0x1000
XCODE:*_*_*_DLINK_FLAGS = -seg1addr 0x1000 -segalign 0x1000
XCODE:*_*_*_MTOC_FLAGS = -align 0x1000
CLANGPDB:*_*_*_DLINK_FLAGS = /ALIGN:4096
MSFT:*_*_*_DLINK_FLAGS = /ALIGN:4096
################################################################################
#
# SKU Identification section - list of all SKU IDs supported by this Platform.
@ -315,7 +308,7 @@
PcdLib|MdePkg/Library/BasePcdLibNull/BasePcdLibNull.inf
DxeHobListLib|UefiPayloadPkg/Library/DxeHobListLibNull/DxeHobListLibNull.inf
DebugLib|MdePkg/Library/BaseDebugLibSerialPort/BaseDebugLibSerialPort.inf
MemoryAllocationLib|UefiPayloadPkg/Library/UefiPayloadEntryMemoryAllocationLib/UefiPayloadEntryMemoryAllocationLib.inf
MemoryAllocationLib|UefiPayloadPkg/Library/UefiPayloadMemoryAllocationLib/UefiPayloadMemoryAllocationLib.inf
[LibraryClasses.common.DXE_CORE]
DxeHobListLib|UefiPayloadPkg/Library/DxeHobListLibNull/DxeHobListLibNull.inf

View File

@ -13,8 +13,8 @@ DEFINE FD_BASE = 0x00800000
DEFINE FD_BLOCK_SIZE = 0x00001000
!if $(TARGET) == "NOOPT"
DEFINE FD_SIZE = 0x00850000
DEFINE NUM_BLOCKS = 0x850
DEFINE FD_SIZE = 0x00A00000
DEFINE NUM_BLOCKS = 0xA00
!else
DEFINE FD_SIZE = 0x00590000