mirror of
https://github.com/acidanthera/audk.git
synced 2025-09-26 02:58:39 +02:00
BaseTools: Replaced GenFw with ImageTool and MicroTool.
This commit is contained in:
parent
29ab261538
commit
1e0cdd036d
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
|
||||
|
@ -26,12 +26,9 @@
|
||||
DEFINE FD_NUM_BLOCKS = 0x300
|
||||
!endif
|
||||
|
||||
[BuildOptions.common.EDKII.DXE_CORE,BuildOptions.common.EDKII.DXE_DRIVER,BuildOptions.common.EDKII.UEFI_DRIVER,BuildOptions.common.EDKII.UEFI_APPLICATION]
|
||||
GCC:*_*_*_DLINK_FLAGS = -z common-page-size=0x1000
|
||||
|
||||
[BuildOptions.common.EDKII.DXE_RUNTIME_DRIVER]
|
||||
GCC:*_*_ARM_DLINK_FLAGS = -z common-page-size=0x1000
|
||||
GCC:*_*_AARCH64_DLINK_FLAGS = -z common-page-size=0x10000
|
||||
GCC:*_*_ARM_DLINK_FLAGS = -z max-page-size=0x1000
|
||||
GCC:*_*_AARCH64_DLINK_FLAGS = -z max-page-size=0x10000
|
||||
|
||||
[LibraryClasses.common]
|
||||
!if $(TARGET) == RELEASE
|
||||
|
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' ] || [ $1 == 'ARM' ]
|
||||
then
|
||||
if [ ! -e "$EDK_TOOLS_PATH/ImageTool/ImageTool32" ]
|
||||
then
|
||||
echo "BaseTools C Tool binary was not found (ImageTool32)"
|
||||
echo "You may need to run:"
|
||||
echo " make -C $EDK_TOOLS_PATH/ImageTool"
|
||||
else
|
||||
shift
|
||||
exec "$EDK_TOOLS_PATH/ImageTool/ImageTool32" "$@"
|
||||
fi
|
||||
elif [ $1 == 'X64' ] || [ $1 == 'AARCH64' ]
|
||||
then
|
||||
if [ ! -e "$EDK_TOOLS_PATH/ImageTool/ImageTool64" ]
|
||||
then
|
||||
echo "BaseTools C Tool binary was not found (ImageTool64)"
|
||||
echo "You may need to run:"
|
||||
echo " make -C $EDK_TOOLS_PATH/ImageTool"
|
||||
else
|
||||
shift
|
||||
exec "$EDK_TOOLS_PATH/ImageTool/ImageTool64" "$@"
|
||||
fi
|
||||
else
|
||||
echo "ImageTool for $1 is not supported"
|
||||
exit 127
|
||||
fi
|
||||
else
|
||||
echo "Unable to find the real '$cmd' to run"
|
||||
echo "This message was printed by"
|
||||
echo " $0"
|
||||
exit 127
|
||||
fi
|
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
|
30
BaseTools/BinWrappers/WindowsLike/ImageTool.bat
Normal file
30
BaseTools/BinWrappers/WindowsLike/ImageTool.bat
Normal file
@ -0,0 +1,30 @@
|
||||
::
|
||||
:: Copyright (c) 2022, Mikhail Krichanov. All rights reserved.
|
||||
:: SPDX-License-Identifier: BSD-3-Clause
|
||||
::
|
||||
@echo off
|
||||
set args=%2
|
||||
:start
|
||||
shift /2
|
||||
if "%2"=="" goto done
|
||||
set args=%args% %2
|
||||
goto start
|
||||
|
||||
:done
|
||||
if "%1%"=="IA32" (
|
||||
call ImageTool32.exe %args%
|
||||
exit
|
||||
)
|
||||
if "%1%"=="ARM" (
|
||||
call ImageTool32.exe %args%
|
||||
exit
|
||||
)
|
||||
if "%1%"=="X64" (
|
||||
call ImageTool64.exe %args%
|
||||
exit
|
||||
)
|
||||
if "%1%"=="AARCH64" (
|
||||
call ImageTool64.exe %args%
|
||||
exit
|
||||
)
|
||||
echo ImageTool for %1% is not supported
|
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)
|
||||
|
||||
@ -295,12 +302,11 @@
|
||||
|
||||
<Command.GCC>
|
||||
"$(DLINK)" -o ${dst} $(DLINK_FLAGS) -Wl,--start-group,@$(STATIC_LIBRARY_FILES_LIST),--end-group $(CC_FLAGS) $(DLINK2_FLAGS)
|
||||
"$(OBJCOPY)" $(OBJCOPY_FLAGS) ${dst}
|
||||
|
||||
<Command.XCODE>
|
||||
"$(DLINK)" $(DLINK_FLAGS) -o ${dst} $(DLINK_SPATH) -filelist $(STATIC_LIBRARY_FILES_LIST) $(DLINK2_FLAGS)
|
||||
|
||||
|
||||
|
||||
|
||||
[Static-Library-File.SEC.AARCH64, Static-Library-File.PEI_CORE.AARCH64, Static-Library-File.PEIM.AARCH64,Static-Library-File.SEC.ARM, Static-Library-File.PEI_CORE.ARM, Static-Library-File.PEIM.ARM]
|
||||
<InputFile>
|
||||
*.lib
|
||||
@ -313,8 +319,6 @@
|
||||
|
||||
<Command.GCC>
|
||||
"$(DLINK)" -o ${dst} $(DLINK_FLAGS) $(DLINK_XIPFLAGS) -Wl,--start-group,@$(STATIC_LIBRARY_FILES_LIST),--end-group $(CC_FLAGS) $(CC_XIPFLAGS) $(DLINK2_FLAGS)
|
||||
"$(OBJCOPY)" $(OBJCOPY_FLAGS) ${dst}
|
||||
|
||||
|
||||
[Static-Library-File.USER_DEFINED, Static-Library-File.HOST_APPLICATION]
|
||||
<InputFile>
|
||||
@ -334,8 +338,8 @@
|
||||
|
||||
<Command.XCODE>
|
||||
"$(DLINK)" -o ${dst} $(DLINK_FLAGS) $(DLINK_SPATH) -filelist $(STATIC_LIBRARY_FILES_LIST) $(DLINK2_FLAGS)
|
||||
|
||||
|
||||
|
||||
|
||||
[Dynamic-Library-File]
|
||||
<InputFile>
|
||||
?.dll
|
||||
@ -345,32 +349,33 @@
|
||||
$(OUTPUT_DIR)(+)$(MODULE_NAME).map
|
||||
|
||||
<Command.MSFT, Command.INTEL, Command.CLANGPDB>
|
||||
"$(GENFW)" -e $(MODULE_TYPE) -o ${dst} ${src} $(GENFW_FLAGS)
|
||||
ImageTool $(ARCH) PeXip ${src} ${dst} $(MODULE_TYPE)
|
||||
$(CP) ${dst} $(DEBUG_DIR)
|
||||
$(CP) ${dst} $(BIN_DIR)(+)$(MODULE_NAME_GUID).efi
|
||||
-$(CP) $(DEBUG_DIR)(+)*.map $(OUTPUT_DIR)
|
||||
-$(CP) $(DEBUG_DIR)(+)*.pdb $(OUTPUT_DIR)
|
||||
<Command.GCC>
|
||||
-$(CP) $(DEBUG_DIR)(+)*.pdb $(OUTPUT_DIR)
|
||||
|
||||
<Command.GCC, Command.CLANGGCC>
|
||||
$(CP) ${src} $(DEBUG_DIR)(+)$(MODULE_NAME).debug
|
||||
$(OBJCOPY) $(OBJCOPY_STRIPFLAG) ${src}
|
||||
|
||||
#
|
||||
#The below 2 lines are only needed for UNIXGCC tool chain, which generates PE image directly
|
||||
# The below 2 lines are only needed for UNIXGCC tool chain, which generates PE image directly
|
||||
#
|
||||
-$(OBJCOPY) $(OBJCOPY_ADDDEBUGFLAG) ${src}
|
||||
-$(CP) $(DEBUG_DIR)(+)$(MODULE_NAME).debug $(BIN_DIR)(+)$(MODULE_NAME_GUID).debug
|
||||
ImageTool $(ARCH) ElfToPe ${src} ${dst} $(MODULE_TYPE)
|
||||
|
||||
"$(GENFW)" -e $(MODULE_TYPE) -o ${dst} ${src} $(GENFW_FLAGS)
|
||||
$(CP) ${dst} $(DEBUG_DIR)
|
||||
$(CP) ${dst} $(BIN_DIR)(+)$(MODULE_NAME_GUID).efi
|
||||
-$(CP) $(DEBUG_DIR)(+)*.map $(OUTPUT_DIR)
|
||||
|
||||
|
||||
<Command.XCODE>
|
||||
# tool to convert Mach-O to PE/COFF
|
||||
"$(MTOC)" -subsystem $(MODULE_TYPE) $(MTOC_FLAGS) ${src} $(DEBUG_DIR)(+)$(MODULE_NAME).pecoff
|
||||
# create symbol file for GDB debug
|
||||
-$(DSYMUTIL) ${src}
|
||||
"$(GENFW)" -e $(MODULE_TYPE) -o ${dst} $(DEBUG_DIR)(+)$(MODULE_NAME).pecoff $(GENFW_FLAGS)
|
||||
ImageTool $(ARCH) PeXip $(DEBUG_DIR)(+)$(MODULE_NAME).pecoff ${dst} $(MODULE_TYPE)
|
||||
$(CP) ${dst} $(DEBUG_DIR)
|
||||
$(CP) ${dst} $(BIN_DIR)(+)$(MODULE_NAME_GUID).efi
|
||||
-$(CP) $(DEBUG_DIR)(+)*.map $(OUTPUT_DIR)
|
||||
@ -404,14 +409,14 @@
|
||||
<Command.MSFT, Command.INTEL>
|
||||
Trim --asl-file --asl-deps -o $(OUTPUT_DIR)(+)${s_dir}(+)${s_base}.i -i $(INC_LIST) ${src}
|
||||
"$(ASLPP)" $(DEPS_FLAGS) $(ASLPP_FLAGS) $(INC) /I${s_path} $(OUTPUT_DIR)(+)${s_dir}(+)${s_base}.i > $(OUTPUT_DIR)(+)${s_dir}(+)${s_base}.iii
|
||||
Trim --source-code -l -o $(OUTPUT_DIR)(+)${s_dir}(+)${s_base}.iiii $(OUTPUT_DIR)(+)${s_dir}(+)${s_base}.iii
|
||||
Trim --source-code -l -o $(OUTPUT_DIR)(+)${s_dir}(+)${s_base}.iiii $(OUTPUT_DIR)(+)${s_dir}(+)${s_base}.iii
|
||||
"$(ASL)" $(ASL_FLAGS) $(ASL_OUTFLAGS)${dst} $(OUTPUT_DIR)(+)${s_dir}(+)${s_base}.iiii
|
||||
$(CP) $(OUTPUT_DIR)(+)${s_dir}(+)${s_base}.aml $(OUTPUT_DIR)(+)${s_dir}(+)${s_base}.amli
|
||||
|
||||
<Command.GCC>
|
||||
Trim --asl-file --asl-deps -o $(OUTPUT_DIR)(+)${s_dir}(+)${s_base}.i -i $(INC_LIST) ${src}
|
||||
"$(ASLPP)" $(DEPS_FLAGS) $(ASLPP_FLAGS) $(INC) -I${s_path} $(OUTPUT_DIR)(+)${s_dir}(+)${s_base}.i > $(OUTPUT_DIR)(+)${s_dir}(+)${s_base}.iii
|
||||
Trim --source-code -l -o $(OUTPUT_DIR)(+)${s_dir}(+)${s_base}.iiii $(OUTPUT_DIR)(+)${s_dir}(+)${s_base}.iii
|
||||
Trim --source-code -l -o $(OUTPUT_DIR)(+)${s_dir}(+)${s_base}.iiii $(OUTPUT_DIR)(+)${s_dir}(+)${s_base}.iii
|
||||
"$(ASL)" $(ASL_FLAGS) $(ASL_OUTFLAGS)${dst} $(OUTPUT_DIR)(+)${s_dir}(+)${s_base}.iiii
|
||||
$(CP) $(OUTPUT_DIR)(+)${s_dir}(+)${s_base}.aml $(OUTPUT_DIR)(+)${s_dir}(+)${s_base}.amli
|
||||
|
||||
@ -438,12 +443,12 @@
|
||||
<Command.MSFT, Command.INTEL>
|
||||
"$(ASLCC)" $(DEPS_FLAGS) /Fo$(OUTPUT_DIR)(+)${s_dir}(+)${s_base}.obj $(ASLCC_FLAGS) $(DEPS_FLAGS) $(INC) ${src}
|
||||
"$(ASLDLINK)" /OUT:$(OUTPUT_DIR)(+)${s_dir}(+)${s_base}.dll $(ASLDLINK_FLAGS) $(OUTPUT_DIR)(+)${s_dir}(+)${s_base}.obj
|
||||
"$(GENFW)" -o ${dst} -c $(OUTPUT_DIR)(+)${s_dir}(+)${s_base}.dll $(GENFW_FLAGS)
|
||||
ImageTool $(ARCH) GetAcpi $(OUTPUT_DIR)(+)${s_dir}(+)${s_base}.dll ${dst}
|
||||
|
||||
<Command.GCC>
|
||||
"$(ASLCC)" $(DEPS_FLAGS) -c -o $(OUTPUT_DIR)(+)${s_dir}(+)${s_base}.obj $(CC_FLAGS) $(ASLCC_FLAGS) $(DEPS_FLAGS) $(INC) ${src}
|
||||
"$(ASLDLINK)" -o $(OUTPUT_DIR)(+)${s_dir}(+)${s_base}.dll $(ASLDLINK_FLAGS) $(OUTPUT_DIR)(+)${s_dir}(+)${s_base}.obj
|
||||
"$(GENFW)" -o ${dst} -c $(OUTPUT_DIR)(+)${s_dir}(+)${s_base}.dll $(GENFW_FLAGS)
|
||||
ImageTool $(ARCH) GetAcpi $(OUTPUT_DIR)(+)${s_dir}(+)${s_base}.dll ${dst}
|
||||
|
||||
[Acpi-Table-Code-File]
|
||||
<InputFile>
|
||||
@ -458,25 +463,24 @@
|
||||
<Command.MSFT, Command.INTEL>
|
||||
"$(ASLCC)" $(DEPS_FLAGS) /Fo$(OUTPUT_DIR)(+)${s_dir}(+)${s_base}.obj $(ASLCC_FLAGS) $(DEPS_FLAGS) $(INC) ${src}
|
||||
"$(ASLDLINK)" /OUT:$(OUTPUT_DIR)(+)${s_dir}(+)${s_base}.dll $(ASLDLINK_FLAGS) $(OUTPUT_DIR)(+)${s_dir}(+)${s_base}.obj
|
||||
"$(GENFW)" -o ${dst} -c $(OUTPUT_DIR)(+)${s_dir}(+)${s_base}.dll $(GENFW_FLAGS)
|
||||
ImageTool $(ARCH) GetAcpi $(OUTPUT_DIR)(+)${s_dir}(+)${s_base}.dll ${dst}
|
||||
|
||||
<Command.GCC>
|
||||
"$(ASLCC)" $(DEPS_FLAGS) -c -o $(OUTPUT_DIR)(+)${s_dir}(+)${s_base}.obj $(CC_FLAGS) $(ASLCC_FLAGS) $(DEPS_FLAGS) $(INC) ${src}
|
||||
"$(ASLDLINK)" -o $(OUTPUT_DIR)(+)${s_dir}(+)${s_base}.dll $(ASLDLINK_FLAGS) $(OUTPUT_DIR)(+)${s_dir}(+)${s_base}.obj
|
||||
"$(GENFW)" -o ${dst} -c $(OUTPUT_DIR)(+)${s_dir}(+)${s_base}.dll $(GENFW_FLAGS)
|
||||
"$(ASLDLINK)" -o $(OUTPUT_DIR)(+)${s_dir}(+)${s_base}.dll $(ASLDLINK_FLAGS) $(OUTPUT_DIR)(+)${s_dir}(+)${s_base}.obj $(CC_FLAGS) $(ASLCC_FLAGS)
|
||||
ImageTool $(ARCH) GetAcpi $(OUTPUT_DIR)(+)${s_dir}(+)${s_base}.dll ${dst}
|
||||
|
||||
<Command.CLANGPDB>
|
||||
"$(ASLCC)" $(DEPS_FLAGS) -c -o $(OUTPUT_DIR)(+)${s_dir}(+)${s_base}.obj $(CC_FLAGS) $(ASLCC_FLAGS) $(DEPS_FLAGS) $(INC) ${src}
|
||||
"$(ASLDLINK)" /OUT:$(OUTPUT_DIR)(+)${s_dir}(+)${s_base}.dll $(ASLDLINK_FLAGS) $(OUTPUT_DIR)(+)${s_dir}(+)${s_base}.obj
|
||||
"$(GENFW)" -o ${dst} -c $(OUTPUT_DIR)(+)${s_dir}(+)${s_base}.dll $(GENFW_FLAGS)
|
||||
ImageTool $(ARCH) GetAcpi $(OUTPUT_DIR)(+)${s_dir}(+)${s_base}.dll ${dst}
|
||||
|
||||
<Command.XCODE>
|
||||
<Command.XCODE>
|
||||
"$(ASLCC)" $(DEPS_FLAGS) -o $(OUTPUT_DIR)(+)${s_dir}(+)${s_base}.obj $(ASLCC_FLAGS) $(DEPS_FLAGS) $(INC) ${src}
|
||||
"$(ASLDLINK)" -o $(OUTPUT_DIR)(+)${s_dir}(+)${s_base}.dll $(ASLDLINK_FLAGS) $(OUTPUT_DIR)(+)${s_dir}(+)${s_base}.obj
|
||||
"$(MTOC)" -subsystem $(MODULE_TYPE) $(MTOC_FLAGS) $(OUTPUT_DIR)(+)${s_dir}(+)${s_base}.dll $(OUTPUT_DIR)(+)${s_dir}(+)${s_base}.pecoff
|
||||
"$(GENFW)" -o ${dst} -c $(OUTPUT_DIR)(+)${s_dir}(+)${s_base}.pecoff $(GENFW_FLAGS)
|
||||
|
||||
|
||||
ImageTool $(ARCH) GetAcpi $(OUTPUT_DIR)(+)${s_dir}(+)${s_base}.pecoff ${dst}
|
||||
|
||||
[Masm16-Code-File]
|
||||
<InputFile>
|
||||
?.asm16, ?.Asm16, ?.ASM16, ?.s16, ?.S16
|
||||
@ -501,7 +505,7 @@
|
||||
Trim --source-code -o ${d_path}(+)${s_base}.iii ${d_path}(+)${s_base}.ii
|
||||
"$(ASM)" -o $(OUTPUT_DIR)(+)${s_dir}(+)${s_base}.obj $(ASM_FLAGS) $(INC) ${d_path}(+)${s_base}.iii
|
||||
"$(DLINK)" -o ${dst} $(DLINK_FLAGS) --start-group $(DLINK_SPATH) $(LIBS) $(OUTPUT_DIR)(+)${s_dir}(+)${s_base}.obj --end-group
|
||||
|
||||
|
||||
<Command.XCODE>
|
||||
Trim --asm-file -o ${d_path}(+)${s_base}.i -i $(INC_LIST) ${src}
|
||||
"$(PP)" $(DEPS_FLAGS) $(PP_FLAGS) $(INC) ${src} > ${d_path}(+)${s_base}.ii
|
||||
@ -509,7 +513,7 @@
|
||||
"$(ASM)" -o $(OUTPUT_DIR)(+)${s_dir}(+)${s_base}.obj $(ASM_FLAGS) $(INC) ${d_path}(+)${s_base}.iii
|
||||
"$(SLINK)" $(SLINK_FLAGS) $(OUTPUT_DIR)(+)${s_dir}(+)${s_base}.slib $(OUTPUT_DIR)(+)${s_dir}(+)${s_base}.obj
|
||||
otool -t $(OUTPUT_DIR)(+)${s_dir}(+)${s_base}.slib | hex2bin.py ${dst}
|
||||
|
||||
|
||||
|
||||
[Nasm-to-Binary-Code-File]
|
||||
<InputFile>
|
||||
@ -537,7 +541,7 @@
|
||||
$(OUTPUT_DIR)(+)${s_base}.mcb
|
||||
|
||||
<Command>
|
||||
"$(GENFW)" -o ${dst} -m ${src} $(GENFW_FLAGS)
|
||||
MicroTool TxtToBin ${src} ${dst}
|
||||
|
||||
[Microcode-Binary-File]
|
||||
<InputFile>
|
||||
@ -550,7 +554,7 @@
|
||||
$(OUTPUT_DIR)(+)$(MODULE_NAME).bin
|
||||
|
||||
<Command>
|
||||
"$(GENFW)" -o ${dst} -j $(MICROCODE_BINARY_FILES) $(GENFW_FLAGS)
|
||||
MicroTool Merge ${dst} $(MICROCODE_BINARY_FILES)
|
||||
-$(CP) ${dst} $(BIN_DIR)(+)$(MODULE_NAME_GUID).bin
|
||||
|
||||
[EFI-Image-File]
|
||||
@ -639,13 +643,17 @@
|
||||
<OutputFile.XCODE>
|
||||
$(OUTPUT_DIR)(+)$(MODULE_NAME)hii.rc
|
||||
|
||||
<Command.MSFT, Command.INTEL, Command.CLANGPDB>
|
||||
"$(GENFW)" -o $(OUTPUT_DIR)(+)$(MODULE_NAME)hii.rc -g $(MODULE_GUID) --hiipackage $(HII_BINARY_PACKAGES) $(GENFW_FLAGS)
|
||||
<Command.CLANGPDB>
|
||||
ImageTool $(ARCH) HiiBinPe $(OUTPUT_DIR)(+)$(MODULE_NAME)hii.rc $(MODULE_GUID) $(HII_BINARY_PACKAGES)
|
||||
"$(RC)" /Fo${dst} -- $(OUTPUT_DIR)(+)$(MODULE_NAME)hii.rc
|
||||
|
||||
<Command.MSFT, Command.INTEL>
|
||||
ImageTool $(ARCH) HiiBinPe $(OUTPUT_DIR)(+)$(MODULE_NAME)hii.rc $(MODULE_GUID) $(HII_BINARY_PACKAGES)
|
||||
"$(RC)" /Fo${dst} $(OUTPUT_DIR)(+)$(MODULE_NAME)hii.rc
|
||||
|
||||
<Command.GCC, Command.CLANGGCC>
|
||||
"$(GENFW)" -o $(OUTPUT_DIR)(+)$(MODULE_NAME)hii.rc -g $(MODULE_GUID) --hiibinpackage $(HII_BINARY_PACKAGES) $(GENFW_FLAGS)
|
||||
ImageTool $(ARCH) HiiBinElf $(OUTPUT_DIR)(+)$(MODULE_NAME)hii.rc $(MODULE_GUID) $(HII_BINARY_PACKAGES)
|
||||
"$(RC)" $(RC_FLAGS) $(OUTPUT_DIR)(+)$(MODULE_NAME)hii.rc ${dst}
|
||||
|
||||
<Command.XCODE>
|
||||
"$(GENFW)" -o $(OUTPUT_DIR)(+)$(MODULE_NAME)hii.rc -g $(MODULE_GUID) --hiibinpackage $(HII_BINARY_PACKAGES) $(GENFW_FLAGS)
|
||||
ImageTool $(ARCH) HiiBinElf $(OUTPUT_DIR)(+)$(MODULE_NAME)hii.rc $(MODULE_GUID) $(HII_BINARY_PACKAGES)
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -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;
|
||||
}
|
734
BaseTools/ImageTool/ElfScan.c
Normal file
734
BaseTools/ImageTool/ElfScan.c
Normal file
@ -0,0 +1,734 @@
|
||||
/** @file
|
||||
Copyright (c) 2022, Mikhail Krichanov. All rights reserved.
|
||||
SPDX-License-Identifier: BSD-3-Clause
|
||||
**/
|
||||
|
||||
#include "ImageTool.h"
|
||||
|
||||
static Elf_Ehdr *mEhdr = NULL;
|
||||
static Elf_Size mPeAlignment = 0x0;
|
||||
static Elf_Addr mBaseAddress = 0x0;
|
||||
static bool mHasPieRelocs = FALSE;
|
||||
|
||||
#if defined (_MSC_EXTENSIONS)
|
||||
#define EFI_IMAGE_MACHINE_IA32 0x014C
|
||||
#define EFI_IMAGE_MACHINE_X64 0x8664
|
||||
#define EFI_IMAGE_MACHINE_ARMTHUMB_MIXED 0x01C2
|
||||
#define EFI_IMAGE_MACHINE_AARCH64 0xAA64
|
||||
#endif
|
||||
|
||||
extern image_tool_image_info_t mImageInfo;
|
||||
|
||||
static
|
||||
Elf_Shdr *
|
||||
GetShdrByIndex (
|
||||
IN UINT32 Index
|
||||
)
|
||||
{
|
||||
UINTN Offset;
|
||||
|
||||
assert (Index < mEhdr->e_shnum);
|
||||
|
||||
Offset = (UINTN)mEhdr->e_shoff + Index * mEhdr->e_shentsize;
|
||||
|
||||
return (Elf_Shdr *)((UINT8 *)mEhdr + Offset);
|
||||
}
|
||||
|
||||
static
|
||||
char *
|
||||
GetString (
|
||||
IN UINT32 Offset,
|
||||
IN UINT32 Index
|
||||
)
|
||||
{
|
||||
const Elf_Shdr *Shdr;
|
||||
char *String;
|
||||
|
||||
if (Index == 0) {
|
||||
Shdr = GetShdrByIndex (mEhdr->e_shstrndx);
|
||||
} else {
|
||||
Shdr = GetShdrByIndex (Index);
|
||||
}
|
||||
|
||||
if (Offset >= Shdr->sh_size) {
|
||||
fprintf (stderr, "ImageTool: Invalid ELF string offset\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
String = (char *)((UINT8 *)mEhdr + Shdr->sh_offset + Offset);
|
||||
|
||||
return String;
|
||||
}
|
||||
|
||||
static
|
||||
BOOLEAN
|
||||
IsHiiRsrcShdr (
|
||||
IN const Elf_Shdr *Shdr
|
||||
)
|
||||
{
|
||||
assert (Shdr != NULL);
|
||||
|
||||
Elf_Shdr *Namedr = GetShdrByIndex (mEhdr->e_shstrndx);
|
||||
|
||||
return (BOOLEAN) (strcmp ((CHAR8*)mEhdr + Namedr->sh_offset + Shdr->sh_name, ELF_HII_SECTION_NAME) == 0);
|
||||
}
|
||||
|
||||
static
|
||||
BOOLEAN
|
||||
IsShdrLoadable (
|
||||
IN const Elf_Shdr *Shdr
|
||||
)
|
||||
{
|
||||
assert (Shdr != NULL);
|
||||
|
||||
return (Shdr->sh_flags & SHF_ALLOC) != 0 && !IsHiiRsrcShdr (Shdr);
|
||||
}
|
||||
|
||||
static
|
||||
VOID
|
||||
SetHiiResourceHeader (
|
||||
IN OUT UINT8 *Hii,
|
||||
IN UINT32 Offset
|
||||
)
|
||||
{
|
||||
UINT32 Index;
|
||||
EFI_IMAGE_RESOURCE_DIRECTORY *RDir;
|
||||
EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY *RDirEntry;
|
||||
EFI_IMAGE_RESOURCE_DIRECTORY_STRING *RDirString;
|
||||
EFI_IMAGE_RESOURCE_DATA_ENTRY *RDataEntry;
|
||||
|
||||
assert (Hii != NULL);
|
||||
|
||||
//
|
||||
// Fill Resource section entry
|
||||
//
|
||||
RDir = (EFI_IMAGE_RESOURCE_DIRECTORY *)Hii;
|
||||
RDirEntry = (EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY *)(RDir + 1);
|
||||
for (Index = 0; Index < RDir->NumberOfNamedEntries; ++Index) {
|
||||
if (RDirEntry->u1.s.NameIsString) {
|
||||
RDirString = (EFI_IMAGE_RESOURCE_DIRECTORY_STRING *)(Hii + RDirEntry->u1.s.NameOffset);
|
||||
|
||||
if ((RDirString->Length == 3)
|
||||
&& (RDirString->String[0] == L'H')
|
||||
&& (RDirString->String[1] == L'I')
|
||||
&& (RDirString->String[2] == L'I')) {
|
||||
//
|
||||
// Resource Type "HII" found
|
||||
//
|
||||
if (RDirEntry->u2.s.DataIsDirectory) {
|
||||
//
|
||||
// Move to next level - resource Name
|
||||
//
|
||||
RDir = (EFI_IMAGE_RESOURCE_DIRECTORY *)(Hii + RDirEntry->u2.s.OffsetToDirectory);
|
||||
RDirEntry = (EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY *)(RDir + 1);
|
||||
|
||||
if (RDirEntry->u2.s.DataIsDirectory) {
|
||||
//
|
||||
// Move to next level - resource Language
|
||||
//
|
||||
RDir = (EFI_IMAGE_RESOURCE_DIRECTORY *)(Hii + RDirEntry->u2.s.OffsetToDirectory);
|
||||
RDirEntry = (EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY *)(RDir + 1);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Now it ought to be resource Data. Update its OffsetToData value
|
||||
//
|
||||
if (!RDirEntry->u2.s.DataIsDirectory) {
|
||||
RDataEntry = (EFI_IMAGE_RESOURCE_DATA_ENTRY *)(Hii + RDirEntry->u2.OffsetToData);
|
||||
RDataEntry->OffsetToData = RDataEntry->OffsetToData + Offset;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
RDirEntry++;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static
|
||||
RETURN_STATUS
|
||||
ParseElfFile (
|
||||
IN const void *File,
|
||||
IN uint32_t FileSize
|
||||
)
|
||||
{
|
||||
static const unsigned char Ident[] = {
|
||||
ELFMAG0, ELFMAG1, ELFMAG2, ELFMAG3, ELFCLASS, ELFDATA2LSB
|
||||
};
|
||||
const Elf_Shdr *Shdr;
|
||||
UINTN Offset;
|
||||
UINT32 Index;
|
||||
char *Last;
|
||||
|
||||
assert (File != NULL || FileSize == 0);
|
||||
|
||||
mEhdr = (Elf_Ehdr *)File;
|
||||
|
||||
//
|
||||
// Check header
|
||||
//
|
||||
if ((FileSize < sizeof (*mEhdr))
|
||||
|| (memcmp (Ident, mEhdr->e_ident, sizeof (Ident)) != 0)) {
|
||||
fprintf (stderr, "ImageTool: Invalid ELF header\n");
|
||||
fprintf (stderr, "ImageTool: mEhdr->e_ident[0] = 0x%x expected 0x%x\n", mEhdr->e_ident[0], Ident[0]);
|
||||
fprintf (stderr, "ImageTool: mEhdr->e_ident[1] = 0x%x expected 0x%x\n", mEhdr->e_ident[1], Ident[1]);
|
||||
fprintf (stderr, "ImageTool: mEhdr->e_ident[2] = 0x%x expected 0x%x\n", mEhdr->e_ident[2], Ident[2]);
|
||||
fprintf (stderr, "ImageTool: mEhdr->e_ident[3] = 0x%x expected 0x%x\n", mEhdr->e_ident[3], Ident[3]);
|
||||
fprintf (stderr, "ImageTool: mEhdr->e_ident[4] = 0x%x expected 0x%x\n", mEhdr->e_ident[4], Ident[4]);
|
||||
fprintf (stderr, "ImageTool: mEhdr->e_ident[5] = 0x%x expected 0x%x\n", mEhdr->e_ident[5], Ident[5]);
|
||||
fprintf (stderr, "ImageTool: FileSize = 0x%x sizeof(*mEhdr) = 0x%lx\n", FileSize, sizeof (*mEhdr));
|
||||
return RETURN_UNSUPPORTED;
|
||||
}
|
||||
|
||||
if ((mEhdr->e_type != ET_EXEC) && (mEhdr->e_type != ET_DYN)) {
|
||||
fprintf (stderr, "ImageTool: ELF e_type not ET_EXEC or ET_DYN\n");
|
||||
return RETURN_INCOMPATIBLE_VERSION;
|
||||
}
|
||||
|
||||
#if defined(EFI_TARGET64)
|
||||
if ((mEhdr->e_machine != EM_X86_64) && (mEhdr->e_machine != EM_AARCH64)) {
|
||||
fprintf (stderr, "ImageTool: Unsupported ELF e_machine\n");
|
||||
return RETURN_INCOMPATIBLE_VERSION;
|
||||
}
|
||||
#elif defined(EFI_TARGET32)
|
||||
if ((mEhdr->e_machine != EM_386) && (mEhdr->e_machine != EM_ARM)) {
|
||||
fprintf (stderr, "ImageTool: Unsupported ELF e_machine\n");
|
||||
return RETURN_INCOMPATIBLE_VERSION;
|
||||
}
|
||||
#endif
|
||||
|
||||
//
|
||||
// Check section headers
|
||||
//
|
||||
mBaseAddress = ~(Elf_Addr)0;
|
||||
for (Index = 0; Index < mEhdr->e_shnum; ++Index) {
|
||||
Offset = (UINTN)mEhdr->e_shoff + Index * mEhdr->e_shentsize;
|
||||
|
||||
if (FileSize < (Offset + sizeof (*Shdr))) {
|
||||
fprintf (stderr, "ImageTool: ELF section header is outside file\n");
|
||||
return RETURN_VOLUME_CORRUPTED;
|
||||
}
|
||||
|
||||
Shdr = (Elf_Shdr *)((UINT8 *)mEhdr + Offset);
|
||||
|
||||
if ((Shdr->sh_type != SHT_NOBITS)
|
||||
&& ((FileSize < Shdr->sh_offset) || ((FileSize - Shdr->sh_offset) < Shdr->sh_size))) {
|
||||
fprintf (stderr, "ImageTool: ELF section %d points outside file\n", Index);
|
||||
return RETURN_VOLUME_CORRUPTED;
|
||||
}
|
||||
|
||||
if (Shdr->sh_link >= mEhdr->e_shnum) {
|
||||
fprintf (stderr, "ImageTool: ELF %d-th section's sh_link is out of range\n", Index);
|
||||
return RETURN_VOLUME_CORRUPTED;
|
||||
}
|
||||
|
||||
if ((Shdr->sh_type == SHT_RELA) || (Shdr->sh_type == SHT_REL)) {
|
||||
if (Shdr->sh_info >= mEhdr->e_shnum) {
|
||||
fprintf (stderr, "ImageTool: ELF %d-th section's sh_info is out of range\n", Index);
|
||||
return RETURN_VOLUME_CORRUPTED;
|
||||
}
|
||||
|
||||
if (Shdr->sh_info == 0) {
|
||||
mHasPieRelocs = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
if (Shdr->sh_addr < mBaseAddress) {
|
||||
mBaseAddress = Shdr->sh_addr;
|
||||
}
|
||||
|
||||
if (!IsShdrLoadable (Shdr)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (mPeAlignment < Shdr->sh_addralign) {
|
||||
mPeAlignment = Shdr->sh_addralign;
|
||||
}
|
||||
}
|
||||
|
||||
if (mEhdr->e_shstrndx >= mEhdr->e_shnum) {
|
||||
fprintf (stderr, "ImageTool: Invalid section name string table\n");
|
||||
return RETURN_VOLUME_CORRUPTED;
|
||||
}
|
||||
Shdr = GetShdrByIndex (mEhdr->e_shstrndx);
|
||||
|
||||
if (Shdr->sh_type != SHT_STRTAB) {
|
||||
fprintf (stderr, "ImageTool: ELF string table section has wrong type\n");
|
||||
return RETURN_VOLUME_CORRUPTED;
|
||||
}
|
||||
|
||||
Last = (char *)((UINT8 *)mEhdr + Shdr->sh_offset + Shdr->sh_size - 1);
|
||||
if (*Last != '\0') {
|
||||
fprintf (stderr, "ImageTool: ELF string table section is not NUL-terminated\n");
|
||||
return RETURN_VOLUME_CORRUPTED;
|
||||
}
|
||||
|
||||
if ((!IS_POW2(mPeAlignment)) || (mPeAlignment > MAX_PE_ALIGNMENT)) {
|
||||
fprintf (stderr, "ImageTool: Invalid section alignment\n");
|
||||
return RETURN_VOLUME_CORRUPTED;
|
||||
}
|
||||
|
||||
return RETURN_SUCCESS;
|
||||
}
|
||||
|
||||
static
|
||||
bool
|
||||
ProcessRelocSection (
|
||||
const Elf_Shdr *Shdr
|
||||
)
|
||||
{
|
||||
const Elf_Shdr *SecShdr;
|
||||
//
|
||||
// PIE relocations will target dummy section 0.
|
||||
//
|
||||
if (Shdr->sh_info != 0) {
|
||||
//
|
||||
// If PIE relocations exist, prefer them.
|
||||
//
|
||||
if (mHasPieRelocs) {
|
||||
return FALSE;
|
||||
}
|
||||
//
|
||||
// Only translate relocations targetting sections that are translated.
|
||||
//
|
||||
SecShdr = GetShdrByIndex (Shdr->sh_info);
|
||||
|
||||
if (!IsShdrLoadable (SecShdr)) {
|
||||
return FALSE;
|
||||
}
|
||||
} else {
|
||||
assert (mHasPieRelocs);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static
|
||||
RETURN_STATUS
|
||||
SetRelocs (
|
||||
VOID
|
||||
)
|
||||
{
|
||||
UINT32 Index;
|
||||
const Elf_Shdr *RelShdr;
|
||||
UINTN RelIdx;
|
||||
const Elf_Rela *Rel;
|
||||
UINT32 RelNum;
|
||||
RelNum = 0;
|
||||
|
||||
for (Index = 0; Index < mEhdr->e_shnum; Index++) {
|
||||
RelShdr = GetShdrByIndex (Index);
|
||||
|
||||
if ((RelShdr->sh_type != SHT_REL) && (RelShdr->sh_type != SHT_RELA)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!ProcessRelocSection (RelShdr)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
for (RelIdx = 0; RelIdx < RelShdr->sh_size; RelIdx += (UINTN)RelShdr->sh_entsize) {
|
||||
Rel = (Elf_Rela *)((UINT8 *)mEhdr + RelShdr->sh_offset + RelIdx);
|
||||
//
|
||||
// Assume ELF virtual addresses match corresponding PE virtual adresses one to one,
|
||||
// so we don't need to recalculate relocations computed by the linker at all r_offset's.
|
||||
// We only need to transform ELF relocations' format into PE one.
|
||||
//
|
||||
#if defined(EFI_TARGET64)
|
||||
if (mEhdr->e_machine == EM_X86_64) {
|
||||
switch (ELF_R_TYPE(Rel->r_info)) {
|
||||
case R_X86_64_NONE:
|
||||
break;
|
||||
case R_X86_64_RELATIVE:
|
||||
case R_X86_64_64:
|
||||
mImageInfo.RelocInfo.Relocs[RelNum].Type = EFI_IMAGE_REL_BASED_DIR64;
|
||||
mImageInfo.RelocInfo.Relocs[RelNum].Target = (uint32_t)(Rel->r_offset - mBaseAddress);
|
||||
++RelNum;
|
||||
|
||||
break;
|
||||
case R_X86_64_32:
|
||||
|
||||
mImageInfo.RelocInfo.Relocs[RelNum].Type = EFI_IMAGE_REL_BASED_HIGHLOW;
|
||||
mImageInfo.RelocInfo.Relocs[RelNum].Target = (uint32_t)(Rel->r_offset - mBaseAddress);
|
||||
++RelNum;
|
||||
|
||||
break;
|
||||
case R_X86_64_32S:
|
||||
case R_X86_64_PLT32:
|
||||
case R_X86_64_PC32:
|
||||
break;
|
||||
case R_X86_64_GOTPCREL:
|
||||
case R_X86_64_GOTPCRELX:
|
||||
case R_X86_64_REX_GOTPCRELX:
|
||||
//
|
||||
// Relocations of these types point to instructions' arguments containing
|
||||
// offsets relative to RIP leading to .got entries. As sections' virtual
|
||||
// addresses do not change during ELF->PE transform, we don't need to
|
||||
// add them to relocations' list. But .got entries contain virtual
|
||||
// addresses which must be updated.
|
||||
//
|
||||
// At r_offset the following value is stored: G + GOT + A - P.
|
||||
// To derive .got entry address (G + GOT) compute: value - A + P.
|
||||
//
|
||||
// Such a method of finding relocatable .got entries can not be used,
|
||||
// due to a BUG in clang compiler, which sometimes generates
|
||||
// R_X86_64_REX_GOTPCRELX relocations instead of R_X86_64_PC32.
|
||||
//
|
||||
break;
|
||||
default:
|
||||
fprintf (stderr, "ImageTool: Unsupported ELF EM_X86_64 relocation 0x%llx in %s\n", ELF_R_TYPE(Rel->r_info), mImageInfo.DebugInfo.SymbolsPath);
|
||||
return RETURN_UNSUPPORTED;
|
||||
}
|
||||
} else if (mEhdr->e_machine == EM_AARCH64) {
|
||||
switch (ELF_R_TYPE(Rel->r_info)) {
|
||||
case R_AARCH64_NONE0:
|
||||
case R_AARCH64_NONE:
|
||||
case R_AARCH64_LD64_GOTOFF_LO15:
|
||||
case R_AARCH64_LD64_GOTPAGE_LO15:
|
||||
case R_AARCH64_LD64_GOT_LO12_NC:
|
||||
case R_AARCH64_ADR_GOT_PAGE:
|
||||
case R_AARCH64_ADR_PREL_PG_HI21:
|
||||
case R_AARCH64_ADD_ABS_LO12_NC:
|
||||
case R_AARCH64_LDST8_ABS_LO12_NC:
|
||||
case R_AARCH64_LDST16_ABS_LO12_NC:
|
||||
case R_AARCH64_LDST32_ABS_LO12_NC:
|
||||
case R_AARCH64_LDST64_ABS_LO12_NC:
|
||||
case R_AARCH64_LDST128_ABS_LO12_NC:
|
||||
case R_AARCH64_ADR_PREL_LO21:
|
||||
case R_AARCH64_CONDBR19:
|
||||
case R_AARCH64_LD_PREL_LO19:
|
||||
case R_AARCH64_CALL26:
|
||||
case R_AARCH64_JUMP26:
|
||||
case R_AARCH64_PREL64:
|
||||
case R_AARCH64_PREL32:
|
||||
case R_AARCH64_PREL16:
|
||||
break;
|
||||
case R_AARCH64_ABS64:
|
||||
case R_AARCH64_RELATIVE:
|
||||
mImageInfo.RelocInfo.Relocs[RelNum].Type = EFI_IMAGE_REL_BASED_DIR64;
|
||||
mImageInfo.RelocInfo.Relocs[RelNum].Target = (uint32_t)(Rel->r_offset - mBaseAddress);
|
||||
++RelNum;
|
||||
|
||||
break;
|
||||
case R_AARCH64_ABS32:
|
||||
|
||||
mImageInfo.RelocInfo.Relocs[RelNum].Type = EFI_IMAGE_REL_BASED_HIGHLOW;
|
||||
mImageInfo.RelocInfo.Relocs[RelNum].Target = (uint32_t)(Rel->r_offset - mBaseAddress);
|
||||
++RelNum;
|
||||
|
||||
break;
|
||||
default:
|
||||
fprintf (stderr, "ImageTool: Unsupported ELF EM_AARCH64 relocation 0x%llx in %s\n", ELF_R_TYPE(Rel->r_info), mImageInfo.DebugInfo.SymbolsPath);
|
||||
return RETURN_UNSUPPORTED;
|
||||
}
|
||||
}
|
||||
#elif defined(EFI_TARGET32)
|
||||
if (mEhdr->e_machine == EM_386) {
|
||||
switch (ELF_R_TYPE(Rel->r_info)) {
|
||||
case R_386_NONE:
|
||||
break;
|
||||
case R_386_32:
|
||||
|
||||
mImageInfo.RelocInfo.Relocs[RelNum].Type = EFI_IMAGE_REL_BASED_HIGHLOW;
|
||||
mImageInfo.RelocInfo.Relocs[RelNum].Target = (Rel->r_offset - mBaseAddress);
|
||||
++RelNum;
|
||||
|
||||
break;
|
||||
case R_386_PLT32:
|
||||
case R_386_PC32:
|
||||
break;
|
||||
default:
|
||||
fprintf (stderr, "ImageTool: Unsupported ELF EM_386 relocation 0x%x in %s\n", ELF_R_TYPE(Rel->r_info), mImageInfo.DebugInfo.SymbolsPath);
|
||||
return RETURN_UNSUPPORTED;
|
||||
}
|
||||
} else if (mEhdr->e_machine == EM_ARM) {
|
||||
switch (ELF32_R_TYPE(Rel->r_info)) {
|
||||
case R_ARM_NONE:
|
||||
case R_ARM_PC24:
|
||||
case R_ARM_REL32:
|
||||
case R_ARM_XPC25:
|
||||
case R_ARM_THM_PC22:
|
||||
case R_ARM_THM_JUMP19:
|
||||
case R_ARM_CALL:
|
||||
case R_ARM_JMP24:
|
||||
case R_ARM_THM_JUMP24:
|
||||
case R_ARM_PREL31:
|
||||
case R_ARM_MOVW_PREL_NC:
|
||||
case R_ARM_MOVT_PREL:
|
||||
case R_ARM_THM_MOVW_PREL_NC:
|
||||
case R_ARM_THM_MOVT_PREL:
|
||||
case R_ARM_THM_JMP6:
|
||||
case R_ARM_THM_ALU_PREL_11_0:
|
||||
case R_ARM_THM_PC12:
|
||||
case R_ARM_REL32_NOI:
|
||||
case R_ARM_ALU_PC_G0_NC:
|
||||
case R_ARM_ALU_PC_G0:
|
||||
case R_ARM_ALU_PC_G1_NC:
|
||||
case R_ARM_ALU_PC_G1:
|
||||
case R_ARM_ALU_PC_G2:
|
||||
case R_ARM_LDR_PC_G1:
|
||||
case R_ARM_LDR_PC_G2:
|
||||
case R_ARM_LDRS_PC_G0:
|
||||
case R_ARM_LDRS_PC_G1:
|
||||
case R_ARM_LDRS_PC_G2:
|
||||
case R_ARM_LDC_PC_G0:
|
||||
case R_ARM_LDC_PC_G1:
|
||||
case R_ARM_LDC_PC_G2:
|
||||
case R_ARM_THM_JUMP11:
|
||||
case R_ARM_THM_JUMP8:
|
||||
case R_ARM_TLS_GD32:
|
||||
case R_ARM_TLS_LDM32:
|
||||
case R_ARM_TLS_IE32:
|
||||
break;
|
||||
case R_ARM_ABS32:
|
||||
|
||||
mImageInfo.RelocInfo.Relocs[RelNum].Type = EFI_IMAGE_REL_BASED_HIGHLOW;
|
||||
mImageInfo.RelocInfo.Relocs[RelNum].Target = (Rel->r_offset - mBaseAddress);
|
||||
++RelNum;
|
||||
|
||||
break;
|
||||
default:
|
||||
fprintf (stderr, "ImageTool: Unsupported ELF EM_ARM relocation 0x%x in %s\n", ELF_R_TYPE(Rel->r_info), mImageInfo.DebugInfo.SymbolsPath);
|
||||
return RETURN_UNSUPPORTED;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
mImageInfo.RelocInfo.NumRelocs = RelNum;
|
||||
|
||||
return RETURN_SUCCESS;
|
||||
}
|
||||
|
||||
static
|
||||
RETURN_STATUS
|
||||
CreateIntermediate (
|
||||
VOID
|
||||
)
|
||||
{
|
||||
const Elf_Shdr *Shdr;
|
||||
UINT32 Index;
|
||||
image_tool_segment_t *Segments;
|
||||
image_tool_reloc_t *Relocs;
|
||||
UINT32 SIndex;
|
||||
const Elf_Rel *Rel;
|
||||
UINTN RIndex;
|
||||
char *Name;
|
||||
UINT32 NumRelocs;
|
||||
|
||||
Segments = NULL;
|
||||
SIndex = 0;
|
||||
Relocs = NULL;
|
||||
NumRelocs = 0;
|
||||
|
||||
for (Index = 0; Index < mEhdr->e_shnum; ++Index) {
|
||||
Shdr = GetShdrByIndex (Index);
|
||||
|
||||
if ((Shdr->sh_type == SHT_REL) || (Shdr->sh_type == SHT_RELA)) {
|
||||
if ((Shdr->sh_flags & SHF_ALLOC) != 0) {
|
||||
fprintf (stderr, "ImageTool: Loadable reloc sections are unsupported\n");
|
||||
return RETURN_VOLUME_CORRUPTED;
|
||||
}
|
||||
|
||||
if (!ProcessRelocSection (Shdr)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
for (RIndex = 0; RIndex < Shdr->sh_size; RIndex += (UINTN)Shdr->sh_entsize) {
|
||||
Rel = (Elf_Rel *)((UINT8 *)mEhdr + Shdr->sh_offset + RIndex);
|
||||
#if defined(EFI_TARGET64)
|
||||
if (mEhdr->e_machine == EM_X86_64) {
|
||||
if ((ELF_R_TYPE(Rel->r_info) == R_X86_64_RELATIVE)
|
||||
|| (ELF_R_TYPE(Rel->r_info) == R_X86_64_64)
|
||||
|| (ELF_R_TYPE(Rel->r_info) == R_X86_64_32)
|
||||
|| (ELF_R_TYPE(Rel->r_info) == R_X86_64_GOTPCREL)
|
||||
|| (ELF_R_TYPE(Rel->r_info) == R_X86_64_GOTPCRELX)
|
||||
|| (ELF_R_TYPE(Rel->r_info) == R_X86_64_REX_GOTPCRELX)) {
|
||||
++NumRelocs;
|
||||
}
|
||||
} else if (mEhdr->e_machine == EM_AARCH64) {
|
||||
if ((ELF_R_TYPE(Rel->r_info) == R_AARCH64_ABS64)
|
||||
|| (ELF_R_TYPE(Rel->r_info) == R_AARCH64_RELATIVE)
|
||||
|| (ELF_R_TYPE(Rel->r_info) == R_AARCH64_ABS32)) {
|
||||
++NumRelocs;
|
||||
}
|
||||
}
|
||||
#elif defined(EFI_TARGET32)
|
||||
if (mEhdr->e_machine == EM_386) {
|
||||
if (ELF_R_TYPE(Rel->r_info) == R_386_32) {
|
||||
++NumRelocs;
|
||||
}
|
||||
} else if (mEhdr->e_machine == EM_ARM) {
|
||||
if (ELF_R_TYPE(Rel->r_info) == R_ARM_ABS32) {
|
||||
++NumRelocs;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
if (!IsShdrLoadable (Shdr)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
++mImageInfo.SegmentInfo.NumSegments;
|
||||
}
|
||||
|
||||
if (mImageInfo.SegmentInfo.NumSegments == 0) {
|
||||
fprintf (stderr, "ImageTool: No loadable sections\n");
|
||||
return RETURN_VOLUME_CORRUPTED;
|
||||
}
|
||||
|
||||
Segments = calloc (1, sizeof (*Segments) * mImageInfo.SegmentInfo.NumSegments);
|
||||
if (Segments == NULL) {
|
||||
fprintf (stderr, "ImageTool: Could not allocate memory for Segments\n");
|
||||
return RETURN_OUT_OF_RESOURCES;
|
||||
};
|
||||
|
||||
mImageInfo.SegmentInfo.Segments = Segments;
|
||||
|
||||
if (NumRelocs != 0) {
|
||||
Relocs = calloc (1, sizeof (*Relocs) * NumRelocs);
|
||||
if (Relocs == NULL) {
|
||||
fprintf (stderr, "ImageTool: Could not allocate memory for Relocs\n");
|
||||
return RETURN_OUT_OF_RESOURCES;
|
||||
};
|
||||
|
||||
mImageInfo.RelocInfo.Relocs = Relocs;
|
||||
}
|
||||
|
||||
for (Index = 0; Index < mEhdr->e_shnum; ++Index) {
|
||||
Shdr = GetShdrByIndex (Index);
|
||||
|
||||
if ((Shdr->sh_flags & SHF_ALLOC) == 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (Shdr->sh_type != SHT_PROGBITS && Shdr->sh_type != SHT_NOBITS) {
|
||||
fprintf (stderr, "ImageTool: Segment #%d type %x unsupported\n", Index, Shdr->sh_type);
|
||||
return RETURN_VOLUME_CORRUPTED;
|
||||
}
|
||||
|
||||
if (IsHiiRsrcShdr (Shdr)) {
|
||||
mImageInfo.HiiInfo.DataSize = (uint32_t)Shdr->sh_size;
|
||||
|
||||
mImageInfo.HiiInfo.Data = calloc (1, mImageInfo.HiiInfo.DataSize);
|
||||
if (mImageInfo.HiiInfo.Data == NULL) {
|
||||
fprintf (stderr, "ImageTool: Could not allocate memory for Hii Data\n");
|
||||
return RETURN_OUT_OF_RESOURCES;
|
||||
};
|
||||
|
||||
if (Shdr->sh_type == SHT_PROGBITS) {
|
||||
memcpy (mImageInfo.HiiInfo.Data, (UINT8 *)mEhdr + Shdr->sh_offset, mImageInfo.HiiInfo.DataSize);
|
||||
}
|
||||
|
||||
SetHiiResourceHeader (mImageInfo.HiiInfo.Data, (UINT32)(Shdr->sh_addr - mBaseAddress));
|
||||
} else {
|
||||
Name = GetString (Shdr->sh_name, 0);
|
||||
if (Name == NULL) {
|
||||
return RETURN_VOLUME_CORRUPTED;
|
||||
}
|
||||
|
||||
Segments[SIndex].Name = calloc (1, strlen (Name) + 1);
|
||||
if (Segments[SIndex].Name == NULL) {
|
||||
fprintf (stderr, "ImageTool: Could not allocate memory for Segment #%d Name\n", Index);
|
||||
return RETURN_OUT_OF_RESOURCES;
|
||||
};
|
||||
|
||||
memcpy (Segments[SIndex].Name, Name, strlen (Name));
|
||||
|
||||
Segments[SIndex].DataSize = (uint32_t)ALIGN_VALUE (Shdr->sh_size, mPeAlignment);
|
||||
|
||||
Segments[SIndex].Data = calloc (1, Segments[SIndex].DataSize);
|
||||
if (Segments[SIndex].Data == NULL) {
|
||||
fprintf (stderr, "ImageTool: Could not allocate memory for Segment #%d Data\n", Index);
|
||||
return RETURN_OUT_OF_RESOURCES;
|
||||
};
|
||||
|
||||
if (Shdr->sh_type == SHT_PROGBITS) {
|
||||
memcpy (Segments[SIndex].Data, (UINT8 *)mEhdr + Shdr->sh_offset, (size_t)Shdr->sh_size);
|
||||
}
|
||||
|
||||
Segments[SIndex].ImageAddress = Shdr->sh_addr - mBaseAddress;
|
||||
Segments[SIndex].ImageSize = Segments[SIndex].DataSize;
|
||||
Segments[SIndex].Read = true;
|
||||
Segments[SIndex].Write = (Shdr->sh_flags & SHF_WRITE) != 0;
|
||||
Segments[SIndex].Execute = (Shdr->sh_flags & SHF_EXECINSTR) != 0;
|
||||
++SIndex;
|
||||
}
|
||||
}
|
||||
|
||||
assert (SIndex == mImageInfo.SegmentInfo.NumSegments);
|
||||
|
||||
return SetRelocs();
|
||||
}
|
||||
|
||||
RETURN_STATUS
|
||||
ScanElf (
|
||||
IN const void *File,
|
||||
IN uint32_t FileSize,
|
||||
IN const char *SymbolsPath
|
||||
)
|
||||
{
|
||||
RETURN_STATUS Status;
|
||||
|
||||
assert (File != NULL || FileSize == 0);
|
||||
|
||||
Status = ParseElfFile (File, FileSize);
|
||||
if (RETURN_ERROR (Status)) {
|
||||
return Status;
|
||||
}
|
||||
|
||||
memset (&mImageInfo, 0, sizeof (mImageInfo));
|
||||
|
||||
mImageInfo.HeaderInfo.BaseAddress = mBaseAddress;
|
||||
mImageInfo.HeaderInfo.EntryPointAddress = (uint32_t)(mEhdr->e_entry - mBaseAddress);
|
||||
mImageInfo.HeaderInfo.IsXip = true;
|
||||
mImageInfo.SegmentInfo.SegmentAlignment = (uint32_t)mPeAlignment;
|
||||
mImageInfo.RelocInfo.RelocsStripped = false;
|
||||
mImageInfo.DebugInfo.SymbolsPathLen = strlen (SymbolsPath);
|
||||
|
||||
switch (mEhdr->e_machine) {
|
||||
#if defined(EFI_TARGET64)
|
||||
case EM_X86_64:
|
||||
mImageInfo.HeaderInfo.Machine = EFI_IMAGE_MACHINE_X64;
|
||||
break;
|
||||
case EM_AARCH64:
|
||||
mImageInfo.HeaderInfo.Machine = EFI_IMAGE_MACHINE_AARCH64;
|
||||
break;
|
||||
#elif defined(EFI_TARGET32)
|
||||
case EM_386:
|
||||
mImageInfo.HeaderInfo.Machine = EFI_IMAGE_MACHINE_IA32;
|
||||
break;
|
||||
case EM_ARM:
|
||||
mImageInfo.HeaderInfo.Machine = EFI_IMAGE_MACHINE_ARMTHUMB_MIXED;
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
fprintf (stderr, "ImageTool: Unknown ELF architecture %d\n", mEhdr->e_machine);
|
||||
return RETURN_INCOMPATIBLE_VERSION;
|
||||
}
|
||||
|
||||
mImageInfo.DebugInfo.SymbolsPath = malloc (mImageInfo.DebugInfo.SymbolsPathLen + 1);
|
||||
if (mImageInfo.DebugInfo.SymbolsPath == NULL) {
|
||||
fprintf (stderr, "ImageTool: Could not allocate memory for Debug Data\n");
|
||||
return RETURN_OUT_OF_RESOURCES;
|
||||
};
|
||||
|
||||
memmove (mImageInfo.DebugInfo.SymbolsPath, SymbolsPath, mImageInfo.DebugInfo.SymbolsPathLen + 1);
|
||||
|
||||
//
|
||||
// There is no corresponding ELF property.
|
||||
//
|
||||
mImageInfo.HeaderInfo.Subsystem = 0;
|
||||
|
||||
Status = CreateIntermediate ();
|
||||
if (RETURN_ERROR (Status)) {
|
||||
ToolImageDestruct (&mImageInfo);
|
||||
}
|
||||
|
||||
return Status;
|
||||
}
|
33
BaseTools/ImageTool/GNUmakefile
Normal file
33
BaseTools/ImageTool/GNUmakefile
Normal file
@ -0,0 +1,33 @@
|
||||
## @file
|
||||
# Copyright (c) 2021, Marvin Häuser. All rights reserved.
|
||||
# Copyright (c) 2022, Mikhail Krichanov. All rights reserved.
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
##
|
||||
|
||||
PROJECT = ImageTool
|
||||
OBJS = $(PROJECT).o
|
||||
OBJS += Image.o PeEmit.o PeScan.o ElfScan.o BinEmit.o
|
||||
OBJS += UefiImageExtraActionLib.o
|
||||
OBJS += PeCoffInit.o PeCoffInfo.o PeCoffLoad.o PeCoffRelocate.o PeCoffHii.o PeCoffDebug.o
|
||||
|
||||
DEBUG = 1
|
||||
SANITIZE = 0
|
||||
OC_USER = ../../OpenCorePkg
|
||||
UDK_PATH = ../..
|
||||
|
||||
include $(OC_USER)/User/Makefile
|
||||
|
||||
.DEFAULT_GOAL := Tools
|
||||
|
||||
CFLAGS += -Werror
|
||||
|
||||
VPATH += ../../MdePkg/Library/BasePeCoffLib2:$\
|
||||
../../MdePkg/Library/BaseUefiImageExtraActionLibNull
|
||||
|
||||
Tools: Tool32 Tool64
|
||||
|
||||
Tool32:
|
||||
$(MAKE) all CFLAGS="$(CFLAGS) -DEFI_TARGET32" PRODUCT=ImageTool32 INFIX=_Tool32
|
||||
|
||||
Tool64:
|
||||
$(MAKE) all CFLAGS="$(CFLAGS) -DEFI_TARGET64" PRODUCT=ImageTool64 INFIX=_Tool64
|
311
BaseTools/ImageTool/Image.c
Normal file
311
BaseTools/ImageTool/Image.c
Normal file
@ -0,0 +1,311 @@
|
||||
/** @file
|
||||
Copyright (c) 2021, Marvin Häuser. All rights reserved.
|
||||
Copyright (c) 2022, Mikhail Krichanov. All rights reserved.
|
||||
SPDX-License-Identifier: BSD-3-Clause
|
||||
**/
|
||||
|
||||
#include "ImageTool.h"
|
||||
|
||||
static
|
||||
bool
|
||||
CheckToolImageSegment (
|
||||
image_tool_segment_info_t *SegmentInfo,
|
||||
image_tool_segment_t *Segment,
|
||||
uint32_t *PreviousEndAddress
|
||||
)
|
||||
{
|
||||
bool Overflow;
|
||||
|
||||
assert (Segment != NULL);
|
||||
assert (PreviousEndAddress != NULL);
|
||||
|
||||
Overflow = BaseOverflowAlignUpU32 (
|
||||
Segment->ImageSize,
|
||||
SegmentInfo->SegmentAlignment,
|
||||
&Segment->ImageSize
|
||||
);
|
||||
if (Overflow) {
|
||||
raise ();
|
||||
return false;
|
||||
}
|
||||
|
||||
if (Segment->Write && Segment->Execute) {
|
||||
raise ();
|
||||
return false;
|
||||
}
|
||||
//
|
||||
// Shrink segment.
|
||||
//
|
||||
if (Segment->ImageSize < Segment->DataSize) {
|
||||
Segment->DataSize = Segment->ImageSize;
|
||||
}
|
||||
|
||||
for (; Segment->DataSize > 0; --Segment->DataSize) {
|
||||
if (Segment->Data[Segment->DataSize - 1] != 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
// FIXME: Expand prior segment
|
||||
if (Segment->ImageAddress != *PreviousEndAddress) {
|
||||
raise ();
|
||||
return false;
|
||||
}
|
||||
|
||||
Overflow = BaseOverflowAddU32 (
|
||||
(uint32_t)Segment->ImageAddress,
|
||||
Segment->ImageSize,
|
||||
PreviousEndAddress
|
||||
);
|
||||
if (Overflow) {
|
||||
raise ();
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static
|
||||
bool
|
||||
CheckToolImageSegmentInfo (
|
||||
image_tool_segment_info_t *SegmentInfo,
|
||||
uint32_t *ImageSize
|
||||
)
|
||||
{
|
||||
uint64_t Index;
|
||||
bool Result;
|
||||
|
||||
assert (SegmentInfo != NULL);
|
||||
assert (ImageSize != NULL);
|
||||
|
||||
if (!IS_POW2 (SegmentInfo->SegmentAlignment)) {
|
||||
raise ();
|
||||
return false;
|
||||
}
|
||||
|
||||
if (SegmentInfo->NumSegments == 0) {
|
||||
raise ();
|
||||
return false;
|
||||
}
|
||||
|
||||
*ImageSize = (uint32_t)SegmentInfo->Segments[0].ImageAddress;
|
||||
for (Index = 0; Index < SegmentInfo->NumSegments; ++Index) {
|
||||
Result = CheckToolImageSegment (
|
||||
SegmentInfo,
|
||||
&SegmentInfo->Segments[Index],
|
||||
ImageSize
|
||||
);
|
||||
if (!Result) {
|
||||
raise ();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static
|
||||
const image_tool_segment_t *
|
||||
ImageGetSegmentByAddress (
|
||||
const image_tool_segment_info_t *SegmentInfo,
|
||||
uint64_t Address
|
||||
)
|
||||
{
|
||||
uint64_t Index;
|
||||
|
||||
assert (SegmentInfo != NULL);
|
||||
|
||||
for (Index = 0; Index < SegmentInfo->NumSegments; ++Index) {
|
||||
if ((SegmentInfo->Segments[Index].ImageAddress <= Address)
|
||||
&& (Address < SegmentInfo->Segments[Index].ImageAddress + SegmentInfo->Segments[Index].ImageSize)) {
|
||||
return &SegmentInfo->Segments[Index];
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static
|
||||
bool
|
||||
CheckToolImageReloc (
|
||||
const image_tool_image_info_t *Image,
|
||||
const image_tool_reloc_t *Reloc
|
||||
)
|
||||
{
|
||||
const image_tool_segment_t *Segment;
|
||||
|
||||
assert (Image != NULL);
|
||||
assert (Reloc != NULL);
|
||||
|
||||
Segment = ImageGetSegmentByAddress (&Image->SegmentInfo, Reloc->Target);
|
||||
if (Segment == NULL) {
|
||||
raise ();
|
||||
return false;
|
||||
}
|
||||
|
||||
/*if (Segment->Write) {
|
||||
printf("!!! writable reloc at %x !!!\n", Reloc->Target);
|
||||
}*/
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static
|
||||
bool
|
||||
CheckToolImageRelocInfo (
|
||||
const image_tool_image_info_t *Image
|
||||
)
|
||||
{
|
||||
const image_tool_reloc_info_t *RelocInfo;
|
||||
uint32_t Index;
|
||||
bool Result;
|
||||
|
||||
assert (Image != NULL);
|
||||
|
||||
RelocInfo = &Image->RelocInfo;
|
||||
|
||||
if (RelocInfo->RelocsStripped && (RelocInfo->NumRelocs > 0)) {
|
||||
raise ();
|
||||
return false;
|
||||
}
|
||||
|
||||
if (RelocInfo->NumRelocs > (MAX_UINT32 / sizeof (UINT16))) {
|
||||
raise ();
|
||||
return false;
|
||||
}
|
||||
|
||||
for (Index = 0; Index < RelocInfo->NumRelocs; ++Index) {
|
||||
Result = CheckToolImageReloc (Image, &RelocInfo->Relocs[Index]);
|
||||
if (!Result) {
|
||||
raise ();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static
|
||||
bool
|
||||
CheckToolImageDebugInfo (
|
||||
image_tool_debug_info_t *DebugInfo
|
||||
)
|
||||
{
|
||||
assert (DebugInfo != NULL);
|
||||
|
||||
if (DebugInfo->SymbolsPath != NULL) {
|
||||
// FIXME: UE-only?
|
||||
if (DebugInfo->SymbolsPathLen > MAX_UINT8) {
|
||||
raise ();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
CheckToolImage (
|
||||
image_tool_image_info_t *Image
|
||||
)
|
||||
{
|
||||
bool Result;
|
||||
uint32_t ImageSize;
|
||||
|
||||
assert (Image != NULL);
|
||||
|
||||
Result = CheckToolImageSegmentInfo (&Image->SegmentInfo, &ImageSize);
|
||||
if (!Result) {
|
||||
raise ();
|
||||
return false;
|
||||
}
|
||||
|
||||
Result = CheckToolImageRelocInfo (Image);
|
||||
if (!Result) {
|
||||
raise ();
|
||||
return false;
|
||||
}
|
||||
|
||||
Result = CheckToolImageDebugInfo (&Image->DebugInfo);
|
||||
if (!Result) {
|
||||
raise ();
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
ImageConvertToXip (
|
||||
image_tool_image_info_t *Image
|
||||
)
|
||||
{
|
||||
image_tool_segment_info_t *SegmentInfo;
|
||||
uint64_t Index;
|
||||
image_tool_segment_t *Segment;
|
||||
void *Data;
|
||||
|
||||
assert (Image != NULL);
|
||||
|
||||
SegmentInfo = &Image->SegmentInfo;
|
||||
|
||||
for (Index = 0; Index < SegmentInfo->NumSegments; ++Index) {
|
||||
Segment = &SegmentInfo->Segments[Index];
|
||||
|
||||
assert (Segment->DataSize <= Segment->ImageSize);
|
||||
|
||||
Data = realloc (Segment->Data, Segment->ImageSize);
|
||||
if (Data == NULL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
memset (
|
||||
(char *)Data + Segment->DataSize,
|
||||
0,
|
||||
Segment->ImageSize - Segment->DataSize
|
||||
);
|
||||
|
||||
Segment->Data = Data;
|
||||
Segment->DataSize = Segment->ImageSize;
|
||||
}
|
||||
|
||||
Image->HeaderInfo.IsXip = true;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
ToolImageDestruct (
|
||||
image_tool_image_info_t *Image
|
||||
)
|
||||
{
|
||||
uint8_t Index;
|
||||
|
||||
assert (Image != NULL);
|
||||
|
||||
if (Image->SegmentInfo.Segments != NULL) {
|
||||
for (Index = 0; Index < Image->SegmentInfo.NumSegments; ++Index) {
|
||||
if (Image->SegmentInfo.Segments[Index].Name != NULL) {
|
||||
free (Image->SegmentInfo.Segments[Index].Name);
|
||||
}
|
||||
if (Image->SegmentInfo.Segments[Index].DataSize != 0) {
|
||||
free (Image->SegmentInfo.Segments[Index].Data);
|
||||
}
|
||||
}
|
||||
|
||||
free (Image->SegmentInfo.Segments);
|
||||
}
|
||||
|
||||
if (Image->HiiInfo.Data != NULL) {
|
||||
free (Image->HiiInfo.Data);
|
||||
}
|
||||
|
||||
if (Image->RelocInfo.Relocs != NULL) {
|
||||
free (Image->RelocInfo.Relocs);
|
||||
}
|
||||
|
||||
if (Image->DebugInfo.SymbolsPath != NULL) {
|
||||
free (Image->DebugInfo.SymbolsPath);
|
||||
}
|
||||
|
||||
memset (Image, 0, sizeof (*Image));
|
||||
}
|
493
BaseTools/ImageTool/ImageTool.c
Normal file
493
BaseTools/ImageTool/ImageTool.c
Normal file
@ -0,0 +1,493 @@
|
||||
/** @file
|
||||
Copyright (c) 2021, Marvin Häuser. All rights reserved.
|
||||
Copyright (c) 2022, Mikhail Krichanov. All rights reserved.
|
||||
SPDX-License-Identifier: BSD-3-Clause
|
||||
**/
|
||||
|
||||
#include "ImageTool.h"
|
||||
#include <IndustryStandard/Acpi10.h>
|
||||
#include <IndustryStandard/Acpi30.h>
|
||||
#include <IndustryStandard/MemoryMappedConfigurationSpaceAccessTable.h>
|
||||
|
||||
#define EFI_ACPI_1_0_FIRMWARE_ACPI_CONTROL_STRUCTURE_VERSION 0x0
|
||||
|
||||
image_tool_image_info_t mImageInfo;
|
||||
|
||||
|
||||
static
|
||||
RETURN_STATUS
|
||||
HiiBin (
|
||||
IN const char *HiiName,
|
||||
IN const char *Guid,
|
||||
IN const char *FileNames[],
|
||||
IN UINT32 NumOfFiles,
|
||||
IN BOOLEAN IsElf
|
||||
)
|
||||
{
|
||||
RETURN_STATUS Status;
|
||||
void *Hii;
|
||||
UINT32 HiiSize;
|
||||
GUID HiiGuid;
|
||||
|
||||
assert (FileNames != NULL);
|
||||
assert (HiiName != NULL);
|
||||
assert (Guid != NULL);
|
||||
|
||||
Status = AsciiStrToGuid (Guid, &HiiGuid);
|
||||
if (RETURN_ERROR (Status)) {
|
||||
fprintf (stderr, "ImageTool: Invalid GUID - %s\n", Guid);
|
||||
return Status;
|
||||
}
|
||||
|
||||
Status = ConstructHii (FileNames, NumOfFiles, &HiiGuid, &Hii, &HiiSize, IsElf);
|
||||
if (RETURN_ERROR (Status)) {
|
||||
fprintf (stderr, "ImageTool: Could not construct HiiBin\n");
|
||||
return Status;
|
||||
}
|
||||
|
||||
UserWriteFile (HiiName, Hii, HiiSize);
|
||||
|
||||
free (Hii);
|
||||
|
||||
return RETURN_SUCCESS;
|
||||
}
|
||||
|
||||
static
|
||||
RETURN_STATUS
|
||||
Rebase (
|
||||
IN const char *BaseAddress,
|
||||
IN const char *OldName,
|
||||
IN const char *NewName
|
||||
)
|
||||
{
|
||||
RETURN_STATUS Status;
|
||||
void *Pe;
|
||||
uint32_t PeSize;
|
||||
UINT64 NewBaseAddress;
|
||||
PE_COFF_LOADER_IMAGE_CONTEXT Context;
|
||||
EFI_IMAGE_NT_HEADERS *PeHdr;
|
||||
|
||||
assert (BaseAddress != NULL);
|
||||
assert (OldName != NULL);
|
||||
assert (NewName != NULL);
|
||||
|
||||
Status = AsciiStrHexToUint64S (BaseAddress, NULL, &NewBaseAddress);
|
||||
if (RETURN_ERROR (Status)) {
|
||||
fprintf (stderr, "ImageTool: Could not convert ASCII string to UINT64\n");
|
||||
return Status;
|
||||
}
|
||||
#ifdef EFI_TARGET32
|
||||
if (NewBaseAddress > MAX_UINT32) {
|
||||
fprintf (stderr, "ImageTool: New Base Address exceeds MAX value\n");
|
||||
return RETURN_INVALID_PARAMETER;
|
||||
}
|
||||
#endif
|
||||
|
||||
Pe = UserReadFile (OldName, &PeSize);
|
||||
if (Pe == NULL) {
|
||||
fprintf (stderr, "ImageTool: Could not open %s: %s\n", OldName, strerror (errno));
|
||||
return RETURN_ABORTED;
|
||||
}
|
||||
|
||||
Status = PeCoffInitializeContext (&Context, Pe, (UINT32)PeSize);
|
||||
if (RETURN_ERROR (Status)) {
|
||||
fprintf (stderr, "ImageTool: Could not initialise Context\n");
|
||||
free (Pe);
|
||||
return Status;
|
||||
}
|
||||
|
||||
Context.ImageBuffer = (void *)Context.FileBuffer;
|
||||
|
||||
Status = PeCoffRelocateImage (&Context, NewBaseAddress, NULL, 0);
|
||||
if (EFI_ERROR (Status)) {
|
||||
fprintf (stderr, "ImageTool: Could not relocate image\n");
|
||||
free (Pe);
|
||||
return Status;
|
||||
}
|
||||
|
||||
PeHdr = (EFI_IMAGE_NT_HEADERS *)(void *)((char *)Context.ImageBuffer + Context.ExeHdrOffset);
|
||||
#ifdef EFI_TARGET32
|
||||
PeHdr->ImageBase = (UINT32)NewBaseAddress;
|
||||
#else
|
||||
PeHdr->ImageBase = NewBaseAddress;
|
||||
#endif
|
||||
|
||||
UserWriteFile (NewName, Pe, PeSize);
|
||||
|
||||
free (Pe);
|
||||
|
||||
return RETURN_SUCCESS;
|
||||
}
|
||||
|
||||
static
|
||||
RETURN_STATUS
|
||||
CheckAcpiTable (
|
||||
IN const void *AcpiTable,
|
||||
IN UINT32 Length
|
||||
)
|
||||
{
|
||||
const EFI_ACPI_DESCRIPTION_HEADER *AcpiHeader;
|
||||
const EFI_ACPI_3_0_FIRMWARE_ACPI_CONTROL_STRUCTURE *Facs;
|
||||
UINT32 ExpectedLength;
|
||||
|
||||
AcpiHeader = (const EFI_ACPI_DESCRIPTION_HEADER *)AcpiTable;
|
||||
|
||||
if (AcpiHeader->Length > Length) {
|
||||
fprintf (stderr, "ImageTool: AcpiTable length section size\n");
|
||||
return RETURN_VOLUME_CORRUPTED;
|
||||
}
|
||||
|
||||
switch (AcpiHeader->Signature) {
|
||||
case EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE_SIGNATURE:
|
||||
switch (AcpiHeader->Revision) {
|
||||
case EFI_ACPI_1_0_FIXED_ACPI_DESCRIPTION_TABLE_REVISION:
|
||||
ExpectedLength = sizeof(EFI_ACPI_1_0_FIXED_ACPI_DESCRIPTION_TABLE);
|
||||
break;
|
||||
case EFI_ACPI_2_0_FIXED_ACPI_DESCRIPTION_TABLE_REVISION:
|
||||
ExpectedLength = sizeof(EFI_ACPI_2_0_FIXED_ACPI_DESCRIPTION_TABLE);
|
||||
break;
|
||||
case EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE_REVISION:
|
||||
ExpectedLength = sizeof(EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE);
|
||||
break;
|
||||
default:
|
||||
if (AcpiHeader->Revision > EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE_REVISION) {
|
||||
ExpectedLength = AcpiHeader->Length;
|
||||
break;
|
||||
}
|
||||
fprintf (stderr, "ImageTool: FACP revision check failed\n");
|
||||
return RETURN_VOLUME_CORRUPTED;
|
||||
}
|
||||
|
||||
if (ExpectedLength != AcpiHeader->Length) {
|
||||
fprintf (stderr, "ImageTool: FACP length check failed\n");
|
||||
return RETURN_VOLUME_CORRUPTED;
|
||||
}
|
||||
break;
|
||||
case EFI_ACPI_3_0_FIRMWARE_ACPI_CONTROL_STRUCTURE_SIGNATURE:
|
||||
Facs = (const EFI_ACPI_3_0_FIRMWARE_ACPI_CONTROL_STRUCTURE *)AcpiTable;
|
||||
if (Facs->Version > EFI_ACPI_3_0_FIRMWARE_ACPI_CONTROL_STRUCTURE_VERSION) {
|
||||
break;
|
||||
}
|
||||
|
||||
if ((Facs->Version != EFI_ACPI_1_0_FIRMWARE_ACPI_CONTROL_STRUCTURE_VERSION)
|
||||
&& (Facs->Version != EFI_ACPI_2_0_FIRMWARE_ACPI_CONTROL_STRUCTURE_VERSION)
|
||||
&& (Facs->Version != EFI_ACPI_3_0_FIRMWARE_ACPI_CONTROL_STRUCTURE_VERSION)) {
|
||||
fprintf (stderr, "ImageTool: FACS version check failed\n");
|
||||
return RETURN_VOLUME_CORRUPTED;
|
||||
}
|
||||
|
||||
if ((Facs->Length != sizeof(EFI_ACPI_1_0_FIRMWARE_ACPI_CONTROL_STRUCTURE))
|
||||
&& (Facs->Length != sizeof(EFI_ACPI_2_0_FIRMWARE_ACPI_CONTROL_STRUCTURE))
|
||||
&& (Facs->Length != sizeof(EFI_ACPI_3_0_FIRMWARE_ACPI_CONTROL_STRUCTURE))) {
|
||||
fprintf (stderr, "ImageTool: FACS length check failed\n");
|
||||
return RETURN_VOLUME_CORRUPTED;
|
||||
}
|
||||
break;
|
||||
case EFI_ACPI_3_0_DIFFERENTIATED_SYSTEM_DESCRIPTION_TABLE_SIGNATURE:
|
||||
if (AcpiHeader->Revision > EFI_ACPI_3_0_DIFFERENTIATED_SYSTEM_DESCRIPTION_TABLE_REVISION) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (AcpiHeader->Length <= sizeof(EFI_ACPI_DESCRIPTION_HEADER)) {
|
||||
fprintf (stderr, "ImageTool: DSDT length check failed\n");
|
||||
return RETURN_VOLUME_CORRUPTED;
|
||||
}
|
||||
break;
|
||||
case EFI_ACPI_3_0_MULTIPLE_APIC_DESCRIPTION_TABLE_SIGNATURE:
|
||||
if (AcpiHeader->Revision > EFI_ACPI_3_0_MULTIPLE_APIC_DESCRIPTION_TABLE_REVISION) {
|
||||
break;
|
||||
}
|
||||
|
||||
if ((AcpiHeader->Revision != EFI_ACPI_1_0_MULTIPLE_APIC_DESCRIPTION_TABLE_REVISION)
|
||||
&& (AcpiHeader->Revision != EFI_ACPI_2_0_MULTIPLE_APIC_DESCRIPTION_TABLE_REVISION)
|
||||
&& (AcpiHeader->Revision != EFI_ACPI_3_0_MULTIPLE_APIC_DESCRIPTION_TABLE_REVISION)) {
|
||||
fprintf (stderr, "ImageTool: APIC revision check failed\n");
|
||||
return RETURN_VOLUME_CORRUPTED;
|
||||
}
|
||||
|
||||
if (AcpiHeader->Length <= (sizeof(EFI_ACPI_DESCRIPTION_HEADER) + sizeof(UINT32) + sizeof(UINT32))) {
|
||||
fprintf (stderr, "ImageTool: APIC length check failed\n");
|
||||
return RETURN_VOLUME_CORRUPTED;
|
||||
}
|
||||
break;
|
||||
case EFI_ACPI_3_0_PCI_EXPRESS_MEMORY_MAPPED_CONFIGURATION_SPACE_BASE_ADDRESS_DESCRIPTION_TABLE_SIGNATURE:
|
||||
if (AcpiHeader->Revision > EFI_ACPI_MEMORY_MAPPED_CONFIGURATION_SPACE_ACCESS_TABLE_REVISION) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (AcpiHeader->Revision != EFI_ACPI_MEMORY_MAPPED_CONFIGURATION_SPACE_ACCESS_TABLE_REVISION) {
|
||||
fprintf (stderr, "ImageTool: MCFG revision check failed\n");
|
||||
return RETURN_VOLUME_CORRUPTED;
|
||||
}
|
||||
|
||||
if (AcpiHeader->Length <= (sizeof(EFI_ACPI_DESCRIPTION_HEADER) + sizeof(UINT64))) {
|
||||
fprintf (stderr, "ImageTool: MCFG length check failed\n");
|
||||
return RETURN_VOLUME_CORRUPTED;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return RETURN_SUCCESS;
|
||||
}
|
||||
|
||||
static
|
||||
RETURN_STATUS
|
||||
GetAcpi (
|
||||
IN const char *PeName,
|
||||
IN const char *AcpiName
|
||||
)
|
||||
{
|
||||
RETURN_STATUS Status;
|
||||
void *Pe;
|
||||
uint32_t PeSize;
|
||||
PE_COFF_LOADER_IMAGE_CONTEXT Context;
|
||||
UINT16 NumberOfSections;
|
||||
const EFI_IMAGE_SECTION_HEADER *Sections;
|
||||
UINT16 Index;
|
||||
UINT32 FileLength;
|
||||
|
||||
assert (PeName != NULL);
|
||||
assert (AcpiName != NULL);
|
||||
|
||||
Pe = UserReadFile (PeName, &PeSize);
|
||||
if (Pe == NULL) {
|
||||
fprintf (stderr, "ImageTool: Could not open %s: %s\n", PeName, strerror (errno));
|
||||
return RETURN_ABORTED;
|
||||
}
|
||||
|
||||
Status = PeCoffInitializeContext (&Context, Pe, (UINT32)PeSize);
|
||||
if (RETURN_ERROR (Status)) {
|
||||
fprintf (stderr, "ImageTool: Could not initialise Context\n");
|
||||
free (Pe);
|
||||
return Status;
|
||||
}
|
||||
|
||||
NumberOfSections = PeCoffGetSectionTable (&Context, &Sections);
|
||||
for (Index = 0; Index < NumberOfSections; ++Index) {
|
||||
if ((strcmp ((char *)Sections[Index].Name, ".data") == 0)
|
||||
|| (strcmp ((char *)Sections[Index].Name, ".sdata") == 0)
|
||||
|| (strcmp ((char *)Sections[Index].Name, ".rdata") == 0)) {
|
||||
|
||||
if (Sections[Index].VirtualSize < Sections[Index].SizeOfRawData) {
|
||||
FileLength = Sections[Index].VirtualSize;
|
||||
} else {
|
||||
FileLength = Sections[Index].SizeOfRawData;
|
||||
}
|
||||
|
||||
Status = CheckAcpiTable ((char *)Context.FileBuffer + Sections[Index].PointerToRawData, FileLength);
|
||||
if (RETURN_ERROR (Status)) {
|
||||
free (Pe);
|
||||
return Status;
|
||||
}
|
||||
|
||||
UserWriteFile (AcpiName, (char *)Context.FileBuffer + Sections[Index].PointerToRawData, FileLength);
|
||||
|
||||
free (Pe);
|
||||
|
||||
return RETURN_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
return RETURN_NOT_FOUND;
|
||||
}
|
||||
|
||||
static
|
||||
bool
|
||||
ImageSetModuleType (
|
||||
OUT image_tool_image_info_t *Image,
|
||||
IN const char *TypeName
|
||||
)
|
||||
{
|
||||
uint16_t ModuleType;
|
||||
|
||||
assert (Image != NULL);
|
||||
|
||||
if ((strcmp (TypeName, "BASE") == 0)
|
||||
|| (strcmp (TypeName, "SEC") == 0)
|
||||
|| (strcmp (TypeName, "SECURITY_CORE") == 0)
|
||||
|| (strcmp (TypeName, "PEI_CORE") == 0)
|
||||
|| (strcmp (TypeName, "PEIM") == 0)
|
||||
|| (strcmp (TypeName, "COMBINED_PEIM_DRIVER") == 0)
|
||||
|| (strcmp (TypeName, "PIC_PEIM") == 0)
|
||||
|| (strcmp (TypeName, "RELOCATABLE_PEIM") == 0)
|
||||
|| (strcmp (TypeName, "DXE_CORE") == 0)
|
||||
|| (strcmp (TypeName, "BS_DRIVER") == 0)
|
||||
|| (strcmp (TypeName, "DXE_DRIVER") == 0)
|
||||
|| (strcmp (TypeName, "DXE_SMM_DRIVER") == 0)
|
||||
|| (strcmp (TypeName, "UEFI_DRIVER") == 0)
|
||||
|| (strcmp (TypeName, "SMM_CORE") == 0)
|
||||
|| (strcmp (TypeName, "MM_STANDALONE") == 0)
|
||||
|| (strcmp (TypeName, "MM_CORE_STANDALONE") == 0)) {
|
||||
ModuleType = EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER;
|
||||
} else if ((strcmp (TypeName, "UEFI_APPLICATION") == 0)
|
||||
|| (strcmp (TypeName, "APPLICATION") == 0)) {
|
||||
ModuleType = EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION;
|
||||
} else if ((strcmp (TypeName, "DXE_RUNTIME_DRIVER") == 0)
|
||||
|| (strcmp (TypeName, "RT_DRIVER") == 0)) {
|
||||
ModuleType = EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER;
|
||||
} else if ((strcmp (TypeName, "DXE_SAL_DRIVER") == 0)
|
||||
|| (strcmp (TypeName, "SAL_RT_DRIVER") == 0)) {
|
||||
ModuleType = EFI_IMAGE_SUBSYSTEM_SAL_RUNTIME_DRIVER;
|
||||
} else {
|
||||
fprintf (stderr, "ImageTool: Unknown EFI_FILETYPE = %s\n", TypeName);
|
||||
return false;
|
||||
}
|
||||
|
||||
Image->HeaderInfo.Subsystem = ModuleType;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static
|
||||
RETURN_STATUS
|
||||
GenExecutable (
|
||||
IN const char *OutputFileName,
|
||||
IN const char *InputFileName,
|
||||
IN const char *FormatName,
|
||||
IN const char *TypeName
|
||||
)
|
||||
{
|
||||
UINT32 InputFileSize;
|
||||
VOID *InputFile;
|
||||
RETURN_STATUS Status;
|
||||
bool Result;
|
||||
void *OutputFile;
|
||||
uint32_t OutputFileSize;
|
||||
|
||||
InputFile = UserReadFile (InputFileName, &InputFileSize);
|
||||
if (InputFile == NULL) {
|
||||
fprintf (stderr, "ImageTool: Could not open %s: %s\n", InputFileName, strerror (errno));
|
||||
return RETURN_ABORTED;
|
||||
}
|
||||
|
||||
Status = ToolContextConstructPe (&mImageInfo, InputFile, InputFileSize);
|
||||
if (Status == RETURN_UNSUPPORTED) {
|
||||
Status = ScanElf (InputFile, InputFileSize, InputFileName);
|
||||
}
|
||||
|
||||
free (InputFile);
|
||||
|
||||
if (RETURN_ERROR (Status)) {
|
||||
fprintf (stderr, "ImageTool: Could not parse input file %s - %llx\n", InputFileName, (unsigned long long)Status);
|
||||
return Status;
|
||||
}
|
||||
|
||||
if (TypeName != NULL) {
|
||||
Result = ImageSetModuleType (&mImageInfo, TypeName);
|
||||
if (!Result) {
|
||||
ToolImageDestruct (&mImageInfo);
|
||||
return RETURN_UNSUPPORTED;
|
||||
}
|
||||
}
|
||||
|
||||
Result = CheckToolImage (&mImageInfo);
|
||||
if (!Result) {
|
||||
ToolImageDestruct (&mImageInfo);
|
||||
return RETURN_UNSUPPORTED;
|
||||
}
|
||||
|
||||
if (strcmp (FormatName, "PE") == 0) {
|
||||
OutputFile = ToolImageEmitPe (&mImageInfo, &OutputFileSize);
|
||||
} else {
|
||||
assert (false);
|
||||
}
|
||||
|
||||
ToolImageDestruct (&mImageInfo);
|
||||
|
||||
if (OutputFile == NULL) {
|
||||
return RETURN_ABORTED;
|
||||
}
|
||||
|
||||
UserWriteFile (OutputFileName, OutputFile, OutputFileSize);
|
||||
|
||||
free (OutputFile);
|
||||
|
||||
return RETURN_SUCCESS;
|
||||
}
|
||||
|
||||
int main (int argc, const char *argv[])
|
||||
{
|
||||
RETURN_STATUS Status;
|
||||
UINT32 NumOfFiles;
|
||||
|
||||
if (argc < 2) {
|
||||
fprintf (stderr, "ImageTool: No command is specified\n");
|
||||
raise ();
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (strcmp (argv[1], "ElfToPe") == 0 || strcmp (argv[1], "PeXip") == 0) {
|
||||
if (argc < 5) {
|
||||
fprintf (stderr, "ImageTool: Command arguments are missing\n");
|
||||
fprintf (stderr, " Usage: ImageTool %s InputFile OutputFile ModuleType\n", argv[1]);
|
||||
raise ();
|
||||
return -1;
|
||||
}
|
||||
|
||||
Status = GenExecutable (argv[3], argv[2], "PE", argv[4]);
|
||||
if (RETURN_ERROR (Status)) {
|
||||
raise ();
|
||||
return -1;
|
||||
}
|
||||
} else if (strcmp (argv[1], "HiiBinElf") == 0) {
|
||||
if (argc < 5) {
|
||||
fprintf (stderr, "ImageTool: Command arguments are missing\n");
|
||||
fprintf (stderr, " Usage: ImageTool HiiBinElf OutputFile GUID InputFile1 InputFile2 ...\n");
|
||||
raise ();
|
||||
return -1;
|
||||
}
|
||||
|
||||
NumOfFiles = (UINT32)argc - 4U;
|
||||
|
||||
Status = HiiBin (argv[2], argv[3], &argv[4], NumOfFiles, TRUE);
|
||||
if (RETURN_ERROR (Status)) {
|
||||
raise ();
|
||||
return -1;
|
||||
}
|
||||
} else if (strcmp (argv[1], "HiiBinPe") == 0) {
|
||||
if (argc < 5) {
|
||||
fprintf (stderr, "ImageTool: Command arguments are missing\n");
|
||||
fprintf (stderr, " Usage: ImageTool HiiBinPe OutputFile GUID InputFile1 InputFile2 ...\n");
|
||||
raise ();
|
||||
return -1;
|
||||
}
|
||||
|
||||
NumOfFiles = (UINT32)argc - 4U;
|
||||
|
||||
Status = HiiBin (argv[2], argv[3], &argv[4], NumOfFiles, FALSE);
|
||||
if (RETURN_ERROR (Status)) {
|
||||
raise ();
|
||||
return -1;
|
||||
}
|
||||
} else if (strcmp (argv[1], "Rebase") == 0) {
|
||||
if (argc < 5) {
|
||||
fprintf (stderr, "ImageTool: Command arguments are missing\n");
|
||||
fprintf (stderr, " Usage: ImageTool Rebase Address InputFile OutputFile\n");
|
||||
raise ();
|
||||
return -1;
|
||||
}
|
||||
|
||||
Status = Rebase (argv[2], argv[3], argv[4]);
|
||||
if (RETURN_ERROR (Status)) {
|
||||
raise ();
|
||||
return -1;
|
||||
}
|
||||
} else if (strcmp (argv[1], "GetAcpi") == 0) {
|
||||
if (argc < 4) {
|
||||
fprintf (stderr, "ImageTool: Command arguments are missing\n");
|
||||
fprintf (stderr, " Usage: ImageTool GetAcpi InputFile OutputFile\n");
|
||||
raise ();
|
||||
return -1;
|
||||
}
|
||||
|
||||
Status = GetAcpi (argv[2], argv[3]);
|
||||
if (RETURN_ERROR (Status)) {
|
||||
raise ();
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
181
BaseTools/ImageTool/ImageTool.h
Normal file
181
BaseTools/ImageTool/ImageTool.h
Normal file
@ -0,0 +1,181 @@
|
||||
/** @file
|
||||
Copyright (c) 2021, Marvin Häuser. All rights reserved.
|
||||
Copyright (c) 2022, Mikhail Krichanov. All rights reserved.
|
||||
SPDX-License-Identifier: BSD-3-Clause
|
||||
**/
|
||||
|
||||
#ifndef IMAGE_TOOL_H
|
||||
#define IMAGE_TOOL_H
|
||||
|
||||
#include <Base.h>
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <errno.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include <IndustryStandard/PeImage2.h>
|
||||
#include <Library/PeCoffLib2.h>
|
||||
#include <Library/BaseLib.h>
|
||||
#include <Library/BaseMemoryLib.h>
|
||||
#include <Library/BaseOverflowLib.h>
|
||||
#include <Library/MemoryAllocationLib.h>
|
||||
#include <UserFile.h>
|
||||
#include "../../UefiPayloadPkg/PayloadLoaderPeim/ElfLib/ElfCommon.h"
|
||||
|
||||
#undef ELF_R_TYPE
|
||||
#undef ELF_R_SYM
|
||||
|
||||
#ifdef EFI_TARGET32
|
||||
#include "../../UefiPayloadPkg/PayloadLoaderPeim/ElfLib/Elf32.h"
|
||||
|
||||
#define EFI_IMAGE_NT_HEADERS EFI_IMAGE_NT_HEADERS32
|
||||
#define EFI_IMAGE_NT_OPTIONAL_HDR_MAGIC EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
|
||||
#define EFI_IMAGE_FILE_MACHINE EFI_IMAGE_FILE_32BIT_MACHINE
|
||||
#define ELFCLASS ELFCLASS32
|
||||
#define Elf_Ehdr Elf32_Ehdr
|
||||
#define Elf_Shdr Elf32_Shdr
|
||||
#define Elf_Sym Elf32_Sym
|
||||
#define Elf_Rel Elf32_Rel
|
||||
#define Elf_Rela Elf32_Rela
|
||||
#define Elf_Size Elf32_Size
|
||||
#define Elf_Addr Elf32_Addr
|
||||
#define ELF_R_TYPE ELF32_R_TYPE
|
||||
#define ELF_R_SYM ELF32_R_SYM
|
||||
|
||||
#elif defined(EFI_TARGET64)
|
||||
#include "../../UefiPayloadPkg/PayloadLoaderPeim/ElfLib/Elf64.h"
|
||||
|
||||
#define EFI_IMAGE_NT_HEADERS EFI_IMAGE_NT_HEADERS64
|
||||
#define EFI_IMAGE_NT_OPTIONAL_HDR_MAGIC EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC
|
||||
#define EFI_IMAGE_FILE_MACHINE 0
|
||||
#define ELFCLASS ELFCLASS64
|
||||
#define Elf_Ehdr Elf64_Ehdr
|
||||
#define Elf_Shdr Elf64_Shdr
|
||||
#define Elf_Sym Elf64_Sym
|
||||
#define Elf_Rel Elf64_Rel
|
||||
#define Elf_Rela Elf64_Rela
|
||||
#define Elf_Size Elf64_Size
|
||||
#define Elf_Addr Elf64_Addr
|
||||
#define ELF_R_TYPE ELF64_R_TYPE
|
||||
#define ELF_R_SYM ELF64_R_SYM
|
||||
#endif
|
||||
|
||||
#define ELF_HII_SECTION_NAME ".hii"
|
||||
#define MAX_PE_ALIGNMENT 0x10000
|
||||
|
||||
#define raise() assert(false)
|
||||
|
||||
typedef struct {
|
||||
EFI_IMAGE_DEBUG_DIRECTORY_ENTRY Dir;
|
||||
EFI_IMAGE_DEBUG_CODEVIEW_NB10_ENTRY Nb10;
|
||||
char Name[];
|
||||
} DebugData;
|
||||
|
||||
#define PAGE(x) ((x) & ~4095U)
|
||||
#define PAGE_OFF(x) ((x) & 4095U)
|
||||
|
||||
typedef struct {
|
||||
uint64_t BaseAddress;
|
||||
uint32_t EntryPointAddress;
|
||||
uint16_t Machine;
|
||||
uint16_t Subsystem;
|
||||
bool IsXip;
|
||||
} image_tool_header_info_t;
|
||||
|
||||
typedef struct {
|
||||
char *Name;
|
||||
uint8_t *Data;
|
||||
uint32_t DataSize;
|
||||
uint64_t ImageAddress;
|
||||
uint32_t ImageSize;
|
||||
bool Read;
|
||||
bool Write;
|
||||
bool Execute;
|
||||
} image_tool_segment_t;
|
||||
|
||||
typedef struct {
|
||||
uint32_t SegmentAlignment;
|
||||
uint32_t NumSegments;
|
||||
image_tool_segment_t *Segments;
|
||||
} image_tool_segment_info_t;
|
||||
|
||||
typedef struct {
|
||||
uint8_t Type;
|
||||
uint32_t Target;
|
||||
} image_tool_reloc_t;
|
||||
|
||||
typedef struct {
|
||||
uint32_t NumRelocs;
|
||||
bool RelocsStripped;
|
||||
image_tool_reloc_t *Relocs;
|
||||
} image_tool_reloc_info_t;
|
||||
|
||||
typedef struct {
|
||||
char *SymbolsPath;
|
||||
uint32_t SymbolsPathLen;
|
||||
} image_tool_debug_info_t;
|
||||
|
||||
typedef struct {
|
||||
uint32_t DebugDirAddress;
|
||||
uint32_t DebugDirSize;
|
||||
} image_tool_pe_datadir_info_t;
|
||||
|
||||
typedef struct {
|
||||
void *Data;
|
||||
uint32_t DataSize;
|
||||
} image_tool_hii_info_t;
|
||||
|
||||
typedef struct {
|
||||
image_tool_header_info_t HeaderInfo;
|
||||
image_tool_segment_info_t SegmentInfo;
|
||||
image_tool_reloc_info_t RelocInfo;
|
||||
image_tool_hii_info_t HiiInfo;
|
||||
image_tool_debug_info_t DebugInfo;
|
||||
} image_tool_image_info_t;
|
||||
|
||||
void
|
||||
ToolImageDestruct (
|
||||
image_tool_image_info_t *Image
|
||||
);
|
||||
|
||||
bool
|
||||
ImageConvertToXip (
|
||||
image_tool_image_info_t *Image
|
||||
);
|
||||
|
||||
RETURN_STATUS
|
||||
ToolContextConstructPe (
|
||||
OUT image_tool_image_info_t *Image,
|
||||
IN const void *File,
|
||||
IN size_t FileSize
|
||||
);
|
||||
|
||||
bool
|
||||
CheckToolImage (
|
||||
image_tool_image_info_t *Image
|
||||
);
|
||||
|
||||
void *
|
||||
ToolImageEmitPe (
|
||||
const image_tool_image_info_t *Image,
|
||||
uint32_t *FileSize
|
||||
);
|
||||
|
||||
RETURN_STATUS
|
||||
ScanElf (
|
||||
IN const void *File,
|
||||
IN uint32_t FileSize,
|
||||
IN const char *SymbolsPath
|
||||
);
|
||||
|
||||
RETURN_STATUS
|
||||
ConstructHii (
|
||||
IN const char *FileNames[],
|
||||
IN UINT32 NumOfFiles,
|
||||
IN GUID *HiiGuid,
|
||||
OUT void **Hii,
|
||||
OUT UINT32 *HiiSize,
|
||||
IN BOOLEAN IsElf
|
||||
);
|
||||
|
||||
#endif // IMAGE_TOOL_H
|
104
BaseTools/ImageTool/Makefile
Normal file
104
BaseTools/ImageTool/Makefile
Normal file
@ -0,0 +1,104 @@
|
||||
## @file
|
||||
# Windows makefile for 'ImageTool' module build.
|
||||
#
|
||||
# Copyright (c) 2022, Mikhail Krichanov. All rights reserved.
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
#
|
||||
!INCLUDE ..\Source\C\Makefiles\ms.common
|
||||
|
||||
APP = ImageTool
|
||||
|
||||
OC_USER = ..\..\OpenCorePkg
|
||||
UDK_PATH = ..\..
|
||||
UDK_ARCH = $(HOST_ARCH)
|
||||
OUT_DIR = .\Windows_$(INFIX)
|
||||
|
||||
OV = $(UDK_PATH)\MdePkg\Library\BaseOverflowLib
|
||||
PE = $(UDK_PATH)\MdePkg\Library\BasePeCoffLib2
|
||||
UA = $(UDK_PATH)\MdePkg\Library\BaseUefiImageExtraActionLibNull
|
||||
|
||||
OBJECTS = ImageTool.obj Image.obj PeEmit.obj PeScan.obj ElfScan.obj BinEmit.obj
|
||||
OBJECTS = $(OBJECTS) {$(OV)}BaseAlignment.obj BaseBitOverflow.obj {$(UA)}UefiImageExtraActionLib.obj
|
||||
OBJECTS = $(OBJECTS) {$(PE)}PeCoffInit.obj PeCoffInfo.obj PeCoffRelocate.obj PeCoffLoad.obj PeCoffHii.obj PeCoffDebug.obj
|
||||
|
||||
BASE = $(UDK_PATH)\MdePkg\Library\BaseLib
|
||||
OUT = $(UDK_PATH)\MdePkg\Library\UefiDebugLibConOut
|
||||
PRIN = $(UDK_PATH)\MdePkg\Library\BasePrintLib
|
||||
ERRO = $(UDK_PATH)\MdePkg\Library\BaseDebugPrintErrorLevelLib
|
||||
BMPN = $(UDK_PATH)\MdeModulePkg\Library\BaseMemoryProfileLibNull
|
||||
CMEM = $(UDK_PATH)\MdeModulePkg\Library\CommonMemoryAllocationLib
|
||||
USER = $(OC_USER)\User\Library
|
||||
OBJECTS = $(OBJECTS) {$(BASE)}SafeString.obj String.obj SwapBytes16.obj SwapBytes32.obj CpuDeadLoop.obj CheckSum.obj
|
||||
OBJECTS = $(OBJECTS) {$(OUT)}DebugLib.obj {$(PRIN)}PrintLib.obj PrintLibInternal.obj {$(ERRO)}BaseDebugPrintErrorLevelLib.obj
|
||||
OBJECTS = $(OBJECTS) {$(USER)}UserFile.obj UserBaseMemoryLib.obj UserMath.obj UserPcd.obj UserMisc.obj UserGlobalVar.obj UserBootServices.obj
|
||||
OBJECTS = $(OBJECTS) {$(BMPN)}BaseMemoryProfileLibNull.obj {$(CMEM)}CommonMemoryAllocationLib.obj {$(CMEM)}CommonMemoryAllocationLibEx.obj
|
||||
|
||||
INC = -I . -I $(OC_USER)\User\Include -I $(OC_USER)\Include\Acidanthera
|
||||
INC = $(INC) -I $(UDK_PATH)\MdePkg\Include -I $(UDK_PATH)\MdePkg\Include\Library -I $(UDK_PATH)\MdePkg\Include\$(UDK_ARCH)
|
||||
INC = $(INC) -I $(UDK_PATH)\MdePkg\Library\BaseLib -I $(UDK_PATH)\MdeModulePkg\Include -I $(UDK_PATH)\UefiCpuPkg\Include
|
||||
INC = $(INC) /FI $(OC_USER)\User\Include\UserPcd.h /FI $(UDK_PATH)\MdePkg\Include\Base.h /FI $(OC_USER)\User\Include\UserGlobalVar.h
|
||||
|
||||
all:
|
||||
-if not exist $(OUT_DIR)64 mkdir $(OUT_DIR)64
|
||||
$(MAKE) $(APP)64 CFLAGS="$(CFLAGS) /D EFI_TARGET64" INFIX=64
|
||||
-if not exist $(OUT_DIR)32 mkdir $(OUT_DIR)32
|
||||
$(MAKE) $(APP)32 CFLAGS="$(CFLAGS) /D EFI_TARGET32" INFIX=32
|
||||
|
||||
$(APP)$(INFIX) : $(OBJECTS)
|
||||
-@if not exist $(BIN_PATH) mkdir $(BIN_PATH)
|
||||
@cd $(OUT_DIR)
|
||||
$(LD) /nologo /debug /OPT:REF /OPT:ICF=10 /incremental:no /nodefaultlib:libc.lib /out:..\$@ $(LIBS) $**
|
||||
@copy /y ..\$@ $(BIN_PATH)\$@.exe
|
||||
|
||||
.PHONY:clean
|
||||
.PHONY:cleanall
|
||||
|
||||
clean:
|
||||
del /f /q $(OUT_DIR)32 $(OUT_DIR)64 $(APP)32 $(APP)64 *.pdb > nul
|
||||
|
||||
cleanall:
|
||||
del /f /q $(OUT_DIR)32 $(OUT_DIR)64 *.pdb $(BIN_PATH)\$(APP)64.exe $(BIN_PATH)\$(APP)32.exe > nul
|
||||
|
||||
.c.obj :
|
||||
$(CC) -c $(CFLAGS) $(INC) $< -Fo$@
|
||||
@move $@ $(OUT_DIR)\
|
||||
|
||||
{$(OV)}.c.obj :
|
||||
$(CC) -c $(CFLAGS) $(INC) $< -Fo$@
|
||||
@move $@ $(OUT_DIR)\
|
||||
|
||||
{$(PE)}.c.obj :
|
||||
$(CC) -c $(CFLAGS) $(INC) $< -Fo$@
|
||||
@move $@ $(OUT_DIR)\
|
||||
|
||||
{$(UA)}.c.obj :
|
||||
$(CC) -c $(CFLAGS) $(INC) $< -Fo$@
|
||||
@move $@ $(OUT_DIR)\
|
||||
|
||||
{$(BASE)}.c.obj :
|
||||
$(CC) -c $(CFLAGS) $(INC) /wd 4005 $< -Fo$@
|
||||
@move $@ $(OUT_DIR)\
|
||||
|
||||
{$(BMPN)}.c.obj :
|
||||
$(CC) -c $(CFLAGS) $(INC) $< -Fo$@
|
||||
@move $@ $(OUT_DIR)\
|
||||
|
||||
{$(CMEM)}.c.obj :
|
||||
$(CC) -c $(CFLAGS) $(INC) $< -Fo$@
|
||||
@move $@ $(OUT_DIR)\
|
||||
|
||||
{$(OUT)}.c.obj :
|
||||
$(CC) -c $(CFLAGS) $(INC) $< -Fo$@
|
||||
@move $@ $(OUT_DIR)\
|
||||
|
||||
{$(PRIN)}.c.obj :
|
||||
$(CC) -c $(CFLAGS) $(INC) /wd 4005 $< -Fo$@
|
||||
@move $@ $(OUT_DIR)\
|
||||
|
||||
{$(ERRO)}.c.obj :
|
||||
$(CC) -c $(CFLAGS) $(INC) $< -Fo$@
|
||||
@move $@ $(OUT_DIR)\
|
||||
|
||||
{$(USER)}.c.obj :
|
||||
$(CC) -c $(CFLAGS) $(INC) /D WIN32 /wd 4754 $< -Fo$@
|
||||
@move $@ $(OUT_DIR)\
|
965
BaseTools/ImageTool/PeEmit.c
Normal file
965
BaseTools/ImageTool/PeEmit.c
Normal file
@ -0,0 +1,965 @@
|
||||
/** @file
|
||||
Copyright (c) 2021, Marvin Häuser. All rights reserved.
|
||||
Copyright (c) 2022, Mikhail Krichanov. All rights reserved.
|
||||
SPDX-License-Identifier: BSD-3-Clause
|
||||
**/
|
||||
|
||||
#include "ImageTool.h"
|
||||
|
||||
typedef struct {
|
||||
uint8_t NumExtraSections;
|
||||
uint32_t SizeOfHeaders;
|
||||
uint8_t NumberOfRvaAndSizes;
|
||||
uint16_t SizeOfOptionalHeader;
|
||||
uint32_t SectionHeadersSize;
|
||||
uint32_t ExtraSectionHeadersSize;
|
||||
} image_tool_emit_pe_hdr_info_t;
|
||||
|
||||
typedef struct {
|
||||
const image_tool_image_info_t *Image;
|
||||
EFI_IMAGE_NT_HEADERS *PeHdr;
|
||||
image_tool_emit_pe_hdr_info_t HdrInfo;
|
||||
uint32_t SectionsSize;
|
||||
uint32_t ExtraSectionsSize;
|
||||
uint32_t UnsignedFileSize;
|
||||
uint32_t RelocTableSize;
|
||||
uint32_t DebugTableSize;
|
||||
uint32_t FileAlignment;
|
||||
} image_tool_pe_emit_context_t;
|
||||
|
||||
static
|
||||
bool
|
||||
EmitPeGetHeaderSizes (
|
||||
const image_tool_image_info_t *Image,
|
||||
image_tool_emit_pe_hdr_info_t *HdrInfo
|
||||
)
|
||||
{
|
||||
assert (Image != NULL);
|
||||
assert (HdrInfo != NULL);
|
||||
|
||||
if (Image->RelocInfo.NumRelocs > 0) {
|
||||
HdrInfo->ExtraSectionHeadersSize += sizeof (EFI_IMAGE_SECTION_HEADER);
|
||||
}
|
||||
|
||||
if (Image->HiiInfo.DataSize > 0) {
|
||||
HdrInfo->ExtraSectionHeadersSize += sizeof (EFI_IMAGE_SECTION_HEADER);
|
||||
}
|
||||
|
||||
if (Image->DebugInfo.SymbolsPath != NULL) {
|
||||
HdrInfo->ExtraSectionHeadersSize += sizeof (EFI_IMAGE_SECTION_HEADER);
|
||||
}
|
||||
|
||||
HdrInfo->SectionHeadersSize = (uint32_t)Image->SegmentInfo.NumSegments * sizeof (EFI_IMAGE_SECTION_HEADER);
|
||||
HdrInfo->NumberOfRvaAndSizes = EFI_IMAGE_NUMBER_OF_DIRECTORY_ENTRIES;
|
||||
HdrInfo->SizeOfOptionalHeader = sizeof (EFI_IMAGE_NT_HEADERS) - sizeof (EFI_IMAGE_NT_HEADERS_COMMON_HDR)
|
||||
+ HdrInfo->NumberOfRvaAndSizes * sizeof (EFI_IMAGE_DATA_DIRECTORY);
|
||||
HdrInfo->SizeOfHeaders = sizeof (EFI_IMAGE_DOS_HEADER) + sizeof (EFI_IMAGE_NT_HEADERS)
|
||||
+ HdrInfo->NumberOfRvaAndSizes * sizeof (EFI_IMAGE_DATA_DIRECTORY)
|
||||
+ HdrInfo->SectionHeadersSize + HdrInfo->ExtraSectionHeadersSize;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static
|
||||
bool
|
||||
EmitPeGetSectionsSize (
|
||||
const image_tool_pe_emit_context_t *Context,
|
||||
uint32_t *SectionsSize
|
||||
)
|
||||
{
|
||||
const image_tool_image_info_t *Image;
|
||||
uint8_t Index;
|
||||
uint32_t DataSize;
|
||||
bool Overflow;
|
||||
|
||||
assert (Context != NULL);
|
||||
assert (SectionsSize != NULL);
|
||||
|
||||
Image = Context->Image;
|
||||
*SectionsSize = 0;
|
||||
|
||||
for (Index = 0; Index < Image->SegmentInfo.NumSegments; ++Index) {
|
||||
Overflow = BaseOverflowAlignUpU32 (
|
||||
Image->SegmentInfo.Segments[Index].DataSize,
|
||||
Context->FileAlignment,
|
||||
&DataSize
|
||||
);
|
||||
if (Overflow) {
|
||||
raise ();
|
||||
return false;
|
||||
}
|
||||
|
||||
Overflow = BaseOverflowAddU32 (*SectionsSize, DataSize, SectionsSize);
|
||||
if (Overflow) {
|
||||
raise ();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static
|
||||
bool
|
||||
EmitPeGetRelocSectionSize (
|
||||
const image_tool_image_info_t *Image,
|
||||
uint32_t *RelocsSize
|
||||
)
|
||||
{
|
||||
uint32_t RelocTableSize;
|
||||
uint32_t BlockAddress;
|
||||
uint32_t BlockSize;
|
||||
uint32_t Index;
|
||||
uint32_t RelocAddress;
|
||||
|
||||
assert (Image != NULL);
|
||||
assert (RelocsSize != NULL);
|
||||
|
||||
if (Image->RelocInfo.NumRelocs == 0) {
|
||||
*RelocsSize = 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
assert (Image->RelocInfo.NumRelocs <= MAX_UINT32);
|
||||
|
||||
RelocTableSize = 0;
|
||||
BlockAddress = PAGE(Image->RelocInfo.Relocs[0].Target);
|
||||
BlockSize = sizeof (EFI_IMAGE_BASE_RELOCATION_BLOCK);
|
||||
|
||||
for (Index = 0; Index < Image->RelocInfo.NumRelocs; ++Index) {
|
||||
RelocAddress = PAGE(Image->RelocInfo.Relocs[Index].Target);
|
||||
if (RelocAddress != BlockAddress) {
|
||||
BlockSize = ALIGN_VALUE (BlockSize, 4);
|
||||
|
||||
RelocTableSize += BlockSize;
|
||||
|
||||
BlockAddress = RelocAddress;
|
||||
BlockSize = sizeof (EFI_IMAGE_BASE_RELOCATION_BLOCK);
|
||||
}
|
||||
|
||||
BlockSize += sizeof (UINT16);
|
||||
}
|
||||
|
||||
BlockSize = ALIGN_VALUE (BlockSize, 4);
|
||||
RelocTableSize += BlockSize;
|
||||
|
||||
*RelocsSize = RelocTableSize;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
EmitPeGetDebugSectionSize (
|
||||
const image_tool_image_info_t *Image,
|
||||
uint32_t *DebugSize
|
||||
)
|
||||
{
|
||||
uint32_t Size;
|
||||
|
||||
assert (Image != NULL);
|
||||
assert (DebugSize != NULL);
|
||||
|
||||
Size = 0;
|
||||
if (Image->DebugInfo.SymbolsPath != NULL) {
|
||||
Size = sizeof (DebugData) + Image->DebugInfo.SymbolsPathLen + 1;
|
||||
}
|
||||
|
||||
*DebugSize = Size;
|
||||
}
|
||||
|
||||
static
|
||||
bool
|
||||
EmitPeGetExtraSectionsSize (
|
||||
image_tool_pe_emit_context_t *Context,
|
||||
uint32_t *SectionsSize
|
||||
)
|
||||
{
|
||||
const image_tool_image_info_t *Image;
|
||||
bool Result;
|
||||
uint32_t AlignedRelocTableSize;
|
||||
bool Overflow;
|
||||
uint32_t AlignedDebugTableSize;
|
||||
uint32_t AlignedHiiTableSize;
|
||||
|
||||
assert (Context != NULL);
|
||||
assert (SectionsSize != NULL);
|
||||
|
||||
Image = Context->Image;
|
||||
|
||||
Result = EmitPeGetRelocSectionSize (Image, &Context->RelocTableSize);
|
||||
if (!Result) {
|
||||
raise ();
|
||||
return false;
|
||||
}
|
||||
|
||||
EmitPeGetDebugSectionSize (Image, &Context->DebugTableSize);
|
||||
|
||||
Overflow = BaseOverflowAlignUpU32 (
|
||||
Context->RelocTableSize,
|
||||
Context->FileAlignment,
|
||||
&AlignedRelocTableSize
|
||||
);
|
||||
if (Overflow) {
|
||||
raise ();
|
||||
return false;
|
||||
}
|
||||
|
||||
Overflow = BaseOverflowAlignUpU32 (
|
||||
Context->DebugTableSize,
|
||||
Context->FileAlignment,
|
||||
&AlignedDebugTableSize
|
||||
);
|
||||
if (Overflow) {
|
||||
raise ();
|
||||
return false;
|
||||
}
|
||||
|
||||
Overflow = BaseOverflowAlignUpU32 (
|
||||
Context->Image->HiiInfo.DataSize,
|
||||
Context->FileAlignment,
|
||||
&AlignedHiiTableSize
|
||||
);
|
||||
if (Overflow) {
|
||||
raise ();
|
||||
return false;
|
||||
}
|
||||
|
||||
Overflow = BaseOverflowAddU32 (
|
||||
AlignedRelocTableSize,
|
||||
AlignedDebugTableSize,
|
||||
SectionsSize
|
||||
);
|
||||
if (Overflow) {
|
||||
raise ();
|
||||
return false;
|
||||
}
|
||||
|
||||
Overflow = BaseOverflowAddU32 (
|
||||
*SectionsSize,
|
||||
AlignedHiiTableSize,
|
||||
SectionsSize
|
||||
);
|
||||
if (Overflow) {
|
||||
raise ();
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static
|
||||
bool
|
||||
ToolImageEmitPeSectionHeaders (
|
||||
const image_tool_pe_emit_context_t *Context,
|
||||
uint8_t **Buffer,
|
||||
uint32_t *BufferSize,
|
||||
uint32_t AlignedHeaderSize
|
||||
)
|
||||
{
|
||||
const image_tool_image_info_t *Image;
|
||||
uint16_t SectionHeadersSize;
|
||||
uint32_t SectionOffset;
|
||||
EFI_IMAGE_SECTION_HEADER *Sections;
|
||||
uint8_t Index;
|
||||
|
||||
assert (Context != NULL);
|
||||
assert (Buffer != NULL);
|
||||
assert (BufferSize != NULL);
|
||||
|
||||
Image = Context->Image;
|
||||
SectionHeadersSize = (uint16_t) (Image->SegmentInfo.NumSegments * sizeof (EFI_IMAGE_SECTION_HEADER));
|
||||
SectionOffset = AlignedHeaderSize;
|
||||
Sections = (void *) *Buffer;
|
||||
|
||||
assert (SectionHeadersSize <= *BufferSize);
|
||||
|
||||
for (Index = 0; Index < Image->SegmentInfo.NumSegments; ++Index) {
|
||||
assert (Sections[Index].Characteristics == 0);
|
||||
|
||||
if (Image->SegmentInfo.Segments[Index].Read) {
|
||||
Sections[Index].Characteristics |= EFI_IMAGE_SCN_MEM_READ;
|
||||
}
|
||||
|
||||
if (Image->SegmentInfo.Segments[Index].Write) {
|
||||
Sections[Index].Characteristics |= EFI_IMAGE_SCN_MEM_WRITE;
|
||||
}
|
||||
|
||||
if (Image->SegmentInfo.Segments[Index].Execute) {
|
||||
Sections[Index].Characteristics |= EFI_IMAGE_SCN_MEM_EXECUTE | EFI_IMAGE_SCN_CNT_CODE;
|
||||
} else {
|
||||
Sections[Index].Characteristics |= EFI_IMAGE_SCN_CNT_INITIALIZED_DATA;
|
||||
}
|
||||
|
||||
Sections[Index].PointerToRawData = SectionOffset;
|
||||
Sections[Index].VirtualAddress = SectionOffset;
|
||||
Sections[Index].SizeOfRawData = ALIGN_VALUE (Image->SegmentInfo.Segments[Index].DataSize, Context->FileAlignment);
|
||||
Sections[Index].VirtualSize = Image->SegmentInfo.Segments[Index].ImageSize;
|
||||
|
||||
strncpy (
|
||||
(char *) Sections[Index].Name,
|
||||
Image->SegmentInfo.Segments[Index].Name,
|
||||
sizeof (Sections[Index].Name)
|
||||
);
|
||||
|
||||
SectionOffset += Sections[Index].SizeOfRawData;
|
||||
}
|
||||
|
||||
*BufferSize -= SectionHeadersSize;
|
||||
*Buffer += SectionHeadersSize;
|
||||
|
||||
assert (SectionHeadersSize == Context->HdrInfo.SectionHeadersSize);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static
|
||||
bool
|
||||
ToolImageEmitPeExtraSectionHeaders (
|
||||
image_tool_pe_emit_context_t *Context,
|
||||
uint8_t **Buffer,
|
||||
uint32_t *BufferSize,
|
||||
uint32_t AlignedHeaderSize
|
||||
)
|
||||
{
|
||||
uint32_t SectionHeadersSize;
|
||||
EFI_IMAGE_SECTION_HEADER *Section;
|
||||
uint32_t SectionOffset;
|
||||
|
||||
assert (Context != NULL);
|
||||
assert (Buffer != NULL);
|
||||
assert (BufferSize != NULL);
|
||||
|
||||
SectionHeadersSize = 0;
|
||||
SectionOffset = AlignedHeaderSize + Context->SectionsSize;
|
||||
|
||||
if (Context->Image->HiiInfo.DataSize > 0) {
|
||||
++Context->PeHdr->CommonHeader.FileHeader.NumberOfSections;
|
||||
|
||||
assert (sizeof (EFI_IMAGE_SECTION_HEADER) <= *BufferSize);
|
||||
|
||||
Section = (void *) *Buffer;
|
||||
|
||||
strncpy ((char *)Section->Name, ".rsrc", sizeof (Section->Name));
|
||||
Section->SizeOfRawData = ALIGN_VALUE (Context->Image->HiiInfo.DataSize, Context->FileAlignment);
|
||||
Section->VirtualSize = Section->SizeOfRawData;
|
||||
Section->Characteristics = EFI_IMAGE_SCN_CNT_INITIALIZED_DATA | EFI_IMAGE_SCN_MEM_READ;
|
||||
Section->PointerToRawData = SectionOffset;
|
||||
Section->VirtualAddress = Section->PointerToRawData;
|
||||
|
||||
SectionOffset += Section->SizeOfRawData;
|
||||
|
||||
Context->PeHdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE].Size = Context->Image->HiiInfo.DataSize;
|
||||
Context->PeHdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE].VirtualAddress = Section->PointerToRawData;
|
||||
|
||||
*BufferSize -= sizeof (EFI_IMAGE_SECTION_HEADER);
|
||||
*Buffer += sizeof (EFI_IMAGE_SECTION_HEADER);
|
||||
SectionHeadersSize += sizeof (EFI_IMAGE_SECTION_HEADER);
|
||||
}
|
||||
|
||||
if (Context->RelocTableSize > 0) {
|
||||
++Context->PeHdr->CommonHeader.FileHeader.NumberOfSections;
|
||||
|
||||
assert (sizeof (EFI_IMAGE_SECTION_HEADER) <= *BufferSize);
|
||||
|
||||
Section = (void *) *Buffer;
|
||||
|
||||
strncpy ((char *)Section->Name, ".reloc", sizeof (Section->Name));
|
||||
Section->SizeOfRawData = ALIGN_VALUE (Context->RelocTableSize, Context->FileAlignment);
|
||||
Section->VirtualSize = Section->SizeOfRawData;
|
||||
Section->Characteristics = EFI_IMAGE_SCN_CNT_INITIALIZED_DATA
|
||||
| EFI_IMAGE_SCN_MEM_DISCARDABLE | EFI_IMAGE_SCN_MEM_READ;
|
||||
Section->PointerToRawData = SectionOffset;
|
||||
Section->VirtualAddress = Section->PointerToRawData;
|
||||
|
||||
SectionOffset += Section->SizeOfRawData;
|
||||
|
||||
Context->PeHdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size = Context->RelocTableSize;
|
||||
Context->PeHdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress = Section->PointerToRawData;
|
||||
|
||||
*BufferSize -= sizeof (EFI_IMAGE_SECTION_HEADER);
|
||||
*Buffer += sizeof (EFI_IMAGE_SECTION_HEADER);
|
||||
SectionHeadersSize += sizeof (EFI_IMAGE_SECTION_HEADER);
|
||||
}
|
||||
|
||||
if (Context->DebugTableSize > 0) {
|
||||
++Context->PeHdr->CommonHeader.FileHeader.NumberOfSections;
|
||||
|
||||
assert (sizeof (EFI_IMAGE_SECTION_HEADER) <= *BufferSize);
|
||||
|
||||
Section = (void *) *Buffer;
|
||||
|
||||
strncpy ((char *)Section->Name, ".debug", sizeof (Section->Name));
|
||||
Section->SizeOfRawData = ALIGN_VALUE (Context->DebugTableSize, Context->FileAlignment);
|
||||
Section->VirtualSize = Section->SizeOfRawData;
|
||||
Section->Characteristics = EFI_IMAGE_SCN_CNT_INITIALIZED_DATA | EFI_IMAGE_SCN_MEM_READ;
|
||||
Section->PointerToRawData = SectionOffset;
|
||||
Section->VirtualAddress = Section->PointerToRawData;
|
||||
|
||||
SectionOffset += Section->SizeOfRawData;
|
||||
|
||||
Context->PeHdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].Size = sizeof (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY);
|
||||
Context->PeHdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress = Section->VirtualAddress;
|
||||
|
||||
*BufferSize -= sizeof (EFI_IMAGE_SECTION_HEADER);
|
||||
*Buffer += sizeof (EFI_IMAGE_SECTION_HEADER);
|
||||
SectionHeadersSize += sizeof (EFI_IMAGE_SECTION_HEADER);
|
||||
}
|
||||
|
||||
assert (SectionHeadersSize == Context->HdrInfo.ExtraSectionHeadersSize);
|
||||
assert (SectionOffset == Context->UnsignedFileSize);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static
|
||||
bool
|
||||
ToolImageEmitPeHeaders (
|
||||
image_tool_pe_emit_context_t *Context,
|
||||
uint8_t **Buffer,
|
||||
uint32_t *BufferSize,
|
||||
uint32_t AlignedHeaderSize
|
||||
)
|
||||
{
|
||||
const image_tool_image_info_t *Image;
|
||||
EFI_IMAGE_DOS_HEADER *DosHdr;
|
||||
EFI_IMAGE_NT_HEADERS *PePlusHdr;
|
||||
bool Result;
|
||||
uint32_t HeaderPadding;
|
||||
|
||||
assert (Context != NULL);
|
||||
assert (Buffer != NULL);
|
||||
assert (BufferSize != NULL);
|
||||
|
||||
assert (sizeof (EFI_IMAGE_DOS_HEADER) <= *BufferSize);
|
||||
|
||||
Image = Context->Image;
|
||||
DosHdr = (void *) *Buffer;
|
||||
|
||||
DosHdr->e_magic = EFI_IMAGE_DOS_SIGNATURE;
|
||||
DosHdr->e_lfanew = sizeof (EFI_IMAGE_DOS_HEADER);
|
||||
|
||||
*BufferSize -= sizeof (EFI_IMAGE_DOS_HEADER);
|
||||
*Buffer += sizeof (EFI_IMAGE_DOS_HEADER);
|
||||
|
||||
assert (sizeof (EFI_IMAGE_NT_HEADERS) <= *BufferSize);
|
||||
|
||||
PePlusHdr = (EFI_IMAGE_NT_HEADERS *)(VOID *) *Buffer;
|
||||
|
||||
PePlusHdr->CommonHeader.Signature = EFI_IMAGE_NT_SIGNATURE;
|
||||
PePlusHdr->CommonHeader.FileHeader.Machine = Image->HeaderInfo.Machine;
|
||||
PePlusHdr->CommonHeader.FileHeader.NumberOfSections = (UINT16)Image->SegmentInfo.NumSegments;
|
||||
PePlusHdr->CommonHeader.FileHeader.SizeOfOptionalHeader = Context->HdrInfo.SizeOfOptionalHeader;
|
||||
PePlusHdr->CommonHeader.FileHeader.Characteristics =
|
||||
EFI_IMAGE_FILE_EXECUTABLE_IMAGE | EFI_IMAGE_FILE_LINE_NUMS_STRIPPED |
|
||||
EFI_IMAGE_FILE_LOCAL_SYMS_STRIPPED | EFI_IMAGE_FILE_LARGE_ADDRESS_AWARE;
|
||||
|
||||
if (Image->RelocInfo.RelocsStripped) {
|
||||
PePlusHdr->CommonHeader.FileHeader.Characteristics |= EFI_IMAGE_FILE_RELOCS_STRIPPED;
|
||||
}
|
||||
|
||||
PePlusHdr->Magic = EFI_IMAGE_NT_OPTIONAL_HDR_MAGIC;
|
||||
PePlusHdr->AddressOfEntryPoint = Image->HeaderInfo.EntryPointAddress;
|
||||
PePlusHdr->SectionAlignment = Image->SegmentInfo.SegmentAlignment;
|
||||
PePlusHdr->FileAlignment = Context->FileAlignment;
|
||||
PePlusHdr->SizeOfHeaders = AlignedHeaderSize;
|
||||
PePlusHdr->SizeOfImage = AlignedHeaderSize;
|
||||
PePlusHdr->ImageBase = (UINTN)Image->HeaderInfo.BaseAddress;
|
||||
PePlusHdr->Subsystem = Image->HeaderInfo.Subsystem;
|
||||
PePlusHdr->NumberOfRvaAndSizes = Context->HdrInfo.NumberOfRvaAndSizes;
|
||||
|
||||
STATIC_ASSERT(
|
||||
OFFSET_OF(EFI_IMAGE_NT_HEADERS, DataDirectory) == sizeof (EFI_IMAGE_NT_HEADERS),
|
||||
"The following code needs to be updated to consider padding."
|
||||
);
|
||||
|
||||
Context->PeHdr = PePlusHdr;
|
||||
|
||||
*BufferSize -= sizeof (EFI_IMAGE_NT_HEADERS) + PePlusHdr->NumberOfRvaAndSizes * sizeof (EFI_IMAGE_DATA_DIRECTORY);
|
||||
*Buffer += sizeof (EFI_IMAGE_NT_HEADERS) + PePlusHdr->NumberOfRvaAndSizes * sizeof (EFI_IMAGE_DATA_DIRECTORY);
|
||||
|
||||
Result = ToolImageEmitPeSectionHeaders (Context, Buffer, BufferSize, AlignedHeaderSize);
|
||||
if (!Result) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Result = ToolImageEmitPeExtraSectionHeaders (Context, Buffer, BufferSize, AlignedHeaderSize);
|
||||
if (!Result) {
|
||||
return false;
|
||||
}
|
||||
|
||||
HeaderPadding = AlignedHeaderSize - Context->HdrInfo.SizeOfHeaders;
|
||||
|
||||
assert (HeaderPadding <= *BufferSize);
|
||||
|
||||
*BufferSize -= HeaderPadding;
|
||||
*Buffer += HeaderPadding;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static
|
||||
bool
|
||||
ToolImageEmitPeSections (
|
||||
const image_tool_pe_emit_context_t *Context,
|
||||
uint8_t **Buffer,
|
||||
uint32_t *BufferSize
|
||||
)
|
||||
{
|
||||
const image_tool_image_info_t *Image;
|
||||
uint32_t SectionsSize;
|
||||
uint8_t Index;
|
||||
const image_tool_segment_t *Segment;
|
||||
uint32_t SectionPadding;
|
||||
bool FirstCode;
|
||||
|
||||
#if defined(EFI_TARGET32)
|
||||
bool FirstData;
|
||||
#endif
|
||||
|
||||
assert (Context != NULL);
|
||||
assert (Buffer != NULL);
|
||||
assert (BufferSize != NULL);
|
||||
|
||||
assert (Context->SectionsSize <= *BufferSize);
|
||||
|
||||
Image = Context->Image;
|
||||
SectionsSize = 0;
|
||||
FirstCode = true;
|
||||
|
||||
#if defined(EFI_TARGET32)
|
||||
FirstData = true;
|
||||
#endif
|
||||
|
||||
for (Index = 0; Index < Image->SegmentInfo.NumSegments; ++Index) {
|
||||
Segment = &Image->SegmentInfo.Segments[Index];
|
||||
|
||||
Context->PeHdr->SizeOfImage += Segment->ImageSize;
|
||||
|
||||
if (Segment->Execute) {
|
||||
if (FirstCode) {
|
||||
Context->PeHdr->BaseOfCode = (UINT32)Segment->ImageAddress;
|
||||
FirstCode = false;
|
||||
}
|
||||
}
|
||||
#if defined(EFI_TARGET32)
|
||||
else {
|
||||
if (FirstData) {
|
||||
Context->PeHdr->BaseOfData = (UINT32)Segment->ImageAddress;
|
||||
FirstData = false;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
assert (Segment->DataSize <= *BufferSize);
|
||||
|
||||
memmove (*Buffer, Segment->Data, Segment->DataSize);
|
||||
|
||||
*BufferSize -= Segment->DataSize;
|
||||
*Buffer += Segment->DataSize;
|
||||
SectionsSize += Segment->DataSize;
|
||||
|
||||
SectionPadding = ALIGN_VALUE_ADDEND (
|
||||
Segment->DataSize,
|
||||
Context->FileAlignment
|
||||
);
|
||||
|
||||
assert (SectionPadding <= *BufferSize);
|
||||
|
||||
*BufferSize -= SectionPadding;
|
||||
*Buffer += SectionPadding;
|
||||
SectionsSize += SectionPadding;
|
||||
|
||||
if (Segment->Execute) {
|
||||
Context->PeHdr->BaseOfCode = MIN(Context->PeHdr->BaseOfCode, (UINT32)Segment->ImageAddress);
|
||||
Context->PeHdr->SizeOfCode += Segment->ImageSize;
|
||||
} else {
|
||||
#if defined(EFI_TARGET32)
|
||||
Context->PeHdr->BaseOfData = MIN(Context->PeHdr->BaseOfData, (UINT32)Segment->ImageAddress);
|
||||
#endif
|
||||
Context->PeHdr->SizeOfInitializedData += Segment->ImageSize;
|
||||
}
|
||||
}
|
||||
|
||||
assert (SectionsSize == Context->SectionsSize);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static
|
||||
bool
|
||||
ToolImageEmitPeRelocTable (
|
||||
const image_tool_pe_emit_context_t *Context,
|
||||
uint8_t **Buffer,
|
||||
uint32_t *BufferSize
|
||||
)
|
||||
{
|
||||
const image_tool_image_info_t *Image;
|
||||
uint32_t RelocTableSize;
|
||||
EFI_IMAGE_BASE_RELOCATION_BLOCK *RelocBlock;
|
||||
uint32_t BlockAddress;
|
||||
uint32_t BlockNumRelocs;
|
||||
uint32_t Index;
|
||||
uint32_t RelocAddress;
|
||||
uint32_t RelocTablePadding;
|
||||
|
||||
assert (Context != NULL);
|
||||
assert (Buffer != NULL);
|
||||
assert (BufferSize != NULL);
|
||||
|
||||
if (Context->RelocTableSize == 0) {
|
||||
return true;
|
||||
}
|
||||
|
||||
Image = Context->Image;
|
||||
|
||||
Context->PeHdr->SizeOfImage += ALIGN_VALUE (Context->RelocTableSize, Image->SegmentInfo.SegmentAlignment);
|
||||
|
||||
assert (Image->RelocInfo.NumRelocs > 0);
|
||||
assert (Image->RelocInfo.NumRelocs <= MAX_UINT32);
|
||||
|
||||
assert (sizeof (EFI_IMAGE_BASE_RELOCATION_BLOCK) <= *BufferSize);
|
||||
|
||||
RelocTableSize = 0;
|
||||
RelocBlock = (void *) *Buffer;
|
||||
BlockAddress = PAGE(Image->RelocInfo.Relocs[0].Target);
|
||||
BlockNumRelocs = 0;
|
||||
|
||||
RelocBlock->VirtualAddress = BlockAddress;
|
||||
RelocBlock->SizeOfBlock = sizeof (*RelocBlock);
|
||||
|
||||
for (Index = 0; Index < Image->RelocInfo.NumRelocs; ++Index) {
|
||||
RelocAddress = PAGE(Image->RelocInfo.Relocs[Index].Target);
|
||||
if (RelocAddress != BlockAddress) {
|
||||
RelocBlock->SizeOfBlock = ALIGN_VALUE (RelocBlock->SizeOfBlock, 4);
|
||||
|
||||
assert (RelocBlock->SizeOfBlock <= *BufferSize);
|
||||
|
||||
*BufferSize -= RelocBlock->SizeOfBlock;
|
||||
*Buffer += RelocBlock->SizeOfBlock;
|
||||
RelocTableSize += RelocBlock->SizeOfBlock;
|
||||
|
||||
RelocBlock = (void *) *Buffer;
|
||||
|
||||
BlockAddress = RelocAddress;
|
||||
BlockNumRelocs = 0;
|
||||
|
||||
RelocBlock->VirtualAddress = BlockAddress;
|
||||
RelocBlock->SizeOfBlock = sizeof (*RelocBlock);
|
||||
}
|
||||
|
||||
RelocBlock->SizeOfBlock += sizeof (*RelocBlock->Relocations);
|
||||
|
||||
assert (RelocBlock->SizeOfBlock <= *BufferSize);
|
||||
|
||||
RelocBlock->Relocations[BlockNumRelocs] = PAGE_OFF(Image->RelocInfo.Relocs[Index].Target);
|
||||
RelocBlock->Relocations[BlockNumRelocs] |= ((uint16_t)Image->RelocInfo.Relocs[Index].Type) << 12U;
|
||||
|
||||
++BlockNumRelocs;
|
||||
}
|
||||
|
||||
RelocBlock->SizeOfBlock = ALIGN_VALUE (RelocBlock->SizeOfBlock, 4);
|
||||
|
||||
assert (RelocBlock->SizeOfBlock <= *BufferSize);
|
||||
|
||||
*BufferSize -= RelocBlock->SizeOfBlock;
|
||||
*Buffer += RelocBlock->SizeOfBlock;
|
||||
RelocTableSize += RelocBlock->SizeOfBlock;
|
||||
|
||||
assert (RelocTableSize == Context->RelocTableSize);
|
||||
|
||||
RelocTablePadding = ALIGN_VALUE_ADDEND (
|
||||
RelocTableSize,
|
||||
Context->FileAlignment
|
||||
);
|
||||
|
||||
assert (RelocTablePadding <= *BufferSize);
|
||||
|
||||
*BufferSize -= RelocTablePadding;
|
||||
*Buffer += RelocTablePadding;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
EFI_IMAGE_DEBUG_DIRECTORY_ENTRY CodeViewDirEntry;
|
||||
EFI_IMAGE_DEBUG_CODEVIEW_RSDS_ENTRY CodeViewEntry;
|
||||
uint8_t PdbPath[];
|
||||
} image_tool_debug_dir_t;
|
||||
|
||||
STATIC_ASSERT(
|
||||
OFFSET_OF(image_tool_debug_dir_t, PdbPath) == sizeof (image_tool_debug_dir_t),
|
||||
"Flexible array aliases padding."
|
||||
);
|
||||
|
||||
static
|
||||
bool
|
||||
ToolImageEmitPeDebugTable (
|
||||
const image_tool_pe_emit_context_t *Context,
|
||||
uint8_t **Buffer,
|
||||
uint32_t *BufferSize
|
||||
)
|
||||
{
|
||||
const image_tool_image_info_t *Image;
|
||||
uint32_t DebugTablePadding;
|
||||
DebugData *Data;
|
||||
|
||||
assert (Context != NULL);
|
||||
assert (Buffer != NULL);
|
||||
assert (BufferSize != NULL);
|
||||
|
||||
Image = Context->Image;
|
||||
|
||||
if (Context->DebugTableSize == 0) {
|
||||
return true;
|
||||
}
|
||||
|
||||
Context->PeHdr->SizeOfImage += ALIGN_VALUE (Context->DebugTableSize, Image->SegmentInfo.SegmentAlignment);
|
||||
|
||||
assert (Image->DebugInfo.SymbolsPathLen + 1 <= Context->DebugTableSize);
|
||||
assert (Context->DebugTableSize <= *BufferSize);
|
||||
|
||||
Data = (DebugData *) *Buffer;
|
||||
|
||||
Data->Dir.Type = EFI_IMAGE_DEBUG_TYPE_CODEVIEW;
|
||||
Data->Dir.SizeOfData = sizeof (EFI_IMAGE_DEBUG_CODEVIEW_NB10_ENTRY) + Image->DebugInfo.SymbolsPathLen + 1;
|
||||
Data->Dir.RVA = (Context->UnsignedFileSize - ALIGN_VALUE (Context->DebugTableSize, Context->FileAlignment)) + sizeof (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY);
|
||||
Data->Dir.FileOffset = Data->Dir.RVA;
|
||||
|
||||
Data->Nb10.Signature = CODEVIEW_SIGNATURE_NB10;
|
||||
memmove (Data->Name, Image->DebugInfo.SymbolsPath, Image->DebugInfo.SymbolsPathLen + 1);
|
||||
|
||||
assert (sizeof (*Data) + Image->DebugInfo.SymbolsPathLen + 1 == Context->DebugTableSize);
|
||||
|
||||
*BufferSize -= Context->DebugTableSize;
|
||||
*Buffer += Context->DebugTableSize;
|
||||
|
||||
DebugTablePadding = ALIGN_VALUE_ADDEND(
|
||||
Context->DebugTableSize,
|
||||
Context->FileAlignment
|
||||
);
|
||||
|
||||
assert (DebugTablePadding <= *BufferSize);
|
||||
|
||||
*BufferSize -= DebugTablePadding;
|
||||
*Buffer += DebugTablePadding;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static
|
||||
bool
|
||||
ToolImageEmitPeHiiTable (
|
||||
const image_tool_pe_emit_context_t *Context,
|
||||
uint8_t **Buffer,
|
||||
uint32_t *BufferSize
|
||||
)
|
||||
{
|
||||
const image_tool_image_info_t *Image;
|
||||
uint32_t HiiTablePadding;
|
||||
|
||||
assert (Context != NULL);
|
||||
assert (Buffer != NULL);
|
||||
assert (BufferSize != NULL);
|
||||
|
||||
Image = Context->Image;
|
||||
|
||||
if (Image->HiiInfo.DataSize == 0) {
|
||||
return true;
|
||||
}
|
||||
|
||||
Context->PeHdr->SizeOfImage += ALIGN_VALUE (Image->HiiInfo.DataSize, Image->SegmentInfo.SegmentAlignment);
|
||||
|
||||
assert (Image->HiiInfo.DataSize <= *BufferSize);
|
||||
|
||||
memmove (*Buffer, Image->HiiInfo.Data, Image->HiiInfo.DataSize);
|
||||
|
||||
*BufferSize -= Image->HiiInfo.DataSize;
|
||||
*Buffer += Image->HiiInfo.DataSize;
|
||||
|
||||
HiiTablePadding = ALIGN_VALUE_ADDEND(
|
||||
Image->HiiInfo.DataSize,
|
||||
Context->FileAlignment
|
||||
);
|
||||
|
||||
assert (HiiTablePadding <= *BufferSize);
|
||||
|
||||
*BufferSize -= HiiTablePadding;
|
||||
*Buffer += HiiTablePadding;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static
|
||||
bool
|
||||
ToolImageEmitPeExtraSections (
|
||||
const image_tool_pe_emit_context_t *Context,
|
||||
uint8_t **Buffer,
|
||||
uint32_t *BufferSize
|
||||
)
|
||||
{
|
||||
uint32_t OldBufferSize;
|
||||
bool Result;
|
||||
|
||||
assert (Context != NULL);
|
||||
assert (Buffer != NULL);
|
||||
assert (BufferSize != NULL);
|
||||
|
||||
OldBufferSize = *BufferSize;
|
||||
|
||||
Result = ToolImageEmitPeHiiTable (Context, Buffer, BufferSize);
|
||||
if (!Result) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Result = ToolImageEmitPeRelocTable (Context, Buffer, BufferSize);
|
||||
if (!Result) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Result = ToolImageEmitPeDebugTable (Context, Buffer, BufferSize);
|
||||
if (!Result) {
|
||||
return false;
|
||||
}
|
||||
|
||||
assert ((OldBufferSize - *BufferSize) == Context->ExtraSectionsSize);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void *
|
||||
ToolImageEmitPe (
|
||||
const image_tool_image_info_t *Image,
|
||||
uint32_t *FileSize
|
||||
)
|
||||
{
|
||||
image_tool_pe_emit_context_t Context;
|
||||
bool Result;
|
||||
uint32_t AlignedHeaderSize;
|
||||
bool Overflow;
|
||||
uint32_t SectionsOffset;
|
||||
void *FileBuffer;
|
||||
uint8_t *Buffer;
|
||||
uint32_t RemainingSize;
|
||||
uint32_t ExpectedSize;
|
||||
|
||||
assert (Image != NULL);
|
||||
assert (FileSize != NULL);
|
||||
|
||||
memset (&Context, 0, sizeof (Context));
|
||||
|
||||
// FIXME: Non-XIP is not well-supported right now.
|
||||
Context.FileAlignment = Image->SegmentInfo.SegmentAlignment;
|
||||
Result = ImageConvertToXip ((image_tool_image_info_t *)Image);
|
||||
if (!Result) {
|
||||
raise ();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Context.Image = Image;
|
||||
|
||||
Result = EmitPeGetHeaderSizes (Image, &Context.HdrInfo);
|
||||
if (!Result) {
|
||||
raise ();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Overflow = BaseOverflowAlignUpU32 (
|
||||
Context.HdrInfo.SizeOfHeaders,
|
||||
Context.FileAlignment,
|
||||
&AlignedHeaderSize
|
||||
);
|
||||
if (Overflow) {
|
||||
raise ();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (AlignedHeaderSize > Image->SegmentInfo.Segments[0].ImageAddress) {
|
||||
raise ();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
AlignedHeaderSize = (uint32_t)Image->SegmentInfo.Segments[0].ImageAddress;
|
||||
|
||||
Result = EmitPeGetSectionsSize (&Context, &Context.SectionsSize);
|
||||
if (!Result) {
|
||||
raise ();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Overflow = BaseOverflowAddU32 (
|
||||
AlignedHeaderSize,
|
||||
Context.SectionsSize,
|
||||
&SectionsOffset
|
||||
);
|
||||
if (Overflow) {
|
||||
raise ();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Result = EmitPeGetExtraSectionsSize (&Context, &Context.ExtraSectionsSize);
|
||||
if (!Result) {
|
||||
raise ();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Overflow = BaseOverflowAddU32 (
|
||||
SectionsOffset,
|
||||
Context.ExtraSectionsSize,
|
||||
&Context.UnsignedFileSize
|
||||
);
|
||||
if (Overflow) {
|
||||
raise ();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
FileBuffer = calloc (1, Context.UnsignedFileSize);
|
||||
if (FileBuffer == NULL) {
|
||||
raise ();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Buffer = FileBuffer;
|
||||
RemainingSize = Context.UnsignedFileSize;
|
||||
ExpectedSize = Context.UnsignedFileSize;
|
||||
|
||||
Result = ToolImageEmitPeHeaders (&Context, &Buffer, &RemainingSize, AlignedHeaderSize);
|
||||
if (!Result) {
|
||||
raise ();
|
||||
free (FileBuffer);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ExpectedSize -= AlignedHeaderSize;
|
||||
|
||||
assert (RemainingSize == ExpectedSize);
|
||||
|
||||
Result = ToolImageEmitPeSections (&Context, &Buffer, &RemainingSize);
|
||||
if (!Result) {
|
||||
raise ();
|
||||
free (FileBuffer);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ExpectedSize -= Context.SectionsSize;
|
||||
|
||||
assert (RemainingSize == ExpectedSize);
|
||||
|
||||
Result = ToolImageEmitPeExtraSections (&Context, &Buffer, &RemainingSize);
|
||||
if (!Result) {
|
||||
raise ();
|
||||
free (FileBuffer);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ExpectedSize -= Context.ExtraSectionsSize;
|
||||
|
||||
assert (RemainingSize == ExpectedSize);
|
||||
assert (RemainingSize == 0);
|
||||
|
||||
Context.PeHdr->SizeOfInitializedData += Context.ExtraSectionsSize;
|
||||
|
||||
*FileSize = Context.UnsignedFileSize;
|
||||
|
||||
return FileBuffer;
|
||||
}
|
433
BaseTools/ImageTool/PeScan.c
Normal file
433
BaseTools/ImageTool/PeScan.c
Normal file
@ -0,0 +1,433 @@
|
||||
/** @file
|
||||
Copyright (c) 2021, Marvin Häuser. All rights reserved.
|
||||
Copyright (c) 2022, Mikhail Krichanov. All rights reserved.
|
||||
SPDX-License-Identifier: BSD-3-Clause
|
||||
**/
|
||||
|
||||
#include "ImageTool.h"
|
||||
|
||||
#define PE_COFF_SECT_NAME_RELOC ".reloc\0"
|
||||
#define PE_COFF_SECT_NAME_RESRC ".rsrc\0\0"
|
||||
#define PE_COFF_SECT_NAME_DEBUG ".debug\0"
|
||||
|
||||
static
|
||||
bool
|
||||
ScanPeGetHeaderInfo (
|
||||
OUT image_tool_header_info_t *HeaderInfo,
|
||||
IN PE_COFF_LOADER_IMAGE_CONTEXT *Context
|
||||
)
|
||||
{
|
||||
assert (HeaderInfo != NULL);
|
||||
assert (Context != NULL);
|
||||
|
||||
HeaderInfo->BaseAddress = (uint64_t)PeCoffGetImageBase (Context);
|
||||
HeaderInfo->EntryPointAddress = PeCoffGetAddressOfEntryPoint (Context);
|
||||
// FIXME:
|
||||
HeaderInfo->Machine = PeCoffGetMachine (Context);
|
||||
HeaderInfo->IsXip = true;
|
||||
HeaderInfo->Subsystem = PeCoffGetSubsystem (Context);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static
|
||||
bool
|
||||
ScanPeGetRelocInfo (
|
||||
OUT image_tool_reloc_info_t *RelocInfo,
|
||||
IN PE_COFF_LOADER_IMAGE_CONTEXT *Context
|
||||
)
|
||||
{
|
||||
BOOLEAN Overflow;
|
||||
UINT32 RelocBlockRvaMax;
|
||||
UINT32 TopOfRelocDir;
|
||||
UINT32 RelocBlockRva;
|
||||
const EFI_IMAGE_BASE_RELOCATION_BLOCK *RelocBlock;
|
||||
UINT32 RelocBlockSize;
|
||||
UINT32 SizeOfRelocs;
|
||||
UINT32 NumRelocs;
|
||||
UINT32 RelocIndex;
|
||||
uint32_t RelocDirSize;
|
||||
const char *ImageBuffer;
|
||||
UINT16 RelocType;
|
||||
UINT16 RelocOffset;
|
||||
|
||||
assert (RelocInfo != NULL);
|
||||
assert (Context != NULL);
|
||||
|
||||
RelocInfo->RelocsStripped = false;
|
||||
|
||||
// FIXME: PE/COFF context access
|
||||
RelocBlockRva = Context->RelocDirRva;
|
||||
RelocDirSize = Context->RelocDirSize;
|
||||
//
|
||||
// Verify the Relocation Directory is not empty.
|
||||
//
|
||||
if (RelocDirSize == 0) {
|
||||
return true;
|
||||
}
|
||||
|
||||
RelocInfo->Relocs = calloc (RelocDirSize / sizeof (UINT16), sizeof (*RelocInfo->Relocs));
|
||||
if (RelocInfo->Relocs == NULL) {
|
||||
fprintf (stderr, "ImageTool: Could not allocate memory for Relocs[]\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
TopOfRelocDir = RelocBlockRva + RelocDirSize;
|
||||
|
||||
RelocBlockRvaMax = TopOfRelocDir - sizeof (EFI_IMAGE_BASE_RELOCATION_BLOCK);
|
||||
//
|
||||
// Align TopOfRelocDir because, if the policy does not demand Relocation Block
|
||||
// sizes to be aligned, the code below will manually align them. Thus, the
|
||||
// end offset of the last Relocation Block must be compared to a manually
|
||||
// aligned Relocation Directoriy end offset.
|
||||
//
|
||||
Overflow = BaseOverflowAlignUpU32 (
|
||||
TopOfRelocDir,
|
||||
ALIGNOF (EFI_IMAGE_BASE_RELOCATION_BLOCK),
|
||||
&TopOfRelocDir
|
||||
);
|
||||
if (Overflow) {
|
||||
fprintf (stderr, "ImageTool: Overflow during TopOfRelocDir calculation\n");
|
||||
return false;
|
||||
}
|
||||
//
|
||||
// Apply all Base Relocations of the Image.
|
||||
//
|
||||
ImageBuffer = (char *)PeCoffLoaderGetImageAddress (Context);
|
||||
while (RelocBlockRva <= RelocBlockRvaMax) {
|
||||
RelocBlock = (const EFI_IMAGE_BASE_RELOCATION_BLOCK *)(const void *)(ImageBuffer + RelocBlockRva);
|
||||
//
|
||||
// Verify the Base Relocation Block size is well-formed.
|
||||
//
|
||||
Overflow = BaseOverflowSubU32 (
|
||||
RelocBlock->SizeOfBlock,
|
||||
sizeof (EFI_IMAGE_BASE_RELOCATION_BLOCK),
|
||||
&SizeOfRelocs
|
||||
);
|
||||
if (Overflow) {
|
||||
fprintf (stderr, "ImageTool: Overflow during SizeOfRelocs calculation\n");
|
||||
return false;
|
||||
}
|
||||
//
|
||||
// Verify the Base Relocation Block is in bounds of the Relocation
|
||||
// Directory.
|
||||
//
|
||||
if (SizeOfRelocs > RelocBlockRvaMax - RelocBlockRva) {
|
||||
fprintf (stderr, "ImageTool: Base Relocation Block is out of bounds of the Relocation Directory\n");
|
||||
return false;
|
||||
}
|
||||
//
|
||||
// This arithmetic cannot overflow because we know
|
||||
// 1) RelocBlock->SizeOfBlock <= RelocMax <= TopOfRelocDir
|
||||
// 2) IS_ALIGNED (TopOfRelocDir, ALIGNOF (EFI_IMAGE_BASE_RELOCATION_BLOCK)).
|
||||
//
|
||||
RelocBlockSize = ALIGN_VALUE (
|
||||
RelocBlock->SizeOfBlock,
|
||||
ALIGNOF (EFI_IMAGE_BASE_RELOCATION_BLOCK)
|
||||
);
|
||||
//
|
||||
// This division is safe due to the guarantee made above.
|
||||
//
|
||||
NumRelocs = SizeOfRelocs / sizeof (*RelocBlock->Relocations);
|
||||
//
|
||||
// Process all Base Relocations of the current Block.
|
||||
//
|
||||
for (RelocIndex = 0; RelocIndex < NumRelocs; ++RelocIndex) {
|
||||
RelocType = IMAGE_RELOC_TYPE (RelocBlock->Relocations[RelocIndex]);
|
||||
RelocOffset = IMAGE_RELOC_OFFSET (RelocBlock->Relocations[RelocIndex]);
|
||||
|
||||
// FIXME: Make separate functions for UE
|
||||
switch (RelocType) {
|
||||
case EFI_IMAGE_REL_BASED_ABSOLUTE:
|
||||
continue;
|
||||
case EFI_IMAGE_REL_BASED_HIGHLOW:
|
||||
case EFI_IMAGE_REL_BASED_DIR64:
|
||||
RelocInfo->Relocs[RelocInfo->NumRelocs].Type = (uint8_t)RelocType;
|
||||
break;
|
||||
default:
|
||||
fprintf (stderr, "ImageTool: Unknown RelocType = 0x%x\n", RelocType);
|
||||
return false;
|
||||
}
|
||||
|
||||
RelocInfo->Relocs[RelocInfo->NumRelocs].Target = RelocBlock->VirtualAddress + RelocOffset;
|
||||
++RelocInfo->NumRelocs;
|
||||
}
|
||||
//
|
||||
// This arithmetic cannot overflow because it has been checked that the
|
||||
// Image Base Relocation Block is in bounds of the Image buffer.
|
||||
//
|
||||
RelocBlockRva += RelocBlockSize;
|
||||
}
|
||||
//
|
||||
// Verify the Relocation Directory size matches the contained data.
|
||||
//
|
||||
if (RelocBlockRva != TopOfRelocDir) {
|
||||
fprintf (stderr, "ImageTool: Relocation Directory size does not match the contained data\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static
|
||||
bool
|
||||
ScanPeGetSegmentInfo (
|
||||
OUT image_tool_segment_info_t *SegmentInfo,
|
||||
OUT image_tool_hii_info_t *HiiInfo,
|
||||
IN PE_COFF_LOADER_IMAGE_CONTEXT *Context
|
||||
)
|
||||
{
|
||||
const EFI_IMAGE_SECTION_HEADER *Section;
|
||||
uint32_t NumSections;
|
||||
image_tool_segment_t *ImageSegment;
|
||||
const char *ImageBuffer;
|
||||
uint32_t Index;
|
||||
UINT32 Size;
|
||||
|
||||
assert (SegmentInfo != NULL);
|
||||
assert (HiiInfo != NULL);
|
||||
assert (Context != NULL);
|
||||
|
||||
SegmentInfo->SegmentAlignment = PeCoffGetSectionAlignment (Context);
|
||||
|
||||
NumSections = PeCoffGetSectionTable (Context, &Section);
|
||||
|
||||
SegmentInfo->Segments = calloc (NumSections, sizeof (*SegmentInfo->Segments));
|
||||
if (SegmentInfo->Segments == NULL) {
|
||||
fprintf (stderr, "ImageTool: Could not allocate memory for Segments[]\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
ImageBuffer = (char *)PeCoffLoaderGetImageAddress (Context);
|
||||
|
||||
ImageSegment = SegmentInfo->Segments;
|
||||
for (Index = 0; Index < NumSections; ++Index, ++Section) {
|
||||
STATIC_ASSERT (
|
||||
sizeof(PE_COFF_SECT_NAME_RELOC) == sizeof(Section->Name) &&
|
||||
sizeof(PE_COFF_SECT_NAME_RESRC) == sizeof(Section->Name) &&
|
||||
sizeof(PE_COFF_SECT_NAME_DEBUG) == sizeof(Section->Name),
|
||||
"Section names exceed section name bounds."
|
||||
);
|
||||
|
||||
if ((Section->Characteristics & EFI_IMAGE_SCN_MEM_DISCARDABLE) == 0
|
||||
&& memcmp (Section->Name, PE_COFF_SECT_NAME_RELOC, sizeof (Section->Name)) != 0
|
||||
&& memcmp (Section->Name, PE_COFF_SECT_NAME_RESRC, sizeof (Section->Name)) != 0
|
||||
&& memcmp (Section->Name, PE_COFF_SECT_NAME_DEBUG, sizeof (Section->Name)) != 0) {
|
||||
ImageSegment->Name = calloc (1, sizeof (Section->Name));
|
||||
if (ImageSegment->Name == NULL) {
|
||||
fprintf (stderr, "ImageTool: Could not allocate memory for Segment Name\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
memmove (ImageSegment->Name, Section->Name, sizeof (Section->Name));
|
||||
|
||||
Size = ALIGN_VALUE (Section->VirtualSize, SegmentInfo->SegmentAlignment);
|
||||
|
||||
ImageSegment->Data = calloc (1, Size);
|
||||
if (ImageSegment->Data == NULL) {
|
||||
fprintf (stderr, "ImageTool: Could not allocate memory for Segment Data\n");
|
||||
free (ImageSegment->Name);
|
||||
return false;
|
||||
}
|
||||
|
||||
memmove (
|
||||
ImageSegment->Data,
|
||||
ImageBuffer + Section->VirtualAddress,
|
||||
Section->VirtualSize
|
||||
);
|
||||
|
||||
ImageSegment->DataSize = Size;
|
||||
ImageSegment->ImageAddress = Section->VirtualAddress;
|
||||
ImageSegment->ImageSize = Size;
|
||||
|
||||
ImageSegment->Read = (Section->Characteristics & EFI_IMAGE_SCN_MEM_READ) != 0;
|
||||
ImageSegment->Write = (Section->Characteristics & EFI_IMAGE_SCN_MEM_WRITE) != 0;
|
||||
ImageSegment->Execute = (Section->Characteristics & EFI_IMAGE_SCN_MEM_EXECUTE) != 0;
|
||||
|
||||
++SegmentInfo->NumSegments;
|
||||
++ImageSegment;
|
||||
} else if (memcmp (Section->Name, PE_COFF_SECT_NAME_RESRC, sizeof (Section->Name)) == 0) {
|
||||
Size = ALIGN_VALUE (Section->VirtualSize, SegmentInfo->SegmentAlignment);
|
||||
|
||||
HiiInfo->Data = calloc (1, Size);
|
||||
if (HiiInfo->Data == NULL) {
|
||||
fprintf (stderr, "ImageTool: Could not allocate memory for Hii Data\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
memmove (
|
||||
HiiInfo->Data,
|
||||
ImageBuffer + Section->VirtualAddress,
|
||||
Section->VirtualSize
|
||||
);
|
||||
|
||||
HiiInfo->DataSize = Size;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
ScanPeGetDebugInfo (
|
||||
OUT image_tool_debug_info_t *DebugInfo,
|
||||
IN PE_COFF_LOADER_IMAGE_CONTEXT *Context
|
||||
)
|
||||
{
|
||||
const CHAR8 *PdbPath;
|
||||
UINT32 PdbPathSize;
|
||||
RETURN_STATUS Status;
|
||||
|
||||
assert (DebugInfo != NULL);
|
||||
assert (Context != NULL);
|
||||
|
||||
Status = PeCoffGetPdbPath (Context, &PdbPath, &PdbPathSize);
|
||||
if (Status == RETURN_NOT_FOUND) {
|
||||
return true;
|
||||
}
|
||||
if (RETURN_ERROR (Status)) {
|
||||
fprintf (stderr, "ImageTool: Could not get PdbPath\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
DebugInfo->SymbolsPath = malloc (PdbPathSize);
|
||||
if (DebugInfo->SymbolsPath == NULL) {
|
||||
fprintf (stderr, "ImageTool: Could not allocate memory for SymbolsPath\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
memmove (DebugInfo->SymbolsPath, PdbPath, PdbPathSize);
|
||||
|
||||
assert (PdbPathSize >= 1);
|
||||
assert (DebugInfo->SymbolsPath[PdbPathSize - 1] == '\0');
|
||||
|
||||
DebugInfo->SymbolsPathLen = PdbPathSize - 1;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
ScanPeGetHiiInfo (
|
||||
OUT image_tool_hii_info_t *HiiInfo,
|
||||
IN PE_COFF_LOADER_IMAGE_CONTEXT *Context
|
||||
)
|
||||
{
|
||||
UINT32 HiiRva;
|
||||
UINT32 HiiSize;
|
||||
RETURN_STATUS Status;
|
||||
const char *ImageBuffer;
|
||||
|
||||
assert (HiiInfo != NULL);
|
||||
assert (Context != NULL);
|
||||
|
||||
Status = PeCoffGetHiiDataRva (Context, &HiiRva, &HiiSize);
|
||||
if (Status == RETURN_NOT_FOUND) {
|
||||
return true;
|
||||
}
|
||||
if (RETURN_ERROR (Status)) {
|
||||
fprintf (stderr, "ImageTool: Could not get HiiRva\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
HiiInfo->Data = calloc (1, HiiSize);
|
||||
if (HiiInfo->Data == NULL) {
|
||||
fprintf (stderr, "ImageTool: Could not allocate memory for HiiInfo Data\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
ImageBuffer = (char *)PeCoffLoaderGetImageAddress (Context);
|
||||
|
||||
memmove (HiiInfo->Data, ImageBuffer + HiiRva, HiiSize);
|
||||
HiiInfo->DataSize = HiiSize;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
RETURN_STATUS
|
||||
ToolContextConstructPe (
|
||||
OUT image_tool_image_info_t *Image,
|
||||
IN const void *File,
|
||||
IN size_t FileSize
|
||||
)
|
||||
{
|
||||
PE_COFF_LOADER_IMAGE_CONTEXT Context;
|
||||
RETURN_STATUS Status;
|
||||
UINT32 ImageSize;
|
||||
UINT32 ImageAlignment;
|
||||
UINT32 DestinationSize;
|
||||
UINT32 DestinationPages;
|
||||
void *Destination;
|
||||
bool Result;
|
||||
|
||||
assert (Image != NULL);
|
||||
assert (File != NULL || FileSize == 0);
|
||||
|
||||
if (FileSize > MAX_UINT32) {
|
||||
fprintf (stderr, "ImageTool: FileSize is too huge\n");
|
||||
return RETURN_UNSUPPORTED;
|
||||
}
|
||||
|
||||
Status = PeCoffInitializeContext (&Context, File, (UINT32)FileSize);
|
||||
if (RETURN_ERROR (Status)) {
|
||||
return Status;
|
||||
}
|
||||
|
||||
ImageSize = PeCoffGetSizeOfImage (&Context);
|
||||
DestinationPages = EFI_SIZE_TO_PAGES (ImageSize);
|
||||
DestinationSize = EFI_PAGES_TO_SIZE (DestinationPages);
|
||||
ImageAlignment = PeCoffGetSectionAlignment (&Context);
|
||||
|
||||
Destination = AllocateAlignedCodePages (
|
||||
DestinationPages,
|
||||
ImageAlignment
|
||||
);
|
||||
if (Destination == NULL) {
|
||||
fprintf (stderr, "ImageTool: Could not allocate Destination buffer\n");
|
||||
return RETURN_OUT_OF_RESOURCES;
|
||||
}
|
||||
|
||||
Status = PeCoffLoadImage (&Context, Destination, DestinationSize);
|
||||
if (RETURN_ERROR (Status)) {
|
||||
fprintf (stderr, "ImageTool: Could not Load Image\n");
|
||||
FreeAlignedPages (Destination, DestinationPages);
|
||||
return RETURN_VOLUME_CORRUPTED;
|
||||
}
|
||||
|
||||
memset (Image, 0, sizeof (*Image));
|
||||
|
||||
Result = ScanPeGetHeaderInfo (&Image->HeaderInfo, &Context);
|
||||
if (!Result) {
|
||||
fprintf (stderr, "ImageTool: Could not retrieve header info\n");
|
||||
ToolImageDestruct (Image);
|
||||
FreeAlignedPages (Destination, DestinationPages);
|
||||
return RETURN_VOLUME_CORRUPTED;
|
||||
}
|
||||
|
||||
Result = ScanPeGetDebugInfo (&Image->DebugInfo, &Context);
|
||||
if (!Result) {
|
||||
fprintf (stderr, "ImageTool: Could not retrieve debug info\n");
|
||||
ToolImageDestruct (Image);
|
||||
FreeAlignedPages (Destination, DestinationPages);
|
||||
return RETURN_VOLUME_CORRUPTED;
|
||||
}
|
||||
|
||||
Result = ScanPeGetSegmentInfo (&Image->SegmentInfo, &Image->HiiInfo, &Context);
|
||||
if (!Result) {
|
||||
fprintf (stderr, "ImageTool: Could not retrieve segment info\n");
|
||||
ToolImageDestruct (Image);
|
||||
FreeAlignedPages (Destination, DestinationPages);
|
||||
return RETURN_VOLUME_CORRUPTED;
|
||||
}
|
||||
|
||||
Result = ScanPeGetRelocInfo (&Image->RelocInfo, &Context);
|
||||
if (!Result) {
|
||||
fprintf (stderr, "ImageTool: Could not retrieve reloc info\n");
|
||||
ToolImageDestruct (Image);
|
||||
FreeAlignedPages (Destination, DestinationPages);
|
||||
return RETURN_VOLUME_CORRUPTED;
|
||||
}
|
||||
|
||||
FreeAlignedPages (Destination, DestinationPages);
|
||||
|
||||
return RETURN_SUCCESS;
|
||||
}
|
@ -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
|
84
BaseTools/MicroTool/Makefile
Normal file
84
BaseTools/MicroTool/Makefile
Normal file
@ -0,0 +1,84 @@
|
||||
## @file
|
||||
# Windows makefile for 'MicroTool' module build.
|
||||
#
|
||||
# Copyright (c) 2022, Mikhail Krichanov. All rights reserved.
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
#
|
||||
!INCLUDE ..\Source\C\Makefiles\ms.common
|
||||
|
||||
APP = MicroTool
|
||||
|
||||
OC_USER = ..\..\OpenCorePkg
|
||||
UDK_PATH = ..\..
|
||||
UDK_ARCH = $(HOST_ARCH)
|
||||
OUT_DIR = .\Windows
|
||||
|
||||
OBJECTS = MicroTool.obj
|
||||
|
||||
BASE = $(UDK_PATH)\MdePkg\Library\BaseLib
|
||||
OUT = $(UDK_PATH)\MdePkg\Library\UefiDebugLibConOut
|
||||
PRIN = $(UDK_PATH)\MdePkg\Library\BasePrintLib
|
||||
ERRO = $(UDK_PATH)\MdePkg\Library\BaseDebugPrintErrorLevelLib
|
||||
BMPN = $(UDK_PATH)\MdeModulePkg\Library\BaseMemoryProfileLibNull
|
||||
CMEM = $(UDK_PATH)\MdeModulePkg\Library\CommonMemoryAllocationLib
|
||||
USER = $(OC_USER)\User\Library
|
||||
OBJECTS = $(OBJECTS) {$(BASE)}SafeString.obj String.obj SwapBytes16.obj SwapBytes32.obj CpuDeadLoop.obj CheckSum.obj
|
||||
OBJECTS = $(OBJECTS) {$(OUT)}DebugLib.obj {$(PRIN)}PrintLib.obj PrintLibInternal.obj {$(ERRO)}BaseDebugPrintErrorLevelLib.obj
|
||||
OBJECTS = $(OBJECTS) {$(USER)}UserFile.obj UserBaseMemoryLib.obj UserMath.obj UserPcd.obj UserMisc.obj UserGlobalVar.obj UserBootServices.obj
|
||||
OBJECTS = $(OBJECTS) {$(BMPN)}BaseMemoryProfileLibNull.obj {$(CMEM)}CommonMemoryAllocationLib.obj {$(CMEM)}CommonMemoryAllocationLibEx.obj
|
||||
|
||||
INC = -I . -I $(OC_USER)\User\Include -I $(OC_USER)\Include\Acidanthera
|
||||
INC = $(INC) -I $(UDK_PATH)\MdePkg\Include -I $(UDK_PATH)\MdePkg\Include\Library -I $(UDK_PATH)\MdePkg\Include\$(UDK_ARCH)
|
||||
INC = $(INC) -I $(UDK_PATH)\MdePkg\Library\BaseLib -I $(UDK_PATH)\MdeModulePkg\Include -I $(UDK_PATH)\UefiCpuPkg\Include
|
||||
INC = $(INC) /FI $(OC_USER)\User\Include\UserPcd.h /FI $(UDK_PATH)\MdePkg\Include\Base.h /FI $(OC_USER)\User\Include\UserGlobalVar.h
|
||||
|
||||
all:
|
||||
-@if not exist $(OUT_DIR) mkdir $(OUT_DIR)
|
||||
$(MAKE) $(APP)
|
||||
|
||||
$(APP) : $(OBJECTS)
|
||||
-@if not exist $(BIN_PATH) mkdir $(BIN_PATH)
|
||||
@cd $(OUT_DIR)
|
||||
$(LD) /nologo /debug /OPT:REF /OPT:ICF=10 /incremental:no /nodefaultlib:libc.lib /out:..\$@ $(LIBS) $**
|
||||
@copy /y ..\$@ $(BIN_PATH)\$@.exe
|
||||
|
||||
.PHONY:clean
|
||||
.PHONY:cleanall
|
||||
|
||||
clean:
|
||||
del /f /q $(OUT_DIR) $(APP) *.pdb > nul
|
||||
|
||||
cleanall:
|
||||
del /f /q $(OUT_DIR) *.pdb $(BIN_PATH)\$(APP).exe $(BIN_PATH)\$(APP).exe > nul
|
||||
|
||||
.c.obj :
|
||||
$(CC) -c $(CFLAGS) $(INC) $< -Fo$@
|
||||
@move $@ $(OUT_DIR)\
|
||||
|
||||
{$(BASE)}.c.obj :
|
||||
$(CC) -c $(CFLAGS) $(INC) /wd 4005 $< -Fo$@
|
||||
@move $@ $(OUT_DIR)\
|
||||
|
||||
{$(BMPN)}.c.obj :
|
||||
$(CC) -c $(CFLAGS) $(INC) $< -Fo$@
|
||||
@move $@ $(OUT_DIR)\
|
||||
|
||||
{$(CMEM)}.c.obj :
|
||||
$(CC) -c $(CFLAGS) $(INC) $< -Fo$@
|
||||
@move $@ $(OUT_DIR)\
|
||||
|
||||
{$(OUT)}.c.obj :
|
||||
$(CC) -c $(CFLAGS) $(INC) $< -Fo$@
|
||||
@move $@ $(OUT_DIR)\
|
||||
|
||||
{$(PRIN)}.c.obj :
|
||||
$(CC) -c $(CFLAGS) $(INC) /wd 4005 $< -Fo$@
|
||||
@move $@ $(OUT_DIR)\
|
||||
|
||||
{$(ERRO)}.c.obj :
|
||||
$(CC) -c $(CFLAGS) $(INC) $< -Fo$@
|
||||
@move $@ $(OUT_DIR)\
|
||||
|
||||
{$(USER)}.c.obj :
|
||||
$(CC) -c $(CFLAGS) $(INC) /D WIN32 /wd 4754 $< -Fo$@
|
||||
@move $@ $(OUT_DIR)\
|
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;
|
||||
}
|
@ -1,7 +1,8 @@
|
||||
/** @file
|
||||
|
||||
Unified linker script for CLANG based builds
|
||||
Unified linker script for GCC, CLANG based builds
|
||||
|
||||
Copyright (c) 2023, Mikhail Krichanov. All rights reserved.<BR>
|
||||
Copyright (c) 2010 - 2021, Intel Corporation. All rights reserved.<BR>
|
||||
Copyright (c) 2015, Linaro Ltd. All rights reserved.<BR>
|
||||
(C) Copyright 2016 Hewlett Packard Enterprise Development LP<BR>
|
||||
@ -12,17 +13,14 @@
|
||||
|
||||
SECTIONS {
|
||||
|
||||
/*
|
||||
* The PE/COFF binary consists of DOS and PE/COFF headers, and a sequence of
|
||||
* section headers adding up to PECOFF_HEADER_SIZE bytes (which differs
|
||||
* between 32-bit and 64-bit builds). The actual start of the .text section
|
||||
* will be rounded up based on its actual alignment.
|
||||
*/
|
||||
. = PECOFF_HEADER_SIZE;
|
||||
. = ALIGNED_PE_HEADER_SIZE;
|
||||
|
||||
.text : ALIGN(CONSTANT(MAXPAGESIZE)) {
|
||||
*(.text .text.* .stub .gnu.linkonce.t.*)
|
||||
*(.rodata .rodata.* .gnu.linkonce.r.*)
|
||||
}
|
||||
|
||||
.rodata : ALIGN(CONSTANT(MAXPAGESIZE)) {
|
||||
*(.rodata .rodata.* .data.rel.ro .data.rel.ro.* .gnu.linkonce.r.*)
|
||||
*(.got .got.*)
|
||||
|
||||
/*
|
||||
@ -36,18 +34,16 @@ SECTIONS {
|
||||
*:AutoGen.obj(.data.g*Guid)
|
||||
}
|
||||
|
||||
/*
|
||||
* The alignment of the .data section should be less than or equal to the
|
||||
* alignment of the .text section. This ensures that the relative offset
|
||||
* between these sections is the same in the ELF and the PE/COFF versions of
|
||||
* this binary.
|
||||
*/
|
||||
.data ALIGN(ALIGNOF(.text)) : ALIGN(CONSTANT(MAXPAGESIZE)) {
|
||||
.data : ALIGN(CONSTANT(MAXPAGESIZE)) {
|
||||
*(.data .data.* .gnu.linkonce.d.*)
|
||||
*(.bss .bss.*)
|
||||
}
|
||||
|
||||
.eh_frame ALIGN(CONSTANT(MAXPAGESIZE)) : {
|
||||
.hii : ALIGN(CONSTANT(MAXPAGESIZE)) {
|
||||
KEEP (*(.hii))
|
||||
}
|
||||
|
||||
.eh_frame : ALIGN(CONSTANT(MAXPAGESIZE)) {
|
||||
KEEP (*(.eh_frame))
|
||||
}
|
||||
|
||||
@ -55,14 +51,6 @@ SECTIONS {
|
||||
*(.rela .rela.*)
|
||||
}
|
||||
|
||||
.hii : ALIGN(CONSTANT(MAXPAGESIZE)) {
|
||||
KEEP (*(.hii))
|
||||
}
|
||||
|
||||
/*
|
||||
* Retain the GNU build id but in a non-allocatable section so GenFw
|
||||
* does not copy it into the PE/COFF image.
|
||||
*/
|
||||
.build-id (INFO) : { *(.note.gnu.build-id) }
|
||||
|
||||
/DISCARD/ : {
|
||||
@ -74,5 +62,7 @@ SECTIONS {
|
||||
*(.hash .gnu.hash)
|
||||
*(.comment)
|
||||
*(COMMON)
|
||||
*(.dynamic)
|
||||
*(.ARM.exidx .ARM.exidx.*)
|
||||
}
|
||||
}
|
@ -1,78 +0,0 @@
|
||||
/** @file
|
||||
|
||||
Unified linker script for GCC based builds
|
||||
|
||||
Copyright (c) 2010 - 2015, Intel Corporation. All rights reserved.<BR>
|
||||
Copyright (c) 2015, Linaro Ltd. All rights reserved.<BR>
|
||||
(C) Copyright 2016 Hewlett Packard Enterprise Development LP<BR>
|
||||
|
||||
SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
|
||||
**/
|
||||
|
||||
SECTIONS {
|
||||
|
||||
/*
|
||||
* The PE/COFF binary consists of DOS and PE/COFF headers, and a sequence of
|
||||
* section headers adding up to PECOFF_HEADER_SIZE bytes (which differs
|
||||
* between 32-bit and 64-bit builds). The actual start of the .text section
|
||||
* will be rounded up based on its actual alignment.
|
||||
*/
|
||||
. = PECOFF_HEADER_SIZE;
|
||||
|
||||
.text : ALIGN(CONSTANT(COMMONPAGESIZE)) {
|
||||
*(.text .text.* .stub .gnu.linkonce.t.*)
|
||||
*(.rodata .rodata.* .gnu.linkonce.r.*)
|
||||
*(.got .got.*)
|
||||
|
||||
/*
|
||||
* The contents of AutoGen.c files are mostly constant from the POV of the
|
||||
* program, but most of it ends up in .data or .bss by default since few of
|
||||
* the variable definitions that get emitted are declared as CONST.
|
||||
* Unfortunately, we cannot pull it into the .text section entirely, since
|
||||
* patchable PCDs are also emitted here, but we can at least move all of the
|
||||
* emitted GUIDs here.
|
||||
*/
|
||||
*:AutoGen.obj(.data.g*Guid)
|
||||
}
|
||||
|
||||
/*
|
||||
* The alignment of the .data section should be less than or equal to the
|
||||
* alignment of the .text section. This ensures that the relative offset
|
||||
* between these sections is the same in the ELF and the PE/COFF versions of
|
||||
* this binary.
|
||||
*/
|
||||
.data ALIGN(ALIGNOF(.text)) : ALIGN(CONSTANT(COMMONPAGESIZE)) {
|
||||
*(.data .data.* .gnu.linkonce.d.*)
|
||||
*(.bss .bss.*)
|
||||
}
|
||||
|
||||
.eh_frame ALIGN(CONSTANT(COMMONPAGESIZE)) : {
|
||||
KEEP (*(.eh_frame))
|
||||
}
|
||||
|
||||
.rela (INFO) : {
|
||||
*(.rela .rela.*)
|
||||
}
|
||||
|
||||
.hii : ALIGN(CONSTANT(COMMONPAGESIZE)) {
|
||||
KEEP (*(.hii))
|
||||
}
|
||||
|
||||
/*
|
||||
* Retain the GNU build id but in a non-allocatable section so GenFw
|
||||
* does not copy it into the PE/COFF image.
|
||||
*/
|
||||
.build-id (INFO) : { *(.note.gnu.build-id) }
|
||||
|
||||
/DISCARD/ : {
|
||||
*(.note.GNU-stack)
|
||||
*(.gnu_debuglink)
|
||||
*(.interp)
|
||||
*(.dynsym)
|
||||
*(.dynstr)
|
||||
*(.dynamic)
|
||||
*(.hash .gnu.hash)
|
||||
*(.comment)
|
||||
}
|
||||
}
|
65
BaseTools/Scripts/Merge.lds
Normal file
65
BaseTools/Scripts/Merge.lds
Normal file
@ -0,0 +1,65 @@
|
||||
/** @file
|
||||
|
||||
Unified linker script for GCC, CLANG based builds
|
||||
|
||||
Copyright (c) 2023, Mikhail Krichanov. All rights reserved.<BR>
|
||||
Copyright (c) 2010 - 2021, Intel Corporation. All rights reserved.<BR>
|
||||
Copyright (c) 2015, Linaro Ltd. All rights reserved.<BR>
|
||||
(C) Copyright 2016 Hewlett Packard Enterprise Development LP<BR>
|
||||
|
||||
SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
|
||||
**/
|
||||
|
||||
SECTIONS {
|
||||
|
||||
. = ALIGNED_PE_HEADER_SIZE;
|
||||
|
||||
.text : ALIGN(CONSTANT(MAXPAGESIZE)) {
|
||||
*(.text .text.* .stub .gnu.linkonce.t.*)
|
||||
*(.rodata .rodata.* .data.rel.ro .data.rel.ro.* .gnu.linkonce.r.*)
|
||||
*(.got .got.*)
|
||||
|
||||
/*
|
||||
* The contents of AutoGen.c files are mostly constant from the POV of the
|
||||
* program, but most of it ends up in .data or .bss by default since few of
|
||||
* the variable definitions that get emitted are declared as CONST.
|
||||
* Unfortunately, we cannot pull it into the .text section entirely, since
|
||||
* patchable PCDs are also emitted here, but we can at least move all of the
|
||||
* emitted GUIDs here.
|
||||
*/
|
||||
*:AutoGen.obj(.data.g*Guid)
|
||||
}
|
||||
|
||||
.data : ALIGN(CONSTANT(MAXPAGESIZE)) {
|
||||
*(.data .data.* .gnu.linkonce.d.*)
|
||||
*(.bss .bss.*)
|
||||
}
|
||||
|
||||
.hii : ALIGN(CONSTANT(MAXPAGESIZE)) {
|
||||
KEEP (*(.hii))
|
||||
}
|
||||
|
||||
.eh_frame : ALIGN(CONSTANT(MAXPAGESIZE)) {
|
||||
KEEP (*(.eh_frame))
|
||||
}
|
||||
|
||||
.rela (INFO) : {
|
||||
*(.rela .rela.*)
|
||||
}
|
||||
|
||||
.build-id (INFO) : { *(.note.gnu.build-id) }
|
||||
|
||||
/DISCARD/ : {
|
||||
*(.note.GNU-stack)
|
||||
*(.gnu_debuglink)
|
||||
*(.interp)
|
||||
*(.dynsym)
|
||||
*(.dynstr)
|
||||
*(.hash .gnu.hash)
|
||||
*(.comment)
|
||||
*(COMMON)
|
||||
*(.dynamic)
|
||||
*(.ARM.exidx .ARM.exidx.*)
|
||||
}
|
||||
}
|
@ -3586,7 +3586,7 @@ Returns:
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
EFI_PHYSICAL_ADDRESS
|
||||
EFI_STATUS
|
||||
AddPadSection (
|
||||
IN OUT EFI_PHYSICAL_ADDRESS *BaseAddress,
|
||||
IN UINT32 Alignment,
|
||||
@ -3599,14 +3599,14 @@ AddPadSection (
|
||||
UINT32 FfsHeaderLength;
|
||||
UINT32 FfsFileLength;
|
||||
UINT32 PadSize;
|
||||
UINTN PadAddress;
|
||||
EFI_PHYSICAL_ADDRESS PadAddress;
|
||||
UINT8 *FfsPart;
|
||||
UINT32 PartSize;
|
||||
UINT32 Offset;
|
||||
EFI_FFS_INTEGRITY_CHECK *IntegrityCheck;
|
||||
|
||||
PadAddress = ALIGN_VALUE (*BaseAddress + sizeof (EFI_COMMON_SECTION_HEADER), Alignment);
|
||||
PadSize = PadAddress - *BaseAddress;
|
||||
PadSize = (UINT32)(PadAddress - *BaseAddress);
|
||||
|
||||
Offset = (UINT32)((UINTN)((*Section).Pe32Section) - (UINTN)(*FfsFile));
|
||||
PartSize = GetFfsFileLength (*FfsFile) - Offset;
|
||||
@ -3636,7 +3636,7 @@ AddPadSection (
|
||||
++NewSection;
|
||||
ZeroMem ((VOID *)NewSection, PadSize - sizeof (EFI_COMMON_SECTION_HEADER));
|
||||
|
||||
*Section = (EFI_FILE_SECTION_POINTER)(EFI_PE32_SECTION *)((UINT8 *)NewSection + PadSize - sizeof (EFI_COMMON_SECTION_HEADER));
|
||||
(*Section).Pe32Section = (EFI_PE32_SECTION *)((UINT8 *)NewSection + PadSize - sizeof (EFI_COMMON_SECTION_HEADER));
|
||||
|
||||
CopyMem (
|
||||
(UINT8 *)((*Section).Pe32Section),
|
||||
@ -4070,7 +4070,7 @@ Returns:
|
||||
PdbPointer = FileName;
|
||||
}
|
||||
|
||||
WriteMapFile (FvMapFile, PdbPointer, *FfsFile, NewPe32BaseAddress, &OrigImageContext);
|
||||
WriteMapFile (FvMapFile, PdbPointer, *FfsFile, NewPe32BaseAddress, &ImageContext);
|
||||
}
|
||||
|
||||
if ((*FfsFile)->Type != EFI_FV_FILETYPE_SECURITY_CORE &&
|
||||
|
@ -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
|
||||
|
||||
|
@ -103,11 +103,32 @@ class ToolDefClassObject(object):
|
||||
else:
|
||||
EdkLogger.error("tools_def.txt parser", FILE_NOT_FOUND, ExtraData=FileName)
|
||||
|
||||
Branch = 0
|
||||
for Index in range(len(FileContent)):
|
||||
Line = FileContent[Index].strip()
|
||||
if Line == "" or Line[0] == '#':
|
||||
continue
|
||||
|
||||
if Line.startswith("!ifdef"):
|
||||
Condition = Line[6:].strip()
|
||||
Reference = GlobalData.gMacroRefPattern.findall(Condition)
|
||||
if Reference[0] in GlobalData.gCommandLineDefines:
|
||||
Branch = 1
|
||||
else:
|
||||
Branch = -1
|
||||
continue
|
||||
|
||||
if Line.startswith("!else"):
|
||||
Branch *= -1
|
||||
continue
|
||||
|
||||
if Line.startswith("!endif"):
|
||||
Branch = 0
|
||||
continue
|
||||
|
||||
if Branch == -1:
|
||||
continue
|
||||
|
||||
if Line.startswith("!include"):
|
||||
IncFile = Line[8:].strip()
|
||||
Done, IncFile = self.ExpandMacros(IncFile)
|
||||
|
@ -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;
|
||||
|
@ -143,36 +143,6 @@ typedef unsigned __int32 UINT32;
|
||||
/// 4-byte signed value
|
||||
///
|
||||
typedef __int32 INT32;
|
||||
///
|
||||
/// 2-byte unsigned value
|
||||
///
|
||||
typedef unsigned short UINT16;
|
||||
///
|
||||
/// 2-byte Character. Unless otherwise specified all strings are stored in the
|
||||
/// UTF-16 encoding format as defined by Unicode 2.1 and ISO/IEC 10646 standards.
|
||||
///
|
||||
typedef unsigned short CHAR16;
|
||||
///
|
||||
/// 2-byte signed value
|
||||
///
|
||||
typedef short INT16;
|
||||
///
|
||||
/// Logical Boolean. 1-byte value containing 0 for FALSE or a 1 for TRUE. Other
|
||||
/// values are undefined.
|
||||
///
|
||||
typedef unsigned char BOOLEAN;
|
||||
///
|
||||
/// 1-byte unsigned value
|
||||
///
|
||||
typedef unsigned char UINT8;
|
||||
///
|
||||
/// 1-byte Character
|
||||
///
|
||||
typedef char CHAR8;
|
||||
///
|
||||
/// 1-byte signed value
|
||||
///
|
||||
typedef signed char INT8;
|
||||
#elif defined (__clang__)
|
||||
///
|
||||
/// 8-byte unsigned value
|
||||
@ -190,36 +160,6 @@ typedef unsigned int UINT32;
|
||||
/// 4-byte signed value
|
||||
///
|
||||
typedef signed int INT32;
|
||||
///
|
||||
/// 2-byte unsigned value
|
||||
///
|
||||
typedef unsigned short UINT16;
|
||||
///
|
||||
/// 2-byte Character. Unless otherwise specified all strings are stored in the
|
||||
/// UTF-16 encoding format as defined by Unicode 2.1 and ISO/IEC 10646 standards.
|
||||
///
|
||||
typedef unsigned short CHAR16;
|
||||
///
|
||||
/// 2-byte signed value
|
||||
///
|
||||
typedef short INT16;
|
||||
///
|
||||
/// Logical Boolean. 1-byte value containing 0 for FALSE or a 1 for TRUE. Other
|
||||
/// values are undefined.
|
||||
///
|
||||
typedef unsigned char BOOLEAN;
|
||||
///
|
||||
/// 1-byte unsigned value
|
||||
///
|
||||
typedef unsigned char UINT8;
|
||||
///
|
||||
/// 1-byte Character
|
||||
///
|
||||
typedef char CHAR8;
|
||||
///
|
||||
/// 1-byte signed value
|
||||
///
|
||||
typedef signed char INT8;
|
||||
#else
|
||||
///
|
||||
/// 8-byte unsigned value
|
||||
@ -237,6 +177,8 @@ typedef unsigned int UINT32;
|
||||
/// 4-byte signed value
|
||||
///
|
||||
typedef int INT32;
|
||||
#endif
|
||||
|
||||
///
|
||||
/// 2-byte unsigned value
|
||||
///
|
||||
@ -267,7 +209,6 @@ typedef char CHAR8;
|
||||
/// 1-byte signed value
|
||||
///
|
||||
typedef signed char INT8;
|
||||
#endif
|
||||
|
||||
///
|
||||
/// Unsigned value of native width. (4 bytes on supported 32-bit processor instructions,
|
||||
|
1
OpenCorePkg
Submodule
1
OpenCorePkg
Submodule
@ -0,0 +1 @@
|
||||
Subproject commit ca9a501490ccce20431f095182b4fb0d359d80e3
|
@ -109,20 +109,6 @@
|
||||
|
||||
!include NetworkPkg/NetworkBuildOptions.dsc.inc
|
||||
|
||||
[BuildOptions.common.EDKII.DXE_RUNTIME_DRIVER]
|
||||
GCC:*_*_*_DLINK_FLAGS = -z common-page-size=0x1000
|
||||
XCODE:*_*_*_DLINK_FLAGS = -seg1addr 0x1000 -segalign 0x1000
|
||||
XCODE:*_*_*_MTOC_FLAGS = -align 0x1000
|
||||
CLANGPDB:*_*_*_DLINK_FLAGS = /ALIGN:4096
|
||||
|
||||
# Force PE/COFF sections to be aligned at 4KB boundaries to support page level
|
||||
# protection of DXE_SMM_DRIVER/SMM_CORE modules
|
||||
[BuildOptions.common.EDKII.DXE_SMM_DRIVER, BuildOptions.common.EDKII.SMM_CORE]
|
||||
GCC:*_*_*_DLINK_FLAGS = -z common-page-size=0x1000
|
||||
XCODE:*_*_*_DLINK_FLAGS = -seg1addr 0x1000 -segalign 0x1000
|
||||
XCODE:*_*_*_MTOC_FLAGS = -align 0x1000
|
||||
CLANGPDB:*_*_*_DLINK_FLAGS = /ALIGN:4096
|
||||
|
||||
################################################################################
|
||||
#
|
||||
# SKU Identification section - list of all SKU IDs supported by this Platform.
|
||||
@ -604,14 +590,15 @@
|
||||
#
|
||||
!if $(LEGACY_WINDOWS_LOADER) == TRUE
|
||||
# Allow execution of EfiLoaderData memory regions.
|
||||
gEfiMdeModulePkgTokenSpaceGuid.PcdDxeNxMemoryProtectionPolicy|0x7FD1
|
||||
gEfiMdeModulePkgTokenSpaceGuid.PcdDxeNxMemoryProtectionPolicy|0xFFFFFFFFFFFFFFD1
|
||||
!elseif $(LINUX_LOADER) == TRUE
|
||||
# Allow execution of EfiConventionalMemory, EfiBootServicesData and EfiLoaderData memory regions.
|
||||
gEfiMdeModulePkgTokenSpaceGuid.PcdDxeNxMemoryProtectionPolicy|0x7F41
|
||||
# Allow execution of EfiReservedMemoryType, EfiConventionalMemory, EfiBootServicesData and EfiLoaderData memory regions.
|
||||
gEfiMdeModulePkgTokenSpaceGuid.PcdDxeNxMemoryProtectionPolicy|0xFFFFFFFFFFFFFF40
|
||||
gEfiMdePkgTokenSpaceGuid.PcdImageLoaderAllowMisalignedOffset|TRUE
|
||||
!elseif $(WINDOWS_10_IA32) == TRUE
|
||||
# Allow execution of EfiReservedMemoryType, EfiConventionalMemory, EfiBootServicesData and EfiRuntimeServicesData memory regions.
|
||||
gEfiMdeModulePkgTokenSpaceGuid.PcdDxeNxMemoryProtectionPolicy|0x7F04
|
||||
gEfiMdeModulePkgTokenSpaceGuid.PcdDxeNxMemoryProtectionPolicy|0xFFFFFFFFFFFFFF04
|
||||
gEfiMdeModulePkgTokenSpaceGuid.PcdImageProtectionPolicy|0x0
|
||||
!endif
|
||||
|
||||
################################################################################
|
||||
|
@ -113,11 +113,6 @@
|
||||
|
||||
!include NetworkPkg/NetworkBuildOptions.dsc.inc
|
||||
|
||||
GCC:*_*_*_DLINK_FLAGS = -z common-page-size=0x1000
|
||||
XCODE:*_*_*_DLINK_FLAGS = -seg1addr 0x1000 -segalign 0x1000
|
||||
XCODE:*_*_*_MTOC_FLAGS = -align 0x1000
|
||||
CLANGPDB:*_*_*_DLINK_FLAGS = /FILEALIGN:4096 /ALIGN:4096
|
||||
|
||||
################################################################################
|
||||
#
|
||||
# SKU Identification section - list of all SKU IDs supported by this Platform.
|
||||
@ -605,14 +600,15 @@
|
||||
#
|
||||
!if $(LEGACY_WINDOWS_LOADER) == TRUE
|
||||
# Allow execution of EfiLoaderData memory regions.
|
||||
gEfiMdeModulePkgTokenSpaceGuid.PcdDxeNxMemoryProtectionPolicy|0x7FD1
|
||||
gEfiMdeModulePkgTokenSpaceGuid.PcdDxeNxMemoryProtectionPolicy|0xFFFFFFFFFFFFFFD1
|
||||
!elseif $(LINUX_LOADER) == TRUE
|
||||
# Allow execution of EfiConventionalMemory, EfiBootServicesData and EfiLoaderData memory regions.
|
||||
gEfiMdeModulePkgTokenSpaceGuid.PcdDxeNxMemoryProtectionPolicy|0x7F41
|
||||
# Allow execution of EfiReservedMemoryType, EfiConventionalMemory, EfiBootServicesData and EfiLoaderData memory regions.
|
||||
gEfiMdeModulePkgTokenSpaceGuid.PcdDxeNxMemoryProtectionPolicy|0xFFFFFFFFFFFFFF40
|
||||
gEfiMdePkgTokenSpaceGuid.PcdImageLoaderAllowMisalignedOffset|TRUE
|
||||
!elseif $(WINDOWS_10_IA32) == TRUE
|
||||
# Allow execution of EfiReservedMemoryType, EfiConventionalMemory, EfiBootServicesData and EfiRuntimeServicesData memory regions.
|
||||
gEfiMdeModulePkgTokenSpaceGuid.PcdDxeNxMemoryProtectionPolicy|0x7F04
|
||||
gEfiMdeModulePkgTokenSpaceGuid.PcdDxeNxMemoryProtectionPolicy|0xFFFFFFFFFFFFFF04
|
||||
gEfiMdeModulePkgTokenSpaceGuid.PcdImageProtectionPolicy|0x0
|
||||
!endif
|
||||
|
||||
################################################################################
|
||||
|
@ -62,10 +62,10 @@ FV = SECFV
|
||||
|
||||
[FD.MEMFD]
|
||||
BaseAddress = $(MEMFD_BASE_ADDRESS)
|
||||
Size = 0xE00000
|
||||
Size = 0xE30000
|
||||
ErasePolarity = 1
|
||||
BlockSize = 0x10000
|
||||
NumBlocks = 0xE0
|
||||
NumBlocks = 0xE3
|
||||
|
||||
0x000000|0x006000
|
||||
gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecPageTablesBase|gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecPageTablesSize
|
||||
@ -82,11 +82,11 @@ gUefiOvmfPkgTokenSpaceGuid.PcdOvmfWorkAreaBase|gUefiOvmfPkgTokenSpaceGuid.PcdOvm
|
||||
0x010000|0x010000
|
||||
gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecPeiTempRamBase|gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecPeiTempRamSize
|
||||
|
||||
0x020000|0x0E0000
|
||||
0x020000|0x100000
|
||||
gUefiOvmfPkgTokenSpaceGuid.PcdOvmfPeiMemFvBase|gUefiOvmfPkgTokenSpaceGuid.PcdOvmfPeiMemFvSize
|
||||
FV = PEIFV
|
||||
|
||||
0x100000|0xD00000
|
||||
0x120000|0xCE0000
|
||||
gUefiOvmfPkgTokenSpaceGuid.PcdOvmfDxeMemFvBase|gUefiOvmfPkgTokenSpaceGuid.PcdOvmfDxeMemFvSize
|
||||
FV = DXEFV
|
||||
|
||||
|
@ -126,20 +126,6 @@
|
||||
|
||||
!include NetworkPkg/NetworkBuildOptions.dsc.inc
|
||||
|
||||
[BuildOptions.common.EDKII.DXE_RUNTIME_DRIVER]
|
||||
GCC:*_*_*_DLINK_FLAGS = -z common-page-size=0x1000
|
||||
XCODE:*_*_*_DLINK_FLAGS = -seg1addr 0x1000 -segalign 0x1000
|
||||
XCODE:*_*_*_MTOC_FLAGS = -align 0x1000
|
||||
CLANGPDB:*_*_*_DLINK_FLAGS = /ALIGN:4096
|
||||
|
||||
# Force PE/COFF sections to be aligned at 4KB boundaries to support page level
|
||||
# protection of DXE_SMM_DRIVER/SMM_CORE modules
|
||||
[BuildOptions.common.EDKII.DXE_SMM_DRIVER, BuildOptions.common.EDKII.SMM_CORE]
|
||||
GCC:*_*_*_DLINK_FLAGS = -z common-page-size=0x1000
|
||||
XCODE:*_*_*_DLINK_FLAGS = -seg1addr 0x1000 -segalign 0x1000
|
||||
XCODE:*_*_*_MTOC_FLAGS = -align 0x1000
|
||||
CLANGPDB:*_*_*_DLINK_FLAGS = /ALIGN:4096
|
||||
|
||||
################################################################################
|
||||
#
|
||||
# SKU Identification section - list of all SKU IDs supported by this Platform.
|
||||
@ -608,7 +594,8 @@
|
||||
gEmbeddedTokenSpaceGuid.PcdMemoryTypeEfiRuntimeServicesData|0x100
|
||||
|
||||
#
|
||||
# TDX need 1G PageTable support
|
||||
# TDX needs 1G PageTable support
|
||||
#
|
||||
gEfiMdeModulePkgTokenSpaceGuid.PcdUse1GPageTable|TRUE
|
||||
|
||||
#
|
||||
@ -633,10 +620,10 @@
|
||||
#
|
||||
!if $(LEGACY_WINDOWS_LOADER) == TRUE
|
||||
# Allow execution of EfiLoaderData memory regions.
|
||||
gEfiMdeModulePkgTokenSpaceGuid.PcdDxeNxMemoryProtectionPolicy|0x7FD1
|
||||
gEfiMdeModulePkgTokenSpaceGuid.PcdDxeNxMemoryProtectionPolicy|0xFFFFFFFFFFFFFFD1
|
||||
!elseif $(LINUX_LOADER) == TRUE
|
||||
# Allow execution of EfiConventionalMemory, EfiBootServicesData and EfiLoaderData memory regions.
|
||||
gEfiMdeModulePkgTokenSpaceGuid.PcdDxeNxMemoryProtectionPolicy|0x7F41
|
||||
# Allow execution of EfiReservedMemoryType, EfiConventionalMemory, EfiBootServicesData and EfiLoaderData memory regions.
|
||||
gEfiMdeModulePkgTokenSpaceGuid.PcdDxeNxMemoryProtectionPolicy|0xFFFFFFFFFFFFFF40
|
||||
gEfiMdePkgTokenSpaceGuid.PcdImageLoaderAllowMisalignedOffset|TRUE
|
||||
!endif
|
||||
|
||||
|
@ -62,10 +62,10 @@ FV = SECFV
|
||||
|
||||
[FD.MEMFD]
|
||||
BaseAddress = $(MEMFD_BASE_ADDRESS)
|
||||
Size = 0xE00000
|
||||
Size = 0xD00000
|
||||
ErasePolarity = 1
|
||||
BlockSize = 0x10000
|
||||
NumBlocks = 0xE0
|
||||
NumBlocks = 0xD0
|
||||
|
||||
0x000000|0x006000
|
||||
gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecPageTablesBase|gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecPageTablesSize
|
||||
@ -97,11 +97,11 @@ gUefiOvmfPkgTokenSpaceGuid.PcdOvmfCpuidBase|gUefiOvmfPkgTokenSpaceGuid.PcdOvmfCp
|
||||
0x010000|0x010000
|
||||
gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecPeiTempRamBase|gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecPeiTempRamSize
|
||||
|
||||
0x020000|0x0E0000
|
||||
0x020000|0x110000
|
||||
gUefiOvmfPkgTokenSpaceGuid.PcdOvmfPeiMemFvBase|gUefiOvmfPkgTokenSpaceGuid.PcdOvmfPeiMemFvSize
|
||||
FV = PEIFV
|
||||
|
||||
0x100000|0xD00000
|
||||
0x130000|0xBD0000
|
||||
gUefiOvmfPkgTokenSpaceGuid.PcdOvmfDxeMemFvBase|gUefiOvmfPkgTokenSpaceGuid.PcdOvmfDxeMemFvSize
|
||||
FV = DXEFV
|
||||
|
||||
|
@ -6,7 +6,7 @@
|
||||
;*
|
||||
;------------------------------------------------------------------------------
|
||||
|
||||
SECTION .rodata
|
||||
SECTION RODATA_SECTION_NAME
|
||||
|
||||
;
|
||||
; Float control word initial value:
|
||||
@ -65,4 +65,3 @@ Done:
|
||||
pop ebx
|
||||
|
||||
ret
|
||||
|
||||
|
@ -6,7 +6,7 @@
|
||||
;*
|
||||
;------------------------------------------------------------------------------
|
||||
|
||||
SECTION .rodata
|
||||
SECTION RODATA_SECTION_NAME
|
||||
;
|
||||
; Float control word initial value:
|
||||
; all exceptions masked, double-extended-precision, round-to-nearest
|
||||
@ -48,4 +48,3 @@ ASM_PFX(InitializeFloatingPointUnits):
|
||||
ldmxcsr [mMmxControlWord]
|
||||
|
||||
ret
|
||||
|
||||
|
@ -46,8 +46,8 @@
|
||||
DebugAgentLib
|
||||
CpuLib
|
||||
UefiCpuLib
|
||||
PeCoffGetEntryPointLib
|
||||
PeCoffExtraActionLib
|
||||
UefiImageLib
|
||||
UefiImageExtraActionLib
|
||||
CpuExceptionHandlerLib
|
||||
ReportStatusCodeLib
|
||||
PeiServicesLib
|
||||
|
@ -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."
|
||||
|
@ -539,7 +539,8 @@ typedef struct {
|
||||
#define R_386_TLS_TPOFF32 37 /* GOT entry of -ve static TLS offset */
|
||||
|
||||
/* Null relocation */
|
||||
#define R_AARCH64_NONE 256 /* No relocation */
|
||||
#define R_AARCH64_NONE0 0
|
||||
#define R_AARCH64_NONE 256 /* No relocation */
|
||||
/* Static AArch64 relocations */
|
||||
/* Static data relocations */
|
||||
#define R_AARCH64_ABS64 257 /* S + A */
|
||||
@ -735,6 +736,7 @@ typedef struct {
|
||||
#define R_ARM_THM_MOVW_PREL_NC 49
|
||||
#define R_ARM_THM_MOVT_PREL 50
|
||||
#define R_ARM_THM_JMP6 52
|
||||
#define R_ARM_THM_JUMP19 51
|
||||
#define R_ARM_THM_ALU_PREL_11_0 53
|
||||
#define R_ARM_THM_PC12 54
|
||||
#define R_ARM_REL32_NOI 56
|
||||
@ -752,21 +754,14 @@ typedef struct {
|
||||
#define R_ARM_LDC_PC_G1 68
|
||||
#define R_ARM_LDC_PC_G2 69
|
||||
#define R_ARM_GOT_PREL 96
|
||||
#define R_ARM_GNU_VTENTRY 100
|
||||
#define R_ARM_GNU_VTINHERIT 101
|
||||
#define R_ARM_THM_JUMP11 102
|
||||
#define R_ARM_THM_JUMP8 103
|
||||
#define R_ARM_TLS_GD32 104
|
||||
#define R_ARM_TLS_LDM32 105
|
||||
#define R_ARM_TLS_IE32 107
|
||||
|
||||
#define R_ARM_THM_JUMP19 51
|
||||
#define R_ARM_GNU_VTENTRY 100
|
||||
#define R_ARM_GNU_VTINHERIT 101
|
||||
#define R_ARM_RSBREL32 250
|
||||
#define R_ARM_THM_RPC22 251
|
||||
#define R_ARM_RREL32 252
|
||||
#define R_ARM_RABS32 253
|
||||
#define R_ARM_RPC24 254
|
||||
#define R_ARM_RBASE 255
|
||||
|
||||
#define R_PPC_NONE 0/* No relocation. */
|
||||
#define R_PPC_ADDR32 1
|
||||
|
@ -23,7 +23,6 @@
|
||||
[Sources]
|
||||
UniversalPayloadEntry.c
|
||||
LoadDxeCore.c
|
||||
MemoryAllocation.c
|
||||
PrintHob.c
|
||||
AcpiTable.c
|
||||
|
||||
@ -54,6 +53,7 @@
|
||||
CpuLib
|
||||
UefiImageLib
|
||||
UefiCpuLib
|
||||
MemoryAllocationLib
|
||||
|
||||
[Guids]
|
||||
gEfiMemoryTypeInformationGuid
|
||||
|
@ -142,13 +142,6 @@
|
||||
MSFT:RELEASE_*_*_CC_FLAGS = /D MDEPKG_NDEBUG
|
||||
!endif
|
||||
|
||||
[BuildOptions.common.EDKII.DXE_RUNTIME_DRIVER]
|
||||
GCC:*_*_*_DLINK_FLAGS = -z common-page-size=0x1000
|
||||
XCODE:*_*_*_DLINK_FLAGS = -seg1addr 0x1000 -segalign 0x1000
|
||||
XCODE:*_*_*_MTOC_FLAGS = -align 0x1000
|
||||
CLANGPDB:*_*_*_DLINK_FLAGS = /ALIGN:4096
|
||||
MSFT:*_*_*_DLINK_FLAGS = /ALIGN:4096
|
||||
|
||||
################################################################################
|
||||
#
|
||||
# SKU Identification section - list of all SKU IDs supported by this Platform.
|
||||
@ -315,7 +308,7 @@
|
||||
PcdLib|MdePkg/Library/BasePcdLibNull/BasePcdLibNull.inf
|
||||
DxeHobListLib|UefiPayloadPkg/Library/DxeHobListLibNull/DxeHobListLibNull.inf
|
||||
DebugLib|MdePkg/Library/BaseDebugLibSerialPort/BaseDebugLibSerialPort.inf
|
||||
MemoryAllocationLib|UefiPayloadPkg/Library/UefiPayloadEntryMemoryAllocationLib/UefiPayloadEntryMemoryAllocationLib.inf
|
||||
MemoryAllocationLib|UefiPayloadPkg/Library/UefiPayloadMemoryAllocationLib/UefiPayloadMemoryAllocationLib.inf
|
||||
|
||||
[LibraryClasses.common.DXE_CORE]
|
||||
DxeHobListLib|UefiPayloadPkg/Library/DxeHobListLibNull/DxeHobListLibNull.inf
|
||||
|
@ -13,8 +13,8 @@ DEFINE FD_BASE = 0x00800000
|
||||
DEFINE FD_BLOCK_SIZE = 0x00001000
|
||||
|
||||
!if $(TARGET) == "NOOPT"
|
||||
DEFINE FD_SIZE = 0x00850000
|
||||
DEFINE NUM_BLOCKS = 0x850
|
||||
DEFINE FD_SIZE = 0x00A00000
|
||||
DEFINE NUM_BLOCKS = 0xA00
|
||||
!else
|
||||
|
||||
DEFINE FD_SIZE = 0x00590000
|
||||
|
Loading…
x
Reference in New Issue
Block a user