mirror of
https://github.com/acidanthera/audk.git
synced 2025-09-22 01:07:44 +02:00
BaseTools: Replaced GenFw with ImageTool and MicroTool.
This commit is contained in:
parent
ef68b89fbc
commit
cf92e9f7d7
6
.gitmodules
vendored
6
.gitmodules
vendored
@ -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
|
||||
|
6
BaseTools/.gitignore
vendored
6
BaseTools/.gitignore
vendored
@ -18,4 +18,8 @@ Source/C/bin/
|
||||
Source/C/libs/
|
||||
Bin/Win32
|
||||
Lib
|
||||
BaseToolsBuild/
|
||||
BaseToolsBuild/
|
||||
ImageTool/ImageTool
|
||||
ImageTool/ImageTool32
|
||||
ImageTool/ImageTool64
|
||||
MicroTool/MicroTool
|
||||
|
43
BaseTools/BinWrappers/PosixLike/ImageTool
Executable file
43
BaseTools/BinWrappers/PosixLike/ImageTool
Executable 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' ]
|
||||
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' ]
|
||||
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
|
25
BaseTools/BinWrappers/PosixLike/MicroTool
Normal file
25
BaseTools/BinWrappers/PosixLike/MicroTool
Normal 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
|
22
BaseTools/BinWrappers/WindowsLike/ImageTool.bat
Normal file
22
BaseTools/BinWrappers/WindowsLike/ImageTool.bat
Normal file
@ -0,0 +1,22 @@
|
||||
::
|
||||
:: 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%
|
||||
) else (
|
||||
if "%1%"=="X64" (
|
||||
call ImageTool64.exe %args%
|
||||
) else (
|
||||
echo Unable to find the command to run!
|
||||
)
|
||||
)
|
6
BaseTools/BinWrappers/WindowsLike/MicroTool.bat
Normal file
6
BaseTools/BinWrappers/WindowsLike/MicroTool.bat
Normal file
@ -0,0 +1,6 @@
|
||||
::
|
||||
:: Copyright (c) 2022, Mikhail Krichanov. All rights reserved.
|
||||
:: SPDX-License-Identifier: BSD-3-Clause
|
||||
::
|
||||
@echo off
|
||||
call MicroTool.exe %*
|
@ -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)
|
||||
|
||||
@ -299,8 +306,8 @@
|
||||
|
||||
<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
|
||||
@ -334,8 +341,8 @@
|
||||
|
||||
<Command.XCODE>
|
||||
"$(DLINK)" -o ${dst} $(DLINK_FLAGS) $(DLINK_SPATH) -filelist $(STATIC_LIBRARY_FILES_LIST) $(DLINK2_FLAGS)
|
||||
|
||||
|
||||
|
||||
|
||||
[Dynamic-Library-File]
|
||||
<InputFile>
|
||||
?.dll
|
||||
@ -346,32 +353,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)
|
||||
@ -405,14 +413,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
|
||||
|
||||
@ -439,12 +447,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>
|
||||
@ -459,25 +467,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
|
||||
@ -502,7 +509,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
|
||||
@ -510,7 +517,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>
|
||||
@ -538,7 +545,7 @@
|
||||
$(OUTPUT_DIR)(+)${s_base}.mcb
|
||||
|
||||
<Command>
|
||||
"$(GENFW)" -o ${dst} -m ${src} $(GENFW_FLAGS)
|
||||
MicroTool TxtToBin ${src} ${dst}
|
||||
|
||||
[Microcode-Binary-File]
|
||||
<InputFile>
|
||||
@ -551,7 +558,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]
|
||||
@ -641,12 +648,12 @@
|
||||
$(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)
|
||||
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)
|
||||
|
@ -2907,15 +2907,15 @@ DEFINE CLANGDWARF_X64_DLINK2_FLAGS = -Wl,--defsym=PECOFF_HEADER_SIZE=0x22
|
||||
*_CLANGDWARF_IA32_ASLPP_FLAGS = DEF(GCC_ASLPP_FLAGS) DEF(CLANG38_IA32_TARGET)
|
||||
*_CLANGDWARF_IA32_VFRPP_FLAGS = DEF(GCC_VFRPP_FLAGS) DEF(CLANG38_IA32_TARGET)
|
||||
|
||||
DEBUG_CLANGDWARF_IA32_CC_FLAGS = DEF(CLANG38_ALL_CC_FLAGS) -m32 -Oz -flto -march=i586 DEF(CLANG38_IA32_TARGET) -g -fno-pic -fno-pie
|
||||
DEBUG_CLANGDWARF_IA32_CC_FLAGS = DEF(CLANG38_ALL_CC_FLAGS) -m32 -malign-double -Oz -flto -march=i586 DEF(CLANG38_IA32_TARGET) -g -fno-pic -fno-pie
|
||||
DEBUG_CLANGDWARF_IA32_DLINK_FLAGS = DEF(CLANGDWARF_IA32_X64_DLINK_FLAGS) -flto -Wl,-O3 -Wl,-melf_i386 -Wl,--oformat,elf32-i386
|
||||
DEBUG_CLANGDWARF_IA32_DLINK2_FLAGS = DEF(CLANGDWARF_IA32_DLINK2_FLAGS) -O3 -fuse-ld=lld
|
||||
|
||||
RELEASE_CLANGDWARF_IA32_CC_FLAGS = DEF(CLANG38_ALL_CC_FLAGS) -m32 -Oz -flto -march=i586 DEF(CLANG38_IA32_TARGET) -fno-pic -fno-pie
|
||||
RELEASE_CLANGDWARF_IA32_CC_FLAGS = DEF(CLANG38_ALL_CC_FLAGS) -m32 -malign-double -Oz -flto -march=i586 DEF(CLANG38_IA32_TARGET) -fno-pic -fno-pie
|
||||
RELEASE_CLANGDWARF_IA32_DLINK_FLAGS = DEF(CLANGDWARF_IA32_X64_DLINK_FLAGS) -flto -Wl,-O3 -Wl,-melf_i386 -Wl,--oformat,elf32-i386
|
||||
RELEASE_CLANGDWARF_IA32_DLINK2_FLAGS = DEF(CLANGDWARF_IA32_DLINK2_FLAGS) -O3 -fuse-ld=lld
|
||||
|
||||
NOOPT_CLANGDWARF_IA32_CC_FLAGS = DEF(CLANG38_ALL_CC_FLAGS) -m32 -O0 -march=i586 DEF(CLANG38_IA32_TARGET) -g -fno-pic -fno-pie
|
||||
NOOPT_CLANGDWARF_IA32_CC_FLAGS = DEF(CLANG38_ALL_CC_FLAGS) -m32 -malign-double -O0 -march=i586 DEF(CLANG38_IA32_TARGET) -g -fno-pic -fno-pie
|
||||
NOOPT_CLANGDWARF_IA32_DLINK_FLAGS = DEF(CLANGDWARF_IA32_X64_DLINK_FLAGS) -Wl,-O0 -Wl,-melf_i386 -Wl,--oformat,elf32-i386
|
||||
NOOPT_CLANGDWARF_IA32_DLINK2_FLAGS = DEF(CLANGDWARF_IA32_DLINK2_FLAGS) -O0 -fuse-ld=lld
|
||||
|
||||
|
@ -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)
|
||||
|
301
BaseTools/ImageTool/BinEmit.c
Normal file
301
BaseTools/ImageTool/BinEmit.c
Normal 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;
|
||||
}
|
962
BaseTools/ImageTool/ElfScan.c
Normal file
962
BaseTools/ImageTool/ElfScan.c
Normal file
@ -0,0 +1,962 @@
|
||||
/** @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 = DEFAULT_PE_ALIGNMENT;
|
||||
static UINT64 mSizeOfHeaders = 0x0;
|
||||
|
||||
#if defined(EFI_TARGET64)
|
||||
static UINT8 *mGotData = NULL;
|
||||
static UINT32 mWGotOffset = 0x0;
|
||||
static const Elf_Shdr *mGOTShdr = NULL;
|
||||
static UINT32 *mGOTPeEntries = NULL;
|
||||
static UINT32 mGOTMaxEntries = 0;
|
||||
static UINT32 mGOTNumEntries = 0;
|
||||
#endif
|
||||
|
||||
#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
|
||||
Elf_Sym *
|
||||
GetSymbol (
|
||||
IN UINT32 TableIndex,
|
||||
IN UINT32 SymbolIndex
|
||||
)
|
||||
{
|
||||
const Elf_Shdr *TableShdr;
|
||||
UINT8 *Symtab;
|
||||
|
||||
TableShdr = GetShdrByIndex (TableIndex);
|
||||
Symtab = (UINT8 *)mEhdr + TableShdr->sh_offset;
|
||||
|
||||
return (Elf_Sym *)(Symtab + SymbolIndex * TableShdr->sh_entsize);
|
||||
}
|
||||
|
||||
static
|
||||
char *
|
||||
GetString (
|
||||
IN UINT32 Offset
|
||||
)
|
||||
{
|
||||
const Elf_Shdr *Shdr;
|
||||
char *String;
|
||||
|
||||
Shdr = GetShdrByIndex (mEhdr->e_shstrndx);
|
||||
|
||||
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
|
||||
IsTextShdr (
|
||||
IN const Elf_Shdr *Shdr
|
||||
)
|
||||
{
|
||||
assert (Shdr != NULL);
|
||||
|
||||
return ((((Shdr->sh_flags & (SHF_EXECINSTR | SHF_ALLOC)) == (SHF_EXECINSTR | SHF_ALLOC)) ||
|
||||
((Shdr->sh_flags & (SHF_WRITE | SHF_ALLOC)) == SHF_ALLOC))
|
||||
&& (Shdr->sh_type == SHT_PROGBITS));
|
||||
}
|
||||
|
||||
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
|
||||
IsDataShdr (
|
||||
IN const Elf_Shdr *Shdr
|
||||
)
|
||||
{
|
||||
assert (Shdr != NULL);
|
||||
|
||||
if (IsHiiRsrcShdr (Shdr)) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return (((Shdr->sh_flags & (SHF_EXECINSTR | SHF_WRITE | SHF_ALLOC)) == (SHF_ALLOC | SHF_WRITE))
|
||||
&& ((Shdr->sh_type == SHT_PROGBITS) || (Shdr->sh_type == SHT_NOBITS)));
|
||||
}
|
||||
|
||||
static
|
||||
BOOLEAN
|
||||
IsRelocShdr (
|
||||
IN const Elf_Shdr *Shdr
|
||||
)
|
||||
{
|
||||
const Elf_Shdr *SecShdr;
|
||||
const Elf_Rel *Rel;
|
||||
UINTN Index;
|
||||
|
||||
assert (Shdr != NULL);
|
||||
|
||||
if ((Shdr->sh_type != SHT_REL) && (Shdr->sh_type != SHT_RELA)) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
SecShdr = GetShdrByIndex (Shdr->sh_info);
|
||||
|
||||
if ((!IsTextShdr (SecShdr)) && (!IsDataShdr (SecShdr))) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
for (Index = 0; Index < Shdr->sh_size; Index += (UINTN)Shdr->sh_entsize) {
|
||||
Rel = (Elf_Rel *)((UINT8 *)mEhdr + Shdr->sh_offset + Index);
|
||||
#if defined(EFI_TARGET64)
|
||||
if ((ELF_R_TYPE(Rel->r_info) == R_X86_64_64)
|
||||
|| (ELF_R_TYPE(Rel->r_info) == R_X86_64_32)) {
|
||||
return TRUE;
|
||||
}
|
||||
#elif defined(EFI_TARGET32)
|
||||
if (ELF_R_TYPE(Rel->r_info) == R_386_32) {
|
||||
return TRUE;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
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
|
||||
VOID
|
||||
FindAddress (
|
||||
IN UINT32 ElfIndex,
|
||||
OUT UINT8 **SectionData,
|
||||
OUT UINT32 *WOffset
|
||||
)
|
||||
{
|
||||
UINT32 Index;
|
||||
|
||||
assert (SectionData != NULL);
|
||||
assert (WOffset != NULL);
|
||||
|
||||
*WOffset = (UINT32)mSizeOfHeaders;
|
||||
|
||||
for (Index = 0; Index < mImageInfo.SegmentInfo.NumSegments; ++Index) {
|
||||
if (mImageInfo.SegmentInfo.Segments[Index].ImageSize == ElfIndex) {
|
||||
*SectionData = mImageInfo.SegmentInfo.Segments[Index].Data;
|
||||
break;
|
||||
}
|
||||
|
||||
*WOffset += mImageInfo.SegmentInfo.Segments[Index].DataSize;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
#if defined(EFI_TARGET64)
|
||||
static
|
||||
RETURN_STATUS
|
||||
FindElfGOTSectionFromGOTEntryElfRva (
|
||||
IN Elf_Addr GOTEntryElfRva
|
||||
)
|
||||
{
|
||||
UINT32 Index;
|
||||
const Elf_Shdr *Shdr;
|
||||
|
||||
if (mGOTShdr != NULL) {
|
||||
if ((GOTEntryElfRva >= mGOTShdr->sh_addr)
|
||||
&& (GOTEntryElfRva < (mGOTShdr->sh_addr + mGOTShdr->sh_size))) {
|
||||
return RETURN_SUCCESS;
|
||||
}
|
||||
|
||||
fprintf (stderr, "ImageTool: GOT entries found in multiple sections\n");
|
||||
return RETURN_UNSUPPORTED;
|
||||
}
|
||||
|
||||
for (Index = 0; Index < mEhdr->e_shnum; ++Index) {
|
||||
Shdr = GetShdrByIndex(Index);
|
||||
if ((GOTEntryElfRva >= Shdr->sh_addr)
|
||||
&& (GOTEntryElfRva < (Shdr->sh_addr + Shdr->sh_size))) {
|
||||
mGOTShdr = Shdr;
|
||||
FindAddress (Index, &mGotData, &mWGotOffset);
|
||||
return RETURN_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
fprintf (stderr, "ImageTool: ElfRva 0x%016llx for GOT entry not found in any section\n", GOTEntryElfRva);
|
||||
return RETURN_VOLUME_CORRUPTED;
|
||||
}
|
||||
|
||||
static
|
||||
RETURN_STATUS
|
||||
AccumulatePeGOTEntries (
|
||||
IN UINT32 GOTPeEntry,
|
||||
OUT BOOLEAN *IsNew
|
||||
)
|
||||
{
|
||||
UINT32 Index;
|
||||
|
||||
assert (IsNew != NULL);
|
||||
|
||||
if (mGOTPeEntries != NULL) {
|
||||
for (Index = 0; Index < mGOTNumEntries; ++Index) {
|
||||
if (mGOTPeEntries[Index] == GOTPeEntry) {
|
||||
*IsNew = FALSE;
|
||||
return RETURN_SUCCESS;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (mGOTPeEntries == NULL) {
|
||||
mGOTMaxEntries = 5;
|
||||
mGOTNumEntries = 0;
|
||||
mGOTPeEntries = calloc (1, mGOTMaxEntries * sizeof (*mGOTPeEntries));
|
||||
if (mGOTPeEntries == NULL) {
|
||||
fprintf (stderr, "ImageTool: Could not allocate memory for mGOTPeEntries\n");
|
||||
return RETURN_OUT_OF_RESOURCES;
|
||||
}
|
||||
} else if (mGOTNumEntries == mGOTMaxEntries) {
|
||||
mGOTMaxEntries *= 2;
|
||||
mGOTPeEntries = realloc (mGOTPeEntries, mGOTMaxEntries * sizeof (*mGOTPeEntries));
|
||||
if (mGOTPeEntries == NULL) {
|
||||
fprintf (stderr, "ImageTool: Could not reallocate memory for mGOTPeEntries\n");
|
||||
return RETURN_OUT_OF_RESOURCES;
|
||||
}
|
||||
}
|
||||
|
||||
mGOTPeEntries[mGOTNumEntries] = mWGotOffset + GOTPeEntry;
|
||||
++mGOTNumEntries;
|
||||
*IsNew = TRUE;
|
||||
|
||||
return RETURN_SUCCESS;
|
||||
}
|
||||
#endif
|
||||
|
||||
static
|
||||
RETURN_STATUS
|
||||
ReadElfFile (
|
||||
IN const char *Name
|
||||
)
|
||||
{
|
||||
static const unsigned char Ident[] = {
|
||||
ELFMAG0, ELFMAG1, ELFMAG2, ELFMAG3, ELFCLASS, ELFDATA2LSB
|
||||
};
|
||||
const Elf_Shdr *Shdr;
|
||||
UINTN Offset;
|
||||
UINT32 Index;
|
||||
UINT32 FileSize;
|
||||
char *Last;
|
||||
|
||||
assert (Name != NULL);
|
||||
|
||||
mEhdr = (Elf_Ehdr *)UserReadFile (Name, &FileSize);
|
||||
if (mEhdr == NULL) {
|
||||
fprintf (stderr, "ImageTool: Could not open %s: %s\n", Name, strerror (errno));
|
||||
return RETURN_VOLUME_CORRUPTED;
|
||||
}
|
||||
|
||||
//
|
||||
// Check header
|
||||
//
|
||||
if ((FileSize < sizeof (*mEhdr))
|
||||
|| (memcmp (Ident, mEhdr->e_ident, sizeof (Ident)) != 0)) {
|
||||
fprintf (stderr, "ImageTool: Invalid ELF header in file %s\n", Name);
|
||||
fprintf (stderr, "ImageTool: 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_VOLUME_CORRUPTED;
|
||||
}
|
||||
|
||||
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_UNSUPPORTED;
|
||||
}
|
||||
|
||||
#if defined(EFI_TARGET64)
|
||||
if (mEhdr->e_machine != EM_X86_64) {
|
||||
fprintf (stderr, "ImageTool: Unsupported ELF e_machine\n");
|
||||
return RETURN_UNSUPPORTED;
|
||||
}
|
||||
#elif defined(EFI_TARGET32)
|
||||
if (mEhdr->e_machine != EM_386) {
|
||||
fprintf (stderr, "ImageTool: Unsupported ELF e_machine\n");
|
||||
return RETURN_UNSUPPORTED;
|
||||
}
|
||||
#endif
|
||||
|
||||
//
|
||||
// Check section headers
|
||||
//
|
||||
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 %s\n", Name);
|
||||
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 %s\n", Index, Name);
|
||||
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))
|
||||
&& (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_addralign <= mPeAlignment) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ((IsTextShdr (Shdr)) || (IsDataShdr (Shdr)) || (IsHiiRsrcShdr (Shdr))) {
|
||||
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
|
||||
RETURN_STATUS
|
||||
FixSegmentsSetRelocs (
|
||||
VOID
|
||||
)
|
||||
{
|
||||
UINT32 Index;
|
||||
const Elf_Shdr *RelShdr;
|
||||
const Elf_Shdr *SecShdr;
|
||||
UINT8 *SecData;
|
||||
UINT32 WSecOffset;
|
||||
UINTN RelIdx;
|
||||
const Elf_Rela *Rel;
|
||||
const Elf_Sym *Sym;
|
||||
const Elf_Shdr *SymShdr;
|
||||
UINT8 *SymData;
|
||||
UINT32 WSymOffset;
|
||||
UINT8 *Targ;
|
||||
UINT32 RelNum;
|
||||
UINTN Offset;
|
||||
#if defined(EFI_TARGET64)
|
||||
Elf_Addr GOTEntryRva;
|
||||
RETURN_STATUS Status;
|
||||
BOOLEAN IsNew;
|
||||
#endif
|
||||
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 (RelShdr->sh_info == 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
SecShdr = GetShdrByIndex (RelShdr->sh_info);
|
||||
FindAddress (RelShdr->sh_info, &SecData, &WSecOffset);
|
||||
|
||||
#if defined(EFI_TARGET64)
|
||||
if ((RelShdr->sh_type != SHT_RELA) || (!((IsTextShdr (SecShdr)) || (IsDataShdr (SecShdr))))) {
|
||||
continue;
|
||||
}
|
||||
#elif defined(EFI_TARGET32)
|
||||
if ((RelShdr->sh_type != SHT_REL) || (!((IsTextShdr (SecShdr)) || (IsDataShdr (SecShdr))))) {
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
|
||||
//
|
||||
// Process all relocation entries for this section.
|
||||
//
|
||||
for (RelIdx = 0; RelIdx < RelShdr->sh_size; RelIdx += (UINTN)RelShdr->sh_entsize) {
|
||||
Rel = (Elf_Rela *)((UINT8 *)mEhdr + RelShdr->sh_offset + RelIdx);
|
||||
|
||||
Offset = (UINTN)((Elf_Addr)WSecOffset + (Rel->r_offset - SecShdr->sh_addr));
|
||||
|
||||
//
|
||||
// Set pointer to symbol table entry associated with the relocation entry.
|
||||
//
|
||||
Sym = GetSymbol (RelShdr->sh_link, ELF_R_SYM(Rel->r_info));
|
||||
if ((Sym->st_shndx == SHN_UNDEF) || (Sym->st_shndx >= mEhdr->e_shnum)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
SymShdr = GetShdrByIndex (Sym->st_shndx);
|
||||
FindAddress (Sym->st_shndx, &SymData, &WSymOffset);
|
||||
|
||||
Targ = SecData + (Rel->r_offset - SecShdr->sh_addr);
|
||||
|
||||
#if defined(EFI_TARGET64)
|
||||
switch (ELF_R_TYPE(Rel->r_info)) {
|
||||
case R_X86_64_NONE:
|
||||
break;
|
||||
case R_X86_64_64:
|
||||
WriteUnaligned64 ((UINT64 *)Targ, ReadUnaligned64((UINT64 *)Targ) - SymShdr->sh_addr + WSymOffset);
|
||||
|
||||
mImageInfo.RelocInfo.Relocs[RelNum].Type = EFI_IMAGE_REL_BASED_DIR64;
|
||||
mImageInfo.RelocInfo.Relocs[RelNum].Target = (uint32_t)Offset;
|
||||
++RelNum;
|
||||
|
||||
break;
|
||||
case R_X86_64_32:
|
||||
WriteUnaligned32 ((UINT32 *)Targ, (UINT32)((UINT64)ReadUnaligned32((UINT32 *)Targ) - SymShdr->sh_addr + WSymOffset));
|
||||
|
||||
mImageInfo.RelocInfo.Relocs[RelNum].Type = EFI_IMAGE_REL_BASED_HIGHLOW;
|
||||
mImageInfo.RelocInfo.Relocs[RelNum].Target = (uint32_t)Offset;
|
||||
++RelNum;
|
||||
|
||||
break;
|
||||
case R_X86_64_32S:
|
||||
*(INT32 *)Targ = (INT32)((INT64)(*(INT32 *)Targ) - SymShdr->sh_addr + WSymOffset);
|
||||
break;
|
||||
case R_X86_64_PLT32:
|
||||
case R_X86_64_PC32:
|
||||
WriteUnaligned32 ((UINT32 *)Targ, (UINT32)(ReadUnaligned32((UINT32 *)Targ) + (WSymOffset - WSecOffset) - (SymShdr->sh_addr - SecShdr->sh_addr)));
|
||||
break;
|
||||
case R_X86_64_GOTPCREL:
|
||||
case R_X86_64_GOTPCRELX:
|
||||
case R_X86_64_REX_GOTPCRELX:
|
||||
GOTEntryRva = Rel->r_offset - Rel->r_addend + *(INT32 *)Targ;
|
||||
|
||||
Status = FindElfGOTSectionFromGOTEntryElfRva (GOTEntryRva);
|
||||
if (RETURN_ERROR (Status)) {
|
||||
return Status;
|
||||
}
|
||||
|
||||
WriteUnaligned32 ((UINT32 *)Targ, (UINT32)(ReadUnaligned32((UINT32 *)Targ) + (mWGotOffset - mGOTShdr->sh_addr) - (WSecOffset - SecShdr->sh_addr)));
|
||||
//
|
||||
// ELF Rva -> Offset in PE GOT
|
||||
//
|
||||
GOTEntryRva -= mGOTShdr->sh_addr;
|
||||
|
||||
Status = AccumulatePeGOTEntries ((UINT32)GOTEntryRva, &IsNew);
|
||||
if (RETURN_ERROR (Status)) {
|
||||
return Status;
|
||||
}
|
||||
|
||||
if (IsNew) {
|
||||
//
|
||||
// Relocate GOT entry if it's the first time we run into it
|
||||
//
|
||||
Targ = mGotData + GOTEntryRva;
|
||||
|
||||
WriteUnaligned64 ((UINT64 *)Targ, ReadUnaligned64((UINT64 *)Targ) - SymShdr->sh_addr + WSymOffset);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
fprintf (stderr, "ImageTool: Unsupported ELF EM_X86_64 relocation 0x%llx\n", ELF_R_TYPE(Rel->r_info));
|
||||
return RETURN_UNSUPPORTED;
|
||||
}
|
||||
#elif defined(EFI_TARGET32)
|
||||
switch (ELF_R_TYPE(Rel->r_info)) {
|
||||
case R_386_NONE:
|
||||
break;
|
||||
case R_386_32:
|
||||
WriteUnaligned32 ((UINT32 *)Targ, ReadUnaligned32((UINT32 *)Targ) - SymShdr->sh_addr + WSymOffset);
|
||||
|
||||
mImageInfo.RelocInfo.Relocs[RelNum].Type = EFI_IMAGE_REL_BASED_HIGHLOW;
|
||||
mImageInfo.RelocInfo.Relocs[RelNum].Target = Offset;
|
||||
++RelNum;
|
||||
|
||||
break;
|
||||
case R_386_PLT32:
|
||||
case R_386_PC32:
|
||||
WriteUnaligned32 ((UINT32 *)Targ, (UINT32)(ReadUnaligned32((UINT32 *)Targ) + (WSymOffset - WSecOffset) - (SymShdr->sh_addr - SecShdr->sh_addr)));
|
||||
break;
|
||||
default:
|
||||
fprintf (stderr, "ImageTool: Unsupported ELF EM_386 relocation 0x%x\n", ELF_R_TYPE(Rel->r_info));
|
||||
return RETURN_UNSUPPORTED;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
assert (RelNum == mImageInfo.RelocInfo.NumRelocs);
|
||||
|
||||
return RETURN_SUCCESS;
|
||||
}
|
||||
|
||||
static
|
||||
RETURN_STATUS
|
||||
FixAddresses (
|
||||
VOID
|
||||
)
|
||||
{
|
||||
RETURN_STATUS Status;
|
||||
UINT32 Index;
|
||||
const Elf_Shdr *Shdr;
|
||||
UINT64 Pointer;
|
||||
#if defined(EFI_TARGET64)
|
||||
UINT32 NewSize;
|
||||
#endif
|
||||
|
||||
mSizeOfHeaders = sizeof (EFI_IMAGE_DOS_HEADER) + sizeof (EFI_IMAGE_NT_HEADERS) +
|
||||
EFI_IMAGE_NUMBER_OF_DIRECTORY_ENTRIES * sizeof (EFI_IMAGE_DATA_DIRECTORY) +
|
||||
mImageInfo.SegmentInfo.NumSegments * sizeof (EFI_IMAGE_SECTION_HEADER);
|
||||
|
||||
if (mImageInfo.RelocInfo.Relocs != NULL) {
|
||||
mSizeOfHeaders += sizeof (EFI_IMAGE_SECTION_HEADER);
|
||||
}
|
||||
|
||||
if (mImageInfo.DebugInfo.SymbolsPath != NULL) {
|
||||
mSizeOfHeaders += sizeof (EFI_IMAGE_SECTION_HEADER);
|
||||
}
|
||||
|
||||
if (mImageInfo.HiiInfo.Data != NULL) {
|
||||
mSizeOfHeaders += sizeof (EFI_IMAGE_SECTION_HEADER);
|
||||
}
|
||||
|
||||
mSizeOfHeaders = ALIGN_VALUE (mSizeOfHeaders, mPeAlignment);
|
||||
|
||||
Status = FixSegmentsSetRelocs ();
|
||||
if (RETURN_ERROR (Status)) {
|
||||
return Status;
|
||||
}
|
||||
|
||||
Pointer = mSizeOfHeaders;
|
||||
|
||||
for (Index = 0; Index < mImageInfo.SegmentInfo.NumSegments; ++Index) {
|
||||
Shdr = GetShdrByIndex (mImageInfo.SegmentInfo.Segments[Index].ImageSize);
|
||||
|
||||
if ((mEhdr->e_entry >= Shdr->sh_addr)
|
||||
&& ((mEhdr->e_entry - Shdr->sh_addr) < Shdr->sh_size)) {
|
||||
mImageInfo.HeaderInfo.EntryPointAddress = (uint32_t)Pointer + (uint32_t)(mEhdr->e_entry - Shdr->sh_addr);
|
||||
}
|
||||
|
||||
mImageInfo.SegmentInfo.Segments[Index].ImageAddress = Pointer;
|
||||
mImageInfo.SegmentInfo.Segments[Index].ImageSize = mImageInfo.SegmentInfo.Segments[Index].DataSize;
|
||||
|
||||
Pointer += mImageInfo.SegmentInfo.Segments[Index].DataSize;
|
||||
}
|
||||
|
||||
if (mImageInfo.HiiInfo.Data != NULL) {
|
||||
SetHiiResourceHeader (mImageInfo.HiiInfo.Data, (UINT32)Pointer);
|
||||
}
|
||||
|
||||
#if defined(EFI_TARGET64)
|
||||
if (mGOTPeEntries != NULL) {
|
||||
NewSize = (mImageInfo.RelocInfo.NumRelocs + mGOTNumEntries) * sizeof (*mImageInfo.RelocInfo.Relocs);
|
||||
|
||||
mImageInfo.RelocInfo.Relocs = realloc (mImageInfo.RelocInfo.Relocs, NewSize);
|
||||
if (mImageInfo.RelocInfo.Relocs == NULL) {
|
||||
fprintf (stderr, "ImageTool: Could not reallocate memory for Relocs\n");
|
||||
return RETURN_OUT_OF_RESOURCES;
|
||||
}
|
||||
|
||||
for (Index = 0; Index < mGOTNumEntries; ++Index) {
|
||||
mImageInfo.RelocInfo.Relocs[mImageInfo.RelocInfo.NumRelocs + Index].Type = EFI_IMAGE_REL_BASED_DIR64;
|
||||
mImageInfo.RelocInfo.Relocs[mImageInfo.RelocInfo.NumRelocs + Index].Target = mGOTPeEntries[Index];
|
||||
}
|
||||
}
|
||||
#endif
|
||||
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;
|
||||
|
||||
Segments = NULL;
|
||||
SIndex = 0;
|
||||
Relocs = NULL;
|
||||
|
||||
for (Index = 0; Index < mEhdr->e_shnum; ++Index) {
|
||||
Shdr = GetShdrByIndex (Index);
|
||||
|
||||
if ((IsTextShdr (Shdr)) || (IsDataShdr (Shdr)) || (IsHiiRsrcShdr (Shdr))) {
|
||||
if ((Shdr->sh_addralign == 0) || (Shdr->sh_addralign == 1)) {
|
||||
fprintf (stderr, "ImageTool: Alignment field is invalid\n");
|
||||
return RETURN_VOLUME_CORRUPTED;
|
||||
}
|
||||
|
||||
if (!IS_ALIGNED(Shdr->sh_addr, Shdr->sh_addralign)) {
|
||||
fprintf (stderr, "ImageTool: Section address not aligned to its own alignment\n");
|
||||
return RETURN_VOLUME_CORRUPTED;
|
||||
}
|
||||
}
|
||||
|
||||
if ((IsTextShdr (Shdr)) || (IsDataShdr (Shdr))) {
|
||||
++mImageInfo.SegmentInfo.NumSegments;
|
||||
}
|
||||
|
||||
if (IsRelocShdr (Shdr)) {
|
||||
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 ((ELF_R_TYPE(Rel->r_info) == R_X86_64_64)
|
||||
|| (ELF_R_TYPE(Rel->r_info) == R_X86_64_32)) {
|
||||
++mImageInfo.RelocInfo.NumRelocs;
|
||||
}
|
||||
#elif defined(EFI_TARGET32)
|
||||
if (ELF_R_TYPE(Rel->r_info) == R_386_32) {
|
||||
++mImageInfo.RelocInfo.NumRelocs;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (mImageInfo.SegmentInfo.NumSegments == 0) {
|
||||
fprintf (stderr, "ImageTool: No .text or .data 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 (mImageInfo.RelocInfo.NumRelocs != 0) {
|
||||
Relocs = calloc (1, sizeof (*Relocs) * mImageInfo.RelocInfo.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 (IsTextShdr (Shdr)) {
|
||||
Name = GetString (Shdr->sh_name);
|
||||
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", SIndex);
|
||||
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", SIndex);
|
||||
return RETURN_OUT_OF_RESOURCES;
|
||||
};
|
||||
|
||||
memcpy (Segments[SIndex].Data, (UINT8 *)mEhdr + Shdr->sh_offset, (size_t)Shdr->sh_size);
|
||||
|
||||
Segments[SIndex].ImageAddress = 0;
|
||||
Segments[SIndex].ImageSize = Index; // Will be needed by FindAddress()
|
||||
Segments[SIndex].Read = true;
|
||||
Segments[SIndex].Write = false;
|
||||
Segments[SIndex].Execute = true;
|
||||
Segments[SIndex].Type = ToolImageSectionTypeCode;
|
||||
++SIndex;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (IsDataShdr (Shdr)) {
|
||||
Name = GetString (Shdr->sh_name);
|
||||
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", SIndex);
|
||||
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", SIndex);
|
||||
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 = 0;
|
||||
Segments[SIndex].ImageSize = Index; // Will be needed by FindAddress()
|
||||
Segments[SIndex].Read = true;
|
||||
Segments[SIndex].Write = true;
|
||||
Segments[SIndex].Execute = false;
|
||||
Segments[SIndex].Type = ToolImageSectionTypeInitialisedData;
|
||||
++SIndex;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (IsHiiRsrcShdr (Shdr)) {
|
||||
mImageInfo.HiiInfo.DataSize = (uint32_t)ALIGN_VALUE (Shdr->sh_size, mPeAlignment);
|
||||
|
||||
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, (size_t)Shdr->sh_size);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
assert (SIndex == mImageInfo.SegmentInfo.NumSegments);
|
||||
|
||||
return FixAddresses();
|
||||
}
|
||||
|
||||
RETURN_STATUS
|
||||
ScanElf (
|
||||
IN const char *ElfName,
|
||||
IN const char *ModuleType
|
||||
)
|
||||
{
|
||||
RETURN_STATUS Status;
|
||||
|
||||
assert (ElfName != NULL);
|
||||
assert (ModuleType != NULL);
|
||||
|
||||
Status = ReadElfFile (ElfName);
|
||||
if (RETURN_ERROR (Status)) {
|
||||
if (mEhdr != NULL) {
|
||||
free (mEhdr);
|
||||
}
|
||||
return Status;
|
||||
}
|
||||
|
||||
memset (&mImageInfo, 0, sizeof (mImageInfo));
|
||||
|
||||
mImageInfo.HeaderInfo.PreferredAddress = 0;
|
||||
mImageInfo.HeaderInfo.EntryPointAddress = 0;
|
||||
mImageInfo.HeaderInfo.IsXip = true;
|
||||
mImageInfo.SegmentInfo.SegmentAlignment = (uint32_t)mPeAlignment;
|
||||
mImageInfo.RelocInfo.RelocsStripped = false;
|
||||
mImageInfo.DebugInfo.SymbolsPathLen = strlen (ElfName) + 1;
|
||||
|
||||
switch (mEhdr->e_machine) {
|
||||
case EM_386:
|
||||
mImageInfo.HeaderInfo.Machine = EFI_IMAGE_MACHINE_IA32;
|
||||
break;
|
||||
case EM_X86_64:
|
||||
mImageInfo.HeaderInfo.Machine = EFI_IMAGE_MACHINE_X64;
|
||||
break;
|
||||
case EM_ARM:
|
||||
mImageInfo.HeaderInfo.Machine = EFI_IMAGE_MACHINE_ARMTHUMB_MIXED;
|
||||
break;
|
||||
case EM_AARCH64:
|
||||
mImageInfo.HeaderInfo.Machine = EFI_IMAGE_MACHINE_AARCH64;
|
||||
break;
|
||||
default:
|
||||
fprintf (stderr, "ImageTool: Unknown ELF architecture %d\n", mEhdr->e_machine);
|
||||
free (mEhdr);
|
||||
return RETURN_UNSUPPORTED;
|
||||
}
|
||||
|
||||
mImageInfo.DebugInfo.SymbolsPath = calloc (1, mImageInfo.DebugInfo.SymbolsPathLen);
|
||||
if (mImageInfo.DebugInfo.SymbolsPath == NULL) {
|
||||
fprintf (stderr, "ImageTool: Could not allocate memory for Debug Data\n");
|
||||
free (mEhdr);
|
||||
return RETURN_OUT_OF_RESOURCES;
|
||||
};
|
||||
|
||||
memcpy (mImageInfo.DebugInfo.SymbolsPath, ElfName, mImageInfo.DebugInfo.SymbolsPathLen);
|
||||
|
||||
if ((strcmp (ModuleType, "BASE") == 0)
|
||||
|| (strcmp (ModuleType, "SEC") == 0)
|
||||
|| (strcmp (ModuleType, "SECURITY_CORE") == 0)
|
||||
|| (strcmp (ModuleType, "PEI_CORE") == 0)
|
||||
|| (strcmp (ModuleType, "PEIM") == 0)
|
||||
|| (strcmp (ModuleType, "COMBINED_PEIM_DRIVER") == 0)
|
||||
|| (strcmp (ModuleType, "PIC_PEIM") == 0)
|
||||
|| (strcmp (ModuleType, "RELOCATABLE_PEIM") == 0)
|
||||
|| (strcmp (ModuleType, "DXE_CORE") == 0)
|
||||
|| (strcmp (ModuleType, "BS_DRIVER") == 0)
|
||||
|| (strcmp (ModuleType, "DXE_DRIVER") == 0)
|
||||
|| (strcmp (ModuleType, "DXE_SMM_DRIVER") == 0)
|
||||
|| (strcmp (ModuleType, "UEFI_DRIVER") == 0)
|
||||
|| (strcmp (ModuleType, "SMM_CORE") == 0)
|
||||
|| (strcmp (ModuleType, "MM_STANDALONE") == 0)
|
||||
|| (strcmp (ModuleType, "MM_CORE_STANDALONE") == 0)) {
|
||||
mImageInfo.HeaderInfo.Subsystem = EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER;
|
||||
} else if ((strcmp (ModuleType, "UEFI_APPLICATION") == 0)
|
||||
|| (strcmp (ModuleType, "APPLICATION") == 0)) {
|
||||
mImageInfo.HeaderInfo.Subsystem = EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION;
|
||||
} else if ((strcmp (ModuleType, "DXE_RUNTIME_DRIVER") == 0)
|
||||
|| (strcmp (ModuleType, "RT_DRIVER") == 0)) {
|
||||
mImageInfo.HeaderInfo.Subsystem = EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER;
|
||||
} else if ((strcmp (ModuleType, "DXE_SAL_DRIVER") == 0)
|
||||
|| (strcmp (ModuleType, "SAL_RT_DRIVER") == 0)) {
|
||||
mImageInfo.HeaderInfo.Subsystem = EFI_IMAGE_SUBSYSTEM_SAL_RUNTIME_DRIVER;
|
||||
} else {
|
||||
fprintf (stderr, "ImageTool: Unknown EFI_FILETYPE = %s\n", ModuleType);
|
||||
free (mImageInfo.DebugInfo.SymbolsPath);
|
||||
free (mEhdr);
|
||||
return RETURN_UNSUPPORTED;
|
||||
}
|
||||
|
||||
Status = CreateIntermediate ();
|
||||
if (RETURN_ERROR (Status)) {
|
||||
ToolImageDestruct (&mImageInfo);
|
||||
}
|
||||
|
||||
#if defined(EFI_TARGET64)
|
||||
if (mGOTPeEntries != NULL) {
|
||||
free (mGOTPeEntries);
|
||||
}
|
||||
#endif
|
||||
free (mEhdr);
|
||||
|
||||
return Status;
|
||||
}
|
35
BaseTools/ImageTool/GNUmakefile
Normal file
35
BaseTools/ImageTool/GNUmakefile
Normal file
@ -0,0 +1,35 @@
|
||||
## @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 UeEmit.o ElfScan.o BinEmit.o
|
||||
OBJS += BaseAlignment.o BaseBitOverflow.o UeImageLib.o 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 += -include Pcds.h -Werror
|
||||
|
||||
VPATH += ../../MdePkg/Library/BaseOverflowLib:$\
|
||||
../../MdePkg/Library/BasePeCoffLib2:$\
|
||||
../../MdePkg/Library/BaseUefiImageExtraActionLibNull:$\
|
||||
../../MdePkg/Library/BaseUeImageLib
|
||||
|
||||
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
|
312
BaseTools/ImageTool/Image.c
Normal file
312
BaseTools/ImageTool/Image.c
Normal file
@ -0,0 +1,312 @@
|
||||
/** @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;
|
||||
void *Memory;
|
||||
|
||||
assert (Image != NULL);
|
||||
|
||||
SegmentInfo = &Image->SegmentInfo;
|
||||
|
||||
for (Index = 0; Index < SegmentInfo->NumSegments; ++Index) {
|
||||
Segment = &SegmentInfo->Segments[Index];
|
||||
|
||||
assert (Segment->DataSize <= Segment->ImageSize);
|
||||
|
||||
Data = calloc (Segment->ImageSize, 1);
|
||||
if (Data == NULL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
memmove (Data, Segment->Data, Segment->DataSize);
|
||||
|
||||
Memory = Segment->Data;
|
||||
|
||||
Segment->Data = Data;
|
||||
Segment->DataSize = Segment->ImageSize;
|
||||
|
||||
free (Memory);
|
||||
}
|
||||
|
||||
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));
|
||||
}
|
552
BaseTools/ImageTool/ImageTool.c
Normal file
552
BaseTools/ImageTool/ImageTool.c
Normal file
@ -0,0 +1,552 @@
|
||||
/** @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
|
||||
PeToUe (
|
||||
IN const char *PeName,
|
||||
IN const char *UeName
|
||||
)
|
||||
{
|
||||
void *Pe;
|
||||
uint32_t PeSize;
|
||||
void *Ue;
|
||||
uint32_t UeSize;
|
||||
bool Result;
|
||||
image_tool_image_info_t Image;
|
||||
|
||||
assert (PeName != NULL);
|
||||
assert (UeName != NULL);
|
||||
|
||||
Pe = UserReadFile (PeName, &PeSize);
|
||||
if (Pe == NULL) {
|
||||
return RETURN_ABORTED;
|
||||
}
|
||||
|
||||
Result = ToolContextConstructPe (&Image, Pe, PeSize, NULL);
|
||||
|
||||
free (Pe);
|
||||
Pe = NULL;
|
||||
|
||||
if (!Result) {
|
||||
return RETURN_ABORTED;
|
||||
}
|
||||
|
||||
Result = CheckToolImage (&Image);
|
||||
if (!Result) {
|
||||
ToolImageDestruct (&Image);
|
||||
return RETURN_ABORTED;
|
||||
}
|
||||
|
||||
Result = ImageConvertToXip (&Image);
|
||||
if (!Result) {
|
||||
ToolImageDestruct (&Image);
|
||||
return RETURN_ABORTED;
|
||||
}
|
||||
|
||||
Ue = ToolImageEmitUe (&Image, &UeSize);
|
||||
|
||||
if (Ue == NULL) {
|
||||
ToolImageDestruct (&Image);
|
||||
return RETURN_ABORTED;
|
||||
}
|
||||
|
||||
ToolImageDestruct (&Image);
|
||||
|
||||
/*UE_LOADER_IMAGE_CONTEXT UeContext;
|
||||
RETURN_STATUS Status = UeInitializeContext(&UeContext, Ue, UeSize);
|
||||
printf("UE status - %llu\n", Status);*/
|
||||
|
||||
UserWriteFile (UeName, Ue, UeSize);
|
||||
|
||||
free (Ue);
|
||||
Ue = NULL;
|
||||
|
||||
return RETURN_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
static
|
||||
RETURN_STATUS
|
||||
PeXip (
|
||||
IN const char *OldName,
|
||||
IN const char *NewName,
|
||||
IN const char *ModuleType
|
||||
)
|
||||
{
|
||||
void *Pe;
|
||||
uint32_t PeSize;
|
||||
bool Result;
|
||||
image_tool_image_info_t Image;
|
||||
|
||||
assert (OldName != NULL);
|
||||
assert (NewName != NULL);
|
||||
assert (ModuleType != NULL);
|
||||
|
||||
Pe = UserReadFile (OldName, &PeSize);
|
||||
if (Pe == NULL) {
|
||||
fprintf (stderr, "ImageTool: Could not open %s: %s\n", OldName, strerror (errno));
|
||||
return RETURN_ABORTED;
|
||||
}
|
||||
|
||||
Result = ToolContextConstructPe (&Image, Pe, PeSize, ModuleType);
|
||||
|
||||
free (Pe);
|
||||
Pe = NULL;
|
||||
|
||||
if (!Result) {
|
||||
ToolImageDestruct (&Image);
|
||||
return RETURN_ABORTED;
|
||||
}
|
||||
|
||||
Pe = ToolImageEmitPe (&Image, &PeSize);
|
||||
if (Pe == NULL) {
|
||||
ToolImageDestruct (&Image);
|
||||
return RETURN_ABORTED;
|
||||
}
|
||||
|
||||
ToolImageDestruct (&Image);
|
||||
|
||||
UserWriteFile (NewName, Pe, PeSize);
|
||||
|
||||
free (Pe);
|
||||
|
||||
return RETURN_SUCCESS;
|
||||
}
|
||||
|
||||
static
|
||||
RETURN_STATUS
|
||||
HiiBin (
|
||||
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)) {
|
||||
|
||||
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
|
||||
RETURN_STATUS
|
||||
ElfToPe (
|
||||
IN const char *ElfName,
|
||||
IN const char *PeName,
|
||||
IN const char *ModuleType
|
||||
)
|
||||
{
|
||||
RETURN_STATUS Status;
|
||||
void *Pe;
|
||||
uint32_t PeSize;
|
||||
|
||||
assert (ElfName != NULL);
|
||||
assert (PeName != NULL);
|
||||
assert (ModuleType != NULL);
|
||||
|
||||
Status = ScanElf (ElfName, ModuleType);
|
||||
if (RETURN_ERROR (Status)) {
|
||||
return Status;
|
||||
}
|
||||
|
||||
Pe = ToolImageEmitPe (&mImageInfo, &PeSize);
|
||||
if (Pe == NULL) {
|
||||
ToolImageDestruct (&mImageInfo);
|
||||
return RETURN_ABORTED;
|
||||
}
|
||||
|
||||
ToolImageDestruct (&mImageInfo);
|
||||
|
||||
UserWriteFile (PeName, Pe, PeSize);
|
||||
|
||||
free (Pe);
|
||||
|
||||
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) {
|
||||
if (argc < 5) {
|
||||
fprintf (stderr, "ImageTool: Command arguments are missing\n");
|
||||
fprintf (stderr, " Usage: ImageTool ElfToPe InputFile OutputFile ModuleType\n");
|
||||
raise ();
|
||||
return -1;
|
||||
}
|
||||
|
||||
Status = ElfToPe (argv[2], argv [3], argv[4]);
|
||||
if (RETURN_ERROR (Status)) {
|
||||
raise ();
|
||||
return -1;
|
||||
}
|
||||
} else if (strcmp (argv[1], "PeXip") == 0) {
|
||||
if (argc < 5) {
|
||||
fprintf (stderr, "ImageTool: Command arguments are missing\n");
|
||||
fprintf (stderr, " Usage: ImageTool PeXip InputFile OutputFile ModuleType\n");
|
||||
raise ();
|
||||
return -1;
|
||||
}
|
||||
|
||||
Status = PeXip (argv[2], argv[3], argv[4]);
|
||||
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;
|
||||
}
|
||||
} else if (strcmp (argv[1], "PeToUe") == 0) {
|
||||
if (argc < 4) {
|
||||
fprintf (stderr, "ImageTool: Command arguments are missing\n");
|
||||
fprintf (stderr, " Usage: ImageTool PeToUe InputFile OutputFile\n");
|
||||
raise ();
|
||||
return -1;
|
||||
}
|
||||
|
||||
Status = PeToUe (argv[2], argv[3]);
|
||||
if (RETURN_ERROR (Status)) {
|
||||
raise ();
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
200
BaseTools/ImageTool/ImageTool.h
Normal file
200
BaseTools/ImageTool/ImageTool.h
Normal file
@ -0,0 +1,200 @@
|
||||
/** @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 <stdbool.h>
|
||||
#include <errno.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include <IndustryStandard/PeImage2.h>
|
||||
#include <IndustryStandard/UeImage.h>
|
||||
#include <Library/PeCoffLib2.h>
|
||||
#include <Library/UeImageLib.h>
|
||||
#include <Library/BaseLib.h>
|
||||
#include <Library/BaseMemoryLib.h>
|
||||
#include <Library/BaseOverflowLib.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 DEFAULT_PE_ALIGNMENT 0x1000
|
||||
|
||||
#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 PreferredAddress;
|
||||
uint32_t EntryPointAddress;
|
||||
uint16_t Machine;
|
||||
uint16_t Subsystem;
|
||||
bool IsXip;
|
||||
} image_tool_header_info_t;
|
||||
|
||||
typedef enum {
|
||||
ToolImageSectionTypeCode,
|
||||
ToolImageSectionTypeInitialisedData,
|
||||
ToolImageSectionTypeUninitialisedData
|
||||
} image_tool_type_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_type_t Type;
|
||||
} 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
|
||||
);
|
||||
|
||||
void *
|
||||
ToolImageEmitUe (
|
||||
const image_tool_image_info_t *Image,
|
||||
uint32_t *FileSize
|
||||
);
|
||||
|
||||
bool
|
||||
ToolContextConstructPe (
|
||||
OUT image_tool_image_info_t *Image,
|
||||
IN const void *File,
|
||||
IN size_t FileSize,
|
||||
IN const char *ModuleType OPTIONAL
|
||||
);
|
||||
|
||||
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 char *ElfName,
|
||||
IN const char *ModuleType
|
||||
);
|
||||
|
||||
VOID
|
||||
SetHiiResourceHeader (
|
||||
IN OUT UINT8 *Hii,
|
||||
IN UINT32 Offset
|
||||
);
|
||||
|
||||
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
|
98
BaseTools/ImageTool/Makefile
Normal file
98
BaseTools/ImageTool/Makefile
Normal file
@ -0,0 +1,98 @@
|
||||
## @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
|
||||
UE = $(UDK_PATH)\MdePkg\Library\BaseUeImageLib
|
||||
UA = $(UDK_PATH)\MdePkg\Library\BaseUefiImageExtraActionLibNull
|
||||
|
||||
OBJECTS = ImageTool.obj Image.obj PeEmit.obj PeScan.obj UeEmit.obj ElfScan.obj BinEmit.obj
|
||||
OBJECTS = $(OBJECTS) {$(OV)}BaseAlignment.obj BaseBitOverflow.obj {$(UE)}UeImageLib.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
|
||||
USER = $(OC_USER)\User\Library
|
||||
OBJECTS = $(OBJECTS) {$(BASE)}SafeString.obj String.obj SwapBytes16.obj SwapBytes32.obj CpuDeadLoop.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
|
||||
|
||||
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) /FI Pcds.h $< -Fo$@
|
||||
@move $@ $(OUT_DIR)\
|
||||
|
||||
{$(UE)}.c.obj :
|
||||
$(CC) -c $(CFLAGS) $(INC) /FI Pcds.h $< -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)\
|
||||
|
||||
{$(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)\
|
11
BaseTools/ImageTool/Pcds.h
Normal file
11
BaseTools/ImageTool/Pcds.h
Normal file
@ -0,0 +1,11 @@
|
||||
/** @file
|
||||
Copyright (c) 2021, Marvin Häuser. All rights reserved.
|
||||
SPDX-License-Identifier: BSD-3-Clause
|
||||
**/
|
||||
|
||||
#define _PCD_GET_MODE_BOOL_PcdImageLoaderProhibitTe TRUE
|
||||
#define _PCD_GET_MODE_32_PcdImageLoaderAlignmentPolicy 0xFFFFFFFFU
|
||||
#define _PCD_GET_MODE_BOOL_PcdImageLoaderWXorX TRUE
|
||||
#define _PCD_GET_MODE_32_PcdImageLoaderRelocTypePolicy 0x00
|
||||
#define _PCD_GET_MODE_BOOL_PcdImageLoaderDebugSupport TRUE
|
||||
#define _PCD_GET_MODE_BOOL_PcdImageLoaderAllowMisalignedOffset FALSE
|
985
BaseTools/ImageTool/PeEmit.c
Normal file
985
BaseTools/ImageTool/PeEmit.c
Normal file
@ -0,0 +1,985 @@
|
||||
/** @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 HiiTableSize;
|
||||
uint32_t DebugTableSize;
|
||||
uint16_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
|
||||
bool
|
||||
EmitPeGetHiiSectionSize (
|
||||
const image_tool_pe_emit_context_t *Context,
|
||||
uint32_t *HiiSize
|
||||
)
|
||||
{
|
||||
assert (Context != NULL);
|
||||
assert (HiiSize != NULL);
|
||||
|
||||
return !BaseOverflowAlignUpU32 (
|
||||
Context->Image->HiiInfo.DataSize,
|
||||
Context->FileAlignment,
|
||||
HiiSize
|
||||
);
|
||||
}
|
||||
|
||||
static
|
||||
bool
|
||||
EmitPeGetDebugSectionSize (
|
||||
const image_tool_image_info_t *Image,
|
||||
uint32_t *DebugSize
|
||||
)
|
||||
{
|
||||
assert (Image != NULL);
|
||||
assert (DebugSize != NULL);
|
||||
|
||||
*DebugSize = 0;
|
||||
|
||||
if (Image->DebugInfo.SymbolsPath != NULL) {
|
||||
return !BaseOverflowAlignUpU32 (
|
||||
sizeof (DebugData) + Image->DebugInfo.SymbolsPathLen,
|
||||
Image->SegmentInfo.SegmentAlignment,
|
||||
DebugSize
|
||||
);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
Result = EmitPeGetDebugSectionSize (Image, &Context->DebugTableSize);
|
||||
if (!Result) {
|
||||
raise ();
|
||||
return false;
|
||||
}
|
||||
|
||||
Result = EmitPeGetHiiSectionSize (Context, &Context->HiiTableSize);
|
||||
if (!Result) {
|
||||
raise ();
|
||||
return false;
|
||||
}
|
||||
|
||||
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->HiiTableSize,
|
||||
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
|
||||
)
|
||||
{
|
||||
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 = ALIGN_VALUE (Context->HdrInfo.SizeOfHeaders, Context->FileAlignment);
|
||||
Sections = (void *) *Buffer;
|
||||
|
||||
assert (SectionHeadersSize <= *BufferSize);
|
||||
|
||||
for (Index = 0; Index < Image->SegmentInfo.NumSegments; ++Index) {
|
||||
switch (Image->SegmentInfo.Segments[Index].Type) {
|
||||
case ToolImageSectionTypeCode:
|
||||
Sections[Index].Characteristics = EFI_IMAGE_SCN_CNT_CODE;
|
||||
break;
|
||||
case ToolImageSectionTypeInitialisedData:
|
||||
Sections[Index].Characteristics = EFI_IMAGE_SCN_CNT_INITIALIZED_DATA;
|
||||
break;
|
||||
case ToolImageSectionTypeUninitialisedData:
|
||||
Sections[Index].Characteristics = EFI_IMAGE_SCN_CNT_UNINITIALIZED_DATA;
|
||||
break;
|
||||
default:
|
||||
assert (false);
|
||||
break;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
Sections[Index].PointerToRawData = SectionOffset;
|
||||
Sections[Index].VirtualAddress = SectionOffset;
|
||||
Sections[Index].SizeOfRawData = ALIGN_VALUE (Image->SegmentInfo.Segments[Index].DataSize, Context->FileAlignment);
|
||||
Sections[Index].VirtualSize = Sections[Index].SizeOfRawData;
|
||||
|
||||
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 SectionHeadersSize;
|
||||
EFI_IMAGE_SECTION_HEADER *Section;
|
||||
|
||||
assert (Context != NULL);
|
||||
assert (Buffer != NULL);
|
||||
assert (BufferSize != NULL);
|
||||
|
||||
SectionHeadersSize = 0;
|
||||
|
||||
if (Context->HiiTableSize > 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 = Context->HiiTableSize;
|
||||
Section->VirtualSize = Context->HiiTableSize;
|
||||
Section->Characteristics = EFI_IMAGE_SCN_CNT_INITIALIZED_DATA | EFI_IMAGE_SCN_MEM_READ;
|
||||
Section->PointerToRawData = ALIGN_VALUE (Context->HdrInfo.SizeOfHeaders, Context->FileAlignment) + Context->SectionsSize;
|
||||
Section->VirtualAddress = Section->PointerToRawData;
|
||||
|
||||
Context->PeHdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE].Size = Context->HiiTableSize;
|
||||
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 = ALIGN_VALUE (Context->RelocTableSize, Context->FileAlignment);
|
||||
Section->Characteristics = EFI_IMAGE_SCN_CNT_INITIALIZED_DATA
|
||||
| EFI_IMAGE_SCN_MEM_DISCARDABLE | EFI_IMAGE_SCN_MEM_READ;
|
||||
Section->PointerToRawData = ALIGN_VALUE (Context->HdrInfo.SizeOfHeaders, Context->FileAlignment)
|
||||
+ Context->SectionsSize + Context->HiiTableSize;
|
||||
Section->VirtualAddress = Section->PointerToRawData;
|
||||
|
||||
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 = Context->DebugTableSize;
|
||||
Section->VirtualSize = Context->DebugTableSize;
|
||||
Section->Characteristics = EFI_IMAGE_SCN_CNT_INITIALIZED_DATA | EFI_IMAGE_SCN_MEM_READ;
|
||||
Section->PointerToRawData = Context->UnsignedFileSize - Context->DebugTableSize;
|
||||
Section->VirtualAddress = Section->PointerToRawData;
|
||||
|
||||
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->PointerToRawData;
|
||||
|
||||
*BufferSize -= sizeof (EFI_IMAGE_SECTION_HEADER);
|
||||
*Buffer += sizeof (EFI_IMAGE_SECTION_HEADER);
|
||||
SectionHeadersSize += sizeof (EFI_IMAGE_SECTION_HEADER);
|
||||
}
|
||||
|
||||
assert (Context->HdrInfo.ExtraSectionHeadersSize == SectionHeadersSize);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static
|
||||
bool
|
||||
ToolImageEmitPeHeaders (
|
||||
image_tool_pe_emit_context_t *Context,
|
||||
uint8_t **Buffer,
|
||||
uint32_t *BufferSize
|
||||
)
|
||||
{
|
||||
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 = Context->HdrInfo.SizeOfHeaders;
|
||||
PePlusHdr->ImageBase = (UINTN)Image->HeaderInfo.PreferredAddress;
|
||||
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);
|
||||
if (!Result) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Result = ToolImageEmitPeExtraSectionHeaders (Context, Buffer, BufferSize);
|
||||
if (!Result) {
|
||||
return false;
|
||||
}
|
||||
|
||||
HeaderPadding = ALIGN_VALUE_ADDEND(
|
||||
Context->HdrInfo.SizeOfHeaders,
|
||||
Context->FileAlignment
|
||||
);
|
||||
|
||||
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];
|
||||
|
||||
if (FirstCode && (Segment->Type == ToolImageSectionTypeCode)) {
|
||||
Context->PeHdr->BaseOfCode = (UINT32)Segment->ImageAddress;
|
||||
FirstCode = false;
|
||||
}
|
||||
|
||||
#if defined(EFI_TARGET32)
|
||||
if (FirstData && (Segment->Type == ToolImageSectionTypeInitialisedData)) {
|
||||
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;
|
||||
|
||||
switch (Segment->Type) {
|
||||
case ToolImageSectionTypeCode:
|
||||
Context->PeHdr->BaseOfCode = MIN(Context->PeHdr->BaseOfCode, (UINT32)Segment->ImageAddress);
|
||||
Context->PeHdr->SizeOfCode += Segment->ImageSize;
|
||||
break;
|
||||
case ToolImageSectionTypeInitialisedData:
|
||||
#if defined(EFI_TARGET32)
|
||||
Context->PeHdr->BaseOfData = MIN(Context->PeHdr->BaseOfData, (UINT32)Segment->ImageAddress);
|
||||
#endif
|
||||
Context->PeHdr->SizeOfInitializedData += Segment->ImageSize;
|
||||
break;
|
||||
case ToolImageSectionTypeUninitialisedData:
|
||||
Context->PeHdr->SizeOfUninitializedData += Segment->ImageSize;
|
||||
break;
|
||||
default:
|
||||
assert (false);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
assert (Image->DebugInfo.SymbolsPathLen <= 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;
|
||||
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;
|
||||
snprintf (Data->Name, Image->DebugInfo.SymbolsPathLen, "%s", Image->DebugInfo.SymbolsPath);
|
||||
|
||||
*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 (Context->HiiTableSize == 0) {
|
||||
return true;
|
||||
}
|
||||
|
||||
assert (Image->HiiInfo.DataSize <= Context->HiiTableSize);
|
||||
assert (Context->HiiTableSize <= *BufferSize);
|
||||
|
||||
memmove (*Buffer, Image->HiiInfo.Data, Image->HiiInfo.DataSize);
|
||||
|
||||
*BufferSize -= Context->HiiTableSize;
|
||||
*Buffer += Context->HiiTableSize;
|
||||
|
||||
HiiTablePadding = ALIGN_VALUE_ADDEND(
|
||||
Context->HiiTableSize,
|
||||
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));
|
||||
|
||||
Context.Image = Image;
|
||||
Context.FileAlignment = (uint16_t)Image->SegmentInfo.SegmentAlignment;
|
||||
|
||||
Result = EmitPeGetHeaderSizes (Image, &Context.HdrInfo);
|
||||
if (!Result) {
|
||||
raise ();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Overflow = BaseOverflowAlignUpU32 (
|
||||
Context.HdrInfo.SizeOfHeaders,
|
||||
Context.FileAlignment,
|
||||
&AlignedHeaderSize
|
||||
);
|
||||
if (Overflow) {
|
||||
raise ();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
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);
|
||||
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->SizeOfHeaders = AlignedHeaderSize;
|
||||
Context.PeHdr->SizeOfImage = Context.UnsignedFileSize;
|
||||
|
||||
Context.PeHdr->SizeOfInitializedData += Context.ExtraSectionsSize;
|
||||
|
||||
*FileSize = Context.UnsignedFileSize;
|
||||
|
||||
return FileBuffer;
|
||||
}
|
597
BaseTools/ImageTool/PeScan.c
Normal file
597
BaseTools/ImageTool/PeScan.c
Normal file
@ -0,0 +1,597 @@
|
||||
/** @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,
|
||||
IN const char *ModuleType OPTIONAL
|
||||
)
|
||||
{
|
||||
assert (HeaderInfo != NULL);
|
||||
assert (Context != NULL);
|
||||
|
||||
HeaderInfo->PreferredAddress = (uint64_t)PeCoffGetImageBase (Context);
|
||||
HeaderInfo->EntryPointAddress = PeCoffGetAddressOfEntryPoint (Context);
|
||||
// FIXME:
|
||||
HeaderInfo->Machine = PeCoffGetMachine (Context);
|
||||
HeaderInfo->IsXip = true;
|
||||
|
||||
if (ModuleType == NULL) {
|
||||
HeaderInfo->Subsystem = PeCoffGetSubsystem (Context);
|
||||
return true;
|
||||
}
|
||||
|
||||
if ((strcmp (ModuleType, "BASE") == 0)
|
||||
|| (strcmp (ModuleType, "SEC") == 0)
|
||||
|| (strcmp (ModuleType, "SECURITY_CORE") == 0)
|
||||
|| (strcmp (ModuleType, "PEI_CORE") == 0)
|
||||
|| (strcmp (ModuleType, "PEIM") == 0)
|
||||
|| (strcmp (ModuleType, "COMBINED_PEIM_DRIVER") == 0)
|
||||
|| (strcmp (ModuleType, "PIC_PEIM") == 0)
|
||||
|| (strcmp (ModuleType, "RELOCATABLE_PEIM") == 0)
|
||||
|| (strcmp (ModuleType, "DXE_CORE") == 0)
|
||||
|| (strcmp (ModuleType, "BS_DRIVER") == 0)
|
||||
|| (strcmp (ModuleType, "DXE_DRIVER") == 0)
|
||||
|| (strcmp (ModuleType, "DXE_SMM_DRIVER") == 0)
|
||||
|| (strcmp (ModuleType, "UEFI_DRIVER") == 0)
|
||||
|| (strcmp (ModuleType, "SMM_CORE") == 0)
|
||||
|| (strcmp (ModuleType, "MM_STANDALONE") == 0)
|
||||
|| (strcmp (ModuleType, "MM_CORE_STANDALONE") == 0)) {
|
||||
HeaderInfo->Subsystem = EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER;
|
||||
} else if ((strcmp (ModuleType, "UEFI_APPLICATION") == 0)
|
||||
|| (strcmp (ModuleType, "APPLICATION") == 0)) {
|
||||
HeaderInfo->Subsystem = EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION;
|
||||
} else if ((strcmp (ModuleType, "DXE_RUNTIME_DRIVER") == 0)
|
||||
|| (strcmp (ModuleType, "RT_DRIVER") == 0)) {
|
||||
HeaderInfo->Subsystem = EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER;
|
||||
} else if ((strcmp (ModuleType, "DXE_SAL_DRIVER") == 0)
|
||||
|| (strcmp (ModuleType, "SAL_RT_DRIVER") == 0)) {
|
||||
HeaderInfo->Subsystem = EFI_IMAGE_SUBSYSTEM_SAL_RUNTIME_DRIVER;
|
||||
} else {
|
||||
fprintf (stderr, "ImageTool: Unknown EFI_FILETYPE = %s\n", ModuleType);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static
|
||||
bool
|
||||
ScanPeGetRelocInfo (
|
||||
OUT image_tool_reloc_info_t *RelocInfo,
|
||||
IN const EFI_IMAGE_SECTION_HEADER *Section,
|
||||
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 *FileBuffer;
|
||||
UINT16 RelocType;
|
||||
UINT16 RelocOffset;
|
||||
|
||||
assert (Context != NULL);
|
||||
assert (Section != NULL);
|
||||
|
||||
RelocInfo->RelocsStripped = false;
|
||||
|
||||
// FIXME: PE/COFF context access
|
||||
RelocBlockRva = Section->PointerToRawData;
|
||||
RelocDirSize = Section->VirtualSize;
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
FileBuffer = (const char *)Context->FileBuffer;
|
||||
while (RelocBlockRva <= RelocBlockRvaMax) {
|
||||
RelocBlock = (const EFI_IMAGE_BASE_RELOCATION_BLOCK *)(const void *)(FileBuffer + 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,
|
||||
OUT image_tool_reloc_info_t *RelocInfo,
|
||||
OUT image_tool_debug_info_t *DebugInfo,
|
||||
IN PE_COFF_LOADER_IMAGE_CONTEXT *Context
|
||||
)
|
||||
{
|
||||
const EFI_IMAGE_SECTION_HEADER *Section;
|
||||
uint32_t NumSections;
|
||||
image_tool_segment_t *ImageSegment;
|
||||
const char *FileBuffer;
|
||||
uint32_t Index;
|
||||
UINT32 Size;
|
||||
|
||||
const EFI_IMAGE_NT_HEADERS *PeHdr;
|
||||
const EFI_IMAGE_DATA_DIRECTORY *DebugDir;
|
||||
UINT32 DebugDirTop;
|
||||
bool Overflow;
|
||||
UINT32 IndexD;
|
||||
const EFI_IMAGE_DEBUG_DIRECTORY_ENTRY *DebugEntry;
|
||||
const char *CodeView;
|
||||
UINT32 DebugTop;
|
||||
UINT32 PdbOffset;
|
||||
|
||||
assert (SegmentInfo != NULL);
|
||||
assert (HiiInfo != NULL);
|
||||
assert (RelocInfo != NULL);
|
||||
assert (DebugInfo != NULL);
|
||||
assert (Context != NULL);
|
||||
|
||||
DebugDir = 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;
|
||||
}
|
||||
|
||||
FileBuffer = (const char *)Context->FileBuffer;
|
||||
|
||||
PeHdr = (const EFI_IMAGE_NT_HEADERS *)(const void *)(FileBuffer + Context->ExeHdrOffset);
|
||||
if (PeHdr->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_DEBUG) {
|
||||
DebugDir = PeHdr->DataDirectory + EFI_IMAGE_DIRECTORY_ENTRY_DEBUG;
|
||||
Overflow = BaseOverflowAddU32 (DebugDir->VirtualAddress, DebugDir->Size, &DebugDirTop);
|
||||
if (Overflow || (DebugDirTop > Context->SizeOfImage)) {
|
||||
fprintf (stderr, "ImageTool: Corrupted DEBUG directory entry\n");
|
||||
DebugDir = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
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 = MAX (Section->VirtualSize, Section->SizeOfRawData);
|
||||
Size = ALIGN_VALUE (Size, 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, FileBuffer + Section->PointerToRawData, Section->SizeOfRawData);
|
||||
|
||||
ImageSegment->DataSize = Size;
|
||||
ImageSegment->ImageAddress = Section->VirtualAddress;
|
||||
ImageSegment->ImageSize = Size;
|
||||
|
||||
if ((Section->Characteristics & EFI_IMAGE_SCN_MEM_READ) != 0) {
|
||||
ImageSegment->Read = true;
|
||||
}
|
||||
|
||||
if ((Section->Characteristics & EFI_IMAGE_SCN_MEM_WRITE) != 0) {
|
||||
ImageSegment->Write = true;
|
||||
}
|
||||
|
||||
if ((Section->Characteristics & EFI_IMAGE_SCN_MEM_EXECUTE) != 0) {
|
||||
ImageSegment->Execute = true;
|
||||
}
|
||||
|
||||
if (ImageSegment->Execute) {
|
||||
ImageSegment->Type = ToolImageSectionTypeCode;
|
||||
} else {
|
||||
ImageSegment->Type = ToolImageSectionTypeInitialisedData;
|
||||
}
|
||||
|
||||
++SegmentInfo->NumSegments;
|
||||
++ImageSegment;
|
||||
} else if (memcmp (Section->Name, PE_COFF_SECT_NAME_RESRC, sizeof (Section->Name)) == 0) {
|
||||
Size = MAX (Section->VirtualSize, Section->SizeOfRawData);
|
||||
Size = ALIGN_VALUE (Size, 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, FileBuffer + Section->PointerToRawData, Section->SizeOfRawData);
|
||||
|
||||
HiiInfo->DataSize = Size;
|
||||
} else if (memcmp (Section->Name, PE_COFF_SECT_NAME_RELOC, sizeof (Section->Name)) == 0) {
|
||||
if (!ScanPeGetRelocInfo (RelocInfo, Section, Context)) {
|
||||
fprintf (stderr, "ImageTool: Could not retrieve reloc info\n");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if ((DebugDir != NULL)
|
||||
&& (DebugDir->VirtualAddress >= Section->VirtualAddress)
|
||||
&& (DebugDirTop <= Section->VirtualAddress + Section->VirtualSize)) {
|
||||
DebugEntry = (const EFI_IMAGE_DEBUG_DIRECTORY_ENTRY *)(const void *)(
|
||||
FileBuffer + Section->PointerToRawData + (DebugDir->VirtualAddress - Section->VirtualAddress));
|
||||
|
||||
for (IndexD = 0; (IndexD + sizeof (*DebugEntry)) <= DebugDir->Size; IndexD += sizeof (*DebugEntry), ++DebugEntry) {
|
||||
if (DebugEntry->Type == EFI_IMAGE_DEBUG_TYPE_CODEVIEW) {
|
||||
Overflow = BaseOverflowAddU32 (DebugEntry->FileOffset, DebugEntry->SizeOfData, &DebugTop);
|
||||
if (Overflow || (DebugTop > Context->FileSize)) {
|
||||
fprintf (stderr, "ImageTool: Corrupted DEBUG information\n");
|
||||
continue;
|
||||
}
|
||||
|
||||
CodeView = FileBuffer + DebugEntry->FileOffset;
|
||||
switch (*(const UINT32 *)(const void *) CodeView) {
|
||||
case CODEVIEW_SIGNATURE_NB10:
|
||||
PdbOffset = sizeof (EFI_IMAGE_DEBUG_CODEVIEW_NB10_ENTRY);
|
||||
break;
|
||||
case CODEVIEW_SIGNATURE_RSDS:
|
||||
PdbOffset = sizeof (EFI_IMAGE_DEBUG_CODEVIEW_RSDS_ENTRY);
|
||||
break;
|
||||
case CODEVIEW_SIGNATURE_MTOC:
|
||||
PdbOffset = sizeof (EFI_IMAGE_DEBUG_CODEVIEW_MTOC_ENTRY);
|
||||
break;
|
||||
default:
|
||||
fprintf (stderr, "ImageTool: Unknown CODEVIEW_SIGNATURE\n");
|
||||
continue;
|
||||
}
|
||||
|
||||
Overflow = BaseOverflowSubU32 (DebugEntry->SizeOfData, PdbOffset, &DebugInfo->SymbolsPathLen);
|
||||
if (Overflow || (DebugInfo->SymbolsPathLen == 0)) {
|
||||
fprintf (stderr, "ImageTool: Corrupted DEBUG string\n");
|
||||
continue;
|
||||
}
|
||||
|
||||
DebugInfo->SymbolsPath = calloc (1, DebugInfo->SymbolsPathLen);
|
||||
if (DebugInfo->SymbolsPath == NULL) {
|
||||
fprintf (stderr, "ImageTool: Could not allocate memory for SymbolsPath\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
memmove (DebugInfo->SymbolsPath, CodeView + PdbOffset, DebugInfo->SymbolsPathLen - 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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 = calloc (1, 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;
|
||||
}
|
||||
|
||||
static
|
||||
bool
|
||||
FixAddresses (
|
||||
IN OUT image_tool_image_info_t *Image
|
||||
)
|
||||
{
|
||||
UINT64 SizeOfHeaders;
|
||||
UINT64 Delta;
|
||||
UINT32 Index;
|
||||
UINT32 IndexS;
|
||||
image_tool_segment_t *Segment;
|
||||
image_tool_reloc_t *Reloc;
|
||||
UINT8 *Fixup;
|
||||
UINT32 Fixup32;
|
||||
UINT64 Fixup64;
|
||||
|
||||
assert (Image != NULL);
|
||||
|
||||
SizeOfHeaders = sizeof (EFI_IMAGE_DOS_HEADER) + sizeof (EFI_IMAGE_NT_HEADERS) +
|
||||
EFI_IMAGE_NUMBER_OF_DIRECTORY_ENTRIES * sizeof (EFI_IMAGE_DATA_DIRECTORY) +
|
||||
Image->SegmentInfo.NumSegments * sizeof (EFI_IMAGE_SECTION_HEADER);
|
||||
|
||||
if (Image->RelocInfo.Relocs != NULL) {
|
||||
SizeOfHeaders += sizeof (EFI_IMAGE_SECTION_HEADER);
|
||||
}
|
||||
|
||||
if (Image->DebugInfo.SymbolsPath != NULL) {
|
||||
SizeOfHeaders += sizeof (EFI_IMAGE_SECTION_HEADER);
|
||||
}
|
||||
|
||||
if (Image->HiiInfo.Data != NULL) {
|
||||
SizeOfHeaders += sizeof (EFI_IMAGE_SECTION_HEADER);
|
||||
}
|
||||
|
||||
SizeOfHeaders = ALIGN_VALUE (SizeOfHeaders, Image->SegmentInfo.SegmentAlignment);
|
||||
if (SizeOfHeaders == Image->SegmentInfo.Segments[0].ImageAddress) {
|
||||
return true;
|
||||
}
|
||||
|
||||
Delta = Image->SegmentInfo.Segments[0].ImageAddress - SizeOfHeaders;
|
||||
|
||||
Image->HeaderInfo.EntryPointAddress -= (UINT32)Delta;
|
||||
|
||||
for (Index = 0; Index < Image->SegmentInfo.NumSegments; ++Index) {
|
||||
Image->SegmentInfo.Segments[Index].ImageAddress -= Delta;
|
||||
}
|
||||
|
||||
if (Image->RelocInfo.Relocs != NULL) {
|
||||
Segment = Image->SegmentInfo.Segments;
|
||||
Reloc = Image->RelocInfo.Relocs;
|
||||
|
||||
for (Index = 0; Index < Image->RelocInfo.NumRelocs; ++Index) {
|
||||
Reloc[Index].Target -= (UINT32)Delta;
|
||||
|
||||
for (IndexS = 0; IndexS < Image->SegmentInfo.NumSegments; ++IndexS) {
|
||||
if ((Reloc[Index].Target >= Segment[IndexS].ImageAddress)
|
||||
&& ((Reloc[Index].Target - Segment[IndexS].ImageAddress) < Segment[IndexS].ImageSize)) {
|
||||
Fixup = Segment[IndexS].Data + (Reloc[Index].Target - Segment[IndexS].ImageAddress);
|
||||
switch (Reloc[Index].Type) {
|
||||
case EFI_IMAGE_REL_BASED_HIGHLOW:
|
||||
Fixup32 = ReadUnaligned32 ((CONST VOID *) Fixup);
|
||||
Fixup32 -= (UINT32)Delta;
|
||||
WriteUnaligned32 ((VOID *) Fixup, Fixup32);
|
||||
break;
|
||||
case EFI_IMAGE_REL_BASED_DIR64:
|
||||
Fixup64 = ReadUnaligned64 ((CONST VOID *) Fixup);
|
||||
Fixup64 -= Delta;
|
||||
WriteUnaligned64 ((VOID *) Fixup, Fixup64);
|
||||
break;
|
||||
default:
|
||||
fprintf (stderr, "ImageTool: Unknown relocation type %u\n", Reloc[Index].Type);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (Image->HiiInfo.Data != NULL) {
|
||||
SetHiiResourceHeader (Image->HiiInfo.Data, (UINT32)(0ULL - Delta));
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
ToolContextConstructPe (
|
||||
OUT image_tool_image_info_t *Image,
|
||||
IN const void *File,
|
||||
IN size_t FileSize,
|
||||
IN const char *ModuleType OPTIONAL
|
||||
)
|
||||
{
|
||||
PE_COFF_LOADER_IMAGE_CONTEXT Context;
|
||||
RETURN_STATUS Status;
|
||||
bool Result;
|
||||
|
||||
assert (Image != NULL);
|
||||
assert (File != NULL || FileSize == 0);
|
||||
|
||||
if (FileSize > MAX_UINT32) {
|
||||
fprintf (stderr, "ImageTool: FileSize is too huge\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
Status = PeCoffInitializeContext (&Context, File, (UINT32)FileSize);
|
||||
if (RETURN_ERROR (Status)) {
|
||||
fprintf (stderr, "ImageTool: Could not initialise Context\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
memset (Image, 0, sizeof (*Image));
|
||||
|
||||
Result = ScanPeGetHeaderInfo (&Image->HeaderInfo, &Context, ModuleType);
|
||||
if (!Result) {
|
||||
fprintf (stderr, "ImageTool: Could not retrieve header info\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
Result = ScanPeGetSegmentInfo (&Image->SegmentInfo, &Image->HiiInfo, &Image->RelocInfo, &Image->DebugInfo, &Context);
|
||||
if (!Result) {
|
||||
fprintf (stderr, "ImageTool: Could not retrieve segment info\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
Result = FixAddresses (Image);
|
||||
|
||||
return Result;
|
||||
}
|
892
BaseTools/ImageTool/UeEmit.c
Normal file
892
BaseTools/ImageTool/UeEmit.c
Normal file
@ -0,0 +1,892 @@
|
||||
/** @file
|
||||
Copyright (c) 2021, Marvin Häuser. All rights reserved.
|
||||
SPDX-License-Identifier: BSD-3-Clause
|
||||
**/
|
||||
|
||||
#include "ImageTool.h"
|
||||
|
||||
// FIXME: NumSegments <= MAX_UINT8
|
||||
|
||||
typedef struct {
|
||||
uint8_t NumSections;
|
||||
uint32_t HeaderSize;
|
||||
uint32_t SegmentHeadersSize;
|
||||
uint32_t SectionHeadersSize;
|
||||
} image_tool_emit_ue_hdr_info_t;
|
||||
|
||||
typedef struct {
|
||||
const image_tool_image_info_t *Image;
|
||||
image_tool_emit_ue_hdr_info_t HdrInfo;
|
||||
uint32_t SegmentsSize;
|
||||
uint8_t SegmentsEndPadding;
|
||||
uint32_t SectionsSize;
|
||||
uint32_t UnsignedFileSize;
|
||||
uint32_t RelocTableSize;
|
||||
uint32_t HiiTableSize;
|
||||
uint32_t DebugTableSize;
|
||||
} image_tool_ue_emit_context_t;
|
||||
|
||||
static
|
||||
bool
|
||||
EmitUeGetHeaderSizes (
|
||||
const image_tool_image_info_t *Image,
|
||||
image_tool_emit_ue_hdr_info_t *HdrInfo
|
||||
)
|
||||
{
|
||||
assert (Image != NULL);
|
||||
assert (HdrInfo != NULL);
|
||||
|
||||
if (Image->RelocInfo.NumRelocs > 0) {
|
||||
++HdrInfo->NumSections;
|
||||
}
|
||||
|
||||
if (Image->HiiInfo.DataSize > 0) {
|
||||
++HdrInfo->NumSections;
|
||||
}
|
||||
//
|
||||
// A debug section can always be generated; make conditional based on tool arg.
|
||||
//
|
||||
++HdrInfo->NumSections;
|
||||
|
||||
HdrInfo->SegmentHeadersSize = (uint32_t)Image->SegmentInfo.NumSegments * sizeof (UE_SEGMENT);
|
||||
HdrInfo->SectionHeadersSize = (uint32_t)HdrInfo->NumSections * sizeof (UE_SECTION);
|
||||
|
||||
HdrInfo->HeaderSize = sizeof (UE_HEADER)
|
||||
+ HdrInfo->SegmentHeadersSize
|
||||
+ HdrInfo->SectionHeadersSize;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static
|
||||
bool
|
||||
EmitUeGetSegmentsSize (
|
||||
const image_tool_image_info_t *Image,
|
||||
uint32_t *SegmentsSize
|
||||
)
|
||||
{
|
||||
uint8_t Index;
|
||||
|
||||
assert (Image != NULL);
|
||||
assert (SegmentsSize != NULL);
|
||||
|
||||
*SegmentsSize = 0;
|
||||
for (Index = 0; Index < Image->SegmentInfo.NumSegments; ++Index) {
|
||||
*SegmentsSize += Image->SegmentInfo.Segments[Index].DataSize;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static
|
||||
bool
|
||||
EmitUeGetRelocSectionSize (
|
||||
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 = (uint32_t)PAGE (Image->RelocInfo.Relocs[0].Target);
|
||||
BlockSize = sizeof (UE_RELOCATION_BLOCK);
|
||||
|
||||
for (Index = 0; Index < Image->RelocInfo.NumRelocs; ++Index) {
|
||||
RelocAddress = PAGE (Image->RelocInfo.Relocs[Index].Target);
|
||||
if (RelocAddress != BlockAddress) {
|
||||
BlockSize = ALIGN_VALUE (BlockSize, UE_RELOCATION_BLOCK_ALIGNMENT);
|
||||
|
||||
RelocTableSize += BlockSize;
|
||||
|
||||
BlockAddress = RelocAddress;
|
||||
BlockSize = sizeof (UE_RELOCATION_BLOCK);
|
||||
}
|
||||
|
||||
BlockSize += sizeof (UINT16);
|
||||
}
|
||||
|
||||
RelocTableSize += BlockSize;
|
||||
|
||||
*RelocsSize = RelocTableSize;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static
|
||||
bool
|
||||
EmitUeGetHiiSectionSize (
|
||||
const image_tool_image_info_t *Image,
|
||||
uint32_t *HiiSize
|
||||
)
|
||||
{
|
||||
assert (Image != NULL);
|
||||
assert (HiiSize != NULL);
|
||||
|
||||
*HiiSize = Image->HiiInfo.DataSize;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static
|
||||
bool
|
||||
EmitUeGetDebugSectionSize (
|
||||
const image_tool_image_info_t *Image,
|
||||
uint32_t *DebugSize
|
||||
)
|
||||
{
|
||||
assert (Image != NULL);
|
||||
assert (DebugSize != NULL);
|
||||
|
||||
static_assert (
|
||||
MAX_UINT8 <= (MAX_UINT32 - MAX_UINT8 - sizeof (UE_DEBUG_TABLE)) / sizeof (UE_SEGMENT_NAME),
|
||||
"The following arithmetics may overflow."
|
||||
);
|
||||
|
||||
*DebugSize = sizeof (UE_DEBUG_TABLE) + Image->SegmentInfo.NumSegments * sizeof (UE_SEGMENT_NAME);
|
||||
|
||||
if (Image->DebugInfo.SymbolsPath != NULL) {
|
||||
assert (Image->DebugInfo.SymbolsPathLen <= MAX_UINT8);
|
||||
*DebugSize += Image->DebugInfo.SymbolsPathLen;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static
|
||||
bool
|
||||
EmitUeGetSectionsSize (
|
||||
image_tool_ue_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 = EmitUeGetRelocSectionSize (Image, &Context->RelocTableSize);
|
||||
if (!Result) {
|
||||
raise ();
|
||||
return false;
|
||||
}
|
||||
|
||||
Result = EmitUeGetDebugSectionSize (Image, &Context->DebugTableSize);
|
||||
if (!Result) {
|
||||
raise ();
|
||||
return false;
|
||||
}
|
||||
|
||||
Result = EmitUeGetHiiSectionSize (Image, &Context->HiiTableSize);
|
||||
if (!Result) {
|
||||
raise ();
|
||||
return false;
|
||||
}
|
||||
|
||||
Overflow = BaseOverflowAlignUpU32 (
|
||||
Context->RelocTableSize,
|
||||
UE_SECTION_ALIGNMENT,
|
||||
&AlignedRelocTableSize
|
||||
);
|
||||
if (Overflow) {
|
||||
raise ();
|
||||
return false;
|
||||
}
|
||||
|
||||
Overflow = BaseOverflowAlignUpU32 (
|
||||
Context->DebugTableSize,
|
||||
UE_SECTION_ALIGNMENT,
|
||||
&AlignedDebugTableSize
|
||||
);
|
||||
if (Overflow) {
|
||||
raise ();
|
||||
return false;
|
||||
}
|
||||
|
||||
Overflow = BaseOverflowAlignUpU32 (
|
||||
Context->HiiTableSize,
|
||||
UE_SECTION_ALIGNMENT,
|
||||
&AlignedHiiTableSize
|
||||
);
|
||||
if (Overflow) {
|
||||
raise ();
|
||||
return false;
|
||||
}
|
||||
|
||||
Overflow = BaseOverflowAddU32 (
|
||||
AlignedRelocTableSize,
|
||||
AlignedDebugTableSize,
|
||||
SectionsSize
|
||||
);
|
||||
if (Overflow) {
|
||||
raise ();
|
||||
return false;
|
||||
}
|
||||
|
||||
assert (IS_ALIGNED (*SectionsSize, UE_SECTION_ALIGNMENT));
|
||||
|
||||
Overflow = BaseOverflowAddU32 (
|
||||
*SectionsSize,
|
||||
AlignedHiiTableSize,
|
||||
SectionsSize
|
||||
);
|
||||
if (Overflow) {
|
||||
raise ();
|
||||
return false;
|
||||
}
|
||||
|
||||
assert (IS_ALIGNED (*SectionsSize, UE_SECTION_ALIGNMENT));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static
|
||||
uint8_t
|
||||
AlignmentToExponent (
|
||||
uint64_t Alignment
|
||||
)
|
||||
{
|
||||
uint8_t Index;
|
||||
|
||||
assert (IS_POW2 (Alignment));
|
||||
|
||||
for (Index = 0; Index < 64; ++Index) {
|
||||
if ((Alignment & (1ULL << Index)) == Alignment) {
|
||||
return Index;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static
|
||||
bool
|
||||
ToolImageEmitUeSegmentHeaders (
|
||||
const image_tool_ue_emit_context_t *Context,
|
||||
uint8_t **Buffer,
|
||||
uint32_t *BufferSize
|
||||
)
|
||||
{
|
||||
const image_tool_image_info_t *Image;
|
||||
uint16_t SegmentHeadersSize;
|
||||
UE_SEGMENT *Segments;
|
||||
uint8_t Index;
|
||||
|
||||
assert (Context != NULL);
|
||||
assert (Buffer != NULL);
|
||||
assert (BufferSize != NULL);
|
||||
|
||||
Image = Context->Image;
|
||||
|
||||
SegmentHeadersSize = (uint16_t)(Image->SegmentInfo.NumSegments * sizeof (UE_SEGMENT));
|
||||
assert (SegmentHeadersSize <= *BufferSize);
|
||||
|
||||
Segments = (void *)*Buffer;
|
||||
|
||||
for (Index = 0; Index < Image->SegmentInfo.NumSegments; ++Index) {
|
||||
// FIXME:
|
||||
Image->SegmentInfo.Segments[Index].ImageSize = ALIGN_VALUE (Image->SegmentInfo.Segments[Index].ImageSize, Image->SegmentInfo.SegmentAlignment);
|
||||
|
||||
Segments[Index].ImageInfo = Image->SegmentInfo.Segments[Index].ImageSize;
|
||||
|
||||
if (!Image->SegmentInfo.Segments[Index].Read) {
|
||||
Segments[Index].ImageInfo |= UE_SEGMENT_INFO_RP;
|
||||
}
|
||||
|
||||
if (!Image->SegmentInfo.Segments[Index].Write) {
|
||||
Segments[Index].ImageInfo |= UE_SEGMENT_INFO_RO;
|
||||
}
|
||||
|
||||
if (!Image->SegmentInfo.Segments[Index].Execute) {
|
||||
Segments[Index].ImageInfo |= UE_SEGMENT_INFO_XP;
|
||||
}
|
||||
|
||||
assert (UE_SEGMENT_SIZE (Segments[Index].ImageInfo) == Image->SegmentInfo.Segments[Index].ImageSize);
|
||||
|
||||
Segments[Index].FileSize = Image->SegmentInfo.Segments[Index].DataSize;
|
||||
}
|
||||
|
||||
*BufferSize -= SegmentHeadersSize;
|
||||
*Buffer += SegmentHeadersSize;
|
||||
|
||||
assert (SegmentHeadersSize == Context->HdrInfo.SegmentHeadersSize);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static
|
||||
bool
|
||||
ToolImageEmitUeSectionHeaders (
|
||||
const image_tool_ue_emit_context_t *Context,
|
||||
uint8_t **Buffer,
|
||||
uint32_t *BufferSize
|
||||
)
|
||||
{
|
||||
uint32_t SectionHeadersSize;
|
||||
UE_SECTION *Section;
|
||||
uint32_t AlignedRelocTableSize;
|
||||
uint32_t AlignedDebugTableSize;
|
||||
uint32_t AlignedHiiTableSize;
|
||||
|
||||
assert (Context != NULL);
|
||||
assert (Buffer != NULL);
|
||||
assert (BufferSize != NULL);
|
||||
|
||||
SectionHeadersSize = 0;
|
||||
|
||||
if (Context->RelocTableSize > 0) {
|
||||
assert (sizeof (UE_SECTION) <= *BufferSize);
|
||||
|
||||
Section = (void *)*Buffer;
|
||||
|
||||
AlignedRelocTableSize = ALIGN_VALUE (Context->RelocTableSize, UE_SECTION_ALIGNMENT);
|
||||
Section->FileInfo = AlignedRelocTableSize;
|
||||
Section->FileInfo |= UeSectionIdRelocTable;
|
||||
|
||||
assert (UE_SECTION_ID (Section->FileInfo) == UeSectionIdRelocTable);
|
||||
assert (UE_SECTION_SIZE (Section->FileInfo) == AlignedRelocTableSize);
|
||||
|
||||
*BufferSize -= sizeof (UE_SECTION);
|
||||
*Buffer += sizeof (UE_SECTION);
|
||||
SectionHeadersSize += sizeof (UE_SECTION);
|
||||
}
|
||||
|
||||
if (Context->DebugTableSize > 0) {
|
||||
assert (sizeof (UE_SECTION) <= *BufferSize);
|
||||
|
||||
Section = (void *)*Buffer;
|
||||
|
||||
AlignedDebugTableSize = ALIGN_VALUE (Context->DebugTableSize, UE_SECTION_ALIGNMENT);
|
||||
Section->FileInfo = AlignedDebugTableSize;
|
||||
Section->FileInfo |= UeSectionIdDebugTable;
|
||||
|
||||
assert (UE_SECTION_ID (Section->FileInfo) == UeSectionIdDebugTable);
|
||||
assert (UE_SECTION_SIZE (Section->FileInfo) == AlignedDebugTableSize);
|
||||
|
||||
*BufferSize -= sizeof (UE_SECTION);
|
||||
*Buffer += sizeof (UE_SECTION);
|
||||
SectionHeadersSize += sizeof (UE_SECTION);
|
||||
}
|
||||
|
||||
if (Context->HiiTableSize > 0) {
|
||||
assert (sizeof (UE_SECTION) <= *BufferSize);
|
||||
|
||||
Section = (void *)*Buffer;
|
||||
|
||||
AlignedHiiTableSize = ALIGN_VALUE (Context->HiiTableSize, UE_SECTION_ALIGNMENT);
|
||||
Section->FileInfo = AlignedHiiTableSize;
|
||||
Section->FileInfo |= UeSectionIdHiiTable;
|
||||
|
||||
assert (UE_SECTION_ID (Section->FileInfo) == UeSectionIdHiiTable);
|
||||
assert (UE_SECTION_SIZE (Section->FileInfo) == AlignedHiiTableSize);
|
||||
|
||||
*BufferSize -= sizeof (UE_SECTION);
|
||||
*Buffer += sizeof (UE_SECTION);
|
||||
SectionHeadersSize += sizeof (UE_SECTION);
|
||||
}
|
||||
|
||||
assert (Context->HdrInfo.SectionHeadersSize == SectionHeadersSize);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static
|
||||
bool
|
||||
ToolImageEmitUeHeader (
|
||||
const image_tool_ue_emit_context_t *Context,
|
||||
uint8_t **Buffer,
|
||||
uint32_t *BufferSize
|
||||
)
|
||||
{
|
||||
UE_HEADER *UeHdr;
|
||||
const image_tool_image_info_t *Image;
|
||||
uint8_t AlignmentExponent;
|
||||
bool Result;
|
||||
|
||||
assert (Context != NULL);
|
||||
assert (Buffer != NULL);
|
||||
assert (BufferSize != NULL);
|
||||
|
||||
assert (sizeof(UE_HEADER) <= *BufferSize);
|
||||
|
||||
UeHdr = (void *)*Buffer;
|
||||
|
||||
UeHdr->Signature = UE_HEADER_SIGNATURE;
|
||||
|
||||
Image = Context->Image;
|
||||
|
||||
AlignmentExponent = AlignmentToExponent (Image->SegmentInfo.SegmentAlignment);
|
||||
UeHdr->ImageInfo = AlignmentExponent;
|
||||
|
||||
if (Image->RelocInfo.RelocsStripped) {
|
||||
UeHdr->ImageInfo |= UE_HEADER_FLAG_RELOCS_STRIPPED;
|
||||
}
|
||||
|
||||
assert (UE_HEADER_ALIGNMENT (UeHdr->ImageInfo) == 1U << AlignmentExponent);
|
||||
|
||||
assert (Image->SegmentInfo.NumSegments > 0);
|
||||
UeHdr->LastSegmentIndex = (UINT8)(Image->SegmentInfo.NumSegments - 1);
|
||||
UeHdr->NumSections = Context->HdrInfo.NumSections;
|
||||
UeHdr->Subsystem = (UINT8)Image->HeaderInfo.Subsystem;
|
||||
UeHdr->Machine = (UINT8)Image->HeaderInfo.Machine;
|
||||
UeHdr->PreferredAddress = Image->HeaderInfo.PreferredAddress;
|
||||
UeHdr->EntryPointAddress = Image->HeaderInfo.EntryPointAddress;
|
||||
UeHdr->ImageInfo2 = Context->UnsignedFileSize;
|
||||
assert (UeHdr->ImageInfo2 == UE_HEADER_UNSIGNED_SIZE (UeHdr->ImageInfo2));
|
||||
|
||||
assert (UeHdr->Reserved == 0);
|
||||
|
||||
STATIC_ASSERT (
|
||||
OFFSET_OF (UE_HEADER, Segments) == sizeof (UE_HEADER),
|
||||
"The following code needs to be updated to consider padding."
|
||||
);
|
||||
|
||||
*BufferSize -= sizeof (UE_HEADER);
|
||||
*Buffer += sizeof (UE_HEADER);
|
||||
|
||||
Result = ToolImageEmitUeSegmentHeaders (Context, Buffer, BufferSize);
|
||||
if (!Result) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Result = ToolImageEmitUeSectionHeaders (Context, Buffer, BufferSize);
|
||||
if (!Result) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static
|
||||
bool
|
||||
ToolImageEmitUeSegments (
|
||||
const image_tool_ue_emit_context_t *Context,
|
||||
uint8_t **Buffer,
|
||||
uint32_t *BufferSize
|
||||
)
|
||||
{
|
||||
const image_tool_image_info_t *Image;
|
||||
uint32_t SegmentsSize;
|
||||
uint8_t Index;
|
||||
size_t DataSize;
|
||||
|
||||
assert (Context != NULL);
|
||||
assert (Buffer != NULL);
|
||||
assert (BufferSize != NULL);
|
||||
|
||||
Image = Context->Image;
|
||||
|
||||
SegmentsSize = 0;
|
||||
|
||||
for (Index = 0; Index < Image->SegmentInfo.NumSegments; ++Index) {
|
||||
assert (Image->SegmentInfo.Segments[Index].DataSize <= *BufferSize);
|
||||
|
||||
DataSize = Image->SegmentInfo.Segments[Index].DataSize;
|
||||
|
||||
memmove (*Buffer, Image->SegmentInfo.Segments[Index].Data, DataSize);
|
||||
|
||||
*BufferSize -= DataSize;
|
||||
*Buffer += DataSize;
|
||||
SegmentsSize += DataSize;
|
||||
}
|
||||
|
||||
assert (SegmentsSize == Context->SegmentsSize);
|
||||
|
||||
*BufferSize -= Context->SegmentsEndPadding;
|
||||
*Buffer += Context->SegmentsEndPadding;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static
|
||||
bool
|
||||
ToolImageEmitUeRelocTable (
|
||||
const image_tool_ue_emit_context_t *Context,
|
||||
uint8_t **Buffer,
|
||||
uint32_t *BufferSize
|
||||
)
|
||||
{
|
||||
const image_tool_image_info_t *Image;
|
||||
uint32_t RelocTableSize;
|
||||
UE_RELOCATION_BLOCK *RelocBlock;
|
||||
uint32_t BlockAddress;
|
||||
uint32_t BlockNumRelocs;
|
||||
uint32_t BlockSize;
|
||||
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;
|
||||
|
||||
assert (Image->RelocInfo.NumRelocs > 0);
|
||||
assert (Image->RelocInfo.NumRelocs <= MAX_UINT32);
|
||||
|
||||
assert (sizeof(UE_RELOCATION_BLOCK) <= *BufferSize);
|
||||
|
||||
RelocTableSize = 0;
|
||||
RelocBlock = (void *)*Buffer;
|
||||
BlockAddress = (uint32_t)PAGE (Image->RelocInfo.Relocs[0].Target);
|
||||
BlockNumRelocs = 0;
|
||||
BlockSize = sizeof (*RelocBlock);
|
||||
|
||||
RelocBlock->BlockInfo = BlockAddress;
|
||||
|
||||
for (Index = 0; Index < Image->RelocInfo.NumRelocs; ++Index) {
|
||||
RelocAddress = PAGE (Image->RelocInfo.Relocs[Index].Target);
|
||||
if (RelocAddress != BlockAddress) {
|
||||
BlockSize = ALIGN_VALUE (BlockSize, UE_RELOCATION_BLOCK_ALIGNMENT);
|
||||
assert (BlockSize <= *BufferSize);
|
||||
|
||||
*BufferSize -= BlockSize;
|
||||
*Buffer += BlockSize;
|
||||
RelocTableSize += BlockSize;
|
||||
|
||||
RelocBlock = (void *)*Buffer;
|
||||
|
||||
BlockAddress = RelocAddress;
|
||||
BlockNumRelocs = 0;
|
||||
BlockSize = sizeof (*RelocBlock);
|
||||
|
||||
RelocBlock->BlockInfo = BlockAddress;
|
||||
}
|
||||
|
||||
BlockSize += sizeof (*RelocBlock->RelocInfo);
|
||||
assert (BlockSize <= *BufferSize);
|
||||
|
||||
RelocBlock->RelocInfo[BlockNumRelocs] = PAGE_OFF (Image->RelocInfo.Relocs[Index].Target);
|
||||
RelocBlock->RelocInfo[BlockNumRelocs] |= Image->RelocInfo.Relocs[Index].Type << 12U;
|
||||
assert (UE_RELOC_OFFSET (RelocBlock->RelocInfo[BlockNumRelocs]) == PAGE_OFF (Image->RelocInfo.Relocs[Index].Target));
|
||||
assert (UE_RELOC_TYPE (RelocBlock->RelocInfo[BlockNumRelocs]) == Image->RelocInfo.Relocs[Index].Type);
|
||||
|
||||
++BlockNumRelocs;
|
||||
if (BlockNumRelocs > UE_RELOCATION_BLOCK_MAX_RELOCS) {
|
||||
return false;
|
||||
}
|
||||
|
||||
++RelocBlock->BlockInfo;
|
||||
assert (BlockNumRelocs == UE_RELOC_BLOCK_NUM (RelocBlock->BlockInfo));
|
||||
assert (BlockAddress == UE_RELOC_BLOCK_ADDRESS (RelocBlock->BlockInfo));
|
||||
}
|
||||
|
||||
*BufferSize -= BlockSize;
|
||||
*Buffer += BlockSize;
|
||||
RelocTableSize += BlockSize;
|
||||
|
||||
assert (RelocTableSize == Context->RelocTableSize);
|
||||
|
||||
RelocTablePadding = ALIGN_VALUE_ADDEND (RelocTableSize, UE_SECTION_ALIGNMENT);
|
||||
|
||||
assert (RelocTablePadding <= *BufferSize);
|
||||
|
||||
*BufferSize -= RelocTablePadding;
|
||||
*Buffer += RelocTablePadding;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static
|
||||
bool
|
||||
ToolImageEmitUeDebugTable (
|
||||
const image_tool_ue_emit_context_t *Context,
|
||||
uint8_t **Buffer,
|
||||
uint32_t *BufferSize
|
||||
)
|
||||
{
|
||||
uint32_t DebugTableSize;
|
||||
UE_DEBUG_TABLE *DebugTable;
|
||||
const image_tool_image_info_t *Image;
|
||||
uint8_t Index;
|
||||
UE_SEGMENT_NAME *SectionName;
|
||||
uint32_t DebugTablePadding;
|
||||
|
||||
assert (Context != NULL);
|
||||
assert (Buffer != NULL);
|
||||
assert (BufferSize != NULL);
|
||||
|
||||
assert (sizeof (UE_DEBUG_TABLE) <= *BufferSize);
|
||||
|
||||
DebugTableSize = sizeof (UE_DEBUG_TABLE);
|
||||
|
||||
DebugTable = (void *)*Buffer;
|
||||
|
||||
assert (DebugTable->SymbolsBaseOffset == 0);
|
||||
assert (DebugTable->Reserved == 0);
|
||||
|
||||
Image = Context->Image;
|
||||
|
||||
*BufferSize -= sizeof (UE_DEBUG_TABLE);
|
||||
*Buffer += sizeof (UE_DEBUG_TABLE);
|
||||
|
||||
if (Image->DebugInfo.SymbolsPath != NULL) {
|
||||
assert (Image->DebugInfo.SymbolsPathLen <= MAX_UINT8);
|
||||
DebugTable->SymbolsPathSize = (uint8_t)Image->DebugInfo.SymbolsPathLen;
|
||||
|
||||
assert (Image->DebugInfo.SymbolsPathLen <= *BufferSize);
|
||||
|
||||
DebugTableSize += Image->DebugInfo.SymbolsPathLen;
|
||||
|
||||
memmove (*Buffer, Image->DebugInfo.SymbolsPath, Image->DebugInfo.SymbolsPathLen);
|
||||
|
||||
*BufferSize -= Image->DebugInfo.SymbolsPathLen;
|
||||
*Buffer += Image->DebugInfo.SymbolsPathLen;
|
||||
} else {
|
||||
assert (DebugTable->SymbolsPathSize == 0);
|
||||
}
|
||||
|
||||
for (Index = 0; Index < Image->SegmentInfo.NumSegments; ++Index) {
|
||||
assert (sizeof (UE_SEGMENT_NAME) <= *BufferSize);
|
||||
|
||||
DebugTableSize += sizeof (UE_SEGMENT_NAME);
|
||||
|
||||
SectionName = (void *)*Buffer;
|
||||
|
||||
strncpy (
|
||||
(char *)SectionName,
|
||||
Image->SegmentInfo.Segments[Index].Name,
|
||||
sizeof (*SectionName)
|
||||
);
|
||||
|
||||
*BufferSize -= sizeof (*SectionName);
|
||||
*Buffer += sizeof (*SectionName);
|
||||
}
|
||||
|
||||
assert (DebugTableSize == Context->DebugTableSize);
|
||||
|
||||
DebugTablePadding = ALIGN_VALUE_ADDEND (DebugTableSize, UE_SECTION_ALIGNMENT);
|
||||
|
||||
assert (DebugTablePadding <= *BufferSize);
|
||||
|
||||
*BufferSize -= DebugTablePadding;
|
||||
*Buffer += DebugTablePadding;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static
|
||||
bool
|
||||
ToolImageEmitUeHiiTable (
|
||||
const image_tool_ue_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 (Context->HiiTableSize == 0) {
|
||||
return true;
|
||||
}
|
||||
|
||||
assert (Image->HiiInfo.DataSize == Context->HiiTableSize);
|
||||
assert (Context->HiiTableSize <= *BufferSize);
|
||||
|
||||
memmove (*Buffer, Image->HiiInfo.Data, Image->HiiInfo.DataSize);
|
||||
|
||||
*BufferSize -= Image->HiiInfo.DataSize;
|
||||
*Buffer += Image->HiiInfo.DataSize;
|
||||
|
||||
HiiTablePadding = ALIGN_VALUE_ADDEND (Image->HiiInfo.DataSize, UE_SECTION_ALIGNMENT);
|
||||
|
||||
assert (HiiTablePadding <= *BufferSize);
|
||||
|
||||
*BufferSize -= HiiTablePadding;
|
||||
*Buffer += HiiTablePadding;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static
|
||||
bool
|
||||
ToolImageEmitUeSections (
|
||||
const image_tool_ue_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 = ToolImageEmitUeRelocTable (Context, Buffer, BufferSize);
|
||||
if (!Result) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Result = ToolImageEmitUeDebugTable (Context, Buffer, BufferSize);
|
||||
if (!Result) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Result = ToolImageEmitUeHiiTable (Context, Buffer, BufferSize);
|
||||
if (!Result) {
|
||||
return false;
|
||||
}
|
||||
|
||||
assert ((OldBufferSize - *BufferSize) == Context->SectionsSize);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void *
|
||||
ToolImageEmitUe (
|
||||
const image_tool_image_info_t *Image,
|
||||
uint32_t *FileSize
|
||||
)
|
||||
{
|
||||
image_tool_ue_emit_context_t Context;
|
||||
bool Result;
|
||||
uint32_t SectionsOffset;
|
||||
bool Overflow;
|
||||
void *FileBuffer;
|
||||
uint8_t *Buffer;
|
||||
uint32_t RemainingSize;
|
||||
uint32_t ExpectedSize;
|
||||
|
||||
assert (Image != NULL);
|
||||
assert (FileSize != NULL);
|
||||
|
||||
memset (&Context, 0, sizeof (Context));
|
||||
|
||||
Context.Image = Image;
|
||||
|
||||
Result = EmitUeGetHeaderSizes (Image, &Context.HdrInfo);
|
||||
if (!Result) {
|
||||
raise ();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Result = EmitUeGetSegmentsSize (Image, &Context.SegmentsSize);
|
||||
if (!Result) {
|
||||
raise ();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Overflow = BaseOverflowAddU32 (
|
||||
Context.HdrInfo.HeaderSize,
|
||||
Context.SegmentsSize,
|
||||
&SectionsOffset
|
||||
);
|
||||
if (Overflow) {
|
||||
raise ();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Context.SegmentsEndPadding = ALIGN_VALUE_ADDEND (SectionsOffset, UE_SECTION_ALIGNMENT);
|
||||
|
||||
Overflow = BaseOverflowAddU32 (
|
||||
SectionsOffset,
|
||||
Context.SegmentsEndPadding,
|
||||
&SectionsOffset
|
||||
);
|
||||
if (Overflow) {
|
||||
raise ();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Result = EmitUeGetSectionsSize (&Context, &Context.SectionsSize);
|
||||
if (!Result) {
|
||||
raise ();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
assert (IS_ALIGNED (Context.SectionsSize, UE_SECTION_ALIGNMENT));
|
||||
|
||||
Overflow = BaseOverflowAddU32 (
|
||||
SectionsOffset,
|
||||
Context.SectionsSize,
|
||||
&Context.UnsignedFileSize
|
||||
);
|
||||
if (Overflow) {
|
||||
raise ();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
assert (IS_ALIGNED (Context.UnsignedFileSize, UE_SECTION_ALIGNMENT));
|
||||
|
||||
FileBuffer = calloc (1, Context.UnsignedFileSize);
|
||||
if (FileBuffer == NULL) {
|
||||
raise ();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Buffer = FileBuffer;
|
||||
RemainingSize = Context.UnsignedFileSize;
|
||||
ExpectedSize = Context.UnsignedFileSize;
|
||||
|
||||
Result = ToolImageEmitUeHeader (&Context, &Buffer, &RemainingSize);
|
||||
if (!Result) {
|
||||
raise ();
|
||||
free (FileBuffer);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ExpectedSize -= Context.HdrInfo.HeaderSize;
|
||||
|
||||
assert (RemainingSize == ExpectedSize);
|
||||
|
||||
Result = ToolImageEmitUeSegments (&Context, &Buffer, &RemainingSize);
|
||||
if (!Result) {
|
||||
raise ();
|
||||
free (FileBuffer);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ExpectedSize -= Context.SegmentsSize + Context.SegmentsEndPadding;
|
||||
|
||||
assert (RemainingSize == ExpectedSize);
|
||||
|
||||
Result = ToolImageEmitUeSections (&Context, &Buffer, &RemainingSize);
|
||||
if (!Result) {
|
||||
raise ();
|
||||
free (FileBuffer);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ExpectedSize -= Context.SectionsSize;
|
||||
|
||||
assert (RemainingSize == ExpectedSize);
|
||||
assert (RemainingSize == 0);
|
||||
|
||||
*FileSize = Context.UnsignedFileSize;
|
||||
|
||||
return FileBuffer;
|
||||
}
|
@ -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)
|
||||
|
||||
|
15
BaseTools/MicroTool/GNUmakefile
Normal file
15
BaseTools/MicroTool/GNUmakefile
Normal 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
|
73
BaseTools/MicroTool/Makefile
Normal file
73
BaseTools/MicroTool/Makefile
Normal file
@ -0,0 +1,73 @@
|
||||
## @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
|
||||
USER = $(OC_USER)\User\Library
|
||||
OBJECTS = $(OBJECTS) {$(BASE)}SafeString.obj String.obj SwapBytes16.obj SwapBytes32.obj CpuDeadLoop.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
|
||||
|
||||
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)\
|
||||
|
||||
{$(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)\
|
298
BaseTools/MicroTool/MicroTool.c
Normal file
298
BaseTools/MicroTool/MicroTool.c
Normal 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;
|
||||
}
|
@ -3591,7 +3591,7 @@ Returns:
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
EFI_PHYSICAL_ADDRESS
|
||||
EFI_STATUS
|
||||
AddPadSection (
|
||||
IN OUT EFI_PHYSICAL_ADDRESS *BaseAddress,
|
||||
IN UINT32 Alignment,
|
||||
@ -3604,14 +3604,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;
|
||||
@ -3641,7 +3641,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),
|
||||
|
@ -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
|
||||
|
||||
|
@ -1 +1 @@
|
||||
Subproject commit 52c587d60be67c337364b830dd3fdc15404a2f04
|
||||
Subproject commit d82e959e621a3d597f1e0d50ff8c2d8b96915fd7
|
@ -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;
|
||||
|
@ -96,7 +96,17 @@ typedef struct {
|
||||
//
|
||||
// Characteristics
|
||||
//
|
||||
#define EFI_IMAGE_FILE_RELOCS_STRIPPED 1 ///< 0x0001 Relocation info stripped from file.
|
||||
#define EFI_IMAGE_FILE_RELOCS_STRIPPED BIT0 ///< 0x0001 Relocation info stripped from file.
|
||||
#define EFI_IMAGE_FILE_EXECUTABLE_IMAGE BIT1 ///< 0x0002 File is executable (i.e. no unresolved externel references).
|
||||
#define EFI_IMAGE_FILE_LINE_NUMS_STRIPPED BIT2 ///< 0x0004 Line numbers stripped from file.
|
||||
#define EFI_IMAGE_FILE_LOCAL_SYMS_STRIPPED BIT3 ///< 0x0008 Local symbols stripped from file.
|
||||
#define EFI_IMAGE_FILE_LARGE_ADDRESS_AWARE BIT5 ///< 0x0020 Supports addresses > 2-GB
|
||||
#define EFI_IMAGE_FILE_BYTES_REVERSED_LO BIT7 ///< 0x0080 Bytes of machine word are reversed.
|
||||
#define EFI_IMAGE_FILE_32BIT_MACHINE BIT8 ///< 0x0100 32 bit word machine.
|
||||
#define EFI_IMAGE_FILE_DEBUG_STRIPPED BIT9 ///< 0x0200 Debugging info stripped from file in .DBG file.
|
||||
#define EFI_IMAGE_FILE_SYSTEM BIT12 ///< 0x1000 System File.
|
||||
#define EFI_IMAGE_FILE_DLL BIT13 ///< 0x2000 File is a DLL.
|
||||
#define EFI_IMAGE_FILE_BYTES_REVERSED_HI BIT15 ///< 0x8000 Bytes of machine word are reversed.
|
||||
|
||||
///
|
||||
/// Header Data Directories.
|
||||
|
219
MdePkg/Include/IndustryStandard/UeCertStore.h
Normal file
219
MdePkg/Include/IndustryStandard/UeCertStore.h
Normal file
@ -0,0 +1,219 @@
|
||||
/** @file
|
||||
Definitions of the UE certificate store format.
|
||||
|
||||
Copyright (c) 2021, Marvin Häuser. All rights reserved.<BR>
|
||||
|
||||
SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
**/
|
||||
|
||||
#ifndef UE_CERT_STORE_H_
|
||||
#define UE_CERT_STORE_H_
|
||||
|
||||
///
|
||||
/// Definition of an UE certificate (PKCS).
|
||||
///
|
||||
typedef struct {
|
||||
///
|
||||
/// The UE certificate (PKCS) information.
|
||||
///
|
||||
/// [Bits 23:0] The size, in Bytes, of TbsData.
|
||||
/// [Bits 31:24] Reserved for future usage. Must be set to 0.
|
||||
///
|
||||
UINT32 Info;
|
||||
///
|
||||
/// The size, in Bytes, of Signature.
|
||||
///
|
||||
UINT32 SignatureSize;
|
||||
///
|
||||
/// The ASN.1 DER encoded X.509 tbsCertificate field.
|
||||
///
|
||||
UINT8 TbsData[];
|
||||
///
|
||||
/// The signature of TbsData, signed by the certificate identified by
|
||||
/// TbsData.issuer, with the algorithm identified by SignatureAlgorithm. Its
|
||||
/// size is strictly defined by the signature algorithm.
|
||||
///
|
||||
//UINT8 Signature[];
|
||||
} UE_CERT_PKCS;
|
||||
|
||||
/**
|
||||
Retrieves the size, in Bytes, of TbsData of an UE certificate (PKCS).
|
||||
|
||||
@param[in] Info The UE certificate (PKCS) information.
|
||||
**/
|
||||
#define UE_CERT_PKCS_TBS_SIZE(Info) ((Info) & 0x00FFFFFFU)
|
||||
|
||||
STATIC_ASSERT (
|
||||
sizeof (UE_CERT_PKCS) == 8 && ALIGNOF (UE_CERT_PKCS) == 4,
|
||||
"The UE certificate (PKCS) definition does not meet the specification."
|
||||
);
|
||||
|
||||
STATIC_ASSERT (
|
||||
OFFSET_OF (UE_CERT_PKCS, TbsData) == sizeof (UE_CERT_PKCS),
|
||||
"The UE certificate (PKCS) definition does not meet the specification."
|
||||
);
|
||||
|
||||
///
|
||||
/// Definition of the UE certificate (minimal RSA) purpose identifiers.
|
||||
///
|
||||
enum {
|
||||
UeCertMinRsaPurposeExecutable = 0x00U,
|
||||
UeCertMinRsaPurposeVariables = 0x01U,
|
||||
UeCertMinRsaPurposeConfig = 0x02U
|
||||
};
|
||||
|
||||
///
|
||||
/// Definition of an UE certificate (minimal RSA).
|
||||
/// The RSA exponent is always 65537.
|
||||
///
|
||||
typedef struct {
|
||||
///
|
||||
/// The certificate subject identifier GUID.
|
||||
///
|
||||
GUID SubjectId;
|
||||
///
|
||||
/// [Bits 28:0] The time the certificate expires. It is calculated by:
|
||||
/// S + M * 60 + H * 3600 + D * 86400 + m * 2678400 + Y * 32140800, with
|
||||
/// S [0,59]: The number of full seconds into the current minute,
|
||||
/// M [0,59]: The number of full minutes into the current hour,
|
||||
/// H [0,23]: The number of full hours into the current day,
|
||||
/// D [0,30]: The number of full days into the current month,
|
||||
/// m [0,11]: The number of full months into the current year,
|
||||
/// Y [0,16]: The number of full years since 2021.
|
||||
/// [Bits 29:31] Reserved for future usage. Must be set to 0.
|
||||
///
|
||||
UINT32 ExpiryTime;
|
||||
///
|
||||
/// [Bits 1:0] The purpose identifier of the certificate.
|
||||
/// [Bits 7:1] Reserved for future usage. Must be set to 0.
|
||||
///
|
||||
UINT8 Purpose;
|
||||
///
|
||||
/// Reserved for future usage. Must be set to 0.
|
||||
///
|
||||
UINT8 Reserved;
|
||||
///
|
||||
/// [Bits 11:0] The size, in 8 Byte units, of the RSA modulus.
|
||||
/// [Bits 15:12] Reserved for future usage. Must be set to 0.
|
||||
///
|
||||
UINT16 NumQwords;
|
||||
///
|
||||
/// The Montgomery Inverse in the 64-bit space: -1 / N[0] mod 2^64.
|
||||
///
|
||||
UINT64 N0Inv;
|
||||
///
|
||||
/// The RSA parameters. If the number of significant Bits is less than the
|
||||
/// number of available Bits, the remaining Bits must be set to 0. Storage
|
||||
/// happens in reverse byte order.
|
||||
///
|
||||
/// [0 .. 8 * NumQwords) The RSA key.
|
||||
/// [8 * NumQwords .. 16 * NumQwords) Montgomery R^2 mod N.
|
||||
///
|
||||
UINT8 Data[];
|
||||
} UE_CERT_MIN_RSA;
|
||||
|
||||
STATIC_ASSERT (
|
||||
sizeof (UE_CERT_MIN_RSA) == 32 && ALIGNOF (UE_CERT_MIN_RSA) == 8,
|
||||
"The UE certificate (minimal RSA) definition does not meet the specification."
|
||||
);
|
||||
|
||||
STATIC_ASSERT (
|
||||
OFFSET_OF (UE_CERT_MIN_RSA, Data) == sizeof (UE_CERT_MIN_RSA),
|
||||
"The UE certificate (minimal RSA) definition does not meet the specification."
|
||||
);
|
||||
|
||||
STATIC_ASSERT (
|
||||
IS_ALIGNED (OFFSET_OF (UE_CERT_MIN_RSA, Data), ALIGNOF (UINT64)),
|
||||
"The UE certificate (minimal RSA) definition does not meet the specification."
|
||||
);
|
||||
|
||||
///
|
||||
/// Definition of the UE certificate store types.
|
||||
///
|
||||
enum {
|
||||
UeCertChainTypePkcs = 0x00
|
||||
};
|
||||
|
||||
///
|
||||
/// The alignment, in Bytes, of each UE certificate chain in the UE certificate
|
||||
/// store.
|
||||
///
|
||||
#define UE_CERT_CHAIN_ALIGNMENT 8U
|
||||
|
||||
///
|
||||
/// Definition of an UE certificate chain.
|
||||
///
|
||||
typedef struct {
|
||||
///
|
||||
/// The signature algorithm used to sign the data.
|
||||
///
|
||||
GUID Algorithm;
|
||||
///
|
||||
/// The UE certificate chain information.
|
||||
///
|
||||
/// [Bit 0] If set, the certificate chain is empty and the data may be
|
||||
/// directly signed by a trusted certificate. In this case,
|
||||
/// instead of a certificate chain structure, the type-specific
|
||||
/// issuer information is stored.
|
||||
/// [Bits 2:1] Reserved for future usage. Must be set to 0.
|
||||
/// [Bits 23:3] The size, in Bytes, of this UE certificate chain, or of the
|
||||
/// type-specific issuer information.
|
||||
/// [Bit 24] The type of the UE certificate store.
|
||||
/// [Bits 31:25] Reserved for future usage. Must be set to 0.
|
||||
///
|
||||
UINT32 Info;
|
||||
///
|
||||
/// The size, in Bytes, of Signature.
|
||||
///
|
||||
UINT32 SignatureSize;
|
||||
///
|
||||
/// The signature of the signed data, signed by the first certificate of the
|
||||
/// chain, with the algorithm identified by SignatureAlgorithm. Its size is
|
||||
/// strictly defined by the signature algorithm.
|
||||
///
|
||||
UINT8 Signature[];
|
||||
///
|
||||
/// The certficate chain. The first certificate signs the data.
|
||||
///
|
||||
//UE_CERT Chain[];
|
||||
} UE_CERT_CHAIN;
|
||||
|
||||
/**
|
||||
Retrieves whether the UE certificate chain is routed, i.e. whether there is
|
||||
no chain of certificates but a type-specific issuer identifier for the trusted
|
||||
certificate that signs the data.
|
||||
|
||||
@param[in] Info The UE certificate chain information.
|
||||
**/
|
||||
#define UE_CERT_CHAIN_ROOTED(Info) ((Info) & 0x00000001U)
|
||||
|
||||
/**
|
||||
Retrieves the size, in Bytes, of the UE certificate chain.
|
||||
|
||||
@param[in] Info The UE certificate chain information.
|
||||
**/
|
||||
#define UE_CERT_CHAIN_SIZE(Info) ((Info) & 0x00FFFFF8U)
|
||||
|
||||
/**
|
||||
Retrieves the type of the UE certificate chain.
|
||||
|
||||
@param[in] Info The UE certificate chain information.
|
||||
**/
|
||||
#define UE_CERT_CHAIN_TYPE(Info) (((Info) & 0x1000000U) >> 24U)
|
||||
|
||||
STATIC_ASSERT (
|
||||
IS_ALIGNED (UE_CERT_CHAIN_SIZE (0xFFFFFFFF), UE_CERT_CHAIN_ALIGNMENT),
|
||||
"The UE certificate chain definition does not meet the specification."
|
||||
);
|
||||
|
||||
STATIC_ASSERT (
|
||||
sizeof (UE_CERT_CHAIN) == 24 && ALIGNOF (UE_CERT_CHAIN) == 4,
|
||||
"The UE certificate chain definition does not meet the specification."
|
||||
);
|
||||
|
||||
STATIC_ASSERT (
|
||||
OFFSET_OF (UE_CERT_CHAIN, Signature) == sizeof (UE_CERT_CHAIN),
|
||||
"The UE certificate chain definition does not meet the specification."
|
||||
);
|
||||
|
||||
#endif // UE_CERT_STORE_H_
|
580
MdePkg/Include/IndustryStandard/UeImage.h
Normal file
580
MdePkg/Include/IndustryStandard/UeImage.h
Normal file
@ -0,0 +1,580 @@
|
||||
/** @file
|
||||
Definitions of the UEFI Executable file format.
|
||||
|
||||
Copyright (c) 2021, Marvin Häuser. All rights reserved.<BR>
|
||||
|
||||
SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
**/
|
||||
|
||||
#ifndef UE_IMAGE_H_
|
||||
#define UE_IMAGE_H_
|
||||
|
||||
//
|
||||
// UEFI Executable segment definitions.
|
||||
//
|
||||
// NOTE: To guarantee all data is sufficiently aligned, no matter what it is,
|
||||
// all UE segments are at least 8 Byte aligned in the UE memory space.
|
||||
// This leaves the bottom 3 Bits unused for valid values. Use them to
|
||||
// indicate the UE segment permissions.
|
||||
//
|
||||
|
||||
///
|
||||
/// The alignment, in Bytes, of each UE segment in the UE memory space.
|
||||
///
|
||||
#define UE_SEGMENT_ALIGNMENT 8U
|
||||
|
||||
///
|
||||
/// Definition of an UEFI Executable segment header.
|
||||
///
|
||||
typedef struct {
|
||||
///
|
||||
/// Information about the UE segment in the UE memory space.
|
||||
///
|
||||
/// [Bit 0] Indicates whether the UE segment is read-protected.
|
||||
/// [Bit 1] Indicates whether the UE segment is execute-protected.
|
||||
/// [Bit 2] Indicates whether the UE segment is write-protected.
|
||||
/// [Bits 31:3] The size, in 8 Byte units, of the UE segment in the UE memory
|
||||
/// space.
|
||||
///
|
||||
UINT32 ImageInfo;
|
||||
///
|
||||
/// The size, in Bytes, of the UE segment in the UE raw file.
|
||||
///
|
||||
UINT32 FileSize;
|
||||
} UE_SEGMENT;
|
||||
|
||||
#define UE_SEGMENT_INFO_RP BIT0
|
||||
#define UE_SEGMENT_INFO_XP BIT1
|
||||
#define UE_SEGMENT_INFO_RO BIT2
|
||||
|
||||
STATIC_ASSERT (
|
||||
sizeof (UE_SEGMENT) == 8 && ALIGNOF (UE_SEGMENT) == 4,
|
||||
"The UE segment definition does not meet the specification."
|
||||
);
|
||||
|
||||
///
|
||||
/// Definition of an UEFI Executable XIP segment header.
|
||||
///
|
||||
typedef struct {
|
||||
///
|
||||
/// Information about the UE segment in the UE memory space.
|
||||
///
|
||||
/// [Bit 0] Indicates whether the UE segment is read-protected.
|
||||
/// [Bit 1] Indicates whether the UE segment is execute-protected.
|
||||
/// [Bit 2] Indicates whether the UE segment is write-protected.
|
||||
/// [Bits 31:3] The size, in 8 Byte units, of the UE segment in the UE memory
|
||||
/// space.
|
||||
///
|
||||
UINT32 ImageInfo;
|
||||
} UE_SEGMENT_XIP;
|
||||
|
||||
STATIC_ASSERT (
|
||||
sizeof (UE_SEGMENT_XIP) == 4 && ALIGNOF (UE_SEGMENT_XIP) == 4,
|
||||
"The UE XIP segment definition does not meet the specification."
|
||||
);
|
||||
|
||||
STATIC_ASSERT (
|
||||
OFFSET_OF (UE_SEGMENT, ImageInfo) == OFFSET_OF (UE_SEGMENT_XIP, ImageInfo),
|
||||
"The UE and UE XIP segment definitions do not align."
|
||||
);
|
||||
|
||||
/**
|
||||
Retrieve the UE segment memory permissions.
|
||||
|
||||
@param[in] ImageInfo The UE segment memory information.
|
||||
**/
|
||||
#define UE_SEGMENT_PERMISSIONS(ImageInfo) ((ImageInfo) & 0x00000007U)
|
||||
|
||||
/**
|
||||
Retrieve the size, in Bytes, of the UE segment in the UE memory space.
|
||||
|
||||
@param[in] ImageInfo The UE segment image information.
|
||||
**/
|
||||
#define UE_SEGMENT_SIZE(ImageInfo) ((ImageInfo) & 0xFFFFFFF8U)
|
||||
|
||||
STATIC_ASSERT (
|
||||
IS_ALIGNED (UE_SEGMENT_SIZE (0xFFFFFFFF), UE_SEGMENT_ALIGNMENT),
|
||||
"The UE segment size definition does not meet the specification."
|
||||
);
|
||||
|
||||
//
|
||||
// UEFI Executable section definitions.
|
||||
//
|
||||
// NOTE: To guarantee all data is sufficiently aligned, no matter what it is,
|
||||
// all UE sections are at least 8 Byte aligned.
|
||||
//
|
||||
// UE sections are identified by ID and can be omitted to save space.
|
||||
//
|
||||
// UE sections are ordered by ID to allow efficient lookups.
|
||||
//
|
||||
// UE relocation table will likely be close to PE/COFF.
|
||||
//
|
||||
// UE HII support needs discussion, REF: https://bugzilla.tianocore.org/show_bug.cgi?id=557
|
||||
//
|
||||
// UE certificate table will likely be a stripped version of PE/COFF.
|
||||
//
|
||||
// UE sections are not loaded into the UE memory space as their data is
|
||||
// only required by the loader.
|
||||
//
|
||||
// UE section Bit 2 is reserved in case more UE section IDs are required
|
||||
// in the future. If it is set, an extended structure should be used.
|
||||
//
|
||||
|
||||
///
|
||||
/// The alignment, in Bytes, of each UE section in the UE raw file.
|
||||
///
|
||||
#define UE_SECTION_ALIGNMENT 8U
|
||||
|
||||
///
|
||||
/// Definition of UE section identifiers.
|
||||
///
|
||||
enum {
|
||||
UeSectionIdRelocTable = 0x00U,
|
||||
UeSectionIdDebugTable = 0x01U,
|
||||
UeSectionIdHiiTable = 0x02U
|
||||
};
|
||||
|
||||
//
|
||||
// Definition of an UE section header.
|
||||
//
|
||||
typedef struct {
|
||||
///
|
||||
/// Information about the UE section.
|
||||
///
|
||||
/// [Bits 1:0] The identifier of the UE section.
|
||||
/// [Bit 2] Reserved for future usage. Must be set to 0.
|
||||
/// [Bits 31:3] The size, in 8 Byte units, of the UE section in the UE raw
|
||||
/// file.
|
||||
///
|
||||
UINT32 FileInfo;
|
||||
} UE_SECTION;
|
||||
|
||||
STATIC_ASSERT (
|
||||
sizeof (UE_SECTION) == 4 && ALIGNOF (UE_SECTION) == 4,
|
||||
"The UE section definition does not meet the specification."
|
||||
);
|
||||
|
||||
/**
|
||||
Retrieves the UE section identifier.
|
||||
|
||||
@param[in] FileInfo The UE section raw file information.
|
||||
**/
|
||||
#define UE_SECTION_ID(FileInfo) ((FileInfo) & 0x00000003U)
|
||||
|
||||
/**
|
||||
Retrieves the size, in Bytes, of the UE section in the UE raw file.
|
||||
|
||||
@param[in] FileInfo The UE section raw file information.
|
||||
**/
|
||||
#define UE_SECTION_SIZE(FileInfo) ((FileInfo) & 0xFFFFFFF8U)
|
||||
|
||||
STATIC_ASSERT (
|
||||
IS_ALIGNED (UE_SECTION_SIZE (0xFFFFFFFF), UE_SECTION_ALIGNMENT),
|
||||
"The UE section size definition does not meet the specification."
|
||||
);
|
||||
|
||||
//
|
||||
// UEFI Executable relocation table definitions.
|
||||
//
|
||||
// NOTE: The rest of the definitions should be close to PE/COFF.
|
||||
// PE/COFF SizeOfBlock allows for a lot more relocations, however forcing
|
||||
// 4 KB blocks still allows for one relocation per Byte with this design.
|
||||
//
|
||||
|
||||
///
|
||||
/// Definition of the UEFI Executable relocation identifiers.
|
||||
///
|
||||
enum {
|
||||
UeRelocRel32 = 0x00U,
|
||||
UeRelocRel64 = 0x01U,
|
||||
UeRelocArmMov32t = 0x02U
|
||||
};
|
||||
|
||||
#define UE_RELOCATION_BLOCK_ALIGNMENT 4U
|
||||
|
||||
#define UE_RELOCATION_BLOCK_MAX_RELOCS 4095U
|
||||
|
||||
///
|
||||
/// Definition of an UEFI Executable relocation block.
|
||||
///
|
||||
typedef struct {
|
||||
///
|
||||
/// Information about the UE relocation block.
|
||||
///
|
||||
/// [Bits 11:0] The amount of relocations of the UE relocation block.
|
||||
/// [Bits 31:12] The base address, in 4 KB units, of the UE relocation block.
|
||||
///
|
||||
UINT32 BlockInfo;
|
||||
///
|
||||
/// The relocations of the UE relocation block.
|
||||
///
|
||||
/// [Bits 11:0] The offset of the UE relocation in the UE relocation block.
|
||||
/// [Bits 31:12] The type of the UE relocation.
|
||||
///
|
||||
UINT16 RelocInfo[];
|
||||
} UE_RELOCATION_BLOCK;
|
||||
|
||||
STATIC_ASSERT (
|
||||
sizeof (UE_RELOCATION_BLOCK) == 4 && ALIGNOF (UE_RELOCATION_BLOCK) == UE_RELOCATION_BLOCK_ALIGNMENT,
|
||||
"The UE relocation block definition does not meet the specification."
|
||||
);
|
||||
|
||||
STATIC_ASSERT (
|
||||
ALIGNOF (UE_RELOCATION_BLOCK) <= UE_SECTION_ALIGNMENT,
|
||||
"The UE relocation block definition does not meet the specification."
|
||||
);
|
||||
|
||||
STATIC_ASSERT (
|
||||
OFFSET_OF (UE_RELOCATION_BLOCK, RelocInfo) == sizeof (UE_RELOCATION_BLOCK),
|
||||
"The UE relocation block definition does not meet the specification."
|
||||
);
|
||||
|
||||
/**
|
||||
Retrieves the target offset of the UE relocation.
|
||||
|
||||
@param[in] RelocInfo The UE relocation information.
|
||||
**/
|
||||
#define UE_RELOC_OFFSET(RelocInfo) ((RelocInfo) & 0x0FFFU)
|
||||
|
||||
/**
|
||||
Retrieves the type of the UE relocation.
|
||||
|
||||
@param[in] RelocInfo The UE relocation information.
|
||||
**/
|
||||
#define UE_RELOC_TYPE(RelocInfo) ((RelocInfo) >> 12U)
|
||||
|
||||
/**
|
||||
Retrieves the amount of relocations in the UE relocation block.
|
||||
|
||||
@param[in] BlockInfo The UE relocation block information.
|
||||
**/
|
||||
#define UE_RELOC_BLOCK_NUM(BlockInfo) ((BlockInfo) & 0x00000FFFU)
|
||||
|
||||
/**
|
||||
Retrieves the base address of the UE relocation block.
|
||||
|
||||
@param[in] BlockInfo The UE relocation block information.
|
||||
**/
|
||||
#define UE_RELOC_BLOCK_ADDRESS(BlockInfo) ((BlockInfo) & 0xFFFFF000U)
|
||||
|
||||
//
|
||||
// UEFI Executable debug table definitions.
|
||||
//
|
||||
// NOTE: The UE symbols base address offset is required for conversion of
|
||||
// PE/COFF Images that have their first section start after the end of the
|
||||
// Image headers. As PDBs cannot easily be rebased, store the offset.
|
||||
//
|
||||
|
||||
///
|
||||
/// Definition of an UEFI Executable segment name.
|
||||
///
|
||||
typedef UINT8 UE_SEGMENT_NAME[8];
|
||||
|
||||
STATIC_ASSERT (
|
||||
sizeof (UE_SEGMENT_NAME) == 8 && ALIGNOF (UE_SEGMENT_NAME) == 1,
|
||||
"The UE segment name definition does not meet the specification."
|
||||
);
|
||||
|
||||
///
|
||||
/// Definition of an UEFI Executable section header.
|
||||
///
|
||||
typedef struct {
|
||||
///
|
||||
/// The offset to be added to the UE base address in order to retrieve the
|
||||
/// UE symbols base address.
|
||||
/// FIXME: Can we rely on equal layouts for all source file formats?
|
||||
///
|
||||
INT16 SymbolsBaseOffset;
|
||||
//
|
||||
// Reserved for future usage. Must be set to 0.
|
||||
//
|
||||
UINT8 Reserved;
|
||||
///
|
||||
/// The size, in Bytes, of the UE symbols path.
|
||||
///
|
||||
UINT8 SymbolsPathSize;
|
||||
///
|
||||
/// The UE symbols path.
|
||||
///
|
||||
UINT8 SymbolsPath[];
|
||||
///
|
||||
/// The UE segment name table. In the same order as the UE segment table.
|
||||
///
|
||||
//UE_SEGMENT_NAME SegmentNames[];
|
||||
} UE_DEBUG_TABLE;
|
||||
|
||||
///
|
||||
/// The minimum size, in Bytes, of the UE debug table.
|
||||
///
|
||||
#define MIN_SIZE_OF_UE_DEBUG_TABLE OFFSET_OF (UE_DEBUG_TABLE, SymbolsPath)
|
||||
|
||||
/**
|
||||
Retrieves the segment name table of an UE debug table.
|
||||
|
||||
@param[in] DebugTable The UE debug table.
|
||||
**/
|
||||
#define UE_DEBUG_TABLE_SEGMENT_NAMES(DebugTable) \
|
||||
(CONST UE_SEGMENT_NAME *) ( \
|
||||
(DebugTable)->SymbolsPath + (DebugTable)->SymbolsPathSize \
|
||||
)
|
||||
|
||||
STATIC_ASSERT (
|
||||
sizeof (UE_DEBUG_TABLE) == 4 && ALIGNOF (UE_DEBUG_TABLE) == 2,
|
||||
"The UE debug table definition does not meet the specification."
|
||||
);
|
||||
|
||||
STATIC_ASSERT (
|
||||
ALIGNOF (UE_DEBUG_TABLE) <= UE_SECTION_ALIGNMENT,
|
||||
"The UE debug table definition is misaligned."
|
||||
);
|
||||
|
||||
STATIC_ASSERT (
|
||||
OFFSET_OF (UE_DEBUG_TABLE, SymbolsPath) == sizeof (UE_DEBUG_TABLE),
|
||||
"The UE relocation block definition does not meet the specification."
|
||||
);
|
||||
|
||||
//
|
||||
// UEFI Executable header definitions.
|
||||
//
|
||||
// NOTE: The UE segment alignment is stored as shift exponent to save up to
|
||||
// 3 Bytes. This also guarantees it to be a power fo two.
|
||||
//
|
||||
// UE fixed-address loading needs reconsideration.
|
||||
//
|
||||
// The UE header can be contained in a separate FFS section to save space.
|
||||
//
|
||||
// The UE segment table overlaps the UE header padding. However, as there
|
||||
// must always be at least one segment, the padding can be ignored.
|
||||
//
|
||||
// The index of the last UE segment is stored over the number of segments
|
||||
// to avoid the check against 0, and to allow for one more segment.
|
||||
//
|
||||
// The remaining reserved fields may be used to indicate revision.
|
||||
//
|
||||
// The certificate table is not stored as an UE section to both omit its
|
||||
// size from the headers (allows for multi-step-signing without having to
|
||||
// hash the certificate table size), and to allow immediate hashing.
|
||||
//
|
||||
// The UE XIP header omits all data that can be derived from platform
|
||||
// constraints. This header is not guaranteed to be backwards-compatible.
|
||||
//
|
||||
|
||||
///
|
||||
/// The signature of an UEFI Executable header.
|
||||
///
|
||||
#define UE_HEADER_SIGNATURE SIGNATURE_16 ('U', 'E')
|
||||
|
||||
#define UE_HEADER_FLAG_RELOCS_STRIPPED BIT7
|
||||
|
||||
///
|
||||
/// Definition of the UEFI Executable machine identifiers.
|
||||
///
|
||||
enum {
|
||||
UeMachineI386 = 0x00U,
|
||||
UeMachineEbc = 0x01U,
|
||||
UeMachineX64 = 0x02U,
|
||||
UeMachineArmThumbMixed = 0x03U,
|
||||
UeMachineArm64 = 0x04U,
|
||||
UeMachineRiscV32 = 0x05U,
|
||||
UeMachineRiscV64 = 0x06U,
|
||||
UeMachineRiscV128 = 0x07U
|
||||
};
|
||||
|
||||
///
|
||||
/// Definition of the UEFI Executable subsystem identifiers.
|
||||
///
|
||||
enum {
|
||||
UeSubsystemEfiApplication = 0x00U,
|
||||
UeSubsystemEfiBootServicesDriver = 0x01U,
|
||||
UeSubsystemEfiRuntimeDriver = 0x02U,
|
||||
UeSubsystemSalRuntimeDriver = 0x03U,
|
||||
};
|
||||
|
||||
///
|
||||
/// Definition of an UEFI Executable header.
|
||||
///
|
||||
typedef struct {
|
||||
///
|
||||
/// The signature to identify the UE raw file format. Must match 'UE'.
|
||||
///
|
||||
UINT16 Signature;
|
||||
///
|
||||
/// [Bits 7:0] Reserved for future usage. Must be set to 0.
|
||||
///
|
||||
UINT8 Reserved;
|
||||
///
|
||||
/// Information about the UE Image.
|
||||
///
|
||||
/// [Bits 4:0] The shift exponent for the UE segment alignment in Bytes.
|
||||
/// [Bits 6:5] Reserved for future usage. Must be set to 0.
|
||||
/// [Bit 7] Indicates whether the UE relocation table has been stripped.
|
||||
///
|
||||
UINT8 ImageInfo;
|
||||
///
|
||||
/// The index of the last segment in the UE segment table.
|
||||
///
|
||||
UINT8 LastSegmentIndex;
|
||||
///
|
||||
/// The number of sections in the UE section table.
|
||||
///
|
||||
UINT8 NumSections;
|
||||
///
|
||||
/// Indicates the subsystem identifier the UE targets.
|
||||
///
|
||||
UINT8 Subsystem;
|
||||
///
|
||||
/// Indicates the machine identifier the UE targets.
|
||||
///
|
||||
UINT8 Machine;
|
||||
///
|
||||
/// Indicates the UE preferred load address.
|
||||
///
|
||||
UINT64 PreferredAddress;
|
||||
///
|
||||
/// Indicates the offset of the UE entry point in the UE memory space.
|
||||
///
|
||||
UINT32 EntryPointAddress;
|
||||
///
|
||||
/// Extended information about the UE Image.
|
||||
///
|
||||
/// [Bits 2:0] Reserved for future usage. Must be set to 0.
|
||||
/// [Bits 31:3] The size, in 8 Byte units, of the unsigned UE raw file. If the
|
||||
/// UE raw file size is larger than this value, the appended data
|
||||
/// is the UE certificate table.
|
||||
///
|
||||
UINT32 ImageInfo2;
|
||||
///
|
||||
/// The UE segment table. It contains all data of the UE memory space.
|
||||
///
|
||||
/// All UE segments are contiguous in the UE memory space.
|
||||
/// The offset of the first UE segment in the UE memory space is 0.
|
||||
///
|
||||
/// All UE segments are contiguous in the UE raw file.
|
||||
/// The offset of the first UE segment in the UE raw file is the end of the
|
||||
/// UEFI Executable header in the UE raw file.
|
||||
///
|
||||
UE_SEGMENT Segments[];
|
||||
///
|
||||
/// The UE section table. It contains data useful for UE loading.
|
||||
///
|
||||
/// All UE sections are contiguous in the UE raw file.
|
||||
/// The offset of the first UE section in the UE raw file is the end of the
|
||||
/// last UE segment in the UE raw file.
|
||||
///
|
||||
/// All UE sections are ordered by their UE section identifier.
|
||||
///
|
||||
//UE_SECTION Sections[];
|
||||
} UE_HEADER;
|
||||
|
||||
///
|
||||
/// The minimum size, in Bytes, of a valid UE header.
|
||||
///
|
||||
#define MIN_SIZE_OF_UE_HEADER \
|
||||
(OFFSET_OF (UE_HEADER, Segments) + sizeof (UE_SEGMENT))
|
||||
|
||||
STATIC_ASSERT (
|
||||
sizeof (UE_HEADER) == 24 && ALIGNOF (UE_HEADER) == 8,
|
||||
"The UE header definition does not meet the specification."
|
||||
);
|
||||
|
||||
STATIC_ASSERT (
|
||||
ALIGNOF (UE_SEGMENT) <= ALIGNOF (UE_SECTION),
|
||||
"The UE header definition is misaligned."
|
||||
);
|
||||
|
||||
STATIC_ASSERT (
|
||||
OFFSET_OF (UE_HEADER, Segments) == sizeof (UE_HEADER),
|
||||
"The UE header definition does not meet the specification."
|
||||
);
|
||||
|
||||
/**
|
||||
Retrieves the UE segment alignment, in Bytes, as a power of two.
|
||||
|
||||
@param[in] ImageInfo The UE header image information.
|
||||
**/
|
||||
#define UE_HEADER_ALIGNMENT(ImageInfo) ((UINT32) 1U << ((ImageInfo) & 0x1FU))
|
||||
|
||||
/**
|
||||
Retrieves the 8 Byte aligned unsigned UE raw file size.
|
||||
If the UE raw file size is larger than this value, the appended data is the UE
|
||||
certificate table.
|
||||
@param[in] ImageInfo2 The UE header image information.
|
||||
**/
|
||||
#define UE_HEADER_UNSIGNED_SIZE(ImageInfo2) ((ImageInfo2) & 0xFFFFFFF8U)
|
||||
|
||||
STATIC_ASSERT (
|
||||
IS_ALIGNED (UE_HEADER_UNSIGNED_SIZE (0xFFFFFFFF), UE_SECTION_ALIGNMENT),
|
||||
"The unsigned UE raw file size definition does not meet the specification."
|
||||
);
|
||||
|
||||
///
|
||||
/// Definition of an UEFI Executable XIP header.
|
||||
///
|
||||
typedef struct {
|
||||
///
|
||||
/// [Bits 7:0] Reserved for future usage. Must be set to 0.
|
||||
///
|
||||
UINT8 Reserved;
|
||||
///
|
||||
/// Information about the UE Image.
|
||||
///
|
||||
/// [Bits 4:0] The shift exponent for the UE segment alignment.
|
||||
/// [Bits 6:5] Reserved for future usage. Must be set to 0.
|
||||
/// [Bit 7] Indicates whether the UE relocation table has been stripped.
|
||||
///
|
||||
UINT8 ImageInfo;
|
||||
///
|
||||
/// The index of the last segment in the UE segment table.
|
||||
///
|
||||
UINT8 LastSegmentIndex;
|
||||
///
|
||||
/// The number of sections in the UE section table.
|
||||
///
|
||||
UINT8 NumSections;
|
||||
///
|
||||
/// Indicates the offset of the UE entry point in the UE memory space.
|
||||
///
|
||||
UINT32 EntryPointAddress;
|
||||
///
|
||||
/// The UE segment table. It contains all data of the UE memory space.
|
||||
///
|
||||
/// All UE segments are contiguous in the UE memory space.
|
||||
/// The offset of the first UE segment in the UE memory space is 0.
|
||||
///
|
||||
/// The UE segments are stored separately in XIP memory.
|
||||
///
|
||||
UE_SEGMENT_XIP Segments[];
|
||||
///
|
||||
/// The UE section table. It contains data useful for UE loading.
|
||||
///
|
||||
/// All UE sections are contiguous in the UE raw file.
|
||||
/// The offset of the first UE section in the UE raw file is the end of the
|
||||
/// UEFI Executable XIP header in the UE raw file.
|
||||
///
|
||||
/// All UE sections are ordered by their UE section identifier.
|
||||
///
|
||||
//UE_SECTION Sections[];
|
||||
} UE_HEADER_XIP;
|
||||
|
||||
///
|
||||
/// The minimum size, in Bytes, of a valid UE XIP header.
|
||||
///
|
||||
#define MIN_SIZE_OF_UE_HEADER_XIP \
|
||||
(OFFSET_OF (UE_HEADER_XIP, Segments) + sizeof (UE_SEGMENT_XIP))
|
||||
|
||||
STATIC_ASSERT (
|
||||
sizeof (UE_HEADER_XIP) == 8 && ALIGNOF (UE_HEADER_XIP) == 4,
|
||||
"The UE XIP header definition does not meet the specification."
|
||||
);
|
||||
|
||||
STATIC_ASSERT (
|
||||
ALIGNOF (UE_SEGMENT_XIP) <= ALIGNOF (UE_SECTION),
|
||||
"The UE XIP header definition is misaligned."
|
||||
);
|
||||
|
||||
STATIC_ASSERT (
|
||||
OFFSET_OF (UE_HEADER_XIP, Segments) == sizeof (UE_HEADER_XIP),
|
||||
"The UE XIP header definition does not meet the specification."
|
||||
);
|
||||
|
||||
#endif // UE_IMAGE_H_
|
250
MdePkg/Include/Library/UeImageLib.h
Normal file
250
MdePkg/Include/Library/UeImageLib.h
Normal file
@ -0,0 +1,250 @@
|
||||
/** @file
|
||||
UEFI Image Loader library implementation for UE Images.
|
||||
|
||||
Copyright (c) 2021, Marvin Häuser. All rights reserved.<BR>
|
||||
|
||||
SPDX-License-Identifier: BSD-3-Clause
|
||||
**/
|
||||
|
||||
#ifndef UE_LIB_H_
|
||||
#define UE_LIB_H_
|
||||
|
||||
#include <IndustryStandard/UeImage.h>
|
||||
|
||||
// FIXME: Deduplicate?
|
||||
//
|
||||
// PcdImageLoaderAlignmentPolicy bits.
|
||||
//
|
||||
|
||||
///
|
||||
/// If set, unaligned Image sections are permitted.
|
||||
///
|
||||
#define PCD_ALIGNMENT_POLICY_CONTIGUOUS_SECTIONS BIT0
|
||||
///
|
||||
/// If set, unaligned Image Relocation Block sizes are permitted.
|
||||
///
|
||||
#define PCD_ALIGNMENT_POLICY_RELOCATION_BLOCK_SIZES BIT1
|
||||
///
|
||||
/// If set, unaligned Image certificate sizes are permitted.
|
||||
///
|
||||
#define PCD_ALIGNMENT_POLICY_CERTIFICATE_SIZES BIT2
|
||||
|
||||
//
|
||||
// PcdImageLoaderRelocTypePolicy bits.
|
||||
//
|
||||
|
||||
///
|
||||
/// If set, ARM Thumb Image relocations are supported.
|
||||
///
|
||||
#define PCD_RELOC_TYPE_POLICY_ARM BIT0
|
||||
|
||||
// FIXME: Add RISC-V support.
|
||||
/**
|
||||
Returns whether the Base Relocation type is supported by this loader.
|
||||
|
||||
@param[in] Type The type of the Base Relocation.
|
||||
**/
|
||||
#define UE_RELOC_TYPE_SUPPORTED(Type) \
|
||||
(((Type) == EFI_IMAGE_REL_BASED_ABSOLUTE) || \
|
||||
((Type) == EFI_IMAGE_REL_BASED_HIGHLOW) || \
|
||||
((Type) == EFI_IMAGE_REL_BASED_DIR64) || \
|
||||
((PcdGet32 (PcdImageLoaderRelocTypePolicy) & PCD_RELOC_TYPE_POLICY_ARM) != 0 && (Type) == EFI_IMAGE_REL_BASED_ARM_MOV32T))
|
||||
|
||||
/**
|
||||
Returns whether the Base Relocation is supported by this loader.
|
||||
|
||||
@param[in] Relocation The composite Base Relocation value.
|
||||
**/
|
||||
#define UE_RELOC_SUPPORTED(RelocInfo) \
|
||||
UE_RELOC_TYPE_SUPPORTED (UE_RELOC_TYPE (RelocInfo))
|
||||
|
||||
typedef struct {
|
||||
CONST VOID *FileBuffer;
|
||||
UINT32 SegmentAlignment;
|
||||
VOID *ImageBuffer;
|
||||
UINT32 SegmentsFileOffset; // Unused for XIP
|
||||
CONST UE_SECTION *Sections;
|
||||
CONST VOID *Segments;
|
||||
UINT32 SectionsFileOffset;
|
||||
UINT32 ImageSize;
|
||||
UINT32 UnsignedFileSize;
|
||||
UINT32 CertTableSize;
|
||||
UINT32 RelocTableSize;
|
||||
UINT8 ImageInfo;
|
||||
UINT8 LastSegmentIndex;
|
||||
UINT8 NumSections;
|
||||
UINT8 Subsystem;
|
||||
UINT8 Machine;
|
||||
UINT64 PreferredAddress; // Unused for XIP
|
||||
UINT32 EntryPointAddress;
|
||||
UINT8 SegmentImageInfoIterSize;
|
||||
} UE_LOADER_IMAGE_CONTEXT;
|
||||
|
||||
typedef struct UE_LOADER_RUNTIME_CONTEXT_ UE_LOADER_RUNTIME_CONTEXT;
|
||||
|
||||
/**
|
||||
Adds the digest of Data to HashContext. This function can be called multiple
|
||||
times to compute the digest of discontinuous data.
|
||||
|
||||
@param[in,out] HashContext The context of the current hash.
|
||||
@param[in] Data The data to be hashed.
|
||||
@param[in] DataSize The size, in Bytes, of Data.
|
||||
|
||||
@returns Whether hashing has been successful.
|
||||
**/
|
||||
typedef
|
||||
BOOLEAN
|
||||
(EFIAPI *UE_LOADER_HASH_UPDATE)(
|
||||
IN OUT VOID *HashContext,
|
||||
IN CONST VOID *Data,
|
||||
IN UINTN DataSize
|
||||
);
|
||||
|
||||
RETURN_STATUS
|
||||
UeInitializeContextPreHash (
|
||||
OUT UE_LOADER_IMAGE_CONTEXT *Context,
|
||||
IN CONST VOID *FileBuffer,
|
||||
IN UINT32 FileSize
|
||||
);
|
||||
|
||||
RETURN_STATUS
|
||||
UeInitializeContextPostHash (
|
||||
IN OUT UE_LOADER_IMAGE_CONTEXT *Context
|
||||
);
|
||||
|
||||
RETURN_STATUS
|
||||
UeInitializeContext (
|
||||
OUT UE_LOADER_IMAGE_CONTEXT *Context,
|
||||
IN CONST VOID *FileBuffer,
|
||||
IN UINT32 FileSize
|
||||
);
|
||||
|
||||
BOOLEAN
|
||||
UeHashImageDefault (
|
||||
IN OUT UE_LOADER_IMAGE_CONTEXT *Context,
|
||||
IN OUT VOID *HashContext,
|
||||
IN UE_LOADER_HASH_UPDATE HashUpdate
|
||||
);
|
||||
|
||||
RETURN_STATUS
|
||||
UeLoadImage (
|
||||
IN OUT UE_LOADER_IMAGE_CONTEXT *Context,
|
||||
OUT VOID *Destination,
|
||||
IN UINT32 DestinationSize
|
||||
);
|
||||
|
||||
RETURN_STATUS
|
||||
UeLoadImageInplace (
|
||||
IN OUT UE_LOADER_IMAGE_CONTEXT *Context
|
||||
);
|
||||
|
||||
RETURN_STATUS
|
||||
UeLoaderGetRuntimeContextSize (
|
||||
IN OUT UE_LOADER_IMAGE_CONTEXT *Context,
|
||||
OUT UINT32 *Size
|
||||
);
|
||||
|
||||
RETURN_STATUS
|
||||
UeRelocateImage (
|
||||
IN OUT UE_LOADER_IMAGE_CONTEXT *Context,
|
||||
IN UINT64 BaseAddress
|
||||
);
|
||||
|
||||
RETURN_STATUS
|
||||
UeRelocateImageForRuntime (
|
||||
IN OUT VOID *Image,
|
||||
IN UINT32 ImageSize,
|
||||
IN UINT64 BaseAddress,
|
||||
IN CONST UE_LOADER_RUNTIME_CONTEXT *RuntimeContext
|
||||
);
|
||||
|
||||
RETURN_STATUS
|
||||
UeGetSymbolsPath (
|
||||
IN OUT UE_LOADER_IMAGE_CONTEXT *Context,
|
||||
OUT CONST CHAR8 **SymbolsPath,
|
||||
OUT UINT32 *SymbolsPathSize
|
||||
);
|
||||
|
||||
RETURN_STATUS
|
||||
UeGetFirstCertificate (
|
||||
IN OUT UE_LOADER_IMAGE_CONTEXT *Context,
|
||||
OUT CONST WIN_CERTIFICATE **Certificate
|
||||
);
|
||||
|
||||
RETURN_STATUS
|
||||
UeGetNextCertificate (
|
||||
IN OUT UE_LOADER_IMAGE_CONTEXT *Context,
|
||||
IN OUT CONST WIN_CERTIFICATE **Certificate
|
||||
);
|
||||
|
||||
RETURN_STATUS
|
||||
UeGetHiiDataRva (
|
||||
IN OUT UE_LOADER_IMAGE_CONTEXT *Context,
|
||||
OUT UINT32 *HiiRva,
|
||||
OUT UINT32 *HiiSize
|
||||
);
|
||||
|
||||
UINT32
|
||||
UeGetAddressOfEntryPoint (
|
||||
IN OUT UE_LOADER_IMAGE_CONTEXT *Context
|
||||
);
|
||||
|
||||
UINT16
|
||||
UeGetMachine (
|
||||
IN OUT UE_LOADER_IMAGE_CONTEXT *Context
|
||||
);
|
||||
|
||||
UINT16
|
||||
UeGetSubsystem (
|
||||
IN OUT UE_LOADER_IMAGE_CONTEXT *Context
|
||||
);
|
||||
|
||||
UINT32
|
||||
UeGetSegmentAlignment (
|
||||
IN OUT UE_LOADER_IMAGE_CONTEXT *Context
|
||||
);
|
||||
|
||||
UINT32
|
||||
UeGetImageSize (
|
||||
IN OUT UE_LOADER_IMAGE_CONTEXT *Context
|
||||
);
|
||||
|
||||
UINT32
|
||||
UeGetImageSizeInplace (
|
||||
IN OUT UE_LOADER_IMAGE_CONTEXT *Context
|
||||
);
|
||||
|
||||
UINT64
|
||||
UeGetPreferredAddress (
|
||||
IN OUT UE_LOADER_IMAGE_CONTEXT *Context
|
||||
);
|
||||
|
||||
BOOLEAN
|
||||
UeGetRelocsStripped (
|
||||
IN OUT UE_LOADER_IMAGE_CONTEXT *Context
|
||||
);
|
||||
|
||||
UINTN
|
||||
UeLoaderGetImageAddress (
|
||||
IN OUT UE_LOADER_IMAGE_CONTEXT *Context
|
||||
);
|
||||
|
||||
UINT8
|
||||
UeGetSegments (
|
||||
IN OUT UE_LOADER_IMAGE_CONTEXT *Context,
|
||||
OUT CONST UE_SEGMENT **Segments
|
||||
);
|
||||
|
||||
UINT8
|
||||
UeGetSegmentImageInfos (
|
||||
IN OUT UE_LOADER_IMAGE_CONTEXT *Context,
|
||||
OUT CONST UINT32 **SegmentImageInfos,
|
||||
OUT UINT8 *SegmentImageInfoIterSize
|
||||
);
|
||||
|
||||
UINT32
|
||||
UeGetSectionsFileOffset (
|
||||
IN OUT UE_LOADER_IMAGE_CONTEXT *Context
|
||||
);
|
||||
|
||||
#endif // UE_LIB_H_
|
@ -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,
|
||||
|
@ -19,7 +19,7 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||
#include <Library/BaseLib.h>
|
||||
#include <Library/BaseOverflowLib.h>
|
||||
|
||||
#include "OverflowInternals.h"
|
||||
#include "BaseOverflowInternals.h"
|
||||
|
||||
//
|
||||
// Software implementations provided try not to be obviously slow, but primarily
|
@ -19,7 +19,7 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||
#include <Library/BaseLib.h>
|
||||
#include <Library/BaseOverflowLib.h>
|
||||
|
||||
#include "OverflowInternals.h"
|
||||
#include "BaseOverflowInternals.h"
|
||||
|
||||
BOOLEAN
|
||||
BaseOverflowAddUN (
|
@ -29,12 +29,12 @@
|
||||
#
|
||||
|
||||
[Sources]
|
||||
Alignment.c
|
||||
BitOverflow.c
|
||||
OverflowInternals.h
|
||||
Math.c
|
||||
NativeOverflow.c
|
||||
TripleOverflow.c
|
||||
BaseAlignment.c
|
||||
BaseBitOverflow.c
|
||||
BaseOverflowInternals.h
|
||||
BaseMath.c
|
||||
BaseNativeOverflow.c
|
||||
BaseTripleOverflow.c
|
||||
|
||||
[Packages]
|
||||
MdePkg/MdePkg.dec
|
||||
|
@ -233,7 +233,7 @@ InternalVerifySections (
|
||||
}
|
||||
//
|
||||
// Set SizeOfImage to the aligned end address of the last ImageSection.
|
||||
//
|
||||
//
|
||||
if ((PcdGet32 (PcdImageLoaderAlignmentPolicy) & PCD_ALIGNMENT_POLICY_CONTIGUOUS_SECTIONS) == 0) {
|
||||
Context->SizeOfImage = NextSectRva;
|
||||
} else {
|
||||
|
109
MdePkg/Library/BaseUeCertStoreLib/UeCertStoreLib.c
Normal file
109
MdePkg/Library/BaseUeCertStoreLib/UeCertStoreLib.c
Normal file
@ -0,0 +1,109 @@
|
||||
#include <Base.h>
|
||||
|
||||
#include <IndustryStandard/UeCertStore.h>
|
||||
|
||||
#include <Library/DebugLib.h>
|
||||
#include <Library/BaseOverflowLib.h>
|
||||
|
||||
typedef struct {
|
||||
CONST UE_CERT_CHAIN *CertStore;
|
||||
UINT32 CertStoreSize;
|
||||
} UE_CS_CONTEXT;
|
||||
|
||||
RETURN_STATUS
|
||||
UeCsInitializeContext (
|
||||
OUT UE_CS_CONTEXT *Context,
|
||||
IN CONST VOID *Buffer,
|
||||
IN UINT32 BufferSize
|
||||
)
|
||||
{
|
||||
ASSERT (Context != NULL);
|
||||
ASSERT (Buffer != NULL || BufferSize == 0);
|
||||
|
||||
if (sizeof (UE_CERT_CHAIN) > BufferSize) {
|
||||
DEBUG_RAISE ();
|
||||
return RETURN_UNSUPPORTED;
|
||||
}
|
||||
|
||||
Context->CertStore = Buffer;
|
||||
Context->CertStoreSize = BufferSize;
|
||||
return RETURN_SUCCESS;
|
||||
}
|
||||
|
||||
RETURN_STATUS
|
||||
UeGetFirstCertChain (
|
||||
IN OUT UE_CS_CONTEXT *Context,
|
||||
IN OUT UE_CERT_CHAIN **CertChain
|
||||
)
|
||||
{
|
||||
ASSERT (Context != NULL);
|
||||
ASSERT (CertChain != NULL);
|
||||
}
|
||||
|
||||
RETURN_STATUS
|
||||
UeGetNextCertChain (
|
||||
IN OUT UE_CS_CONTEXT *Context,
|
||||
IN OUT UE_CERT_CHAIN **CertChain
|
||||
)
|
||||
{
|
||||
ASSERT (Context != NULL);
|
||||
ASSERT (CertChain != NULL);
|
||||
}
|
||||
|
||||
STATIC
|
||||
RETURN_STATUS
|
||||
InternalValidatePkcsCertChain (
|
||||
IN OUT UE_CS_CONTEXT *Context,
|
||||
IN OUT UE_CERT_CHAIN *CertChain,
|
||||
IN UINT32 RemainingSize
|
||||
)
|
||||
{
|
||||
BOOLEAN Overflow;
|
||||
CONST UE_CERT_PKCS *Certs;
|
||||
UINT32 CertChainPayloadSize;
|
||||
UINT32 CertChainChainSize;
|
||||
UINT32 CertSize;
|
||||
|
||||
ASSERT (Context != NULL);
|
||||
ASSERT (CertChain != NULL);
|
||||
ASSERT (UE_CERT_CHAIN_TYPE (CertChain->Info) == UeCertChainTypePkcs);
|
||||
|
||||
Overflow = BaseOverflowSubU32 (
|
||||
RemainingSize,
|
||||
sizeof (UE_CERT_CHAIN),
|
||||
&RemainingSize
|
||||
);
|
||||
if (Overflow) {
|
||||
DEBUG_RAISE ();
|
||||
return RETURN_UNSUPPORTED;
|
||||
}
|
||||
|
||||
CertChainChainSize = UE_CERT_CHAIN_SIZE (CertChain->Info);
|
||||
|
||||
Overflow = BaseOverflowAddU32 (
|
||||
CertChain->SignatureSize,
|
||||
CertChainChainSize,
|
||||
&CertChainPayloadSize
|
||||
);
|
||||
if (Overflow) {
|
||||
DEBUG_RAISE ();
|
||||
return RETURN_UNSUPPORTED;
|
||||
}
|
||||
|
||||
if (CertChainPayloadSize > RemainingSize) {
|
||||
DEBUG_RAISE ();
|
||||
return RETURN_UNSUPPORTED;
|
||||
}
|
||||
|
||||
Certs = CertChain->Signature + CertChain->SignatureSize;
|
||||
}
|
||||
|
||||
RETURN_STATUS
|
||||
UeValidateCertChain (
|
||||
IN OUT UE_CS_CONTEXT *Context,
|
||||
IN OUT UE_CERT_CHAIN *CertChain
|
||||
)
|
||||
{
|
||||
ASSERT (Context != NULL);
|
||||
ASSERT (CertChain != NULL);
|
||||
}
|
31
MdePkg/Library/BaseUeImageLib/BaseUeImageLib.inf
Normal file
31
MdePkg/Library/BaseUeImageLib/BaseUeImageLib.inf
Normal file
@ -0,0 +1,31 @@
|
||||
## @file
|
||||
# UEFI Image Loader library implementation for PE/COFF and TE Images.
|
||||
#
|
||||
# Copyright (c) 2021, Marvin Häuser. All rights reserved.<BR>
|
||||
#
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
##
|
||||
|
||||
[Defines]
|
||||
INF_VERSION = 0x00010005
|
||||
BASE_NAME = UeImageLib
|
||||
FILE_GUID = 357AD87E-8D6B-468A-B3FA-0D9CC4C725CD
|
||||
MODULE_TYPE = BASE
|
||||
VERSION_STRING = 1.0
|
||||
LIBRARY_CLASS = BaseUeImageLib
|
||||
|
||||
[Sources]
|
||||
UeImageLib.c
|
||||
|
||||
[Packages]
|
||||
MdePkg/MdePkg.dec
|
||||
|
||||
[LibraryClasses]
|
||||
BaseLib
|
||||
BaseMemoryLib
|
||||
BaseOverflowLib
|
||||
DebugLib
|
||||
PcdLib
|
||||
|
||||
[FixedPcd]
|
||||
gEfiMdePkgTokenSpaceGuid.PcdImageLoaderRelocTypePolicy
|
1132
MdePkg/Library/BaseUeImageLib/UeImageLib.c
Normal file
1132
MdePkg/Library/BaseUeImageLib/UeImageLib.c
Normal file
File diff suppressed because it is too large
Load Diff
33
MdePkg/Library/BaseUefiImageLib/BaseUefiImageLibUe.inf
Normal file
33
MdePkg/Library/BaseUefiImageLib/BaseUefiImageLibUe.inf
Normal file
@ -0,0 +1,33 @@
|
||||
## @file
|
||||
# UEFI Image Loader library implementation for UE Images.
|
||||
#
|
||||
# Copyright (c) 2021, Marvin Häuser. All rights reserved.<BR>
|
||||
#
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
##
|
||||
|
||||
[Defines]
|
||||
INF_VERSION = 0x00010005
|
||||
BASE_NAME = BaseUefiImageLibUe
|
||||
FILE_GUID = 25BC78F1-426B-4C9D-A60D-173A56FB28C1
|
||||
MODULE_TYPE = BASE
|
||||
VERSION_STRING = 1.0
|
||||
LIBRARY_CLASS = UefiImageLib
|
||||
|
||||
[Sources]
|
||||
CommonSupport.c
|
||||
UeSupport.h
|
||||
UeSupport.c
|
||||
UefiImageLibUe.c
|
||||
|
||||
[Packages]
|
||||
MdePkg/MdePkg.dec
|
||||
|
||||
[LibraryClasses]
|
||||
BaseLib
|
||||
BaseMemoryLib
|
||||
BaseOverflowLib
|
||||
CacheMaintenanceLib
|
||||
DebugLib
|
||||
MemoryAllocationLib
|
||||
UeImageLib
|
234
MdePkg/Library/BaseUefiImageLib/UeSupport.c
Normal file
234
MdePkg/Library/BaseUefiImageLib/UeSupport.c
Normal file
@ -0,0 +1,234 @@
|
||||
#include <Base.h>
|
||||
#include <Uefi/UefiBaseType.h>
|
||||
#include <Uefi/UefiSpec.h>
|
||||
|
||||
#include <Library/BaseLib.h>
|
||||
#include <Library/BaseMemoryLib.h>
|
||||
#include <Library/BaseOverflowLib.h>
|
||||
#include <Library/DebugLib.h>
|
||||
#include <Library/MemoryAllocationLib.h>
|
||||
#include <Library/UefiImageLib.h>
|
||||
#include <Library/UeImageLib.h>
|
||||
|
||||
STATIC
|
||||
UINT32
|
||||
InternalPermissionsToAttributes (
|
||||
IN UINT32 ImageInfo
|
||||
)
|
||||
{
|
||||
UINT32 Attributes;
|
||||
|
||||
STATIC_ASSERT (
|
||||
(UE_SEGMENT_INFO_RP << 13U) == EFI_MEMORY_RP &&
|
||||
(UE_SEGMENT_INFO_XP << 13U) == EFI_MEMORY_XP &&
|
||||
(UE_SEGMENT_INFO_RO << 15U) == EFI_MEMORY_RO,
|
||||
"The following conversion is incorrect."
|
||||
);
|
||||
|
||||
Attributes = (ImageInfo & (UE_SEGMENT_INFO_RP | UE_SEGMENT_INFO_XP)) << 13U;
|
||||
Attributes |= (ImageInfo & UE_SEGMENT_INFO_RO) << 15U;
|
||||
|
||||
return Attributes;
|
||||
}
|
||||
|
||||
UEFI_IMAGE_RECORD *
|
||||
UefiImageLoaderGetImageRecordUe (
|
||||
IN OUT UE_LOADER_IMAGE_CONTEXT *Context
|
||||
)
|
||||
{
|
||||
UEFI_IMAGE_RECORD *ImageRecord;
|
||||
UINTN ImageAddress;
|
||||
UINT32 NumRecordSegments;
|
||||
UEFI_IMAGE_RECORD_SEGMENT *RecordSegment;
|
||||
UINT16 NumSegments;
|
||||
UINT8 SegmentIterSize;
|
||||
CONST UINT32 *SegmentImageInfos;
|
||||
CONST UINT32 *SegmentImageInfoPtr;
|
||||
UINT32 SegmentImageInfo;
|
||||
UINTN SegmentImageAddress;
|
||||
UINT32 SegmentSize;
|
||||
UINT32 SegmentPermissions;
|
||||
UINT32 RangeSize;
|
||||
UINT32 Permissions;
|
||||
|
||||
ASSERT (Context != NULL);
|
||||
|
||||
NumSegments = 1 + (UINT16) UeGetSegmentImageInfos (
|
||||
Context,
|
||||
&SegmentImageInfos,
|
||||
&SegmentIterSize
|
||||
);
|
||||
|
||||
ImageRecord = AllocatePool (
|
||||
sizeof (*ImageRecord)
|
||||
+ NumSegments * sizeof (*ImageRecord->Segments)
|
||||
);
|
||||
if (ImageRecord == NULL) {
|
||||
DEBUG_RAISE ();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ImageRecord->Signature = UEFI_IMAGE_RECORD_SIGNATURE;
|
||||
InitializeListHead (&ImageRecord->Link);
|
||||
|
||||
SegmentImageInfo = *SegmentImageInfos;
|
||||
|
||||
RangeSize = UE_SEGMENT_SIZE (SegmentImageInfo);
|
||||
Permissions = UE_SEGMENT_PERMISSIONS (SegmentImageInfo);
|
||||
|
||||
SegmentImageAddress = 0;
|
||||
NumRecordSegments = 0;
|
||||
|
||||
STATIC_ASSERT (
|
||||
OFFSET_OF (UE_SEGMENT, ImageInfo) == 0 &&
|
||||
OFFSET_OF (UE_SEGMENT, ImageInfo) == OFFSET_OF (UE_SEGMENT_XIP, ImageInfo),
|
||||
"Below's logic assumes the given layout."
|
||||
);
|
||||
|
||||
for (
|
||||
SegmentImageInfoPtr = (CONST VOID *) ((CONST CHAR8 *) SegmentImageInfos + SegmentIterSize);
|
||||
(CONST CHAR8 *) SegmentImageInfoPtr < (CONST CHAR8 *) SegmentImageInfos + (UINT32) SegmentIterSize * NumSegments;
|
||||
SegmentImageAddress += SegmentSize,
|
||||
SegmentImageInfoPtr = (CONST VOID *) ((CONST CHAR8 *) SegmentImageInfoPtr + SegmentIterSize)
|
||||
) {
|
||||
SegmentImageInfo = *SegmentImageInfoPtr;
|
||||
|
||||
SegmentSize = UE_SEGMENT_SIZE (SegmentImageInfo);
|
||||
SegmentPermissions = UE_SEGMENT_PERMISSIONS (SegmentImageInfo);
|
||||
//
|
||||
// Skip Image segments with the same memory permissions as the current range
|
||||
// as they can be merged.
|
||||
//
|
||||
if (SegmentPermissions == Permissions) {
|
||||
RangeSize += SegmentSize;
|
||||
continue;
|
||||
}
|
||||
//
|
||||
// Create an Image record section for the current memory permission range.
|
||||
//
|
||||
RecordSegment = &ImageRecord->Segments[NumRecordSegments];
|
||||
RecordSegment->Size = RangeSize;
|
||||
RecordSegment->Attributes = InternalPermissionsToAttributes (Permissions);
|
||||
++NumRecordSegments;
|
||||
//
|
||||
// Start a Image record section with the current Image section.
|
||||
//
|
||||
RangeSize = SegmentSize;
|
||||
Permissions = SegmentPermissions;
|
||||
}
|
||||
|
||||
ImageAddress = UeLoaderGetImageAddress (Context);
|
||||
|
||||
ImageRecord->NumSegments = NumRecordSegments;
|
||||
ImageRecord->StartAddress = ImageAddress;
|
||||
ImageRecord->EndAddress = ImageAddress + SegmentImageAddress;
|
||||
//
|
||||
// Zero the remaining array entries to avoid uninitialised data.
|
||||
//
|
||||
ZeroMem (
|
||||
ImageRecord->Segments + NumRecordSegments,
|
||||
(NumSegments - NumRecordSegments) * sizeof (*ImageRecord->Segments)
|
||||
);
|
||||
|
||||
return ImageRecord;
|
||||
}
|
||||
|
||||
RETURN_STATUS
|
||||
UefiImageDebugLocateImageUe (
|
||||
OUT UE_LOADER_IMAGE_CONTEXT *Context,
|
||||
IN UINTN Address
|
||||
)
|
||||
{
|
||||
ASSERT (Context != NULL);
|
||||
(VOID) Address;
|
||||
//
|
||||
// FIXME:
|
||||
// This feature is currently unsupported.
|
||||
//
|
||||
DEBUG_RAISE ();
|
||||
return RETURN_NOT_FOUND;
|
||||
}
|
||||
|
||||
RETURN_STATUS
|
||||
UefiImageGetFixedAddressUe (
|
||||
IN OUT UE_LOADER_IMAGE_CONTEXT *Context,
|
||||
OUT UINT64 *Address
|
||||
)
|
||||
{
|
||||
ASSERT (Context != NULL);
|
||||
ASSERT (Address != NULL);
|
||||
//
|
||||
// This feature is currently unsupported.
|
||||
//
|
||||
DEBUG_RAISE ();
|
||||
return RETURN_NOT_FOUND;
|
||||
}
|
||||
|
||||
// FIXME:
|
||||
RETURN_STATUS
|
||||
InternalGetDebugTable (
|
||||
IN CONST UE_LOADER_IMAGE_CONTEXT *Context,
|
||||
OUT CONST UE_DEBUG_TABLE **DebugTable
|
||||
);
|
||||
|
||||
RETURN_STATUS
|
||||
UefiImageDebugPrintSegmentsUe (
|
||||
IN OUT UE_LOADER_IMAGE_CONTEXT *Context
|
||||
)
|
||||
{
|
||||
RETURN_STATUS DebugStatus;
|
||||
CONST UE_DEBUG_TABLE *DebugTable;
|
||||
CONST CHAR8 *Name;
|
||||
CONST UE_SEGMENT *Segments;
|
||||
UINT8 LastSegmentIndex;
|
||||
UINT8 SegmentIndex;
|
||||
UINT32 SectionFileOffset;
|
||||
UINT32 SegmentImageAddress;
|
||||
CONST UE_SEGMENT_NAME *NameTable;
|
||||
UINT32 ImageSize;
|
||||
|
||||
DebugStatus = InternalGetDebugTable (Context, &DebugTable);
|
||||
LastSegmentIndex = UeGetSegments (Context, &Segments);
|
||||
NameTable = UE_DEBUG_TABLE_SEGMENT_NAMES (DebugTable);
|
||||
SectionFileOffset = UeGetSectionsFileOffset (Context);
|
||||
//
|
||||
// The first Image segment must begin the Image memory space.
|
||||
//
|
||||
SegmentImageAddress = 0;
|
||||
|
||||
for (SegmentIndex = 0; SegmentIndex <= LastSegmentIndex; ++SegmentIndex) {
|
||||
if (!RETURN_ERROR (DebugStatus)) {
|
||||
Name = (CONST CHAR8 *) NameTable[DebugTable->SymbolsPathSize];
|
||||
} else {
|
||||
STATIC_ASSERT (
|
||||
sizeof (*NameTable) == sizeof ("Unknown"),
|
||||
"The following may cause prohibited memory accesses."
|
||||
);
|
||||
|
||||
Name = "Unknown";
|
||||
}
|
||||
|
||||
ImageSize = UE_SEGMENT_SIZE (Segments[SegmentIndex].ImageInfo);
|
||||
|
||||
DEBUG ((
|
||||
DEBUG_VERBOSE,
|
||||
" Segment - '%c%c%c%c%c%c%c%c'\n",
|
||||
" ImageSize - 0x%08x\n"
|
||||
" ImageAddress - 0x%08x\n"
|
||||
" FileSize - 0x%08x\n"
|
||||
" FileOffset - 0x%08x\n"
|
||||
" Permissions - 0x%08x\n",
|
||||
Name[0], Name[1], Name[2], Name[3], Name[4], Name[5], Name[6], Name[7],
|
||||
ImageSize,
|
||||
SegmentImageAddress,
|
||||
Segments[SegmentIndex].FileSize,
|
||||
SectionFileOffset,
|
||||
UE_SEGMENT_PERMISSIONS (Segments[SegmentIndex].ImageInfo)
|
||||
));
|
||||
|
||||
SegmentImageAddress += ImageSize;
|
||||
SectionFileOffset += Segments[SegmentIndex].FileSize;
|
||||
}
|
||||
|
||||
return RETURN_SUCCESS;
|
||||
}
|
29
MdePkg/Library/BaseUefiImageLib/UeSupport.h
Normal file
29
MdePkg/Library/BaseUefiImageLib/UeSupport.h
Normal file
@ -0,0 +1,29 @@
|
||||
#ifndef UE_SUPPORT_H_
|
||||
#define UE_SUPPORT_H_
|
||||
|
||||
#include <Library/UeImageLib.h>
|
||||
#include <Library/UefiImageLib.h>
|
||||
|
||||
UEFI_IMAGE_RECORD *
|
||||
UefiImageLoaderGetImageRecordUe (
|
||||
IN OUT UE_LOADER_IMAGE_CONTEXT *Context
|
||||
);
|
||||
|
||||
RETURN_STATUS
|
||||
UefiImageDebugLocateImageUe (
|
||||
OUT UE_LOADER_IMAGE_CONTEXT *Context,
|
||||
IN UINTN Address
|
||||
);
|
||||
|
||||
RETURN_STATUS
|
||||
UefiImageGetFixedAddressUe (
|
||||
IN OUT UE_LOADER_IMAGE_CONTEXT *Context,
|
||||
OUT UINT64 *Address
|
||||
);
|
||||
|
||||
RETURN_STATUS
|
||||
UefiImageDebugPrintSegmentsUe (
|
||||
IN OUT UE_LOADER_IMAGE_CONTEXT *Context
|
||||
);
|
||||
|
||||
#endif // UE_SUPPORT_H_
|
281
MdePkg/Library/BaseUefiImageLib/UefiImageLibUe.c
Normal file
281
MdePkg/Library/BaseUefiImageLib/UefiImageLibUe.c
Normal file
@ -0,0 +1,281 @@
|
||||
/** @file
|
||||
UEFI Image Loader library implementation for UE Images.
|
||||
|
||||
Copyright (c) 2021, Marvin Häuser. All rights reserved.<BR>
|
||||
|
||||
SPDX-License-Identifier: BSD-3-Clause
|
||||
**/
|
||||
|
||||
#define UEFI_IMAGE_LOADER_IMAGE_CONTEXT UE_LOADER_IMAGE_CONTEXT
|
||||
#define UEFI_IMAGE_LOADER_RUNTIME_CONTEXT UE_LOADER_RUNTIME_CONTEXT
|
||||
|
||||
#include <Base.h>
|
||||
#include <Uefi/UefiBaseType.h>
|
||||
#include <Uefi/UefiSpec.h>
|
||||
|
||||
#include <Library/BaseLib.h>
|
||||
#include <Library/BaseMemoryLib.h>
|
||||
#include <Library/BaseOverflowLib.h>
|
||||
#include <Library/CacheMaintenanceLib.h>
|
||||
#include <Library/DebugLib.h>
|
||||
#include <Library/MemoryAllocationLib.h>
|
||||
#include <Library/UeImageLib.h>
|
||||
#include <Library/PcdLib.h>
|
||||
#include <Library/UefiImageLib.h>
|
||||
|
||||
#include "UeSupport.h"
|
||||
|
||||
RETURN_STATUS
|
||||
UefiImageInitializeContextPreHash (
|
||||
OUT UEFI_IMAGE_LOADER_IMAGE_CONTEXT *Context,
|
||||
IN CONST VOID *FileBuffer,
|
||||
IN UINT32 FileSize
|
||||
)
|
||||
{
|
||||
return UeInitializeContextPreHash (Context, FileBuffer, FileSize);
|
||||
}
|
||||
|
||||
RETURN_STATUS
|
||||
UefiImageInitializeContextPostHash (
|
||||
OUT UEFI_IMAGE_LOADER_IMAGE_CONTEXT *Context
|
||||
)
|
||||
{
|
||||
return UeInitializeContextPostHash (Context);
|
||||
}
|
||||
|
||||
BOOLEAN
|
||||
UefiImageHashImageDefault (
|
||||
IN OUT UEFI_IMAGE_LOADER_IMAGE_CONTEXT *Context,
|
||||
IN OUT VOID *HashContext,
|
||||
IN UEFI_IMAGE_LOADER_HASH_UPDATE HashUpdate
|
||||
)
|
||||
{
|
||||
return UeHashImageDefault (Context, HashContext, HashUpdate);
|
||||
}
|
||||
|
||||
RETURN_STATUS
|
||||
UefiImageLoadImage (
|
||||
IN OUT UEFI_IMAGE_LOADER_IMAGE_CONTEXT *Context,
|
||||
OUT VOID *Destination,
|
||||
IN UINT32 DestinationSize
|
||||
)
|
||||
{
|
||||
return UeLoadImage (Context, Destination, DestinationSize);
|
||||
}
|
||||
|
||||
BOOLEAN
|
||||
UefiImageImageIsInplace (
|
||||
IN OUT UEFI_IMAGE_LOADER_IMAGE_CONTEXT *Context
|
||||
)
|
||||
{
|
||||
ASSERT (Context != NULL);
|
||||
//
|
||||
// FIXME: Implement
|
||||
//
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
RETURN_STATUS
|
||||
UefiImageLoadImageInplace (
|
||||
IN OUT UEFI_IMAGE_LOADER_IMAGE_CONTEXT *Context
|
||||
)
|
||||
{
|
||||
return UeLoadImageInplace (Context);
|
||||
}
|
||||
|
||||
RETURN_STATUS
|
||||
UefiImageLoaderGetRuntimeContextSize (
|
||||
IN OUT UEFI_IMAGE_LOADER_IMAGE_CONTEXT *Context,
|
||||
OUT UINT32 *Size
|
||||
)
|
||||
{
|
||||
return UeLoaderGetRuntimeContextSize (Context, Size);
|
||||
}
|
||||
|
||||
RETURN_STATUS
|
||||
UefiImageRelocateImage (
|
||||
IN OUT UEFI_IMAGE_LOADER_IMAGE_CONTEXT *Context,
|
||||
IN UINT64 BaseAddress,
|
||||
OUT UEFI_IMAGE_LOADER_RUNTIME_CONTEXT *RuntimeContext OPTIONAL,
|
||||
IN UINT32 RuntimeContextSize
|
||||
)
|
||||
{
|
||||
return UeRelocateImage (
|
||||
Context,
|
||||
BaseAddress
|
||||
);
|
||||
}
|
||||
|
||||
RETURN_STATUS
|
||||
UefiImageRuntimeRelocateImage (
|
||||
IN OUT VOID *Image,
|
||||
IN UINT32 ImageSize,
|
||||
IN UINT64 BaseAddress,
|
||||
IN CONST UEFI_IMAGE_LOADER_RUNTIME_CONTEXT *RuntimeContext
|
||||
)
|
||||
{
|
||||
return UeRelocateImageForRuntime (
|
||||
Image,
|
||||
ImageSize,
|
||||
BaseAddress,
|
||||
RuntimeContext
|
||||
);
|
||||
}
|
||||
|
||||
VOID
|
||||
UefiImageDiscardSegments (
|
||||
IN OUT UEFI_IMAGE_LOADER_IMAGE_CONTEXT *Context
|
||||
)
|
||||
{
|
||||
ASSERT (Context != NULL);
|
||||
//
|
||||
// Anything discardable is not loaded in the first place.
|
||||
//
|
||||
}
|
||||
|
||||
RETURN_STATUS
|
||||
UefiImageGetSymbolsPath (
|
||||
IN OUT UEFI_IMAGE_LOADER_IMAGE_CONTEXT *Context,
|
||||
OUT CONST CHAR8 **SymbolsPath,
|
||||
OUT UINT32 *SymbolsPathSize
|
||||
)
|
||||
{
|
||||
return UeGetSymbolsPath (Context, SymbolsPath, SymbolsPathSize);
|
||||
}
|
||||
|
||||
RETURN_STATUS
|
||||
UefiImageGetFirstCertificate (
|
||||
IN OUT UEFI_IMAGE_LOADER_IMAGE_CONTEXT *Context,
|
||||
OUT CONST WIN_CERTIFICATE **Certificate
|
||||
)
|
||||
{
|
||||
return UeGetFirstCertificate (Context, Certificate);
|
||||
}
|
||||
|
||||
RETURN_STATUS
|
||||
UefiImageGetNextCertificate (
|
||||
IN OUT UEFI_IMAGE_LOADER_IMAGE_CONTEXT *Context,
|
||||
IN OUT CONST WIN_CERTIFICATE **Certificate
|
||||
)
|
||||
{
|
||||
return UeGetNextCertificate (Context, Certificate);
|
||||
}
|
||||
|
||||
RETURN_STATUS
|
||||
UefiImageGetHiiDataRva (
|
||||
IN OUT UEFI_IMAGE_LOADER_IMAGE_CONTEXT *Context,
|
||||
OUT UINT32 *HiiRva,
|
||||
OUT UINT32 *HiiSize
|
||||
)
|
||||
{
|
||||
return UeGetHiiDataRva (Context, HiiRva, HiiSize);
|
||||
}
|
||||
|
||||
UINT32
|
||||
UefiImageGetEntryPointAddress (
|
||||
IN OUT UEFI_IMAGE_LOADER_IMAGE_CONTEXT *Context
|
||||
)
|
||||
{
|
||||
return UeGetAddressOfEntryPoint (Context);
|
||||
}
|
||||
|
||||
UINT16
|
||||
UefiImageGetMachine (
|
||||
IN OUT UEFI_IMAGE_LOADER_IMAGE_CONTEXT *Context
|
||||
)
|
||||
{
|
||||
return UeGetMachine (Context);
|
||||
}
|
||||
|
||||
UINT16
|
||||
UefiImageGetSubsystem (
|
||||
IN OUT UEFI_IMAGE_LOADER_IMAGE_CONTEXT *Context
|
||||
)
|
||||
{
|
||||
return UeGetSubsystem (Context);
|
||||
}
|
||||
|
||||
UINT32
|
||||
UefiImageGetSegmentAlignment (
|
||||
IN OUT UEFI_IMAGE_LOADER_IMAGE_CONTEXT *Context
|
||||
)
|
||||
{
|
||||
return UeGetSegmentAlignment (Context);
|
||||
}
|
||||
|
||||
UINT32
|
||||
UefiImageGetImageSize (
|
||||
IN OUT UEFI_IMAGE_LOADER_IMAGE_CONTEXT *Context
|
||||
)
|
||||
{
|
||||
return UeGetImageSize (Context);
|
||||
}
|
||||
|
||||
UINT32
|
||||
UefiImageGetImageSizeInplace (
|
||||
IN OUT UEFI_IMAGE_LOADER_IMAGE_CONTEXT *Context
|
||||
)
|
||||
{
|
||||
return UeGetImageSizeInplace (Context);
|
||||
}
|
||||
|
||||
UINT64
|
||||
UefiImageGetPreferredAddress (
|
||||
IN OUT UEFI_IMAGE_LOADER_IMAGE_CONTEXT *Context
|
||||
)
|
||||
{
|
||||
return UeGetPreferredAddress (Context);
|
||||
}
|
||||
|
||||
BOOLEAN
|
||||
UefiImageGetRelocsStripped (
|
||||
IN OUT UEFI_IMAGE_LOADER_IMAGE_CONTEXT *Context
|
||||
)
|
||||
{
|
||||
return UeGetRelocsStripped (Context);
|
||||
}
|
||||
|
||||
UINTN
|
||||
UefiImageLoaderGetImageAddress (
|
||||
IN OUT UEFI_IMAGE_LOADER_IMAGE_CONTEXT *Context
|
||||
)
|
||||
{
|
||||
return UeLoaderGetImageAddress (Context);
|
||||
}
|
||||
|
||||
UEFI_IMAGE_RECORD *
|
||||
UefiImageLoaderGetImageRecord (
|
||||
IN OUT UEFI_IMAGE_LOADER_IMAGE_CONTEXT *Context
|
||||
)
|
||||
{
|
||||
return UefiImageLoaderGetImageRecordUe (Context);
|
||||
}
|
||||
|
||||
RETURN_STATUS
|
||||
UefiImageDebugLocateImage (
|
||||
OUT UEFI_IMAGE_LOADER_IMAGE_CONTEXT *Context,
|
||||
IN UINTN Address
|
||||
)
|
||||
{
|
||||
return UefiImageDebugLocateImageUe (Context, Address);
|
||||
}
|
||||
|
||||
RETURN_STATUS
|
||||
UefiImageGetFixedAddress (
|
||||
IN OUT UEFI_IMAGE_LOADER_IMAGE_CONTEXT *Context,
|
||||
OUT UINT64 *Address
|
||||
)
|
||||
{
|
||||
return UefiImageGetFixedAddressUe (
|
||||
Context,
|
||||
Address
|
||||
);
|
||||
}
|
||||
|
||||
VOID
|
||||
UefiImageDebugPrintSegments (
|
||||
IN OUT UEFI_IMAGE_LOADER_IMAGE_CONTEXT *Context
|
||||
)
|
||||
{
|
||||
UefiImageDebugPrintSegmentsUe (Context);
|
||||
}
|
@ -16,3 +16,4 @@
|
||||
RegisterFilterLib|MdePkg/Library/RegisterFilterLibNull/RegisterFilterLibNull.inf
|
||||
CpuLib|MdePkg/Library/BaseCpuLib/BaseCpuLib.inf
|
||||
SmmCpuRendezvousLib|MdePkg/Library/SmmCpuRendezvousLibNull/SmmCpuRendezvousLibNull.inf
|
||||
BaseOverflowLib|MdePkg/Library/BaseOverflowLib/BaseOverflowLib.inf
|
||||
|
@ -60,6 +60,8 @@
|
||||
MdePkg/Library/BaseArmTrngLibNull/BaseArmTrngLibNull.inf
|
||||
MdePkg/Library/BasePeCoffLib2/BasePeCoffLib2.inf
|
||||
MdePkg/Library/BaseUefiImageLib/BaseUefiImageLibPeCoff.inf
|
||||
MdePkg/Library/BaseUeImageLib/BaseUeImageLib.inf
|
||||
MdePkg/Library/BaseUefiImageLib/BaseUefiImageLibUe.inf
|
||||
MdePkg/Library/BaseUefiImageExtraActionLibNull/BaseUefiImageExtraActionLibNull.inf
|
||||
MdePkg/Library/BasePerformanceLibNull/BasePerformanceLibNull.inf
|
||||
MdePkg/Library/BasePostCodeLibDebug/BasePostCodeLibDebug.inf
|
||||
|
@ -46,6 +46,10 @@
|
||||
SafeIntLib|MdePkg/Library/BaseSafeIntLib/BaseSafeIntLib.inf
|
||||
RngLib|MdePkg/Library/BaseRngLib/BaseRngLib.inf
|
||||
VariablePolicyHelperLib|MdeModulePkg/Library/VariablePolicyHelperLib/VariablePolicyHelperLib.inf
|
||||
PeCoffLib2|MdePkg/Library/BasePeCoffLib2/BasePeCoffLib2.inf
|
||||
UefiImageLib|MdePkg/Library/BaseUefiImageLib/BaseUefiImageLibPeCoff.inf
|
||||
CacheMaintenanceLib|MdePkg/Library/BaseCacheMaintenanceLib/BaseCacheMaintenanceLib.inf
|
||||
UefiImageExtraActionLib|MdePkg/Library/BaseUefiImageExtraActionLibNull/BaseUefiImageExtraActionLibNull.inf
|
||||
|
||||
!ifdef CONTINUOUS_INTEGRATION
|
||||
BaseCryptLib|CryptoPkg/Library/BaseCryptLibNull/BaseCryptLibNull.inf
|
||||
|
1
OpenCorePkg
Submodule
1
OpenCorePkg
Submodule
@ -0,0 +1 @@
|
||||
Subproject commit 1d65bf850099bc0d8cc3b282bebd16310a3ab487
|
@ -146,7 +146,6 @@
|
||||
PrintLib|MdePkg/Library/BasePrintLib/BasePrintLib.inf
|
||||
BaseMemoryLib|MdePkg/Library/BaseMemoryLibRepStr/BaseMemoryLibRepStr.inf
|
||||
BaseLib|MdePkg/Library/BaseLib/BaseLib.inf
|
||||
BaseOverflowLib|MdePkg/Library/BaseOverflowLib/BaseOverflowLib.inf
|
||||
SafeIntLib|MdePkg/Library/BaseSafeIntLib/BaseSafeIntLib.inf
|
||||
TimeBaseLib|EmbeddedPkg/Library/TimeBaseLib/TimeBaseLib.inf
|
||||
BmpSupportLib|MdeModulePkg/Library/BaseBmpSupportLib/BaseBmpSupportLib.inf
|
||||
@ -600,14 +599,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
|
||||
|
||||
################################################################################
|
||||
|
@ -143,7 +143,6 @@
|
||||
PrintLib|MdePkg/Library/BasePrintLib/BasePrintLib.inf
|
||||
BaseMemoryLib|MdePkg/Library/BaseMemoryLibRepStr/BaseMemoryLibRepStr.inf
|
||||
BaseLib|MdePkg/Library/BaseLib/BaseLib.inf
|
||||
BaseOverflowLib|MdePkg/Library/BaseOverflowLib/BaseOverflowLib.inf
|
||||
SafeIntLib|MdePkg/Library/BaseSafeIntLib/BaseSafeIntLib.inf
|
||||
TimeBaseLib|EmbeddedPkg/Library/TimeBaseLib/TimeBaseLib.inf
|
||||
BmpSupportLib|MdeModulePkg/Library/BaseBmpSupportLib/BaseBmpSupportLib.inf
|
||||
@ -604,14 +603,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
|
||||
|
||||
################################################################################
|
||||
|
@ -62,10 +62,10 @@ FV = SECFV
|
||||
|
||||
[FD.MEMFD]
|
||||
BaseAddress = $(MEMFD_BASE_ADDRESS)
|
||||
Size = 0xD00000
|
||||
Size = 0xE00000
|
||||
ErasePolarity = 1
|
||||
BlockSize = 0x10000
|
||||
NumBlocks = 0xD0
|
||||
NumBlocks = 0xE0
|
||||
|
||||
0x000000|0x006000
|
||||
gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecPageTablesBase|gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecPageTablesSize
|
||||
@ -86,7 +86,7 @@ gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecPeiTempRamBase|gUefiOvmfPkgTokenSpaceGuid.P
|
||||
gUefiOvmfPkgTokenSpaceGuid.PcdOvmfPeiMemFvBase|gUefiOvmfPkgTokenSpaceGuid.PcdOvmfPeiMemFvSize
|
||||
FV = PEIFV
|
||||
|
||||
0x100000|0xC00000
|
||||
0x100000|0xD00000
|
||||
gUefiOvmfPkgTokenSpaceGuid.PcdOvmfDxeMemFvBase|gUefiOvmfPkgTokenSpaceGuid.PcdOvmfDxeMemFvSize
|
||||
FV = DXEFV
|
||||
|
||||
|
@ -166,7 +166,6 @@
|
||||
PrintLib|MdePkg/Library/BasePrintLib/BasePrintLib.inf
|
||||
BaseMemoryLib|MdePkg/Library/BaseMemoryLibRepStr/BaseMemoryLibRepStr.inf
|
||||
BaseLib|MdePkg/Library/BaseLib/BaseLib.inf
|
||||
BaseOverflowLib|MdePkg/Library/BaseOverflowLib/BaseOverflowLib.inf
|
||||
SafeIntLib|MdePkg/Library/BaseSafeIntLib/BaseSafeIntLib.inf
|
||||
TimeBaseLib|EmbeddedPkg/Library/TimeBaseLib/TimeBaseLib.inf
|
||||
BmpSupportLib|MdeModulePkg/Library/BaseBmpSupportLib/BaseBmpSupportLib.inf
|
||||
@ -633,10 +632,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
|
||||
|
||||
|
@ -82,6 +82,14 @@
|
||||
## SOMETIMES_PRODUCES ## GUID # Unique ID for the type of the signature.
|
||||
gEfiCertSha256Guid
|
||||
|
||||
## SOMETIMES_CONSUMES ## GUID # Unique ID for the type of the signature.
|
||||
## SOMETIMES_PRODUCES ## GUID # Unique ID for the type of the signature.
|
||||
gEfiCertSha384Guid
|
||||
|
||||
## SOMETIMES_CONSUMES ## GUID # Unique ID for the type of the signature.
|
||||
## SOMETIMES_PRODUCES ## GUID # Unique ID for the type of the signature.
|
||||
gEfiCertSha512Guid
|
||||
|
||||
## SOMETIMES_CONSUMES ## Variable:L"db"
|
||||
## SOMETIMES_PRODUCES ## Variable:L"db"
|
||||
## SOMETIMES_CONSUMES ## Variable:L"dbx"
|
||||
|
@ -1983,7 +1983,7 @@ EnrollImageSignatureToSigDB (
|
||||
Status = UefiImageGetFirstCertificate (&ImageContext, &Certificate);
|
||||
|
||||
if (Status == RETURN_NOT_FOUND) {
|
||||
if (!HashPeImage (&ImageContext, HASHALG_SHA256, ImageDigest, &ImageDigestSize, &CertType)) {
|
||||
if (!HashPeImage (&ImageContext, HASHALG_SHA256, ImageDigest, &ImageDigestSize)) {
|
||||
Status = EFI_SECURITY_VIOLATION;
|
||||
goto ON_EXIT;
|
||||
}
|
||||
@ -1995,7 +1995,7 @@ EnrollImageSignatureToSigDB (
|
||||
goto ON_EXIT;
|
||||
}
|
||||
|
||||
if (!HashPeImage (&ImageContext, HASHALG_SHA256, ImageDigest, &ImageDigestSize, &CertType)) {
|
||||
if (!HashPeImage (&ImageContext, HASHALG_SHA256, ImageDigest, &ImageDigestSize)) {
|
||||
Status = EFI_ABORTED;
|
||||
goto ON_EXIT;
|
||||
}
|
||||
|
@ -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
|
@ -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.
|
||||
//
|
||||
}
|
@ -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
|
||||
|
@ -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."
|
||||
|
@ -315,7 +315,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
|
||||
|
@ -1,32 +0,0 @@
|
||||
-Wall
|
||||
-Wextra
|
||||
-Wpedantic
|
||||
-Wno-missing-prototypes
|
||||
-Wcast-align
|
||||
-Wcast-qual
|
||||
-Wextra-semi-stmt
|
||||
-Wshorten-64-to-32
|
||||
-Wshift-sign-overflow
|
||||
-Wsign-compare
|
||||
-Wsign-conversion
|
||||
-Wsigned-enum-bitfield
|
||||
-Wconditional-uninitialized
|
||||
-Wimplicit-int-conversion
|
||||
|
||||
-fshort-wchar
|
||||
-target
|
||||
x86_64-unknown-windows-gnu
|
||||
|
||||
-IMdePkg/Include
|
||||
-IMdeModulePkg/Include
|
||||
-IMdePkg/Include/X64
|
||||
-IUefiCpuPkg/Include
|
||||
-IMdeModulePkg/Core/Dxe
|
||||
-IMdeModulePkg/Core/Pei
|
||||
-ISecurityPkg/Include
|
||||
-IArmPkg/Include
|
||||
-IArmPlatformPkg/Include
|
||||
-IStandaloneMmPkg/Include
|
||||
-ICryptoPkg/Include
|
||||
-IEmbeddedPkg/Include
|
||||
-includeUefi.h
|
@ -72,6 +72,7 @@ function SetWorkspace()
|
||||
# Set $WORKSPACE
|
||||
#
|
||||
export WORKSPACE=$PWD
|
||||
export PACKAGES_PATH=$PWD
|
||||
return 0
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user